Skip to content

feat(lsp) Adds SFTP URI resolution to the runtime provider for LSP workspaces. - #2703

Open
gat0sy wants to merge 6 commits into
Acode-Foundation:mainfrom
gat0sy:feat/sftp-remote-lsp
Open

feat(lsp) Adds SFTP URI resolution to the runtime provider for LSP workspaces.#2703
gat0sy wants to merge 6 commits into
Acode-Foundation:mainfrom
gat0sy:feat/sftp-remote-lsp

Conversation

@gat0sy

@gat0sy gat0sy commented Aug 8, 2026

Copy link
Copy Markdown

This PR is based on PR #2702

@greptile-apps

greptile-apps Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds SFTP-aware URI resolution and expands LSP navigation, workspace-edit, lifecycle, and settings behavior. Two URI/client association paths remain ambiguous and can route edits or remote files through the wrong LSP or SFTP context.

  • Registers an SFTP runtime that presents remote paths to language servers as file URIs.
  • Adds definition-family navigation, hover file-link handling, and shared text-edit utilities.
  • Handles workspace/applyEdit requests and delays disposal of idle clients.
  • Consolidates custom-server settings and selection-menu LSP actions.

Confidence Score: 3/5

The PR is not yet safe to merge because workspace edits can still use the wrong LSP synchronization state and authority-free file URIs can resolve to the wrong SFTP connection.

The workspace-edit fix retains an arbitrary plugin fallback, while SFTP reverse resolution matches same-path remote roots without preserving the requesting connection identity; these paths can misapply edits or open files from another host.

Files Needing Attention: src/cm/lsp/transport.ts, src/components/referencesPanel/utils.js, src/cm/lsp/runtimes/sftpRemote.ts

Important Files Changed

Filename Overview
src/cm/lsp/transport.ts Adds workspace-edit handling and root checks, but retains an arbitrary plugin fallback that can map edits through the wrong client.
src/cm/lsp/runtimes/sftpRemote.ts Adds SFTP-to-file URI conversion and external-WebSocket delegation while necessarily discarding connection authority from server-facing URIs.
src/components/referencesPanel/utils.js Maps file URIs back to accessible folders, but SFTP reverse resolution chooses the first pathname match without the requesting connection identity.
src/cm/lsp/clientManager.ts Separates SFTP client cache identities by original root and adds initialization, lifecycle, capability, and shared-edit changes.
src/cm/lsp/textEditUtils.ts Centralizes bounded LSP position conversion and unsynchronized-change mapping; correctness depends on receiving the originating plugin.
src/lib/editorManager.js Resolves server-facing file URIs before opening documents, inheriting the ambiguity of the shared SFTP reverse resolver.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  SFTP["SFTP workspace URI<br/>authority + path"] --> Runtime["SFTP runtime"]
  Runtime --> FileURI["file URI<br/>path only"]
  FileURI --> LSP["External LSP server"]
  LSP --> Response["Definition / reference / workspace edit"]
  Response --> Resolve["Resolve against added folders"]
  Resolve --> Target["SFTP target view"]
  Target --> Plugin["Select requesting LSP plugin"]
  Resolve -. "pathname-only first match" .-> WrongHost["Wrong SFTP connection"]
  Plugin -. "fallback to first plugin" .-> WrongClient["Wrong synchronization state"]
Loading

Reviews (2): Last reviewed commit: "feat(lsp): add SFTP remote runtime provi..." | Re-trigger Greptile

Comment thread src/cm/lsp/transport.ts
Comment thread src/cm/lsp/transport.ts Outdated
Comment thread src/cm/lsp/runtimes/sftpRemote.ts
Comment thread src/cm/lsp/runtimes/sftpRemote.ts
gat0sy added 3 commits August 10, 2026 03:38
LspToPosition threw range error on format error.
We attempt to fix it here with by clamping so we get the correct line count between the client and server.

applyTextEdit as also been extracted so both transport and client manager can import it from the helper.
LspToPosition threw range error on format error.
We attempt to fix it here with by clamping so we get the correct line count between the client and server.

applyTextEdit as also been extracted so both transport and client manager can import it from the helper.
go to def and similar fonction have been added,
a new interceptFileLink method has been created to solve an FileUriExposedException you may get if taping the signature link on the hover.

if the link is a website, it skips and let the normal behavior occur ( open a web browser page )
if the link is a file, it modifies the uri so the tap behave like a go to instead of crashing the whole app.
There are notably also some fixes for code actions, rename...ect, now they use the new lspPostionToOffset that uses clamping
@gat0sy
gat0sy force-pushed the feat/sftp-remote-lsp branch from 5fa3ac0 to 3b11814 Compare August 10, 2026 04:39
gat0sy added 3 commits August 10, 2026 05:07
…actions menu

Added resolveContentUriForFileUri() to map LSP file:// responses back to
content:// and sftp:// URIs via addedFolder matching

Refactor editorManager displayFile/openFile to resolve URIs before
opening, enabling cross-workspace go-to-definition and references

Added SFTP path-aware root URI resolution for remote workspace context

Replace selection menu code-actions button with full LSP actions menu
(definition, declaration, implementation, type-definition, references,
rename, code-actions) with single-item auto-execution
Added sftpRemote.ts runtime provider that translates sftp:// URIs to

 file:// before sending to LSP servers, stripping host/credentials

 Register sftpRemoteRuntimeProvider in registerBuiltins.ts
Delegate transport to external-websocket provider since SFTP LSP
connections are handled via WebSocket tunnel
@gat0sy
gat0sy force-pushed the feat/sftp-remote-lsp branch from 3b11814 to ebfcfac Compare August 10, 2026 05:20
@bajrangCoder

This comment was marked as outdated.

Comment thread src/cm/lsp/transport.ts
Comment on lines +258 to +266

// Find the plugin belonging to THIS server, not just any plugin
const allPlugins = LSPPlugin.getAll(view);
const plugin =
allPlugins.find(
(p) => (p.client as {
__acodeServerId?: string
}).__acodeServerId === server.id,
) ?? allPlugins[0];

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.

P1 Workspace edit still uses wrong client

When a workspace edit opens or retrieves a view without the requesting server's plugin, this fallback selects the view's first unrelated plugin. applyTextEdits then maps the server's ranges through that plugin's syncedDoc and unsyncedChanges, causing edits at incorrect offsets or rejecting valid edits.

Knowledge Base Used: LSP Integration

Comment on lines +248 to +275
if (rootUrl.startsWith("sftp:")) {
let parts;
try {
parts = Url.decodeUrl(rootUrl);
} catch {
continue;
}
const rootPath = (parts.pathname || "").replace(/\/+$/, "");
if (!rootPath) continue;

let childPath = null;
if (targetPath === rootPath) {
childPath = rootPath;
} else if (targetPath.startsWith(`${rootPath}/`)) {
childPath = targetPath;
} else {
continue;
}

return Url.formate({
protocol: "sftp:",
hostname: parts.hostname,
username: parts.username,
password: parts.password,
port: parts.port,
path: childPath,
query: parts.query,
});

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.

P1 SFTP responses resolve to wrong connection

When two added SFTP folders have the same remote root path but different connection identities, this pathname-only search reconstructs the server's authority-free file:// URI with the first matching folder's credentials. Definitions, references, tooltip links, and workspace-edited files from the other workspace then open through the wrong SFTP host.

Knowledge Base Used:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants