Files
paseo/packages/app/src/utils/workspace-tab-identity.ts
T
906205f97a Add browser pane element picker (#670)
* feat: add browser pane element picker

Port the browser pane from PR #198 and route picked elements through workspace attachments so the context follows every agent composer in a workspace.

Co-authored-by: Jason Kneen <jason.kneen@bouncingfish.com>

* docs: document electron platform overlays

* fix: harden browser pane navigation

* fix: polish browser tab interactions

* fix: route browser pane focus shortcuts

---------

Co-authored-by: Jason Kneen <jason.kneen@bouncingfish.com>
2026-05-02 19:28:40 +08:00

90 lines
2.7 KiB
TypeScript

import type { WorkspaceTabTarget } from "@/stores/workspace-tabs-store";
export function normalizeWorkspaceTabTarget(
value: WorkspaceTabTarget | null | undefined,
): WorkspaceTabTarget | null {
if (!value || typeof value !== "object" || typeof value.kind !== "string") {
return null;
}
if (value.kind === "draft") {
const draftId = trimNonEmpty(value.draftId);
return draftId ? { kind: "draft", draftId } : null;
}
if (value.kind === "agent") {
const agentId = trimNonEmpty(value.agentId);
return agentId ? { kind: "agent", agentId } : null;
}
if (value.kind === "terminal") {
const terminalId = trimNonEmpty(value.terminalId);
return terminalId ? { kind: "terminal", terminalId } : null;
}
if (value.kind === "browser") {
const browserId = trimNonEmpty(value.browserId);
return browserId ? { kind: "browser", browserId } : null;
}
if (value.kind === "file") {
const path = trimNonEmpty(value.path);
return path ? { kind: "file", path: path.replace(/\\/g, "/") } : null;
}
if (value.kind === "setup") {
const workspaceId = trimNonEmpty(value.workspaceId);
return workspaceId ? { kind: "setup", workspaceId } : null;
}
return null;
}
export function workspaceTabTargetsEqual(
left: WorkspaceTabTarget,
right: WorkspaceTabTarget,
): boolean {
if (left.kind !== right.kind) {
return false;
}
if (left.kind === "draft" && right.kind === "draft") {
return left.draftId === right.draftId;
}
if (left.kind === "agent" && right.kind === "agent") {
return left.agentId === right.agentId;
}
if (left.kind === "terminal" && right.kind === "terminal") {
return left.terminalId === right.terminalId;
}
if (left.kind === "browser" && right.kind === "browser") {
return left.browserId === right.browserId;
}
if (left.kind === "file" && right.kind === "file") {
return left.path === right.path;
}
if (left.kind === "setup" && right.kind === "setup") {
return left.workspaceId === right.workspaceId;
}
return false;
}
export function buildDeterministicWorkspaceTabId(target: WorkspaceTabTarget): string {
if (target.kind === "draft") {
return target.draftId;
}
if (target.kind === "agent") {
return `agent_${target.agentId}`;
}
if (target.kind === "terminal") {
return `terminal_${target.terminalId}`;
}
if (target.kind === "browser") {
return `browser_${target.browserId}`;
}
if (target.kind === "setup") {
return `setup_${target.workspaceId}`;
}
return `file_${target.path}`;
}
function trimNonEmpty(value: string | null | undefined): string | null {
if (typeof value !== "string") {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}