agy-mcp-bridge 0.1.24 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -82,10 +82,21 @@ Two switches control delegation itself: `agy-mcp-bridge delegation off` blocks n
82
82
 
83
83
  ## Agents, profiles and pools
84
84
 
85
- `agents.profiles.<id>` declares named agents that inherit an adapter and override its defaults (`env` such as `CODEX_HOME`, `model`, `executable`, `codex_sandbox`, `codex_ask_for_approval`), so one machine can run two logged-in accounts side by side. A profile id is a valid `agent` value and `agents_list` reports each one's availability and warnings. `priority` and `enabled` still order the adapters themselves.
85
+ `agents.profiles.<id>` declares named agents that inherit an adapter and override its defaults (`env` such as `CODEX_HOME`, `model`, `executable`, `codex_sandbox`, `codex_ask_for_approval`). A profile id is a valid `agent` value and `agents_list` reports each one's availability and warnings.
86
+
87
+ Whether a profile really is a second account depends on the adapter. A `codex` profile with its own `CODEX_HOME` signs in separately, so two Codex accounts do run side by side. An `antigravity` profile does **not**: `agy` resolves its credential from the machine's own login (on Windows the credential is in the keyring, so pointing `HOME`, `USERPROFILE`, `APPDATA` and `LOCALAPPDATA` at another directory changes nothing), which means several antigravity profiles share one Google account and a pool of them cannot fail over to spare quota. `agy` signs in through Google OAuth.
88
+
89
+ Four rules about these ids are easy to get wrong, all measured rather than inferred:
90
+
91
+ - `agents.enabled` must list **every profile id** you declare, not just the adapters. A profile missing there is silently disabled, and a pool of such members then refuses with `Unknown agent "<pool id>"` — a message that names the pool while the broken line is `enabled`. Omitting `enabled` entirely enables everything; the example keeps the key so you can see it exists, which means a new profile has to be added to that list too.
92
+ - A `codex` profile also needs the base `codex` id in `enabled`, because that is what makes the bridge probe the codex CLI at all. Without it the profile is unavailable **and reports no warning**, so `agents_list` shows a dead agent with no reason.
93
+ - `model` on a profile is read only for a `codex` profile; an `antigravity` profile runs with the model you choose in the web UI.
94
+ - `priority` and `enabled` accept a pool id without complaining, but the default agent is matched against agent ids only — a pool there silently selects nothing. Name the pool in the `agent` argument of a task instead.
86
95
 
87
96
  `agents.pools.<id>` groups profiles for quota handling. Delegating to a pool id picks the first healthy member. When a member stops with something that reads like an exhausted quota or rate limit, the bridge marks it cooling for `quota_cooldown_seconds` and re-runs **the same task** on the next member — each member at most once per task, after which the task fails instead of looping. The replaced attempt is kept on the record as `attempts[]` (agent, error, exit, log tails) so a reviewer can still see why the first CLI stopped, and the retry keeps holding the execution lock rather than releasing and re-taking it, so no second ordinary task slips into the gap.
88
97
 
98
+ The owner's Settings reach an `antigravity` **profile** exactly as they reach `antigravity`, because they key on the adapter behind the id, not on the id: the model, the permission level, the effort, and the soft deadline with its `--log-file` and its extended `--print-timeout` are all on the command line of a profile task. Read that as a widening, not a cosmetic fix — before, a profile was locked to the CLI's own defaults and could not be given `--dangerously-skip-permissions` at all; now your permission level applies to its tasks too, so a profile is no more restricted than the agent it comes from.
99
+
89
100
  Two knobs are opt-in because they widen what the bridge can reach. Neither is reachable from a task, and neither stays invisible: the codex pair is reported in `agents_list` warnings, and the XERJ pair in `/api/xerj/status` plus the refusal `code_search` gives while it is off.
90
101
 
91
102
  - `codex_sandbox: "danger-full-access"` / `codex_ask_for_approval: "never"` — readable from the bridge's own config file only. No task, tool argument or MCP client can ask for them, and `--ask-for-approval` is passed where codex accepts it (before `exec`).
@@ -12,7 +12,7 @@
12
12
  "default_autonomy": "auto",
13
13
  "agents": {
14
14
  "priority": ["antigravity", "codex"],
15
- "enabled": ["antigravity", "codex"],
15
+ "enabled": ["antigravity", "codex", "codex-work", "codex-backup"],
16
16
  "codex_sandbox": "workspace-write",
17
17
  "codex_ask_for_approval": "on-request",
18
18
  "profiles": {
@@ -6,6 +6,7 @@ export function antigravityAdapter(executable, defaultTransport, options = {}) {
6
6
  return {
7
7
  id: options.id ?? 'antigravity',
8
8
  label: options.label ?? 'Antigravity',
9
+ family: 'antigravity',
9
10
  capabilities: CAPABILITIES,
10
11
  buildInvocation(task) {
11
12
  const transport = task.promptTransport ?? defaultTransport;
@@ -9,6 +9,7 @@ export function codexAdapter(command, options = {}) {
9
9
  return {
10
10
  id: options.id ?? 'codex',
11
11
  label: options.label ?? 'Codex',
12
+ family: 'codex',
12
13
  capabilities: CAPABILITIES,
13
14
  buildInvocation(task) {
14
15
  const resultFile = path.join(task.stateDirectory, 'results', `${task.taskId}.txt`);
@@ -183,7 +183,7 @@ export class TaskManager {
183
183
  context: input.context === undefined ? null : redact(input.context), timeout_seconds: timeout,
184
184
  client: meta.client ? redact(meta.client).slice(0, 100) : null,
185
185
  agent: task.agent, isolation: input.isolation, owns: input.owns, autonomy,
186
- model: agent?.adapter.id === 'antigravity' ? await readModel(this.runtime.stateDirectory) : null,
186
+ model: agent?.adapter.family === 'antigravity' ? await readModel(this.runtime.stateDirectory) : null,
187
187
  permission: permissionState(this.runtime.stateDirectory).level,
188
188
  effort: readEffort(this.runtime.stateDirectory)
189
189
  }
@@ -312,7 +312,7 @@ export class TaskManager {
312
312
  entry.request.permission = permission;
313
313
  // Soft deadline (owner setting, off by default): agy gets the absolute limit as its own print timeout and a log file whose growth shows it is alive.
314
314
  const soft = readSoftTimeout(this.runtime.stateDirectory);
315
- const antigravity = agent.adapter.id === 'antigravity';
315
+ const antigravity = agent.adapter.family === 'antigravity';
316
316
  const absoluteLimit = Math.max(timeout, soft.limit_seconds);
317
317
  let logFile;
318
318
  if (antigravity && soft.enabled) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agy-mcp-bridge",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Local loopback HTTP MCP bridge that delegates bounded coding tasks to multiple agent CLIs (Antigravity, Codex) with optional parallel git worktrees",
5
5
  "license": "MIT",
6
6
  "keywords": [