@omg-dev/app 0.6.14 → 0.6.16

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.
@@ -0,0 +1,319 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { z as n } from "./embedded-B6IaTsrk.js";
3
+ const t = `# Changelog
4
+
5
+ Recent product updates and deployment notes.
6
+
7
+ ## August 27, 2026 - The native iOS client, native push, and a matched dark theme (v0.6.16)
8
+
9
+ - **The native omg.dev client for iOS now lives in this repository.** The
10
+ \`mobile/\` directory held a todo prototype while the real client was developed
11
+ on a branch. The real client is now on \`main\`: sign-in, sessions, transcript
12
+ and composer, dictation, the Bots roster and bot chat, shared Computers, and
13
+ the plan screen. It ships through TestFlight and EAS Update, not through this
14
+ release bundle.
15
+ - **The dark theme is softer, and an installed app's status bar now matches
16
+ it.** The background moved from pure black to #141414, and body text moved
17
+ from pure white to a warm off-white. The chrome of an installed app kept its
18
+ own copies of the old colour, so an iPhone home-screen app painted a black
19
+ status bar above a lighter page. The theme colour, the splash, the safe-area
20
+ strips, the boot-failure page, and the web manifest now all use the same
21
+ value.
22
+ - **The server can send push notifications to the native app.** Delivery goes
23
+ through Expo and APNs, and it is fanned out from the same path as every other
24
+ notification, so existing callers inherit it with the same user scoping. The
25
+ payload is deliberately redacted: it carries a per-kind title and a project
26
+ name, and never the question text. Delivery needs a native build and an APNs
27
+ key.
28
+ - **The usage summary now arrives in one request.** \`/api/usage/summary\` groups
29
+ sources by kind, averages clamped windows by label, keeps the soonest reset,
30
+ and excludes accounts that did not report. A remote client no longer pays one
31
+ round trip per account. The per-account routes remain available.
32
+ - **Batch dictation now picks a provider that can perform it.** The fallback
33
+ matched any provider that defined a transcribe function, which included the
34
+ hosted relay. That relay is realtime-only and always answers 503, so a
35
+ workspace with a working ElevenLabs or OpenAI key still failed. Batch-capable
36
+ providers are now marked, and only they are selected.
37
+ - **A session row falls back to the local placeholder when an avatar cannot
38
+ load.** The fallback chain ended at Gravatar, which always returns a URL. On a
39
+ box that cannot reach gravatar.com, every row rendered a broken image. The
40
+ configured identity now stays visible without a network.
41
+
42
+ ## August 27, 2026 - Session sharing, pinned chats sync, and env-token Claude accounts (v0.6.15)
43
+
44
+ - **A Claude login held in \`CLAUDE_CODE_OAUTH_TOKEN\` now counts as a connected
45
+ account.** A box authenticated only through that variable showed the default
46
+ Claude account as disconnected, and the Coding Agents page asked for a login
47
+ that was not needed. Sessions launched from such a box worked the whole time,
48
+ so the page disagreed with the runtime. The account row now reads "From
49
+ CLAUDE_CODE_OAUTH_TOKEN", and the re-login button is hidden there, because the
50
+ variable outranks anything a browser sign-in stores. An isolated account no
51
+ longer inherits the variable, so accounts cannot all run on one login.
52
+ - **Hosted sessions show who they are shared with.** The session list carries an
53
+ assignee avatar, and a user filter menu narrows the list to one person.
54
+ - **Pinned chats now follow your account instead of one browser.** Pins are held
55
+ by the server, so a session pinned on one device appears pinned on the others.
56
+ - **The thread rail shows project favicons.** Each project in the rail carries
57
+ its own icon, and the activity marks beside it are simpler to read.
58
+ - **Voice failures now explain what to fix.** Batch dictation no longer goes
59
+ silent when a provider rejects a key, runs out of API credit, rate limits a
60
+ request, or cannot be reached. The server returns a stable safe error code,
61
+ and the composer shows an actionable message without exposing the provider's
62
+ response body. The mic also reports its starting and transcribing states to
63
+ assistive technology.
64
+ - **Long-press uses the native iPhone selection controls again.** A user can
65
+ select and adjust any part of a message, while the separate copy button
66
+ remains available for copying the whole message in one tap.
67
+ - **Swipe between chats is now optional per device.** The new switch under
68
+ Settings > More > This device disables only the horizontal chat-switching
69
+ gesture. Vertical scrolling, native text selection, and other gestures keep
70
+ working normally.
71
+ - **Opening the keyboard no longer scrolls the newest message away.** A
72
+ transcript pinned to the latest turn stays pinned when the soft keyboard
73
+ opens or closes.
74
+ - **Headings in an answer are no longer smaller than the text they introduce.**
75
+ A rule written for the user bubble was applying to every assistant reply, so
76
+ H1, H2 and H3 all rendered at 14px against 17px body text. The rule is now
77
+ scoped to the user bubble.
78
+ - **Computer Use refuses a debugging port that another process already holds.**
79
+ Before, a box that already had a browser on port 9222 reported a successful
80
+ start while Chrome had in fact exited. The desktop stayed empty and every
81
+ Computer Use call went to the other browser. The start now fails and says so.
82
+ - The onboarding survey is cut to two questions, and its analytics are posted to
83
+ the embedding host rather than sent from the sandboxed frame, where every
84
+ event was being dropped.
85
+ - **Deployment note:** pi resolves its proxy base from \`OMG_AI_URL\` when
86
+ \`ANTHROPIC_BASE_URL\` is unset. There is no behavior change while infra still
87
+ injects \`ANTHROPIC_BASE_URL\`, which keeps priority. This release must be
88
+ rebaked into the agent template before the infra side stops injecting the
89
+ vendor-named variable.
90
+
91
+ ## August 25, 2026 - OpenCode Go models appear without a Claude account (v0.6.14)
92
+
93
+ - **An OpenCode Go key alone now unlocks OpenCode's paid models.** If OpenCode
94
+ was the only agent signed in on a box, the picker showed the free Zen tier
95
+ and nothing else — even with a Go key connected and every \`opencode-go/*\`
96
+ model already discovered. The box was being treated as anonymous because the
97
+ "is someone signed in here" check counted only Claude and Codex. Anyone
98
+ paying for OpenCode Go and using nothing else was being billed for models the
99
+ picker hid from them.
100
+ - The check that stops a *Claude* account from unlocking OpenCode's paid
101
+ providers is unchanged. A box whose OpenCode was never signed into still gets
102
+ the free tier, because offering models that fail at launch is worse than
103
+ offering fewer.
104
+
105
+ ## August 25, 2026 - Pin a bot to a specific Claude account (v0.6.13)
106
+
107
+ - **The bot editor now lets you choose which Claude account a bot runs on.**
108
+ Open Edit bot, then Advanced. The agent row lists Claude - Auto and every
109
+ connected account, the same picker sessions and routines already had. Before,
110
+ a bot always fell back to the automatic account pick.
111
+ - Claude - Auto keeps the old behavior. It picks the connected account with the
112
+ most headroom at launch.
113
+ - Changing the account is a launch setting, so the bot reads "Update available"
114
+ after you save. The new account applies when you press Apply changes.
115
+ - A pinned account that is removed or signed out falls back to Claude - Auto.
116
+ The bot still starts.
117
+ - A bot created by another bot inherits that bot's account, the same way it
118
+ already inherits the repo and the owner.
119
+
120
+ ## August 25, 2026 - Tagging a bot with @ now reaches the bot (v0.6.12)
121
+
122
+ - **An \`@\` tag in a session chat delivers the message to that bot.** Before,
123
+ the tag was only text and routed nowhere. The tag carries the bot identity,
124
+ so renaming a bot or having two bots with the same name cannot send the
125
+ message to the wrong one.
126
+ - The tagged bot joins the conversation from the point it was tagged. It does
127
+ not read the earlier history of that session.
128
+ - A tag for a bot that is unknown, disabled, or restarting is reported instead
129
+ of being dropped without a word.
130
+ - **Note:** the tagged bot answers in its own chat. Its reply does not appear
131
+ in the session that tagged it.
132
+
133
+ ## August 25, 2026 - Tag a bot with @ in the composer (v0.6.11)
134
+
135
+ - **Typing \`@\` in the message box opens a bot picker.** Search your bots by
136
+ name, then press Enter or Tab to insert the tag. The picker is available in
137
+ every composer, including chat and the new-session box.
138
+ - The picker skips bots that are disabled, because a disabled bot cannot
139
+ accept a message. It does not open on an email address such as
140
+ \`name@example.com\`.
141
+ - The tag is text in the message. It does not notify or route to the bot yet.
142
+
143
+ ## August 25, 2026 - Mobile chat stays focused and Grok thoughts stay private (v0.6.10)
144
+
145
+ - **Grok reasoning no longer appears as an assistant answer while it streams.**
146
+ The live protocol now keeps thinking and answer text as separate typed data.
147
+ The fix does not inspect Grok text or depend on provider-specific markers.
148
+ - **Mobile chat keeps the hardware keyboard ready after send.** The composer
149
+ retains focus without reopening the software keyboard.
150
+ - **Live transcript motion is faster and the keyboard gap is gone.** New chat
151
+ activity reaches the bottom sooner, and the composer no longer leaves an
152
+ empty inset after the mobile keyboard closes.
153
+
154
+ ## August 25, 2026 - Switch bar says Schedules (v0.6.9)
155
+
156
+ - **The Chat / Bots / Schedules toggle now says Schedules.** The page heading
157
+ already used that word. The third segment was still labeled Scheduled.
158
+
159
+ ## August 25, 2026 - Chat streams more smoothly (v0.6.8)
160
+
161
+ - **Assistant markdown now uses Streamdown 2.6.** Word-by-word streaming
162
+ animation stays on one timeline, so sibling sections no longer fade in on
163
+ top of each other. The renderer also picks up the 2.6 accessibility and
164
+ download fixes. Long code and tables stay full height, so the transcript
165
+ layout model still matches what you see.
166
+ ## August 24, 2026 - Bot roster status is quieter (v0.6.7)
167
+
168
+ - **Unread is one small dot on its conversation row.** Unread rows no longer
169
+ use a blue outline or stronger text. Idle bots no longer show a status chip.
170
+ Working bots use one spinner and keep their latest message preview visible.
171
+
172
+ ## August 24, 2026 - Bot unread state stays quiet (v0.6.6)
173
+
174
+ - **Unread is now one clear dot.** The highlighted row and stronger text keep
175
+ unread conversations easy to scan without a label that crowds the bot name.
176
+ Working, Idle, and Disabled remain explicit and separate from unread state.
177
+
178
+ ## August 24, 2026 - Bot status and recent conversations stand out (v0.6.5)
179
+
180
+ - **Bot state is explicit.** Each roster row now labels the bot as Working,
181
+ Idle, or Disabled. Unread conversations have a larger badge, stronger text,
182
+ and a highlighted row. Activity and unread state stay separate, so a bot can
183
+ show both Working and Unread at the same time.
184
+ - **The newest bot conversation is first.** The desktop rail and mobile Bots
185
+ page now use the same recency order. Bots with no conversation stay at the
186
+ end.
187
+ - **Schedule names have more room on mobile.** The name now has its own line
188
+ instead of sharing a cramped row with the enable switch.
189
+
190
+ ## August 24, 2026 - Chat updates glide instead of jumping (v0.6.4)
191
+
192
+ - **New messages, tool calls, and the working indicator now move the chat
193
+ smoothly.** A time-based spring follows the live bottom of the transcript.
194
+ Streamed text and tool-status updates no longer cancel that motion and snap
195
+ the view. Changing sessions also no longer paints a provisional transcript
196
+ height that makes the layout flicker before it settles.
197
+ - **Computer control now follows the input device.** There is one Take control
198
+ toggle. A mouse points directly, while touch acts like a trackpad. A tap no
199
+ longer blocks the next drag, and agent browser input no longer shows a
200
+ desktop-wide lock that did not protect a shared resource.
201
+
202
+ ## August 24, 2026 - Hosted onboarding answers reach analytics (v0.6.3)
203
+
204
+ - **The hosted onboarding survey now sends answers through the host.** The
205
+ embedded package previously expected an analytics account at package-build
206
+ time. Release builds do not own one, so the survey event code compiled to a
207
+ no-op. The host now supplies the analytics handler that already identifies
208
+ the signed-in user. Role, friction, daily-tool, AI-tool, completion, and skip
209
+ results can reach the hosted product's existing analytics account.
210
+
211
+ ## August 24, 2026 - The Computer on a phone, and Schedules as a real list (v0.6.2)
212
+
213
+ - **The Computer survives a restart.** Its lifecycle used to live only in the
214
+ server's memory, so a deploy or a crash left the desktop running with nobody
215
+ holding it: the screen stayed up while the tab went dead, and the next start
216
+ failed because the ports were still taken. A restarted server now reattaches
217
+ to a healthy desktop instead of orphaning it, so a deploy is invisible to
218
+ whoever is watching and to an agent mid-task.
219
+ - **Touch works properly.** Dragging moves the pointer by offset, the way a
220
+ trackpad does, instead of teleporting it to wherever your finger landed --
221
+ which on a touchscreen put the target under your own hand. A tap clicks where
222
+ the cursor is. There is a keyboard button, because a canvas cannot take focus
223
+ on iOS and there was previously no way to raise the soft keyboard at all.
224
+ - **Opening the Computer starts it.** The Start button is gone: opening the
225
+ page was already the decision, and the progress indicator covers the wait.
226
+ - **Schedules is a list you can work.** The enable switch moves to the right
227
+ edge where a thumb already is, the agent icon becomes a quick switch, each
228
+ schedule fits on one line, and the findings banner is gone -- findings have
229
+ their own surface, and a banner about them was the loudest thing on a page
230
+ meant to be a list of schedules.
231
+ ## August 24, 2026 - Fix the release bundle (v0.6.1)
232
+
233
+ - **The v0.6.0 release bundle failed to build.** The Computer pulls in noVNC,
234
+ which ships top-level await, and the embedded-library build targeted a browser
235
+ set that predates it. The app build had already been raised; this config was
236
+ missed, so the app was fine and only the release bundle broke.
237
+
238
+ ## August 24, 2026 - The Computer: a desktop you and your agents share (v0.6.0)
239
+
240
+ - **This box now has a screen you can watch and take over.** The Computer is a
241
+ real desktop -- a window manager, a panel, a file manager, a terminal, and a
242
+ browser -- streamed into the app and controllable from it. Open it from the
243
+ Pages menu, press Take control, and you have the pointer and keyboard. On a
244
+ phone or tablet the usual gestures work: tap to click, two-finger tap for a
245
+ right click, drag to move, two-finger drag to scroll, pinch to zoom.
246
+ - **Agents drive the browser on that same screen.** A new Computer Use MCP gives
247
+ them navigate, click, type, press, read and screenshot. Because they work in a
248
+ visible window on the desktop you are watching, you see what they do as they
249
+ do it, rather than reading about it afterwards.
250
+ - **Chrome runs headful, not headless.** Headless Chrome announces itself in the
251
+ user agent and is trivially fingerprinted. This is an ordinary browser that
252
+ happens to have no monitor, with a persistent profile, so a site you sign into
253
+ stays signed in and an agent can pick up where you left off.
254
+ - **It costs nothing until you ask for it.** No part of the desktop is installed
255
+ by setup, and nothing starts until you press the button. The screen reaches
256
+ the browser over the existing websocket -- no extra proxy process and no new
257
+ runtime dependency.
258
+ - **The Computer Use MCP is off by default and separate from the omg MCP.** It
259
+ drives a screen that only exists where the desktop is installed, so it is its
260
+ own catalog with its own switch, next to the omg.dev MCP on the Coding agents
261
+ page rather than buried in Settings.
262
+
263
+ ## August 24, 2026 - Scrolling does what you tell it (v0.5.1)
264
+
265
+ - **The transcript no longer scrolls itself.** Following the newest message was
266
+ decided by measuring the distance to the bottom on every scroll event. That
267
+ works only while the total height is stable, and it stopped being stable when
268
+ the transcript started keeping only the visible rows in the page: a row that
269
+ comes into view replaces its estimated height with its real one, the total
270
+ moves, and the view could re-pin itself with no new message and no input from
271
+ you. Following is now a stored state that only a real gesture can change.
272
+ Scroll away and it stays away. Scroll back to the bottom, or press New
273
+ activity, and it follows again. A re-measure cannot change it. Nor can a
274
+ prepend, or the page correcting its own position. Keyboard scrolling counts
275
+ as a gesture now, which it did not before.
276
+ - **Tool calls send less over the wire.** The arguments of a tool call are no
277
+ longer streamed with the transcript. The name and the count are, which is all
278
+ a collapsed pill shows, and the arguments load when you open one. Measured on
279
+ real sessions this cuts a transcript load by 13 to 31 percent. The trade is
280
+ that opening a pill now waits for one small request.
281
+ - **Connection diagnostics are recorded again.** The browser posted five kinds
282
+ of websocket event to a route that had been deleted as unused, so every one
283
+ returned 404 and the client half of the connection record was lost. The route
284
+ is back. Only the browser knows the close code and the retry count, so the
285
+ server could not stand in for it.
286
+
287
+ ## August 24, 2026 - A transcript that stays fast, and can be searched (v0.5.0)
288
+
289
+ - **Tool-heavy sessions are readable again.** The transcript asked the server for
290
+ 80 raw messages, but the screen shows collapsed rows, and one run of tool calls
291
+ collapses into a single pill. A session that was mostly tool work therefore
292
+ arrived as three rows on an otherwise empty screen, and it could not page back,
293
+ because the page did not overflow and the backfill only ran when it did.
294
+ Paging is now measured in rows, so a page always carries enough to read. The
295
+ row rule has one definition that the server and the browser share.
296
+ - **A find bar for the transcript.** Virtualization keeps only the rows near the
297
+ viewport in the page, so the browser find command can only see those. Search
298
+ now runs on the server, over the whole session, and jumps to the row that
299
+ matched. It reports how many matches exist, walks forward and backward, and
300
+ keeps loading older pages while it hunts for a match that is not loaded yet.
301
+ It does not take over Control+F, because that would be a hostile default.
302
+ - **Sending a message during a reply no longer doubles the reply.** The chat
303
+ library appends a new copy of a message when the incoming update does not
304
+ match the end of the list. Sending mid-reply moved the reply away from the
305
+ end, so a second copy appeared, and the two drew on top of each other. The
306
+ live turn is now kept at the end, and an older copy of it is dropped.
307
+ - **Images no longer reload when you scroll back to them.** Off-screen rows are
308
+ removed from the page, so returning to an image used to download it again and
309
+ show the loading pulse again. Images and video now load in the element itself,
310
+ so the browser cache serves them. Video also seeks properly now, instead of
311
+ downloading the whole file first. The hosted surface keeps the previous path,
312
+ because it authenticates with a header.
313
+ `;
314
+ function s() {
315
+ return /* @__PURE__ */ e("div", { className: "mx-auto max-w-xl space-y-5 pb-10", children: /* @__PURE__ */ e("article", { className: "markdown rounded-2xl border border-border bg-card/40 px-4 py-4", children: /* @__PURE__ */ e(n, { children: t }) }) });
316
+ }
317
+ export {
318
+ s as default
319
+ };
@@ -2,7 +2,7 @@ import { jsx as e, jsxs as s, Fragment as te } from "react/jsx-runtime";
2
2
  import { memo as ne, useState as m, useRef as T, useCallback as v, useEffect as C, useMemo as q, Suspense as U } from "react";
3
3
  import { createPortal as re } from "react-dom";
4
4
  import { cn as y } from "cnfast";
5
- import { f as oe, a3 as W, a4 as se, X as I, a5 as ie, a6 as ae, L as H, a7 as le, y as de, C as ce, a8 as L } from "./embedded-oaPwSSek.js";
5
+ import { f as oe, a3 as W, a4 as se, X as I, a5 as ie, a6 as ae, L as H, a7 as le, y as de, C as ce, a8 as L } from "./embedded-B6IaTsrk.js";
6
6
  import { c as me } from "./create-CBk9uwJH.js";
7
7
  /**
8
8
  * @license lucide-react v0.577.0 - ISC
@@ -1,7 +1,7 @@
1
1
  import { jsxs as r, jsx as k, Fragment as vA } from "react/jsx-runtime";
2
2
  import { useState as L, useRef as R, useEffect as p, useCallback as q } from "react";
3
- import { f as UA, o as iQ, X as CA, a9 as wQ, y as sQ, aa as tQ, ab as eQ, a3 as aQ, ac as MQ, R as hQ, C as NQ } from "./embedded-oaPwSSek.js";
4
- import { K as ZA } from "./keyboard-M0kWYsLv.js";
3
+ import { f as UA, o as iQ, X as CA, a9 as wQ, y as sQ, aa as tQ, ab as eQ, a3 as aQ, ac as MQ, R as hQ, C as NQ } from "./embedded-B6IaTsrk.js";
4
+ import { K as ZA } from "./keyboard-DCTxfrP6.js";
5
5
  /**
6
6
  * @license lucide-react v0.577.0 - ISC
7
7
  *
@@ -1,7 +1,7 @@
1
1
  import { jsx as ao } from "react/jsx-runtime";
2
2
  import { useRef as Dt, useCallback as Lt, useSyncExternalStore as ut, useEffect as so } from "react";
3
3
  import { g as io } from "./_commonjsHelpers-C6fGbg64.js";
4
- import { ad as uo } from "./embedded-oaPwSSek.js";
4
+ import { ad as uo } from "./embedded-B6IaTsrk.js";
5
5
  var Ar = "vercel.ai.error", co = Symbol.for(Ar), Ut, Ft, se = class Nr extends (Ft = Error, Ut = co, Ft) {
6
6
  /**
7
7
  * Creates an AI SDK Error.
@@ -1,16 +1,16 @@
1
- import { jsxs as t, jsx as e, Fragment as B } from "react/jsx-runtime";
2
- import { R, B as d, L as $, n as A, o as S, M as H, p as j, q as I, s as h, T as E, u as D, v as W, w as P, x as X, y as J, X as Q, K as V } from "./embedded-oaPwSSek.js";
3
- import { cn as M } from "cnfast";
4
- import { useState as T } from "react";
5
- function O(s) {
1
+ import { jsxs as t, jsx as e, Fragment as O } from "react/jsx-runtime";
2
+ import { R, B as d, L as $, n as A, o as S, M as G, p as j, q as E, s as h, T as P, u as D, v as W, w as T, x as X, y as J, X as Q, K as V } from "./embedded-B6IaTsrk.js";
3
+ import { cn as U } from "cnfast";
4
+ import { useState as I } from "react";
5
+ function B(s) {
6
6
  return /CLI$|runtime$/i.test(s);
7
7
  }
8
8
  function Y(s) {
9
- return s.some((a) => O(a.label) && !a.ok);
9
+ return s.some((a) => B(a.label) && !a.ok);
10
10
  }
11
11
  function Z(s) {
12
12
  const a = s.filter((r) => !r.ok);
13
- return a.length ? a.some((r) => O(r.label)) ? "Install" : "Connect" : null;
13
+ return a.length ? a.some((r) => B(r.label)) ? "Install" : "Connect" : null;
14
14
  }
15
15
  function ee(s) {
16
16
  const a = s.filter((r) => !r.ok);
@@ -62,7 +62,7 @@ function L({
62
62
  /* @__PURE__ */ e(
63
63
  X,
64
64
  {
65
- className: M(
65
+ className: U(
66
66
  "size-4 shrink-0 text-muted-foreground/60 transition-transform duration-150",
67
67
  u && "rotate-180"
68
68
  )
@@ -86,7 +86,7 @@ function te({
86
86
  /* @__PURE__ */ e("span", { className: "block truncate text-xs font-medium", children: s.label }),
87
87
  s.needsReconnect ? /* @__PURE__ */ e("span", { className: "block truncate text-[11px] text-destructive", children: "Sign-in expired" }) : s.detail || s.fromEnv ? /* @__PURE__ */ e("span", { className: "block truncate text-[11px] text-muted-foreground", children: s.detail ?? "From the environment" }) : null
88
88
  ] }),
89
- s.connected ? /* @__PURE__ */ t(B, { children: [
89
+ s.connected ? /* @__PURE__ */ t(O, { children: [
90
90
  /* @__PURE__ */ e("span", { className: "text-[11px] text-success", children: "Connected" }),
91
91
  s.fromEnv ? null : /* @__PURE__ */ e(
92
92
  "button",
@@ -96,7 +96,7 @@ function te({
96
96
  title: `Disconnect ${s.label}`,
97
97
  "aria-label": `Disconnect ${s.label}`,
98
98
  className: "flex size-7 items-center justify-center rounded-full text-muted-foreground transition hover:bg-destructive/10 hover:text-destructive",
99
- children: /* @__PURE__ */ e(E, { className: "size-3.5" })
99
+ children: /* @__PURE__ */ e(P, { className: "size-3.5" })
100
100
  }
101
101
  )
102
102
  ] }) : /* @__PURE__ */ t(d, { size: "sm", variant: "outline", onClick: () => a(s), children: [
@@ -115,19 +115,19 @@ function re({
115
115
  onRemoveClaudeAccount: u,
116
116
  onConnectProvider: x,
117
117
  onDisconnectProvider: b,
118
- onSetupCheck: U,
118
+ onSetupCheck: _,
119
119
  onRefresh: K,
120
120
  computerMcpEnabled: g,
121
- onComputerMcpChange: q
121
+ onComputerMcpChange: M
122
122
  }) {
123
- const [p, y] = T(!1), [v, C] = T(null), z = (n) => C((l) => l === n ? null : n);
123
+ const [p, y] = I(!1), [v, C] = I(null), z = (n) => C((i) => i === n ? null : n);
124
124
  async function F() {
125
125
  if (!p) {
126
126
  y(!0);
127
127
  try {
128
- await K(), P.success("Coding agents refreshed");
128
+ await K(), T.success("Coding agents refreshed");
129
129
  } catch (n) {
130
- P.error(n instanceof Error ? n.message : "Could not refresh coding agents");
130
+ T.error(n instanceof Error ? n.message : "Could not refresh coding agents");
131
131
  } finally {
132
132
  y(!1);
133
133
  }
@@ -144,7 +144,7 @@ function re({
144
144
  disabled: p,
145
145
  className: "flex items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground disabled:opacity-50",
146
146
  children: [
147
- /* @__PURE__ */ e(R, { className: M("size-3.5", p && "animate-spin") }),
147
+ /* @__PURE__ */ e(R, { className: U("size-3.5", p && "animate-spin") }),
148
148
  "Refresh"
149
149
  ]
150
150
  }
@@ -162,14 +162,14 @@ function re({
162
162
  onToggle: () => z(`setup:${n.key}`),
163
163
  children: [
164
164
  /* @__PURE__ */ e(ne, { checks: n.checks }),
165
- n.instructions.map((l) => /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: l }, l)),
165
+ n.instructions.map((i) => /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: i }, i)),
166
166
  /* @__PURE__ */ t(
167
167
  d,
168
168
  {
169
169
  size: "sm",
170
170
  variant: "outline",
171
171
  disabled: !n.canAutoSetup || n.running,
172
- onClick: () => U(n.key),
172
+ onClick: () => _(n.key),
173
173
  title: n.canAutoSetup ? n.actionLabel : "Install a supported coding agent first",
174
174
  children: [
175
175
  n.running ? /* @__PURE__ */ e($, { className: "size-4 animate-spin" }) : /* @__PURE__ */ e(A, { className: "size-4" }),
@@ -183,7 +183,7 @@ function re({
183
183
  )),
184
184
  /* @__PURE__ */ t("div", { className: "flex items-center justify-between gap-4 px-4 py-3", children: [
185
185
  /* @__PURE__ */ t("div", { className: "flex min-w-0 items-center gap-3", children: [
186
- /* @__PURE__ */ e(H, { className: "size-4 shrink-0 text-muted-foreground" }),
186
+ /* @__PURE__ */ e(G, { className: "size-4 shrink-0 text-muted-foreground" }),
187
187
  /* @__PURE__ */ t("span", { className: "min-w-0", children: [
188
188
  /* @__PURE__ */ e("span", { className: "block truncate text-sm font-medium", children: "Computer Use MCP" }),
189
189
  /* @__PURE__ */ e("span", { className: "block text-xs text-muted-foreground", children: g ? "Agents can drive this box's desktop and browser." : "Off. Agents cannot see or drive the desktop." })
@@ -193,21 +193,21 @@ function re({
193
193
  j,
194
194
  {
195
195
  checked: g,
196
- onCheckedChange: q,
196
+ onCheckedChange: M,
197
197
  "aria-label": g ? "Disable the Computer Use MCP" : "Enable the Computer Use MCP"
198
198
  }
199
199
  )
200
200
  ] })
201
201
  ] }) : null,
202
202
  /* @__PURE__ */ e("div", { className: "overflow-hidden rounded-2xl border border-border bg-card/40 divide-y divide-border", children: a.map((n) => {
203
- const l = n.status, c = n.key === "aisdk" ? l.accounts ?? [] : [], k = l.providers ?? [], _ = c.some((i) => i.connected), G = c.length > 0 || k.length > 0, w = Y(l.checks);
203
+ const i = n.status, c = n.key === "aisdk" ? i.accounts ?? [] : [], k = i.providers ?? [], q = c.some((l) => l.connected), H = c.length > 0 || k.length > 0, w = Y(i.checks);
204
204
  return /* @__PURE__ */ t(
205
205
  L,
206
206
  {
207
- icon: /* @__PURE__ */ e("img", { src: I(n.key), alt: W(n.key), className: "size-5" }),
207
+ icon: /* @__PURE__ */ e("img", { src: E(n.key), alt: W(n.key), className: "size-5" }),
208
208
  title: n.label,
209
- note: Z(l.checks),
210
- ok: l.configured,
209
+ note: Z(i.checks),
210
+ ok: i.configured,
211
211
  showDot: !1,
212
212
  open: v === `agent:${n.key}`,
213
213
  onToggle: () => z(`agent:${n.key}`),
@@ -215,39 +215,40 @@ function re({
215
215
  j,
216
216
  {
217
217
  checked: n.visible,
218
- onCheckedChange: (i) => {
219
- if (i && !l.configured) {
218
+ onCheckedChange: (l) => {
219
+ if (l && !i.configured) {
220
220
  C(`agent:${n.key}`);
221
221
  return;
222
222
  }
223
- r(n.key, i);
223
+ r(n.key, l);
224
224
  },
225
225
  "aria-label": `${n.label} visible in composer`
226
226
  }
227
227
  ),
228
228
  children: [
229
- c.length ? /* @__PURE__ */ e("div", { className: "space-y-1.5", children: c.map((i) => /* @__PURE__ */ t(
229
+ c.length ? /* @__PURE__ */ e("div", { className: "space-y-1.5", children: c.map((l) => /* @__PURE__ */ t(
230
230
  "div",
231
231
  {
232
232
  className: "flex items-center gap-2 rounded-xl border border-border/70 bg-background/55 px-2.5 py-2",
233
233
  children: [
234
234
  /* @__PURE__ */ t("span", { className: "relative flex size-7 shrink-0 items-center justify-center rounded-full bg-muted", children: [
235
- /* @__PURE__ */ e("img", { src: I("aisdk"), alt: "", className: "size-4.5" }),
236
- /* @__PURE__ */ e("span", { className: "absolute -bottom-0.5 -right-0.5 flex size-3.5 items-center justify-center rounded-full bg-foreground text-[8px] font-bold text-background ring-1 ring-background", children: i.number })
235
+ /* @__PURE__ */ e("img", { src: E("aisdk"), alt: "", className: "size-4.5" }),
236
+ /* @__PURE__ */ e("span", { className: "absolute -bottom-0.5 -right-0.5 flex size-3.5 items-center justify-center rounded-full bg-foreground text-[8px] font-bold text-background ring-1 ring-background", children: l.number })
237
237
  ] }),
238
238
  /* @__PURE__ */ t("span", { className: "min-w-0 flex-1", children: [
239
- /* @__PURE__ */ e("span", { className: "block truncate text-xs font-medium", children: i.label }),
240
- i.needsReconnect ? /* @__PURE__ */ e("span", { className: "block truncate text-[11px] text-destructive", children: "Sign-in expired" }) : null
239
+ /* @__PURE__ */ e("span", { className: "block truncate text-xs font-medium", children: l.label }),
240
+ l.needsReconnect ? /* @__PURE__ */ e("span", { className: "block truncate text-[11px] text-destructive", children: "Sign-in expired" }) : null,
241
+ l.fromEnv ? /* @__PURE__ */ e("span", { className: "block truncate text-[11px] text-muted-foreground", children: "From CLAUDE_CODE_OAUTH_TOKEN" }) : null
241
242
  ] }),
242
- i.connected ? /* @__PURE__ */ t(B, { children: [
243
+ l.connected ? /* @__PURE__ */ t(O, { children: [
243
244
  /* @__PURE__ */ e("span", { className: "text-[11px] text-success", children: "Connected" }),
244
- /* @__PURE__ */ e(
245
+ l.fromEnv ? null : /* @__PURE__ */ e(
245
246
  "button",
246
247
  {
247
248
  type: "button",
248
- onClick: () => o(n.key, i.id),
249
- title: `Sign in to ${i.label} again`,
250
- "aria-label": `Sign in to ${i.label} again`,
249
+ onClick: () => o(n.key, l.id),
250
+ title: `Sign in to ${l.label} again`,
251
+ "aria-label": `Sign in to ${l.label} again`,
251
252
  className: "flex size-7 items-center justify-center rounded-full text-muted-foreground transition hover:bg-muted hover:text-foreground",
252
253
  children: /* @__PURE__ */ e(R, { className: "size-3.5" })
253
254
  }
@@ -257,32 +258,32 @@ function re({
257
258
  {
258
259
  size: "sm",
259
260
  variant: "outline",
260
- onClick: () => o(n.key, i.id),
261
+ onClick: () => o(n.key, l.id),
261
262
  children: [
262
263
  /* @__PURE__ */ e(h, { className: "size-3.5" }),
263
- i.needsReconnect ? "Reconnect" : "Connect"
264
+ l.needsReconnect ? "Reconnect" : "Connect"
264
265
  ]
265
266
  }
266
267
  ),
267
- i.removable ? /* @__PURE__ */ e(
268
+ l.removable ? /* @__PURE__ */ e(
268
269
  "button",
269
270
  {
270
271
  type: "button",
271
- onClick: () => u(i),
272
- title: `Remove ${i.label}`,
273
- "aria-label": `Remove ${i.label}`,
272
+ onClick: () => u(l),
273
+ title: `Remove ${l.label}`,
274
+ "aria-label": `Remove ${l.label}`,
274
275
  className: "flex size-7 items-center justify-center rounded-full text-muted-foreground transition hover:bg-destructive/10 hover:text-destructive",
275
- children: /* @__PURE__ */ e(E, { className: "size-3.5" })
276
+ children: /* @__PURE__ */ e(P, { className: "size-3.5" })
276
277
  }
277
278
  ) : null
278
279
  ]
279
280
  },
280
- i.id
281
+ l.id
281
282
  )) }) : null,
282
- k.length ? /* @__PURE__ */ e("div", { className: "space-y-1.5", children: k.map((i) => /* @__PURE__ */ e(
283
+ k.length ? /* @__PURE__ */ e("div", { className: "space-y-1.5", children: k.map((l) => /* @__PURE__ */ e(
283
284
  te,
284
285
  {
285
- provider: i,
286
+ provider: l,
286
287
  onConnect: (N) => {
287
288
  if (n.key === "jcode" && w) {
288
289
  m(n.key);
@@ -292,29 +293,29 @@ function re({
292
293
  },
293
294
  onDisconnect: (N) => b(n.key, N)
294
295
  },
295
- i.id
296
+ l.id
296
297
  )) }) : null,
297
298
  /* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-2", children: [
298
- l.canAutoSetup && w ? /* @__PURE__ */ t(
299
+ i.canAutoSetup && w ? /* @__PURE__ */ t(
299
300
  d,
300
301
  {
301
302
  size: "sm",
302
303
  variant: "outline",
303
- disabled: l.setupRunning,
304
+ disabled: i.setupRunning,
304
305
  onClick: () => m(n.key),
305
306
  title: "Run setup for this agent",
306
307
  children: [
307
- l.setupRunning ? /* @__PURE__ */ e($, { className: "size-4 animate-spin" }) : /* @__PURE__ */ e(A, { className: "size-4" }),
308
- l.setupRunning ? "Running…" : "Install"
308
+ i.setupRunning ? /* @__PURE__ */ e($, { className: "size-4 animate-spin" }) : /* @__PURE__ */ e(A, { className: "size-4" }),
309
+ i.setupRunning ? "Running…" : "Install"
309
310
  ]
310
311
  }
311
312
  ) : null,
312
- c.length && _ ? /* @__PURE__ */ t(
313
+ c.length && q ? /* @__PURE__ */ t(
313
314
  d,
314
315
  {
315
316
  size: "sm",
316
317
  variant: "outline",
317
- disabled: l.setupRunning,
318
+ disabled: i.setupRunning,
318
319
  onClick: () => f(),
319
320
  title: "Add another Claude account",
320
321
  children: [
@@ -323,14 +324,14 @@ function re({
323
324
  ]
324
325
  }
325
326
  ) : null,
326
- l.canLoginInTerminal && !G ? /* @__PURE__ */ t(
327
+ i.canLoginInTerminal && !H ? /* @__PURE__ */ t(
327
328
  d,
328
329
  {
329
330
  size: "sm",
330
331
  variant: "outline",
331
- disabled: l.setupRunning,
332
+ disabled: i.setupRunning,
332
333
  onClick: () => o(n.key),
333
- title: n.key === "aisdk" && c.length ? "Add another Claude account" : D.has(n.key) ? `Sign in to ${n.label} in your browser` : `Open terminal and run ${l.loginCommand}`,
334
+ title: n.key === "aisdk" && c.length ? "Add another Claude account" : D.has(n.key) ? `Sign in to ${n.label} in your browser` : `Open terminal and run ${i.loginCommand}`,
334
335
  children: [
335
336
  D.has(n.key) ? /* @__PURE__ */ e(h, { className: "size-4" }) : /* @__PURE__ */ e(S, { className: "size-4" }),
336
337
  "Login"
@@ -1,7 +1,7 @@
1
1
  import { jsxs as pe, jsx as J, Fragment as zt } from "react/jsx-runtime";
2
2
  import { useState as Ve, useRef as Qe, useCallback as ve, useEffect as Le } from "react";
3
- import { f as Fn, a3 as Ai, ab as Mn, B as Ge, R as Tn, X as Qn, L as Xi, ae as Ln } from "./embedded-oaPwSSek.js";
4
- import { K as Rn } from "./keyboard-M0kWYsLv.js";
3
+ import { f as Fn, a3 as Ai, ab as Mn, B as Ge, R as Tn, X as Qn, L as Xi, ae as Ln } from "./embedded-B6IaTsrk.js";
4
+ import { K as Rn } from "./keyboard-DCTxfrP6.js";
5
5
  /**
6
6
  * @license lucide-react v0.577.0 - ISC
7
7
  *