Skip to content

feat(settings): group agent profiles by device - #360

Merged
cxxxxxn (cxxxxxn) merged 3 commits into
mainfrom
feat/device-agent-groups-main
Oct 29, 2026
Merged

cxxxxxn (cxxxxxn) merged 3 commits into
mainfrom
feat/device-agent-groups-main

Conversation

@cxxxxxn

Copy link
Copy Markdown
Contributor

Summary

Group Agent Profiles by device and separate device management from Agent preferences. This is a standalone, single-commit PR based on current main; it excludes unrelated alpha history and does not repeat the device rename implementation already merged in #347.

  • Keep online and offline Profiles under their devices, with persistent folding and direct Edit/Delete actions.
  • Show Connect for the disconnected local desktop device, Not connected for other offline devices, and Disconnect in the local device menu.
  • Add a device-fixed, progressive Agent catalogue and configuration flow, preserving drafts when changing harnesses.
  • Avoid unsupported-capability warning flashes while editing and false refresh-failure messages during successful saves; failed post-save refreshes retry without creating duplicate Profiles.
  • Update architecture documentation and remove obsolete UI labels and test mocks.

Contracts and compatibility

GET /api/acp/profiles adds optional, display-only knownDevices metadata. Runtime availability and placement still use connected devices; Chat, Ink, and Utility Agent selection behavior is unchanged. Offline display metadata does not authorize connections or execution.

The migration preserves mainline desktop preference synchronization and uses its accessible semantic foreground tokens. It includes the post-mutation snapshot serialization needed by the save/retry flow, but does not import the separate alpha batch-discovery feature or its endpoint.

Validation

  • pnpm typecheck passed across the repository after restoring mainline dependencies with pnpm install --frozen-lockfile; no dependency manifests or lockfile changed.
  • pnpm format and pnpm lint:fix completed without additional file changes. Lint reports 350 warnings and zero errors.
  • 104 targeted web unit tests passed, covering Settings navigation, device grouping, local connection state, editor capabilities, drafts, save/retry feedback, catalogue loading, and the shared Profile store.
  • All 40 Profile-route tests passed.
  • All 9 Playwright tests in device-agent-settings.spec.ts and settings-components.spec.ts passed, including pointer/touch flows, rename, offline groups, delayed capability loading, and text contrast of at least 4.5:1 across light/dark themes.
  • Localization parity, source license headers, and git diff --check passed.

Remaining limitations

Browser tests render production components with simulated device/desktop IPC data. Real Windows/macOS connection lifecycle and native confirmation dialogs were not validated on physical devices. Narrow-screen name truncation is unchanged. The full repository test suite was not run; validation targets the changed surfaces. No release is included.

Separate device management from Agent settings, preserve offline device groups, and add progressive per-device profile creation. Refine local connection controls, fix asynchronous editor feedback, and remove obsolete discovery UI code.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 29, 2026 04:08

Copilot AI 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.

🟡 Changes recommended

Unresolved bugs leave hidden icon pickers interactive, strand keyboard focus when switching to the chooser, and drop runtime version metadata for disconnected local devices after a server restart.

4 open issues
What changed in this PR

This PR reorganizes Settings around device-grouped Agent Profiles, separating device management from Agent preferences while preserving existing runtime selection behavior.

Changes:

  • Group online and offline Profiles by device, with folding, direct actions, and local desktop connection controls.
  • Add a device-fixed creation flow with preserved harness drafts, capability-aware controls, and refresh-only retries after successful saves.
  • Extend display-only device metadata and update documentation, localization, and tests.
File Description
packages/​shared/​src/​types/​api/​acp.ts Define optional known-device metadata.
docs/​architecture/​agent-profiles.md Document grouped Settings and save/retry behavior.
apps/​web/​src/​utils/​agentletDevice.ts Generalize device resolution for display metadata.
apps/​web/​src/​store/​settingsUiStore.ts Add the Agent settings tab identifier.
apps/​web/​src/​store/​acpProfilesStore.ts Store known devices and serialize post-mutation refreshes.
apps/​web/​src/​store/​acpProfilesStore.test.ts Cover metadata, refresh ordering, and failures.
apps/​web/​src/​i18n/​resources/​zh-CN/​common.json Update Chinese Settings labels.
apps/​web/​src/​i18n/​resources/​en/​common.json Update English Settings labels.
apps/​web/​src/​components/​Settings/​SettingsModal.tsx Separate device management from Agent preferences.
apps/​web/​src/​components/​Settings/​SettingsModal.test.tsx Update navigation and section tests.
apps/​web/​src/​components/​Settings/​agent-profiles/​useDetectedClis.ts Add rechecks, errors, and connection-aware invalidation.
apps/​web/​src/​components/​Settings/​agent-profiles/​useDetectedClis.test.tsx Cover rechecks and stale discovery responses.
apps/​web/​src/​components/​Settings/​agent-profiles/​ExternalAgentsSettings.tsx Integrate grouped Profiles and focused editors.
apps/​web/​src/​components/​Settings/​agent-profiles/​ExternalAgentsSettings.test.tsx Test grouping, offline Profiles, and navigation.
apps/​web/​src/​components/​Settings/​agent-profiles/​DeviceInformation.tsx Add device identity, version, and copy controls.
apps/​web/​src/​components/​Settings/​agent-profiles/​CreateAgentProfile.tsx Add progressive harness selection with retained drafts.
apps/​web/​src/​components/​Settings/​agent-profiles/​ConnectedDevicesSetting.tsx Combine device metadata, Profiles, and desktop controls.
apps/​web/​src/​components/​Settings/​agent-profiles/​ConnectedDevicesSetting.test.tsx Cover offline groups and local connection transitions.
apps/​web/​src/​components/​Settings/​agent-profiles/​ConnectedDeviceRow.tsx Extract foldable device cards and action menus.
apps/​web/​src/​components/​Settings/​agent-profiles/​ConnectedDeviceRow.test.tsx Test device menus and clipboard feedback.
apps/​web/​src/​components/​Settings/​agent-profiles/​CommandProfileForm.tsx Add capability guidance and refresh-only save recovery.
apps/​web/​src/​components/​Settings/​agent-profiles/​AgentProfileEditor.tsx Route creation through the new catalogue flow.
apps/​web/​src/​components/​Settings/​agent-profiles/​AgentProfileEditor.test.tsx Cover drafts, capability loading, and save recovery.
apps/​web/​src/​components/​Settings/​agent-profiles/​AgentIconPicker.tsx Align the avatar tooltip wrapper.
apps/​web/​src/​components/​Settings/​agent-profiles/​AgentIconField.tsx Simplify the icon settings row.
apps/​web/​src/​api/​_routes.ts Correct the Profile route comment; no behavior change.
apps/​web/​e2e/​settings-components.spec.ts Adapt browser tests to navigation and device menus.
apps/​web/​e2e/​device-agent-settings.spec.ts Add grouped-device and progressive-creation browser coverage.
apps/​server/​src/​modules/​agent/​acp/​profiles.route.ts Project offline metadata and persisted device names.
apps/​server/​src/​modules/​agent/​acp/​profiles.route.test.ts Verify offline metadata does not grant availability.

Review effort: Balanced

Comment on lines +140 to +141
if (expanded && profilesRef.current)
dismissPopoversWithin(profilesRef.current);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified again on the latest branch: this is fixed by 15c3fd3. DropdownMenu now registers its trigger as Popover.owner independently of floating positioning, and dismissPopoversWithin checks that owner. The production-browser regression opens the avatar dialog, keyboard-activates the device fold, asserts that the portal is removed and focus stays on the fold button, then re-expands and asserts the picker does not reopen. This passed again in the 10-test Settings browser run. No additional avatar change was needed.

Comment thread apps/web/src/components/Settings/agent-profiles/ConnectedDevicesSetting.tsx Outdated
Keep dropdown ownership independent of positioning, restore chooser focus when detection loses the selection, and fill missing local device metadata without changing availability.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 29, 2026 05:31

Copilot AI 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.

🔵 Needs a closer look

Activating Disconnect with the keyboard closes the menu without restoring focus, leaving focus on the document body even if the confirmation is cancelled.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Restore focus after cancelling keyboard-triggered Disconnect

apps/​web/​src/​components/​Settings/​agent-profiles/​ConnectedDevicesSetting.tsx:224

Closing this menu through dismissPopoversWithin reports ancestor-hidden, which deliberately disables DropdownMenu's focus restoration. If Disconnect is activated with the keyboard, its focused menu item is removed and focus falls back to the document body; cancelling the native confirmation does not restore it either. Close through a controlled menu action and restore focus to the visible device-menu trigger, or to Connect if the legacy standalone menu disappears after disconnect.

3 resolved since last review

Review effort: Balanced

Close device menus through controlled state and restore Connect focus when legacy menus disappear. Cover cancellation, errors, success, and preserved Rename behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 29, 2026 06:06
@cxxxxxn

Copy link
Copy Markdown
Contributor Author

Fixed the newly reported Disconnect focus issue in df9af4d. Device menus now close through controlled open state, preserving DropdownMenu focus restoration after cancellation, failure, and success. Legacy bridges without a device identity fall back to Connect when their menu disappears, without stealing focus from another control. Controlled Rename also closes its menu before editing. Regression tests reproduced all six identity/outcome combinations before the fix and now pass; the browser suite covers keyboard cancellation/success and the previously fixed avatar folding. Repository format, lint:fix (existing warnings only), and typecheck passed; all 10 Settings browser tests passed. Native Electron confirmation is simulated through the IPC fixture, not real-device tested.

Copilot AI 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.

🔵 Needs a closer look

Device reconnects can leave the discovery cache key unchanged, preserving stale capability controls or errors until a manual recheck or editor reopen.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Refresh discovery cache key when agentlet reconnects

apps/​web/​src/​components/​Settings/​agent-profiles/​ExternalAgentsSettings.tsx:227

If a device disconnects and reconnects between snapshot polls, this key stays unchanged: LiveAgentletConnection.handleReconnect() retains the constructor's connectedAt value (external/agenetes/packages/agentlet-gateway/src/connection.ts:169–186). Discovery therefore keeps the previous connection's catalogue or error, potentially leaving stale capability controls until an explicit recheck or reopening the editor. Expose a connection generation or timestamp that advances on reconnect and use it in this key.

Review effort: Balanced

@cxxxxxn
cxxxxxn (cxxxxxn) merged commit af25629 into main Oct 29, 2026
8 checks passed
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.

2 participants