@ycodium-ai/agent-antigravity 0.2.2743

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/README.md ADDED
@@ -0,0 +1,256 @@
1
+ # @ycodium-ai/agent-antigravity
2
+
3
+ Google Antigravity executor plugin. It runs the official Antigravity agent program
4
+ (`agy_acp_server`) over Agent Client Protocol stdio, one process per conversation, and runs the
5
+ shared `ycodium-acp-executor` state machine.
6
+
7
+ This is an external plugin: it is not part of the pre-installed set. Install it from the plugin
8
+ center, then add a provider with the Antigravity card. Open the provider afterwards: its page has
9
+ a section for the downloaded runtime, the Google sign-in and the model list (see "The settings
10
+ section" below). That section exists on Web and Desktop only; Mobile has no screen for adding or
11
+ editing a provider.
12
+
13
+ ## Setting it up
14
+
15
+ - **Program.** The plugin picks the program in this order: the **program path** field, then the
16
+ runtime the plugin downloaded itself (see below), then the provider's `PATH`. The program is
17
+ `agy_acp_server.exe` on Windows and `agy_acp_server.par` elsewhere; the `localharness_external`
18
+ file that ships with it must sit in the same folder. A path in the field that does not exist is
19
+ reported as an error; it never falls back to the downloaded runtime or `PATH`.
20
+ - **Account directory.** Optional. Each provider gets its own private account profile under the
21
+ plugin's data directory, so two providers never share a Google sign-in by accident. Set a
22
+ directory here to share one profile between providers on purpose.
23
+ - A session started without a Google sign-in fails with a message that says so.
24
+
25
+ ## The settings section
26
+
27
+ The provider's page shows three blocks, all for that provider's own instance and on the machine the
28
+ provider runs on. Buttons are disabled for read-only viewers.
29
+
30
+ - **Antigravity runtime.** The state (not installed, the installed version, an update is
31
+ available, the install phase with the downloaded bytes of the total, or why the last attempt
32
+ failed). Before you press **Install** or **Update** it states the download size, the installed
33
+ size and the free disk space the install needs. **Remove runtime** asks for confirmation first
34
+ and, when something holds the runtime, is disabled with the reason beside it.
35
+ - **Google sign-in.** The state (not signed in, signed in, or the step in progress). **Sign in with
36
+ Google** starts the flow; while it waits the block shows the sign-in link with **Open** (system
37
+ browser) and **Copy link**, a box to paste the address the browser ended up on with **Finish**,
38
+ the deadline, and **Cancel sign-in**. A browser on the provider's own machine finishes by itself,
39
+ so nothing needs pasting there. **Sign out** asks first because it stops the provider's
40
+ conversations.
41
+ - **Models.** **Refresh models** asks Antigravity for the model list and shows how many came back,
42
+ or why it failed.
43
+
44
+ Sign-in, sign-out and **Refresh models** all start the program, so while it cannot be found (no
45
+ runtime installed, no usable program path, nothing on `PATH`) they are disabled and the sign-in
46
+ block says to install the runtime or set the program path. `auth.state` carries the reason as
47
+ `programUnavailable`; the plugin resolves the program again when the state is subscribed, when the
48
+ instance is created, and when the runtime is installed, updated or removed.
49
+
50
+ Failures arrive with a stable `code`; the section has hand-written English and Simplified Chinese
51
+ text for every code it knows and shows the backend's English message for a code it does not.
52
+ The add dialog has no instance yet, so there the section is a single hint line.
53
+
54
+ ## The downloaded runtime
55
+
56
+ The plugin can download Google's official runtime for you, but **only when you ask**: nothing is
57
+ downloaded when the plugin loads, when a provider is added, or on a health check. The download
58
+ is large, so the state the plugin reports before you start includes the sizes and the free disk
59
+ space it needs. Per platform (as the section shows them, in 1024-based units):
60
+
61
+ | Platform | Download | Installed | Free space needed |
62
+ | ------------- | -------- | --------- | ----------------- |
63
+ | Windows x64 | 447 MB | 536 MB | 1.2 GB |
64
+ | Windows arm64 | 447 MB | 532 MB | 1.2 GB |
65
+ | macOS arm64 | 301 MB | 876 MB | 1.4 GB |
66
+ | Linux x64 | 650 MB | 1.9 GB | 2.8 GB |
67
+ | Linux arm64 | 626 MB | 1.8 GB | 2.7 GB |
68
+
69
+ Google publishes no runtime for other platforms (Intel Macs, for one): install the program
70
+ yourself and set the program path.
71
+
72
+ - The release table lives in the plugin's source: for each of the five supported platforms it pins
73
+ the download URL, the archive's SHA-256 and byte count, and the two program files' names and
74
+ sizes. A download that does not match is discarded whole; only those two files are extracted,
75
+ and the runtime is started once in a throwaway profile to check it identifies as the expected
76
+ release before it is activated. The download goes through the host's proxy settings and gives up
77
+ after 45 minutes.
78
+ - Files go under `<plugin data>/runtime/<platform>-<arch>/versions/<release id>/`, and
79
+ `active.json` switches to a new version atomically. An update is just a new release id in the
80
+ table; it installs next to the old version and never touches files a running session uses.
81
+ - **Old versions are cleaned up after a successful update.** Once the new version is read back as
82
+ the active one, every other version directory nobody holds is deleted. A version a running
83
+ session still holds is remembered and deleted when its last lease is returned, unless it has
84
+ become the active version again by then. A version a provider's program path points into is left
85
+ alone. A failed update deletes nothing, and a deletion that fails (a locked file, say) is only
86
+ logged: the runtime state is unaffected and the next successful update tries again.
87
+ - Each running agent process holds a lease on the version it started with. Removing the runtime is
88
+ refused while a lease is held, while an install is running, and while a provider's program path
89
+ points into the downloaded files.
90
+ - The host has no install button for a program a plugin manages, so the settings section above
91
+ drives plugin commands `runtime.install` and `runtime.remove` and the stream `runtime.state` (install phase,
92
+ downloaded bytes of the total, update available, whether it can be removed and why not, the last
93
+ error, and the sizes from the release table). An install keeps running if the client that
94
+ started it disconnects.
95
+
96
+ ## Signing in
97
+
98
+ Only personal Google accounts are supported (`oauth-personal`). Sign-in runs on the machine the
99
+ provider runs on: the agent listens on a loopback port there and waits for the browser to come
100
+ back to it.
101
+
102
+ - **Same machine as the browser.** Open the sign-in link; the browser finishes the sign-in by
103
+ itself.
104
+ - **Remote machine.** Open the link anywhere, sign in, then copy the full address the browser
105
+ ends up on (it points at `127.0.0.1` and will not load) and hand it back. The plugin checks it
106
+ belongs to this sign-in and delivers it to the agent once.
107
+ - A sign-in lasts at most five minutes and can be cancelled. Signing out stops every session of
108
+ the provider first. Typing `/logout` in a conversation does the same.
109
+ - Once signed in, the plugin opens one short-lived session to read the account's model list, so a
110
+ new provider reports its models right away. The same refresh is available on demand.
111
+ - The plugin writes its own "signed in" marker into the account directory and never reads the
112
+ agent's token file. The marker is what the health check reports; an agent that asks to sign in
113
+ again removes it.
114
+ - Everyone who can operate the provider can see the sign-in link while a sign-in is running. The
115
+ link carries no credentials.
116
+
117
+ The settings section drives these entry points; any client that can call plugin commands can too.
118
+
119
+ ### Backend entry points
120
+
121
+ Plugin commands (all need operate access; payloads carry `instanceId`):
122
+ `auth.start`, `auth.complete` (`callbackUrl`), `auth.cancel`, `auth.logout`,
123
+ `models.refresh`. Stream: `auth.state`.
124
+
125
+ `auth.start`, `auth.complete`, `auth.cancel`, `auth.logout` and every `auth.state` item return
126
+ `{ instanceId, phase, operation, authorizationUrl, expiresAt, error, signedIn }`:
127
+
128
+ - `phase`: `idle`, `starting`, `waiting` (the link is in `authorizationUrl`), `verifying`,
129
+ `succeeded`, `failed`, `cancelled`.
130
+ - `operation`: `sign-in`, `sign-out`, `refresh-models`, or `null` when nothing runs.
131
+ - `error`: `null` or `{ code, message }`. Failures also reach command callers as errors carrying
132
+ the same `code`. Codes: `program-unavailable`, `too-many-processes`, `process-exited`,
133
+ `agent-timeout`, `invalid-url`, `multiple-urls`, `expired`, `denied`,
134
+ `subscription-required`, `sign-in-unsupported`, `session-init-failed`, `sign-in-required`,
135
+ `callback-too-long`, `callback-malformed`, `callback-mismatch`, `callback-no-response`,
136
+ `callback-bad-issuer`, `callback-already-sent`, `callback-delivery-failed`,
137
+ `no-active-sign-in`, `sign-in-not-ready`, `logout-unsupported`, `logout-failed`,
138
+ `refresh-failed`, `busy`, `instance-unavailable`, `instance-disposed`, `sign-in-failed`.
139
+
140
+ `models.refresh` returns `{ models: [{ slug, name? }], currentModel }`.
141
+
142
+ ## Behaviour worth knowing
143
+
144
+ - **Uninstalling the plugin keeps what it stored**, including the downloaded runtime (up to
145
+ about 2 GB). Press **Remove runtime** first if you want the disk space back.
146
+ - **The health check never starts the agent.** The program is a single-file bundle that unpacks
147
+ about 1 GB on every launch, so the plugin only checks that the files exist on disk and that its
148
+ own signed-in marker is there. The model list and version are cached from the last sign-in,
149
+ model refresh or real session; a provider that has done none of these shows no models.
150
+ - **Each process unpacks into its own short temp folder** under the plugin's data directory, which
151
+ is removed when the process ends. Leftovers from a crash are swept the next time the provider is
152
+ created.
153
+ - **Permission levels** map to the agent's own modes: approval-required and auto to `default`,
154
+ auto-accept-edits to `auto_edit`, full-access to `yolo`.
155
+ - **Workspace file reads and writes** go through the client, limited to the conversation's working
156
+ directory (and the attachment folder for reads).
157
+ - Choices the agent asks for (`interaction_…` requests) are shown as questions.
158
+ - Image attachments are sent as native image blocks (BMP, JPEG, PNG, WebP; 10 MiB each, 50 MiB
159
+ total, declared on the card as `capabilities.inlineImages`). The host passes any image outside
160
+ those facts, such as a GIF or an oversized one, by its file path only instead of failing the turn.
161
+ - **Commands that outlive a turn can be stopped.** A command the agent started that is still
162
+ running when the turn ends is shown as a background task. With no turn running, Stop closes
163
+ that conversation's agent process (the agent ends its own background commands when it closes),
164
+ the task is marked stopped, and the next message resumes the same conversation. Stop during a
165
+ running turn only cancels that turn, and other conversations are never touched.
166
+ - **Short generated text.** Conversation titles, branch names, commit messages, pull request
167
+ descriptions and hand-over summaries can be written by Antigravity. Each one runs in its own
168
+ agent process in an empty temporary folder; the agent may only answer, so any tool call, permission
169
+ request, question or file access fails the generation. The folder, the process's temp directory and
170
+ the conversation files the temporary session left in the account directory are removed afterwards.
171
+ It is not available for an account whose `config/hooks.json` or `config/mcp_config.json` (in the
172
+ account directory) is anything but empty, because those run when the agent starts. These processes
173
+ count against the provider's limit of two; when it is reached the generation fails with a message
174
+ saying so. Signing out or removing the provider stops them first.
175
+
176
+ ## Skills
177
+
178
+ Antigravity looks for personal skills under `GEMINI_HOME`, which the plugin points at the
179
+ provider's private account directory. So when a session starts the plugin links that directory's
180
+ `config/skills` and `antigravity-cli/skills` back to the same folders under the real
181
+ `~/.gemini` (a symlink on macOS and Linux, a junction on Windows, which needs no administrator
182
+ rights). MCP configuration, hooks and credentials stay private. A real directory already at a link
183
+ path is the user's own and is never replaced; a stale link is repointed; a link that cannot be
184
+ made is logged and the session starts without personal skills. The home is resolved from the
185
+ program's launch environment (`USERPROFILE` on Windows, `HOME` elsewhere; the provider's
186
+ environment variables override the server's).
187
+
188
+ The health check reports machine-level skills by reading those two roots on disk (no process): a
189
+ skill is a folder with a `SKILL.md` whose YAML header has `name` and `description`, a root may
190
+ itself hold one `SKILL.md`, the first root wins a duplicate name, and the scan is bounded at 8 MB
191
+ of skill text, 10,000 directory entries and 1 MB per file. A scan that runs over budget or cannot
192
+ read a folder leaves `skills` out of the result instead of reporting a partial list. Project skills
193
+ (`.gemini/skills`, `.agents/skills`, `.agent/skills` under the working directory) are a known gap:
194
+ the health check has no working directory, so it does not report them, although the agent itself
195
+ loads them. `verifiedSkills` stays `false` on the card.
196
+
197
+ ## Subagents
198
+
199
+ ACP 1.1.1 presents a subagent launch as an ordinary tool whose title is `Running start_subagent`
200
+ (or `Run start_subagent?` while it waits for approval) with kind `other` or none. The plugin
201
+ turns it into `task.*` events with `taskType: "subagent"` and the tool call id as `taskId`
202
+ instead of drawing a tool row, and does not split the reply around it. A same-named MCP tool
203
+ (`_meta.is_mcp_tool_call` true on its first update) is left as an ordinary tool; the plugin decides
204
+ that on the first update it sees, because later updates omit `_meta`.
205
+
206
+ The launch call returns a description of the batch, not a result, so the entry is titled
207
+ "Antigravity subagent batch" and stays `running` while the turn runs; only a failed call completes
208
+ it. When the turn ends the plugin settles every open batch as `idle` with `timelineBypass` (the
209
+ agent panel keeps it, the parent timeline does not) and never as interrupted; a cancelled turn or a
210
+ stopped session settles it as `cancelled`, and a turn that fails because the process died as
211
+ `failed`. A replayed history sends a completed launch before its result: the plugin waits for the
212
+ result and then settles it as `idle` (or `completed` with the error for a failure).
213
+
214
+ ## Large tool payloads
215
+
216
+ Every tool call update is truncated before the shared executor sees it, so event raw payloads are
217
+ bounded: strings keep their last 8,000 characters behind a truncation marker; `rawInput`,
218
+ `rawOutput` and `_meta` each keep at most 512 nodes and 64,000 characters, `content` 512 nodes and
219
+ 32,000 characters, nesting stops at twelve levels, image bytes and `data:image` strings are
220
+ dropped, and a formatted copy identical to the combined output is not kept twice.
221
+
222
+ ## Not yet checked against the real program
223
+
224
+ The behaviour below is inferred from the ACP protocol and the published release, not observed on
225
+ Google's program. Google's cloud OAuth client for Antigravity uses the authorization endpoint
226
+ `https://accounts.google.com/o/oauth2/v2/auth` with `response_type=code` and a single `state`,
227
+ which matches what the sign-in check accepts. Nothing public about that client documents the
228
+ ACP program's own output, so the first run on a real machine must record each of these as is:
229
+
230
+ 1. `initialize`: `agentInfo.name` and `agentInfo.version`. The release table says
231
+ `agy_acp_server_1.1.1`; the post-install check compares the version number with or without
232
+ that prefix, so either form passes, and a different number fails the install.
233
+ 2. The sign-in prompt line on stdout or stderr, and the authorization link's `redirect_uri`
234
+ (`127.0.0.1` or `localhost`, a random or fixed port, path `/` or something longer) and whether
235
+ it carries `code_challenge`. The link check only accepts `http://127.0.0.1:<port>/`; another
236
+ shape fails sign-in with `invalid-url`.
237
+ 3. Whether the callback address the browser lands on carries `iss`.
238
+ 4. The JSON-RPC error code and message when `authenticate` fails for an account without a
239
+ subscription, and whether it contains `SUBSCRIPTION_REQUIRED`.
240
+ 5. The error code of `session/new` when signed out (assumed `-32000`) and when signed in but the
241
+ session cannot start (assumed `-32603`).
242
+ 6. The `logout` method name and its reply.
243
+ 7. The model entries in `configOptions`: `value` and `name` as sent.
244
+ 8. With `BROWSER` set, whether the program runs the helper instead of opening a browser, and
245
+ whether a Windows path with `;` in it is split.
246
+ 9. `start_subagent`: the tool call's title before and after approval, its `kind` and `_meta`.
247
+
248
+ Manifest permission is `{ kind: "executor" }`.
249
+
250
+ Develop with `vp run --filter @ycodium-ai/agent-antigravity typecheck`, `build`, and `test`.
251
+ `build` also bundles the settings section (`assets/ui.js`, from `src/ui/`); `typecheck` covers the
252
+ server code and the section separately.
253
+
254
+ ## License
255
+
256
+ UNLICENSED.
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
2
+ <circle cx="16" cy="16" r="12" stroke="#4F6BED" stroke-width="2"/>
3
+ <path d="M16 8l6 9h-4v7h-4v-7h-4l6-9z" fill="#4F6BED"/>
4
+ </svg>
package/assets/ui.js ADDED
@@ -0,0 +1,95 @@
1
+ var G=window.__ycodiumPluginHost.modules?.["@ycodium-ai/plugin-api/provider-settings"];if(!G)throw new Error("This plugin needs a newer Ycodium app. Update the app.");var{PROVIDER_SETTINGS_VIEW_CAPABILITY:$,accountDirectoryCandidates:Re,accountDirectorySlug:Be,accountProbeHasSignedInAccount:Ie,allocateAccountDirectory:Ae,providerInstanceAccountPaths:Te}=G;var xe=window.__ycodiumPluginHost.react;var{Activity:Ce,Children:Ee,Component:Ne,Fragment:Pe,Profiler:_e,PureComponent:Ue,StrictMode:Fe,Suspense:Me,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:Oe,__COMPILER_RUNTIME:Ke,act:Le,cache:Ve,cacheSignal:ze,captureOwnerStack:He,cloneElement:De,createContext:j,createElement:J,createRef:Ye,forwardRef:qe,isValidElement:We,lazy:Ge,memo:$e,startTransition:je,unstable_useCacheRefresh:Je,use:Qe,useActionState:Xe,useCallback:Ze,useContext:Q,useDebugValue:et,useDeferredValue:tt,useEffect:nt,useEffectEvent:rt,useId:it,useImperativeHandle:ot,useInsertionEffect:at,useLayoutEffect:st,useMemo:lt,useOptimistic:dt,useReducer:ut,useRef:ct,useState:u,useSyncExternalStore:mt,useTransition:pt,version:gt}=xe;var X=j(null),Z=X.Provider;function f(){let e=Q(X);if(e===null)throw new Error("Antigravity UI has not been registered.");return e}var ee={"insufficient-space":"runtime.errors.insufficientSpace","download-failed":"runtime.errors.downloadFailed",timeout:"runtime.errors.timeout","verification-failed":"runtime.errors.verificationFailed","extract-failed":"runtime.errors.extractFailed","validation-failed":"runtime.errors.validationFailed","activate-failed":"runtime.errors.activateFailed","install-failed":"runtime.errors.installFailed","runtime-damaged":"runtime.errors.damaged","unsupported-platform":"runtime.errors.unsupportedPlatform","no-instance":"runtime.errors.noInstance",busy:"runtime.errors.busy","remove-failed":"runtime.errors.removeFailed","runtime-installing":"runtime.removeBlocked.installing","runtime-in-use":"runtime.removeBlocked.inUse","runtime-custom-path":"runtime.removeBlocked.customPath"},te={installing:"runtime.removeBlocked.installing","in-use":"runtime.removeBlocked.inUse","custom-path":"runtime.removeBlocked.customPath"},V={"program-unavailable":"auth.errors.programUnavailable","too-many-processes":"auth.errors.tooManyProcesses","process-exited":"auth.errors.processExited","agent-timeout":"auth.errors.agentTimeout","invalid-url":"auth.errors.invalidUrl","multiple-urls":"auth.errors.multipleUrls",expired:"auth.errors.expired",denied:"auth.errors.denied","subscription-required":"auth.errors.subscriptionRequired","sign-in-unsupported":"auth.errors.signInUnsupported","session-init-failed":"auth.errors.sessionInitFailed","sign-in-required":"auth.errors.signInRequired","callback-too-long":"auth.errors.callbackTooLong","callback-malformed":"auth.errors.callbackMalformed","callback-mismatch":"auth.errors.callbackMismatch","callback-no-response":"auth.errors.callbackNoResponse","callback-bad-issuer":"auth.errors.callbackBadIssuer","callback-already-sent":"auth.errors.callbackAlreadySent","callback-delivery-failed":"auth.errors.callbackDeliveryFailed","no-active-sign-in":"auth.errors.noActiveSignIn","sign-in-not-ready":"auth.errors.signInNotReady","logout-unsupported":"auth.errors.logoutUnsupported","logout-failed":"auth.errors.logoutFailed","refresh-failed":"auth.errors.refreshFailed",busy:"auth.errors.busy","instance-unavailable":"auth.errors.instanceUnavailable","instance-disposed":"auth.errors.instanceDisposed","sign-in-failed":"auth.errors.signInFailed"};function b(e,t,i,p={}){let d=i.code===void 0?void 0:t[i.code];return d===void 0?i.message:e(d,p)}function A(e){return(t=>J(f().ui[e],{...t,className:`ycodium-antigravity-ui ${typeof t.className=="string"?t.className:""}`}))}var l=A("Button"),ne=A("Input"),re=A("Badge"),ie=A("Alert"),oe=A("AlertDescription"),z=A("Spinner");function T(){let e=f().i18n.usePluginTranslation();return{t:(t,i)=>e(t,i)}}var{jsx:n,jsxs:o,Fragment:k}=window.__ycodiumPluginHost.jsxRuntime;function E(e){return o("section",{className:"grid gap-2",children:[n("h3",{className:"text-ui-md font-medium",children:e.title}),e.description===void 0?null:n("p",{className:"text-ui-sm text-muted-foreground",children:e.description}),e.children]})}function R(e){return n(ie,{variant:"error",children:n(oe,{"data-slot":"alert-description",children:e.text})})}function H(e){let[t,i]=u(!1);return t?o("div",{className:"grid gap-2",children:[n("p",{className:"text-ui-sm",children:e.prompt}),o("div",{className:"flex flex-wrap gap-2",children:[n(l,{size:"xs",variant:"destructive-outline",disabled:e.disabled,onClick:()=>{i(!1),e.onConfirm()},children:e.confirmLabel}),n(l,{size:"xs",variant:"ghost",onClick:()=>i(!1),children:e.cancelLabel})]})]}):n("div",{className:"flex flex-wrap gap-2",children:n(l,{size:"xs",variant:"outline",disabled:e.disabled,onClick:()=>i(!0),children:e.label})})}var D=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function ae(e){return!D(e)||typeof e.phase!="string"||typeof e.installed!="boolean"?null:e}function se(e){return!D(e)||typeof e.phase!="string"||typeof e.signedIn!="boolean"?null:e}function le(e){return!D(e)||!Array.isArray(e.models)?null:e}function N(e){let i=(D(e)?e:void 0)?.pluginCode,p=e instanceof Error?e.message:String(e);return{code:typeof i=="string"?i:void 0,message:p}}function h(e){let t=e/1048576;return t>=1024?`${(t/1024).toFixed(1)} GB`:`${Math.max(1,Math.round(t))} MB`}function de(e){let{t}=T(),i=f(),p=i.useFormatTimestamp(),d={environmentId:e.environmentId},c=i.commands.useSubscription("auth.state",{instanceId:e.instanceId},d),g=se(c.data),[S,P]=u(!1),[_,C]=u(null),[s,v]=u(""),[U,r]=u(null),[m,B]=u(null),F=async(a,y)=>{P(!0);try{return await i.commands.invoke(a,y,d)}finally{P(!1)}},x=async(a,y={})=>{C(null);try{return await F(a,{instanceId:e.instanceId,...y}),!0}catch(w){return C(N(w)),!1}},M=async()=>{await x("auth.complete",{callbackUrl:s.trim()})&&v("")},ge=async()=>{r(null),B(null);try{r(le(await F("models.refresh",{instanceId:e.instanceId})))}catch(a){B(N(a))}},ye=async a=>{try{await i.writeClipboard(a),i.notify(t("auth.copied"),"success")}catch{i.notify(t("auth.copyFailed"),"error")}},fe=a=>{let y=a.operation,w=y!==null,O=y==="sign-in",K=O&&a.phase==="waiting"?a.authorizationUrl:null,L=S||e.readOnly,I=w?null:a.programUnavailable,q=_??(w?null:a.error),W=I!==null&&q?.code===I.code?null:q,ve=O?a.phase==="waiting"?"auth.state.waiting":a.phase==="verifying"?"auth.state.verifying":"auth.state.starting":y==="sign-out"?"auth.state.signingOut":y==="refresh-models"?"auth.state.refreshing":a.signedIn?"auth.state.signedIn":a.phase==="cancelled"?"auth.state.cancelled":"auth.state.signedOut";return o(k,{children:[o("p",{className:"flex items-center gap-2 text-ui-md",children:[w?n(z,{className:"size-3.5"}):n(re,{variant:a.signedIn?"success":"outline",children:t(a.signedIn?"auth.badge.signedIn":"auth.badge.signedOut")}),n("span",{children:t(ve)})]}),W===null?null:n(R,{text:b(t,V,W)}),I===null?null:n("p",{className:"text-ui-sm text-muted-foreground",children:b(t,V,I)}),K===null?null:o("div",{className:"grid gap-2",children:[n("p",{className:"text-ui-sm text-muted-foreground",children:t("auth.linkIntro")}),n("p",{className:"break-all text-ui-xs select-text",children:K}),o("div",{className:"flex flex-wrap gap-2",children:[n(l,{size:"xs",variant:"outline",onClick:()=>i.openExternal(K),children:t("auth.open")}),n(l,{size:"xs",variant:"outline",onClick:()=>{ye(K)},children:t("auth.copy")})]}),o("label",{className:"grid gap-1",children:[n("span",{className:"text-ui-sm font-medium",children:t("auth.pasteLabel")}),n(ne,{value:s,onChange:Y=>v(Y.target.value),onKeyDown:Y=>{Y.key==="Enter"&&s.trim().length>0&&!L&&M()},placeholder:t("auth.pastePlaceholder"),spellCheck:!1,autoComplete:"off","aria-label":t("auth.pasteLabel")})]}),n("p",{className:"text-ui-sm text-muted-foreground",children:t("auth.pasteHint")}),n("div",{className:"flex flex-wrap gap-2",children:n(l,{size:"xs",disabled:L||s.trim().length===0,onClick:()=>{M()},children:t("auth.complete")})})]}),a.expiresAt!==null&&O?n("p",{className:"text-ui-xs text-muted-foreground",children:t("auth.expiresAt",{time:p(a.expiresAt)})}):null,o("div",{className:"flex flex-wrap gap-2",children:[!w&&!a.signedIn?n(l,{size:"xs",disabled:L||I!==null,onClick:()=>{v(""),x("auth.start")},children:t("auth.start")}):null,O?n(l,{size:"xs",variant:"outline",disabled:e.readOnly,onClick:()=>{v(""),x("auth.cancel")},children:t("auth.cancel")}):null]}),!w&&a.signedIn?n(H,{label:t("auth.logout"),prompt:t("auth.logoutConfirm"),confirmLabel:t("auth.logoutConfirmAction"),cancelLabel:t("common.cancel"),disabled:L||I!==null,onConfirm:()=>{x("auth.logout")}}):null]})},he=c.error!==null?null:c.isUnavailable?n("p",{className:"text-ui-sm text-muted-foreground",children:t("common.unavailable")}):n("p",{className:"text-ui-sm text-muted-foreground",children:t("common.loading")});return o(k,{children:[o(E,{title:t("auth.title"),description:t("auth.description"),children:[c.error===null?null:n(R,{text:t("common.loadFailed",{message:c.error})}),g===null?he:fe(g)]}),o(E,{title:t("models.title"),description:t("models.description"),children:[n("div",{className:"flex flex-wrap gap-2",children:n(l,{size:"xs",variant:"outline",disabled:g===null||g.operation!==null||g.programUnavailable!==null||S||e.readOnly,onClick:()=>{ge()},children:t("models.refresh")})}),U===null?null:n("p",{className:"text-ui-sm text-muted-foreground",children:t("models.result",{count:U.models.length})}),m===null?null:n(R,{text:b(t,V,m)})]})]})}var we=new Set(["downloading","extracting","verifying"]);function ue(e){let{t}=T(),i=f(),p={environmentId:e.environmentId},d=i.commands.useSubscription("runtime.state",{},p),c=ae(d.data),[g,S]=u(!1),[P,_]=u(null),C=async(r,m)=>{_(null),S(!0);try{await i.commands.invoke(r,m,p)}catch(B){_(N(B))}finally{S(!1)}},s=c?.release??null,v={download:s===null?"":h(s.archiveBytes),installed:s===null?"":h(s.installedBytes),free:s===null?"":h(s.requiredFreeBytes),size:s===null?"":h(s.requiredFreeBytes)},U=r=>{let m=we.has(r.phase),B=s!==null&&(!r.installed||r.updateAvailable),F=m?r.phase==="downloading"?r.totalBytes===null||r.totalBytes<=0?t("runtime.state.downloadingUnknown",{done:h(r.downloadedBytes)}):t("runtime.state.downloading",{done:h(r.downloadedBytes),total:h(r.totalBytes),percent:Math.min(100,Math.floor(r.downloadedBytes*100/r.totalBytes))}):t(r.phase==="extracting"?"runtime.state.extracting":"runtime.state.verifying"):r.installed?r.updateAvailable?t("runtime.state.updateAvailable",{version:r.installedVersion??"",latest:s?.version??""}):t("runtime.state.installed",{version:r.installedVersion??""}):t(s===null?"runtime.state.unsupported":"runtime.state.notInstalled"),x=P??r.error,M=r.canRemove||r.removeBlocked!==null;return o(k,{children:[o("p",{className:"flex items-center gap-2 text-ui-md",children:[m?n(z,{className:"size-3.5"}):null,n("span",{children:F})]}),x===null||m?null:n(R,{text:b(t,ee,x,v)}),B&&!m?o(k,{children:[n("p",{className:"text-ui-sm text-muted-foreground",children:t("runtime.sizes",v)}),n("div",{className:"flex flex-wrap gap-2",children:n(l,{size:"xs",disabled:g||e.readOnly,onClick:()=>{C("runtime.install",{instanceId:e.instanceId})},children:t(r.installed?"runtime.update":"runtime.install")})})]}):null,M?o(k,{children:[n(H,{label:t("runtime.remove"),prompt:t("runtime.removeConfirm"),confirmLabel:t("runtime.removeConfirmAction"),cancelLabel:t("common.cancel"),disabled:g||e.readOnly||!r.canRemove,onConfirm:()=>{C("runtime.remove",{})}}),r.removeBlocked===null?null:n("p",{className:"text-ui-sm text-muted-foreground",children:b(t,te,r.removeBlocked)})]}):null]})};return o(E,{title:t("runtime.title"),description:t("runtime.description"),children:[d.error===null?null:n(R,{text:t("common.loadFailed",{message:d.error})}),c!==null?U(c):d.isUnavailable?n("p",{className:"text-ui-sm text-muted-foreground",children:t("common.unavailable")}):d.error===null?n("p",{className:"text-ui-sm text-muted-foreground",children:t("common.loading")}):null]})}function ce(e){let{t}=T();return e.placement==="add"||e.instanceId===null?n("p",{className:"ycodium-antigravity-ui text-ui-sm text-muted-foreground",children:t("add.hint")}):o("div",{className:"ycodium-antigravity-ui grid gap-6",children:[n(ue,{instanceId:e.instanceId,environmentId:e.environmentId,readOnly:e.readOnly}),n(de,{instanceId:e.instanceId,environmentId:e.environmentId,readOnly:e.readOnly})]})}var me=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
2
+ @layer properties, theme, base, components, utilities;
3
+ @layer properties;
4
+ @layer utilities {
5
+ @scope (.ycodium-antigravity-ui) {
6
+ .fixed:where(:scope, *) {
7
+ position: fixed;
8
+ }
9
+ .container:where(:scope, *) {
10
+ width: 100%;
11
+ @media (width >= 40rem) {
12
+ max-width: 40rem;
13
+ }
14
+ @media (width >= 48rem) {
15
+ max-width: 48rem;
16
+ }
17
+ @media (width >= 64rem) {
18
+ max-width: 64rem;
19
+ }
20
+ @media (width >= 80rem) {
21
+ max-width: 80rem;
22
+ }
23
+ @media (width >= 96rem) {
24
+ max-width: 96rem;
25
+ }
26
+ }
27
+ .flex:where(:scope, *) {
28
+ display: flex;
29
+ }
30
+ .grid:where(:scope, *) {
31
+ display: grid;
32
+ }
33
+ .table:where(:scope, *) {
34
+ display: table;
35
+ }
36
+ .size-3\\.5:where(:scope, *) {
37
+ width: calc(var(--spacing, 0.25rem) * 3.5);
38
+ height: calc(var(--spacing, 0.25rem) * 3.5);
39
+ }
40
+ .flex-wrap:where(:scope, *) {
41
+ flex-wrap: wrap;
42
+ }
43
+ .items-center:where(:scope, *) {
44
+ align-items: center;
45
+ }
46
+ .gap-1:where(:scope, *) {
47
+ gap: calc(var(--spacing, 0.25rem) * 1);
48
+ }
49
+ .gap-2:where(:scope, *) {
50
+ gap: calc(var(--spacing, 0.25rem) * 2);
51
+ }
52
+ .gap-6:where(:scope, *) {
53
+ gap: calc(var(--spacing, 0.25rem) * 6);
54
+ }
55
+ .text-ui-md:where(:scope, *) {
56
+ font-size: var(--ui-text-md);
57
+ line-height: var(--tw-leading, var(--ui-leading-md));
58
+ }
59
+ .text-ui-sm:where(:scope, *) {
60
+ font-size: var(--ui-text-sm);
61
+ line-height: var(--tw-leading, var(--ui-leading-sm));
62
+ }
63
+ .text-ui-xs:where(:scope, *) {
64
+ font-size: var(--ui-text-xs);
65
+ line-height: var(--tw-leading, var(--ui-leading-xs));
66
+ }
67
+ .font-medium:where(:scope, *) {
68
+ --tw-font-weight: var(--font-weight-medium, 500);
69
+ font-weight: var(--font-weight-medium, 500);
70
+ }
71
+ .break-all:where(:scope, *) {
72
+ word-break: break-all;
73
+ }
74
+ .text-muted-foreground:where(:scope, *) {
75
+ color: var(--contrast-muted-foreground);
76
+ }
77
+ .outline:where(:scope, *) {
78
+ outline-style: var(--tw-outline-style);
79
+ outline-width: 1px;
80
+ }
81
+ .select-text:where(:scope, *) {
82
+ -webkit-user-select: text;
83
+ user-select: text;
84
+ }
85
+ }
86
+ }
87
+ @layer properties {
88
+ @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
89
+ *, ::before, ::after, ::backdrop {
90
+ --tw-font-weight: initial;
91
+ --tw-outline-style: solid;
92
+ }
93
+ }
94
+ }
95
+ `;var pe="setup";function ke(e){let t=i=>o(Z,{value:e,children:[n("style",{children:me}),n(ce,{...i})]});return{pages:{},panels:{},views:{[pe]:t},viewCapabilities:{[pe]:[$]}}}export{pe as ANTIGRAVITY_SETUP_SECTION_ID,ke as default};