feat: canonical workspace tab IDs with URL routing and draft agent tabs

Rewrite workspace tab management to use stable tab IDs (agent_, terminal_, draft_, file_) with
dedicated /tab/[tabId] routes, replace separate file-tabs store with unified workspace-tabs store,
support multiple concurrent draft agent tabs, and detect text files by content instead of extension allowlist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Mohamed Boudra
2026-03-03 20:11:55 +07:00
co-authored by Claude Opus 4.6
parent 97f0f4b266
commit 73eabd2eea
17 changed files with 1732 additions and 768 deletions
@@ -11,6 +11,7 @@ import {
parseHostDraftRouteFromPathname,
parseHostWorkspaceAgentRouteFromPathname,
parseHostWorkspaceFileRouteFromPathname,
parseHostWorkspaceTabRouteFromPathname,
parseHostWorkspaceTerminalRouteFromPathname,
parseHostWorkspaceRouteFromPathname,
} from "./host-routes";
@@ -73,6 +74,15 @@ describe("workspace route parsing", () => {
});
});
it("parses workspace route for /tab targets", () => {
expect(
parseHostWorkspaceRouteFromPathname("/h/local/workspace/L3RtcC9yZXBv/tab/draft_abc123")
).toEqual({
serverId: "local",
workspaceId: "/tmp/repo",
});
});
it("parses workspace file route", () => {
const encodedPath = encodeFilePathForPathSegment("src/index.ts");
expect(
@@ -110,6 +120,18 @@ describe("workspace route parsing", () => {
});
});
it("parses workspace tab route", () => {
expect(
parseHostWorkspaceTabRouteFromPathname(
"/h/local/workspace/L3RtcC9yZXBv/tab/draft_abc123"
)
).toEqual({
serverId: "local",
workspaceId: "/tmp/repo",
tabId: "draft_abc123",
});
});
it("still parses legacy percent-encoded workspace routes", () => {
expect(
parseHostWorkspaceAgentRouteFromPathname(