feat: projects → workspaces → tabs

This commit is contained in:
Mohamed Boudra
2026-03-01 18:22:11 +07:00
parent 2e201cab09
commit 080fb74642
43 changed files with 4054 additions and 2654 deletions
+147 -4
View File
@@ -57,7 +57,7 @@ export function parseHostAgentRouteFromPathname(
export function parseHostAgentDraftRouteFromPathname(
pathname: string
): { serverId: string } | null {
const match = pathname.match(/^\/h\/([^/]+)\/agent\/?$/);
const match = pathname.match(/^\/h\/([^/]+)\/(?:agent|new)\/?$/);
if (!match) {
return null;
}
@@ -73,17 +73,151 @@ export function parseHostAgentDraftRouteFromPathname(
}
export function buildHostAgentDraftRoute(serverId: string): string {
return buildHostDraftRoute(serverId);
}
export function parseHostDraftRouteFromPathname(
pathname: string
): { serverId: string } | null {
const match = pathname.match(/^\/h\/([^/]+)\/new\/?$/);
if (!match) {
return null;
}
const encodedServerId = match[1];
if (!encodedServerId) {
return null;
}
const serverId = trimNonEmpty(decodeSegment(encodedServerId));
if (!serverId) {
return null;
}
return { serverId };
}
export function buildHostDraftRoute(serverId: string): string {
const normalized = trimNonEmpty(serverId);
if (!normalized) {
return "/";
}
return `/h/${encodeSegment(normalized)}/agent`;
return `/h/${encodeSegment(normalized)}/new`;
}
export function parseHostWorkspaceRouteFromPathname(
pathname: string
): { serverId: string; workspaceId: string } | null {
const match = pathname.match(/^\/h\/([^/]+)\/workspace\/([^/]+)(?:\/|$)/);
if (!match) {
return null;
}
const [, encodedServerId, encodedWorkspaceId] = match;
if (!encodedServerId || !encodedWorkspaceId) {
return null;
}
const serverId = trimNonEmpty(decodeSegment(encodedServerId));
const workspaceId = trimNonEmpty(decodeSegment(encodedWorkspaceId));
if (!serverId || !workspaceId) {
return null;
}
return { serverId, workspaceId };
}
export function parseHostWorkspaceAgentRouteFromPathname(
pathname: string
): { serverId: string; workspaceId: string; agentId: string } | null {
const match = pathname.match(
/^\/h\/([^/]+)\/workspace\/([^/]+)\/agent\/([^/]+)(?:\/|$)/
);
if (!match) {
return null;
}
const [, encodedServerId, encodedWorkspaceId, encodedAgentId] = match;
if (!encodedServerId || !encodedWorkspaceId || !encodedAgentId) {
return null;
}
const serverId = trimNonEmpty(decodeSegment(encodedServerId));
const workspaceId = trimNonEmpty(decodeSegment(encodedWorkspaceId));
const agentId = trimNonEmpty(decodeSegment(encodedAgentId));
if (!serverId || !workspaceId || !agentId) {
return null;
}
return { serverId, workspaceId, agentId };
}
export function parseHostWorkspaceTerminalRouteFromPathname(
pathname: string
): { serverId: string; workspaceId: string; terminalId: string } | null {
const match = pathname.match(
/^\/h\/([^/]+)\/workspace\/([^/]+)\/terminal\/([^/]+)(?:\/|$)/
);
if (!match) {
return null;
}
const [, encodedServerId, encodedWorkspaceId, encodedTerminalId] = match;
if (!encodedServerId || !encodedWorkspaceId || !encodedTerminalId) {
return null;
}
const serverId = trimNonEmpty(decodeSegment(encodedServerId));
const workspaceId = trimNonEmpty(decodeSegment(encodedWorkspaceId));
const terminalId = trimNonEmpty(decodeSegment(encodedTerminalId));
if (!serverId || !workspaceId || !terminalId) {
return null;
}
return { serverId, workspaceId, terminalId };
}
export function buildHostWorkspaceRoute(
serverId: string,
workspaceId: string
): string {
const normalizedServerId = trimNonEmpty(serverId);
const normalizedWorkspaceId = trimNonEmpty(workspaceId);
if (!normalizedServerId || !normalizedWorkspaceId) {
return "/";
}
return `/h/${encodeSegment(normalizedServerId)}/workspace/${encodeSegment(
normalizedWorkspaceId
)}`;
}
export function buildHostWorkspaceAgentRoute(
serverId: string,
workspaceId: string,
agentId: string
): string {
const base = buildHostWorkspaceRoute(serverId, workspaceId);
const normalizedAgentId = trimNonEmpty(agentId);
if (base === "/" || !normalizedAgentId) {
return "/";
}
return `${base}/agent/${encodeSegment(normalizedAgentId)}`;
}
export function buildHostWorkspaceTerminalRoute(
serverId: string,
workspaceId: string,
terminalId: string
): string {
const base = buildHostWorkspaceRoute(serverId, workspaceId);
const normalizedTerminalId = trimNonEmpty(terminalId);
if (base === "/" || !normalizedTerminalId) {
return "/";
}
return `${base}/terminal/${encodeSegment(normalizedTerminalId)}`;
}
export function buildHostAgentDetailRoute(
serverId: string,
agentId: string
agentId: string,
workspaceId?: string
): string {
const normalizedWorkspaceId = trimNonEmpty(workspaceId);
if (normalizedWorkspaceId) {
return buildHostWorkspaceAgentRoute(
serverId,
normalizedWorkspaceId,
agentId
);
}
const normalizedServerId = trimNonEmpty(serverId);
const normalizedAgentId = trimNonEmpty(agentId);
if (!normalizedServerId || !normalizedAgentId) {
@@ -127,5 +261,14 @@ export function mapPathnameToServer(
if (suffix.startsWith("agents")) {
return `${base}/agents`;
}
return `${base}/agent`;
if (suffix.startsWith("new")) {
return `${base}/new`;
}
if (suffix.startsWith("workspace/")) {
return `${base}/${suffix}`;
}
if (suffix.startsWith("agent/")) {
return `${base}/${suffix}`;
}
return base;
}