Skip to content

fix(agents): launch omp through its local CLI instead of the npx bridge - #855

Merged
kaizhou-lab merged 1 commit into
mainfrom
fix/omp-direct-cli-launch
Aug 14, 2026
Merged

fix(agents): launch omp through its local CLI instead of the npx bridge#855
kaizhou-lab merged 1 commit into
mainfrom
fix/omp-direct-cli-launch

Conversation

@kaizhou-lab

@kaizhou-lab kaizhou-lab commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Problem

Migration 031 seeded omp as npx -y @oh-my-pi/pi-coding-agent acp with binary_name: "omp", copying the shape the Registry-listed npx rows use. That shape does not fit omp, and the row ended up paying both launch paths' costs while getting neither's benefit.

There is no Registry entry to conform to. Audited against the public ACP Registry catalogue: 11 of the 13 command='npx' builtin rows match their Registry entry's package and args exactly.

backend Registry-declared distribution our args match
autohand npx @autohandai/autohand-acp -y @autohandai/autohand-acp
codebuddy npx @tencent-ai/codebuddy-code --acp -y --package … codebuddy --acp
deepagents npx deepagents-acp same
dimcode npx dimcode acp same
dirac npx dirac-cli --acp same
glm-acp-agent npx glm-acp-agent same
grok npx @xai-official/grok agent stdio same
kilo npx @kilocode/cli acp same
nova npx @compass-ai/nova acp same
pi npx pi-acp same
sigit npx @smbcloud/sigit same
mimo-code not listed non-Registry builtin
omp not listed non-Registry builtin

For the 11, npx is the vendor's declared ACP distribution and bridging is correct — this PR does not touch them. omp is one of the two non-Registry builtins, so its bridge was chosen by analogy rather than from a declared distribution.

And the package is not an adapter. @oh-my-pi/pi-coding-agent ships bin: {omp: dist/cli.js}; omp acp is the vendor's own entrypoint (packages/coding-agent/src/commands/acp.ts, built on @agentclientprotocol/sdk), and the vendor publishes standalone binaries per release. Contrast pi-acp ("ACP adapter for pi coding agent") or @autohandai/autohand-acp ("ACP adapter for the Autohand CLI"), where binary_name names a different CLI the package wraps and the PATH gate is genuinely required.

The local binary was already mandatory. binary_name: "omp" makes probe_resolved_command fail the row with PrimaryMissing when omp is absent, and cli_probe::validate_with_budget already runs the local omp --version. Confirmed on a simulated clean machine (HOME pointed at an empty dir, minimal PATH):

c9e8a2f4   omp   Builtin   missing   CLI `omp` not on $PATH

So the row required a local install, probed it, executed it — and then spawned a different copy through npx.

What that cost, spawn to initialize response:

cold npx cache warm local CLI
omp 81.0s 10.0s 0.7s

81s on a fast link, against a 30s handshake budget — the failure reported in iOfficeAI/AionUi#4009.

What changed

039_omp_direct_cli_launch.sql sets command='omp', args=["acp"], agent_source_info={"binary_name":"omp"} (bridge dropped). The release-lock entry goes with it, and the two lock-count assertions fall to 12.

Written as an UPDATE, not a re-seed. agent_capabilities and auth_methods hold what a live handshake learned on the user's own install; an ON CONFLICT DO UPDATE that lists them resets that to an integration-time snapshot (dead code on a fresh row, silent data loss on an existing one — the migration-023 shape). An UPDATE of the launch columns cannot reach those columns at all, so the guarantee is structural rather than review-dependent.

Verification

Real-path check, doctor run from this branch's build against a freshly migrated DB:

before:  c9e8a2f4  omp  Builtin  available  npx
after:   c9e8a2f4  omp  Builtin  available  /Users/zhoukai/.bun/bin/omp

Catalogue still 43 rows, availability unchanged at 41/2, and pi / mimo-code still resolve to npx — the change is scoped to omp. Seeded row after 039:

omp|omp|["acp"]|{"binary_name":"omp"}|[".omp/skills",".claude/skills"]
  • cargo test -p aionui-db -p aionui-runtime -p aionui-ai-agent — all green (331 / 12 suites / 939 + 38)
  • cargo clippy on those three with -D warnings — clean
  • cargo fmt --all -- --check — clean
  • just migration-check — passed
  • Written test-first: both row assertions were watched failing for the right reason (command was Some("npx"); the lock still carried omp). The third test is a guard that passes before and after — its job is to catch a re-seed clobbering the probed handshake columns.
  • Local workspace nextest not run (work-hours policy); CI's Test check is the authority.

Trade-off

omp's version is no longer pinned by acp-registry-npx-lock.json — it now tracks whatever the user has installed, exactly as the other direct-CLI builtins (qwen, agy) do. Version upkeep moves to the VERIFIED_* path.

Not in scope

  • The other 12 npx rows stay. For the 11 Registry-listed ones, npx is the declared distribution and bridging is correct as-is. glm-acp-agent is a different shape again — a pure ACP package with no separate product CLI, whose binary_name gate looks questionable but which should drop the gate, not go direct; left for its own change with its own evidence.
  • mimo-code stays on npx. Same non-Registry status, but its cold start is 16.0s (warm 3.6s) — inside the budget, so there is no failure to fix. Its npm package is a launcher that resolves a 95 MB platform binary, and the vendor's postinstall recommends a native install over npm; that is worth revisiting, but not under a bug fix.
  • Install-path detection. platform_extra_bins() covers .cargo/bin, go/bin, .deno/bin, .local/bin, .volta/bin and nvm — but not ~/.bun/bin (where omp lands via bun) or ~/.mimocode/bin (where mimo's own installer puts it). A user who follows the vendor's install and lacks that directory in their login-shell PATH still gets a hidden row. That is the broader half of AionUi#4009 proposal 1 and affects every agent, so it belongs in its own change.

Migration number 039 is contested

039 is currently claimed by three open PRs — this one, #644 (039_project_knowledge.sql) and #815 (039_user_scope_assistant_ids.sql) — and 038 is likewise claimed by #815, #644 and the sidebar stack. Whichever lands first takes the number; the others must rebase and rename.

This is caught, not silent: scripts/migration/check-immutability.sh rejects duplicate numeric prefixes. Verified by putting both 039 files in a scratch checkout of main:

Duplicate database migration versions are not allowed.
Duplicate versions:
39: 039_project_knowledge.sql, 039_omp_direct_cli_launch.sql

(exit 1). So if another 039 merges first, this PR's CI turns red on rebase and the fix is a one-file rename — no risk of two different 039s reaching a release. Renumbering pre-emptively would not help: #644 also claims 040 and 041.

Closes iOfficeAI/AionUi#4009

Scope note on that link: the issue's timeout and npm-cache halves are covered (the first by #854, the second already shipped), and its primary ask — use the installed omp instead of forcing npx — is what this PR does. What it does NOT add is a scan of extra install locations such as %LOCALAPPDATA%\omp: detection still goes through the app's resolved PATH, so an omp that is installed but not on PATH stays hidden. That gap is agent-agnostic and tracked separately.

Migration 031 seeded omp as `npx -y @oh-my-pi/pi-coding-agent acp` with
`binary_name: "omp"`, copying the shape the Registry-listed npx rows use.
That shape does not fit omp, for two independent reasons.

There is no Registry entry to conform to. Audited against the public ACP
Registry catalogue, 11 of the 13 npx rows match their Registry entry's
package and args exactly — for those, npx IS the vendor's declared ACP
distribution and bridging is correct. omp and mimo-code are the only
non-Registry builtins, so omp's bridge was chosen by analogy rather than
from a declared distribution.

And the package is not an adapter. `@oh-my-pi/pi-coding-agent` ships bin
`omp`; `omp acp` is the vendor's own entrypoint, and the vendor also
publishes standalone binaries. Meanwhile `binary_name: "omp"` already made
a local `omp` on $PATH mandatory — `probe_resolved_command` fails the row
with `PrimaryMissing` without one, and `cli_probe::validate_with_budget`
already runs the local `omp --version`. So the bridge re-downloaded a CLI
the user had to have installed before the row was even offered.

Measured spawn to `initialize` response: 81.0s on a cold npx cache and
10.0s warm, against 0.7s for the local binary. The cold figure is from a
fast link and exceeded the 30s handshake budget outright, which is the
failure reported in iOfficeAI/AionUi#4009.

039 is written as an UPDATE of the launch columns rather than a re-seed:
`agent_capabilities` and `auth_methods` hold what a live handshake learned
on the user's install, and an `ON CONFLICT DO UPDATE` listing them resets
that to an integration-time snapshot. An UPDATE cannot reach them at all.

Version pinning follows the launch path off the bridge: the release-lock
entry is dropped and the two lock-count assertions fall to 12, so omp now
tracks the user's installed CLI exactly as qwen and agy do. The omp case
leaves the npx migration test for a dedicated one, and the team-capability
case moves out of that file's npx grouping.

Refs iOfficeAI/AionUi#4009
@kaizhou-lab
kaizhou-lab merged commit 13b5dd4 into main Aug 14, 2026
6 checks passed
@kaizhou-lab
kaizhou-lab deleted the fix/omp-direct-cli-launch branch August 14, 2026 12:24
kaizhou-lab added a commit that referenced this pull request Aug 14, 2026
…d versions (#859)

## Summary

Scheduled ACP Registry version sync. Four npx pins drifted since #848,
each backed by a fresh serial ACP probe of the exact pinned version.
Lock-only change — four lines; no metadata, migration, or entrypoint
edits, and no lock-derived test assertion embeds any of these versions.

| backend | package | old → new | initialize | session/new |
|---|---|---|---|---|
| dimcode | `dimcode` | 0.3.12 → **0.3.13** | ok (agentInfo version
0.3.13) | auth required (`-32000`, "Provider credentials are required")
|
| dirac | `dirac-cli` | 0.4.35 → **0.4.36** | ok (agentInfo dirac
0.4.36) | success (modes plan/act) |
| grok | `@xai-official/grok` | 1.0.3 → **1.0.4** | ok (protocolVersion
1) | auth required (`-32000`, "no auth method id provided") |
| kilo | `@kilocode/cli` | 7.4.21 → **7.4.22** | ok (agentInfo Kilo
7.4.22) | success |

All four meet the release-lock criterion: `initialize` succeeds and
`session/new` either succeeds or returns a clearly classified
authentication requirement. Probes ran serially with no inherited HOME
or credentials.

The other 7 Registry-pinned packages (autohand, codebuddy, deepagents,
glm-acp-agent, nova, pi, sigit) match the snapshot exactly. Package
names and entrypoint args are unchanged for all 11. Drifted but not
upgraded: none.

**Note on the manifest's shape, unrelated to this bump:** the lock now
holds 12 entries rather than 13 — #855 moved `omp` off the npx bridge to
its local CLI, so it no longer needs a pin. What remains is 11
Registry-pinned packages plus `mimo-code`, the one non-Registry builtin
(no `registry_json_id`), which stays excluded from drift reconciliation.

dimcode continues to self-report `agentInfo.title` as "DimAgent" while
the public Registry card and CDN entry still say "DimCode"
(`dimcode.dev` unchanged), so the seeded display name is untouched —
same standing observation as #837/#848.

## Registry snapshot

- Audit pinned to release tag
[`v2026.08.14-ec4f9f7`](https://cdn.agentclientprotocol.com/registry/v1/v2026.08.14-ec4f9f7/registry.json)
of `agentclientprotocol/registry`, fetched via the versioned CDN path
for reproducibility.
- No newly listed and no delisted agents versus the previous baseline
(38 ids).

## Validation

- `just migration-check` — pass
- `just lint-fix` (`cargo fix` + `clippy --fix --workspace -D warnings`)
— clean
- `just fmt` — clean
- **Local `cargo nextest` intentionally skipped, by standing policy for
lock-only bumps** (established 2026-08-11; #810, #814, #822, #837 and
#848 all merged green under it). The Test check on this PR is the
authority for this change: the merge decision depends on CI rather than
the local run, and this host's load only manufactures timeout-shaped
test failures, which nothing in the local steps above is subject to.

## Logging

No logging changes: lock-only version bumps; existing startup/session
error paths already identify a failing agent by backend.

Co-authored-by: zk <>
piorpua pushed a commit that referenced this pull request Aug 17, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.1.68](v0.1.67...v0.1.68)
(2026-08-17)


### Features

* **codex:** auto-name sessions and label command steps
([#868](#868))
([7aedbbd](7aedbbd))
* **conversation:** mid-turn interjection — deliver messages while a
turn is in flight
([#836](#836))
([484327d](484327d))


### Bug Fixes

* **acp:** give a first-run npx agent room to install before initialize
times out ([#854](#854))
([f6131a4](f6131a4))
* **acp:** stop collapsing agent failures into an opaque -32603
([#869](#869))
([27fc006](27fc006))
* **agents:** launch omp through its local CLI instead of the npx bridge
([#855](#855))
([13b5dd4](13b5dd4))
* **antigravity:** read the HTTP status before parsing the hook decision
([#867](#867))
([60bab79](60bab79))
* **auth:** stop CSRF rejecting agy's PreToolUse callback
([#860](#860))
([1d91312](1d91312))
* **runtime:** find agent CLIs installed by bun and by vendor installers
([#856](#856))
([8881980](8881980))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Auto-detect local omp executable before falling back to npx

1 participant