feat(connect-ui): [VLOP-95] add Pearl Connect (BYOA) agent UI - #116
Conversation
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>
📦 Bundle sizes
Compared against the latest successful |
OjusWiZard
left a comment
There was a problem hiding this comment.
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:8716is the same origin the binary serves the bundle from, so the fetches are same-origin: no CORS preflight, andrequire_local_originpasses. This was my main worry and it's clean.- Both patch bodies (
{harness}and{protected: {mode}, password}) satisfy the server'sextra="forbid"exactly, and the harness path correctly sends no password. - Harness literals match
HARNESSESexactly;GET /settingsreturns{protected: {mode, whitelist}, harness}and nothing else, soConnectSettingsis precise (noversion/macleak). POST /sessionwith no body is fine (the server'sSessionRequestis 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.
Review —
|
… 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>
|
Second review round addressed in 48a1a00:
32 tests, 100% coverage, lint + build green. 🤖 Generated with Claude Code |
Tanya-atatakai
left a comment
There was a problem hiding this comment.
Re-review — all four items from the previous review are addressed and verified:
- Whitelist label map deleted —
whitelistLabels.tsgone; whitelist renders address+chain as-is from BE (read-only, no client-side drift). - Stale
TBDcomment inuseSettingsremoved. - Claude icons removed —
iconfield +<img>gone fromCodingTool;public/logos/deleted. - Pearl styling adopted —
theme.tsnow 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
left a comment
There was a problem hiding this comment.
Verified against the connect server API (head ba3cc2f): the three earlier compatibility issues are resolved.
SettingsPatch.protectednow exposes onlymode?— nowhitelist?, matching the server's frozen-whitelistProtectedPatch(422WHITELIST_FROZEN).mockSettings.tsmarketplace addresses now match the server'sdefault_whitelist()byte-for-byte across gnosis / base / polygon / optimism.- The stale client-side label map is removed;
WhitelistedAddresses.tsxrenders 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.
Summary
New
connect-uiapp — the embedded agent UI (Profile view) for Pearl Connect (BYOA), served by thepearl-connectbinary at127.0.0.1:8716and iframed by Pearl like the other agent UIs. Dev port 4500, preview 4600.Implements the Profile-tab Figma designs:
POST /session. Alaunched: falseresponse (deep link not handled) surfaces the server's error as a dismissable alert; 503 shows a "still starting up" message.harnesspreference — no password, per the backend design.PATCH {protected: {mode}, password}. Handles 401 (wrong password) and 429 (rate-limited) inline.Screenshots
API contract
Mirrors valory-xyz/connect#7 + #8 (open, stacked): nested
{protected: {mode, whitelist}, harness}settings shape, JSON merge-patchPATCH /settings(password gatesprotectedonly), on-demandPOST /session. If those PRs change during review, all shapes live insrc/types.ts.POST /sessionstartup 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
devMockpattern —IS_MOCK_ENABLED=trueruns the full UI against stateful mocks (mode/harness changes persist across the invalidation refetch), so it's demoable before the binary ships.Testing
collectCoverageFrom)Not in this PR
v*-connecttag) — pending team confirmation of the tag conventionGET /(backend task)agents.tsentry,AGENT_UI_RELEASESpin🤖 Generated with Claude Code