Skip to content

Commit 5fa3ac0

Browse files
committed
feat(lsp): add SFTP remote runtime provider for LSP workspaces
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
1 parent 43e2cf7 commit 5fa3ac0

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

src/cm/lsp/runtimes/registerBuiltins.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { registerRuntimeProvider } from "../runtimeProviders";
22
import builtinAlpineRuntimeProvider from "./builtinAlpine";
33
import externalWebSocketRuntimeProvider from "./externalWebSocket";
44
import webWorkerRuntimeProvider from "./webWorker";
5+
import { sftpRemoteRuntimeProvider } from "./sftpRemote";
56

67
registerRuntimeProvider(builtinAlpineRuntimeProvider, { replace: true });
78
registerRuntimeProvider(externalWebSocketRuntimeProvider, { replace: true });
89
registerRuntimeProvider(webWorkerRuntimeProvider, { replace: true });
10+
registerRuntimeProvider(sftpRemoteRuntimeProvider, { replace: true });
11+

src/cm/lsp/runtimes/sftpRemote.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type {
2+
LspRuntimeProvider,
3+
LspRuntimeContext,
4+
LspRuntimeUriResolutionContext,
5+
TransportDescriptor,
6+
} from "../types";
7+
import { getRuntimeProvider } from "../runtimeProviders";
8+
9+
function sftpUriToFileUri(uri: string): string | null {
10+
const match = /^sftp:\/\/[^/]*(\/.*)$/.exec(uri);
11+
if (!match) return null;
12+
const path = match[1].split("?")[0];
13+
if (!path) return null;
14+
return "file://" + path;
15+
}
16+
17+
export const sftpRemoteRuntimeProvider: LspRuntimeProvider = {
18+
id: "sftp-remote",
19+
label: "SFTP Remote",
20+
priority: -30,
21+
22+
canHandle(server, context) {
23+
const uri = String(context.rootUri || context.uri || "");
24+
return /^sftp:/i.test(uri);
25+
},
26+
27+
resolveUris(server, context: LspRuntimeUriResolutionContext) {
28+
const documentUri = sftpUriToFileUri(context.originalDocumentUri);
29+
const rootUri = context.originalRootUri
30+
? sftpUriToFileUri(context.originalRootUri)
31+
: null;
32+
return { documentUri, rootUri, scope: "workspace" };
33+
},
34+
35+
async start(server, context: LspRuntimeContext): Promise<TransportDescriptor> {
36+
// Delegate transport to external-websocket provider
37+
const external = getRuntimeProvider("external-websocket");
38+
if (!external || !external.start) {
39+
throw new Error("SFTP workspace requires external-websocket transport provider");
40+
}
41+
return external.start(server, context);
42+
},
43+
};

0 commit comments

Comments
 (0)