Repository navigation
fix(projects): create on a server's SSH project; Add Project SSH lists the server's targets - #27331
Conversation
7fa838a to
9f1a4dc
Compare
9f043a9 to
89a2114
Compare
9f1a4dc to
f361c91
Compare
6932c4a to
30c154d
Compare
f361c91 to
0d11eb9
Compare
30c154d to
b7f5009
Compare
…e server's SSH hosts
b7f5009 to
3273689
Compare
📝 Walkthrough
Priority: ➖ Normal Severity of issue fixed: Medium Merge Risk: 🟡 Moderate · up to Projects on a paired server's SSH hosts may show the wrong available agents when the server has several SSH hosts. An old error message can also linger in Add Project. Resolve the agent-detection behavior or explicitly accept it before merging. Pre-merge checks |
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
🟡 Minor · Clear the stale remote error when reopening the remote step. · AddRepoSteps.tsx:99-133
src/renderer/src/components/sidebar/AddRepoSteps.tsx:99-133
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winClear the stale remote error when reopening the remote step.
When server target loading fails,
handleOpenRemoteStepsetsremoteError. A later successful reload does not clear it, so the old message can remain visible under the form. Clear the error when the remote load starts.Suggested fix
const gen = ++remoteGenRef.current setStep('remote') + setRemoteError(null) try {
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
5a71f489-051b-4490-8460-084ee6738b3f
📒 Files selected for processing (37)
src/renderer/src/components/settings/RepositoryHostSetupsSection.tsxsrc/renderer/src/components/sidebar/AddRemoteHostSshFormPanel.tsxsrc/renderer/src/components/sidebar/AddRepoDialog.tsxsrc/renderer/src/components/sidebar/AddRepoDialogStepContent.tsxsrc/renderer/src/components/sidebar/AddRepoRemoteStep.tsxsrc/renderer/src/components/sidebar/AddRepoStartSteps.test.tsxsrc/renderer/src/components/sidebar/AddRepoStartSteps.tsxsrc/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.tssrc/renderer/src/components/sidebar/AddRepoSteps.tsxsrc/renderer/src/components/sidebar/AddServerSshHostDialog.tsxsrc/renderer/src/components/sidebar/NonGitFolderDialog.tsxsrc/renderer/src/components/sidebar/RemoteFileBrowser.tsxsrc/renderer/src/components/sidebar/add-remote-host-ssh-actions.tssrc/renderer/src/components/sidebar/add-repo-local-start-actions.tssrc/renderer/src/components/sidebar/add-repo-server-ssh-targets.tssrc/renderer/src/components/sidebar/repo-header-create-state.test.tssrc/renderer/src/components/sidebar/repo-header-create-state.tssrc/renderer/src/components/sidebar/use-remote-file-browser-listing.test.tssrc/renderer/src/components/sidebar/use-remote-file-browser-listing.tssrc/renderer/src/components/sidebar/use-server-ssh-projects.tssrc/renderer/src/components/sidebar/worktree-list/rows/SectionHeader.tsxsrc/renderer/src/components/sidebar/worktree-list/viewport/VirtualizedWorktreeViewport.tsxsrc/renderer/src/components/sidebar/worktree-list/viewport/virtual-row-context.tssrc/renderer/src/hooks/composer-state/host-runtime-effects.tssrc/renderer/src/hooks/composer-state/runtime-target-selection.tssrc/renderer/src/hooks/composer-state/server-ssh-repo-connect.test.tssrc/renderer/src/hooks/composer-state/workspace-identity-state.tssrc/renderer/src/hooks/use-repo-ssh-gate-resolver.tssrc/renderer/src/i18n/locales/en.jsonsrc/renderer/src/i18n/locales/es.jsonsrc/renderer/src/i18n/locales/fr.jsonsrc/renderer/src/i18n/locales/ja.jsonsrc/renderer/src/i18n/locales/ko.jsonsrc/renderer/src/i18n/locales/zh.jsonsrc/renderer/src/lib/repo-ssh-connection.test.tssrc/renderer/src/lib/repo-ssh-connection.tssrc/renderer/src/store/slices/runtime-environment-ssh-selectors.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.
| // Why: a server-owned repo's connectionId names that server's own SSH target, which this client | ||
| // cannot probe for agents; the server answers for it. | ||
| const isRemote = typeof connectionId === 'string' && !runtimeEnvironmentId |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Detect agents on the selected SSH target through its server.
When runtimeEnvironmentId is set, isRemote becomes false. The agent lookup and detection call then use only that environment ID, not connectionId. Two SSH targets on the same server therefore share one agent list even when their installed agents differ. Route detection through the server for the selected SSH target, and key its result by both environment and target.
ELI5
If your Orca server keeps its own SSH hosts, a computer paired with that server could see projects on those hosts but could not use them. It could not start a new workspace in such a project, and it could not add a new project on one of those hosts. Now it can do both, and the server does the work.
What Changed
1. Creating a workspace in a project on the server's SSH host (#25887)
2. Add Project on the server's SSH hosts (#8489, UI half)
ssh.target-management.v1shows the option disabled with "Update this server to add projects on its SSH hosts". There is never a local fallback.Mechanism
lib/repo-ssh-connection.ts, answers "which machine owns this repo's SSH target". It returns(environmentId, targetId)for a server's target and(null, targetId)for this client's. The sidebar header, the composer gate and the composer Connect button all use it. It also reads status with the existingselectRuntimeAwareSshStatus.useRemoteRepotakes the selected server. When one is set, it routes list, connect, browse and add through the server RPCs from feat(ssh): a paired client can manage the server's own SSH hosts (ssh.target-management.v1) #27329. The folder browser routes a(server, target)pair the same way.Why
The execution host owns everything about its SSH targets (
docs/reference/ssh-execution-boundary.md). Reading or dialing a server's target from the client was the root cause of both issues. Routing through the server keeps one source of truth.The alternative was to keep adding special cases to each gate. One helper fixes every reader at once.
A server whose capability is unknown or missing gets a disabled option with a reason, never a silent local action (
docs/reference/remote-wire-compatibility.md).Linked Issue
Fixes #25887
Fixes #8489
Builds on #27329 (server RPCs, merged first). Tests and ideas adapted from the community PR #8492 by @jae-heo, credited in the tests.
Visual Proof
Not captured: this run had no local Electron (agent constraint). The new UI reuses existing pieces:
Monitoricon as "Project on SSH host";Strings are translated in all six locales.
Testing
pnpm tc,pnpm lint(owner-routing ratchet 0, runtime-Electron ratchet 0),pnpm run check:code-quality:changedNew tests:
hooks/composer-state/server-ssh-repo-connect.test.tsfails onmain: Connect for a server-owned repo calledwindow.api.ssh.connect. It now asks the server, and local repos are unchanged.lib/repo-ssh-connection.test.tscovers the [Bug]: Remote client can't create workspaces on a server-owned SSH project #25887 gate:AddRepoSteps.default-checkout.test.ts, adapted from fix(ssh): enable server-owned SSH projects in paired clients #8492:use-remote-file-browser-listing.test.ts: a(server, target)pair is browsed by the server.AddRepoStartSteps.test.tsx: the server option is enabled only when supported, otherwise disabled with the update reason.Focused suites:
components/sidebar,hooks,lib,runtime,components/new-workspace,components/settings,i18n,store(2138 files pass).I manually tested these changes locally
Automated tests added/updated, or explained why not below
Review
P0/P1 review by two independent reviewers; see comments.
Agent skill upstream boundary
Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)