From c97414cd37c55f07a96862bd49933f1ed6dfbdd3 Mon Sep 17 00:00:00 2001 From: CD Date: Sun, 8 Mar 2026 14:38:41 +0900 Subject: [PATCH] fix(bridge): stall-based approval detection + known issues from deep debugging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - IDLE→stall detection: RUNNING+delta=0 for 6 polls (30s) - lastModifiedTime-based thinking filter (partial) - ResolveOutstandingSteps confirmed CANCELS steps (removed) - HandleCascadeUserInteraction always socket hang up (removed) - VS Code accept commands: silent success, no effect - Hybrid approval: focus+all commands sequential, no break - logToFile: console.log backup added - Known issues: 4 critical findings documented - better-antigravity reference added for future research --- better-antigravity-main/.github/FUNDING.yml | 2 + better-antigravity-main/.gitignore | 10 + better-antigravity-main/.vscodeignore | 12 + better-antigravity-main/FIXES.md | 105 +++ better-antigravity-main/LEGAL.md | 59 ++ better-antigravity-main/LICENSE | 644 ++++++++++++++++++ better-antigravity-main/README.md | 209 ++++++ better-antigravity-main/build.mjs | 57 ++ better-antigravity-main/cli.js | 65 ++ .../fixes/auto-run-fix/patch.js | 400 +++++++++++ better-antigravity-main/package-lock.json | 503 ++++++++++++++ better-antigravity-main/package.json | 94 +++ better-antigravity-main/publish-ovsx.mjs | 44 ++ better-antigravity-main/src/auto-run.ts | 235 +++++++ better-antigravity-main/src/commands.ts | 81 +++ better-antigravity-main/src/extension.ts | 72 ++ .../static/BA-background.png | Bin 0 -> 15954 bytes better-antigravity-main/tsconfig.json | 26 + docs/devlog/2026-03-08.md | 1 + docs/devlog/entries/20260308-005.md | 14 + extension/out/extension.js | 601 +++++++++++----- extension/out/extension.js.map | 2 +- extension/src/extension.ts | 560 +++++++++++---- 23 files changed, 3516 insertions(+), 280 deletions(-) create mode 100644 better-antigravity-main/.github/FUNDING.yml create mode 100644 better-antigravity-main/.gitignore create mode 100644 better-antigravity-main/.vscodeignore create mode 100644 better-antigravity-main/FIXES.md create mode 100644 better-antigravity-main/LEGAL.md create mode 100644 better-antigravity-main/LICENSE create mode 100644 better-antigravity-main/README.md create mode 100644 better-antigravity-main/build.mjs create mode 100644 better-antigravity-main/cli.js create mode 100644 better-antigravity-main/fixes/auto-run-fix/patch.js create mode 100644 better-antigravity-main/package-lock.json create mode 100644 better-antigravity-main/package.json create mode 100644 better-antigravity-main/publish-ovsx.mjs create mode 100644 better-antigravity-main/src/auto-run.ts create mode 100644 better-antigravity-main/src/commands.ts create mode 100644 better-antigravity-main/src/extension.ts create mode 100644 better-antigravity-main/static/BA-background.png create mode 100644 better-antigravity-main/tsconfig.json create mode 100644 docs/devlog/entries/20260308-005.md diff --git a/better-antigravity-main/.github/FUNDING.yml b/better-antigravity-main/.github/FUNDING.yml new file mode 100644 index 0000000..c0955d3 --- /dev/null +++ b/better-antigravity-main/.github/FUNDING.yml @@ -0,0 +1,2 @@ +custom: + - https://github.com/Kanezal/better-antigravity#support diff --git a/better-antigravity-main/.gitignore b/better-antigravity-main/.gitignore new file mode 100644 index 0000000..87c8bf3 --- /dev/null +++ b/better-antigravity-main/.gitignore @@ -0,0 +1,10 @@ +GEMINI.md +node_modules/ +dist/ +out/ +.env +*.vsix +*.bak +*.log +.DS_Store +Thumbs.db diff --git a/better-antigravity-main/.vscodeignore b/better-antigravity-main/.vscodeignore new file mode 100644 index 0000000..872f687 --- /dev/null +++ b/better-antigravity-main/.vscodeignore @@ -0,0 +1,12 @@ +.env +publish-ovsx.mjs +.git/ +.gitignore +node_modules/ +out/ +src/ +build.mjs +tsconfig.json +*.bak +*.log +*.map diff --git a/better-antigravity-main/FIXES.md b/better-antigravity-main/FIXES.md new file mode 100644 index 0000000..26fc0f6 --- /dev/null +++ b/better-antigravity-main/FIXES.md @@ -0,0 +1,105 @@ +# Fixes — Technical Details + +Detailed root cause analysis and patch descriptions for each fix in Better Antigravity. + +--- + +## Auto-Run Fix + +**Status:** Working +**Affected versions:** 1.107.0+ +**Files patched:** `workbench.desktop.main.js`, `jetskiAgent.js` + +### The Problem + +You set **Settings -> Agent -> Terminal Execution -> "Always Proceed"**, but Antigravity **still asks you to click "Run"** on every single terminal command. Every. Single. Time. + +The setting saves correctly, Strict Mode is off -- it just doesn't work. + +### Root Cause + +Found in the source code: the `run_command` step renderer component has an `onChange` handler that auto-confirms commands when you switch the dropdown to "Always run" **on a specific step**. But there's **no `useEffect` hook** that checks the saved policy at mount time and auto-confirms **new steps**. + +In other words: the UI reads your setting, displays the correct dropdown value, but never actually acts on it automatically. + +```javascript +// What exists (only fires on dropdown CHANGE): +y = Mt(_ => { + setTerminalAutoExecutionPolicy(_), + _ === EAGER && confirm(true) // <- only when you manually switch +}, []) + +// What's MISSING (should fire on component mount): +useEffect(() => { + if (policy === EAGER && !secureMode) confirm(true) // <- auto-confirm new steps +}, []) +``` + +### How the Patch Works + +The patcher uses **structural regex matching** to find the `onChange` handler in the minified source. It matches the code by shape, not by variable names -- so it works even when Antigravity re-minifies on update. + +**Step 1: Find the onChange handler** + +Pattern: `=(()=>{(),===.EAGER&&(!0)},[...])` + +This matches the handler structurally: +- An assignment to a variable +- A `useCallback` call +- Arrow function with one argument +- Two expressions: set state + check EAGER and confirm + +**Step 2: Extract variable names from context** + +From the surrounding 3000 characters, extract: +- `policyVar`: `=?.terminalAutoExecutionPolicy??.OFF` +- `secureVar`: `=?.secureModeEnabled??!1` +- `useEffectFn`: the most frequently used short-named function matching the `fn(()=>{...})` pattern (frequency analysis) + +**Step 3: Generate and inject the patch** + +```javascript +/*BA:autorun*/(()=>{===.EAGER&&!&&(!0)},[]) +``` + +The patch is injected immediately after the `onChange` handler's closing bracket. + +### Example Output + +``` + Antigravity "Always Proceed" Auto-Run Fix + + C:\Users\user\AppData\Local\Programs\Antigravity + Version: 1.107.0 (IDE 1.19.5) + + [workbench] Found onChange at offset 12362782 + callback=Mt, enum=Dhe, confirm=b + policyVar=u + secureVar=d + useEffect=mn (confidence: 30 hits) + [workbench] Patched (+43 bytes) + [jetskiAgent] Found onChange at offset 8388797 + callback=ve, enum=rx, confirm=F + policyVar=d + secureVar=f + useEffect=At (confidence: 55 hits) + [jetskiAgent] Patched (+42 bytes) + +Done! Restart Antigravity. +``` + +### Safety + +- Original files are saved as `.ba-backup` before patching +- The patch marker `/*BA:autorun*/` prevents double-patching +- Only **adds** code, never removes existing logic +- `--revert` restores the original file from backup +- Async I/O in the extension prevents blocking the Extension Host + +### Why two files? + +The `run_command` step renderer exists in **two** bundles: +1. `workbench.desktop.main.js` -- the main workbench bundle (~15MB) +2. `jetskiAgent.js` -- the Cascade chat panel webview (~10MB) + +Both contain the same bug with slightly different minified variable names. The structural matcher handles both transparently. diff --git a/better-antigravity-main/LEGAL.md b/better-antigravity-main/LEGAL.md new file mode 100644 index 0000000..ea07f67 --- /dev/null +++ b/better-antigravity-main/LEGAL.md @@ -0,0 +1,59 @@ +# Legal Notice + +## Disclaimer + +This project is an unofficial, community-maintained collection of patches for +[Antigravity IDE](https://antigravity.dev). It is **not affiliated with, +endorsed by, or sponsored by Google LLC or any of its subsidiaries.** + +## Nature of the Project + +Better Antigravity provides **bugfix patches** that restore documented, expected +functionality in Antigravity IDE. Specifically: + +- The "Always Proceed" terminal execution policy is documented to auto-execute + commands, but does not function as described. Our patch restores this behavior. +- All patches are non-destructive: they create automatic backups and can be + fully reverted at any time. +- No data is collected, transmitted, or shared with any party. + +## Compliance + +- This project **does not access** Google's backend servers, APIs, or + authentication systems. +- This project **does not extract** AI models, training data, or proprietary + algorithms. +- This project **does not bypass** security features, licensing, or + usage restrictions. +- All modifications are local to the user's machine and affect only the + client-side UI behavior. + +## Interoperability + +Where applicable, this project relies on the right to achieve interoperability +as provided by: + +- **EU Software Directive** (Directive 2009/24/EC), Article 6 +- **UK Copyright, Designs and Patents Act 1988**, Section 50B +- Similar provisions in other jurisdictions + +## User Responsibility + +Users are responsible for ensuring their use of this software complies with +applicable terms of service and local laws. By using this software, you +acknowledge that: + +1. You are applying modifications to software on your own machine at your + own risk. +2. Backups of original files are created automatically and can be restored. +3. This project may stop working after Antigravity updates — in that case, + revert and wait for an updated patch. + +## Takedown + +If Google or the Antigravity team requests removal of this project, we will +comply promptly. Contact: [open a GitHub issue](https://github.com/Kanezal/better-antigravity/issues). + +## License + +This project is released under the [GNU Affero General Public License v3.0](LICENSE). diff --git a/better-antigravity-main/LICENSE b/better-antigravity-main/LICENSE new file mode 100644 index 0000000..4e21dfc --- /dev/null +++ b/better-antigravity-main/LICENSE @@ -0,0 +1,644 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they receive +widespread use, become available for other developers to incorporate. +Many developers of free software are heartened and encouraged by the +resulting cooperation. However, in the case of software used on network +servers, this result may fail to come about. The GNU General Public +License permits making a modified version and letting the public access +it on a server without ever releasing its source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding Source + of the work are being offered to the general public at no charge under + subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied by +the Installation Information. But this requirement does not apply if +neither you nor any third party retains the ability to install modified +object code on the User Product (for example, the work has been +installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in source +code form), and must require no special password or key for unpacking, +reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE +OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR +DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR +A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH +HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + Better Antigravity + Copyright (C) 2026 Kanezal + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . diff --git a/better-antigravity-main/README.md b/better-antigravity-main/README.md new file mode 100644 index 0000000..7f6b56c --- /dev/null +++ b/better-antigravity-main/README.md @@ -0,0 +1,209 @@ +
+ +# Better Antigravity + +**Community-driven fixes and improvements for [Antigravity IDE](https://antigravity.dev)** + +[![Open VSX](https://img.shields.io/open-vsx/v/kanezal/better-antigravity)](https://open-vsx.org/extension/kanezal/better-antigravity) +[![npm](https://img.shields.io/npm/v/better-antigravity)](https://www.npmjs.com/package/better-antigravity) +[![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](LICENSE) +[![Antigravity](https://img.shields.io/badge/Antigravity-v1.107.0+-blue.svg)](https://antigravity.dev) +[![Sponsor](https://img.shields.io/badge/Sponsor-Support%20this%20project-ff69b4?logo=githubsponsors&logoColor=white)](https://github.com/Kanezal/better-antigravity#support) + +*Antigravity is great. We just make it a little better.* + +
+ +--- + +## What is this? + +Better Antigravity is both a **VS Code extension** and an **npm CLI tool** that fixes known bugs and adds quality-of-life features to Antigravity IDE. + +| Channel | What it does | Install | +|---------|-------------|---------| +| **Extension** | Auto-applies fixes on startup + chat rename + SDK features | [Open VSX](https://open-vsx.org/extension/kanezal/better-antigravity) | +| **CLI** | Quick one-off patching via `npx` (no extension install needed) | `npx better-antigravity auto-run` | + +> [!NOTE] +> The extension includes everything the CLI does, plus extra features powered by the [Antigravity SDK](https://www.npmjs.com/package/antigravity-sdk). If you install the extension, you don't need the CLI. + +--- + +## Install (Extension) + +Search for **"Better Antigravity"** in the Extensions panel, or install from [Open VSX](https://open-vsx.org/extension/kanezal/better-antigravity). + +Manual install: + +```bash +antigravity --install-extension better-antigravity-0.5.0.vsix --force +``` + +On activation the extension will: +1. **Auto-apply the auto-run fix** (silent, no prompt) +2. **Initialize the SDK** for chat rename and future features +3. **Install the integration script** (prompts for reload on first install, auto-reloads on updates) +4. **Suppress integrity warnings** ("corrupt installation" notification silenced automatically) + +--- + +## Install (CLI only) + +If you just want the auto-run fix without installing an extension: + +```bash +npx better-antigravity auto-run # apply fix +npx better-antigravity auto-run --check # check status +npx better-antigravity auto-run --revert # revert to original +``` + +Custom install path (if Antigravity is not in the default location): + +```bash +npx better-antigravity auto-run --path "D:\Antigravity" +``` + +--- + +## Features + +### Auto-Run Fix + +**The problem:** You set **Settings -> Agent -> Terminal Execution -> "Always Proceed"**, but Antigravity **still asks you to click "Run"** on every terminal command. + +**Root cause:** The `run_command` step renderer has an `onChange` handler that auto-confirms when you switch the dropdown, but there's **no `useEffect`** that checks the saved policy at mount time. + +```javascript +// What exists (only fires on dropdown CHANGE): +onChange = useCallback(_ => { + setPolicy(_), _ === EAGER && confirm(true) +}, []) + +// What's MISSING (should fire on mount): +useEffect(() => { + if (policy === EAGER && !secureMode) confirm(true) +}, []) +``` + +**The fix:** Our patcher adds the missing `useEffect`. It uses **structural regex matching** (not hardcoded variable names) so it works across Antigravity versions. + +> For the full root cause analysis, pattern matching explanation, and example output, see **[FIXES.md](FIXES.md)**. + +### Chat Rename (Extension only) + +Rename conversations to custom titles via the [Antigravity SDK](https://www.npmjs.com/package/antigravity-sdk) title proxy. Custom titles override the auto-generated summaries in the sidebar. + +### Integrity Check Suppression (Extension only) + +When the SDK patches workbench.html, Antigravity shows a sticky "Your installation appears to be corrupt" warning with no dismiss button. As of v0.4.0, the extension automatically updates the checksum in `product.json` after patching so IntegrityService sees `isPure = true`. No warnings on next restart. + +Multiple SDK-based extensions are coordinated automatically -- the original checksum is restored only when the last extension uninstalls. + +### Status Command (Extension only) + +`Ctrl+Shift+P` -> **"Better Antigravity: Show Status"** to see: +- SDK initialization state +- Language Server connection +- Integration script status +- Auto-run fix status per file + +--- + +## Commands + +| Command | Description | +|---------|-------------| +| `Better Antigravity: Show Status` | Show extension and fix status | +| `Better Antigravity: Revert Auto-Run Fix` | Restore original files from backup | + +--- + +## Safety + +- **Automatic backups** -- original files saved as `.ba-backup` before patching +- **One-command revert** -- CLI `--revert` or extension command +- **Non-destructive** -- patches only add code, never remove existing logic +- **Version-resilient** -- structural regex matching, not hardcoded variable names +- **Async I/O** -- file operations don't block the extension host + +--- + +## Compatibility + +| Antigravity Version | Status | +|---------------------|--------| +| 1.107.0 | Tested | +| Other versions | Should work (dynamic pattern matching) | + +--- + +## Project Structure + +``` +better-antigravity/ +├── src/ +│ ├── extension.ts # Extension entry point (thin orchestrator) +│ ├── auto-run.ts # Auto-run fix logic (async, no vscode dependency) +│ └── commands.ts # VS Code command handlers +├── fixes/ +│ └── auto-run-fix/ +│ └── patch.js # Standalone CLI patcher +├── cli.js # npx entry point +├── build.mjs # esbuild config +├── publish-ovsx.mjs # Open VSX publish script +└── package.json # Dual: npm package + VS Code extension +``` + +--- + +## Development + +```bash +npm install +npm run build # Compile extension +npm run watch # Watch mode +npm run package # Build VSIX -> out/ +npm run publish:ovsx # Publish to Open VSX (reads .env) +``` + +The extension depends on [antigravity-sdk](https://www.npmjs.com/package/antigravity-sdk) from the monorepo sibling directory. The build script aliases it automatically. + +--- + +## Contributing + +Found another Antigravity bug? Have a fix? PRs are welcome. + +### Adding a new fix: + +1. Create a folder under `fixes/` with a descriptive name +2. Include a `patch.js` that supports `--check` and `--revert` flags +3. Use structural pattern matching, not hardcoded variable names +4. Update this README's feature table + +--- + +## Disclaimer + +> [!WARNING] +> This project is not affiliated with Google or the Antigravity team. These are community patches and improvements. If Antigravity updates and the patches break, simply revert and re-apply (or wait for an updated patch). + +**Always report bugs officially** at [antigravity.google/support](https://antigravity.google/support) -- community patches are temporary solutions, not replacements for official fixes. + +--- + +## ❤️ Support + +If you find this project useful and want to support its development, you can send **USDT** to: + +| Network | Address | +|---------|---------| +| **TON** | `UQCjVh3C3mZc44GjT2IDsS4pmeOoUgRNxWMcb85NS5Bz_v1d` | +| **TRON (TRC20)** | `TH3JKGjNrSDCsjkkSuneaSMZoJYF7CNTXD` | + +--- + +## License + +[AGPL-3.0-or-later](LICENSE) diff --git a/better-antigravity-main/build.mjs b/better-antigravity-main/build.mjs new file mode 100644 index 0000000..c8da125 --- /dev/null +++ b/better-antigravity-main/build.mjs @@ -0,0 +1,57 @@ +import * as esbuild from 'esbuild'; +import * as fs from 'fs'; +import * as path from 'path'; + +const isWatch = process.argv.includes('--watch'); + +/** @type {esbuild.BuildOptions} */ +const config = { + entryPoints: ['src/extension.ts'], + bundle: true, + outfile: 'dist/extension.js', + external: ['vscode'], + format: 'cjs', + platform: 'node', + target: 'es2020', + sourcemap: true, + minify: false, + // Resolve antigravity-sdk from monorepo sibling + alias: { + 'antigravity-sdk': path.resolve('..', 'antigravity-sdk', 'dist', 'index.js'), + }, +}; + +// Ensure dist/ exists +if (!fs.existsSync('dist')) fs.mkdirSync('dist'); + +// Copy sql-wasm.wasm AND sql-wasm.js to dist/ (required by antigravity-sdk's StateBridge) +const sqlFiles = ['sql-wasm.wasm', 'sql-wasm.js']; +for (const sqlFile of sqlFiles) { + const searchPaths = [ + path.join('node_modules', 'sql.js', 'dist', sqlFile), + path.join('..', 'antigravity-sdk', 'node_modules', 'sql.js', 'dist', sqlFile), + ]; + + let copied = false; + for (const src of searchPaths) { + if (fs.existsSync(src)) { + fs.copyFileSync(src, path.join('dist', sqlFile)); + console.log(`Copied ${sqlFile} from ${src}`); + copied = true; + break; + } + } + if (!copied) { + console.error(`ERROR: ${sqlFile} not found. Run "npm install" first.`); + process.exit(1); + } +} + +if (isWatch) { + const ctx = await esbuild.context(config); + await ctx.watch(); + console.log('Watching...'); +} else { + await esbuild.build(config); + console.log('Build complete'); +} diff --git a/better-antigravity-main/cli.js b/better-antigravity-main/cli.js new file mode 100644 index 0000000..b98868a --- /dev/null +++ b/better-antigravity-main/cli.js @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +/** + * better-antigravity CLI + * Usage: + * npx better-antigravity — list available fixes + * npx better-antigravity auto-run — apply auto-run fix + * npx better-antigravity auto-run --check — check status + * npx better-antigravity auto-run --revert — revert fix + */ + +const path = require('path'); +const fs = require('fs'); + +const fixes = { + 'auto-run': { + script: path.join(__dirname, 'fixes', 'auto-run-fix', 'patch.js'), + description: '"Always Proceed" terminal policy doesn\'t auto-execute commands' + } +}; + +const args = process.argv.slice(2); +const fixName = args[0]; +const flags = args.slice(1); + +// Header +console.log(''); +console.log(' better-antigravity — community fixes for Antigravity IDE'); +console.log(' https://github.com/Kanezal/better-antigravity'); +console.log(''); + +if (!fixName || fixName === '--help' || fixName === '-h') { + console.log(' Available fixes:'); + console.log(''); + for (const [name, fix] of Object.entries(fixes)) { + console.log(` ${name.padEnd(15)} ${fix.description}`); + } + console.log(''); + console.log(' Usage:'); + console.log(' npx better-antigravity Apply fix'); + console.log(' npx better-antigravity --check Check status'); + console.log(' npx better-antigravity --revert Revert fix'); + console.log(' npx better-antigravity --path Use custom install path'); + console.log(''); + console.log(' The tool auto-detects Antigravity in: CWD, PATH, Registry, default locations.'); + console.log(' Use --path if auto-detection fails (e.g. custom install on another drive).'); + console.log(''); + process.exit(0); +} + +const fix = fixes[fixName]; +if (!fix) { + console.log(` Unknown fix: "${fixName}"`); + console.log(` Available: ${Object.keys(fixes).join(', ')}`); + process.exit(1); +} + +if (!fs.existsSync(fix.script)) { + console.log(` Fix script not found: ${fix.script}`); + process.exit(1); +} + +// Forward to the fix script with flags +process.argv = [process.argv[0], fix.script, ...flags]; +require(fix.script); diff --git a/better-antigravity-main/fixes/auto-run-fix/patch.js b/better-antigravity-main/fixes/auto-run-fix/patch.js new file mode 100644 index 0000000..548ee6f --- /dev/null +++ b/better-antigravity-main/fixes/auto-run-fix/patch.js @@ -0,0 +1,400 @@ +#!/usr/bin/env node + +/** + * Antigravity "Always Proceed" Auto-Run Fix + * ========================================== + * + * Fixes a bug where the "Always Proceed" terminal execution policy doesn't + * actually auto-execute commands. Uses regex patterns to find code structures + * regardless of minified variable names — works across versions. + * + * Usage: + * node patch.js - Apply patch + * node patch.js --revert - Restore original files + * node patch.js --check - Check patch status + * + * License: MIT + */ + +const fs = require('fs'); +const path = require('path'); +const os = require('os'); + +// ─── Installation Detection ───────────────────────────────────────────────── + +/** + * Validates that a candidate directory is a real Antigravity installation + * by checking for the workbench main JS file. + */ +function isAntigravityDir(dir) { + if (!dir) return false; + try { + const workbench = path.join(dir, 'resources', 'app', 'out', 'vs', 'workbench', 'workbench.desktop.main.js'); + return fs.existsSync(workbench); + } catch { return false; } +} + +/** + * Checks if a directory looks like the Antigravity installation root + * (contains Antigravity.exe or antigravity binary). + */ +function looksLikeAntigravityRoot(dir) { + if (!dir) return false; + try { + const exe = process.platform === 'win32' ? 'Antigravity.exe' : 'antigravity'; + return fs.existsSync(path.join(dir, exe)); + } catch { return false; } +} + +/** + * Tries to find Antigravity installation path from Windows Registry. + * InnoSetup writes uninstall info to HKCU or HKLM. + */ +function findFromRegistry() { + if (process.platform !== 'win32') return null; + try { + const { execSync } = require('child_process'); + // InnoSetup typically writes to this key; try HKCU first, then HKLM + const regPaths = [ + 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Antigravity_is1', + 'HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Antigravity_is1', + 'HKLM\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Antigravity_is1', + ]; + for (const regPath of regPaths) { + try { + const output = execSync( + `reg query "${regPath}" /v InstallLocation`, + { encoding: 'utf8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] } + ); + const match = output.match(/InstallLocation\s+REG_SZ\s+(.+)/i); + if (match) { + const dir = match[1].trim().replace(/\\$/, ''); + if (isAntigravityDir(dir)) return dir; + } + } catch { /* key not found, try next */ } + } + } catch { /* child_process failed */ } + return null; +} + +/** + * Tries to find Antigravity by looking at PATH entries for the executable. + */ +function findFromPath() { + try { + const pathDirs = (process.env.PATH || '').split(path.delimiter); + const exe = process.platform === 'win32' ? 'Antigravity.exe' : 'antigravity'; + for (const dir of pathDirs) { + if (!dir) continue; + if (fs.existsSync(path.join(dir, exe))) { + // The exe could be in the root or in a bin/ subdirectory + if (isAntigravityDir(dir)) return dir; + const parent = path.dirname(dir); + if (isAntigravityDir(parent)) return parent; + } + } + } catch { /* PATH parsing failed */ } + return null; +} + +function findAntigravityPath() { + // 1. Check CWD and its ancestors (user may run from install dir or a subdir) + let dir = process.cwd(); + const root = path.parse(dir).root; + while (dir && dir !== root) { + if (looksLikeAntigravityRoot(dir) && isAntigravityDir(dir)) return dir; + dir = path.dirname(dir); + } + + // 2. Check PATH + const fromPath = findFromPath(); + if (fromPath) return fromPath; + + // 3. Check Windows Registry (InnoSetup uninstall keys) + const fromReg = findFromRegistry(); + if (fromReg) return fromReg; + + // 4. Hardcoded well-known locations + const candidates = []; + if (process.platform === 'win32') { + candidates.push( + path.join(process.env.LOCALAPPDATA || '', 'Programs', 'Antigravity'), + path.join(process.env.PROGRAMFILES || '', 'Antigravity'), + ); + } else if (process.platform === 'darwin') { + candidates.push( + '/Applications/Antigravity.app/Contents/Resources', + path.join(os.homedir(), 'Applications', 'Antigravity.app', 'Contents', 'Resources') + ); + } else { + candidates.push('/usr/share/antigravity', '/opt/antigravity', + path.join(os.homedir(), '.local', 'share', 'antigravity')); + } + for (const c of candidates) { + if (isAntigravityDir(c)) return c; + } + + return null; +} + +// ─── Smart Pattern Matching ───────────────────────────────────────────────── + +/** + * Finds the onChange handler for terminalAutoExecutionPolicy and extracts + * variable names from context, regardless of minification. + * + * Pattern we're looking for (structure, not exact names): + * =(()=>{ + * ?.setTerminalAutoExecutionPolicy?.(), + * ===.EAGER&&(!0) + * },[...]) + * + * From the surrounding context we also extract: + * = ?.terminalAutoExecutionPolicy ?? .OFF + * = ?.secureModeEnabled ?? !1 + */ +function analyzeFile(content, label) { + // 1. Find the onChange handler: contains setTerminalAutoExecutionPolicy AND .EAGER + // Pattern: VARNAME=CALLBACK(ARG=>{...setTerminalAutoExecutionPolicy...,ARG===ENUM.EAGER&&CONFIRM(!0)},[...]) + const onChangeRe = /(\w+)=(\w+)\((\w+)=>\{\w+\?\.setTerminalAutoExecutionPolicy\?\.\(\3\),\3===(\w+)\.EAGER&&(\w+)\(!0\)\},\[[\w,]*\]\)/; + const onChangeMatch = content.match(onChangeRe); + + if (!onChangeMatch) { + console.log(` ❌ [${label}] Could not find onChange handler pattern`); + return null; + } + + const [fullMatch, assignVar, callbackAlias, argName, enumAlias, confirmFn] = onChangeMatch; + const matchIndex = content.indexOf(fullMatch); + + console.log(` 📋 [${label}] Found onChange at offset ${matchIndex}`); + console.log(` callback=${callbackAlias}, enum=${enumAlias}, confirm=${confirmFn}`); + + // 2. Find policy variable: VARNAME=HANDLER?.terminalAutoExecutionPolicy??ENUM.OFF + const policyRe = new RegExp(`(\\w+)=\\w+\\?\\.terminalAutoExecutionPolicy\\?\\?${enumAlias}\\.OFF`); + const policyMatch = content.substring(Math.max(0, matchIndex - 2000), matchIndex).match(policyRe); + + if (!policyMatch) { + console.log(` ❌ [${label}] Could not find policy variable`); + return null; + } + const policyVar = policyMatch[1]; + console.log(` policyVar=${policyVar}`); + + // 3. Find secureMode variable: VARNAME=HANDLER?.secureModeEnabled??!1 + const secureRe = /(\w+)=\w+\?\.secureModeEnabled\?\?!1/; + const secureMatch = content.substring(Math.max(0, matchIndex - 2000), matchIndex).match(secureRe); + + if (!secureMatch) { + console.log(` ❌ [${label}] Could not find secureMode variable`); + return null; + } + const secureVar = secureMatch[1]; + console.log(` secureVar=${secureVar}`); + + // 4. Find useEffect alias: look for ALIAS(()=>{...},[...]) calls nearby (not useCallback/useMemo) + const nearbyCode = content.substring(Math.max(0, matchIndex - 5000), matchIndex + 5000); + const effectCandidates = {}; + const effectRe = /\b(\w{2,3})\(\(\)=>\{[^}]{3,80}\},\[/g; + let m; + while ((m = effectRe.exec(nearbyCode)) !== null) { + const alias = m[1]; + if (alias !== callbackAlias && alias !== 'var' && alias !== 'new') { + effectCandidates[alias] = (effectCandidates[alias] || 0) + 1; + } + } + + // Also check broader file for common useEffect patterns (with cleanup return) + const cleanupRe = /\b(\w{2,3})\(\(\)=>\{[^}]*return\s*\(\)=>/g; + while ((m = cleanupRe.exec(content)) !== null) { + const alias = m[1]; + if (alias !== callbackAlias) { + effectCandidates[alias] = (effectCandidates[alias] || 0) + 5; // higher weight + } + } + + // Remove known non-useEffect aliases (useMemo patterns) + // useMemo: alias(()=>EXPRESSION,[deps]) — returns a value, often assigned + // useEffect: alias(()=>{STATEMENTS},[deps]) — no return value + + // Pick the most common candidate + let useEffectAlias = null; + let maxCount = 0; + for (const [alias, count] of Object.entries(effectCandidates)) { + if (count > maxCount) { + maxCount = count; + useEffectAlias = alias; + } + } + + if (!useEffectAlias) { + console.log(` ❌ [${label}] Could not determine useEffect alias`); + return null; + } + console.log(` useEffect=${useEffectAlias} (confidence: ${maxCount} hits)`); + + // 5. Build patch + const patchCode = `_aep=${useEffectAlias}(()=>{${policyVar}===${enumAlias}.EAGER&&!${secureVar}&&${confirmFn}(!0)},[]),`; + + return { + target: fullMatch, + replacement: patchCode + fullMatch, + patchMarker: `_aep=${useEffectAlias}(()=>{${policyVar}===${enumAlias}.EAGER`, + label + }; +} + +// ─── File Operations ──────────────────────────────────────────────────────── + +function patchFile(filePath, label) { + if (!fs.existsSync(filePath)) { + console.log(` ❌ [${label}] File not found: ${filePath}`); + return false; + } + + const content = fs.readFileSync(filePath, 'utf8'); + + // Check if already patched + if (content.includes('_aep=')) { + const existingPatch = content.match(/_aep=\w+\(\(\)=>\{[^}]+EAGER[^}]+\},\[\]\)/); + if (existingPatch) { + console.log(` ⏭️ [${label}] Already patched`); + return true; + } + } + + const analysis = analyzeFile(content, label); + if (!analysis) return false; + + // Verify target is unique + const count = content.split(analysis.target).length - 1; + if (count !== 1) { + console.log(` ❌ [${label}] Target found ${count} times (expected 1)`); + return false; + } + + // Backup + if (!fs.existsSync(filePath + '.bak')) { + fs.copyFileSync(filePath, filePath + '.bak'); + console.log(` 📦 [${label}] Backup created`); + } + + // Apply + const patched = content.replace(analysis.target, analysis.replacement); + fs.writeFileSync(filePath, patched, 'utf8'); + + const diff = fs.statSync(filePath).size - fs.statSync(filePath + '.bak').size; + console.log(` ✅ [${label}] Patched (+${diff} bytes)`); + return true; +} + +function revertFile(filePath, label) { + const bak = filePath + '.bak'; + if (!fs.existsSync(bak)) { + console.log(` ⏭️ [${label}] No backup, skipping`); + return; + } + fs.copyFileSync(bak, filePath); + console.log(` ✅ [${label}] Restored`); +} + +function checkFile(filePath, label) { + if (!fs.existsSync(filePath)) { + console.log(` ❌ [${label}] Not found`); + return false; + } + const content = fs.readFileSync(filePath, 'utf8'); + const patched = content.includes('_aep=') && /_aep=\w+\(\(\)=>\{[^}]+EAGER/.test(content); + const hasBak = fs.existsSync(filePath + '.bak'); + + if (patched) { + console.log(` ✅ [${label}] PATCHED` + (hasBak ? ' (backup exists)' : '')); + } else { + const analysis = analyzeFile(content, label); + if (analysis) { + console.log(` ⬜ [${label}] NOT PATCHED (patchable)`); + } else { + console.log(` ⚠️ [${label}] NOT PATCHED (may be incompatible)`); + } + } + return patched; +} + +// ─── Version Info ─────────────────────────────────────────────────────────── + +function getVersion(basePath) { + try { + const pkg = JSON.parse(fs.readFileSync(path.join(basePath, 'resources', 'app', 'package.json'), 'utf8')); + const product = JSON.parse(fs.readFileSync(path.join(basePath, 'resources', 'app', 'product.json'), 'utf8')); + return `${pkg.version} (IDE ${product.ideVersion})`; + } catch { return 'unknown'; } +} + +// ─── Main ─────────────────────────────────────────────────────────────────── + +function main() { + const args = process.argv.slice(2); + const action = args.includes('--revert') ? 'revert' : args.includes('--check') ? 'check' : 'apply'; + + // Parse --path flag + let explicitPath = null; + const pathIdx = args.indexOf('--path'); + if (pathIdx !== -1 && args[pathIdx + 1]) { + explicitPath = path.resolve(args[pathIdx + 1]); + } + + console.log(''); + console.log('╔══════════════════════════════════════════════════╗'); + console.log('║ Antigravity "Always Proceed" Auto-Run Fix ║'); + console.log('╚══════════════════════════════════════════════════╝'); + + let basePath; + if (explicitPath) { + if (!isAntigravityDir(explicitPath)) { + console.log(`\n\u274C --path "${explicitPath}" does not look like an Antigravity installation.`); + console.log(' Expected to find: resources/app/out/vs/workbench/workbench.desktop.main.js'); + process.exit(1); + } + basePath = explicitPath; + } else { + basePath = findAntigravityPath(); + } + + if (!basePath) { + console.log('\n\u274C Antigravity installation not found!'); + console.log(''); + console.log(' Try one of:'); + console.log(' 1. Run from the Antigravity install directory:'); + console.log(' cd "C:\\Path\\To\\Antigravity" && npx better-antigravity auto-run'); + console.log(' 2. Specify the path explicitly:'); + console.log(' npx better-antigravity auto-run --path "D:\\Antigravity"'); + process.exit(1); + } + + console.log(`\n📍 ${basePath}`); + console.log(`📦 Version: ${getVersion(basePath)}`); + console.log(''); + + const files = [ + { path: path.join(basePath, 'resources', 'app', 'out', 'vs', 'workbench', 'workbench.desktop.main.js'), label: 'workbench' }, + { path: path.join(basePath, 'resources', 'app', 'out', 'jetskiAgent', 'main.js'), label: 'jetskiAgent' }, + ]; + + switch (action) { + case 'check': + files.forEach(f => checkFile(f.path, f.label)); + break; + case 'revert': + files.forEach(f => revertFile(f.path, f.label)); + console.log('\n✨ Restored! Restart Antigravity.'); + break; + case 'apply': + const ok = files.every(f => patchFile(f.path, f.label)); + console.log(ok + ? '\n✨ Done! Restart Antigravity.\n💡 Run with --revert to undo.\n⚠️ Re-run after Antigravity updates.' + : '\n⚠️ Some patches failed.'); + break; + } +} + +main(); diff --git a/better-antigravity-main/package-lock.json b/better-antigravity-main/package-lock.json new file mode 100644 index 0000000..722e155 --- /dev/null +++ b/better-antigravity-main/package-lock.json @@ -0,0 +1,503 @@ +{ + "name": "better-antigravity", + "version": "0.2.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "better-antigravity", + "version": "0.2.0", + "license": "AGPL-3.0-or-later", + "dependencies": { + "antigravity-sdk": "^1.3.0", + "sql.js": "^1.14.0" + }, + "bin": { + "better-antigravity": "cli.js" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/vscode": "^1.85.0", + "esbuild": "^0.20.0" + }, + "engines": { + "node": ">=16.0.0", + "vscode": "^1.85.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/node": { + "version": "20.19.35", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.35.tgz", + "integrity": "sha512-Uarfe6J91b9HAUXxjvSOdiO2UPOKLm07Q1oh0JHxoZ1y8HoqxDAu3gVrsrOHeiio0kSsoVBt4wFrKOm0dKxVPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/vscode": { + "version": "1.109.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.109.0.tgz", + "integrity": "sha512-0Pf95rnwEIwDbmXGC08r0B4TQhAbsHQ5UyTIgVgoieDe4cOnf92usuR5dEczb6bTKEp7ziZH4TV1TRGPPCExtw==", + "license": "MIT" + }, + "node_modules/antigravity-sdk": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/antigravity-sdk/-/antigravity-sdk-1.3.0.tgz", + "integrity": "sha512-AonqXNmtnkYYib/pSCcDlxnVxLsNIafIbBQxwTV0zHt6RZBjG8ejknkJAhd8hRyilMefMTOE28oPzTblby2K2A==", + "license": "AGPL-3.0-or-later", + "dependencies": { + "sql.js": "^1.14.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@types/vscode": "^1.85.0" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/sql.js": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.0.tgz", + "integrity": "sha512-NXYh+kFqLiYRCNAaHD0PcbjFgXyjuolEKLMk5vRt2DgPENtF1kkNzzMlg42dUk5wIsH8MhUzsRhaUxIisoSlZQ==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/better-antigravity-main/package.json b/better-antigravity-main/package.json new file mode 100644 index 0000000..9cd8b43 --- /dev/null +++ b/better-antigravity-main/package.json @@ -0,0 +1,94 @@ +{ + "name": "better-antigravity", + "displayName": "Better Antigravity", + "description": "Community-driven fixes and improvements for Antigravity IDE — auto-run fix, chat rename, and more", + "version": "0.6.0", + "publisher": "kanezal", + "icon": "static/BA-background.png", + "galleryBanner": { + "color": "#1a1a1a", + "theme": "dark" + }, + "markdown": "github", + "badges": [ + { + "url": "https://img.shields.io/npm/v/better-antigravity", + "href": "https://www.npmjs.com/package/better-antigravity", + "description": "npm version" + }, + { + "url": "https://img.shields.io/badge/License-AGPL--3.0-blue.svg", + "href": "https://github.com/Kanezal/better-antigravity/blob/main/LICENSE", + "description": "License: AGPL-3.0" + }, + { + "url": "https://img.shields.io/badge/Antigravity-v1.107.0+-blue.svg", + "href": "https://antigravity.dev", + "description": "Antigravity compatibility" + } + ], + "engines": { + "vscode": "^1.85.0", + "node": ">=16.0.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onStartupFinished" + ], + "main": "./dist/extension.js", + "bin": { + "better-antigravity": "cli.js" + }, + "contributes": { + "commands": [ + { + "command": "better-antigravity.status", + "title": "Better Antigravity: Show Status" + }, + { + "command": "better-antigravity.revertAutoRun", + "title": "Better Antigravity: Revert Auto-Run Fix" + } + ] + }, + "scripts": { + "build": "node build.mjs", + "watch": "node build.mjs --watch", + "prepackage": "node -e \"require('fs').mkdirSync('out',{recursive:true})\"", + "package": "npm run prepackage && npx @vscode/vsce package --no-dependencies --out out/better-antigravity.vsix", + "publish:ovsx": "node publish-ovsx.mjs", + "fix:auto-run": "node fixes/auto-run-fix/patch.js", + "fix:auto-run:check": "node fixes/auto-run-fix/patch.js --check", + "fix:auto-run:revert": "node fixes/auto-run-fix/patch.js --revert" + }, + "repository": { + "type": "git", + "url": "https://github.com/Kanezal/better-antigravity" + }, + "homepage": "https://github.com/Kanezal/better-antigravity#readme", + "bugs": { + "url": "https://github.com/Kanezal/better-antigravity/issues" + }, + "author": "Kanezal", + "license": "AGPL-3.0-or-later", + "keywords": [ + "antigravity", + "antigravity-ide", + "google-antigravity", + "fix", + "auto-run", + "rename-chat", + "community" + ], + "devDependencies": { + "@types/node": "^20.0.0", + "@types/vscode": "^1.85.0", + "esbuild": "^0.20.0" + }, + "dependencies": { + "antigravity-sdk": "^1.5.0", + "sql.js": "^1.14.0" + } +} \ No newline at end of file diff --git a/better-antigravity-main/publish-ovsx.mjs b/better-antigravity-main/publish-ovsx.mjs new file mode 100644 index 0000000..177dbbf --- /dev/null +++ b/better-antigravity-main/publish-ovsx.mjs @@ -0,0 +1,44 @@ +#!/usr/bin/env node + +/** + * Publish to Open VSX using token from .env + * + * Usage: + * node publish-ovsx.mjs — publish VSIX + * node publish-ovsx.mjs create-namespace — create publisher namespace (first time only) + */ + +import { readFileSync } from 'fs'; +import { execSync } from 'child_process'; +import { createRequire } from 'module'; + +const require = createRequire(import.meta.url); +const pkg = require('./package.json'); +const cmd = process.argv[2] || 'publish'; + +// Read token from .env +let pat; +try { + const env = readFileSync('.env', 'utf8'); + const match = env.match(/OVSX_PAT=(.+)/); + if (!match) throw new Error('OVSX_PAT not found in .env'); + pat = match[1].trim(); +} catch (err) { + console.error('ERROR: Could not read .env file. Create .env with OVSX_PAT='); + process.exit(1); +} + +try { + if (cmd === 'create-namespace') { + console.log(`Creating namespace "${pkg.publisher}" on Open VSX...`); + execSync(`npx ovsx create-namespace ${pkg.publisher} --pat ${pat}`, { stdio: 'inherit' }); + console.log('Namespace created!'); + } else { + const vsixFile = `out/better-antigravity.vsix`; + console.log(`Publishing ${vsixFile} to Open VSX...`); + execSync(`npx ovsx publish ${vsixFile} --pat ${pat}`, { stdio: 'inherit' }); + console.log('Done!'); + } +} catch { + process.exit(1); +} diff --git a/better-antigravity-main/src/auto-run.ts b/better-antigravity-main/src/auto-run.ts new file mode 100644 index 0000000..801cc38 --- /dev/null +++ b/better-antigravity-main/src/auto-run.ts @@ -0,0 +1,235 @@ +/** + * Auto-Run Fix — Patches the "Always Proceed" terminal policy to actually auto-execute. + * + * Uses structural regex matching to find the onChange handler in minified code + * and injects a missing useEffect that auto-confirms commands when policy is EAGER. + * + * Works across AG versions because it matches code STRUCTURE, not variable NAMES. + * + * @module auto-run + */ + +import * as path from 'path'; +import * as fs from 'fs'; +import * as fsp from 'fs/promises'; + +/** Marker comment to identify our patches */ +const PATCH_MARKER = '/*BA:autorun*/'; + +/** + * Resolve the Antigravity workbench directory. + */ +export function getWorkbenchDir(): string | null { + const appData = process.env.LOCALAPPDATA || ''; + const dir = path.join( + appData, + 'Programs', 'Antigravity', 'resources', 'app', 'out', + 'vs', 'code', 'electron-browser', 'workbench', + ); + return fs.existsSync(dir) ? dir : null; +} + +/** + * Target files that need the auto-run patch. + */ +export function getTargetFiles(workbenchDir: string): Array<{ path: string; label: string }> { + return [ + { path: path.join(workbenchDir, 'workbench.desktop.main.js'), label: 'workbench' }, + { path: path.join(workbenchDir, 'jetskiAgent.js'), label: 'jetskiAgent' }, + ].filter(f => fs.existsSync(f.path)); +} + +/** + * Check if a file already has the auto-run patch applied. + */ +export async function isPatched(filePath: string): Promise { + try { + // Read only first 50 bytes of the marker area via a small buffer scan + // The marker is injected mid-file, so we must read the full file. + // Use async to avoid blocking extension host. + const content = await fsp.readFile(filePath, 'utf8'); + return content.includes(PATCH_MARKER); + } catch { + return false; + } +} + +/** + * Analyze a file to find the onChange handler and extract variable names. + * + * Returns null if pattern not found (file may already be fixed by AG update). + */ +function analyzeFile(content: string): AnalysisResult | null { + // Find onChange handler for terminalAutoExecutionPolicy + // Pattern: =(()=>{(),===.EAGER&&(true)},[...]) + const onChangeRegex = /(\w+)=(\w+)\((\(\w+\))=>\{(\w+)\(\w+\),\w+===(\w+)\.EAGER&&(\w+)\(!0\)\},\[/g; + const match = onChangeRegex.exec(content); + + if (!match) return null; + + const [fullMatch, , , , , enumName, confirmFn] = match; + const insertPos = match.index + fullMatch.length; + + // Extract context variables from surrounding code + const contextStart = Math.max(0, match.index - 3000); + const contextEnd = Math.min(content.length, match.index + 3000); + const context = content.substring(contextStart, contextEnd); + + // policyVar: =?.terminalAutoExecutionPolicy??.OFF + const policyMatch = /(\w+)=\w+\?\.terminalAutoExecutionPolicy\?\?(\w+)\.OFF/.exec(context); + // secureVar: =?.secureModeEnabled??!1 + const secureMatch = /(\w+)=\w+\?\.secureModeEnabled\?\?!1/.exec(context); + + if (!policyMatch || !secureMatch) return null; + + const policyVar = policyMatch[1]; + const secureVar = secureMatch[1]; + + // Find useEffect — most frequently used short-named function in the scope + const useEffectFn = findUseEffect(context, [confirmFn]); + + if (!useEffectFn) return null; + + // Find insertion point: after the useCallback closing + const afterOnChange = content.indexOf('])', insertPos); + if (afterOnChange === -1) return null; + + const insertAt = content.indexOf(';', afterOnChange); + if (insertAt === -1) return null; + + return { + enumName, + confirmFn, + policyVar, + secureVar, + useEffectFn, + insertAt: insertAt + 1, + }; +} + +/** + * Find the useEffect function name by frequency analysis. + */ +function findUseEffect(context: string, exclude: string[]): string | null { + const candidates: Record = {}; + const regex = /(\w{1,3})\(\(\)=>\{/g; + let m; + + while ((m = regex.exec(context)) !== null) { + const fn = m[1]; + if (fn.length <= 3 && !exclude.includes(fn)) { + candidates[fn] = (candidates[fn] || 0) + 1; + } + } + + let best = ''; + let maxCount = 0; + for (const [fn, count] of Object.entries(candidates)) { + if (count > maxCount) { + best = fn; + maxCount = count; + } + } + + return best || null; +} + +interface AnalysisResult { + enumName: string; + confirmFn: string; + policyVar: string; + secureVar: string; + useEffectFn: string; + insertAt: number; +} + +/** + * Apply the auto-run patch to a single file. + * + * @returns Patch status message + */ +export async function patchFile(filePath: string, label: string): Promise { + try { + let content = await fsp.readFile(filePath, 'utf8'); + + if (content.includes(PATCH_MARKER)) { + return { success: true, label, status: 'already-patched' }; + } + + const analysis = analyzeFile(content); + if (!analysis) { + return { success: false, label, status: 'pattern-not-found' }; + } + + const { enumName, confirmFn, policyVar, secureVar, useEffectFn, insertAt } = analysis; + + // Build the patch + const patch = `${PATCH_MARKER}${useEffectFn}(()=>{${policyVar}===${enumName}.EAGER&&!${secureVar}&&${confirmFn}(!0)},[])`; + + // Create backup (only if one doesn't exist) + const backup = filePath + '.ba-backup'; + try { await fsp.access(backup); } catch { + await fsp.copyFile(filePath, backup); + } + + // Insert + content = content.substring(0, insertAt) + patch + content.substring(insertAt); + await fsp.writeFile(filePath, content, 'utf8'); + + return { success: true, label, status: 'patched', bytesAdded: patch.length }; + } catch (err: any) { + return { success: false, label, status: 'error', error: err.message }; + } +} + +/** + * Revert the auto-run patch on a single file. + */ +export function revertFile(filePath: string, label: string): PatchResult { + const backup = filePath + '.ba-backup'; + if (!fs.existsSync(backup)) { + return { success: false, label, status: 'no-backup' }; + } + + try { + fs.copyFileSync(backup, filePath); + fs.unlinkSync(backup); + return { success: true, label, status: 'reverted' }; + } catch (err: any) { + return { success: false, label, status: 'error', error: err.message }; + } +} + +export interface PatchResult { + success: boolean; + label: string; + status: 'patched' | 'already-patched' | 'pattern-not-found' | 'reverted' | 'no-backup' | 'error'; + bytesAdded?: number; + error?: string; +} + +/** + * Auto-apply the fix to all target files. + * + * @returns Array of results for each file + */ +export async function autoApply(): Promise { + const dir = getWorkbenchDir(); + if (!dir) return []; + + const files = getTargetFiles(dir); + return Promise.all(files.map(f => patchFile(f.path, f.label))); +} + +/** + * Revert all target files from backups. + * + * @returns Number of files reverted + */ +export function revertAll(): PatchResult[] { + const dir = getWorkbenchDir(); + if (!dir) return []; + + const files = getTargetFiles(dir); + return files.map(f => revertFile(f.path, f.label)); +} diff --git a/better-antigravity-main/src/commands.ts b/better-antigravity-main/src/commands.ts new file mode 100644 index 0000000..5be253a --- /dev/null +++ b/better-antigravity-main/src/commands.ts @@ -0,0 +1,81 @@ +/** + * Better Antigravity — VS Code command handlers. + * + * Each exported function is a command handler registered in extension.ts. + * + * @module commands + */ + +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fsp from 'fs/promises'; +import { AntigravitySDK } from 'antigravity-sdk'; +import { getWorkbenchDir, getTargetFiles, isPatched, revertAll } from './auto-run'; + +/** + * Show extension status in the output channel. + */ +export async function status(sdk: AntigravitySDK | null, output: vscode.OutputChannel): Promise { + const lines = [ + '=== Better Antigravity ===', + '', + `SDK: ${sdk?.isInitialized ? `v${sdk.version}` : 'not initialized'}`, + `LS: ${sdk?.ls?.isReady ? `port ${sdk.ls.port}` : 'not ready'}`, + `UI: ${sdk?.integration.isInstalled() ? 'installed' : 'not installed'}`, + `Titles: ${sdk?.integration.titles.count ?? 0} custom`, + ]; + + const dir = getWorkbenchDir(); + if (dir) { + const files = getTargetFiles(dir); + for (const f of files) { + const patched = await isPatched(f.path); + lines.push(`AutoRun: ${f.label} = ${patched ? 'fixed' : 'not fixed'}`); + } + } else { + lines.push('AutoRun: workbench directory not found'); + } + + output.appendLine(lines.join('\n')); + output.show(true); +} + +/** + * Revert the auto-run fix and prompt for reload. + * + * Also clears V8 Code Cache to prevent stale cached patched code + * from being loaded by Electron (which causes grey screen). + */ +export async function revertAutoRun(): Promise { + const dir = getWorkbenchDir(); + if (!dir) { + vscode.window.showErrorMessage('Workbench directory not found.'); + return; + } + + const results = revertAll(); + const reverted = results.filter(r => r.status === 'reverted').length; + + if (reverted > 0) { + // Clear V8 Code Cache — stale cache after revert causes grey screen + const appData = process.env.APPDATA || ''; + const cacheDirs = [ + path.join(appData, 'Antigravity', 'CachedData'), + path.join(appData, 'Antigravity', 'GPUCache'), + path.join(appData, 'Antigravity', 'Code Cache'), + ]; + for (const d of cacheDirs) { + try { await fsp.rm(d, { recursive: true, force: true }); } catch { /* may not exist */ } + } + + const action = await vscode.window.showInformationMessage( + `Auto-run fix reverted (${reverted} file(s)). Caches cleared. Reload to apply.`, + 'Reload Now', + ); + if (action === 'Reload Now') { + vscode.commands.executeCommand('workbench.action.reloadWindow'); + } + } else { + vscode.window.showInformationMessage('No backups found. Nothing to revert.'); + } +} diff --git a/better-antigravity-main/src/extension.ts b/better-antigravity-main/src/extension.ts new file mode 100644 index 0000000..6849749 --- /dev/null +++ b/better-antigravity-main/src/extension.ts @@ -0,0 +1,72 @@ +/** + * Better Antigravity — Extension entry point. + * + * Thin orchestrator: wires up modules, no business logic here. + * + * @module extension + */ + +import * as vscode from 'vscode'; +import { AntigravitySDK } from 'antigravity-sdk'; +import { autoApply } from './auto-run'; +import { status, revertAutoRun } from './commands'; + +let sdk: AntigravitySDK | null = null; +let output: vscode.OutputChannel; + +function log(msg: string): void { + const ts = new Date().toISOString().substring(11, 19); + output?.appendLine(`[${ts}] ${msg}`); +} + +export async function activate(context: vscode.ExtensionContext) { + output = vscode.window.createOutputChannel('Better Antigravity'); + context.subscriptions.push(output); + log('Activating...'); + + // ── Commands ────────────────────────────────────────────────────── + context.subscriptions.push( + vscode.commands.registerCommand('better-antigravity.status', () => status(sdk, output)), + vscode.commands.registerCommand('better-antigravity.revertAutoRun', revertAutoRun), + ); + + // ── Auto-Run Fix (async, non-blocking, no prompt) ───────────────── + autoApply().then(fixResults => { + for (const r of fixResults) { + log(`[auto-run] ${r.label}: ${r.status}${r.bytesAdded ? ` (+${r.bytesAdded}b)` : ''}${r.error ? ` -- ${r.error}` : ''}`); + } + }); + + // ── SDK Init ───────────────────────────────────────────────────── + try { + sdk = new AntigravitySDK(context); + await sdk.initialize(); + log(`SDK v${sdk.version} initialized`); + + // Title proxy for chat rename + sdk.integration.enableTitleProxy(); + + // Seamless install (handles first-time prompt + auto-reload on update) + await sdk.integration.installSeamless( + (cmd) => vscode.commands.executeCommand(cmd), + (msg, ...items) => vscode.window.showInformationMessage(msg, ...items), + ); + + // Heartbeat (keeps renderer script alive) + const hbTimer = setInterval(() => sdk?.integration.signalActive(), 30_000); + context.subscriptions.push({ dispose: () => clearInterval(hbTimer) }); + + // Auto-repair (re-patch after AG updates) + sdk.integration.enableAutoRepair(); + + log('Active'); + } catch (err: any) { + log(`SDK init failed: ${err.message}`); + log('Running in degraded mode (auto-run fix only)'); + } +} + +export function deactivate() { + sdk?.dispose(); + sdk = null; +} diff --git a/better-antigravity-main/static/BA-background.png b/better-antigravity-main/static/BA-background.png new file mode 100644 index 0000000000000000000000000000000000000000..0251ac3cf3286411528ec0e8501038822ea42b2b GIT binary patch literal 15954 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 AHvj+t literal 0 HcmV?d00001 diff --git a/better-antigravity-main/tsconfig.json b/better-antigravity-main/tsconfig.json new file mode 100644 index 0000000..9cdbaa0 --- /dev/null +++ b/better-antigravity-main/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": [ + "ES2020" + ], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "rootDir": "src", + "outDir": "dist", + "declaration": false, + "sourceMap": true, + "resolveJsonModule": true + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules", + "dist", + "fixes" + ] +} \ No newline at end of file diff --git a/docs/devlog/2026-03-08.md b/docs/devlog/2026-03-08.md index b58eeb0..f9a73ec 100644 --- a/docs/devlog/2026-03-08.md +++ b/docs/devlog/2026-03-08.md @@ -13,3 +13,4 @@ | 9 | 07:50 | SDK EventMonitor 제거 — ERR_CONNECTION_REFUSED 원인 차단 (-404 lines) | `f6ae9c8` | ✅ | | 10 | 08:00 | GetCascadeTrajectorySteps 완전 제거 + stall-based WAITING 감지 | `9b9c9c7` | ✅ | | 11 | 08:10 | Stall 감지 calibration + VS Code 명령어 기반 승인 핸들러 | `f1f9a0b` | 🔧 | +| 12 | 11:30~14:35 | 승인 로직 정밀 디버깅: IDLE→stall 전환, lastModifiedTime 구분, RPC/Commands 전수 테스트, ResolveOutstandingSteps cancel 발견 | - | 🔧 | diff --git a/docs/devlog/entries/20260308-005.md b/docs/devlog/entries/20260308-005.md new file mode 100644 index 0000000..41f9fe1 --- /dev/null +++ b/docs/devlog/entries/20260308-005.md @@ -0,0 +1,14 @@ +# Discord Bridge 승인 로직 정밀 디버깅 + +- **시간**: 2026-03-08 11:30~14:35 + +## 결정 사항 + +- IDLE 기반 감지 → stall 기반 (RUNNING+delta=0) 전환 +- `ResolveOutstandingSteps` → step cancel 발견 → 제거 +- VS Code accept commands → 무효과 (webview focus 의존) → OS 레벨 필요 + +## 미완료 + +- Accept 프로그래밍: OS 레벨 UI Automation 접근 필요 +- Thinking/생성 중 false stall: 추가 discriminator 필요 diff --git a/extension/out/extension.js b/extension/out/extension.js index 82e0879..137a355 100644 --- a/extension/out/extension.js +++ b/extension/out/extension.js @@ -53,14 +53,18 @@ const os = __importStar(require("os")); const cp = __importStar(require("child_process")); // ─── File-based logging (AI can read directly) ─── function logToFile(msg) { + const ts = new Date().toISOString().replace('T', ' ').substring(0, 19); + const line = `${ts} ${msg}`; + console.log(`Gravity Bridge: ${msg}`); try { if (!bridgePath) return; const logFile = path.join(bridgePath, 'extension.log'); - const ts = new Date().toISOString().replace('T', ' ').substring(0, 19); - fs.appendFileSync(logFile, `${ts} ${msg}\n`, 'utf-8'); + fs.appendFileSync(logFile, line + '\n', 'utf-8'); + } + catch (e) { + console.error(`Gravity Bridge LOG WRITE FAIL: ${e.message}`); } - catch { } } // antigravity-sdk embedded locally (src/sdk/) let AntigravitySDK; @@ -229,6 +233,314 @@ async function initSDK(context) { return false; } } +// ─── Approval Observer via SDK IntegrationManager ─── +async function setupApprovalObserver() { + if (!sdk) { + logToFile('[OBSERVER] no SDK'); + return; + } + try { + const integration = sdk.integration; + if (!integration) { + logToFile('[OBSERVER] sdk.integration unavailable'); + return; + } + // 1. Start HTTP bridge server in Extension Host + const bridgePort = await startObserverHttpBridge(); + if (!bridgePort) { + logToFile('[OBSERVER] HTTP bridge failed'); + return; + } + // 2. Register a TOP_BAR button so build() works + try { + integration.register({ + id: 'gravity_bridge_status', + point: 'topBar', + icon: '🌉', + tooltip: 'Gravity Bridge Active', + }); + } + catch { /* already registered */ } + // 3. Write renderer script with HTTP fetch() approach + const observerJS = generateApprovalObserverScript(bridgePort); + const patcher = integration._patcher; + if (patcher && typeof patcher.getScriptPath === 'function') { + let baseScript = ''; + try { + baseScript = integration.build(); + } + catch { + baseScript = ''; + } + const combinedScript = baseScript + '\n' + observerJS; + const scriptPath = patcher.getScriptPath(); + fs.writeFileSync(scriptPath, combinedScript, 'utf8'); + logToFile(`[OBSERVER] script written → ${scriptPath} (port=${bridgePort})`); + if (!integration.isInstalled()) { + patcher.install(combinedScript); + logToFile('[OBSERVER] workbench.html patched (needs reload)'); + } + // Also patch workbench-jetski-agent.html (Antigravity's actual entry point!) + const scriptDir = path.dirname(scriptPath); + const jetskiHtml = path.join(scriptDir, 'workbench-jetski-agent.html'); + const scriptBasename = path.basename(scriptPath); + try { + if (fs.existsSync(jetskiHtml)) { + let html = fs.readFileSync(jetskiHtml, 'utf8'); + if (!html.includes(scriptBasename)) { + html = html.replace('', `\n\n\n\n`); + fs.writeFileSync(jetskiHtml, html, 'utf8'); + logToFile('[OBSERVER] workbench-jetski-agent.html PATCHED'); + } + else { + logToFile('[OBSERVER] workbench-jetski-agent.html already has script tag'); + } + } + } + catch (e) { + logToFile(`[OBSERVER] jetski patch error: ${e.message}`); + } + } + try { + integration.enableAutoRepair(); + } + catch { } + setInterval(() => { try { + integration.signalActive(); + } + catch { } }, 30_000); + logToFile(`[OBSERVER] setup complete (HTTP bridge on port ${bridgePort})`); + console.log(`Gravity Bridge: ✅ Approval observer installed (port ${bridgePort})`); + } + catch (err) { + logToFile(`[OBSERVER] setup error: ${err.message}`); + } +} +// ─── HTTP Bridge Server (Extension Host → Renderer communication) ─── +let observerHttpServer = null; +const pendingResponses = new Map(); +function startObserverHttpBridge() { + return new Promise((resolve) => { + try { + const http = require('http'); + const server = http.createServer((req, res) => { + // CORS headers for renderer fetch() + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + if (req.method === 'OPTIONS') { + res.writeHead(200); + res.end(); + return; + } + const url = new URL(req.url, `http://127.0.0.1`); + // POST /pending — renderer reports a detected approval button + if (req.method === 'POST' && url.pathname === '/pending') { + let body = ''; + req.on('data', (c) => body += c); + req.on('end', () => { + try { + const data = JSON.parse(body); + const rid = data.request_id || Date.now().toString(); + // Write pending file for Discord bot + const pendingDir = path.join(bridgePath, 'pending'); + if (!fs.existsSync(pendingDir)) + fs.mkdirSync(pendingDir, { recursive: true }); + const pending = { + ...data, + request_id: rid, + timestamp: Date.now() / 1000, + status: 'pending', + project_name: projectName, + auto_detected: true, + source: 'dom_observer', + }; + fs.writeFileSync(path.join(pendingDir, `${rid}.json`), JSON.stringify(pending, null, 2)); + logToFile(`[HTTP] pending created: ${rid} cmd="${data.command}" ctx="${(data.description || '').substring(0, 50)}"`); + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ ok: true, request_id: rid })); + } + catch (e) { + logToFile(`[HTTP] pending error: ${e.message}`); + res.writeHead(400); + res.end(JSON.stringify({ error: e.message })); + } + }); + return; + } + // GET /response/:rid — renderer polls for Discord approval + if (req.method === 'GET' && url.pathname.startsWith('/response/')) { + const rid = url.pathname.split('/')[2]; + const respFile = path.join(bridgePath, 'response', `${rid}.json`); + if (fs.existsSync(respFile)) { + try { + const data = JSON.parse(fs.readFileSync(respFile, 'utf8')); + fs.unlinkSync(respFile); + logToFile(`[HTTP] response sent: ${rid} approved=${data.approved}`); + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(data)); + } + catch { + res.writeHead(200); + res.end(JSON.stringify({ waiting: true })); + } + } + else { + res.writeHead(200); + res.end(JSON.stringify({ waiting: true })); + } + return; + } + // GET /ping — health check + if (url.pathname === '/ping') { + res.writeHead(200); + res.end('pong'); + return; + } + res.writeHead(404); + res.end('not found'); + }); + // Listen on random port + server.listen(0, '127.0.0.1', () => { + const port = server.address().port; + observerHttpServer = server; + logToFile(`[HTTP] bridge server started on port ${port}`); + // Write port to workbench dir so renderer can read it via XHR + const patcher = sdk.integration?._patcher; + if (patcher && typeof patcher.getWorkbenchDir === 'function') { + const portFile = path.join(patcher.getWorkbenchDir(), 'ag-bridge-port'); + fs.writeFileSync(portFile, port.toString(), 'utf8'); + logToFile(`[HTTP] port written → ${portFile}`); + } + resolve(port); + }); + server.on('error', (e) => { + logToFile(`[HTTP] server error: ${e.message}`); + resolve(0); + }); + } + catch (e) { + logToFile(`[HTTP] server failed: ${e.message}`); + resolve(0); + } + }); +} +// ─── Renderer Script (uses fetch() — no Node.js APIs) ─── +function generateApprovalObserverScript(_port) { + // Port is NOT hardcoded — renderer reads it dynamically from ag-bridge-port file via XHR + return ` +// ── Gravity Bridge: Approval Observer (renderer-side, dynamic port) ── +(function(){ + 'use strict'; + var BASE='',_lastTs=0,_obs=false,_sent={},_ready=false; + + function log(m){console.log('[GB Observer] '+m);} + log('Script loaded — discovering bridge port...'); + + // ── Dynamic Port Discovery (like SDK heartbeat) ── + function discoverPort(cb){ + var attempts=0; + var timer=setInterval(function(){ + attempts++; + if(attempts>30){clearInterval(timer);log('Port discovery timeout');return;} + try{ + var xhr=new XMLHttpRequest(); + xhr.open('GET','./ag-bridge-port?t='+Date.now(),false); + xhr.send(); + if(xhr.status===200){ + var port=parseInt(xhr.responseText.trim(),10); + if(port>0&&port<65536){ + clearInterval(timer); + log('Port discovered: '+port); + cb(port); + } + } + }catch(e){} + },2000); + } + + discoverPort(function(port){ + BASE='http://127.0.0.1:'+port; + // Verify bridge is alive + fetch(BASE+'/ping').then(function(r){return r.text();}).then(function(t){ + if(t==='pong'){log('Bridge connected on port '+port);_ready=true;startObserver();} + else log('Bridge ping failed: '+t); + }).catch(function(e){log('Bridge unreachable: '+e.message);}); + }); + + var PATS=[ + {sel:'button',re:/^Run$/i,type:'terminal_command'}, + {sel:'button',re:/^Accept/i,type:'agent_step'}, + {sel:'button',re:/^Allow/i,type:'permission'}, + {sel:'button',re:/^Continue$/i,type:'continue'}, + ]; + + function ctx(b){ + var p=b.closest('[class*="step"]')||b.closest('[class*="action"]')||b.parentElement; + if(!p)return ''; + var c=p.querySelector('pre,code,[class*="command"],[class*="terminal"]'); + if(c)return(c.textContent||'').trim().substring(0,200); + return(p.textContent||'').replace((b.textContent||''),'').trim().substring(0,200); + } + + function scan(){ + if(!_ready)return; + var now=Date.now();if(now-_lastTs<1000)return; + var panel=document.querySelector('#jetski-agent-panel,.antigravity-agent-side-panel,[class*="agent-panel"]'); + if(!panel)return; + for(var i=0;i600){clearInterval(t);delete _sent[bid];return;} + fetch(BASE+'/response/'+rid).then(function(r){return r.json();}).then(function(d){ + if(d.waiting)return; + clearInterval(t); + if(d.approved){log('APPROVED '+rid+' → clicking');b.click();} + else{ + log('REJECTED '+rid); + var p=b.closest('[class*="step"]')||b.parentElement; + if(p){var rb=p.querySelectorAll('button'); + for(var k=0;k0 before next pending + let lastModTime = ''; // track lastModifiedTime to distinguish thinking vs approval setInterval(async () => { pollCount++; + if (pollCount <= 3 || pollCount % 12 === 0) { + logToFile(`[POLL#${pollCount}] alive`); + } try { const allTraj = await sdk.ls.rawRPC('GetAllCascadeTrajectories', {}); - if (!allTraj?.trajectorySummaries) + if (!allTraj?.trajectorySummaries) { + if (pollCount <= 3) + logToFile('[POLL] no trajectorySummaries'); return; + } let bestSession = null; let bestSessionId = ''; let bestModTime = ''; @@ -326,129 +648,72 @@ function setupMonitor() { if (delta > 0) { console.log(`Gravity Bridge: [POLL#${pollCount}] +${delta} steps (${currentCount}) "${currentTitle}"`); } - // ── IMMEDIATE PENDING DETECTION ── - // On EVERY poll: check last 3 steps for non-DONE status - // This catches: file review, file access permission, command approval - if (isRunning) { - try { - const stepsResp = await sdk.ls.rawRPC('GetCascadeTrajectorySteps', { cascadeId: bestSessionId }); - const steps = stepsResp?.steps || []; - if (steps.length > 0) { - // Check last 3 steps (some may be in-flight) - const checkCount = Math.min(3, steps.length); - for (let i = steps.length - checkCount; i < steps.length; i++) { - const step = steps[i]; - const stepStatus = (step.status || '').replace('CORTEX_STEP_STATUS_', ''); - const stepType = (step.type || '').replace('CORTEX_STEP_TYPE_', ''); - const stepIdx = step.metadata?.sourceTrajectoryStepInfo?.stepIndex ?? i; - // Skip already-handled steps - if (stepIdx <= lastPendingStepIndex) - continue; - // Skip completed/rejected steps - if (stepStatus === 'DONE' || stepStatus === 'REJECTED') - continue; - // ── Non-DONE step found! Create pending based on type ── - let cmd = ''; - let desc = ''; - const toolName = step.metadata?.toolCall?.name || ''; - let argsJson = ''; - try { - argsJson = step.metadata?.toolCall?.argumentsJson || ''; - } - catch { } - if (toolName === 'run_command' || toolName === 'send_command_input') { - // Command execution approval - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.CommandLine || args.command || args.Input || toolName; - } - catch { - cmd = toolName; - } - desc = `명령어 실행 승인 (${stepType})`; - } - else if (toolName === 'browser_subagent') { - // Browser subagent - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.Task?.substring(0, 150) || 'browser task'; - } - catch { - cmd = 'browser_subagent'; - } - desc = `브라우저 서브에이전트 실행`; - } - else if (stepType === 'CODE_ACTION' || toolName === 'replace_file_content' || toolName === 'multi_replace_file_content' || toolName === 'write_to_file') { - // File modification review - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.TargetFile || args.target_file || toolName; - } - catch { - cmd = toolName; - } - desc = `파일 수정 검토 요청`; - } - else if (toolName === 'view_file' || toolName === 'view_file_outline' || toolName === 'view_code_item') { - // File access (usually auto-approved, but handle if pending) - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.AbsolutePath || args.File || toolName; - } - catch { - cmd = toolName; - } - desc = `파일 접근 권한 요청`; - } - else if (toolName === 'notify_user') { - // AI asking for user feedback — this needs a different response - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.Message?.substring(0, 200) || 'notify_user'; - } - catch { - cmd = 'notify_user'; - } - desc = `사용자 피드백 요청`; - } - else if (toolName) { - cmd = toolName; - desc = `도구 실행: ${toolName}`; - } - else { - cmd = stepType || 'unknown'; - desc = `${stepType} (${stepStatus})`; - } - // Create pending for Discord - const rid = Date.now().toString(); - const pending = { - request_id: rid, - conversation_id: bestSessionId, - command: cmd.substring(0, 500), - description: desc.substring(0, 200), - timestamp: Date.now() / 1000, - status: 'pending', - project_name: projectName, - step_index: stepIdx, - step_type: stepType, - step_status: stepStatus, - tool_name: toolName, - auto_detected: true, - }; - const pendingDir = path.join(bridgePath, 'pending'); - fs.writeFileSync(path.join(pendingDir, `${rid}.json`), JSON.stringify(pending, null, 2)); - lastPendingStepIndex = stepIdx; - logToFile(`[PENDING] step=${stepIdx} type=${stepType} status=${stepStatus} tool=${toolName} cmd=${cmd.substring(0, 60)}`); - console.log(`Gravity Bridge: [POLL#${pollCount}] PENDING! step=${stepIdx} ${toolName || stepType} → pending/${rid}.json`); - } + // Log session state on EVERY poll for diagnostics + const statusStr = String(bestSession.status || 'UNKNOWN'); + if (pollCount <= 10 || pollCount % 6 === 0 || delta > 0) { + logToFile(`[POLL#${pollCount}] status=${statusStr} steps=${currentCount} delta=${delta}`); + } + // ── Stall-based approval detection ── + // INSIGHT: Both thinking and approval show RUNNING+delta=0. + // DIFFERENTIATOR: lastModifiedTime + // - Thinking: lastModifiedTime KEEPS CHANGING (server actively processing) + // - Approval wait: lastModifiedTime FROZEN (server idle, waiting for user) + // DEBUG: dump session keys on first poll to find modTime field + if (pollCount === 1) { + const keys = Object.keys(bestSession).filter(k => !['latestNotifyUserStep', 'latestTaskBoundaryStep', 'latestToolCallStep'].includes(k)); + logToFile(`[DEBUG] session keys: ${keys.join(', ')}`); + logToFile(`[DEBUG] lastModifiedTime=${bestSession.lastModifiedTime}, lastModifiedTimestamp=${bestSession.lastModifiedTimestamp}, modifiedTime=${bestSession.modifiedTime}`); + } + const currentModTime = bestSession.lastModifiedTime || bestSession.lastModifiedTimestamp || bestSession.modifiedTime || ''; + const modTimeChanged = currentModTime !== lastModTime; + const isStall = isRunning && delta === 0; + // Log modTime on stalls for debugging + if (isStall && consecutiveIdleCount < 8) { + logToFile(`[STALL-DBG] idle=${consecutiveIdleCount} modTime='${currentModTime}' changed=${modTimeChanged}`); + } + if (delta > 0) { + consecutiveIdleCount = 0; + sawRunningAfterPending = true; + lastModTime = currentModTime; + } + else if (isStall) { + if (modTimeChanged) { + // lastModifiedTime is still changing = AI is thinking, NOT approval + consecutiveIdleCount = 0; // Reset! + if (pollCount <= 10 || pollCount % 12 === 0) { + logToFile(`[THINK] step=${currentCount} modTime changing → not stall`); } } - catch (e) { - // Only log occasionally to avoid spam - if (pollCount % 10 === 0) { - logToFile(`[PENDING] step query error: ${e.message}`); - } + else { + // lastModifiedTime frozen = real stall (approval waiting) + consecutiveIdleCount++; } + lastModTime = currentModTime; + const now = Date.now(); + const cooldownOk = (now - lastPendingTime) > 60_000; + if (consecutiveIdleCount >= 6 && sawRunningAfterPending && cooldownOk) { + // 6 polls × 5s = 30 seconds of FROZEN stall = approval waiting + lastPendingStepIndex = currentCount; + lastPendingTime = now; + sawRunningAfterPending = false; + const command = `Stall at step ${currentCount}`; + const description = `승인 대기 감지 (${consecutiveIdleCount * 5}초 정지), Title: "${currentTitle}"`; + logToFile(`[STALL] step=${currentCount} frozenCount=${consecutiveIdleCount} → pending`); + writePendingApproval({ conversation_id: activeSessionId, command, description }); + } + else if (consecutiveIdleCount === 6) { + const reasons = []; + if (!sawRunningAfterPending) + reasons.push('needDelta>0'); + if (!cooldownOk) + reasons.push(`cooldown(${Math.round((60000 - (now - lastPendingTime)) / 1000)}s)`); + if (reasons.length > 0) + logToFile(`[STALL] SKIP: ${reasons.join(', ')}`); + } + } + else if (!isRunning) { + consecutiveIdleCount = 0; + lastModTime = currentModTime; } // ── Process latestNotifyUserStep ── const notifyStep = bestSession.latestNotifyUserStep; @@ -519,48 +784,79 @@ async function processResponseFile(filePath) { } catch { } } - if (resp.approved) { - // Step 1: Focus Antigravity panel — webview MUST be active for commands to work - // acceptAgentStep dispatches via postMessage to Chat Client webview + // ═══ APPROVAL STRATEGY (VS Code Commands Only) ═══ + // Phase 0 ResolveOutstandingSteps: REMOVED — confirmed it CANCELS steps! + // Phase 1 HandleCascadeUserInteraction: REMOVED — always gets "socket hang up" + // Phase 2: ALL VS Code commands sequentially (no break on "success") + const approved = resp.approved; + // Focus panel with multiple attempts + longer delay + for (let i = 0; i < 2; i++) { try { await vscode.commands.executeCommand('antigravity.agentPanel.focus'); - logToFile('[RESPONSE] panel focused'); + if (i === 0) + logToFile('[RESPONSE] panel focus attempt 1'); } catch (e) { - logToFile(`[RESPONSE] panel focus failed: ${e.message}`); + logToFile(`[RESPONSE] panel focus attempt ${i + 1} failed: ${e.message}`); } - // Wait for webview to initialize await new Promise(r => setTimeout(r, 500)); - // Step 2: Accept — only acceptAgentStep (the universal approval command) - try { - await vscode.commands.executeCommand('antigravity.agent.acceptAgentStep'); - logToFile('[RESPONSE] acceptAgentStep sent'); + } + // Phase 2: Sequential VS Code commands (MUST try ALL — no break!) + // Focus panel first + try { + await vscode.commands.executeCommand('antigravity.agentPanel.focus'); + logToFile('[RESPONSE] panel focused'); + } + catch (e) { + logToFile(`[RESPONSE] panel focus failed: ${e.message}`); + } + await new Promise(r => setTimeout(r, 500)); + if (approved) { + const approveCommands = [ + 'antigravity.interactiveCascade.acceptSuggestedAction', + 'antigravity.terminalCommand.run', + 'antigravity.terminalCommand.accept', + 'antigravity.command.accept', + 'antigravity.agent.acceptAgentStep', + ]; + for (const cmd of approveCommands) { + try { + await vscode.commands.executeCommand(cmd); + logToFile(`[RESPONSE] cmd OK: ${cmd}`); + } + catch (e) { + logToFile(`[RESPONSE] cmd FAIL: ${cmd} → ${e.message}`); + } } - catch (e) { - logToFile(`[RESPONSE] acceptAgentStep failed: ${e.message}`); - } - logToFile('[RESPONSE] approve done'); } else { - // REJECT — same pattern: focus first, then reject - try { - await vscode.commands.executeCommand('antigravity.agentPanel.focus'); + const rejectCommands = [ + 'antigravity.interactiveCascade.rejectSuggestedAction', + 'antigravity.terminalCommand.reject', + 'antigravity.command.reject', + 'antigravity.agent.rejectAgentStep', + ]; + for (const cmd of rejectCommands) { + try { + await vscode.commands.executeCommand(cmd); + logToFile(`[RESPONSE] cmd OK: ${cmd}`); + } + catch (e) { + logToFile(`[RESPONSE] cmd FAIL: ${cmd} → ${e.message}`); + } } - catch { } - await new Promise(r => setTimeout(r, 500)); - try { - await vscode.commands.executeCommand('antigravity.agent.rejectAgentStep'); - logToFile('[RESPONSE] rejectAgentStep sent'); - } - catch (e) { - logToFile(`[RESPONSE] rejectAgentStep failed: ${e.message}`); - } - logToFile('[RESPONSE] reject done'); } + logToFile(`[RESPONSE] ${approved ? 'approve' : 'reject'} done`); + // Cleanup try { fs.unlinkSync(filePath); } catch { } + try { + if (fs.existsSync(pendingFile)) + fs.unlinkSync(pendingFile); + } + catch { } } catch (e) { const log = `[RESPONSE] error: ${e.message}`; @@ -693,8 +989,9 @@ async function activate(context) { const sdkReady = await initSDK(context); if (sdkReady) { setupMonitor(); // Now just logs that monitor is disabled + setupApprovalObserver(); // DOM observer via SDK IntegrationManager statusBar.text = '$(check) Bridge'; - statusBar.tooltip = `Gravity Bridge: ${projectName} (POLL active)`; + statusBar.tooltip = `Gravity Bridge: ${projectName} (POLL + Observer active)`; // Register SDK-powered commands context.subscriptions.push(vscode.commands.registerCommand('gravityBridge.approve', async () => { try { diff --git a/extension/out/extension.js.map b/extension/out/extension.js.map index 1922b8d..9b953ee 100644 --- a/extension/out/extension.js.map +++ b/extension/out/extension.js.map @@ -1 +1 @@ -{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/extension/src/extension.ts b/extension/src/extension.ts index a9e8933..47fb35d 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -18,12 +18,16 @@ import * as cp from 'child_process'; // ─── File-based logging (AI can read directly) ─── function logToFile(msg: string) { + const ts = new Date().toISOString().replace('T', ' ').substring(0, 19); + const line = `${ts} ${msg}`; + console.log(`Gravity Bridge: ${msg}`); try { if (!bridgePath) return; const logFile = path.join(bridgePath, 'extension.log'); - const ts = new Date().toISOString().replace('T', ' ').substring(0, 19); - fs.appendFileSync(logFile, `${ts} ${msg}\n`, 'utf-8'); - } catch { } + fs.appendFileSync(logFile, line + '\n', 'utf-8'); + } catch (e: any) { + console.error(`Gravity Bridge LOG WRITE FAIL: ${e.message}`); + } } // antigravity-sdk embedded locally (src/sdk/) @@ -201,6 +205,299 @@ async function initSDK(context: vscode.ExtensionContext): Promise { } } +// ─── Approval Observer via SDK IntegrationManager ─── + +async function setupApprovalObserver() { + if (!sdk) { logToFile('[OBSERVER] no SDK'); return; } + try { + const integration = sdk.integration; + if (!integration) { logToFile('[OBSERVER] sdk.integration unavailable'); return; } + + // 1. Start HTTP bridge server in Extension Host + const bridgePort = await startObserverHttpBridge(); + if (!bridgePort) { logToFile('[OBSERVER] HTTP bridge failed'); return; } + + // 2. Register a TOP_BAR button so build() works + try { + integration.register({ + id: 'gravity_bridge_status', + point: 'topBar', + icon: '🌉', + tooltip: 'Gravity Bridge Active', + }); + } catch { /* already registered */ } + + // 3. Write renderer script with HTTP fetch() approach + const observerJS = generateApprovalObserverScript(bridgePort); + const patcher = (integration as any)._patcher; + if (patcher && typeof patcher.getScriptPath === 'function') { + let baseScript = ''; + try { baseScript = integration.build(); } catch { baseScript = ''; } + const combinedScript = baseScript + '\n' + observerJS; + const scriptPath = patcher.getScriptPath(); + fs.writeFileSync(scriptPath, combinedScript, 'utf8'); + logToFile(`[OBSERVER] script written → ${scriptPath} (port=${bridgePort})`); + if (!integration.isInstalled()) { + patcher.install(combinedScript); + logToFile('[OBSERVER] workbench.html patched (needs reload)'); + } + + // Also patch workbench-jetski-agent.html (Antigravity's actual entry point!) + const scriptDir = path.dirname(scriptPath); + const jetskiHtml = path.join(scriptDir, 'workbench-jetski-agent.html'); + const scriptBasename = path.basename(scriptPath); + try { + if (fs.existsSync(jetskiHtml)) { + let html = fs.readFileSync(jetskiHtml, 'utf8'); + if (!html.includes(scriptBasename)) { + html = html.replace('', + `\n\n\n\n`); + fs.writeFileSync(jetskiHtml, html, 'utf8'); + logToFile('[OBSERVER] workbench-jetski-agent.html PATCHED'); + } else { + logToFile('[OBSERVER] workbench-jetski-agent.html already has script tag'); + } + } + } catch (e: any) { + logToFile(`[OBSERVER] jetski patch error: ${e.message}`); + } + } + + try { integration.enableAutoRepair(); } catch { } + setInterval(() => { try { integration.signalActive(); } catch { } }, 30_000); + + logToFile(`[OBSERVER] setup complete (HTTP bridge on port ${bridgePort})`); + console.log(`Gravity Bridge: ✅ Approval observer installed (port ${bridgePort})`); + } catch (err: any) { + logToFile(`[OBSERVER] setup error: ${err.message}`); + } +} + +// ─── HTTP Bridge Server (Extension Host → Renderer communication) ─── + +let observerHttpServer: any = null; +const pendingResponses = new Map(); + +function startObserverHttpBridge(): Promise { + return new Promise((resolve) => { + try { + const http = require('http'); + const server = http.createServer((req: any, res: any) => { + // CORS headers for renderer fetch() + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; } + + const url = new URL(req.url, `http://127.0.0.1`); + + // POST /pending — renderer reports a detected approval button + if (req.method === 'POST' && url.pathname === '/pending') { + let body = ''; + req.on('data', (c: string) => body += c); + req.on('end', () => { + try { + const data = JSON.parse(body); + const rid = data.request_id || Date.now().toString(); + // Write pending file for Discord bot + const pendingDir = path.join(bridgePath, 'pending'); + if (!fs.existsSync(pendingDir)) fs.mkdirSync(pendingDir, { recursive: true }); + const pending = { + ...data, + request_id: rid, + timestamp: Date.now() / 1000, + status: 'pending', + project_name: projectName, + auto_detected: true, + source: 'dom_observer', + }; + fs.writeFileSync(path.join(pendingDir, `${rid}.json`), JSON.stringify(pending, null, 2)); + logToFile(`[HTTP] pending created: ${rid} cmd="${data.command}" ctx="${(data.description || '').substring(0, 50)}"`); + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ ok: true, request_id: rid })); + } catch (e: any) { + logToFile(`[HTTP] pending error: ${e.message}`); + res.writeHead(400); res.end(JSON.stringify({ error: e.message })); + } + }); + return; + } + + // GET /response/:rid — renderer polls for Discord approval + if (req.method === 'GET' && url.pathname.startsWith('/response/')) { + const rid = url.pathname.split('/')[2]; + const respFile = path.join(bridgePath, 'response', `${rid}.json`); + if (fs.existsSync(respFile)) { + try { + const data = JSON.parse(fs.readFileSync(respFile, 'utf8')); + fs.unlinkSync(respFile); + logToFile(`[HTTP] response sent: ${rid} approved=${data.approved}`); + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(data)); + } catch { + res.writeHead(200); res.end(JSON.stringify({ waiting: true })); + } + } else { + res.writeHead(200); res.end(JSON.stringify({ waiting: true })); + } + return; + } + + // GET /ping — health check + if (url.pathname === '/ping') { + res.writeHead(200); res.end('pong'); + return; + } + + res.writeHead(404); res.end('not found'); + }); + + // Listen on random port + server.listen(0, '127.0.0.1', () => { + const port = server.address().port; + observerHttpServer = server; + logToFile(`[HTTP] bridge server started on port ${port}`); + + // Write port to workbench dir so renderer can read it via XHR + const patcher = (sdk.integration as any)?._patcher; + if (patcher && typeof patcher.getWorkbenchDir === 'function') { + const portFile = path.join(patcher.getWorkbenchDir(), 'ag-bridge-port'); + fs.writeFileSync(portFile, port.toString(), 'utf8'); + logToFile(`[HTTP] port written → ${portFile}`); + } + + resolve(port); + }); + + server.on('error', (e: any) => { + logToFile(`[HTTP] server error: ${e.message}`); + resolve(0); + }); + } catch (e: any) { + logToFile(`[HTTP] server failed: ${e.message}`); + resolve(0); + } + }); +} + +// ─── Renderer Script (uses fetch() — no Node.js APIs) ─── + +function generateApprovalObserverScript(_port: number): string { + // Port is NOT hardcoded — renderer reads it dynamically from ag-bridge-port file via XHR + return ` +// ── Gravity Bridge: Approval Observer (renderer-side, dynamic port) ── +(function(){ + 'use strict'; + var BASE='',_lastTs=0,_obs=false,_sent={},_ready=false; + + function log(m){console.log('[GB Observer] '+m);} + log('Script loaded — discovering bridge port...'); + + // ── Dynamic Port Discovery (like SDK heartbeat) ── + function discoverPort(cb){ + var attempts=0; + var timer=setInterval(function(){ + attempts++; + if(attempts>30){clearInterval(timer);log('Port discovery timeout');return;} + try{ + var xhr=new XMLHttpRequest(); + xhr.open('GET','./ag-bridge-port?t='+Date.now(),false); + xhr.send(); + if(xhr.status===200){ + var port=parseInt(xhr.responseText.trim(),10); + if(port>0&&port<65536){ + clearInterval(timer); + log('Port discovered: '+port); + cb(port); + } + } + }catch(e){} + },2000); + } + + discoverPort(function(port){ + BASE='http://127.0.0.1:'+port; + // Verify bridge is alive + fetch(BASE+'/ping').then(function(r){return r.text();}).then(function(t){ + if(t==='pong'){log('Bridge connected on port '+port);_ready=true;startObserver();} + else log('Bridge ping failed: '+t); + }).catch(function(e){log('Bridge unreachable: '+e.message);}); + }); + + var PATS=[ + {sel:'button',re:/^Run$/i,type:'terminal_command'}, + {sel:'button',re:/^Accept/i,type:'agent_step'}, + {sel:'button',re:/^Allow/i,type:'permission'}, + {sel:'button',re:/^Continue$/i,type:'continue'}, + ]; + + function ctx(b){ + var p=b.closest('[class*="step"]')||b.closest('[class*="action"]')||b.parentElement; + if(!p)return ''; + var c=p.querySelector('pre,code,[class*="command"],[class*="terminal"]'); + if(c)return(c.textContent||'').trim().substring(0,200); + return(p.textContent||'').replace((b.textContent||''),'').trim().substring(0,200); + } + + function scan(){ + if(!_ready)return; + var now=Date.now();if(now-_lastTs<1000)return; + var panel=document.querySelector('#jetski-agent-panel,.antigravity-agent-side-panel,[class*="agent-panel"]'); + if(!panel)return; + for(var i=0;i600){clearInterval(t);delete _sent[bid];return;} + fetch(BASE+'/response/'+rid).then(function(r){return r.json();}).then(function(d){ + if(d.waiting)return; + clearInterval(t); + if(d.approved){log('APPROVED '+rid+' → clicking');b.click();} + else{ + log('REJECTED '+rid); + var p=b.closest('[class*="step"]')||b.parentElement; + if(p){var rb=p.querySelectorAll('button'); + for(var k=0;k(); const lastSnapshotText = new Map(); @@ -255,12 +552,22 @@ function setupMonitor() { let lastNotifyStepIndex = -1; let lastTaskStepIndex = -1; let lastPendingStepIndex = -1; // dedup: don't re-create pending for same step + let consecutiveIdleCount = 0; // debounce: require N consecutive stall polls + let lastPendingTime = 0; // cooldown: minimum gap between pendings + let sawRunningAfterPending = true; // gate: must see delta>0 before next pending + let lastModTime = ''; // track lastModifiedTime to distinguish thinking vs approval setInterval(async () => { pollCount++; + if (pollCount <= 3 || pollCount % 12 === 0) { + logToFile(`[POLL#${pollCount}] alive`); + } try { const allTraj = await sdk.ls.rawRPC('GetAllCascadeTrajectories', {}); - if (!allTraj?.trajectorySummaries) return; + if (!allTraj?.trajectorySummaries) { + if (pollCount <= 3) logToFile('[POLL] no trajectorySummaries'); + return; + } let bestSession: any = null; let bestSessionId = ''; @@ -299,106 +606,74 @@ function setupMonitor() { console.log(`Gravity Bridge: [POLL#${pollCount}] +${delta} steps (${currentCount}) "${currentTitle}"`); } - // ── IMMEDIATE PENDING DETECTION ── - // On EVERY poll: check last 3 steps for non-DONE status - // This catches: file review, file access permission, command approval - if (isRunning) { - try { - const stepsResp = await sdk.ls.rawRPC('GetCascadeTrajectorySteps', { cascadeId: bestSessionId }); - const steps = stepsResp?.steps || []; - if (steps.length > 0) { - // Check last 3 steps (some may be in-flight) - const checkCount = Math.min(3, steps.length); - for (let i = steps.length - checkCount; i < steps.length; i++) { - const step = steps[i]; - const stepStatus = (step.status || '').replace('CORTEX_STEP_STATUS_', ''); - const stepType = (step.type || '').replace('CORTEX_STEP_TYPE_', ''); - const stepIdx = step.metadata?.sourceTrajectoryStepInfo?.stepIndex ?? i; + // Log session state on EVERY poll for diagnostics + const statusStr = String(bestSession.status || 'UNKNOWN'); + if (pollCount <= 10 || pollCount % 6 === 0 || delta > 0) { + logToFile(`[POLL#${pollCount}] status=${statusStr} steps=${currentCount} delta=${delta}`); + } - // Skip already-handled steps - if (stepIdx <= lastPendingStepIndex) continue; - // Skip completed/rejected steps - if (stepStatus === 'DONE' || stepStatus === 'REJECTED') continue; + // ── Stall-based approval detection ── + // INSIGHT: Both thinking and approval show RUNNING+delta=0. + // DIFFERENTIATOR: lastModifiedTime + // - Thinking: lastModifiedTime KEEPS CHANGING (server actively processing) + // - Approval wait: lastModifiedTime FROZEN (server idle, waiting for user) - // ── Non-DONE step found! Create pending based on type ── - let cmd = ''; - let desc = ''; - const toolName = step.metadata?.toolCall?.name || ''; - let argsJson = ''; - try { argsJson = step.metadata?.toolCall?.argumentsJson || ''; } catch { } + // DEBUG: dump session keys on first poll to find modTime field + if (pollCount === 1) { + const keys = Object.keys(bestSession).filter(k => !['latestNotifyUserStep', 'latestTaskBoundaryStep', 'latestToolCallStep'].includes(k)); + logToFile(`[DEBUG] session keys: ${keys.join(', ')}`); + logToFile(`[DEBUG] lastModifiedTime=${bestSession.lastModifiedTime}, lastModifiedTimestamp=${(bestSession as any).lastModifiedTimestamp}, modifiedTime=${(bestSession as any).modifiedTime}`); + } - if (toolName === 'run_command' || toolName === 'send_command_input') { - // Command execution approval - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.CommandLine || args.command || args.Input || toolName; - } catch { cmd = toolName; } - desc = `명령어 실행 승인 (${stepType})`; - } else if (toolName === 'browser_subagent') { - // Browser subagent - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.Task?.substring(0, 150) || 'browser task'; - } catch { cmd = 'browser_subagent'; } - desc = `브라우저 서브에이전트 실행`; - } else if (stepType === 'CODE_ACTION' || toolName === 'replace_file_content' || toolName === 'multi_replace_file_content' || toolName === 'write_to_file') { - // File modification review - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.TargetFile || args.target_file || toolName; - } catch { cmd = toolName; } - desc = `파일 수정 검토 요청`; - } else if (toolName === 'view_file' || toolName === 'view_file_outline' || toolName === 'view_code_item') { - // File access (usually auto-approved, but handle if pending) - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.AbsolutePath || args.File || toolName; - } catch { cmd = toolName; } - desc = `파일 접근 권한 요청`; - } else if (toolName === 'notify_user') { - // AI asking for user feedback — this needs a different response - try { - const args = JSON.parse(argsJson || '{}'); - cmd = args.Message?.substring(0, 200) || 'notify_user'; - } catch { cmd = 'notify_user'; } - desc = `사용자 피드백 요청`; - } else if (toolName) { - cmd = toolName; - desc = `도구 실행: ${toolName}`; - } else { - cmd = stepType || 'unknown'; - desc = `${stepType} (${stepStatus})`; - } + const currentModTime = bestSession.lastModifiedTime || (bestSession as any).lastModifiedTimestamp || (bestSession as any).modifiedTime || ''; + const modTimeChanged = currentModTime !== lastModTime; + const isStall = isRunning && delta === 0; - // Create pending for Discord - const rid = Date.now().toString(); - const pending = { - request_id: rid, - conversation_id: bestSessionId, - command: cmd.substring(0, 500), - description: desc.substring(0, 200), - timestamp: Date.now() / 1000, - status: 'pending', - project_name: projectName, - step_index: stepIdx, - step_type: stepType, - step_status: stepStatus, - tool_name: toolName, - auto_detected: true, - }; - const pendingDir = path.join(bridgePath, 'pending'); - fs.writeFileSync(path.join(pendingDir, `${rid}.json`), JSON.stringify(pending, null, 2)); - lastPendingStepIndex = stepIdx; - logToFile(`[PENDING] step=${stepIdx} type=${stepType} status=${stepStatus} tool=${toolName} cmd=${cmd.substring(0, 60)}`); - console.log(`Gravity Bridge: [POLL#${pollCount}] PENDING! step=${stepIdx} ${toolName || stepType} → pending/${rid}.json`); - } - } - } catch (e: any) { - // Only log occasionally to avoid spam - if (pollCount % 10 === 0) { - logToFile(`[PENDING] step query error: ${e.message}`); + // Log modTime on stalls for debugging + if (isStall && consecutiveIdleCount < 8) { + logToFile(`[STALL-DBG] idle=${consecutiveIdleCount} modTime='${currentModTime}' changed=${modTimeChanged}`); + } + + if (delta > 0) { + consecutiveIdleCount = 0; + sawRunningAfterPending = true; + lastModTime = currentModTime; + } else if (isStall) { + if (modTimeChanged) { + // lastModifiedTime is still changing = AI is thinking, NOT approval + consecutiveIdleCount = 0; // Reset! + if (pollCount <= 10 || pollCount % 12 === 0) { + logToFile(`[THINK] step=${currentCount} modTime changing → not stall`); } + } else { + // lastModifiedTime frozen = real stall (approval waiting) + consecutiveIdleCount++; } + lastModTime = currentModTime; + + const now = Date.now(); + const cooldownOk = (now - lastPendingTime) > 60_000; + + if (consecutiveIdleCount >= 6 && sawRunningAfterPending && cooldownOk) { + // 6 polls × 5s = 30 seconds of FROZEN stall = approval waiting + lastPendingStepIndex = currentCount; + lastPendingTime = now; + sawRunningAfterPending = false; + + const command = `Stall at step ${currentCount}`; + const description = `승인 대기 감지 (${consecutiveIdleCount * 5}초 정지), Title: "${currentTitle}"`; + + logToFile(`[STALL] step=${currentCount} frozenCount=${consecutiveIdleCount} → pending`); + writePendingApproval({ conversation_id: activeSessionId, command, description }); + } else if (consecutiveIdleCount === 6) { + const reasons = []; + if (!sawRunningAfterPending) reasons.push('needDelta>0'); + if (!cooldownOk) reasons.push(`cooldown(${Math.round((60000 - (now - lastPendingTime)) / 1000)}s)`); + if (reasons.length > 0) logToFile(`[STALL] SKIP: ${reasons.join(', ')}`); + } + } else if (!isRunning) { + consecutiveIdleCount = 0; + lastModTime = currentModTime; } // ── Process latestNotifyUserStep ── @@ -475,42 +750,72 @@ async function processResponseFile(filePath: string) { } catch { } } - if (resp.approved) { - // Step 1: Focus Antigravity panel — webview MUST be active for commands to work - // acceptAgentStep dispatches via postMessage to Chat Client webview - try { - await vscode.commands.executeCommand('antigravity.agentPanel.focus'); - logToFile('[RESPONSE] panel focused'); - } catch (e: any) { - logToFile(`[RESPONSE] panel focus failed: ${e.message}`); - } - // Wait for webview to initialize - await new Promise(r => setTimeout(r, 500)); + // ═══ APPROVAL STRATEGY (VS Code Commands Only) ═══ + // Phase 0 ResolveOutstandingSteps: REMOVED — confirmed it CANCELS steps! + // Phase 1 HandleCascadeUserInteraction: REMOVED — always gets "socket hang up" + // Phase 2: ALL VS Code commands sequentially (no break on "success") - // Step 2: Accept — only acceptAgentStep (the universal approval command) - try { - await vscode.commands.executeCommand('antigravity.agent.acceptAgentStep'); - logToFile('[RESPONSE] acceptAgentStep sent'); - } catch (e: any) { - logToFile(`[RESPONSE] acceptAgentStep failed: ${e.message}`); - } - logToFile('[RESPONSE] approve done'); - } else { - // REJECT — same pattern: focus first, then reject + const approved = resp.approved; + + // Focus panel with multiple attempts + longer delay + for (let i = 0; i < 2; i++) { try { await vscode.commands.executeCommand('antigravity.agentPanel.focus'); - } catch { } - await new Promise(r => setTimeout(r, 500)); - try { - await vscode.commands.executeCommand('antigravity.agent.rejectAgentStep'); - logToFile('[RESPONSE] rejectAgentStep sent'); + if (i === 0) logToFile('[RESPONSE] panel focus attempt 1'); } catch (e: any) { - logToFile(`[RESPONSE] rejectAgentStep failed: ${e.message}`); + logToFile(`[RESPONSE] panel focus attempt ${i + 1} failed: ${e.message}`); } - logToFile('[RESPONSE] reject done'); + await new Promise(r => setTimeout(r, 500)); } + // Phase 2: Sequential VS Code commands (MUST try ALL — no break!) + // Focus panel first + try { + await vscode.commands.executeCommand('antigravity.agentPanel.focus'); + logToFile('[RESPONSE] panel focused'); + } catch (e: any) { + logToFile(`[RESPONSE] panel focus failed: ${e.message}`); + } + await new Promise(r => setTimeout(r, 500)); + + if (approved) { + const approveCommands = [ + 'antigravity.interactiveCascade.acceptSuggestedAction', + 'antigravity.terminalCommand.run', + 'antigravity.terminalCommand.accept', + 'antigravity.command.accept', + 'antigravity.agent.acceptAgentStep', + ]; + for (const cmd of approveCommands) { + try { + await vscode.commands.executeCommand(cmd); + logToFile(`[RESPONSE] cmd OK: ${cmd}`); + } catch (e: any) { + logToFile(`[RESPONSE] cmd FAIL: ${cmd} → ${e.message}`); + } + } + } else { + const rejectCommands = [ + 'antigravity.interactiveCascade.rejectSuggestedAction', + 'antigravity.terminalCommand.reject', + 'antigravity.command.reject', + 'antigravity.agent.rejectAgentStep', + ]; + for (const cmd of rejectCommands) { + try { + await vscode.commands.executeCommand(cmd); + logToFile(`[RESPONSE] cmd OK: ${cmd}`); + } catch (e: any) { + logToFile(`[RESPONSE] cmd FAIL: ${cmd} → ${e.message}`); + } + } + } + + logToFile(`[RESPONSE] ${approved ? 'approve' : 'reject'} done`); + + // Cleanup try { fs.unlinkSync(filePath); } catch { } + try { if (fs.existsSync(pendingFile)) fs.unlinkSync(pendingFile); } catch { } } catch (e: any) { const log = `[RESPONSE] error: ${e.message}`; console.log(`Gravity Bridge: ${log}`); @@ -638,8 +943,9 @@ export async function activate(context: vscode.ExtensionContext) { if (sdkReady) { setupMonitor(); // Now just logs that monitor is disabled + setupApprovalObserver(); // DOM observer via SDK IntegrationManager statusBar.text = '$(check) Bridge'; - statusBar.tooltip = `Gravity Bridge: ${projectName} (POLL active)`; + statusBar.tooltip = `Gravity Bridge: ${projectName} (POLL + Observer active)`; // Register SDK-powered commands context.subscriptions.push(