Skip to content

feat(manus): adapter for manus.im — 6 read-only commands#1837

Open
LeoLin990405 wants to merge 2 commits into
jackwener:mainfrom
LeoLin990405:feat/manus-adapter
Open

feat(manus): adapter for manus.im — 6 read-only commands#1837
LeoLin990405 wants to merge 2 commits into
jackwener:mainfrom
LeoLin990405:feat/manus-adapter

Conversation

@LeoLin990405
Copy link
Copy Markdown
Contributor

Adds an adapter for Manus, the autonomous AI agent web app at manus.im/app. Closes #1836.

Commands

All read-only, all backed by Manus's Connect-RPC backend at api.manus.im.

Command RPC
manus status UserService/UserInfo + GetAvailableCredits
manus list [--limit N] [--archived] SessionService/ListSessions
manus read <uid> SessionService/ListSessions (filter in-process)
manus credits UserService/GetAvailableCredits
manus connectors [--limit N] ConnectorsService/ListConnectors
manus skills SkillService/ListSkills

Architecture

Cookie-mode adapter. The session_id cookie issued by manus.im is a JWT that Manus's own frontend re-uses as a Bearer token against the cross-origin Connect-RPC backend at api.manus.im. The adapter does the same — each command is one POST inside the manus.im page context with Authorization: Bearer ${session_id cookie}. No DOM scraping, so the surface is resilient to UI re-skins.

--limit is validated against int32.gte_lte constraints client-side so users get a clear ArgumentError (code: ARGUMENT) instead of an opaque server 400.

Scope discipline

Manus's /app route is a pure React SPA — visiting https://manus.im/app/session/<uid> returns HTTP 404, and sidebar items are <div role="button"> with empty href. Because there is no per-session URL and no confirmation dialog for destructive actions, the following are deliberately out of scope (no verifiable post-state to assert against):

  • manus open <uid>
  • manus new-task <prompt> / manus chat <uid> <message>
  • manus pause / resume / cancel <uid>
  • manus delete / archive <uid>

See docs/adapters/browser/manus.md for the full NOT-exposed list and rationale.

Verification

  • clis/manus/manus.test.js — 17 cases:
    • 1× registration (all 6 commands, access: 'read')
    • 1× status (UserInfo + credits merging)
    • 5× list (default archive filter / --archived / --limit body interpolation / --limit 0 / -5 / 1.5 all rejected)
    • 3× read (happy path / uid not found / missing UID argument)
    • 1× credits (8 fields)
    • 2× connectors (all + --limit)
    • 1× skills (user-added with source=user)
    • 1× auth error propagation
    • isManusUrl URL parser
  • npm run test:adapter — 380 files / 3731 tests pass.
  • npm run build-manifest — clean, +6 entries (manus/status, manus/list, manus/read, manus/credits, manus/connectors, manus/skills).
  • Live smoke test against a real logged-in Manus account: every command returns real data end-to-end via the Browser Bridge.
$ opencli manus status
- Field: Email           Value: zhongyuelin990405@gmail.com
- Field: Display Name    Value: Lin Zhongyue
- Field: Membership Tier Value: 60
- Field: Total Credits   Value: 12311
- Field: Periodic Credits Value: 12000
- Field: Refresh Credits Value: 300

$ opencli manus list --limit 0
ok: false
error:
  code: ARGUMENT

$ opencli manus connectors --limit 3
- UID: cf19c9d0-…  Name: Apify         Brief: Connect AI agents to thousands…
- UID: 4bca3029-…  Name: Outlook Calendar
- UID: d485c6dd-…  Name: Outlook Mail

Adds an adapter for [Manus](https://manus.im), the autonomous AI agent web
app, with six read-only commands that map onto Manus's Connect-RPC backend
at api.manus.im.

## Commands

- `manus status` — account + headline credits
  (`UserService/UserInfo` + `GetAvailableCredits`)
- `manus list [--limit N] [--archived]` — session list
  (`SessionService/ListSessions`)
- `manus read <uid>` — single-session detail
  (`SessionService/ListSessions`, filter in-process)
- `manus credits` — full credit breakdown
  (`UserService/GetAvailableCredits`)
- `manus connectors [--limit N]` — connectors / integrations
  (`ConnectorsService/ListConnectors`)
- `manus skills` — user-added and system skills
  (`SkillService/ListSkills`)

## Architecture

Cookie-mode adapter. The `session_id` cookie issued by `manus.im` is a JWT
that Manus's frontend already re-uses as a Bearer token against the
cross-origin Connect-RPC backend at `api.manus.im`. The adapter does the
same: each command issues exactly one Connect-RPC POST with
`Authorization: Bearer ${session_id cookie}` from inside the manus.im page
context. No DOM scraping, so the surface is resilient to UI re-skins.

## Scope discipline

Manus's `/app` route is a pure React SPA — visiting
`https://manus.im/app/session/<uid>` returns HTTP 404. Because there is
no per-session URL and no confirmation dialog for destructive actions,
new-task submission, chat replies, archive, delete, and `open <uid>` are
deliberately out of scope: there would be no verifiable post-state to
assert against. See `docs/adapters/browser/manus.md` for the full
NOT-exposed list and rationale.

## Tests

- `clis/manus/manus.test.js`, 16 cases:
  - 1× registration (6 commands, all `access: 'read'`)
  - 1× status (UserInfo + credits merging)
  - 3× list (default archive filter, `--archived`, `--limit` forwarding)
  - 3× read (happy path, not found, missing UID argument)
  - 1× credits (8 fields)
  - 2× connectors (all + `--limit`)
  - 1× skills (user-added)
  - 1× auth error propagation
  - 4× `isManusUrl` URL parser
- `npm run test:adapter` — 381 files / 3739 tests pass.

Live smoke test confirmed against a logged-in Manus account:
`status` / `list` / `read` / `credits` / `connectors` / `skills` all
return real data end-to-end through the Browser Bridge.

Refs: opencli/OpenCLI#1836
Address coder review suggestions (non-blocking, but worth doing pre-merge):
- Reject `--limit 0`, negative, fractional, or `Infinity` for `manus list`
  and `manus connectors`. Manus's Connect-RPC backend enforces the same
  via Buf Validate (`int32.gte_lte`), so failing client-side gives a
  clearer error and avoids a wasted round-trip.
- `manus list` test now asserts the RPC source contains the expected
  `pageSize:1` interpolation and method path, not just that
  `page.evaluate` was called.
- New test case covers the three rejected limit shapes (0 / negative /
  fractional) — verified live via `opencli manus list --limit 0` which
  now exits with `code: ARGUMENT`.

`npx vitest run clis/manus/manus.test.js` — 17/17 pass.
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.

[adapter request] manus.im — autonomous AI agent web app

1 participant