โจ chore(agent): agencyConfig contract + git-over-RPC backend#15542
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
๐ก Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97fd736e89
โน๏ธ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with ๐.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codecov Reportโ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## canary #15542 +/- ##
==========================================
- Coverage 70.57% 70.56% -0.01%
==========================================
Files 3303 3303
Lines 326110 326141 +31
Branches 29763 29767 +4
==========================================
Hits 230140 230140
- Misses 95787 95818 +31
Partials 183 183
Flags with carried forward coverage won't be shown. Click here to find out more.
๐ New features to boost your workflow:
|
โฆTarget Type-only contract for the unified per-device working-directory work. Adds `workingDirByDevice` (per-device cwd) and `executionTarget` to agencyConfig. No runtime logic consumes them yet โ the server/client wiring lands in the UI PR so it can be validated as one unit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
โฆimpl Backend/RPC capability for "git branch / changes / PR for remote devices". Dormant โ no client caller yet; merging changes no existing behavior. - `@lobechat/local-file-shell/git`: repoType + branch / linked-PR / working-tree / ahead-behind + `gitInfo` aggregate + `DeviceGitInfo` type (desktop + CLI). - desktop `GitCtr.gitInfo()` (@IpcMethod) delegates to it; registered in GatewayConnectionCtr's RPC dispatch. `utils/git` re-exports the helpers. - server: `deviceGateway.gitInfo()` wrapper + `device.gitInfo` TRPC query. - `@lobechat/types`: `DeviceGitInfo` shape. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
97fd736 to
331cba7
Compare
โฆe UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
โฆhell Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
โฆe UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
โฆe UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ba5611a to
92383e3
Compare
โฆe UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
deviceGateway is a device-scoped gateway client (status/list/tool-call/git/ workspace RPC), not tool-execution-specific. Move it out of toolExecution/ into its own services/deviceGateway/ and update all import sites. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
92383e3 to
a3cc180
Compare
โฆe UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
โฆe UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
โฆe UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
โฆe UI (#15543) * โจ feat(agent): unified per-device working directory + execution-device UI Client UI consuming the backend contract (#15542). User-facing โ validate before merge. - New `src/store/device` (SWR fetch + cwd writes) โ single source of device data; `deviceCwd` helper moves here from the chat-input feature layer. - One `WorkingDirectoryPicker` for local + remote (native dialog vs manual path). - Shared `WorkspaceControls` strip composed by both chat-input bars. - GitStatus reads remote git via `useDeviceGitInfo` (read-only). - Execution-device switcher graduates out of labs โ writes only executionTarget. - One-time migration of legacy localStorage recents into device.workingDirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โจ feat(agent): wire executionTargetโruntimeMode + workingDirByDevice cwd The runtime-decision wiring, kept out of the backend contract PR so it's reviewed/validated together with the UI that drives it. - `helpers/executionTarget`: resolveRuntimeMode / executionTarget resolvers. - server tool gate (AgentToolsEngine) derives runtimeMode from `agencyConfig.executionTarget`, with a no-regression fallback to the legacy per-platform runtimeMode. - server cwd precedence (aiAgent resolveWorkspaceInit + hetero dispatch) now consumes `workingDirByDevice[targetDeviceId]`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โ test(agent): cover executionTarget + workingDir helpers; drop dead lab key - Unit-test resolveRuntimeMode / resolveExecutionTarget and the working-dir precedence (locks the web defaultโcloud graduation + legacy fallback) - Remove the now-unused `executionDeviceSwitcher` lab i18n keys (toggle deleted) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): guide web users to the desktop app in the device switcher On web with no remote device, replace the muted "no devices" dead-end with a prominent, clickable download-desktop card (and drop the now-duplicate header link). Desktop keeps the muted hint since local execution is already available. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): fix execution-device copy for desktop + web - Desktop "no devices" hint no longer tells an already-on-desktop user to "install the desktop app" โ just points at `lh connect`. - Tighten the web download-card description to the desktop's real benefit (run on your computer with local file access). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): flatten the web download card to a plain row Drop the outer border/background so it reads as a normal menu row (like the sandbox option), and shorten the description to a single line so the row stops being taller than its neighbours. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): reword download-card desc to "access to your computer" Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โจ feat(agent): add "no device" execution target (plain chat, no run tools) Restores the option to run an agent with no execution environment, lost when the per-platform runtimeMode was unified into executionTarget. Adds `none` to HeteroExecutionTarget (โ runtimeMode `none`), surfaces it at the top of the switcher on both web + desktop, and flips the web default back to `none` so an unconfigured web agent is plain chat again (desktop still defaults to local). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): rename HeteroExecutionTargetโDeviceExecutionTarget, reorder switcher - Rename the type (it now carries `none`, so "device" target fits better than "hetero") across types + helpers + dispatcher + switcher. - Move "no device" to the bottom of the list (real targets first, opt-out last). - Reword the download card to "let agents connect directly to your computer". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): move "no device" back to top, restore EN download copy "No device" sits above the dynamic device rows; keep the EN download-card wording as "Run agents with access to your computer". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): swap switcher icons โ MonitorOff for "no device", Box for sandbox Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): clarify execution-device info tooltip + "no device" desc - Info tooltip now explains the cloud sandbox is provided by the centralized LobeHub Marketplace, and that picking a device makes it the agent's runtime for reading/writing files and operating the computer. - "No device" description now conveys "no device enabled, can't operate a computer" instead of "plain chat". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): move info icon beside the title, shorten "no device" desc - Info tooltip trigger now sits next to the "Execution Device" title instead of right-aligned; the download link stays on the right. - "No device" description trimmed to just "No device enabled". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): zh tooltip wording โ "ๆไพๆๅก" Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): reorder tooltip โ device runtime first, marketplace last Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): trim tooltip โ drop "่ฎพๅค"/devices and trailing period Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): tag the current machine's device row, drop duplicate "This device" When the desktop's own machine appears in the device list, badge that real row with a "This device" tag and hide the generic "This device" (local) option โ no more two entries for the same machine. The local option still shows as a fallback when the machine isn't enrolled in the list yet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ feat(agent): hoist this-machine device above sandbox + auto-bind on first run Switcher-only (no routing/dispatch changes): - Order is now: no device โ this device โ cloud sandbox โ other devices. - On desktop, when this machine is enrolled and online and the agent has no explicit target yet, default to it and persist the binding once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): widen gap between execution-device rows Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): hide "Get Desktop App" link on desktop Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): capitalize "Cloud Sandbox" label Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ feat(agent): web working-dir entry via "Add folder" modal instead of inline input The browser folder picker can't yield an absolute path (sandboxed handle), so on web / a remote device the working directory is entered manually. Replace the inline input with an "Add folderโฆ" row that opens a modal for absolute-path entry; the local desktop machine still opens the native folder dialog. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โป๏ธ refactor(agent): split working-dir footer into local/remote row components Replace the scattered `isLocalDevice ?` forks (icon, label, handler) with one branch that picks between two self-contained rows: ChooseLocalFolderRow (native dialog) and AddRemoteFolderRow (absolute-path modal). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): use the device default cwd as the add-folder placeholder Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โจ feat(agent): validate manually-entered working dir via device statPath RPC Web / remote clients can't browse the target device's filesystem, so the "Add folder" modal now checks the typed path on the device before binding it. New `statPath` device RPC mirrors gitInfo end-to-end: - desktop WorkspaceCtr.statPath (fs.stat โ exists / isDirectory) + RPC dispatch - server deviceGateway.statPath + device.statPath tRPC (invokeRpc relay) - modal blocks on a definitive negative (not found / not a directory); an unreachable device is treated as "can't verify" and allowed through Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โป๏ธ refactor(agent): route statPath through deviceService, not lambdaClient Components shouldn't import lambdaClient directly โ add a thin deviceService wrapping device.statPath, and call it from the working-dir picker. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โป๏ธ refactor(i18n): move working-directory strings from plugin to a device ns The working-directory / git control-bar strings (53 keys) were lumped under the `plugin` namespace. Move them to a dedicated `device` namespace and drop the now-redundant `localSystem.` prefix (`plugin:localSystem.workingDirectory.X` โ `device:workingDirectory.X`). Updates the 4 consumer components; the `device` ns auto-registers via defaultResources. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โป๏ธ refactor(agent): route all device TRPC calls through deviceService Components/hooks/stores shouldn't reach into lambdaClient.device.* directly. Expand deviceService with listDevices/updateDevice/listGitBranches/ checkoutGitBranch/checkCapability/getAgentProfile and migrate every imperative call site (device store, BranchSwitcher, CreatePlatformAgent, the remote-agent guard, RemoteAgentConfigCard) + the DeviceListItem type. lambdaQuery.device.* React-Query hooks are left as-is (a different pattern). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โจ feat(agent): pull/push a remote device's branch over RPC Wire git pull/push through the device's pullGitBranch/pushGitBranch RPC so the web/remote GitStatus bar can sync, not just the local desktop over IPC. Shows the pull/push affordances for remote devices too. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โป๏ธ refactor(agent): route git pull/push through deviceService too Add pullGitBranch/pushGitBranch to deviceService and switch GitStatus off the direct lambdaClient.device.* calls, so no component reaches the device router directly anymore. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ fix(agent): detect repoType for manually-added working dirs A directory added via the "Add folder" modal committed without a repoType, so a GitHub repo showed a plain folder icon. statPath now also returns the git repo type (detected on the target device); the modal threads it into the committed entry. Collapses the modal's separate validate+submit into one onSubmit that validates and enriches in a single round-trip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ style(agent): create new branch via a modal instead of inline footer "Checkout new branchโฆ" now opens a focused modal (branch-name input + create) rather than expanding an inline footer inside the branch dropdown. Always creates + checks out the branch โ no checkout/overwrite options. Errors show inline in the modal; drops the dead inline-create state/styles. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โป๏ธ refactor(agent): route all git ops through a unified gitService Pick Electron IPC vs device RPC inside the service so UI / store / hooks stay transport-agnostic. Replace the bundled `gitInfo` device RPC with granular reads (branch / linked PR / working-tree / ahead-behind) that mirror the local IPC methods one-to-one, and move the git read SWR hooks into the device store (useFetchGitInfo / WorkingTreeStatus / AheadBehind). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โจ feat(agent): route Review git ops through device RPC (remote-capable) Extend the device-RPC git pipeline to the 4 ops the Review panel needs (getGitWorkingTreePatches / getGitBranchDiff / listGitRemoteBranches / revertGitFile), mirroring the listGitBranches pattern end-to-end: desktop RPC dispatch โ deviceGateway โ device.* tRPC โ gitService. Adds minimal DeviceGit* mirror types to @lobechat/types. Review (useReviewPatches / useGitRemoteBranches / FileItem) now goes through gitService with a deviceId, dropping the isDesktop gate so web/remote devices get the diff + revert too. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ fix(agent): resolve repoType from device store so remote Review tab shows useRepoType now reads the persisted workingDirs[].repoType from the device store (keyed by deviceId), so a remote device's git/github type โ and thus the Review tab visibility โ resolves without a local-only IPC probe. The IPC probe + localStorage fallback are kept only when the target is the local machine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ๐ feat(agent): optimistic branch switch in the branch switcher Flip the displayed branch the instant a checkout is clicked (or a new branch created) instead of waiting for the IPC/RPC round-trip + gitInfo refetch. The git-info SWR cache is optimistically updated and reconciled on completion โ a failed checkout rolls the label back and toasts the error. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * โจ feat: support remote device files panel * ๐ style: restore desktop this-device option * ๐ fix: keep files panel local for this device --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Backend base layer โ pure infrastructure that's safe to merge first because it changes no existing runtime behavior. Two kinds of dormant additions only:
agencyConfig.workingDirByDevice(per-device cwd) +agencyConfig.executionTarget, andDeviceGitInfo. Type declarations; nothing consumes them on this branch.@lobechat/local-file-shell/git(one shared impl), desktopGitCtr.gitInfo()+ RPC dispatch registration,deviceGateway.gitInfo()+device.gitInfoTRPC query. No client caller yet.Change Type
How to Test
bun run type-checkpasses.canaryโ git endpoints are additive and uncalled; agencyConfig fields are unread.Closes LOBE-10094
Part of LOBE-10093