Skip to content

Commit ab19f2a

Browse files
authored
fix: don't fall back to expanded_directory for URI handler opens (#865)
When the URI handler is invoked without a folder parameter, it should open a bare remote window rather than falling back to the agent's expanded_directory. This restores pre-v1.10.0 behavior for URI-based opens while preserving the fallback for sidebar and interactive opens. Fixes #843
1 parent df3d773 commit ab19f2a

File tree

4 files changed

+76
-43
lines changed

4 files changed

+76
-43
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Change Log
22

3+
## Unreleased
4+
5+
### Fixed
6+
7+
- URI handler no longer falls back to the agent's `expanded_directory` when the `folder`
8+
query parameter is absent. An absent `folder` now opens a bare remote window, restoring
9+
pre-v1.10.0 behavior.
10+
311
## [v1.14.2-pre](https://github.com/coder/vscode-coder/releases/tag/v1.14.2-pre) 2026-03-26
412

513
### Added

src/commands.ts

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ import {
3636
WorkspaceTreeItem,
3737
} from "./workspace/workspacesProvider";
3838

39+
interface OpenOptions {
40+
workspaceOwner?: string;
41+
workspaceName?: string;
42+
agentName?: string;
43+
folderPath?: string;
44+
openRecent?: boolean;
45+
/** When false, an absent folderPath opens a bare remote window instead of
46+
* falling back to the agent's expanded_directory. Defaults to true. */
47+
useDefaultDirectory?: boolean;
48+
}
49+
50+
const openDefaults = {
51+
openRecent: false,
52+
useDefaultDirectory: true,
53+
} as const satisfies Partial<OpenOptions>;
54+
3955
export class Commands {
4056
private readonly logger: Logger;
4157
private readonly pathResolver: PathResolver;
@@ -437,27 +453,19 @@ export class Commands {
437453
throw new Error("You are not logged in");
438454
}
439455
if (item instanceof AgentTreeItem) {
440-
await this.openWorkspace(
441-
baseUrl,
442-
item.workspace,
443-
item.agent,
444-
undefined,
445-
true,
446-
);
456+
await this.openWorkspace(baseUrl, item.workspace, item.agent, {
457+
openRecent: true,
458+
});
447459
} else if (item instanceof WorkspaceTreeItem) {
448460
const agents = await this.extractAgentsWithFallback(item.workspace);
449461
const agent = await maybeAskAgent(agents);
450462
if (!agent) {
451463
// User declined to pick an agent.
452464
return;
453465
}
454-
await this.openWorkspace(
455-
baseUrl,
456-
item.workspace,
457-
agent,
458-
undefined,
459-
true,
460-
);
466+
await this.openWorkspace(baseUrl, item.workspace, agent, {
467+
openRecent: true,
468+
});
461469
} else {
462470
throw new TypeError("Unable to open unknown sidebar item");
463471
}
@@ -523,13 +531,16 @@ export class Commands {
523531
* Throw if not logged into a deployment or if a matching workspace or agent
524532
* cannot be found.
525533
*/
526-
public async open(
527-
workspaceOwner?: string,
528-
workspaceName?: string,
529-
agentName?: string,
530-
folderPath?: string,
531-
openRecent?: boolean,
532-
): Promise<boolean> {
534+
public async open(options: OpenOptions = {}): Promise<boolean> {
535+
const {
536+
workspaceOwner,
537+
workspaceName,
538+
agentName,
539+
folderPath,
540+
openRecent,
541+
useDefaultDirectory,
542+
} = { ...openDefaults, ...options };
543+
533544
const baseUrl = this.extensionClient.getAxiosInstance().defaults.baseURL;
534545
if (!baseUrl) {
535546
throw new Error("You are not logged in");
@@ -556,13 +567,11 @@ export class Commands {
556567
return false;
557568
}
558569

559-
return this.openWorkspace(
560-
baseUrl,
561-
workspace,
562-
agent,
570+
return this.openWorkspace(baseUrl, workspace, agent, {
563571
folderPath,
564572
openRecent,
565-
);
573+
useDefaultDirectory,
574+
});
566575
}
567576

568577
/**
@@ -749,9 +758,16 @@ export class Commands {
749758
baseUrl: string,
750759
workspace: Workspace,
751760
agent: WorkspaceAgent,
752-
folderPath: string | undefined,
753-
openRecent = false,
761+
options: Pick<
762+
OpenOptions,
763+
"folderPath" | "openRecent" | "useDefaultDirectory"
764+
> = {},
754765
): Promise<boolean> {
766+
const { openRecent, useDefaultDirectory } = {
767+
...openDefaults,
768+
...options,
769+
};
770+
let { folderPath } = options;
755771
const remoteAuthority = toRemoteAuthority(
756772
baseUrl,
757773
workspace.owner_name,
@@ -765,7 +781,7 @@ export class Commands {
765781
newWindow = false;
766782
}
767783

768-
if (!folderPath) {
784+
if (!folderPath && useDefaultDirectory) {
769785
folderPath = agent.expanded_directory;
770786
}
771787

src/uri/uriHandler.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,14 @@ async function handleOpen(ctx: UriRouteContext): Promise<void> {
9292

9393
let opened = false;
9494
try {
95-
opened = await commands.open(
96-
owner,
97-
workspace,
98-
agent ?? undefined,
99-
folder ?? undefined,
95+
opened = await commands.open({
96+
workspaceOwner: owner,
97+
workspaceName: workspace,
98+
agentName: agent ?? undefined,
99+
folderPath: folder ?? undefined,
100100
openRecent,
101-
);
101+
useDefaultDirectory: false,
102+
});
102103
} finally {
103104
// Clear the pending chat ID if commands.open() did not
104105
// actually open a window (user cancelled, or it threw).

test/unit/uri/uriHandler.test.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,14 @@ describe("uriHandler", () => {
134134
);
135135

136136
expect(deploymentManager.setDeployment).toHaveBeenCalled();
137-
expect(commands.open).toHaveBeenCalledWith("o", "w", "a", "/f", true);
137+
expect(commands.open).toHaveBeenCalledWith({
138+
workspaceOwner: "o",
139+
workspaceName: "w",
140+
agentName: "a",
141+
folderPath: "/f",
142+
openRecent: true,
143+
useDefaultDirectory: false,
144+
});
138145
});
139146

140147
it.each([
@@ -146,13 +153,14 @@ describe("uriHandler", () => {
146153
const { handleUri, commands } = createTestContext();
147154
const query = `owner=o&workspace=w&${param}&url=${encodeURIComponent(TEST_URL)}`;
148155
await handleUri(createMockUri("/open", query));
149-
expect(commands.open).toHaveBeenCalledWith(
150-
"o",
151-
"w",
152-
undefined,
153-
undefined,
154-
expected,
155-
);
156+
expect(commands.open).toHaveBeenCalledWith({
157+
workspaceOwner: "o",
158+
workspaceName: "w",
159+
agentName: undefined,
160+
folderPath: undefined,
161+
openRecent: expected,
162+
useDefaultDirectory: false,
163+
});
156164
});
157165

158166
it("opens chat when chatId is present and open succeeds", async () => {

0 commit comments

Comments
 (0)