@agentex/agent 0.0.37 → 0.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +54 -17
  3. package/dist/providers/antigravity/codec.d.ts +4 -0
  4. package/dist/providers/antigravity/codec.d.ts.map +1 -0
  5. package/dist/providers/antigravity/codec.js +27 -0
  6. package/dist/providers/antigravity/codec.js.map +1 -0
  7. package/dist/providers/antigravity/connection.d.ts +100 -0
  8. package/dist/providers/antigravity/connection.d.ts.map +1 -0
  9. package/dist/providers/antigravity/connection.js +267 -0
  10. package/dist/providers/antigravity/connection.js.map +1 -0
  11. package/dist/providers/antigravity/discovery.d.ts +11 -0
  12. package/dist/providers/antigravity/discovery.d.ts.map +1 -0
  13. package/dist/providers/antigravity/discovery.js +92 -0
  14. package/dist/providers/antigravity/discovery.js.map +1 -0
  15. package/dist/providers/antigravity/execute.d.ts +9 -0
  16. package/dist/providers/antigravity/execute.d.ts.map +1 -0
  17. package/dist/providers/antigravity/execute.js +206 -0
  18. package/dist/providers/antigravity/execute.js.map +1 -0
  19. package/dist/providers/antigravity/index.d.ts +12 -0
  20. package/dist/providers/antigravity/index.d.ts.map +1 -0
  21. package/dist/providers/antigravity/index.js +46 -0
  22. package/dist/providers/antigravity/index.js.map +1 -0
  23. package/dist/providers/antigravity/parse.d.ts +114 -0
  24. package/dist/providers/antigravity/parse.d.ts.map +1 -0
  25. package/dist/providers/antigravity/parse.js +369 -0
  26. package/dist/providers/antigravity/parse.js.map +1 -0
  27. package/dist/providers/antigravity/probe.d.ts +3 -0
  28. package/dist/providers/antigravity/probe.d.ts.map +1 -0
  29. package/dist/providers/antigravity/probe.js +84 -0
  30. package/dist/providers/antigravity/probe.js.map +1 -0
  31. package/dist/providers/antigravity/runtime.d.ts +30 -0
  32. package/dist/providers/antigravity/runtime.d.ts.map +1 -0
  33. package/dist/providers/antigravity/runtime.js +69 -0
  34. package/dist/providers/antigravity/runtime.js.map +1 -0
  35. package/dist/providers/antigravity/session.d.ts +7 -0
  36. package/dist/providers/antigravity/session.d.ts.map +1 -0
  37. package/dist/providers/antigravity/session.js +317 -0
  38. package/dist/providers/antigravity/session.js.map +1 -0
  39. package/dist/providers/gemini/index.d.ts.map +1 -1
  40. package/dist/providers/gemini/index.js +6 -0
  41. package/dist/providers/gemini/index.js.map +1 -1
  42. package/dist/registry.d.ts.map +1 -1
  43. package/dist/registry.js +2 -0
  44. package/dist/registry.js.map +1 -1
  45. package/dist/types.d.ts +6 -5
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js.map +1 -1
  48. package/dist/utils/auth.d.ts +1 -1
  49. package/dist/utils/auth.d.ts.map +1 -1
  50. package/dist/utils/auth.js +79 -1
  51. package/dist/utils/auth.js.map +1 -1
  52. package/dist/utils/binary.d.ts.map +1 -1
  53. package/dist/utils/binary.js +10 -0
  54. package/dist/utils/binary.js.map +1 -1
  55. package/dist/utils/instructions.d.ts +36 -12
  56. package/dist/utils/instructions.d.ts.map +1 -1
  57. package/dist/utils/instructions.js +116 -62
  58. package/dist/utils/instructions.js.map +1 -1
  59. package/dist/utils/runtime-homes.d.ts.map +1 -1
  60. package/dist/utils/runtime-homes.js +4 -0
  61. package/dist/utils/runtime-homes.js.map +1 -1
  62. package/dist/utils/skills.d.ts +3 -3
  63. package/dist/utils/skills.d.ts.map +1 -1
  64. package/dist/utils/skills.js +16 -2
  65. package/dist/utils/skills.js.map +1 -1
  66. package/package.json +3 -2
  67. package/src/providers/antigravity/codec.ts +29 -0
  68. package/src/providers/antigravity/connection.ts +304 -0
  69. package/src/providers/antigravity/discovery.ts +90 -0
  70. package/src/providers/antigravity/execute.ts +214 -0
  71. package/src/providers/antigravity/index.ts +48 -0
  72. package/src/providers/antigravity/parse.ts +439 -0
  73. package/src/providers/antigravity/probe.ts +89 -0
  74. package/src/providers/antigravity/runtime.ts +64 -0
  75. package/src/providers/antigravity/session.ts +359 -0
  76. package/src/providers/gemini/index.ts +6 -0
  77. package/src/registry.ts +2 -0
  78. package/src/types.ts +6 -5
  79. package/src/utils/auth.ts +82 -1
  80. package/src/utils/binary.ts +10 -0
  81. package/src/utils/instructions.ts +162 -73
  82. package/src/utils/runtime-homes.ts +4 -0
  83. package/src/utils/skills.ts +17 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.39 — Antigravity provider (Google's successor to Gemini CLI)
4
+
5
+ Gemini CLI stopped serving free, Google AI Pro, and Google AI Ultra sign-ins on 2026-06-18 ("This client is no longer supported for Gemini Code Assist for individuals"). Google moved those accounts to the Antigravity CLI, `agy`. This release adds it as a first-class provider. Wire behavior follows the documented headless protocol and was checked against `agy` 1.2.14.
6
+
7
+ ### Added
8
+
9
+ - **`antigravity` provider** (`getProvider("antigravity")`). Drives `agy --input-format stream-json --output-format stream-json`.
10
+ - **Sessions.** One `agy` process per session. Each `send()` writes one NDJSON user message and resolves on that turn's `result`. Sessions resume with `--conversation`. `sessionParams` are `{ sessionId, cwd }`, because Antigravity scopes conversations to a directory. Params saved for another directory start a new conversation instead of resuming the wrong one.
11
+ - **One-shot `execute()`.** Writes the prompt over stdin and closes it, so prompts are never argv-limited or visible in `ps`. It waits for the process to exit.
12
+ - **Interrupts.** The CLI has no control protocol, so `interrupt()`, timeouts, and abort signals SIGINT the process group (Ctrl+C). If `agy` exits instead of reporting `INTERRUPTED`, the next `send()` resumes the conversation in a new process. A message sent to a process that exits without acknowledging it is re-run once on a fresh one.
13
+ - **Events.** `system/init`, `assistant` (with `assistant_delta` under `includePartialMessages`), `thinking`, correlated `tool_call`/`tool_result` (`toolCallId` = `<conversationId>:<stepIndex>`, subagent steps included), `result`, `turn_start`/`turn_end`, `auth_required`, and `unknown` for future step types.
14
+ - **Usage.** agy reports cumulative usage per process. agentex reports each turn's share, with `cachedInputTokens` from `cache_read_tokens`.
15
+ - **Config mapping.** `model` → `--model`. `effort` → `--effort` (`low|medium|high|max`). `modeId`/`mode` → `--mode` (`default`, `accept-edits`, `plan`). `planMode` → `--mode plan`, which wins over `skipPermissions` → `--dangerously-skip-permissions`. `sandbox` → `--sandbox`. `instructionsFile` is prepended to a new conversation's first message. `skillDirs` are linked into `~/.gemini/antigravity-cli/skills`.
16
+ - **Permissions.** Headless agy cannot ask. Tools needing approval are soft-denied by policy and surface on `ExecutionResult.permissionDenials`. `capabilities.permissionRequests` is `false`.
17
+ - **Errors.** `AGY_ERROR` stderr reports map to `rate_limited`, `invalid_model`, `waiting_for_input` (status `blocked`), or `agent_error`.
18
+ - **Discovery.** `listModels()` reads `agy models`. `listModes()` is static and spawns nothing. `probeCapabilities()` checks `--help` for the stream-json flags (profile `agy-stream-json-v1`) and reports "not signed in" as `missing` rather than `upgrade_required`.
19
+ - **Fast sign-in failure.** An unsigned headless `agy` prints a login URL and blocks for 60 seconds waiting for a pasted code. agentex stops it as soon as the prompt appears, emits `auth_required` with `loginCommand: "agy"`, and fails with `errorCode: "auth_required"`. Against the real CLI this takes about 0.5s instead of 60.
20
+ - **Auth.** `resolveAuthForProvider("antigravity")` reports the sign-in from `agy models` (there is no status subcommand). `GEMINI_API_KEY` counts only when `~/.gemini/antigravity-cli/settings.json` sets `"modelProvider": "gemini"`, because the CLI ignores the variable otherwise. `detectAuth` and `loginCommandFor` (`"agy"`) follow the same rules.
21
+ - **`SkillRuntime` gains `"antigravity"`.** Workspace skills use the standard `.agents/skills` channel. Global skills go to `~/.gemini/antigravity-cli/skills`. Instructions use `AGENTS.md`, and the global native file is the `~/.gemini/GEMINI.md` it shares with Gemini CLI.
22
+ - `findBinary("agy")` also checks `~/.local/bin/agy`, where the official installer puts it and which GUI apps usually lack on `PATH`. It also checks `/usr/local/bin`, `/opt/homebrew/bin`, and on Windows `%LOCALAPPDATA%\agy\bin`.
23
+
24
+ ### Changed
25
+
26
+ - `installSkills`/`removeSkills`/`listInstalledSkills` with `includeNativeDirs` skip a runtime folder that is already a standard channel, so nothing is installed or reported twice.
27
+ - Global `resolveInstructionTargets`/`installInstructions` merge runtimes that share a file. Gemini CLI and Antigravity both read `~/.gemini/GEMINI.md`, so it becomes one target serving both.
28
+ - The `gemini` provider documents the personal-account retirement and points to `antigravity`. It still works with paid API keys and Gemini Code Assist Standard/Enterprise.
29
+ - The barrel-import module budget in `tests/packaging/lazy-graph.test.ts` is re-pinned from 51 to 53. The new provider adds the same light `index` + `codec` pair every provider ships, and no heavy modules.
30
+
31
+ ## 0.0.38 — AGENTS.md is the workspace instruction file for every runtime
32
+
33
+ Claude Code reads `AGENTS.md` since 2.1.277, loaded exactly where `CLAUDE.md` would be, but only in a folder with no `CLAUDE.md`. A `CLAUDE.md`, a `CLAUDE.local.md`, or one in a parent folder hides `AGENTS.md` completely (verified against 2.1.281). Not yet on Bedrock, Vertex or Foundry.
34
+
35
+ ### Changed (breaking)
36
+
37
+ - **`installInstructions` writes `AGENTS.md` only by default.** Claude's workspace file is now `AGENTS.md`, like every other runtime. `CLAUDE.md` is Claude's native file, written only with `includeNativeFiles: true`, and then as a one-line `@AGENTS.md` pointer in the managed region instead of a second copy of the brief. A copy would have made anything the user writes in `AGENTS.md` invisible to Claude. Opt in for Claude Code before 2.1.277 or on a third-party API provider. `includeNativeFiles` still writes Gemini's `GEMINI.md` as a copy.
38
+ - **An existing workspace `CLAUDE.md` is reconciled** whenever `claude` is among the runtimes and the opt-in is off, because it would hide `AGENTS.md`: one holding nothing but this installer's managed region (for example the full brief 0.0.37 and earlier wrote) is deleted, and one the user wrote keeps their content and gains `@AGENTS.md` in the managed region. `managed: false` leaves it alone.
39
+ - **`removeInstructions` always checks native files** (`CLAUDE.md`, `GEMINI.md`), so an opt-in install is fully removable. It still only strips the managed region.
40
+
41
+ ### Added
42
+
43
+ - `InstructionStatus` gains `"removed"`, and `InstructionInstallResult` a `removed` count.
44
+ - `InstructionTarget.importsFile` marks a pointer file (`"AGENTS.md"` on an opt-in `CLAUDE.md`).
45
+
46
+ ### Migration
47
+
48
+ A host that relied on the default `CLAUDE.md` gets `AGENTS.md` only. Nothing else is needed on Claude Code 2.1.277+ with first-party auth: the next install deletes the old managed-only `CLAUDE.md`. Elsewhere, pass `includeNativeFiles: true`.
49
+
3
50
  ## 0.0.37 — Turn liveness and background-task identity (Claude)
4
51
 
5
52
  Claude Code starts turns by itself. When a background task finishes, the CLI
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @agentex/agent
2
2
 
3
- Programmatic execution of AI coding agents. Spawn and manage Claude Code, Codex, Gemini, Cursor, OpenCode, Pi, OpenClaw, or any CLI-based agent as a child process with streaming output, multi-turn sessions, auth detection, isolated workspaces, skill installation, and a unified interface.
3
+ Programmatic execution of AI coding agents. Spawn and manage Claude Code, Codex, Antigravity, Gemini, Cursor, OpenCode, Pi, OpenClaw, or any CLI-based agent as a child process with streaming output, multi-turn sessions, auth detection, isolated workspaces, skill installation, and a unified interface.
4
4
 
5
5
  ## Install
6
6
 
@@ -48,7 +48,7 @@ Providers fall into three tiers:
48
48
 
49
49
  - **Tier 1 — deep native:** `claude`, `codex`. Hand-built adapters over each CLI's richest protocol (Claude's stream-json, Codex's `app-server` JSON-RPC). Subscription-native, fullest feature set.
50
50
  - **Tier 2 — ACP:** `gemini`, `copilot`, plus any agent registered via [`acpProvider`](#custom--byok-providers) or `extends: "acp"` config. One shared, tested base over the open [Agent Client Protocol](https://agentclientprotocol.com) (JSON-RPC over stdio).
51
- - **Tier 3 — bespoke escape hatches:** `opencode` (authenticated HTTP/SSE daemon), `pi` (persistent RPC), `cursor` (exec-backed resume), `openclaw` (HTTP gateway), `process` (any executable).
51
+ - **Tier 3 — bespoke escape hatches:** `opencode` (authenticated HTTP/SSE daemon), `pi` (persistent RPC), `antigravity` (persistent stream-json), `cursor` (exec-backed resume), `openclaw` (HTTP gateway), `process` (any executable).
52
52
 
53
53
  | Provider | Transport | Tier | Sessions | Modes | Permissions |
54
54
  | ---------- | -------------------------------------- | ---- | --------- | ----- | ----------- |
@@ -58,12 +58,41 @@ Providers fall into three tiers:
58
58
  | `copilot` | `copilot --acp` (ACP) | 2 | ✅ | ✅ | ✅ |
59
59
  | `opencode` | authenticated `opencode serve` HTTP + SSE | 3 | ✅ resume | ✅ | ✅ |
60
60
  | `pi` | persistent `pi --mode rpc` | 3 | ✅ resume | — | — |
61
+ | `antigravity` | persistent `agy` stream-json (stdin + stdout) | 3 | ✅ resume | ✅ | policy |
61
62
  | `cursor` | `cursor-agent` stream-json per turn | 3 | ✅ resume | probed | — |
62
63
  | `openclaw` | HTTP gateway | 3 | — | — | — |
63
64
  | `process` | any executable | 3 | — | — | — |
64
65
 
65
66
  Cursor sessions are exec-backed. Each `send()` starts one CLI process and promotes the returned Cursor session ID into `--resume` for the next turn. `probeCapabilities()` verifies the selected binary's model catalog and advertised modes. Each execution independently validates the supported stream-json acceptance marker before releasing output. Older Cursor CLIs report `upgrade_required` instead of silently advertising discovery features they do not expose.
66
67
 
68
+ ### Antigravity (Google)
69
+
70
+ Google moved personal accounts (Free, Google AI Pro, Google AI Ultra) from Gemini CLI to the [Antigravity CLI](https://antigravity.google/docs/cli/overview) on 2026-06-18. Signing in to Gemini CLI with one of those accounts now fails with "This client is no longer supported for Gemini Code Assist for individuals". Use the `antigravity` provider for them. The `gemini` provider still works with a paid API key or Gemini Code Assist Standard/Enterprise.
71
+
72
+ ```bash
73
+ curl -fsSL https://antigravity.google/cli/install.sh | bash # installs ~/.local/bin/agy
74
+ agy # once, to sign in through the browser
75
+ ```
76
+
77
+ ```typescript
78
+ const agy = getProvider("antigravity");
79
+ const session = await agy.createSession!({
80
+ cwd,
81
+ config: { model: "gemini-3.1-pro-high", effort: "high", modeId: "accept-edits" },
82
+ onEvent: (e) => { if (e.type === "assistant") console.log(e.text); },
83
+ });
84
+ await (await session.send("Summarize this repo")).result;
85
+ await (await session.send("Now list its entry points")).result; // same agy process, same conversation
86
+ ```
87
+
88
+ - **Transport.** A session is one `agy --input-format stream-json --output-format stream-json` process. Each `send()` writes one NDJSON user message and resolves on that turn's `result` event. `execute()` writes one message and closes stdin, so prompts never travel through argv. Saved `sessionParams` are `{ sessionId, cwd }` and resume with `--conversation`. Antigravity scopes conversations to a directory, so params saved for another `cwd` start a new conversation instead of resuming.
89
+ - **Interrupts.** The CLI has no control protocol, so `interrupt()`, timeouts, and abort signals send SIGINT to the process group, like Ctrl+C. If agy exits instead of reporting the turn as `INTERRUPTED`, the next `send()` starts a new process on the same conversation.
90
+ - **Permissions.** Headless agy cannot ask. `skipPermissions` maps to `--dangerously-skip-permissions`. Without it, actions that would need approval (shell commands by default) are soft-denied and listed in `ExecutionResult.permissionDenials`, and the run still succeeds. Grant specific actions with `permissions.allow` rules in `~/.gemini/antigravity-cli/settings.json`. `permissionRequests` is therefore `false`.
91
+ - **Modes, effort, models.** `listModes()` returns `default`, `accept-edits`, and `plan` (`--mode`). `planMode` maps to `--mode plan`. `config.effort` maps to `--effort` (`low`, `medium`, `high`, `max`). `listModels()` reads `agy models`, which needs a signed-in account.
92
+ - **Sign-in.** An unsigned headless agy prints a login URL and waits a minute for a code. agentex stops it as soon as the prompt appears, emits `auth_required` with `loginCommand: "agy"`, and fails the turn with `errorCode: "auth_required"`.
93
+ - **Usage.** agy reports cumulative usage per process. agentex reports each turn's share, keyed by the pinned model (or `"default"`). `cachedInputTokens` comes from `cache_read_tokens`.
94
+ - **Not yet wired.** `config.mcpServers` (agy reads `~/.gemini/config/mcp_config.json` and `.agents/mcp_config.json` itself), and history import.
95
+
67
96
  OpenCode sessions use a password-authenticated loopback server, SSE events, permission and question reconciliation, durable service-backed history, saved-session discovery and import, runtime model and agent discovery, and upstream provider authentication. `config.mcpServers` remains unsupported for OpenCode because strict isolation from ambient OpenCode MCP configuration is not yet proven.
68
97
 
69
98
  ### OpenCode and Cursor discovery
@@ -256,7 +285,7 @@ interface ProviderConfig {
256
285
  command?: string; // Override CLI binary path
257
286
  model?: string;
258
287
  modelVariant?: string; // OpenCode provider-native variant, separate from effort
259
- effort?: string;
288
+ effort?: string; // claude/antigravity: --effort; codex: turn effort override
260
289
  unattendedPermissionPolicy?: "allow" | "deny";
261
290
  inputRequestTimeoutSec?: number; // OpenCode permission/question response deadline, default 300
262
291
  maxTurns?: number;
@@ -269,14 +298,14 @@ interface ProviderConfig {
269
298
  strictMcpConfig?: boolean; // claude: --strict-mcp-config — MCP surface is exactly what you attach
270
299
  allowedTools?: string[]; // claude: --allowed-tools (patterns verbatim; codex ignores)
271
300
  disallowedTools?: string[]; // claude: --disallowed-tools (deny wins; codex ignores)
272
- includePartialMessages?: boolean; // claude: emit assistant_delta/thinking_delta typewriter events
301
+ includePartialMessages?: boolean; // claude, antigravity: emit assistant_delta/thinking_delta typewriter events
273
302
  extraArgs?: string[]; // always appended LAST — hosts can override any generated flag
274
303
  search?: boolean;
275
- sandbox?: boolean;
304
+ sandbox?: boolean; // antigravity: --sandbox (terminal sandbox)
276
305
  thinking?: string;
277
- mode?: string; // cursor: --mode <mode>; not for plan mode
278
- modeId?: string; // select an operating mode from listModes() (codex/ACP)
279
- planMode?: boolean; // read-only "plan" mode (claude/codex)
306
+ mode?: string; // cursor, antigravity: --mode <mode>; not for plan mode
307
+ modeId?: string; // select an operating mode from listModes() (codex/ACP/antigravity)
308
+ planMode?: boolean; // read-only "plan" mode (claude/codex/cursor/opencode/antigravity)
280
309
  workspace?: { strategy: "worktree"; baseBranch?: string; branchName?: string };
281
310
  }
282
311
  ```
@@ -434,7 +463,7 @@ When in doubt, `raw` is the verbatim provider event — parse it yourself for an
434
463
 
435
464
  ### Other providers
436
465
 
437
- `gemini` and `copilot` (ACP) and the session-backed `opencode` and `pi` emit real, correlated `StreamEvent`s — assistant text, thinking, and tool_call/tool_result with proper tool-call ids (ACP and Codex have no per-event/message ids, so those stay `null`). `cursor` and `openclaw` still emit the same `StreamEvent` shape with most ids stubbed to `null`; their `raw` field is populated. `cursor` will gain full fidelity when it moves to the ACP tier.
466
+ `gemini` and `copilot` (ACP), `antigravity`, and the session-backed `opencode` and `pi` emit real, correlated `StreamEvent`s — assistant text, thinking, and tool_call/tool_result with proper tool-call ids (ACP and Codex have no per-event/message ids, so those stay `null`). `cursor` and `openclaw` still emit the same `StreamEvent` shape with most ids stubbed to `null`; their `raw` field is populated. `cursor` will gain full fidelity when it moves to the ACP tier. `antigravity` has no per-call tool ids, so `toolCallId` is `<conversationId>:<stepIndex>`, and `messageId` uses the same key for a response step's `assistant` and `assistant_delta` events.
438
467
 
439
468
  ## Sessions (multi-turn)
440
469
 
@@ -797,6 +826,7 @@ const executeRun = await claude.execute({
797
826
  | -------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
798
827
  | `claude` | `--permission-mode plan` (CLI-native plan UX) | Agent calls the `ExitPlanMode` tool with the plan as a permission request. Host extracts via `parseExitPlanMode(req)` from `onUserInputRequest`. The plan is **not** in the persisted transcript — capture it live. |
799
828
  | `codex` | `--sandbox read-only` **plus** an injected planning system preamble | Plain text in the agent's final assistant message (i.e. `result.summary`). |
829
+ | `antigravity` | `--mode plan` (CLI-native: read-only tools, then a plan) | Plain text in the turn's response (`result.summary`). Headless runs proceed through plan review automatically. |
800
830
 
801
831
  The mechanism difference matters:
802
832
 
@@ -905,6 +935,7 @@ await claude.execute({ prompt: "Respond with 'hello'.", config: { timeoutSec: 15
905
935
  | `codex` | `codex login status` · fallback: `$CODEX_HOME/auth.json` | `OPENAI_API_KEY` | — |
906
936
  | `gemini` | `$GEMINI_CONFIG_DIR/oauth_creds.json` | `GEMINI_API_KEY`, `GOOGLE_API_KEY` | — |
907
937
  | `cursor` | selected CLI's `status` command | `CURSOR_API_KEY` | `OPENAI_API_KEY` is intentionally ignored |
938
+ | `antigravity` | `agy models` exit status (keyring sign-in) | `GEMINI_API_KEY`, only with `"modelProvider": "gemini"` in `~/.gemini/antigravity-cli/settings.json` | The CLI ignores `GEMINI_API_KEY` otherwise |
908
939
  | `opencode`| — | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY` | — |
909
940
  | `pi` | — | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY` | — |
910
941
 
@@ -917,6 +948,7 @@ The library reflects real CLI behavior rather than imposing its own:
917
948
  | Claude | API key wins (documented). Set `hasApiKey` + show a billing warning. |
918
949
  | Codex | Subscription wins (current CLI; see openai/codex#2733, #3286). |
919
950
  | Gemini | API key wins in non-interactive mode. |
951
+ | Antigravity | `settings.json` decides: `modelProvider: "gemini"` uses the API key, otherwise the signed-in account. |
920
952
 
921
953
  ### Caching
922
954
 
@@ -1024,7 +1056,7 @@ const skillDirs = ["/path/to/code-review", "/path/to/testing"];
1024
1056
  await installSkills(skillDirs, {
1025
1057
  location: "workspace", // or "global"
1026
1058
  cwd: process.cwd(), // required for workspace installs
1027
- includeNativeDirs: false, // true also installs into ~/.gemini/skills/, etc.
1059
+ includeNativeDirs: false, // true also installs into ~/.gemini/skills/, ~/.gemini/antigravity-cli/skills/, etc.
1028
1060
  });
1029
1061
 
1030
1062
  const installed = await listInstalledSkills({ location: "workspace", cwd: process.cwd() });
@@ -1041,11 +1073,11 @@ Channels and locations follow the emerging `.agents/skills/` + `.claude/skills/`
1041
1073
  import { installInstructions, removeInstructions } from "@agentex/agent";
1042
1074
 
1043
1075
  // Workspace (repo-root) install — the common case.
1044
- // Writes the brief into {cwd}/CLAUDE.md and {cwd}/AGENTS.md (deduped by filename).
1076
+ // Writes the brief into {cwd}/AGENTS.md, which every runtime reads.
1045
1077
  await installInstructions(brief, {
1046
1078
  location: "workspace", // or "global"
1047
1079
  cwd: process.cwd(), // required for workspace installs
1048
- includeNativeFiles: false, // true also writes Gemini's native GEMINI.md
1080
+ includeNativeFiles: false, // true also writes CLAUDE.md (an @AGENTS.md pointer) and GEMINI.md
1049
1081
  managed: true, // wrap in markers + merge (default); false overwrites the file
1050
1082
  managedTag: "agentex", // marker tag → <!-- agentex:managed:start -->
1051
1083
  });
@@ -1058,7 +1090,12 @@ await installInstructions(brief, { location: "global" });
1058
1090
  await removeInstructions({ location: "workspace", cwd: process.cwd() });
1059
1091
  ```
1060
1092
 
1061
- Every runtime except Claude reads `AGENTS.md`; Claude reads `CLAUDE.md`. Gemini reads `GEMINI.md` by default (only reads `AGENTS.md` when configured), so it gets a native escape hatch via `includeNativeFiles`. Re-installing unchanged content is idempotent (reported as `skipped`). Use `resolveInstructionTargets(opts)` to see which files *would* be written without touching disk, and `upsertManagedBlock` / `stripManagedBlock` for the low-level merge.
1093
+ Every runtime reads `AGENTS.md` at a workspace root. Claude Code does since 2.1.277, but only where the folder has no `CLAUDE.md`: a `CLAUDE.md`, a `CLAUDE.local.md`, or one in a parent folder hides `AGENTS.md` completely. So a workspace `CLAUDE.md` is only ever a one-line `@AGENTS.md` pointer, never a second copy of the brief:
1094
+
1095
+ - `includeNativeFiles: true` writes the pointer. Use it for Claude Code before 2.1.277, or on Bedrock, Vertex or Foundry, where Claude doesn't read `AGENTS.md` on its own. It also writes Gemini's native `GEMINI.md` (a copy), since Gemini reads `AGENTS.md` only when configured.
1096
+ - With the opt-in off, an existing `CLAUDE.md` is reconciled whenever Claude is among the runtimes: one holding nothing but the managed region is removed (reported `removed`), and one the user wrote gets `@AGENTS.md` in its managed region, so the brief still reaches Claude.
1097
+
1098
+ Re-installing unchanged content is idempotent (reported as `skipped`). Use `resolveInstructionTargets(opts)` to see which files *would* be written without touching disk, and `upsertManagedBlock` / `stripManagedBlock` for the low-level merge.
1062
1099
 
1063
1100
  ### Discover Slash-Invokable Skills
1064
1101
 
@@ -1242,7 +1279,7 @@ registerProvider(myProvider);
1242
1279
  - `ensureCommandResolvable(command)` — like `findBinary` but accepts an absolute path too.
1243
1280
  - `clearBinaryCache()` — invalidate the binary-resolution cache.
1244
1281
  - `provider.checkQuota?(ctx)` — rate-limit / quota status (when `capabilities.quotaProbing`).
1245
- - `provider.listModels?(opts?)` — enumerate models the binary can drive. Currently no built-in provider implements this: none of the Claude / Codex / Gemini CLIs expose a non-interactive model-listing subcommand yet (run `pnpm list-models` to re-probe). Pass the model you want directly via `ExecutionContext.model` or `ProviderConfig.model`.
1282
+ - `provider.listModels?(opts?)` — enumerate models the binary can drive, where the CLI exposes a catalog (for example `cursor`, `opencode`, and `antigravity` via `agy models`). Otherwise pass the model you want directly via `ExecutionContext.model` or `ProviderConfig.model`.
1246
1283
 
1247
1284
  ### Workspace
1248
1285
  - `prepareWorkspace({ strategy, baseBranch?, branchName?, targetDir? })` → `PreparedWorkspace` with `cwd`, `diff()`, `cleanup()`.
@@ -1268,7 +1305,7 @@ registerProvider(myProvider);
1268
1305
  - `renderTemplate(template, ctx)` — `{{var}}` interpolation.
1269
1306
  - `redactEnvForLogs(env)` — redact sensitive values before logging.
1270
1307
  - `resolveInstructions(path?)` — read an instructions file, or `null` if no path.
1271
- - `installInstructions(content, opts?)` / `removeInstructions(opts?)` — write/remove a managed instruction brief across per-runtime files (`CLAUDE.md` / `AGENTS.md` / native `GEMINI.md`), workspace or global.
1308
+ - `installInstructions(content, opts?)` / `removeInstructions(opts?)` — write/remove a managed instruction brief across per-runtime files (`AGENTS.md`, plus opt-in native `CLAUDE.md` pointer / `GEMINI.md`), workspace or global.
1272
1309
  - `resolveInstructionTargets(opts?)` — list which instruction files would be written, without touching disk.
1273
1310
  - `upsertManagedBlock(existing, content, opts?)` / `stripManagedBlock(existing, opts?)` — low-level managed-region merge/strip (preserves content outside the markers).
1274
1311
  - `getDefaultRuntimeHome(runtime, homeDir?)` — pass `homeDir` to resolve against a sandboxed base instead of `os.homedir()`.
@@ -1278,8 +1315,8 @@ registerProvider(myProvider);
1278
1315
  ## Requirements
1279
1316
 
1280
1317
  - Node.js >= 18
1281
- - Each provider's CLI installed and resolvable on `$PATH` (`claude`, `codex`, `gemini`, `agent` for Cursor, `opencode`, `pi`, or a reachable OpenClaw gateway)
1282
- - For subscription auth, the relevant CLI must already be logged in (`codex login`, `claude login`, `gemini auth login`, etc.)
1318
+ - Each provider's CLI installed and resolvable on `$PATH` (`claude`, `codex`, `agy` for Antigravity, `gemini`, `agent` for Cursor, `opencode`, `pi`, or a reachable OpenClaw gateway). `agy` is also found at `~/.local/bin/agy` when that folder is not on `$PATH`.
1319
+ - For subscription auth, the relevant CLI must already be logged in (`codex login`, `claude login`, `agy` once for Antigravity, etc.)
1283
1320
 
1284
1321
  ## License
1285
1322
 
@@ -0,0 +1,4 @@
1
+ import type { SessionCodec } from "../../types.js";
2
+ /** Antigravity session params: the conversation id plus the directory it is scoped to. */
3
+ export declare const antigravitySessionCodec: SessionCodec;
4
+ //# sourceMappingURL=codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../../src/providers/antigravity/codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAqBnD,0FAA0F;AAC1F,eAAO,MAAM,uBAAuB,EAAE,YAMrC,CAAC"}
@@ -0,0 +1,27 @@
1
+ function readNonEmptyString(value) {
2
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
3
+ }
4
+ function readSessionId(obj) {
5
+ return readNonEmptyString(obj["sessionId"])
6
+ ?? readNonEmptyString(obj["session_id"])
7
+ ?? readNonEmptyString(obj["conversationId"]);
8
+ }
9
+ function normalize(raw) {
10
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw))
11
+ return null;
12
+ const obj = raw;
13
+ const sessionId = readSessionId(obj);
14
+ if (!sessionId)
15
+ return null;
16
+ const cwd = readNonEmptyString(obj["cwd"]);
17
+ return { sessionId, ...(cwd ? { cwd } : {}) };
18
+ }
19
+ /** Antigravity session params: the conversation id plus the directory it is scoped to. */
20
+ export const antigravitySessionCodec = {
21
+ deserialize: normalize,
22
+ serialize: (params) => normalize(params),
23
+ getDisplayId(params) {
24
+ return params ? readSessionId(params) : null;
25
+ },
26
+ };
27
+ //# sourceMappingURL=codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.js","sourceRoot":"","sources":["../../../src/providers/antigravity/codec.ts"],"names":[],"mappings":"AAEA,SAAS,kBAAkB,CAAC,KAAc;IACxC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpF,CAAC;AAED,SAAS,aAAa,CAAC,GAA4B;IACjD,OAAO,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;WACtC,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;WACrC,kBAAkB,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/E,MAAM,GAAG,GAAG,GAA8B,CAAC;IAC3C,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAChD,CAAC;AAED,0FAA0F;AAC1F,MAAM,CAAC,MAAM,uBAAuB,GAAiB;IACnD,WAAW,EAAE,SAAS;IACtB,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC;IACxC,YAAY,CAAC,MAAM;QACjB,OAAO,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;CACF,CAAC"}
@@ -0,0 +1,100 @@
1
+ import type { StreamEvent } from "../../types.js";
2
+ import { type AgyErrorReport, type AgyResult, type AgyStreamParser } from "./parse.js";
3
+ export interface AgyConnectionOptions {
4
+ command: string;
5
+ args: string[];
6
+ cwd: string;
7
+ env: Record<string, string>;
8
+ parser: AgyStreamParser;
9
+ onEvent?: (event: StreamEvent) => void | Promise<void>;
10
+ onOutput?: (stream: "stdout" | "stderr", chunk: string) => void | Promise<void>;
11
+ }
12
+ /** How a turn (or the whole process) ended, as seen by the host. */
13
+ export interface AgyTurnOutcome {
14
+ /** The turn's `result` event, or null when the process exited first. */
15
+ result: AgyResult | null;
16
+ /** The process has exited. */
17
+ exited: boolean;
18
+ exitCode: number | null;
19
+ signal: string | null;
20
+ /** The CLI asked for a sign-in, which a headless run can never complete. */
21
+ authRequired: boolean;
22
+ agyError: AgyErrorReport | null;
23
+ /** Last ~16KB of stderr, for error messages. */
24
+ stderr: string;
25
+ }
26
+ /**
27
+ * One headless `agy` process speaking `stream-json` in both directions.
28
+ *
29
+ * Every stdout line is parsed and dispatched through a single promise chain,
30
+ * so `onEvent` handlers run strictly in wire order and a turn's waiter
31
+ * resolves only after the handler for its `result` event has settled.
32
+ */
33
+ export declare class AgyConnection {
34
+ private readonly options;
35
+ readonly pid: number | null;
36
+ authRequired: boolean;
37
+ agyError: AgyErrorReport | null;
38
+ private readonly child;
39
+ private chain;
40
+ private stdoutBuffer;
41
+ private stderrLineBuffer;
42
+ private stderrTail;
43
+ private exitInfo;
44
+ private finalized;
45
+ private readonly waiters;
46
+ private readonly exitWaiters;
47
+ constructor(options: AgyConnectionOptions);
48
+ get alive(): boolean;
49
+ /** Exit status, or null while the process runs. */
50
+ get exit(): {
51
+ code: number | null;
52
+ signal: string | null;
53
+ } | null;
54
+ /** Last ~16KB of stderr. */
55
+ get stderr(): string;
56
+ /** Resolves once the process has exited and every queued event was dispatched. */
57
+ exited(): Promise<void>;
58
+ /** Send one user message. Resolve it with `nextTurn()`. */
59
+ write(text: string): void;
60
+ /** Close stdin. `agy` finishes the current turn and exits. */
61
+ endInput(): void;
62
+ /** Resolves with the next `result` event, or with the exit when no result comes. */
63
+ nextTurn(): Promise<AgyTurnOutcome>;
64
+ /** Signal the whole process group. */
65
+ signal(signal: NodeJS.Signals): void;
66
+ /** True when the process exited within `ms`. */
67
+ waitForExit(ms: number): Promise<boolean>;
68
+ /**
69
+ * Stop the process: close stdin and give it a moment to exit on its own
70
+ * (an idle `agy` flushes its conversation history and exits), then
71
+ * SIGTERM, then SIGKILL after `graceSec`.
72
+ */
73
+ terminate(graceSec?: number, idleWaitMs?: number): Promise<void>;
74
+ private onStdout;
75
+ private enqueueLine;
76
+ private onStderr;
77
+ private inspectStderrLine;
78
+ /**
79
+ * A headless run without a cached sign-in prints a login URL and waits a
80
+ * full minute for a code nobody can paste. Fail fast instead: report it
81
+ * and stop the process.
82
+ */
83
+ private onAuthRequired;
84
+ private appendStderrTail;
85
+ private finalize;
86
+ private outcome;
87
+ private emitEvent;
88
+ private emitOutput;
89
+ }
90
+ /** First meaningful stderr line, skipping the sign-in URL noise. */
91
+ export declare function firstAgyErrorLine(stderr: string): string | null;
92
+ /** Waits for `promise` up to `ms`; resolves null on timeout. */
93
+ export declare function within<T>(promise: Promise<T>, ms: number): Promise<T | null>;
94
+ /**
95
+ * Interrupt the running turn like Ctrl+C would: SIGINT the process group,
96
+ * give agy a moment to report the turn as INTERRUPTED, and stop the process
97
+ * if it does not. Resolves with whatever outcome arrived.
98
+ */
99
+ export declare function interruptAgyTurn(connection: AgyConnection, pending: Promise<AgyTurnOutcome>, graceSec?: number): Promise<AgyTurnOutcome | null>;
100
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/providers/antigravity/connection.ts"],"names":[],"mappings":"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"}