From b35b0af716d0f37d1baf8463c8e20360fd056f39 Mon Sep 17 00:00:00 2001
From: Kyle Carberry <kyle@carberry.com>
Date: Wed, 8 Feb 2023 14:04:41 -0600
Subject: [PATCH] feat: open an agent-defined directory by default

This allows for a magical open-click to open a folder experience!
---
 src/commands.ts  | 67 +++++++++++++++++++++++++++++++-----------------
 src/extension.ts |  3 ++-
 src/remote.ts    |  4 ++-
 yarn.lock        |  2 +-
 4 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/src/commands.ts b/src/commands.ts
index 0f11391c..4db02219 100644
--- a/src/commands.ts
+++ b/src/commands.ts
@@ -1,6 +1,6 @@
 import axios from "axios"
 import { getUser, getWorkspaces, updateWorkspaceVersion } from "coder/site/src/api/api"
-import { Workspace } from "coder/site/src/api/typesGenerated"
+import { Workspace, WorkspaceAgent } from "coder/site/src/api/typesGenerated"
 import * as vscode from "vscode"
 import { Remote } from "./remote"
 import { Storage } from "./storage"
@@ -104,6 +104,7 @@ export class Commands {
   public async open(...args: string[]): Promise<void> {
     let workspaceOwner: string
     let workspaceName: string
+    let folderPath: string | undefined
 
     if (args.length === 0) {
       const quickPick = vscode.window.createQuickPick()
@@ -156,9 +157,20 @@ export class Commands {
       }
       workspaceOwner = workspace.owner_name
       workspaceName = workspace.name
+
+      // TODO: multiple agent support
+      const agents = workspace.latest_build.resources.reduce((acc, resource) => {
+        return acc.concat(resource.agents || [])
+      }, [] as WorkspaceAgent[])
+
+      if (agents.length === 1) {
+        folderPath = agents[0].expanded_directory
+      }
     } else {
       workspaceOwner = args[0]
       workspaceName = args[1]
+      // workspaceAgent is reserved for args[2], but multiple agents aren't supported yet.
+      folderPath = args[3]
     }
 
     // A workspace can have multiple agents, but that's handled
@@ -171,39 +183,46 @@ export class Commands {
       newWindow = false
     }
 
-    const output: {
-      workspaces: { folderUri: vscode.Uri; remoteAuthority: string }[]
-    } = await vscode.commands.executeCommand("_workbench.getRecentlyOpened")
-    const opened = output.workspaces.filter(
-      // Filter out `/` since that's added below.
-      (opened) => opened.folderUri?.authority === remoteAuthority,
-    )
-    if (opened.length > 0) {
-      let selected: (typeof opened)[0]
+    // If a folder isn't specified, we can try to open a recently opened folder.
+    if (!folderPath) {
+      const output: {
+        workspaces: { folderUri: vscode.Uri; remoteAuthority: string }[]
+      } = await vscode.commands.executeCommand("_workbench.getRecentlyOpened")
+      const opened = output.workspaces.filter(
+        // Filter out `/` since that's added below.
+        (opened) => opened.folderUri?.authority === remoteAuthority,
+      )
+      if (opened.length > 0) {
+        let selected: (typeof opened)[0]
 
-      if (opened.length > 1) {
-        const items: vscode.QuickPickItem[] = opened.map((folder): vscode.QuickPickItem => {
-          return {
-            label: folder.folderUri.path,
+        if (opened.length > 1) {
+          const items: vscode.QuickPickItem[] = opened.map((folder): vscode.QuickPickItem => {
+            return {
+              label: folder.folderUri.path,
+            }
+          })
+          const item = await vscode.window.showQuickPick(items, {
+            title: "Select a recently opened folder",
+          })
+          if (!item) {
+            return
           }
-        })
-        const item = await vscode.window.showQuickPick(items, {
-          title: "Select a recently opened folder",
-        })
-        if (!item) {
-          return
+          selected = opened[items.indexOf(item)]
+        } else {
+          selected = opened[0]
         }
-        selected = opened[items.indexOf(item)]
-      } else {
-        selected = opened[0]
+
+        folderPath = selected.folderUri.path
       }
+    }
 
+    if (folderPath) {
       await vscode.commands.executeCommand(
         "vscode.openFolder",
         vscode.Uri.from({
           scheme: "vscode-remote",
           authority: remoteAuthority,
-          path: selected.folderUri.path,
+          path: folderPath,
         }),
         // Open this in a new window!
         newWindow,
diff --git a/src/extension.ts b/src/extension.ts
index 97c703d7..a6078ba6 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -30,6 +30,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
         const owner = params.get("owner")
         const workspace = params.get("workspace")
         const agent = params.get("agent")
+        const folder = params.get("folder")
         if (!owner) {
           throw new Error("owner must be specified as a query parameter")
         }
@@ -45,7 +46,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
         if (token) {
           await storage.setSessionToken(token)
         }
-        vscode.commands.executeCommand("coder.open", owner, workspace, agent)
+        vscode.commands.executeCommand("coder.open", owner, workspace, agent, folder)
       }
     },
   })
diff --git a/src/remote.ts b/src/remote.ts
index df3b076a..21353b93 100644
--- a/src/remote.ts
+++ b/src/remote.ts
@@ -1,6 +1,7 @@
 import axios from "axios"
 import {
   getBuildInfo,
+  getTemplate,
   getWorkspace,
   getWorkspaceBuildLogs,
   getWorkspaceByOwnerAndName,
@@ -134,9 +135,10 @@ export class Remote {
             buildComplete = r
           }),
       )
+      const template = await getTemplate(this.storage.workspace.template_id)
       this.storage.workspace = {
         ...this.storage.workspace,
-        latest_build: await startWorkspace(this.storage.workspace.id),
+        latest_build: await startWorkspace(this.storage.workspace.id, template.active_version_id),
       }
     }
 
diff --git a/yarn.lock b/yarn.lock
index a4143900..f0a31e41 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1418,7 +1418,7 @@ co@3.1.0:
 
 "coder@https://github.com/coder/coder":
   version "0.0.0"
-  resolved "https://github.com/coder/coder#8a5760a2fea074fda65d199620aaa9ed447e7c8d"
+  resolved "https://github.com/coder/coder#7a1731b6205d9c68f6308ee362ff2d62124b6950"
 
 collapse-white-space@^1.0.2:
   version "1.0.6"