Update files

This commit is contained in:
Mohamed Boudra
2026-02-13 05:08:26 +00:00
parent b64fa4ca93
commit 4948ba581a
33 changed files with 764 additions and 565 deletions
+118
View File
@@ -0,0 +1,118 @@
type NullableString = string | null | undefined;
function trimNonEmpty(value: NullableString): string | null {
if (typeof value !== "string") {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
}
function encodeSegment(value: string): string {
return encodeURIComponent(value);
}
export function parseServerIdFromPathname(pathname: string): string | null {
const match = pathname.match(/^\/h\/([^/]+)(?:\/|$)/);
if (!match) {
return null;
}
const raw = match[1];
if (!raw) {
return null;
}
try {
return trimNonEmpty(decodeURIComponent(raw));
} catch {
return trimNonEmpty(raw);
}
}
export function parseHostAgentRouteFromPathname(
pathname: string
): { serverId: string; agentId: string } | null {
const match = pathname.match(/^\/h\/([^/]+)\/agent\/([^/]+)(?:\/|$)/);
if (!match) {
return null;
}
const [, encodedServerId, encodedAgentId] = match;
if (!encodedServerId || !encodedAgentId) {
return null;
}
const decode = (value: string) => {
try {
return decodeURIComponent(value);
} catch {
return value;
}
};
const serverId = trimNonEmpty(decode(encodedServerId));
const agentId = trimNonEmpty(decode(encodedAgentId));
if (!serverId || !agentId) {
return null;
}
return { serverId, agentId };
}
export function buildHostAgentDraftRoute(serverId: string): string {
const normalized = trimNonEmpty(serverId);
if (!normalized) {
return "/";
}
return `/h/${encodeSegment(normalized)}/agent`;
}
export function buildHostAgentDetailRoute(
serverId: string,
agentId: string
): string {
const normalizedServerId = trimNonEmpty(serverId);
const normalizedAgentId = trimNonEmpty(agentId);
if (!normalizedServerId || !normalizedAgentId) {
return "/";
}
return `/h/${encodeSegment(normalizedServerId)}/agent/${encodeSegment(
normalizedAgentId
)}`;
}
export function buildHostAgentsRoute(serverId: string): string {
const normalized = trimNonEmpty(serverId);
if (!normalized) {
return "/";
}
return `/h/${encodeSegment(normalized)}/agents`;
}
export function buildHostSettingsRoute(serverId: string): string {
const normalized = trimNonEmpty(serverId);
if (!normalized) {
return "/";
}
return `/h/${encodeSegment(normalized)}/settings`;
}
export function mapPathnameToServer(
pathname: string,
nextServerId: string
): string {
const normalized = trimNonEmpty(nextServerId);
if (!normalized) {
return "/";
}
const suffix = pathname.replace(/^\/h\/[^/]+\/?/, "");
const base = `/h/${encodeSegment(normalized)}`;
if (suffix.startsWith("settings")) {
return `${base}/settings`;
}
if (suffix.startsWith("agents")) {
return `${base}/agents`;
}
return `${base}/agent`;
}
@@ -7,14 +7,14 @@ import {
} from "./new-agent-routing";
describe("buildNewAgentRoute", () => {
it("falls back to /agent when no working directory is provided", () => {
expect(buildNewAgentRoute(undefined)).toBe("/agent");
expect(buildNewAgentRoute(" ")).toBe("/agent");
it("falls back to host-scoped draft route when no working directory is provided", () => {
expect(buildNewAgentRoute("srv-1", undefined)).toBe("/h/srv-1/agent");
expect(buildNewAgentRoute("srv-1", " ")).toBe("/h/srv-1/agent");
});
it("encodes the working directory query parameter", () => {
expect(buildNewAgentRoute("/Users/me/dev/paseo")).toBe(
"/agent?workingDir=%2FUsers%2Fme%2Fdev%2Fpaseo"
expect(buildNewAgentRoute("srv-1", "/Users/me/dev/paseo")).toBe(
"/h/srv-1/agent?workingDir=%2FUsers%2Fme%2Fdev%2Fpaseo"
);
});
});
+11 -3
View File
@@ -1,4 +1,5 @@
import type { CheckoutStatusPayload } from "@/hooks/use-checkout-status-query";
import { buildHostAgentDraftRoute } from "@/utils/host-routes";
export function resolveNewAgentWorkingDir(
cwd: string,
@@ -7,10 +8,17 @@ export function resolveNewAgentWorkingDir(
return (checkout?.isPaseoOwnedWorktree ? checkout.mainRepoRoot : null) ?? cwd;
}
export function buildNewAgentRoute(workingDir?: string | null): string {
export function buildNewAgentRoute(
serverId: string,
workingDir?: string | null
): string {
const baseRoute = buildHostAgentDraftRoute(serverId);
if (baseRoute === "/") {
return baseRoute;
}
const trimmedWorkingDir = workingDir?.trim();
if (!trimmedWorkingDir) {
return "/agent";
return baseRoute;
}
return `/agent?workingDir=${encodeURIComponent(trimmedWorkingDir)}`;
return `${baseRoute}?workingDir=${encodeURIComponent(trimmedWorkingDir)}`;
}
@@ -33,16 +33,17 @@ describe("resolveNotificationTarget", () => {
describe("buildNotificationRoute", () => {
it("routes directly to server-scoped agent path when both ids are present", () => {
expect(buildNotificationRoute({ serverId: "srv-1", agentId: "agent-1" })).toBe(
"/agent/srv-1/agent-1"
"/h/srv-1/agent/agent-1"
);
});
it("falls back to legacy agent route when serverId is absent", () => {
expect(buildNotificationRoute({ agentId: "agent-legacy" })).toBe("/agent/agent-legacy");
it("falls back to host-scoped draft route when only serverId is present", () => {
expect(buildNotificationRoute({ serverId: "srv-only" })).toBe("/h/srv-only/agent");
});
it("falls back to agents list when no agent id is present", () => {
expect(buildNotificationRoute({ serverId: "srv-only" })).toBe("/agents");
it("falls back to root when no server id is present", () => {
expect(buildNotificationRoute({ agentId: "agent-legacy" })).toBe("/");
expect(buildNotificationRoute(undefined)).toBe("/");
});
it("encodes path segments", () => {
@@ -51,6 +52,6 @@ describe("buildNotificationRoute", () => {
serverId: "srv/with/slash",
agentId: "agent with space",
})
).toBe("/agent/srv%2Fwith%2Fslash/agent%20with%20space");
).toBe("/h/srv%2Fwith%2Fslash/agent/agent%20with%20space");
});
});
@@ -1,3 +1,8 @@
import {
buildHostAgentDetailRoute,
buildHostAgentDraftRoute,
} from "@/utils/host-routes";
type NotificationData = Record<string, unknown> | null | undefined;
function readNonEmptyString(
@@ -25,10 +30,10 @@ export function resolveNotificationTarget(data: NotificationData): {
export function buildNotificationRoute(data: NotificationData): string {
const { serverId, agentId } = resolveNotificationTarget(data);
if (serverId && agentId) {
return `/agent/${encodeURIComponent(serverId)}/${encodeURIComponent(agentId)}`;
return buildHostAgentDetailRoute(serverId, agentId);
}
if (agentId) {
return `/agent/${encodeURIComponent(agentId)}`;
if (serverId) {
return buildHostAgentDraftRoute(serverId);
}
return "/agents";
return "/";
}
@@ -161,6 +161,6 @@ describe("sendOsNotification", () => {
expect(clicked.onclick).toBeTypeOf("function");
clicked.onclick?.({} as Event);
expect(assign).toHaveBeenCalledWith("/agent/srv%20with%20space/agent%2F1");
expect(assign).toHaveBeenCalledWith("/h/srv%20with%20space/agent/agent%2F1");
});
});