@oar-sh/oar 0.9.1 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/.github/extensions/web-relay/extension.mjs +0 -3
  2. package/.github/extensions/web-relay/polling/heartbeat.mjs +2 -55
  3. package/.github/extensions/web-relay/polling/polling-loop.mjs +0 -1
  4. package/.github/extensions/web-relay/runtime/api-client.mjs +2 -34
  5. package/.github/extensions/web-relay/runtime/config-loader.mjs +2 -104
  6. package/.github/extensions/web-relay/runtime/send-and-wait-errors.mjs +2 -170
  7. package/.github/extensions/web-relay/runtime/session-io.mjs +1 -71
  8. package/.github/extensions/web-relay/runtime/worker-websocket-link.mjs +2 -325
  9. package/.github/extensions/web-relay/skills/prompt-context.mjs +2 -160
  10. package/CHANGELOG.md +269 -0
  11. package/README.md +407 -424
  12. package/bin/oar.js +142 -11
  13. package/package.json +8 -4
  14. package/server/README.md +59 -22
  15. package/server/claude-worker/claude-sdk-adapter.mjs +7 -2
  16. package/server/claude-worker/claude-session-process.mjs +1013 -45
  17. package/server/claude-worker/claude-session-worker.mjs +54 -9
  18. package/server/claude-worker/claude-turn-publisher.mjs +110 -19
  19. package/server/claude-worker/claude-worker-link-wiring.mjs +9 -0
  20. package/server/copilot-sdk-runtime.mjs +12 -3
  21. package/server/copilot-worker/copilot-ask-user-tool.mjs +89 -0
  22. package/server/copilot-worker/copilot-attachments.mjs +35 -2
  23. package/server/copilot-worker/copilot-continuation-signals.mjs +55 -0
  24. package/server/copilot-worker/copilot-model-switch.mjs +425 -0
  25. package/server/copilot-worker/copilot-prompt-context.mjs +20 -8
  26. package/server/copilot-worker/copilot-question-bridge.mjs +129 -16
  27. package/server/copilot-worker/copilot-sdk-adapter.mjs +59 -11
  28. package/server/copilot-worker/copilot-sdk-event-normalizer.mjs +136 -12
  29. package/server/copilot-worker/copilot-sdk-session-process.mjs +2753 -527
  30. package/server/copilot-worker/copilot-sdk-session-worker.mjs +94 -25
  31. package/server/cursor-worker/cursor-session-worker.mjs +5 -5
  32. package/server/cursor-worker/cursor-turn-runner.mjs +50 -4
  33. package/server/db-schema.mjs +61 -1
  34. package/server/features.mjs +155 -41
  35. package/server/grok-worker/grok-session-worker.mjs +5 -5
  36. package/server/grok-worker/grok-turn-runner.mjs +45 -4
  37. package/server/migrations/0004-steer-settle-markers.mjs +119 -0
  38. package/server/public/app/annotate-core.mjs +181 -0
  39. package/server/public/app/annotate-editor.js +617 -0
  40. package/server/public/app/api-client.js +86 -5
  41. package/server/public/app/ask-user-view.js +102 -13
  42. package/server/public/app/attachments-view.js +172 -3
  43. package/server/public/app/background-task-timeout-options.mjs +9 -0
  44. package/server/public/app/background-tasks-view.mjs +34 -19
  45. package/server/public/app/bootstrap.js +153 -69
  46. package/server/public/app/composer-control-state.mjs +52 -34
  47. package/server/public/app/context-tier-options.mjs +24 -4
  48. package/server/public/app/conversation-draft-sync.mjs +187 -0
  49. package/server/public/app/conversation-list-filter.mjs +86 -0
  50. package/server/public/app/conversation-preferences.mjs +47 -10
  51. package/server/public/app/conversation-provider-indicator.mjs +8 -0
  52. package/server/public/app/conversation-view.js +1032 -218
  53. package/server/public/app/emoji-view.js +2 -0
  54. package/server/public/app/font-scaling.js +4 -37
  55. package/server/public/app/journal-view.js +190 -24
  56. package/server/public/app/model-selector-options.mjs +185 -1
  57. package/server/public/app/new-conversation-model-choice.mjs +29 -9
  58. package/server/public/app/pwa-install.js +64 -136
  59. package/server/public/app/question-multi-select.mjs +52 -0
  60. package/server/public/app/reasoning-effort-labels.mjs +13 -3
  61. package/server/public/app/relay-prompt-sanitizer.mjs +26 -3
  62. package/server/public/app/router.js +120 -11
  63. package/server/public/app/settings-modal.js +225 -20
  64. package/server/public/app/settings-tabs.js +1 -1
  65. package/server/public/app/socket-handlers.js +47 -4
  66. package/server/public/app/steered-turn-merge.mjs +100 -0
  67. package/server/public/app/store.js +159 -16
  68. package/server/public/app/sync-outbox.mjs +16 -8
  69. package/server/public/app/tool-activity-emoji.mjs +36 -0
  70. package/server/public/app/transcript-viewport-anchor.mjs +210 -0
  71. package/server/public/app/update-ui.js +194 -0
  72. package/server/public/index.html +483 -24
  73. package/server/public/sw.js +7 -0
  74. package/server/relay-tools.md +2 -0
  75. package/server/relay.mjs +23 -21
  76. package/server/repositories/message-repository.mjs +78 -21
  77. package/server/repositories/question-repository.mjs +19 -1
  78. package/server/repositories/session-repository.mjs +7 -31
  79. package/server/routes/ask-user-routes.mjs +10 -0
  80. package/server/routes/messages-routes.mjs +689 -159
  81. package/server/routes/sessions-routes.mjs +574 -80
  82. package/server/server-runtime.mjs +393 -925
  83. package/server/services/claude-auth-service.mjs +7 -1
  84. package/server/services/cli-install-service.mjs +8 -27
  85. package/server/services/cli-process-runner.mjs +30 -0
  86. package/server/services/copilot-model-discovery-service.mjs +202 -0
  87. package/server/services/data-dir-resolution.mjs +47 -0
  88. package/server/services/grok-auth-service.mjs +9 -1
  89. package/server/services/live-turn-picker.mjs +47 -0
  90. package/server/services/model-variant-catalog-service.mjs +1183 -0
  91. package/server/services/oar-cli-helpers.mjs +6 -2
  92. package/server/services/relay-prompt-sanitizer.mjs +30 -3
  93. package/server/services/relay-question-context.mjs +46 -0
  94. package/server/services/sdk-session-import-service.mjs +144 -16
  95. package/server/services/sdk-session-sync-service.mjs +84 -27
  96. package/server/services/session-worker-registry-service.mjs +116 -3
  97. package/server/services/session-worker-supervisor-service.mjs +7 -1
  98. package/server/services/session-worker-websocket-service.mjs +119 -24
  99. package/server/services/status-event-service.mjs +8 -2
  100. package/server/services/steer-resend.mjs +45 -0
  101. package/server/services/update-check-service.mjs +220 -0
  102. package/server/services/update-install-service.mjs +279 -0
  103. package/server/services/windows-autostart-service.mjs +42 -6
  104. package/server/services/windows-boot-autostart-service.mjs +487 -0
  105. package/shared/ask-user-bridge.mjs +37 -5
  106. package/shared/background-task-timeout.mjs +12 -4
  107. package/shared/claude-model-catalog.mjs +49 -0
  108. package/shared/context-window-fallbacks.mjs +1 -0
  109. package/shared/control-poller.mjs +4 -1
  110. package/shared/copilot-model-order.mjs +182 -0
  111. package/shared/media-embed-instructions.mjs +35 -0
  112. package/shared/model-descriptors.mjs +181 -30
  113. package/shared/model-id.mjs +6 -0
  114. package/shared/pwa-app-name.mjs +44 -0
  115. package/shared/question-multi-select.mjs +16 -0
  116. package/shared/relay-stop-failure.mjs +15 -0
  117. package/shared/slash-command-guard.mjs +76 -0
  118. package/shared/steer-note.mjs +66 -0
  119. package/shared/steer-settle-failure.mjs +89 -0
  120. package/shared/steer-settle-markers.mjs +18 -0
  121. package/shared/update-semver.mjs +50 -0
  122. package/shared/worker-crash-guard.mjs +40 -14
  123. package/shared/worker-runtime/api-client.mjs +34 -0
  124. package/shared/worker-runtime/config-loader.mjs +104 -0
  125. package/shared/worker-runtime/heartbeat.mjs +109 -0
  126. package/shared/worker-runtime/prompt-context.mjs +160 -0
  127. package/shared/worker-runtime/runner-link-wiring.mjs +44 -0
  128. package/shared/worker-runtime/send-and-wait-errors.mjs +170 -0
  129. package/shared/worker-runtime/worker-websocket-link.mjs +436 -0
  130. package/server/claude-worker/claude-session-test-harness.mjs +0 -236
  131. package/server/claude-worker/fixtures/workflow-run-record.json +0 -1
  132. package/server/copilot-worker/copilot-sdk-test-harness.mjs +0 -329
  133. package/server/copilot-worker/fixtures/abort-turn.json +0 -588
  134. package/server/copilot-worker/fixtures/ask-user-turn.json +0 -1154
  135. package/server/copilot-worker/fixtures/background-timer-continuation.json +0 -445
  136. package/server/copilot-worker/fixtures/background-timer-turn.json +0 -497
  137. package/server/copilot-worker/fixtures/happy-turn.json +0 -566
  138. package/server/copilot-worker/fixtures/quota-turn.json +0 -647
  139. package/server/copilot-worker/fixtures/reasoning-turn.json +0 -625
  140. package/server/copilot-worker/fixtures/resume-turn.json +0 -700
  141. package/server/copilot-worker/fixtures/subagent-turn.json +0 -1378
  142. package/server/copilot-worker/fixtures/tool-permission-turn.json +0 -1293
  143. package/server/routes/messages-routes-test-harness.mjs +0 -111
  144. package/server/services/fixtures/claude-auth-stub.sh +0 -62
  145. package/server/services/fixtures/cli-install-stub.sh +0 -75
  146. package/server/services/fixtures/grok-stub.sh +0 -86
package/CHANGELOG.md CHANGED
@@ -3,6 +3,275 @@
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
+ ## [Unreleased]
7
+
8
+ ## [0.9.3] — 2026-09-27
9
+
10
+ Highlights: mid-turn steering on Claude and Copilot, Copilot background tasks on
11
+ par with Claude's, multi-select question cards, drafts that stay safe across
12
+ devices, and a sidebar title filter.
13
+
14
+ ### Added
15
+
16
+ - **Mid-turn steering** for Claude conversations: messages sent while a turn is
17
+ running are pushed into the live turn (any number of them — Claude Code
18
+ parity) instead of queueing behind it. Folded messages settle with a compact
19
+ *merged* marker; a message the CLI answers on its own turn gets its real
20
+ reply as before.
21
+ - A **conversation title filter** above the sidebar list. Case-insensitive,
22
+ clears with × or Escape, and automatically loads older pages while active so
23
+ it searches every conversation, not just the loaded ones.
24
+ - **Resend** on a steered message that was cut off by **Stop**: the marker
25
+ reads *Stopped with the turn — not answered* and one tap sends the original
26
+ text and attachments again. Each original can be resent once (again only if
27
+ that Resend was cancelled or failed), and the button reads **Resent** on
28
+ every device and after reloads.
29
+ - The running reply's **Stop** header stays pinned at the top of the chat
30
+ while a long reply scrolls, so it is always in reach on a phone.
31
+ - Background subagents in the task panel show the **model they actually run
32
+ on** (e.g. *Opus 5.5*) beside their kind pill, and the **command they are
33
+ running right now** with its tool emoji (e.g. *🔧 Tool (Bash): npm test*),
34
+ cropped to the row — instead of *using Bash · opus*.
35
+ - **Mid-turn steering for Copilot conversations** (SDK engine, hosted and
36
+ BYOK alike, every Copilot model): a message sent while a turn runs is
37
+ pushed into the live turn. The runtime folds it in at the next tool boundary
38
+ (the message settles with the same *merged* marker as on Claude, and the
39
+ reply continues in the running bubble) or, when the model is mid-sentence,
40
+ answers it right after on its own bubble. The composer reads **Steer** for
41
+ these conversations; while a question card, approval, elicitation or a
42
+ compaction is open it reads **Queue** and the message waits in the queue,
43
+ cancellable, then steers in one round-trip after the answer. **Stop** now
44
+ ends only the reply — background agents the turn started keep running under
45
+ their own Stop — and messages pushed just before the Stop settle as *Stopped
46
+ with the turn — not answered* with **Resend**, exactly as on Claude.
47
+ - Messages steered into a running turn (Claude and Copilot) carry a short
48
+ hidden note telling the model to handle them in addition to the request it
49
+ is working on. In testing, a model that received a steer before its first
50
+ output answered only the new message and dropped the original request.
51
+ - The newest message you steered into a running Copilot turn keeps its
52
+ **Cancel** until the runtime picks it up: cancelling pulls it back out of the
53
+ runtime, so it is never answered. (Copilot's queue can only give back its
54
+ newest waiting message, so older ones lose Cancel once pushed, as on Claude.)
55
+ - **Background tasks for Copilot conversations** now match Claude's: background
56
+ agents the model spawns and detached shells appear in the task panel as they
57
+ run, with the agent's kind, the model it runs on, the command it is running
58
+ right now, its token count and a **Stop** that works (the runtime's task
59
+ registry). A reply no longer waits for a background agent to finish; the
60
+ agent's result arrives afterwards as its own *continuation* reply, and the
61
+ relay's *Background task timeout* slider now governs Copilot tasks too
62
+ (expiry stops them instead of silently forgetting them).
63
+ - **Multi-select question cards.** A question that allows several answers
64
+ renders checkmarks instead of one-shot buttons, plus one **Reply with
65
+ selection** button; the reply lists every ticked choice and whatever you
66
+ typed in addition. Previously the first click answered the whole card.
67
+ Claude cards follow Claude's own `multiSelect` flag. Copilot models get the
68
+ relay's own `ask_user` tool, which adds a `multi_select` field to the
69
+ runtime's (the built-in has no way to say "pick several"); a question worded
70
+ "select all that apply" counts too, and every Copilot choice card has a
71
+ **Select several** switch for the cases a model forgets to flag.
72
+
73
+ ### Changed
74
+
75
+ - Copilot replies settle when the main agent goes idle rather than when the
76
+ whole session does, so a background agent the turn spawned no longer keeps
77
+ the reply's bubble spinning for as long as it runs; the agent's own
78
+ follow-up arrives as a *continuation* reply, as on Claude. A background agent
79
+ that asks a question, or in ask mode asks to run something, after the reply
80
+ settled gets its card on a row of its own; approvals follow the
81
+ conversation's current mode, not the one the session started in. A
82
+ follow-up turn that ends with nothing to show (no text, and no activity
83
+ beyond the background agent's own bookkeeping, such as its granted
84
+ permissions) no longer leaves an empty "completed without a text reply"
85
+ row. Messages
86
+ are sent to the Copilot runtime as `immediate` throughout — the only mode
87
+ that never strands a message behind background work.
88
+
89
+ - The background task panel scrolls when it holds more tasks than fit,
90
+ instead of growing past the window — in phone landscape too, where the
91
+ composer now always stays on screen.
92
+ - The **Background task timeout** setting defaults to **4 hours** instead of
93
+ no limit, for Claude and Copilot alike: long-running work still finishes,
94
+ but a forgotten shell or agent no longer keeps its session alive forever.
95
+ A value you already chose (including *No limit*) is kept.
96
+ - Rotating a phone to landscape keeps the portrait text size instead of
97
+ jumping to the larger desktop size, and opening the on-screen keyboard
98
+ no longer shrinks it.
99
+ - Rotating a phone (or resizing the window, or opening the keyboard) keeps
100
+ your place in the transcript: a reader at the end stays at the end, and
101
+ mid-history the same message stays at the top of the screen. Previously
102
+ the reflow left you screens above where you were, usually further back.
103
+ A question card's reply box you are typing in stays in view when the
104
+ keyboard opens.
105
+
106
+ - The composer's send button no longer turns into **Stop** while a turn runs.
107
+ It reads **Steer** when a Claude turn is live and text is drafted, and stays
108
+ disabled on an empty composer. While steering is held (open question card or
109
+ plan approval, compaction) it stays enabled and reads **Queue**, with the
110
+ reason in its tooltip: the message waits as an ordinary pending bubble (with
111
+ **Cancel**) and steers into the turn once the card is answered or the
112
+ compaction ends. Stopping lives where the work is: the running reply's bubble
113
+ carries **Stop**, and queued messages carry **Cancel** until they are picked
114
+ up. The label follows the worker within about a second, including right
115
+ after a worker starts or the relay restarts.
116
+ - Queued messages are claimed strictly in send order, including messages that
117
+ went through a delivery retry. Previously a retried message could starve
118
+ behind newer ones for minutes in an active conversation, or run after them
119
+ so replies arrived out of order.
120
+ - `@anthropic-ai/claude-agent-sdk` 0.3.283 (bundled Claude Code 2.1.283),
121
+ which makes **Claude Opus 5.5** (`claude-opus-5-5`, plus its 1M-context
122
+ variant) discoverable. Model discovery runs the SDK's bundled CLI, so
123
+ `claude update` alone never surfaces a new Claude model.
124
+ - `@github/copilot-sdk` 1.0.14: typed message provenance (human vs. system vs.
125
+ agent senders), a `fast` auto-routing tier, a `managedSettings.clearCache`
126
+ RPC, and streaming-throughput fixes.
127
+ - `@cursor/sdk` 1.0.32 (additive API changes only).
128
+ - The npm package no longer ships test fixtures and test harnesses.
129
+ - The README is reorganized around installing and using OAR; relay internals
130
+ and development notes moved to DEVELOPING.md.
131
+
132
+ ### Fixed
133
+
134
+ - **Deleting a conversation no longer leaves its session running.** Its
135
+ worker used to keep running (about 40 MB each, holding its workspace
136
+ folder) until the relay restarted, and Claude and Copilot SDK
137
+ conversations never had their CLI session removed. Delete now stops the
138
+ worker first, removes the CLI session (Copilot through the SDK, Claude by
139
+ deleting that session's transcript) and the conversation at once. A
140
+ Copilot session the relay only imported from the host, and never ran, is
141
+ hidden instead: its CLI session stays, and no process is stopped for it. A
142
+ conversation that is still working, with a running turn or live background
143
+ tasks, is not deleted: the sidebar says why, so you can stop it first (a task
144
+ without a Stop button: use **Kill session**). A worker that a failed turn
145
+ marked as errored counts as working for as long as its process runs.
146
+ - A message starting with "/" (other than the relay's own `/compact` and
147
+ `/preview`) that reached a Claude conversation between turns ran as a Claude
148
+ CLI command instead: Claude never saw the text, and the next reply was
149
+ pinned to that message. It now reaches Claude as the text you typed, as the
150
+ composer's "send again to send as text" promises.
151
+ - A Copilot turn that ended in `task_complete` after streaming a fragment
152
+ published the fragment as its final reply; the completion summary now takes
153
+ precedence in the saved reply too, not only in the live stream.
154
+ - A background subagent's own events could open a spurious *continuation*
155
+ reply after the Copilot turn that spawned it had settled, and its
156
+ session-level model notice could confuse a pending model switch.
157
+ - Switching the model, mode or effort between turns no longer strands the
158
+ next message: the Claude CLI re-initialises after such a change, and the
159
+ worker took that for a turn it opened on its own, so the reply landed on
160
+ a *continuation* row while the message itself stayed processing with an
161
+ empty Stop bubble (until the session was killed). A background task's reply
162
+ that arrives during such a switch still gets its own row instead of
163
+ trading places with the message's reply.
164
+ - A steered message could wedge its conversation indefinitely when a
165
+ long-running (or hung) background task was alive: the merge settle waited for
166
+ a full idle that never came, keeping every later message stuck behind it.
167
+ Background tasks no longer block the settle; delivery watchdogs share the
168
+ same rule.
169
+ - **Drafts no longer get overwritten across devices.** The draft version check
170
+ never actually ran, so an idle device re-saved its stale (usually empty)
171
+ composer over another device's draft every few seconds. Saves are now
172
+ version-checked and happen only on real edits; a device you are not typing
173
+ on picks up the other's draft, and when two devices edit at once the newest
174
+ keystroke wins and the other text is offered back with **Restore** (and
175
+ **Undo**).
176
+ - Other ways to lose a draft are fixed too: text typed or attachments added
177
+ while a send was in flight, switching conversations mid-send or before the
178
+ next draft loaded, reopening the open conversation (which dropped its draft
179
+ attachments), a failed send overwriting what was typed meanwhile, and drafts
180
+ over 20,000 characters re-saving in a loop (the saved part is now cut
181
+ cleanly, and the composer says the rest is not saved).
182
+ - A steered message could run twice: Claude had already answered it, but the
183
+ relay's recovery (or a worker crash or restart) delivered it again. Steered
184
+ messages are now handled at most once: if the outcome cannot be recorded, the
185
+ message ends with an error telling you to check the reply above rather than
186
+ being run again.
187
+ - A message sent while a question card was open or the conversation was
188
+ compacting could stall for many seconds, or be pushed past the open card.
189
+ Question cards are never bypassed or dropped by steering: such messages wait
190
+ and steer in once the card is answered.
191
+ - **Stop now really stops** when steered messages were already pushed into the
192
+ turn. The Claude CLI otherwise opened a follow-up turn for them that re-ran
193
+ the stopped tool call; those messages now show *Stopped with the turn — not
194
+ answered* with **Resend** instead of claiming they were handled. A stopped
195
+ message is also no longer re-run if its worker dies right after the Stop.
196
+ - After a reload, a message sent after a folded steer is no longer styled as
197
+ steered with its reply merged into the previous turn, and older replies stay
198
+ anchored under their own messages.
199
+ - The live reply bubble no longer carries over into another conversation or
200
+ drops below later steered messages, and the live bubble and **Stop** follow
201
+ the turn that is actually producing output. A finished background task's
202
+ answer is no longer lost when a queued message takes over the turn.
203
+ - A screenshot-only send no longer vanishes from the transcript before its
204
+ message lands.
205
+ - Sidebar filter: keeps searching older pages while the list is busy loading,
206
+ matches accented titles regardless of how they were typed, no longer zooms
207
+ the page on iOS, and announces the match count once to screen readers
208
+ (saying when only loaded conversations were searched).
209
+ - A background agent's failure no longer vanishes: a Copilot follow-up turn
210
+ that carries the failure line, but has nothing else to show, keeps its row.
211
+ - The **Background task timeout** slider no longer reads *No limit* while the
212
+ settings load; it starts at the 4-hour default.
213
+ - Settings calls the SDK engine the Copilot default (it still read
214
+ *experimental*, with Extension as *current*), and the background task
215
+ timeout help names Copilot's background agents and shells.
216
+ - `oar` probed a different port than the one it started the relay on when the
217
+ config's `port` was not 3333 or differed from `--port`, then killed the relay
218
+ it had just started after 20 seconds. It now uses one port: `--port` for that
219
+ run, else the config's. `--help` no longer lists `--token`, which the
220
+ launcher never read.
221
+ - Concurrent conversation deletes could start extra Copilot runtimes that were
222
+ never shut down.
223
+ - Question cards said *Copilot question* in every conversation; they now name
224
+ the runtime that asks (Claude, Copilot, Cursor, OpenAI).
225
+
226
+ ## [0.9.2] — 2026-09-13
227
+
228
+ ### Added
229
+
230
+ - **Opt-in self-update**: a settings toggle for automatic update checks (off by
231
+ default; the relay never contacts oar.sh unless you opt in), plus a manual
232
+ check button. `OAR_NO_UPDATE_CHECK=1` disables even manual checks.
233
+ - Agents can embed **images, video and audio inline** in replies by bare
234
+ absolute path, on every provider. Clicking an embedded image opens the file
235
+ viewer with zoom, download and copy.
236
+ - **Screenshot annotations**: mark up uploaded screenshots with highlighter
237
+ strokes before (or after) sending; the original upload is never modified.
238
+ - A **Features** settings tab; feature flags now live in the database (the
239
+ `config.json` `features` key is migrated once and removed; env vars still win).
240
+ - Windows **system-startup autostart** mode (a boot-triggered scheduled task,
241
+ one UAC confirmation) alongside the existing at-sign-in mode.
242
+ - `config.json` can carry the data directory.
243
+
244
+ ### Changed
245
+
246
+ - New Copilot conversations default to the **SDK engine** when the relay can
247
+ run it, falling back to the CLI extension otherwise; an explicitly stored
248
+ setting always wins.
249
+ - The Copilot model catalog shows each model's real reasoning efforts and
250
+ context window, in a canonical order.
251
+ - Model labels are compact enough for phone composers (`Fable 5.1`,
252
+ `Haiku 4.5`), and the composer placeholder names the selected model's family.
253
+ - Claude models stay in the picker when Anthropic rotates the advertised
254
+ lineup; `@anthropic-ai/claude-agent-sdk` 0.3.261 (Fable 5.1 model floor).
255
+ - Global installs run from the OAR state root, so self-update can replace the
256
+ package directory on Windows.
257
+ - Transient relay notices render as an opaque toast instead of bleeding
258
+ through modals.
259
+
260
+ ### Fixed
261
+
262
+ - A custom PWA app name no longer reverts on Android: the relay serves it in
263
+ the manifest instead of a browser-local override.
264
+ - Queue writes are fenced to one processing attempt, so a superseded delivery
265
+ can no longer overwrite a settled message.
266
+ - Live-bubble rendering: cross-conversation teardown, muted streams after
267
+ enqueue, a live-poll deadlock and anchor theft.
268
+ - A queued send's own text no longer reappears in the composer.
269
+ - Copilot turns ending in a bare `task_complete` tool call show the real
270
+ summary instead of a cut-off fragment; detached Copilot shells appear as
271
+ background-task cards.
272
+ - Copilot worker and server-side session ownership hardening (continuations,
273
+ questions, shutdown, rekeying, worker kill verification).
274
+
6
275
  ## [0.9.1] — 2026-09-02
7
276
 
8
277
  ### Fixed