Skip to content

feat(connect-ui): [VLOP-95] add Pearl Connect (BYOA) agent UI - #116

Merged
atepem merged 4 commits into
mainfrom
feat/connect-ui
Jul 15, 2026
Merged

feat(connect-ui): [VLOP-95] add Pearl Connect (BYOA) agent UI#116
atepem merged 4 commits into
mainfrom
feat/connect-ui

Conversation

@atepem

@atepem atepem commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

New connect-ui app — the embedded agent UI (Profile view) for Pearl Connect (BYOA), served by the pearl-connect binary at 127.0.0.1:8716 and iframed by Pearl like the other agent UIs. Dev port 4500, preview 4600.

Implements the Profile-tab Figma designs:

  • Get started with Connect — "New Connect Session" button → POST /session. A launched: false response (deep link not handled) surfaces the server's error as a dismissable alert; 503 shows a "still starting up" message.
  • Coding tool — Claude Desktop / Claude Code CLI select (filled variant, icons). Patches the harness preference — no password, per the backend design.
  • Transaction mode — Restricted/Unrestricted cards; switching opens a password confirmation modal → PATCH {protected: {mode}, password}. Handles 401 (wrong password) and 429 (rate-limited) inline.
  • Whitelisted addresses — read-only (whitelist is not user-editable by product decision). Well-known contracts render with friendly labels (Mech Marketplace on Gnosis → "Olas Marketplace"); unknown addresses fall back to a truncated address + chain.

Screenshots

Screenshot 2026-07-13 133910 image image

API contract

Mirrors valory-xyz/connect#7 + #8 (open, stacked): nested {protected: {mode, whitelist}, harness} settings shape, JSON merge-patch PATCH /settings (password gates protected only), on-demand POST /session. If those PRs change during review, all shapes live in src/types.ts.

POST /session startup flow context: the binary launches nothing at boot — Pearl polls /healthcheck, then opens the first session itself; this app's button is for subsequent sessions.

Mock mode

All hooks follow the repo devMock pattern — IS_MOCK_ENABLED=true runs the full UI against stateful mocks (mode/harness changes persist across the invalidation refetch), so it's demoable before the binary ships.

Testing

  • 32 tests, 100% statements/branches/functions/lines (per-project jest config with explicit collectCoverageFrom)
  • lint + build green
  • Verified rendering + interactions against the dev server (mock mode): session error alert, harness switch, mode toggle with password modal, whitelist show/hide

Not in this PR

  • Release workflow (v*-connect tag) — pending team confirmation of the tag convention
  • pearl-connect serving the built bundle at GET / (backend task)
  • Pearl (olas-operate-app) integration: agents.ts entry, AGENT_UI_RELEASES pin

🤖 Generated with Claude Code

New app serving the embedded Profile view for the Connect agent
(dev 4500, preview 4600), matching the Pearl 1.0 Figma designs:

- Get started: New Connect Session button -> POST /session; the
  server's launched:false error surfaces as a dismissable alert
- Coding tool: Claude Desktop / Claude Code CLI select with icons;
  PATCHes the harness preference (no password required)
- Transaction mode: Restricted/Unrestricted cards with password
  confirmation modal -> PATCH {protected: {mode}, password}
- Whitelisted addresses: read-only, label map for well-known
  contracts (Mech Marketplace), truncated-address fallback

API contract mirrors pearl-connect PRs #7/#8 (nested protected
settings, JSON merge-patch, on-demand session endpoint). All hooks
follow the repo devMock pattern so the app runs fully mocked with
IS_MOCK_ENABLED=true. 100% coverage across statements/branches/
functions/lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@atepem
atepem requested a review from Tanya-atatakai as a code owner July 13, 2026 14:35
@github-actions

Copy link
Copy Markdown

📦 Bundle sizes

App Total js css png
agentsfun-ui 1844.6 KB (+0.0 KB, +0.0%) 1001.2 KB 0.0 KB 825.8 KB
babydegen-ui 4079.0 KB (+0.0 KB, +0.0%) 1583.4 KB 0.0 KB 2488.0 KB
predict-ui 5255.4 KB (+0.0 KB, +0.0%) 1828.0 KB 0.0 KB 3409.9 KB

Compared against the latest successful main run, not this PR's merge-base — deltas may conflate this PR's change with intervening main commits. Warns at ±10% per-app delta; non-blocking. Sudden bundle growth is a malware canary.

@atepem atepem changed the title feat(connect-ui): add Pearl Connect (BYOA) agent UI feat(connect-ui): [VLOP-95] add Pearl Connect (BYOA) agent UI Jul 13, 2026

@OjusWiZard OjusWiZard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked this against what the pearl-connect server actually serves (built the branch, diffed types.ts + the three hooks against the routes). The request/response wiring is correct — I specifically verified the things most likely to bite:

  • LOCAL = http://127.0.0.1:8716 is the same origin the binary serves the bundle from, so the fetches are same-origin: no CORS preflight, and require_local_origin passes. This was my main worry and it's clean.
  • Both patch bodies ({harness} and {protected: {mode}, password}) satisfy the server's extra="forbid" exactly, and the harness path correctly sends no password.
  • Harness literals match HARNESSES exactly; GET /settings returns {protected: {mode, whitelist}, harness} and nothing else, so ConnectSettings is precise (no version/mac leak).
  • POST /session with no body is fine (the server's SessionRequest is optional), and the 503 / 200-{launched: false, error} / 401 / 429 mappings all land where you expect.

What does not line up is the whitelist display: the sole label is keyed on an address the API never returns, and the default whitelist has four chains rather than one. Details inline. There's also a latent type/API drift on SettingsPatch.protected.whitelist.

Separately, and not this PR's problem: nothing in either repo yet copies dist/apps/connect-ui into pearl_connect/assets/ui, where the server's ui_build_dir() looks for the bundle. That glue still needs a home.

Comment thread apps/connect-ui/src/constants/whitelistLabels.ts Outdated
Comment thread apps/connect-ui/src/mocks/mockSettings.ts Outdated
Comment thread apps/connect-ui/src/types.ts
@Tanya-atatakai

Copy link
Copy Markdown
Contributor

Review — connect-ui vs the pearl-connect backend

API-contract usage is correct. Verified against pearl-connect #7/#8:

  • Shapes in types.ts mirror the nested {protected:{mode,whitelist}, harness} + merge-patch exactly.
  • GET /settings (open), PATCH /settings password-gates protected only — mode goes through the password modal as {protected:{mode}, password} (no whitelist, so it won't hit the frozen-whitelist 422); harness patches as {harness} with no password. ✅
  • POST /session handles 503 ("still starting up"), launched:false → shows the server error, plus 401/429 on settings. ✅
  • LOCAL = http://127.0.0.1:8716 → same-origin, passes the backend's require_local_origin/TrustedHost. ✅
  • Correctly does not touch the bearer-authed endpoints (/wallet, /sign-*, /mcp) — it has no token. Whitelist is read-only, matching the frozen server-side behavior. ✅

A few changes:

1. Delete the hardcoded whitelist label map

src/constants/whitelistLabels.ts hardcodes address → friendly name, but the whitelist is fetched read-only from GET /settings and there's no edit feature yet. This client-side map duplicates BE-owned data: it drifts (the backend derives marketplace addresses from mech-client, which change on upgrade), it's incomplete (only one address mapped — the backend's default_whitelist() returns a marketplace per mech-client chain, so most entries fall back to a truncated address anyway), and there's no design for labeled entries. Suggest removing it and rendering the address (+ chain) as-is; revisit friendly names — ideally supplied by the backend — when whitelist editing is added.

2. Stale TBD comment (nit)

src/hooks/useSettings.ts: // TBD: endpoint path to be confirmed with the pearl-connect backend. — the path is settled (GET /settings, open, per #7). Drop the comment.

3. Claude icons were removed from Figma but are still in the code

CodingTool.tsx renders <img src={/logos/${option.icon}} …> with claude-desktop.svg / claude-cli.svg, and both assets live in public/logos/. Remove the icon field, the <img>, and the two SVGs to match the current Figma.

4. Buttons don't use Pearl styling

The modal buttons (PasswordModal — default "Cancel" + primary "Switch to … mode") render with plain antd styling, and theme.ts sets colorPrimary: '#7C3AED' with an "approximated from Figma; swap for the exact token when available" note. This is the Profile tab rendered inside Pearl, so the buttons/theme should use Pearl's exact design tokens (primary color, button radius/size, secondary/default button style) for visual consistency.

atepem and others added 2 commits July 14, 2026 22:42
… from patch type

Address review on #116:
- whitelistLabels.ts: key the Olas Marketplace label on the real
  Mech Marketplace addresses from mech_client/configs/mechs.json
  (gnosis/base/polygon/optimism) instead of an address the API
  never returns
- mockSettings.ts: mirror the server's default_whitelist() so mock
  mode exercises the same multi-chain list live mode sends
- types.ts: remove protected.whitelist from SettingsPatch — the
  server 422s any whitelist patch (WHITELIST_FROZEN); reads keep it
  via ProtectedSettings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… theme tokens

Address second review round on #116:
- Delete the client-side whitelist label map (BE-owned data that
  drifts on mech-client upgrades); entries render as truncated
  address + chain, full address on hover. Friendly names should come
  from the backend if/when whitelist editing lands. Supersedes the
  map expansion from the previous round.
- Remove Claude harness icons (removed from Figma): icon field,
  optionRender/labelRender, and both SVGs
- Drop stale TBD comment in useSettings (path settled by BE #7)
- theme.ts mirrors Pearl's design tokens (colors.ts + theme.ts in
  olas-operate-app): primary #7E22CE, button hover/active variants,
  default-button border, fontSize 16

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@atepem

atepem commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Second review round addressed in 48a1a00:

  1. Whitelist label map deleted — entries now render as truncated address + chain (full address on hover). Rationale: the whitelist is BE-owned, read-only data; a client-side name map duplicates what the backend derives from mech-client and drifts on upgrades. Note for @OjusWiZard: this supersedes the map expansion from the previous round (ab55b47) — the four mechs.json addresses you supplied now live only in the mock, which still mirrors default_whitelist() so mock and live mode stay in agreement. Friendly names should come from the backend if/when whitelist editing lands. This also resolves the "four identical Olas Marketplace rows" design question from the earlier thread — rows are now distinguishable by address + chain.
  2. Claude harness icons removed (dropped from Figma): icon field, optionRender/labelRender, and both SVGs.
  3. Stale TBD comment dropped in useSettings.tsGET /settings is settled per pearl-connect feat: add predict UI #7.
  4. Pearl design tokens adopted in theme.ts, mirrored from olas-operate-app's theme.ts/colors.ts: primary #7E22CE with Pearl's button hover/active variants, default-button border #dfe6ec, fontSize 16, matching Card/Input/Alert component tokens. The mode-card radio dot uses the same primary.

32 tests, 100% coverage, lint + build green.

🤖 Generated with Claude Code

Tanya-atatakai
Tanya-atatakai previously approved these changes Jul 15, 2026

@Tanya-atatakai Tanya-atatakai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review — all four items from the previous review are addressed and verified:

  1. Whitelist label map deletedwhitelistLabels.ts gone; whitelist renders address+chain as-is from BE (read-only, no client-side drift).
  2. Stale TBD comment in useSettings removed.
  3. Claude icons removedicon field + <img> gone from CodingTool; public/logos/ deleted.
  4. Pearl styling adoptedtheme.ts now mirrors olas-operate-app's tokens (colorPrimary #7E22CE, button hover/active #6a1cb1/#5c1a9e, default border #dfe6ec), so the modal buttons match the host.

API-contract usage against pearl-connect #7/#8 remains correct (nested settings shape, password-gates-protected-only, POST /session 503/launched:false handling, LOCAL same-origin, no token-gated calls). No regressions.

LGTM. 🚀

Tag-triggered release matching the other apps, delegating to the
_build-app.yml reusable workflow (no REACT_APP_AGENT_NAME — connect-ui
does not branch on agent type). Documents the release process and the
pearl-connect consumption path in the app README and CLAUDE.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@OjusWiZard OjusWiZard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified against the connect server API (head ba3cc2f): the three earlier compatibility issues are resolved.

  • SettingsPatch.protected now exposes only mode? — no whitelist?, matching the server's frozen-whitelist ProtectedPatch (422 WHITELIST_FROZEN).
  • mockSettings.ts marketplace addresses now match the server's default_whitelist() byte-for-byte across gnosis / base / polygon / optimism.
  • The stale client-side label map is removed; WhitelistedAddresses.tsx renders addresses directly (no drift on mech-client updates).

Hooks target the correct same-origin endpoints (GET/PATCH /settings, POST /session) with matching status/shape handling. No incompatibilities remain.

@atepem
atepem merged commit d3799b0 into main Jul 15, 2026
11 checks passed
@atepem
atepem deleted the feat/connect-ui branch July 15, 2026 22:08
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.

3 participants