@@ -6,7 +6,7 @@ import { makeCoderSdk, needToken } from "./api"
6
6
import { extractAgents } from "./api-helper"
7
7
import { CertificateError } from "./error"
8
8
import { Storage } from "./storage"
9
- import { AuthorityPrefix , toSafeHost } from "./util"
9
+ import { toRemoteAuthority , toSafeHost } from "./util"
10
10
import { OpenableTreeItem } from "./workspacesProvider"
11
11
12
12
export class Commands {
@@ -499,6 +499,26 @@ export class Commands {
499
499
await openWorkspace ( baseUrl , workspaceOwner , workspaceName , workspaceAgent , folderPath , openRecent )
500
500
}
501
501
502
+ /**
503
+ * Open a devcontainer from a workspace belonging to the currently logged-in deployment.
504
+ *
505
+ * Throw if not logged into a deployment.
506
+ */
507
+ public async openDevContainer ( ...args : string [ ] ) : Promise < void > {
508
+ const baseUrl = this . restClient . getAxiosInstance ( ) . defaults . baseURL
509
+ if ( ! baseUrl ) {
510
+ throw new Error ( "You are not logged in" )
511
+ }
512
+
513
+ const workspaceOwner = args [ 0 ] as string
514
+ const workspaceName = args [ 1 ] as string
515
+ const workspaceAgent = undefined // args[2] is reserved, but we do not support multiple agents yet.
516
+ const devContainerName = args [ 3 ] as string
517
+ const devContainerFolder = args [ 4 ] as string
518
+
519
+ await openDevContainer ( baseUrl , workspaceOwner , workspaceName , workspaceAgent , devContainerName , devContainerFolder )
520
+ }
521
+
502
522
/**
503
523
* Update the current workspace. If there is no active workspace connection,
504
524
* this is a no-op.
@@ -536,10 +556,7 @@ async function openWorkspace(
536
556
) {
537
557
// A workspace can have multiple agents, but that's handled
538
558
// when opening a workspace unless explicitly specified.
539
- let remoteAuthority = `ssh-remote+${ AuthorityPrefix } .${ toSafeHost ( baseUrl ) } --${ workspaceOwner } --${ workspaceName } `
540
- if ( workspaceAgent ) {
541
- remoteAuthority += `.${ workspaceAgent } `
542
- }
559
+ const remoteAuthority = toRemoteAuthority ( baseUrl , workspaceOwner , workspaceName , workspaceAgent )
543
560
544
561
let newWindow = true
545
562
// Open in the existing window if no workspaces are open.
@@ -598,3 +615,32 @@ async function openWorkspace(
598
615
reuseWindow : ! newWindow ,
599
616
} )
600
617
}
618
+
619
+ async function openDevContainer (
620
+ baseUrl : string ,
621
+ workspaceOwner : string ,
622
+ workspaceName : string ,
623
+ workspaceAgent : string | undefined ,
624
+ devContainerName : string ,
625
+ devContainerFolder : string ,
626
+ ) {
627
+ const remoteAuthority = toRemoteAuthority ( baseUrl , workspaceOwner , workspaceName , workspaceAgent )
628
+
629
+ const devContainer = Buffer . from ( JSON . stringify ( { containerName : devContainerName } ) , "utf-8" ) . toString ( "hex" )
630
+ const devContainerAuthority = `attached-container+${ devContainer } @${ remoteAuthority } `
631
+
632
+ let newWindow = true
633
+ if ( ! vscode . workspace . workspaceFolders ?. length ) {
634
+ newWindow = false
635
+ }
636
+
637
+ await vscode . commands . executeCommand (
638
+ "vscode.openFolder" ,
639
+ vscode . Uri . from ( {
640
+ scheme : "vscode-remote" ,
641
+ authority : devContainerAuthority ,
642
+ path : devContainerFolder ,
643
+ } ) ,
644
+ newWindow ,
645
+ )
646
+ }
0 commit comments