diff --git a/packages/core/src/agents/agentsRoutes.ts b/packages/core/src/agents/agentsRoutes.ts new file mode 100644 index 0000000000..dfdb7d92fc --- /dev/null +++ b/packages/core/src/agents/agentsRoutes.ts @@ -0,0 +1,57 @@ +/** + * The agents surface (scouts + the agent-applications platform) is mounted under + * both `/code/agents/*` (the Code view) and `/website/agents/*` (the Channels / + * Bluebird view), sharing the same view components. Internal navigation resolves + * its routes through the per-space map below so every `` / `navigate` stays + * in the space the user is currently in instead of jumping back to `/code`. + */ +export type AgentsSpace = "code" | "website"; + +/** Which space a pathname belongs to. Defaults to `code` off the website tree. */ +export function agentsSpaceFromPath(pathname: string): AgentsSpace { + return pathname.startsWith("/website") ? "website" : "code"; +} + +/** + * Every agents route, keyed by space. `$idOrSlug` / `$skillName` / `$sessionId` + * params are filled in by the call site via TanStack's typed `params`. + */ +export const AGENTS_ROUTE = { + code: { + root: "/code/agents", + scouts: "/code/agents/scouts", + scoutDetail: "/code/agents/scouts/$skillName", + scratchpad: "/code/agents/scouts/scratchpad", + applications: "/code/agents/applications", + fleetApprovals: "/code/agents/applications/approvals", + application: "/code/agents/applications/$idOrSlug", + configuration: "/code/agents/applications/$idOrSlug/configuration", + sessions: "/code/agents/applications/$idOrSlug/sessions", + sessionDetail: "/code/agents/applications/$idOrSlug/sessions/$sessionId", + users: "/code/agents/applications/$idOrSlug/users", + memory: "/code/agents/applications/$idOrSlug/memory", + approvals: "/code/agents/applications/$idOrSlug/approvals", + observability: "/code/agents/applications/$idOrSlug/observability", + chat: "/code/agents/applications/$idOrSlug/chat", + }, + website: { + root: "/website/agents", + scouts: "/website/agents/scouts", + scoutDetail: "/website/agents/scouts/$skillName", + scratchpad: "/website/agents/scouts/scratchpad", + applications: "/website/agents/applications", + fleetApprovals: "/website/agents/applications/approvals", + application: "/website/agents/applications/$idOrSlug", + configuration: "/website/agents/applications/$idOrSlug/configuration", + sessions: "/website/agents/applications/$idOrSlug/sessions", + sessionDetail: "/website/agents/applications/$idOrSlug/sessions/$sessionId", + users: "/website/agents/applications/$idOrSlug/users", + memory: "/website/agents/applications/$idOrSlug/memory", + approvals: "/website/agents/applications/$idOrSlug/approvals", + observability: "/website/agents/applications/$idOrSlug/observability", + chat: "/website/agents/applications/$idOrSlug/chat", + }, +} as const satisfies Record>; + +/** The set of route keys available per space. */ +export type AgentsRouteKey = keyof (typeof AGENTS_ROUTE)["code"]; diff --git a/packages/core/src/inbox/reportMembership.ts b/packages/core/src/inbox/reportMembership.ts index edfca5f9e8..feee69e86d 100644 --- a/packages/core/src/inbox/reportMembership.ts +++ b/packages/core/src/inbox/reportMembership.ts @@ -99,25 +99,87 @@ export const INBOX_TAB_LABEL: Record = { }; /** - * Canonical inbox tab list routes. Use these constants instead of hard-coding - * `/code/inbox/pulls` etc., so renames stay in one place. - * - * Detail routes (`/code/inbox//$reportId`) stay as TanStack Router - * literals at call sites – TanStack's typed-link API needs them as literal - * strings to infer params. + * The two navigation spaces that host the inbox. The inbox subtree is mounted + * under both `/code/inbox/*` (the Code view) and `/website/inbox/*` (the + * Channels / Bluebird view) — sharing the same view components. Internal + * navigation (tabs, cards, back-links, redirects) resolves routes through the + * per-space maps below so it never jumps the user out of the space they're in. */ -export const INBOX_TAB_LIST_ROUTE: Record< - InboxTabKey, - `/code/inbox/${InboxTabKey}` -> = { - pulls: "/code/inbox/pulls", - reports: "/code/inbox/reports", - runs: "/code/inbox/runs", - dismissed: "/code/inbox/dismissed", -}; +export type InboxSpace = "code" | "website"; + +/** Which space a pathname belongs to. Defaults to `code` off the website tree. */ +export function inboxSpaceFromPath(pathname: string): InboxSpace { + return pathname.startsWith("/website") ? "website" : "code"; +} + +/** Inbox root route per space (the index, which redirects to the pulls tab). */ +export const INBOX_ROOT_ROUTE = { + code: "/code/inbox", + website: "/website/inbox", +} as const satisfies Record; + +/** + * Canonical inbox tab list routes, keyed by space. Use these constants instead + * of hard-coding `/code/inbox/pulls` etc., so renames stay in one place and a + * call site stays in whichever space it's navigating within. + */ +export const INBOX_TAB_LIST_ROUTE_BY_SPACE = { + code: { + pulls: "/code/inbox/pulls", + reports: "/code/inbox/reports", + runs: "/code/inbox/runs", + dismissed: "/code/inbox/dismissed", + }, + website: { + pulls: "/website/inbox/pulls", + reports: "/website/inbox/reports", + runs: "/website/inbox/runs", + dismissed: "/website/inbox/dismissed", + }, +} as const satisfies Record>; + +/** Detail routes (`//$reportId`), keyed by space. */ +export const INBOX_TAB_DETAIL_ROUTE_BY_SPACE = { + code: { + pulls: "/code/inbox/pulls/$reportId", + reports: "/code/inbox/reports/$reportId", + runs: "/code/inbox/runs/$reportId", + dismissed: "/code/inbox/dismissed/$reportId", + }, + website: { + pulls: "/website/inbox/pulls/$reportId", + reports: "/website/inbox/reports/$reportId", + runs: "/website/inbox/runs/$reportId", + dismissed: "/website/inbox/dismissed/$reportId", + }, +} as const satisfies Record>; + +/** Union of every list route across both spaces (a valid TanStack `to`). */ +export type InboxListRoute = + (typeof INBOX_TAB_LIST_ROUTE_BY_SPACE)[InboxSpace][InboxTabKey]; + +/** Union of every detail route across both spaces (a valid TanStack `to`). */ +export type InboxDetailRoute = + (typeof INBOX_TAB_DETAIL_ROUTE_BY_SPACE)[InboxSpace][InboxTabKey]; + +/** + * Back-compat alias for the Code-space list routes. Prefer + * `INBOX_TAB_LIST_ROUTE_BY_SPACE[space]` in space-aware call sites. + */ +export const INBOX_TAB_LIST_ROUTE = INBOX_TAB_LIST_ROUTE_BY_SPACE.code; + +const INBOX_TAB_FROM_PATH_RE = new RegExp( + `^/(?:code|website)/inbox/(${INBOX_TAB_KEYS.join("|")})`, +); + +/** Which inbox tab a pathname is on, in either space. */ +export function inboxTabFromPath(pathname: string): InboxTabKey { + const match = pathname.match(INBOX_TAB_FROM_PATH_RE); + return (match?.[1] as InboxTabKey | undefined) ?? "pulls"; +} const INBOX_DETAIL_PATH_RE = new RegExp( - `^/code/inbox/(${INBOX_TAB_KEYS.join("|")})/[^/]+$`, + `^/(?:code|website)/inbox/(${INBOX_TAB_KEYS.join("|")})/[^/]+$`, ); export function isInboxDetailPath(pathname: string): boolean { diff --git a/packages/ui/src/features/agent-applications/agent-builder/useAgentBuilderClientTools.ts b/packages/ui/src/features/agent-applications/agent-builder/useAgentBuilderClientTools.ts index f296f0be4d..def249cd4a 100644 --- a/packages/ui/src/features/agent-applications/agent-builder/useAgentBuilderClientTools.ts +++ b/packages/ui/src/features/agent-applications/agent-builder/useAgentBuilderClientTools.ts @@ -1,6 +1,7 @@ import { useNavigate } from "@tanstack/react-router"; import { useCallback, useRef } from "react"; import type { ClientToolHandler } from "../hooks/useAgentChat"; +import { useAgentsRoutes } from "../hooks/useAgentsRoutes"; import { useAgentBuilderStore } from "./agentBuilderStore"; /** @@ -33,6 +34,7 @@ export const AGENT_BUILDER_CLIENT_TOOLS = [ */ export function useAgentBuilderClientTools(): ClientToolHandler { const navigate = useNavigate(); + const routes = useAgentsRoutes(); const followMode = useAgentBuilderStore((s) => s.followMode); const setPendingSecret = useAgentBuilderStore((s) => s.setPendingSecret); const setPendingMcpConnect = useAgentBuilderStore( @@ -115,66 +117,45 @@ export function useAgentBuilderClientTools(): ClientToolHandler { const tab = str(args.tab) ?? "overview"; switch (tab) { case "configuration": - navigate({ - to: "/code/agents/applications/$idOrSlug/configuration", - params, - }); + navigate({ to: routes.configuration, params }); break; case "sessions": - navigate({ - to: "/code/agents/applications/$idOrSlug/sessions", - params, - }); + navigate({ to: routes.sessions, params }); break; case "memory": - navigate({ - to: "/code/agents/applications/$idOrSlug/memory", - params, - }); + navigate({ to: routes.memory, params }); break; case "approvals": - navigate({ - to: "/code/agents/applications/$idOrSlug/approvals", - params, - }); + navigate({ to: routes.approvals, params }); break; case "observability": - navigate({ - to: "/code/agents/applications/$idOrSlug/observability", - params, - }); + navigate({ to: routes.observability, params }); break; case "chat": - navigate({ - to: "/code/agents/applications/$idOrSlug/chat", - params, - }); + navigate({ to: routes.chat, params }); break; default: - navigate({ - to: "/code/agents/applications/$idOrSlug", - params, - }); + navigate({ to: routes.application, params }); } return { result: { focused: true } }; } case "focus_file": navigate({ - to: "/code/agents/applications/$idOrSlug/configuration", + to: routes.configuration, params, search: { node: str(args.path) }, }); return { result: { focused: true } }; case "focus_spec_section": navigate({ - to: "/code/agents/applications/$idOrSlug/configuration", + to: routes.configuration, params, search: { node: str(args.section) }, }); return { result: { focused: true } }; case "focus_revision": navigate({ - to: "/code/agents/applications/$idOrSlug/configuration", + to: routes.configuration, params, search: { revision: str(args.revisionId) }, }); @@ -185,7 +166,7 @@ export function useAgentBuilderClientTools(): ClientToolHandler { return { result: { focused: false, reason: "missing_session_id" } }; } navigate({ - to: "/code/agents/applications/$idOrSlug/sessions/$sessionId", + to: routes.sessionDetail, params: { idOrSlug: slug, sessionId }, }); return { result: { focused: true } }; @@ -194,6 +175,6 @@ export function useAgentBuilderClientTools(): ClientToolHandler { return { result: { focused: false, reason: "unknown_focus_target" } }; } }, - [navigate, setPendingSecret, setPendingMcpConnect], + [navigate, setPendingSecret, setPendingMcpConnect, routes], ); } diff --git a/packages/ui/src/features/agent-applications/components/AgentApplicationDetailView.tsx b/packages/ui/src/features/agent-applications/components/AgentApplicationDetailView.tsx index ea96141cbc..f60240c153 100644 --- a/packages/ui/src/features/agent-applications/components/AgentApplicationDetailView.tsx +++ b/packages/ui/src/features/agent-applications/components/AgentApplicationDetailView.tsx @@ -3,6 +3,7 @@ import { Link } from "@tanstack/react-router"; import { useAgentAnalytics } from "../hooks/useAgentAnalytics"; import { useAgentApplication } from "../hooks/useAgentApplication"; import { useAgentApplicationSessions } from "../hooks/useAgentApplicationSessions"; +import { useAgentsRoutes } from "../hooks/useAgentsRoutes"; import { AgentAnalyticsKpiStrip } from "./AgentAnalyticsView"; import { AgentDetailEmptyState, AgentDetailLayout } from "./AgentDetailLayout"; import { AgentSessionRow } from "./AgentSessionRow"; @@ -24,6 +25,7 @@ export function AgentApplicationDetailView({ idOrSlug }: { idOrSlug: string }) { isLoading: sessionsLoading, isError: sessionsError, } = useAgentApplicationSessions(idOrSlug, { limit: 25 }); + const routes = useAgentsRoutes(); return ( @@ -34,7 +36,7 @@ export function AgentApplicationDetailView({ idOrSlug }: { idOrSlug: string }) { Activity · last 7 days diff --git a/packages/ui/src/features/agent-applications/components/AgentApplicationsListView.tsx b/packages/ui/src/features/agent-applications/components/AgentApplicationsListView.tsx index 5f542f9231..bf7896e9a7 100644 --- a/packages/ui/src/features/agent-applications/components/AgentApplicationsListView.tsx +++ b/packages/ui/src/features/agent-applications/components/AgentApplicationsListView.tsx @@ -9,6 +9,7 @@ import type { AgentAnalyticsAgentRow, AgentApplication, } from "@posthog/shared/agent-platform-types"; +import { useAgentsRoutes } from "@posthog/ui/features/agent-applications/hooks/useAgentsRoutes"; import { AgentsTabLayout } from "@posthog/ui/features/agents/components/AgentsTabLayout"; import { Badge } from "@posthog/ui/primitives/Badge"; import { Button } from "@posthog/ui/primitives/Button"; @@ -277,9 +278,10 @@ function ApplicationRow({ stats?: AgentAnalyticsAgentRow; }) { const isLive = application.live_revision != null; + const routes = useAgentsRoutes(); return ( @@ -356,10 +358,11 @@ function RowStat({ */ function OperationalStrip({ pendingCount }: { pendingCount: number }) { const pendingAttention = pendingCount > 0; + const routes = useAgentsRoutes(); return ( ({ ...prev, session: undefined }), }); - }, [resumeSessionId, chat.resume, navigate, idOrSlug]); + }, [resumeSessionId, chat.resume, navigate, idOrSlug, routes.chat]); // The rail mixes chats from every revision; decide per click whether to // resume inline (same target) or navigate to a different revision's surface. @@ -154,7 +156,7 @@ export function AgentChatPane({ return; } navigate({ - to: "/code/agents/applications/$idOrSlug/chat", + to: routes.chat, params: { idOrSlug }, search: entry.revisionId ? { revision: entry.revisionId, session: entry.sessionId } diff --git a/packages/ui/src/features/agent-applications/components/AgentChatPendingApprovalCard.tsx b/packages/ui/src/features/agent-applications/components/AgentChatPendingApprovalCard.tsx index 1cf57fc59f..00648f5c5d 100644 --- a/packages/ui/src/features/agent-applications/components/AgentChatPendingApprovalCard.tsx +++ b/packages/ui/src/features/agent-applications/components/AgentChatPendingApprovalCard.tsx @@ -11,6 +11,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { Link } from "@tanstack/react-router"; import { useAuthStateValue } from "../../auth/store"; import { agentApplicationsKeys } from "../hooks/agentApplicationsKeys"; +import { useAgentsRoutes } from "../hooks/useAgentsRoutes"; import { approvalStateColor, approvalStateLabel } from "../utils/format"; import { AgentApprovalDecisionForm } from "./AgentApprovalDecisionForm"; import { ArgsSection } from "./AgentApprovalDetail"; @@ -40,6 +41,7 @@ export function AgentChatPendingApprovalCard({ }) { const queryClient = useQueryClient(); const projectId = useAuthStateValue((state) => state.currentProjectId); + const routes = useAgentsRoutes(); const isOwnerGate = approval.approver_scope?.type === "agent"; const mutation = useMutation({ @@ -85,7 +87,7 @@ export function AgentChatPendingApprovalCard({ @@ -144,7 +118,7 @@ export function AgentDetailLayout({ > @@ -178,7 +152,7 @@ export function AgentDetailLayout({ {TABS.map((tab) => ( data ?? [], [data]); const appsById = useMemo(() => { @@ -145,7 +147,7 @@ export function AgentFleetApprovalsPane({ className="shrink-0 cursor-default select-none border-(--gray-5) border-b px-6 pt-5" > diff --git a/packages/ui/src/features/agent-applications/components/AgentFleetLiveSessionsPanel.tsx b/packages/ui/src/features/agent-applications/components/AgentFleetLiveSessionsPanel.tsx index ded04b28fd..4c7f14ad08 100644 --- a/packages/ui/src/features/agent-applications/components/AgentFleetLiveSessionsPanel.tsx +++ b/packages/ui/src/features/agent-applications/components/AgentFleetLiveSessionsPanel.tsx @@ -11,6 +11,7 @@ import { Link } from "@tanstack/react-router"; import { useMemo } from "react"; import { useAgentApplications } from "../hooks/useAgentApplications"; import { useAgentFleetLiveSessions } from "../hooks/useAgentFleetLiveSessions"; +import { useAgentsRoutes } from "../hooks/useAgentsRoutes"; import { sessionStateColor } from "../utils/format"; import { RefreshIndicator } from "./RefreshIndicator"; @@ -101,9 +102,10 @@ function LiveSessionRow({ const idOrSlug = application?.slug ?? application?.id ?? session.application_id; const trigger = triggerLabel(session.trigger_metadata); + const routes = useAgentsRoutes(); return ( diff --git a/packages/ui/src/features/agent-applications/components/AgentRevisionBar.tsx b/packages/ui/src/features/agent-applications/components/AgentRevisionBar.tsx index 736be9dd4d..1f0d7994ae 100644 --- a/packages/ui/src/features/agent-applications/components/AgentRevisionBar.tsx +++ b/packages/ui/src/features/agent-applications/components/AgentRevisionBar.tsx @@ -11,6 +11,7 @@ import { AlertDialog, Flex, Popover, Text } from "@radix-ui/themes"; import { useNavigate } from "@tanstack/react-router"; import { useMemo, useState } from "react"; import { useAgentRevisionLifecycle } from "../hooks/useAgentRevisionLifecycle"; +import { useAgentsRoutes } from "../hooks/useAgentsRoutes"; import { useCreateAgentDraftFromRevision } from "../hooks/useCreateAgentDraftFromRevision"; import { revisionStateColor } from "../utils/format"; @@ -108,6 +109,7 @@ export function AgentRevisionBar({ const lifecycle = useAgentRevisionLifecycle(idOrSlug); const cloneToDraft = useCreateAgentDraftFromRevision(idOrSlug, agent.id); const navigate = useNavigate(); + const routes = useAgentsRoutes(); const [pickerOpen, setPickerOpen] = useState(false); const [filters, setFilters] = useState>( () => new Set(["live", "ready", "draft"]), @@ -262,7 +264,7 @@ export function AgentRevisionBar({ color="gray" onClick={() => navigate({ - to: "/code/agents/applications/$idOrSlug/chat", + to: routes.chat, params: { idOrSlug }, search: { revision: selected.id }, }) diff --git a/packages/ui/src/features/agent-applications/components/AgentSessionRow.tsx b/packages/ui/src/features/agent-applications/components/AgentSessionRow.tsx index 574c731530..5cbb54343e 100644 --- a/packages/ui/src/features/agent-applications/components/AgentSessionRow.tsx +++ b/packages/ui/src/features/agent-applications/components/AgentSessionRow.tsx @@ -6,6 +6,7 @@ import type { import { Badge } from "@posthog/ui/primitives/Badge"; import { Flex, Text } from "@radix-ui/themes"; import { Link } from "@tanstack/react-router"; +import { useAgentsRoutes } from "../hooks/useAgentsRoutes"; import { formatSpendUsd, sessionStateColor } from "../utils/format"; function principalLabel(principal: AgentSessionPrincipal | null): string { @@ -21,9 +22,10 @@ export function AgentSessionRow({ session: AgentSessionSummary; idOrSlug: string; }) { + const routes = useAgentsRoutes(); return ( diff --git a/packages/ui/src/features/agent-applications/components/AgentSessionTranscriptView.tsx b/packages/ui/src/features/agent-applications/components/AgentSessionTranscriptView.tsx index b716e4e622..bb8cf1e047 100644 --- a/packages/ui/src/features/agent-applications/components/AgentSessionTranscriptView.tsx +++ b/packages/ui/src/features/agent-applications/components/AgentSessionTranscriptView.tsx @@ -7,6 +7,7 @@ import { useMemo } from "react"; import { AgentBuilderHeaderControls } from "../agent-builder/AgentBuilderHeaderControls"; import { useSetAgentBuilderPage } from "../agent-builder/useSetAgentBuilderPage"; import { useAgentApplicationSession } from "../hooks/useAgentApplicationSession"; +import { useAgentsRoutes } from "../hooks/useAgentsRoutes"; import { sessionStateColor } from "../utils/format"; import { AgentSessionDetailBody } from "./AgentSessionDetailBody"; import { CopyButton } from "./CopyButton"; @@ -24,6 +25,7 @@ export function AgentSessionTranscriptView({ sessionId: string; }) { const { data: session } = useAgentApplicationSession(idOrSlug, sessionId); + const routes = useAgentsRoutes(); const headerContent = useMemo( () => ( @@ -49,7 +51,7 @@ export function AgentSessionTranscriptView({ > diff --git a/packages/ui/src/features/agent-applications/hooks/useAgentsRoutes.ts b/packages/ui/src/features/agent-applications/hooks/useAgentsRoutes.ts new file mode 100644 index 0000000000..19d45bac72 --- /dev/null +++ b/packages/ui/src/features/agent-applications/hooks/useAgentsRoutes.ts @@ -0,0 +1,23 @@ +import { + AGENTS_ROUTE, + type AgentsSpace, + agentsSpaceFromPath, +} from "@posthog/core/agents/agentsRoutes"; +import { useRouterState } from "@tanstack/react-router"; + +/** + * The navigation space the agents surface is currently rendered in — `code` + * under `/code/agents/*`, `website` under `/website/agents/*`. The scouts and + * agent-applications view components are shared across both subtrees, so they + * read this to keep every link / navigate inside the active space. + */ +export function useAgentsSpace(): AgentsSpace { + return useRouterState({ + select: (s) => agentsSpaceFromPath(s.location.pathname), + }); +} + +/** The space-resolved agents route map for the current space. */ +export function useAgentsRoutes() { + return AGENTS_ROUTE[useAgentsSpace()]; +} diff --git a/packages/ui/src/features/agents/components/AgentsTabLayout.tsx b/packages/ui/src/features/agents/components/AgentsTabLayout.tsx index cd3ef5dc9d..5ab2ff22b2 100644 --- a/packages/ui/src/features/agents/components/AgentsTabLayout.tsx +++ b/packages/ui/src/features/agents/components/AgentsTabLayout.tsx @@ -3,6 +3,7 @@ import { AgentBuilderHeaderControls } from "@posthog/ui/features/agent-applicati import type { AgentBuilderPageContext } from "@posthog/ui/features/agent-applications/agent-builder/agentBuilderStore"; import { useSetAgentBuilderPage } from "@posthog/ui/features/agent-applications/agent-builder/useSetAgentBuilderPage"; import { AGENT_PLATFORM_FLAG } from "@posthog/ui/features/agent-applications/featureFlag"; +import { useAgentsRoutes } from "@posthog/ui/features/agent-applications/hooks/useAgentsRoutes"; import { useFeatureFlag } from "@posthog/ui/features/feature-flags/useFeatureFlag"; import { useSetHeaderContent } from "@posthog/ui/hooks/useSetHeaderContent"; import { Flex, Text } from "@radix-ui/themes"; @@ -50,6 +51,7 @@ export function AgentsTabLayout({ const pageContext: AgentBuilderPageContext = activeTab === "applications" ? { kind: "agent-list" } : { kind: "scouts" }; useSetAgentBuilderPage(pageContext); + const routes = useAgentsRoutes(); // The Applications tab is gated behind the agent-platform flag. const applicationsEnabled = useFeatureFlag(AGENT_PLATFORM_FLAG); @@ -69,13 +71,13 @@ export function AgentsTabLayout({ {applicationsEnabled ? ( diff --git a/packages/ui/src/features/canvas/components/ChannelsSidebar.tsx b/packages/ui/src/features/canvas/components/ChannelsSidebar.tsx index 1f2cdc8a11..1df8959513 100644 --- a/packages/ui/src/features/canvas/components/ChannelsSidebar.tsx +++ b/packages/ui/src/features/canvas/components/ChannelsSidebar.tsx @@ -1,30 +1,33 @@ import { - BrainIcon, GearSixIcon, HouseIcon, - RobotIcon, + SlidersHorizontalIcon, SquaresFourIcon, - TrayIcon, } from "@phosphor-icons/react"; import { ANALYTICS_EVENTS } from "@posthog/shared/analytics-events"; import { HOME_TAB_FLAG } from "@posthog/shared/constants"; import { ChannelsList } from "@posthog/ui/features/canvas/components/ChannelsList"; import { useChannelsSidebarStore } from "@posthog/ui/features/canvas/components/channelsSidebarStore"; import { useFeatureFlag } from "@posthog/ui/features/feature-flags/useFeatureFlag"; +import { useInboxAllReports } from "@posthog/ui/features/inbox/hooks/useInboxAllReports"; import { openSettings } from "@posthog/ui/features/settings/hooks/useOpenSettings"; +import { AgentsItem } from "@posthog/ui/features/sidebar/components/items/AgentsItem"; +import { InboxItem } from "@posthog/ui/features/sidebar/components/items/InboxItem"; +import { SearchItem } from "@posthog/ui/features/sidebar/components/items/SearchItem"; import { ProjectSwitcher } from "@posthog/ui/features/sidebar/components/ProjectSwitcher"; import { SidebarItem } from "@posthog/ui/features/sidebar/components/SidebarItem"; import { UpdateBanner } from "@posthog/ui/features/sidebar/components/UpdateBanner"; import { ResizableSidebar } from "@posthog/ui/primitives/ResizableSidebar"; import { - navigateToAgents, navigateToCanvas, - navigateToInbox, - navigateToSkills, + navigateToWebsiteAgents, + navigateToWebsiteCustomize, navigateToWebsiteHome, + navigateToWebsiteInbox, } from "@posthog/ui/router/navigationBridge"; import { useAppView } from "@posthog/ui/router/useAppView"; import { track } from "@posthog/ui/shell/analytics"; +import { useCommandMenuStore } from "@posthog/ui/shell/commandMenuStore"; import { Box, Flex } from "@radix-ui/themes"; import { useRouterState } from "@tanstack/react-router"; @@ -38,35 +41,37 @@ function trackNav(navTarget: string, navigate: () => void) { navigate(); } -// Non-canvas /website mirrors (Home, Files, etc.) — used to tell whether the -// current /website route is a canvas surface (channels index / a channel / a -// dashboard) so the Canvas nav item highlights only there. +// Non-canvas /website surfaces — used to tell whether the current /website route +// is a canvas surface (channels index / a channel / a dashboard) so the Canvas +// nav item highlights only there. const NON_CANVAS_WEBSITE_PREFIXES = [ "/website/home", - "/website/skills", - "/website/mcp-servers", + "/website/inbox", + "/website/agents", + "/website/customize", "/website/command-center", ]; -// The global nav brought over from the Code app — a single icon+label row each, -// no rail. Home points at the /website/home mirror so it stays in the Channels -// space (same shared HomeView, channels chrome kept); the other rows are -// app-wide destinations that leave the Channels space for the Code view. The -// channel tree below is channel browsing. +// The channels-space global nav. It mirrors the Code view's top items — +// Search, Inbox, Agents — but every destination stays inside the Channels +// space (the /website mirrors) so navigating never bounces back to /code. Order: +// Home · Search · Inbox · Canvas · Agents · Customize. The channel tree below is +// channel browsing. function ChannelsNav() { const view = useAppView(); const homeTabEnabled = useFeatureFlag(HOME_TAB_FLAG); + const openCommandMenu = useCommandMenuStore((s) => s.open); + // Same PR-review count the Code view's Inbox item shows; `ignoreFilters` keeps + // the badge stable against the inbox's filter chrome. + const { counts: inboxCounts } = useInboxAllReports({ ignoreFilters: true }); // Active on the canvas surfaces: the channels index, a channel, or a canvas — - // any /website route that isn't one of the cross-app mirrors above. - const isCanvasActive = useRouterState({ - select: (s) => { - const path = s.location.pathname; - return ( - path.startsWith("/website") && - !NON_CANVAS_WEBSITE_PREFIXES.some((p) => path.startsWith(p)) - ); - }, - }); + // any /website route that isn't one of the non-canvas surfaces above. + const path = useRouterState({ select: (s) => s.location.pathname }); + const isCanvasActive = + path.startsWith("/website") && + !NON_CANVAS_WEBSITE_PREFIXES.some((p) => path.startsWith(p)); + const isCustomizeActive = path.startsWith("/website/customize"); + return ( {homeTabEnabled && ( @@ -83,17 +88,11 @@ function ChannelsNav() { onClick={() => trackNav("home", navigateToWebsiteHome)} /> )} - - } - label="Global Inbox" + trackNav("search", openCommandMenu)} /> + trackNav("inbox", navigateToInbox)} + onClick={() => trackNav("inbox", navigateToWebsiteInbox)} + pullRequestCount={inboxCounts.pulls} /> trackNav("canvas", navigateToCanvas)} /> - - } - label="Agents" + trackNav("agents", navigateToAgents)} + onClick={() => trackNav("agents", navigateToWebsiteAgents)} /> } - label="Files" - isActive={view.type === "skills"} - onClick={() => trackNav("files", navigateToSkills)} + label="Customize" + isActive={isCustomizeActive} + onClick={() => trackNav("customize", navigateToWebsiteCustomize)} /> ); diff --git a/packages/ui/src/features/canvas/components/CustomizeLayout.tsx b/packages/ui/src/features/canvas/components/CustomizeLayout.tsx new file mode 100644 index 0000000000..9b0c1f408c --- /dev/null +++ b/packages/ui/src/features/canvas/components/CustomizeLayout.tsx @@ -0,0 +1,64 @@ +import { LightbulbIcon, PlugsIcon } from "@phosphor-icons/react"; +import { SidebarItem } from "@posthog/ui/features/sidebar/components/SidebarItem"; +import { Box, Flex, Text } from "@radix-ui/themes"; +import { Outlet, useNavigate, useRouterState } from "@tanstack/react-router"; + +// The Customize page's own secondary left sidebar. Skills and MCP servers were +// previously standalone /website mirrors; grouping them here keeps the top-level +// channels nav lean while giving both surfaces a shared home. Each item renders +// the same shared view (SkillsView / McpServersView) in the outlet to its right. +function CustomizeNav() { + const navigate = useNavigate(); + const pathname = useRouterState({ select: (s) => s.location.pathname }); + // Explicit prefix checks (rather than `!isMcp`) so a future third sub-route + // doesn't light up the Skills item. The bare /website/customize index + // redirects to Skills, so it counts as Skills-active. + const isMcp = pathname.startsWith("/website/customize/mcp-servers"); + const isSkills = + pathname.startsWith("/website/customize/skills") || + pathname === "/website/customize" || + pathname === "/website/customize/"; + + return ( + + + + Customize + + + + + } + label="Skills" + isActive={isSkills} + onClick={() => navigate({ to: "/website/customize/skills" })} + /> + } + label="MCP servers" + isActive={isMcp} + onClick={() => navigate({ to: "/website/customize/mcp-servers" })} + /> + + + ); +} + +/** Layout for `/website/customize/*`: secondary sidebar + the active sub-view. */ +export function CustomizeLayout() { + return ( + + + + + + + ); +} diff --git a/packages/ui/src/features/inbox/components/AgentRunCard.tsx b/packages/ui/src/features/inbox/components/AgentRunCard.tsx index 2e5a57063e..abc0c7e4a0 100644 --- a/packages/ui/src/features/inbox/components/AgentRunCard.tsx +++ b/packages/ui/src/features/inbox/components/AgentRunCard.tsx @@ -14,6 +14,7 @@ import { import { InboxMetaSourceStack } from "@posthog/ui/features/inbox/components/InboxMetaSourceStack"; import { InboxBadge } from "@posthog/ui/features/inbox/components/utils/InboxBadge"; import { hasKnownSourceProduct } from "@posthog/ui/features/inbox/components/utils/source-product-icons"; +import { useInboxRoutes } from "@posthog/ui/features/inbox/hooks/useInboxSpace"; import { Flex, Text } from "@radix-ui/themes"; import { useNavigate } from "@tanstack/react-router"; @@ -102,6 +103,7 @@ interface AgentRunCardProps { export function AgentRunCard({ report }: AgentRunCardProps) { const navigate = useNavigate(); + const { detail } = useInboxRoutes(); const hasSource = hasKnownSourceProduct(report.source_products); const runId = `…-${report.id.split("-").pop() ?? report.id}`; const variant = resolveRunVariant(report); @@ -114,7 +116,7 @@ export function AgentRunCard({ report }: AgentRunCardProps) { type="button" onClick={() => navigate({ - to: "/code/inbox/runs/$reportId", + to: detail.runs, params: { reportId: report.id }, }) } diff --git a/packages/ui/src/features/inbox/components/AgentRunDetail.tsx b/packages/ui/src/features/inbox/components/AgentRunDetail.tsx index c8751d0306..fae531037a 100644 --- a/packages/ui/src/features/inbox/components/AgentRunDetail.tsx +++ b/packages/ui/src/features/inbox/components/AgentRunDetail.tsx @@ -46,6 +46,7 @@ import { hasKnownSourceProduct, } from "@posthog/ui/features/inbox/components/utils/source-product-icons"; import { useInboxReportSignals } from "@posthog/ui/features/inbox/hooks/useInboxReports"; +import { useInboxRoutes } from "@posthog/ui/features/inbox/hooks/useInboxSpace"; import { type ReportTaskData, useReportTasks, @@ -139,12 +140,11 @@ function RunOutputReadyCard({ report }: { report: SignalReport }) { const prRef = prUrl ? parsePrUrl(prUrl) : null; const sourceMeta = getSourceProductMeta(report.source_products?.[0]); const headline = deriveHeadline(report.summary); + const { detail } = useInboxRoutes(); return ( @@ -209,7 +209,7 @@ export function AgentRunDetail({ reportId }: AgentRunDetailProps) { return ( @@ -219,6 +219,7 @@ export function AgentRunDetail({ reportId }: AgentRunDetailProps) { } function AgentRunDetailContent({ report }: { report: SignalReport }) { + const { list } = useInboxRoutes(); const { data: signalsResp } = useInboxReportSignals(report.id); const { data: reportTasks, isLoading: isLoadingReportTasks } = useReportTasks( report.id, @@ -266,7 +267,7 @@ function AgentRunDetailContent({ report }: { report: SignalReport }) { return ( diff --git a/packages/ui/src/features/inbox/components/DismissedReportDetail.tsx b/packages/ui/src/features/inbox/components/DismissedReportDetail.tsx index 4127484f85..19af2bd2cd 100644 --- a/packages/ui/src/features/inbox/components/DismissedReportDetail.tsx +++ b/packages/ui/src/features/inbox/components/DismissedReportDetail.tsx @@ -9,6 +9,7 @@ import type { SignalReport } from "@posthog/shared/types"; import { InboxDetailFrame } from "@posthog/ui/features/inbox/components/InboxDetailFrame"; import { InboxReportDetailGate } from "@posthog/ui/features/inbox/components/InboxReportDetailGate"; import { useInboxRestoreReport } from "@posthog/ui/features/inbox/hooks/useInboxRestoreReport"; +import { useInboxRoutes } from "@posthog/ui/features/inbox/hooks/useInboxSpace"; import { copyInboxReportLink } from "@posthog/ui/features/inbox/utils/copyInboxReportLink"; import { Spinner } from "@radix-ui/themes"; import { useNavigate } from "@tanstack/react-router"; @@ -39,7 +40,7 @@ export function DismissedReportDetail({ @@ -55,7 +56,7 @@ function DismissedReportDetailContent({ report }: { report: SignalReport }) { return ( restore.mutate(report.id, { - onSuccess: () => navigate({ to: "/code/inbox/dismissed" }), + onSuccess: () => navigate({ to: list.dismissed }), }) } > diff --git a/packages/ui/src/features/inbox/components/InboxDetailFrame.tsx b/packages/ui/src/features/inbox/components/InboxDetailFrame.tsx index 0031823dfc..0b9cd408f5 100644 --- a/packages/ui/src/features/inbox/components/InboxDetailFrame.tsx +++ b/packages/ui/src/features/inbox/components/InboxDetailFrame.tsx @@ -1,4 +1,5 @@ import type { IconProps } from "@phosphor-icons/react"; +import type { InboxTabKey } from "@posthog/core/inbox/reportMembership"; import type { SignalReport } from "@posthog/shared/types"; import { DetailSection } from "@posthog/ui/features/inbox/components/DetailSection"; import { InboxDetailPageHeader } from "@posthog/ui/features/inbox/components/InboxDetailPageHeader"; @@ -20,14 +21,15 @@ import { SignalReportSummaryMarkdown } from "@posthog/ui/features/inbox/componen import { hasKnownSourceProduct } from "@posthog/ui/features/inbox/components/utils/source-product-icons"; import { useInboxReportDismissAction } from "@posthog/ui/features/inbox/hooks/useInboxReportDismissAction"; import { useInboxReportSignals } from "@posthog/ui/features/inbox/hooks/useInboxReports"; +import { useInboxRoutes } from "@posthog/ui/features/inbox/hooks/useInboxSpace"; import { RelativeTimestamp } from "@posthog/ui/primitives/RelativeTimestamp"; import { Flex, Text } from "@radix-ui/themes"; import type { ComponentType, ReactNode } from "react"; interface InboxDetailFrameProps { report: SignalReport; - /** List route for the back-link (e.g. "/code/inbox/pulls"). */ - backTo: "/code/inbox/pulls" | "/code/inbox/reports" | "/code/inbox/dismissed"; + /** The list tab to return to; resolved to the active space's route. */ + backTab: Extract; backLabel: string; /** * Whether to render the Dismiss button + dialog. Off for already-dismissed @@ -68,7 +70,7 @@ interface InboxDetailFrameProps { */ export function InboxDetailFrame({ report, - backTo, + backTab, backLabel, fallbackTitle, breadcrumb, @@ -80,6 +82,8 @@ export function InboxDetailFrame({ showDismiss = true, children, }: InboxDetailFrameProps) { + const { list } = useInboxRoutes(); + const backTo = list[backTab]; const { data: signalsResp } = useInboxReportSignals(report.id); const signals = signalsResp?.signals ?? []; const signalsLoaded = signalsResp !== undefined; diff --git a/packages/ui/src/features/inbox/components/InboxReportDetailGate.tsx b/packages/ui/src/features/inbox/components/InboxReportDetailGate.tsx index 557ba6c150..a37105d441 100644 --- a/packages/ui/src/features/inbox/components/InboxReportDetailGate.tsx +++ b/packages/ui/src/features/inbox/components/InboxReportDetailGate.tsx @@ -1,4 +1,6 @@ import { + type InboxDetailRoute, + type InboxTabKey, isDismissedReport, isPullRequestReport, isReportTabReport, @@ -7,6 +9,7 @@ import { Spinner } from "@posthog/quill"; import type { SignalReport } from "@posthog/shared/types"; import { DetailBackLink } from "@posthog/ui/features/inbox/components/DetailBackLink"; import { useInboxReportById } from "@posthog/ui/features/inbox/hooks/useInboxReports"; +import { useInboxRoutes } from "@posthog/ui/features/inbox/hooks/useInboxSpace"; import { type InboxDetailTab, useReportOpenTracker, @@ -18,33 +21,24 @@ import { type ReactNode, useEffect } from "react"; interface InboxReportDetailGateProps { reportId: string; cachedReport?: SignalReport | null; - backTo: - | "/code/inbox/pulls" - | "/code/inbox/reports" - | "/code/inbox/runs" - | "/code/inbox/dismissed"; + /** The list tab this detail belongs to; back-link + redirects resolve to the active space. */ + backTab: InboxTabKey; backLabel: string; missingCopy: string; children: (report: SignalReport) => ReactNode; } -type InboxDetailRoute = - | "/code/inbox/pulls/$reportId" - | "/code/inbox/reports/$reportId" - | "/code/inbox/runs/$reportId" - | "/code/inbox/dismissed/$reportId"; - /** - * Detail route a non-suppressed report belongs on, by the same tab-membership - * predicates the inbox tabs use: Pulls when a PR exists, Reports when it belongs - * to the Reports tab, otherwise Runs. `isReportTabReport` already excludes - * `failed` and in-flight runs, so failed/finished and live runs both fall - * through to Runs — the only tab that actually lists them. + * Tab a non-suppressed report belongs on, by the same tab-membership predicates + * the inbox tabs use: Pulls when a PR exists, Reports when it belongs to the + * Reports tab, otherwise Runs. `isReportTabReport` already excludes `failed` and + * in-flight runs, so failed/finished and live runs both fall through to Runs — + * the only tab that actually lists them. */ -function nonSuppressedDetailRoute(report: SignalReport): InboxDetailRoute { - if (isPullRequestReport(report)) return "/code/inbox/pulls/$reportId"; - if (isReportTabReport(report)) return "/code/inbox/reports/$reportId"; - return "/code/inbox/runs/$reportId"; +function nonSuppressedTab(report: SignalReport): InboxTabKey { + if (isPullRequestReport(report)) return "pulls"; + if (isReportTabReport(report)) return "reports"; + return "runs"; } /** @@ -55,12 +49,14 @@ function nonSuppressedDetailRoute(report: SignalReport): InboxDetailRoute { export function InboxReportDetailGate({ reportId, cachedReport = null, - backTo, + backTab, backLabel, missingCopy, children, }: InboxReportDetailGateProps) { const navigate = useNavigate(); + const { list, detail } = useInboxRoutes(); + const backTo = list[backTab]; const { data: report, isLoading, @@ -82,15 +78,15 @@ export function InboxReportDetailGate({ // `initialDataUpdatedAt: 0`). Both terminal states belong on the Archive route, // so resolved cards keep their reference-only detail view instead of being // bounced to Runs. - const onDismissedRoute = backTo === "/code/inbox/dismissed"; + const onDismissedRoute = backTab === "dismissed"; const isArchived = resolvedReport != null && isDismissedReport(resolvedReport); let redirectTo: InboxDetailRoute | null = null; if (resolvedReport && !isFetching) { if (isArchived && !onDismissedRoute) { - redirectTo = "/code/inbox/dismissed/$reportId"; + redirectTo = detail.dismissed; } else if (!isArchived && onDismissedRoute) { - redirectTo = nonSuppressedDetailRoute(resolvedReport); + redirectTo = detail[nonSuppressedTab(resolvedReport)]; } } @@ -146,7 +142,7 @@ export function InboxReportDetailGate({ ); } - const trackTab = tabFromBackTo(backTo); + const trackTab = trackedTabFor(backTab); return ( <> {trackTab && } @@ -160,12 +156,10 @@ export function InboxReportDetailGate({ * `InboxDetailTab` (its rank would be measured against the wrong list), so it * returns `null` and the open/close engagement events are skipped for it. */ -function tabFromBackTo( - backTo: InboxReportDetailGateProps["backTo"], -): InboxDetailTab | null { - if (backTo === "/code/inbox/pulls") return "pulls"; - if (backTo === "/code/inbox/runs") return "runs"; - if (backTo === "/code/inbox/dismissed") return null; +function trackedTabFor(backTab: InboxTabKey): InboxDetailTab | null { + if (backTab === "pulls") return "pulls"; + if (backTab === "runs") return "runs"; + if (backTab === "dismissed") return null; return "reports"; } diff --git a/packages/ui/src/features/inbox/components/InboxTabBar.tsx b/packages/ui/src/features/inbox/components/InboxTabBar.tsx index ef130f3876..72f545a97c 100644 --- a/packages/ui/src/features/inbox/components/InboxTabBar.tsx +++ b/packages/ui/src/features/inbox/components/InboxTabBar.tsx @@ -1,12 +1,13 @@ import { INBOX_TAB_KEYS, INBOX_TAB_LABEL, - INBOX_TAB_LIST_ROUTE, type InboxTabCounts, type InboxTabKey, + inboxTabFromPath, } from "@posthog/core/inbox/reportMembership"; import { Tabs, TabsList, TabsTrigger } from "@posthog/quill"; import { InboxScopeSelect } from "@posthog/ui/features/inbox/components/InboxScopeSelect"; +import { useInboxRoutes } from "@posthog/ui/features/inbox/hooks/useInboxSpace"; import { Flex } from "@radix-ui/themes"; import { useNavigate, useRouterState } from "@tanstack/react-router"; @@ -14,17 +15,11 @@ interface InboxTabBarProps { counts: InboxTabCounts; } -function activeTabFromPath(pathname: string): InboxTabKey { - if (pathname.startsWith(INBOX_TAB_LIST_ROUTE.reports)) return "reports"; - if (pathname.startsWith(INBOX_TAB_LIST_ROUTE.runs)) return "runs"; - if (pathname.startsWith(INBOX_TAB_LIST_ROUTE.dismissed)) return "dismissed"; - return "pulls"; -} - export function InboxTabBar({ counts }: InboxTabBarProps) { const navigate = useNavigate(); + const { list } = useInboxRoutes(); const pathname = useRouterState({ select: (s) => s.location.pathname }); - const activeKey = activeTabFromPath(pathname); + const activeKey = inboxTabFromPath(pathname); return ( @@ -32,7 +27,7 @@ export function InboxTabBar({ counts }: InboxTabBarProps) { value={activeKey} onValueChange={(value: string) => { const key = value as InboxTabKey; - navigate({ to: INBOX_TAB_LIST_ROUTE[key] }); + navigate({ to: list[key] }); }} > @@ -49,7 +49,7 @@ function PullRequestDetailContent({ report }: { report: SignalReport }) { return ( @@ -39,7 +39,7 @@ function ReportDetailContent({ report }: { report: SignalReport }) { return ( navigate({ - to: "/code/inbox/runs/$reportId", + to: detail.runs, params: { reportId: report.id }, }) } diff --git a/packages/ui/src/features/inbox/hooks/useInboxReportDetailPrefetch.ts b/packages/ui/src/features/inbox/hooks/useInboxReportDetailPrefetch.ts index a88b2def30..b01b9f74f7 100644 --- a/packages/ui/src/features/inbox/hooks/useInboxReportDetailPrefetch.ts +++ b/packages/ui/src/features/inbox/hooks/useInboxReportDetailPrefetch.ts @@ -1,26 +1,15 @@ import { seedInboxReportDetailCache } from "@posthog/core/inbox/inboxQuery"; +import type { InboxDetailRoute as InboxDetailRoutePath } from "@posthog/core/inbox/reportMembership"; import type { SignalReport } from "@posthog/shared/types"; import { useQueryClient } from "@tanstack/react-query"; import { useRouter } from "@tanstack/react-router"; import { useCallback, useMemo } from "react"; -export type InboxDetailRoute = - | { - to: "/code/inbox/pulls/$reportId"; - params: { reportId: string }; - } - | { - to: "/code/inbox/reports/$reportId"; - params: { reportId: string }; - } - | { - to: "/code/inbox/runs/$reportId"; - params: { reportId: string }; - } - | { - to: "/code/inbox/dismissed/$reportId"; - params: { reportId: string }; - }; +/** A detail-route target (`//$reportId`, either space) + its params. */ +export interface InboxDetailRoute { + to: InboxDetailRoutePath; + params: { reportId: string }; +} /** * `` already triggers route preload on hover/focus, so we diff --git a/packages/ui/src/features/inbox/hooks/useInboxSpace.ts b/packages/ui/src/features/inbox/hooks/useInboxSpace.ts new file mode 100644 index 0000000000..415bc16a2f --- /dev/null +++ b/packages/ui/src/features/inbox/hooks/useInboxSpace.ts @@ -0,0 +1,31 @@ +import { + INBOX_ROOT_ROUTE, + INBOX_TAB_DETAIL_ROUTE_BY_SPACE, + INBOX_TAB_LIST_ROUTE_BY_SPACE, + type InboxSpace, + inboxSpaceFromPath, +} from "@posthog/core/inbox/reportMembership"; +import { useRouterState } from "@tanstack/react-router"; + +/** + * The navigation space the inbox is currently rendered in — `code` under + * `/code/inbox/*`, `website` under `/website/inbox/*`. Inbox view components are + * shared across both subtrees, so they read this to resolve their tabs, cards, + * back-links, and redirects to routes that keep the user in their space. + */ +export function useInboxSpace(): InboxSpace { + return useRouterState({ + select: (s) => inboxSpaceFromPath(s.location.pathname), + }); +} + +/** Space-resolved inbox route maps for the current space. */ +export function useInboxRoutes() { + const space = useInboxSpace(); + return { + space, + root: INBOX_ROOT_ROUTE[space], + list: INBOX_TAB_LIST_ROUTE_BY_SPACE[space], + detail: INBOX_TAB_DETAIL_ROUTE_BY_SPACE[space], + }; +} diff --git a/packages/ui/src/features/scouts/components/FleetMemoryCallout.tsx b/packages/ui/src/features/scouts/components/FleetMemoryCallout.tsx index 0629c17c24..7a5e555397 100644 --- a/packages/ui/src/features/scouts/components/FleetMemoryCallout.tsx +++ b/packages/ui/src/features/scouts/components/FleetMemoryCallout.tsx @@ -1,4 +1,5 @@ import { ArrowRightIcon, NotebookIcon } from "@phosphor-icons/react"; +import { useAgentsRoutes } from "@posthog/ui/features/agent-applications/hooks/useAgentsRoutes"; import { RelativeTimestamp } from "@posthog/ui/primitives/RelativeTimestamp"; import { Flex, Text } from "@radix-ui/themes"; import { Link } from "@tanstack/react-router"; @@ -13,6 +14,7 @@ import { useScoutScratchpad } from "../hooks/useScoutScratchpad"; */ export function FleetMemoryCallout() { const { data: entries } = useScoutScratchpad(); + const routes = useAgentsRoutes(); // Hold until the first load settles, then only show when there's something to // read. Entries arrive newest-first, so the head drives the "updated" hint. @@ -25,7 +27,7 @@ export function FleetMemoryCallout() { return ( diff --git a/packages/ui/src/features/scouts/components/ScoutDetailView.tsx b/packages/ui/src/features/scouts/components/ScoutDetailView.tsx index 230b9d67b3..a25f16bb9e 100644 --- a/packages/ui/src/features/scouts/components/ScoutDetailView.tsx +++ b/packages/ui/src/features/scouts/components/ScoutDetailView.tsx @@ -21,6 +21,7 @@ import { scoutRunsWindowLabel, } from "@posthog/core/scouts/scoutRunsWindow"; import { ANALYTICS_EVENTS } from "@posthog/shared"; +import { useAgentsRoutes } from "@posthog/ui/features/agent-applications/hooks/useAgentsRoutes"; import { MarkdownRenderer } from "@posthog/ui/features/editor/components/MarkdownRenderer"; import { useSetHeaderContent } from "@posthog/ui/hooks/useSetHeaderContent"; import { RelativeTimestamp } from "@posthog/ui/primitives/RelativeTimestamp"; @@ -53,6 +54,7 @@ export function ScoutDetailView({ }) { const skillName = scoutSkillNameFromSlug(skillSlug); const displayName = prettifyScoutSkillName(skillName); + const routes = useAgentsRoutes(); const headerContent = useMemo( () => ( @@ -138,7 +140,7 @@ export function ScoutDetailView({ className="border-(--gray-5) border-b px-6 pt-5 pb-5" > diff --git a/packages/ui/src/features/scouts/components/ScoutRowCard.tsx b/packages/ui/src/features/scouts/components/ScoutRowCard.tsx index 9bf258310f..00e9d0ab71 100644 --- a/packages/ui/src/features/scouts/components/ScoutRowCard.tsx +++ b/packages/ui/src/features/scouts/components/ScoutRowCard.tsx @@ -13,6 +13,7 @@ import { import { buildScoutCheckinPrompt } from "@posthog/core/scouts/scoutPrompts"; import type { ScoutSurface } from "@posthog/shared"; import { ANALYTICS_EVENTS } from "@posthog/shared"; +import { useAgentsRoutes } from "@posthog/ui/features/agent-applications/hooks/useAgentsRoutes"; import { track } from "@posthog/ui/shell/analytics"; import { skillUrl } from "@posthog/ui/utils/posthogLinks"; import { Box, Flex, Text, Tooltip } from "@radix-ui/themes"; @@ -41,6 +42,7 @@ export function ScoutRowCard({ linkToDetail?: boolean; }) { const [settingsOpen, setSettingsOpen] = useState(false); + const routes = useAgentsRoutes(); const cloudSkillUrl = skillUrl(config.skill_name); const surface: ScoutSurface = linkToDetail ? "fleet_list" : "scout_detail"; @@ -69,7 +71,7 @@ export function ScoutRowCard({ {linkToDetail ? ( ("recent"); @@ -71,7 +73,7 @@ export function ScratchpadView() { className="border-(--gray-5) border-b px-6 pt-5 pb-5" > diff --git a/packages/ui/src/features/sidebar/components/SidebarNavSection.tsx b/packages/ui/src/features/sidebar/components/SidebarNavSection.tsx index b13a01201a..e9d0eace3f 100644 --- a/packages/ui/src/features/sidebar/components/SidebarNavSection.tsx +++ b/packages/ui/src/features/sidebar/components/SidebarNavSection.tsx @@ -11,10 +11,12 @@ import { navigateToInbox, navigateToMcpServers, navigateToSkills, + navigateToWebsiteAgents, navigateToWebsiteCommandCenter, + navigateToWebsiteCustomizeMcpServers, + navigateToWebsiteCustomizeSkills, navigateToWebsiteHome, - navigateToWebsiteMcpServers, - navigateToWebsiteSkills, + navigateToWebsiteInbox, } from "@posthog/ui/router/navigationBridge"; import { useAppView } from "@posthog/ui/router/useAppView"; import { openTaskInput } from "@posthog/ui/router/useOpenTask"; @@ -42,9 +44,9 @@ interface SidebarNavSectionProps { // The sidebar navigation section shared by the Code pane (above the task list) // and the Channels pane. It is fully self-contained — every item's active // state, badge count, and click handler is wired here — so it can be dropped -// into either layout. In the Channels space, destinations with a /website -// mirror (Home, Skills, MCP servers, Command Center) stay in that space; -// Inbox, Agents and New task have no mirror yet and jump back to Code. Search +// into either layout. In the Channels space every destination resolves to its +// /website mirror (Skills + MCP servers via the Customize page) so navigating +// stays in that space; in the Code space they use the canonical routes. Search // opens the command menu in place. export function SidebarNavSection({ commandCenterActiveCount: providedActiveCount, @@ -52,19 +54,25 @@ export function SidebarNavSection({ const view = useAppView(); const homeTabEnabled = useFeatureFlag(HOME_TAB_FLAG); - // When this section renders inside the Channels space, the destinations that - // have a /website mirror stay in that space; everything else (and the whole - // section in the Code space) uses the canonical routes. Inbox, Agents and New - // task have no mirror yet, so they intentionally jump back to Code. + // When this section renders inside the Channels space, every destination + // resolves to its /website mirror so navigating stays in that space; in the + // Code space they use the canonical routes. const inChannels = useRouterState({ select: (s) => s.location.pathname.startsWith("/website"), }); const goNewTask = () => openTaskInput(inChannels ? { space: "website" } : undefined); const goHome = inChannels ? navigateToWebsiteHome : navigateToHome; - const goSkills = inChannels ? navigateToWebsiteSkills : navigateToSkills; + const goInbox = inChannels ? navigateToWebsiteInbox : navigateToInbox; + const goAgents = inChannels ? navigateToWebsiteAgents : navigateToAgents; + // Skills + MCP servers live in the channels-space Customize page (each its own + // sub-route so they don't collapse onto the same destination); in Code they + // are still their own top-level destinations. + const goSkills = inChannels + ? navigateToWebsiteCustomizeSkills + : navigateToSkills; const goMcpServers = inChannels - ? navigateToWebsiteMcpServers + ? navigateToWebsiteCustomizeMcpServers : navigateToMcpServers; const goCommandCenter = inChannels ? navigateToWebsiteCommandCenter @@ -128,13 +136,13 @@ export function SidebarNavSection({ - + diff --git a/packages/ui/src/features/task-detail/components/TaskInput.tsx b/packages/ui/src/features/task-detail/components/TaskInput.tsx index 3a9e4167a0..f4cb7d6bbf 100644 --- a/packages/ui/src/features/task-detail/components/TaskInput.tsx +++ b/packages/ui/src/features/task-detail/components/TaskInput.tsx @@ -6,7 +6,7 @@ import type { Task } from "@posthog/shared/domain-types"; import { openSettings } from "@posthog/ui/features/settings/hooks/useOpenSettings"; import type { TaskInputReportAssociation } from "@posthog/ui/features/task-detail/stores/taskInputPrefillStore"; import { useTaskInputPrefillStore } from "@posthog/ui/features/task-detail/stores/taskInputPrefillStore"; -import { navigateToInbox } from "@posthog/ui/router/navigationBridge"; +import { navigateToInboxInCurrentSpace } from "@posthog/ui/router/navigationBridge"; import { useAppView } from "@posthog/ui/router/useAppView"; import { Flex, Text, Tooltip } from "@radix-ui/themes"; import { useQuery } from "@tanstack/react-query"; @@ -246,7 +246,7 @@ export function TaskInput({ const handleOpenAssociatedReport = useCallback(() => { if (!activeReportAssociation) return; - navigateToInbox(); + navigateToInboxInCurrentSpace(); setSelectedReportIds([activeReportAssociation.reportId]); }, [activeReportAssociation, setSelectedReportIds]); diff --git a/packages/ui/src/router/navigationBridge.ts b/packages/ui/src/router/navigationBridge.ts index f5859e384e..c23a92b180 100644 --- a/packages/ui/src/router/navigationBridge.ts +++ b/packages/ui/src/router/navigationBridge.ts @@ -1,3 +1,4 @@ +import { inboxSpaceFromPath } from "@posthog/core/inbox/reportMembership"; import type { NotificationTarget } from "@posthog/platform/notifications"; import { ANALYTICS_EVENTS } from "@posthog/shared"; import type { SettingsCategory } from "@posthog/ui/features/settings/types"; @@ -108,6 +109,18 @@ export function navigateToInbox(): void { void getRouterOrNull()?.navigate({ to: "/code/inbox" }); } +// Space-aware inbox open: from a /website route this opens the channels-space +// inbox so the user stays in their space; everywhere else it opens /code/inbox. +// Used by the Cmd+I shortcut and the "open associated report" action. +export function navigateToInboxInCurrentSpace(): void { + const pathname = getCurrentLocation()?.pathname ?? ""; + if (inboxSpaceFromPath(pathname) === "website") { + navigateToWebsiteInbox(); + } else { + navigateToInbox(); + } +} + export function navigateToInboxPullRequestDetail(reportId: string): void { void getRouterOrNull()?.navigate({ to: "/code/inbox/pulls/$reportId", @@ -192,12 +205,32 @@ export function navigateToCanvas(): void { void getRouterOrNull()?.navigate({ to: "/website" }); } -export function navigateToWebsiteSkills(): void { - void getRouterOrNull()?.navigate({ to: "/website/skills" }); +// The Channels-space inbox + agents mirrors. Same shared views as /code/inbox +// and /code/agents, but their internal navigation is space-aware so staying +// under /website keeps the channels chrome. +export function navigateToWebsiteInbox(): void { + void getRouterOrNull()?.navigate({ to: "/website/inbox" }); +} + +export function navigateToWebsiteAgents(): void { + void getRouterOrNull()?.navigate({ to: "/website/agents" }); +} + +// Customize is a channels-only page: a secondary sidebar hosting Skills and MCP +// servers. It replaces the old standalone /website/skills + /website/mcp-servers +// mirrors. The bare entry lands on Skills (the index redirect); the two +// sub-routes are addressable directly so separate nav items don't collapse onto +// the same destination. +export function navigateToWebsiteCustomize(): void { + void getRouterOrNull()?.navigate({ to: "/website/customize" }); +} + +export function navigateToWebsiteCustomizeSkills(): void { + void getRouterOrNull()?.navigate({ to: "/website/customize/skills" }); } -export function navigateToWebsiteMcpServers(): void { - void getRouterOrNull()?.navigate({ to: "/website/mcp-servers" }); +export function navigateToWebsiteCustomizeMcpServers(): void { + void getRouterOrNull()?.navigate({ to: "/website/customize/mcp-servers" }); } export function navigateToWebsiteCommandCenter(): void { diff --git a/packages/ui/src/router/routeTree.gen.ts b/packages/ui/src/router/routeTree.gen.ts index c378c10fa9..1e14b7bfd7 100644 --- a/packages/ui/src/router/routeTree.gen.ts +++ b/packages/ui/src/router/routeTree.gen.ts @@ -17,20 +17,33 @@ import { Route as IndexRouteImport } from './routes/index' import { Route as WebsiteIndexRouteImport } from './routes/website/index' import { Route as SettingsIndexRouteImport } from './routes/settings/index' import { Route as CodeIndexRouteImport } from './routes/code/index' -import { Route as WebsiteSkillsRouteImport } from './routes/website/skills' import { Route as WebsiteNewRouteImport } from './routes/website/new' -import { Route as WebsiteMcpServersRouteImport } from './routes/website/mcp-servers' +import { Route as WebsiteInboxRouteImport } from './routes/website/inbox' import { Route as WebsiteHomeRouteImport } from './routes/website/home' +import { Route as WebsiteCustomizeRouteImport } from './routes/website/customize' import { Route as WebsiteCommandCenterRouteImport } from './routes/website/command-center' +import { Route as WebsiteAgentsRouteImport } from './routes/website/agents' import { Route as SettingsCategoryRouteImport } from './routes/settings/$category' import { Route as FoldersFolderIdRouteImport } from './routes/folders/$folderId' import { Route as CodeInboxRouteImport } from './routes/code/inbox' import { Route as CodeHomeRouteImport } from './routes/code/home' import { Route as CodeArchivedRouteImport } from './routes/code/archived' import { Route as CodeAgentsRouteImport } from './routes/code/agents' +import { Route as WebsiteInboxIndexRouteImport } from './routes/website/inbox/index' +import { Route as WebsiteCustomizeIndexRouteImport } from './routes/website/customize/index' +import { Route as WebsiteAgentsIndexRouteImport } from './routes/website/agents/index' import { Route as WebsiteChannelIdIndexRouteImport } from './routes/website/$channelId/index' import { Route as CodeInboxIndexRouteImport } from './routes/code/inbox/index' import { Route as CodeAgentsIndexRouteImport } from './routes/code/agents/index' +import { Route as WebsiteInboxRunsRouteImport } from './routes/website/inbox/runs' +import { Route as WebsiteInboxReportsRouteImport } from './routes/website/inbox/reports' +import { Route as WebsiteInboxPullsRouteImport } from './routes/website/inbox/pulls' +import { Route as WebsiteInboxDismissedRouteImport } from './routes/website/inbox/dismissed' +import { Route as WebsiteInboxAgentsRouteImport } from './routes/website/inbox/agents' +import { Route as WebsiteCustomizeSkillsRouteImport } from './routes/website/customize/skills' +import { Route as WebsiteCustomizeMcpServersRouteImport } from './routes/website/customize/mcp-servers' +import { Route as WebsiteAgentsScoutsRouteImport } from './routes/website/agents/scouts' +import { Route as WebsiteAgentsApplicationsRouteImport } from './routes/website/agents/applications' import { Route as WebsiteChannelIdNewRouteImport } from './routes/website/$channelId/new' import { Route as WebsiteChannelIdInboxRouteImport } from './routes/website/$channelId/inbox' import { Route as WebsiteChannelIdHistoryRouteImport } from './routes/website/$channelId/history' @@ -45,12 +58,26 @@ import { Route as CodeInboxDismissedRouteImport } from './routes/code/inbox/dism import { Route as CodeInboxAgentsRouteImport } from './routes/code/inbox/agents' import { Route as CodeAgentsScoutsRouteImport } from './routes/code/agents/scouts' import { Route as CodeAgentsApplicationsRouteImport } from './routes/code/agents/applications' +import { Route as WebsiteInboxRunsIndexRouteImport } from './routes/website/inbox/runs.index' +import { Route as WebsiteInboxReportsIndexRouteImport } from './routes/website/inbox/reports.index' +import { Route as WebsiteInboxPullsIndexRouteImport } from './routes/website/inbox/pulls.index' +import { Route as WebsiteInboxDismissedIndexRouteImport } from './routes/website/inbox/dismissed.index' +import { Route as WebsiteAgentsScoutsIndexRouteImport } from './routes/website/agents/scouts.index' +import { Route as WebsiteAgentsApplicationsIndexRouteImport } from './routes/website/agents/applications/index' import { Route as CodeInboxRunsIndexRouteImport } from './routes/code/inbox/runs.index' import { Route as CodeInboxReportsIndexRouteImport } from './routes/code/inbox/reports.index' import { Route as CodeInboxPullsIndexRouteImport } from './routes/code/inbox/pulls.index' import { Route as CodeInboxDismissedIndexRouteImport } from './routes/code/inbox/dismissed.index' import { Route as CodeAgentsScoutsIndexRouteImport } from './routes/code/agents/scouts.index' import { Route as CodeAgentsApplicationsIndexRouteImport } from './routes/code/agents/applications/index' +import { Route as WebsiteInboxRunsReportIdRouteImport } from './routes/website/inbox/runs.$reportId' +import { Route as WebsiteInboxReportsReportIdRouteImport } from './routes/website/inbox/reports.$reportId' +import { Route as WebsiteInboxPullsReportIdRouteImport } from './routes/website/inbox/pulls.$reportId' +import { Route as WebsiteInboxDismissedReportIdRouteImport } from './routes/website/inbox/dismissed.$reportId' +import { Route as WebsiteAgentsScoutsScratchpadRouteImport } from './routes/website/agents/scouts.scratchpad' +import { Route as WebsiteAgentsScoutsSkillNameRouteImport } from './routes/website/agents/scouts.$skillName' +import { Route as WebsiteAgentsApplicationsApprovalsRouteImport } from './routes/website/agents/applications/approvals' +import { Route as WebsiteAgentsApplicationsIdOrSlugRouteImport } from './routes/website/agents/applications/$idOrSlug' import { Route as WebsiteChannelIdTasksTaskIdRouteImport } from './routes/website/$channelId/tasks/$taskId' import { Route as WebsiteChannelIdDashboardsDashboardIdRouteImport } from './routes/website/$channelId/dashboards/$dashboardId' import { Route as CodeTasksPendingKeyRouteImport } from './routes/code/tasks/pending.$key' @@ -63,15 +90,25 @@ import { Route as CodeAgentsScoutsFindingsRouteImport } from './routes/code/agen import { Route as CodeAgentsScoutsSkillNameRouteImport } from './routes/code/agents/scouts.$skillName' import { Route as CodeAgentsApplicationsApprovalsRouteImport } from './routes/code/agents/applications/approvals' import { Route as CodeAgentsApplicationsIdOrSlugRouteImport } from './routes/code/agents/applications/$idOrSlug' +import { Route as WebsiteAgentsScoutsSkillNameIndexRouteImport } from './routes/website/agents/scouts.$skillName.index' +import { Route as WebsiteAgentsApplicationsIdOrSlugIndexRouteImport } from './routes/website/agents/applications/$idOrSlug/index' import { Route as CodeAgentsScoutsSkillNameIndexRouteImport } from './routes/code/agents/scouts.$skillName.index' import { Route as CodeAgentsApplicationsIdOrSlugIndexRouteImport } from './routes/code/agents/applications/$idOrSlug/index' +import { Route as WebsiteAgentsApplicationsIdOrSlugUsersRouteImport } from './routes/website/agents/applications/$idOrSlug/users' +import { Route as WebsiteAgentsApplicationsIdOrSlugObservabilityRouteImport } from './routes/website/agents/applications/$idOrSlug/observability' +import { Route as WebsiteAgentsApplicationsIdOrSlugMemoryRouteImport } from './routes/website/agents/applications/$idOrSlug/memory' +import { Route as WebsiteAgentsApplicationsIdOrSlugConfigurationRouteImport } from './routes/website/agents/applications/$idOrSlug/configuration' +import { Route as WebsiteAgentsApplicationsIdOrSlugChatRouteImport } from './routes/website/agents/applications/$idOrSlug/chat' +import { Route as WebsiteAgentsApplicationsIdOrSlugApprovalsRouteImport } from './routes/website/agents/applications/$idOrSlug/approvals' import { Route as CodeAgentsApplicationsIdOrSlugUsersRouteImport } from './routes/code/agents/applications/$idOrSlug/users' import { Route as CodeAgentsApplicationsIdOrSlugObservabilityRouteImport } from './routes/code/agents/applications/$idOrSlug/observability' import { Route as CodeAgentsApplicationsIdOrSlugMemoryRouteImport } from './routes/code/agents/applications/$idOrSlug/memory' import { Route as CodeAgentsApplicationsIdOrSlugConfigurationRouteImport } from './routes/code/agents/applications/$idOrSlug/configuration' import { Route as CodeAgentsApplicationsIdOrSlugChatRouteImport } from './routes/code/agents/applications/$idOrSlug/chat' import { Route as CodeAgentsApplicationsIdOrSlugApprovalsRouteImport } from './routes/code/agents/applications/$idOrSlug/approvals' +import { Route as WebsiteAgentsApplicationsIdOrSlugSessionsIndexRouteImport } from './routes/website/agents/applications/$idOrSlug/sessions.index' import { Route as CodeAgentsApplicationsIdOrSlugSessionsIndexRouteImport } from './routes/code/agents/applications/$idOrSlug/sessions.index' +import { Route as WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRouteImport } from './routes/website/agents/applications/$idOrSlug/sessions.$sessionId' import { Route as CodeAgentsApplicationsIdOrSlugSessionsSessionIdRouteImport } from './routes/code/agents/applications/$idOrSlug/sessions.$sessionId' const WebsiteRoute = WebsiteRouteImport.update({ @@ -114,19 +151,14 @@ const CodeIndexRoute = CodeIndexRouteImport.update({ path: '/code/', getParentRoute: () => rootRouteImport, } as any) -const WebsiteSkillsRoute = WebsiteSkillsRouteImport.update({ - id: '/skills', - path: '/skills', - getParentRoute: () => WebsiteRoute, -} as any) const WebsiteNewRoute = WebsiteNewRouteImport.update({ id: '/new', path: '/new', getParentRoute: () => WebsiteRoute, } as any) -const WebsiteMcpServersRoute = WebsiteMcpServersRouteImport.update({ - id: '/mcp-servers', - path: '/mcp-servers', +const WebsiteInboxRoute = WebsiteInboxRouteImport.update({ + id: '/inbox', + path: '/inbox', getParentRoute: () => WebsiteRoute, } as any) const WebsiteHomeRoute = WebsiteHomeRouteImport.update({ @@ -134,11 +166,21 @@ const WebsiteHomeRoute = WebsiteHomeRouteImport.update({ path: '/home', getParentRoute: () => WebsiteRoute, } as any) +const WebsiteCustomizeRoute = WebsiteCustomizeRouteImport.update({ + id: '/customize', + path: '/customize', + getParentRoute: () => WebsiteRoute, +} as any) const WebsiteCommandCenterRoute = WebsiteCommandCenterRouteImport.update({ id: '/command-center', path: '/command-center', getParentRoute: () => WebsiteRoute, } as any) +const WebsiteAgentsRoute = WebsiteAgentsRouteImport.update({ + id: '/agents', + path: '/agents', + getParentRoute: () => WebsiteRoute, +} as any) const SettingsCategoryRoute = SettingsCategoryRouteImport.update({ id: '/settings/$category', path: '/settings/$category', @@ -169,6 +211,21 @@ const CodeAgentsRoute = CodeAgentsRouteImport.update({ path: '/code/agents', getParentRoute: () => rootRouteImport, } as any) +const WebsiteInboxIndexRoute = WebsiteInboxIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteInboxRoute, +} as any) +const WebsiteCustomizeIndexRoute = WebsiteCustomizeIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteCustomizeRoute, +} as any) +const WebsiteAgentsIndexRoute = WebsiteAgentsIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteAgentsRoute, +} as any) const WebsiteChannelIdIndexRoute = WebsiteChannelIdIndexRouteImport.update({ id: '/$channelId/', path: '/$channelId/', @@ -184,6 +241,53 @@ const CodeAgentsIndexRoute = CodeAgentsIndexRouteImport.update({ path: '/', getParentRoute: () => CodeAgentsRoute, } as any) +const WebsiteInboxRunsRoute = WebsiteInboxRunsRouteImport.update({ + id: '/runs', + path: '/runs', + getParentRoute: () => WebsiteInboxRoute, +} as any) +const WebsiteInboxReportsRoute = WebsiteInboxReportsRouteImport.update({ + id: '/reports', + path: '/reports', + getParentRoute: () => WebsiteInboxRoute, +} as any) +const WebsiteInboxPullsRoute = WebsiteInboxPullsRouteImport.update({ + id: '/pulls', + path: '/pulls', + getParentRoute: () => WebsiteInboxRoute, +} as any) +const WebsiteInboxDismissedRoute = WebsiteInboxDismissedRouteImport.update({ + id: '/dismissed', + path: '/dismissed', + getParentRoute: () => WebsiteInboxRoute, +} as any) +const WebsiteInboxAgentsRoute = WebsiteInboxAgentsRouteImport.update({ + id: '/agents', + path: '/agents', + getParentRoute: () => WebsiteInboxRoute, +} as any) +const WebsiteCustomizeSkillsRoute = WebsiteCustomizeSkillsRouteImport.update({ + id: '/skills', + path: '/skills', + getParentRoute: () => WebsiteCustomizeRoute, +} as any) +const WebsiteCustomizeMcpServersRoute = + WebsiteCustomizeMcpServersRouteImport.update({ + id: '/mcp-servers', + path: '/mcp-servers', + getParentRoute: () => WebsiteCustomizeRoute, + } as any) +const WebsiteAgentsScoutsRoute = WebsiteAgentsScoutsRouteImport.update({ + id: '/scouts', + path: '/scouts', + getParentRoute: () => WebsiteAgentsRoute, +} as any) +const WebsiteAgentsApplicationsRoute = + WebsiteAgentsApplicationsRouteImport.update({ + id: '/applications', + path: '/applications', + getParentRoute: () => WebsiteAgentsRoute, + } as any) const WebsiteChannelIdNewRoute = WebsiteChannelIdNewRouteImport.update({ id: '/$channelId/new', path: '/$channelId/new', @@ -256,6 +360,40 @@ const CodeAgentsApplicationsRoute = CodeAgentsApplicationsRouteImport.update({ path: '/applications', getParentRoute: () => CodeAgentsRoute, } as any) +const WebsiteInboxRunsIndexRoute = WebsiteInboxRunsIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteInboxRunsRoute, +} as any) +const WebsiteInboxReportsIndexRoute = + WebsiteInboxReportsIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteInboxReportsRoute, + } as any) +const WebsiteInboxPullsIndexRoute = WebsiteInboxPullsIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteInboxPullsRoute, +} as any) +const WebsiteInboxDismissedIndexRoute = + WebsiteInboxDismissedIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteInboxDismissedRoute, + } as any) +const WebsiteAgentsScoutsIndexRoute = + WebsiteAgentsScoutsIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteAgentsScoutsRoute, + } as any) +const WebsiteAgentsApplicationsIndexRoute = + WebsiteAgentsApplicationsIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteAgentsApplicationsRoute, + } as any) const CodeInboxRunsIndexRoute = CodeInboxRunsIndexRouteImport.update({ id: '/', path: '/', @@ -287,6 +425,54 @@ const CodeAgentsApplicationsIndexRoute = path: '/', getParentRoute: () => CodeAgentsApplicationsRoute, } as any) +const WebsiteInboxRunsReportIdRoute = + WebsiteInboxRunsReportIdRouteImport.update({ + id: '/$reportId', + path: '/$reportId', + getParentRoute: () => WebsiteInboxRunsRoute, + } as any) +const WebsiteInboxReportsReportIdRoute = + WebsiteInboxReportsReportIdRouteImport.update({ + id: '/$reportId', + path: '/$reportId', + getParentRoute: () => WebsiteInboxReportsRoute, + } as any) +const WebsiteInboxPullsReportIdRoute = + WebsiteInboxPullsReportIdRouteImport.update({ + id: '/$reportId', + path: '/$reportId', + getParentRoute: () => WebsiteInboxPullsRoute, + } as any) +const WebsiteInboxDismissedReportIdRoute = + WebsiteInboxDismissedReportIdRouteImport.update({ + id: '/$reportId', + path: '/$reportId', + getParentRoute: () => WebsiteInboxDismissedRoute, + } as any) +const WebsiteAgentsScoutsScratchpadRoute = + WebsiteAgentsScoutsScratchpadRouteImport.update({ + id: '/scratchpad', + path: '/scratchpad', + getParentRoute: () => WebsiteAgentsScoutsRoute, + } as any) +const WebsiteAgentsScoutsSkillNameRoute = + WebsiteAgentsScoutsSkillNameRouteImport.update({ + id: '/$skillName', + path: '/$skillName', + getParentRoute: () => WebsiteAgentsScoutsRoute, + } as any) +const WebsiteAgentsApplicationsApprovalsRoute = + WebsiteAgentsApplicationsApprovalsRouteImport.update({ + id: '/approvals', + path: '/approvals', + getParentRoute: () => WebsiteAgentsApplicationsRoute, + } as any) +const WebsiteAgentsApplicationsIdOrSlugRoute = + WebsiteAgentsApplicationsIdOrSlugRouteImport.update({ + id: '/$idOrSlug', + path: '/$idOrSlug', + getParentRoute: () => WebsiteAgentsApplicationsRoute, + } as any) const WebsiteChannelIdTasksTaskIdRoute = WebsiteChannelIdTasksTaskIdRouteImport.update({ id: '/$channelId/tasks/$taskId', @@ -356,6 +542,18 @@ const CodeAgentsApplicationsIdOrSlugRoute = path: '/$idOrSlug', getParentRoute: () => CodeAgentsApplicationsRoute, } as any) +const WebsiteAgentsScoutsSkillNameIndexRoute = + WebsiteAgentsScoutsSkillNameIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteAgentsScoutsSkillNameRoute, + } as any) +const WebsiteAgentsApplicationsIdOrSlugIndexRoute = + WebsiteAgentsApplicationsIdOrSlugIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) const CodeAgentsScoutsSkillNameIndexRoute = CodeAgentsScoutsSkillNameIndexRouteImport.update({ id: '/', @@ -368,6 +566,42 @@ const CodeAgentsApplicationsIdOrSlugIndexRoute = path: '/', getParentRoute: () => CodeAgentsApplicationsIdOrSlugRoute, } as any) +const WebsiteAgentsApplicationsIdOrSlugUsersRoute = + WebsiteAgentsApplicationsIdOrSlugUsersRouteImport.update({ + id: '/users', + path: '/users', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) +const WebsiteAgentsApplicationsIdOrSlugObservabilityRoute = + WebsiteAgentsApplicationsIdOrSlugObservabilityRouteImport.update({ + id: '/observability', + path: '/observability', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) +const WebsiteAgentsApplicationsIdOrSlugMemoryRoute = + WebsiteAgentsApplicationsIdOrSlugMemoryRouteImport.update({ + id: '/memory', + path: '/memory', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) +const WebsiteAgentsApplicationsIdOrSlugConfigurationRoute = + WebsiteAgentsApplicationsIdOrSlugConfigurationRouteImport.update({ + id: '/configuration', + path: '/configuration', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) +const WebsiteAgentsApplicationsIdOrSlugChatRoute = + WebsiteAgentsApplicationsIdOrSlugChatRouteImport.update({ + id: '/chat', + path: '/chat', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) +const WebsiteAgentsApplicationsIdOrSlugApprovalsRoute = + WebsiteAgentsApplicationsIdOrSlugApprovalsRouteImport.update({ + id: '/approvals', + path: '/approvals', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) const CodeAgentsApplicationsIdOrSlugUsersRoute = CodeAgentsApplicationsIdOrSlugUsersRouteImport.update({ id: '/users', @@ -404,12 +638,24 @@ const CodeAgentsApplicationsIdOrSlugApprovalsRoute = path: '/approvals', getParentRoute: () => CodeAgentsApplicationsIdOrSlugRoute, } as any) +const WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute = + WebsiteAgentsApplicationsIdOrSlugSessionsIndexRouteImport.update({ + id: '/sessions/', + path: '/sessions/', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) const CodeAgentsApplicationsIdOrSlugSessionsIndexRoute = CodeAgentsApplicationsIdOrSlugSessionsIndexRouteImport.update({ id: '/sessions/', path: '/sessions/', getParentRoute: () => CodeAgentsApplicationsIdOrSlugRoute, } as any) +const WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute = + WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRouteImport.update({ + id: '/sessions/$sessionId', + path: '/sessions/$sessionId', + getParentRoute: () => WebsiteAgentsApplicationsIdOrSlugRoute, + } as any) const CodeAgentsApplicationsIdOrSlugSessionsSessionIdRoute = CodeAgentsApplicationsIdOrSlugSessionsSessionIdRouteImport.update({ id: '/sessions/$sessionId', @@ -429,11 +675,12 @@ export interface FileRoutesByFullPath { '/code/inbox': typeof CodeInboxRouteWithChildren '/folders/$folderId': typeof FoldersFolderIdRoute '/settings/$category': typeof SettingsCategoryRoute + '/website/agents': typeof WebsiteAgentsRouteWithChildren '/website/command-center': typeof WebsiteCommandCenterRoute + '/website/customize': typeof WebsiteCustomizeRouteWithChildren '/website/home': typeof WebsiteHomeRoute - '/website/mcp-servers': typeof WebsiteMcpServersRoute + '/website/inbox': typeof WebsiteInboxRouteWithChildren '/website/new': typeof WebsiteNewRoute - '/website/skills': typeof WebsiteSkillsRoute '/code/': typeof CodeIndexRoute '/settings/': typeof SettingsIndexRoute '/website/': typeof WebsiteIndexRoute @@ -451,9 +698,21 @@ export interface FileRoutesByFullPath { '/website/$channelId/history': typeof WebsiteChannelIdHistoryRoute '/website/$channelId/inbox': typeof WebsiteChannelIdInboxRoute '/website/$channelId/new': typeof WebsiteChannelIdNewRoute + '/website/agents/applications': typeof WebsiteAgentsApplicationsRouteWithChildren + '/website/agents/scouts': typeof WebsiteAgentsScoutsRouteWithChildren + '/website/customize/mcp-servers': typeof WebsiteCustomizeMcpServersRoute + '/website/customize/skills': typeof WebsiteCustomizeSkillsRoute + '/website/inbox/agents': typeof WebsiteInboxAgentsRoute + '/website/inbox/dismissed': typeof WebsiteInboxDismissedRouteWithChildren + '/website/inbox/pulls': typeof WebsiteInboxPullsRouteWithChildren + '/website/inbox/reports': typeof WebsiteInboxReportsRouteWithChildren + '/website/inbox/runs': typeof WebsiteInboxRunsRouteWithChildren '/code/agents/': typeof CodeAgentsIndexRoute '/code/inbox/': typeof CodeInboxIndexRoute '/website/$channelId/': typeof WebsiteChannelIdIndexRoute + '/website/agents/': typeof WebsiteAgentsIndexRoute + '/website/customize/': typeof WebsiteCustomizeIndexRoute + '/website/inbox/': typeof WebsiteInboxIndexRoute '/code/agents/applications/$idOrSlug': typeof CodeAgentsApplicationsIdOrSlugRouteWithChildren '/code/agents/applications/approvals': typeof CodeAgentsApplicationsApprovalsRoute '/code/agents/scouts/$skillName': typeof CodeAgentsScoutsSkillNameRouteWithChildren @@ -466,22 +725,46 @@ export interface FileRoutesByFullPath { '/code/tasks/pending/$key': typeof CodeTasksPendingKeyRoute '/website/$channelId/dashboards/$dashboardId': typeof WebsiteChannelIdDashboardsDashboardIdRoute '/website/$channelId/tasks/$taskId': typeof WebsiteChannelIdTasksTaskIdRoute + '/website/agents/applications/$idOrSlug': typeof WebsiteAgentsApplicationsIdOrSlugRouteWithChildren + '/website/agents/applications/approvals': typeof WebsiteAgentsApplicationsApprovalsRoute + '/website/agents/scouts/$skillName': typeof WebsiteAgentsScoutsSkillNameRouteWithChildren + '/website/agents/scouts/scratchpad': typeof WebsiteAgentsScoutsScratchpadRoute + '/website/inbox/dismissed/$reportId': typeof WebsiteInboxDismissedReportIdRoute + '/website/inbox/pulls/$reportId': typeof WebsiteInboxPullsReportIdRoute + '/website/inbox/reports/$reportId': typeof WebsiteInboxReportsReportIdRoute + '/website/inbox/runs/$reportId': typeof WebsiteInboxRunsReportIdRoute '/code/agents/applications/': typeof CodeAgentsApplicationsIndexRoute '/code/agents/scouts/': typeof CodeAgentsScoutsIndexRoute '/code/inbox/dismissed/': typeof CodeInboxDismissedIndexRoute '/code/inbox/pulls/': typeof CodeInboxPullsIndexRoute '/code/inbox/reports/': typeof CodeInboxReportsIndexRoute '/code/inbox/runs/': typeof CodeInboxRunsIndexRoute + '/website/agents/applications/': typeof WebsiteAgentsApplicationsIndexRoute + '/website/agents/scouts/': typeof WebsiteAgentsScoutsIndexRoute + '/website/inbox/dismissed/': typeof WebsiteInboxDismissedIndexRoute + '/website/inbox/pulls/': typeof WebsiteInboxPullsIndexRoute + '/website/inbox/reports/': typeof WebsiteInboxReportsIndexRoute + '/website/inbox/runs/': typeof WebsiteInboxRunsIndexRoute '/code/agents/applications/$idOrSlug/approvals': typeof CodeAgentsApplicationsIdOrSlugApprovalsRoute '/code/agents/applications/$idOrSlug/chat': typeof CodeAgentsApplicationsIdOrSlugChatRoute '/code/agents/applications/$idOrSlug/configuration': typeof CodeAgentsApplicationsIdOrSlugConfigurationRoute '/code/agents/applications/$idOrSlug/memory': typeof CodeAgentsApplicationsIdOrSlugMemoryRoute '/code/agents/applications/$idOrSlug/observability': typeof CodeAgentsApplicationsIdOrSlugObservabilityRoute '/code/agents/applications/$idOrSlug/users': typeof CodeAgentsApplicationsIdOrSlugUsersRoute + '/website/agents/applications/$idOrSlug/approvals': typeof WebsiteAgentsApplicationsIdOrSlugApprovalsRoute + '/website/agents/applications/$idOrSlug/chat': typeof WebsiteAgentsApplicationsIdOrSlugChatRoute + '/website/agents/applications/$idOrSlug/configuration': typeof WebsiteAgentsApplicationsIdOrSlugConfigurationRoute + '/website/agents/applications/$idOrSlug/memory': typeof WebsiteAgentsApplicationsIdOrSlugMemoryRoute + '/website/agents/applications/$idOrSlug/observability': typeof WebsiteAgentsApplicationsIdOrSlugObservabilityRoute + '/website/agents/applications/$idOrSlug/users': typeof WebsiteAgentsApplicationsIdOrSlugUsersRoute '/code/agents/applications/$idOrSlug/': typeof CodeAgentsApplicationsIdOrSlugIndexRoute '/code/agents/scouts/$skillName/': typeof CodeAgentsScoutsSkillNameIndexRoute + '/website/agents/applications/$idOrSlug/': typeof WebsiteAgentsApplicationsIdOrSlugIndexRoute + '/website/agents/scouts/$skillName/': typeof WebsiteAgentsScoutsSkillNameIndexRoute '/code/agents/applications/$idOrSlug/sessions/$sessionId': typeof CodeAgentsApplicationsIdOrSlugSessionsSessionIdRoute + '/website/agents/applications/$idOrSlug/sessions/$sessionId': typeof WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute '/code/agents/applications/$idOrSlug/sessions/': typeof CodeAgentsApplicationsIdOrSlugSessionsIndexRoute + '/website/agents/applications/$idOrSlug/sessions/': typeof WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute } export interface FileRoutesByTo { '/': typeof IndexRoute @@ -494,9 +777,7 @@ export interface FileRoutesByTo { '/settings/$category': typeof SettingsCategoryRoute '/website/command-center': typeof WebsiteCommandCenterRoute '/website/home': typeof WebsiteHomeRoute - '/website/mcp-servers': typeof WebsiteMcpServersRoute '/website/new': typeof WebsiteNewRoute - '/website/skills': typeof WebsiteSkillsRoute '/code': typeof CodeIndexRoute '/settings': typeof SettingsIndexRoute '/website': typeof WebsiteIndexRoute @@ -508,9 +789,15 @@ export interface FileRoutesByTo { '/website/$channelId/history': typeof WebsiteChannelIdHistoryRoute '/website/$channelId/inbox': typeof WebsiteChannelIdInboxRoute '/website/$channelId/new': typeof WebsiteChannelIdNewRoute + '/website/customize/mcp-servers': typeof WebsiteCustomizeMcpServersRoute + '/website/customize/skills': typeof WebsiteCustomizeSkillsRoute + '/website/inbox/agents': typeof WebsiteInboxAgentsRoute '/code/agents': typeof CodeAgentsIndexRoute '/code/inbox': typeof CodeInboxIndexRoute '/website/$channelId': typeof WebsiteChannelIdIndexRoute + '/website/agents': typeof WebsiteAgentsIndexRoute + '/website/customize': typeof WebsiteCustomizeIndexRoute + '/website/inbox': typeof WebsiteInboxIndexRoute '/code/agents/applications/approvals': typeof CodeAgentsApplicationsApprovalsRoute '/code/agents/scouts/findings': typeof CodeAgentsScoutsFindingsRoute '/code/agents/scouts/scratchpad': typeof CodeAgentsScoutsScratchpadRoute @@ -521,22 +808,44 @@ export interface FileRoutesByTo { '/code/tasks/pending/$key': typeof CodeTasksPendingKeyRoute '/website/$channelId/dashboards/$dashboardId': typeof WebsiteChannelIdDashboardsDashboardIdRoute '/website/$channelId/tasks/$taskId': typeof WebsiteChannelIdTasksTaskIdRoute + '/website/agents/applications/approvals': typeof WebsiteAgentsApplicationsApprovalsRoute + '/website/agents/scouts/scratchpad': typeof WebsiteAgentsScoutsScratchpadRoute + '/website/inbox/dismissed/$reportId': typeof WebsiteInboxDismissedReportIdRoute + '/website/inbox/pulls/$reportId': typeof WebsiteInboxPullsReportIdRoute + '/website/inbox/reports/$reportId': typeof WebsiteInboxReportsReportIdRoute + '/website/inbox/runs/$reportId': typeof WebsiteInboxRunsReportIdRoute '/code/agents/applications': typeof CodeAgentsApplicationsIndexRoute '/code/agents/scouts': typeof CodeAgentsScoutsIndexRoute '/code/inbox/dismissed': typeof CodeInboxDismissedIndexRoute '/code/inbox/pulls': typeof CodeInboxPullsIndexRoute '/code/inbox/reports': typeof CodeInboxReportsIndexRoute '/code/inbox/runs': typeof CodeInboxRunsIndexRoute + '/website/agents/applications': typeof WebsiteAgentsApplicationsIndexRoute + '/website/agents/scouts': typeof WebsiteAgentsScoutsIndexRoute + '/website/inbox/dismissed': typeof WebsiteInboxDismissedIndexRoute + '/website/inbox/pulls': typeof WebsiteInboxPullsIndexRoute + '/website/inbox/reports': typeof WebsiteInboxReportsIndexRoute + '/website/inbox/runs': typeof WebsiteInboxRunsIndexRoute '/code/agents/applications/$idOrSlug/approvals': typeof CodeAgentsApplicationsIdOrSlugApprovalsRoute '/code/agents/applications/$idOrSlug/chat': typeof CodeAgentsApplicationsIdOrSlugChatRoute '/code/agents/applications/$idOrSlug/configuration': typeof CodeAgentsApplicationsIdOrSlugConfigurationRoute '/code/agents/applications/$idOrSlug/memory': typeof CodeAgentsApplicationsIdOrSlugMemoryRoute '/code/agents/applications/$idOrSlug/observability': typeof CodeAgentsApplicationsIdOrSlugObservabilityRoute '/code/agents/applications/$idOrSlug/users': typeof CodeAgentsApplicationsIdOrSlugUsersRoute + '/website/agents/applications/$idOrSlug/approvals': typeof WebsiteAgentsApplicationsIdOrSlugApprovalsRoute + '/website/agents/applications/$idOrSlug/chat': typeof WebsiteAgentsApplicationsIdOrSlugChatRoute + '/website/agents/applications/$idOrSlug/configuration': typeof WebsiteAgentsApplicationsIdOrSlugConfigurationRoute + '/website/agents/applications/$idOrSlug/memory': typeof WebsiteAgentsApplicationsIdOrSlugMemoryRoute + '/website/agents/applications/$idOrSlug/observability': typeof WebsiteAgentsApplicationsIdOrSlugObservabilityRoute + '/website/agents/applications/$idOrSlug/users': typeof WebsiteAgentsApplicationsIdOrSlugUsersRoute '/code/agents/applications/$idOrSlug': typeof CodeAgentsApplicationsIdOrSlugIndexRoute '/code/agents/scouts/$skillName': typeof CodeAgentsScoutsSkillNameIndexRoute + '/website/agents/applications/$idOrSlug': typeof WebsiteAgentsApplicationsIdOrSlugIndexRoute + '/website/agents/scouts/$skillName': typeof WebsiteAgentsScoutsSkillNameIndexRoute '/code/agents/applications/$idOrSlug/sessions/$sessionId': typeof CodeAgentsApplicationsIdOrSlugSessionsSessionIdRoute + '/website/agents/applications/$idOrSlug/sessions/$sessionId': typeof WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute '/code/agents/applications/$idOrSlug/sessions': typeof CodeAgentsApplicationsIdOrSlugSessionsIndexRoute + '/website/agents/applications/$idOrSlug/sessions': typeof WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute } export interface FileRoutesById { __root__: typeof rootRouteImport @@ -551,11 +860,12 @@ export interface FileRoutesById { '/code/inbox': typeof CodeInboxRouteWithChildren '/folders/$folderId': typeof FoldersFolderIdRoute '/settings/$category': typeof SettingsCategoryRoute + '/website/agents': typeof WebsiteAgentsRouteWithChildren '/website/command-center': typeof WebsiteCommandCenterRoute + '/website/customize': typeof WebsiteCustomizeRouteWithChildren '/website/home': typeof WebsiteHomeRoute - '/website/mcp-servers': typeof WebsiteMcpServersRoute + '/website/inbox': typeof WebsiteInboxRouteWithChildren '/website/new': typeof WebsiteNewRoute - '/website/skills': typeof WebsiteSkillsRoute '/code/': typeof CodeIndexRoute '/settings/': typeof SettingsIndexRoute '/website/': typeof WebsiteIndexRoute @@ -573,9 +883,21 @@ export interface FileRoutesById { '/website/$channelId/history': typeof WebsiteChannelIdHistoryRoute '/website/$channelId/inbox': typeof WebsiteChannelIdInboxRoute '/website/$channelId/new': typeof WebsiteChannelIdNewRoute + '/website/agents/applications': typeof WebsiteAgentsApplicationsRouteWithChildren + '/website/agents/scouts': typeof WebsiteAgentsScoutsRouteWithChildren + '/website/customize/mcp-servers': typeof WebsiteCustomizeMcpServersRoute + '/website/customize/skills': typeof WebsiteCustomizeSkillsRoute + '/website/inbox/agents': typeof WebsiteInboxAgentsRoute + '/website/inbox/dismissed': typeof WebsiteInboxDismissedRouteWithChildren + '/website/inbox/pulls': typeof WebsiteInboxPullsRouteWithChildren + '/website/inbox/reports': typeof WebsiteInboxReportsRouteWithChildren + '/website/inbox/runs': typeof WebsiteInboxRunsRouteWithChildren '/code/agents/': typeof CodeAgentsIndexRoute '/code/inbox/': typeof CodeInboxIndexRoute '/website/$channelId/': typeof WebsiteChannelIdIndexRoute + '/website/agents/': typeof WebsiteAgentsIndexRoute + '/website/customize/': typeof WebsiteCustomizeIndexRoute + '/website/inbox/': typeof WebsiteInboxIndexRoute '/code/agents/applications/$idOrSlug': typeof CodeAgentsApplicationsIdOrSlugRouteWithChildren '/code/agents/applications/approvals': typeof CodeAgentsApplicationsApprovalsRoute '/code/agents/scouts/$skillName': typeof CodeAgentsScoutsSkillNameRouteWithChildren @@ -588,22 +910,46 @@ export interface FileRoutesById { '/code/tasks/pending/$key': typeof CodeTasksPendingKeyRoute '/website/$channelId/dashboards/$dashboardId': typeof WebsiteChannelIdDashboardsDashboardIdRoute '/website/$channelId/tasks/$taskId': typeof WebsiteChannelIdTasksTaskIdRoute + '/website/agents/applications/$idOrSlug': typeof WebsiteAgentsApplicationsIdOrSlugRouteWithChildren + '/website/agents/applications/approvals': typeof WebsiteAgentsApplicationsApprovalsRoute + '/website/agents/scouts/$skillName': typeof WebsiteAgentsScoutsSkillNameRouteWithChildren + '/website/agents/scouts/scratchpad': typeof WebsiteAgentsScoutsScratchpadRoute + '/website/inbox/dismissed/$reportId': typeof WebsiteInboxDismissedReportIdRoute + '/website/inbox/pulls/$reportId': typeof WebsiteInboxPullsReportIdRoute + '/website/inbox/reports/$reportId': typeof WebsiteInboxReportsReportIdRoute + '/website/inbox/runs/$reportId': typeof WebsiteInboxRunsReportIdRoute '/code/agents/applications/': typeof CodeAgentsApplicationsIndexRoute '/code/agents/scouts/': typeof CodeAgentsScoutsIndexRoute '/code/inbox/dismissed/': typeof CodeInboxDismissedIndexRoute '/code/inbox/pulls/': typeof CodeInboxPullsIndexRoute '/code/inbox/reports/': typeof CodeInboxReportsIndexRoute '/code/inbox/runs/': typeof CodeInboxRunsIndexRoute + '/website/agents/applications/': typeof WebsiteAgentsApplicationsIndexRoute + '/website/agents/scouts/': typeof WebsiteAgentsScoutsIndexRoute + '/website/inbox/dismissed/': typeof WebsiteInboxDismissedIndexRoute + '/website/inbox/pulls/': typeof WebsiteInboxPullsIndexRoute + '/website/inbox/reports/': typeof WebsiteInboxReportsIndexRoute + '/website/inbox/runs/': typeof WebsiteInboxRunsIndexRoute '/code/agents/applications/$idOrSlug/approvals': typeof CodeAgentsApplicationsIdOrSlugApprovalsRoute '/code/agents/applications/$idOrSlug/chat': typeof CodeAgentsApplicationsIdOrSlugChatRoute '/code/agents/applications/$idOrSlug/configuration': typeof CodeAgentsApplicationsIdOrSlugConfigurationRoute '/code/agents/applications/$idOrSlug/memory': typeof CodeAgentsApplicationsIdOrSlugMemoryRoute '/code/agents/applications/$idOrSlug/observability': typeof CodeAgentsApplicationsIdOrSlugObservabilityRoute '/code/agents/applications/$idOrSlug/users': typeof CodeAgentsApplicationsIdOrSlugUsersRoute + '/website/agents/applications/$idOrSlug/approvals': typeof WebsiteAgentsApplicationsIdOrSlugApprovalsRoute + '/website/agents/applications/$idOrSlug/chat': typeof WebsiteAgentsApplicationsIdOrSlugChatRoute + '/website/agents/applications/$idOrSlug/configuration': typeof WebsiteAgentsApplicationsIdOrSlugConfigurationRoute + '/website/agents/applications/$idOrSlug/memory': typeof WebsiteAgentsApplicationsIdOrSlugMemoryRoute + '/website/agents/applications/$idOrSlug/observability': typeof WebsiteAgentsApplicationsIdOrSlugObservabilityRoute + '/website/agents/applications/$idOrSlug/users': typeof WebsiteAgentsApplicationsIdOrSlugUsersRoute '/code/agents/applications/$idOrSlug/': typeof CodeAgentsApplicationsIdOrSlugIndexRoute '/code/agents/scouts/$skillName/': typeof CodeAgentsScoutsSkillNameIndexRoute + '/website/agents/applications/$idOrSlug/': typeof WebsiteAgentsApplicationsIdOrSlugIndexRoute + '/website/agents/scouts/$skillName/': typeof WebsiteAgentsScoutsSkillNameIndexRoute '/code/agents/applications/$idOrSlug/sessions/$sessionId': typeof CodeAgentsApplicationsIdOrSlugSessionsSessionIdRoute + '/website/agents/applications/$idOrSlug/sessions/$sessionId': typeof WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute '/code/agents/applications/$idOrSlug/sessions/': typeof CodeAgentsApplicationsIdOrSlugSessionsIndexRoute + '/website/agents/applications/$idOrSlug/sessions/': typeof WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath @@ -619,11 +965,12 @@ export interface FileRouteTypes { | '/code/inbox' | '/folders/$folderId' | '/settings/$category' + | '/website/agents' | '/website/command-center' + | '/website/customize' | '/website/home' - | '/website/mcp-servers' + | '/website/inbox' | '/website/new' - | '/website/skills' | '/code/' | '/settings/' | '/website/' @@ -641,9 +988,21 @@ export interface FileRouteTypes { | '/website/$channelId/history' | '/website/$channelId/inbox' | '/website/$channelId/new' + | '/website/agents/applications' + | '/website/agents/scouts' + | '/website/customize/mcp-servers' + | '/website/customize/skills' + | '/website/inbox/agents' + | '/website/inbox/dismissed' + | '/website/inbox/pulls' + | '/website/inbox/reports' + | '/website/inbox/runs' | '/code/agents/' | '/code/inbox/' | '/website/$channelId/' + | '/website/agents/' + | '/website/customize/' + | '/website/inbox/' | '/code/agents/applications/$idOrSlug' | '/code/agents/applications/approvals' | '/code/agents/scouts/$skillName' @@ -656,22 +1015,46 @@ export interface FileRouteTypes { | '/code/tasks/pending/$key' | '/website/$channelId/dashboards/$dashboardId' | '/website/$channelId/tasks/$taskId' + | '/website/agents/applications/$idOrSlug' + | '/website/agents/applications/approvals' + | '/website/agents/scouts/$skillName' + | '/website/agents/scouts/scratchpad' + | '/website/inbox/dismissed/$reportId' + | '/website/inbox/pulls/$reportId' + | '/website/inbox/reports/$reportId' + | '/website/inbox/runs/$reportId' | '/code/agents/applications/' | '/code/agents/scouts/' | '/code/inbox/dismissed/' | '/code/inbox/pulls/' | '/code/inbox/reports/' | '/code/inbox/runs/' + | '/website/agents/applications/' + | '/website/agents/scouts/' + | '/website/inbox/dismissed/' + | '/website/inbox/pulls/' + | '/website/inbox/reports/' + | '/website/inbox/runs/' | '/code/agents/applications/$idOrSlug/approvals' | '/code/agents/applications/$idOrSlug/chat' | '/code/agents/applications/$idOrSlug/configuration' | '/code/agents/applications/$idOrSlug/memory' | '/code/agents/applications/$idOrSlug/observability' | '/code/agents/applications/$idOrSlug/users' + | '/website/agents/applications/$idOrSlug/approvals' + | '/website/agents/applications/$idOrSlug/chat' + | '/website/agents/applications/$idOrSlug/configuration' + | '/website/agents/applications/$idOrSlug/memory' + | '/website/agents/applications/$idOrSlug/observability' + | '/website/agents/applications/$idOrSlug/users' | '/code/agents/applications/$idOrSlug/' | '/code/agents/scouts/$skillName/' + | '/website/agents/applications/$idOrSlug/' + | '/website/agents/scouts/$skillName/' | '/code/agents/applications/$idOrSlug/sessions/$sessionId' + | '/website/agents/applications/$idOrSlug/sessions/$sessionId' | '/code/agents/applications/$idOrSlug/sessions/' + | '/website/agents/applications/$idOrSlug/sessions/' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -684,9 +1067,7 @@ export interface FileRouteTypes { | '/settings/$category' | '/website/command-center' | '/website/home' - | '/website/mcp-servers' | '/website/new' - | '/website/skills' | '/code' | '/settings' | '/website' @@ -698,9 +1079,15 @@ export interface FileRouteTypes { | '/website/$channelId/history' | '/website/$channelId/inbox' | '/website/$channelId/new' + | '/website/customize/mcp-servers' + | '/website/customize/skills' + | '/website/inbox/agents' | '/code/agents' | '/code/inbox' | '/website/$channelId' + | '/website/agents' + | '/website/customize' + | '/website/inbox' | '/code/agents/applications/approvals' | '/code/agents/scouts/findings' | '/code/agents/scouts/scratchpad' @@ -711,22 +1098,44 @@ export interface FileRouteTypes { | '/code/tasks/pending/$key' | '/website/$channelId/dashboards/$dashboardId' | '/website/$channelId/tasks/$taskId' + | '/website/agents/applications/approvals' + | '/website/agents/scouts/scratchpad' + | '/website/inbox/dismissed/$reportId' + | '/website/inbox/pulls/$reportId' + | '/website/inbox/reports/$reportId' + | '/website/inbox/runs/$reportId' | '/code/agents/applications' | '/code/agents/scouts' | '/code/inbox/dismissed' | '/code/inbox/pulls' | '/code/inbox/reports' | '/code/inbox/runs' + | '/website/agents/applications' + | '/website/agents/scouts' + | '/website/inbox/dismissed' + | '/website/inbox/pulls' + | '/website/inbox/reports' + | '/website/inbox/runs' | '/code/agents/applications/$idOrSlug/approvals' | '/code/agents/applications/$idOrSlug/chat' | '/code/agents/applications/$idOrSlug/configuration' | '/code/agents/applications/$idOrSlug/memory' | '/code/agents/applications/$idOrSlug/observability' | '/code/agents/applications/$idOrSlug/users' + | '/website/agents/applications/$idOrSlug/approvals' + | '/website/agents/applications/$idOrSlug/chat' + | '/website/agents/applications/$idOrSlug/configuration' + | '/website/agents/applications/$idOrSlug/memory' + | '/website/agents/applications/$idOrSlug/observability' + | '/website/agents/applications/$idOrSlug/users' | '/code/agents/applications/$idOrSlug' | '/code/agents/scouts/$skillName' + | '/website/agents/applications/$idOrSlug' + | '/website/agents/scouts/$skillName' | '/code/agents/applications/$idOrSlug/sessions/$sessionId' + | '/website/agents/applications/$idOrSlug/sessions/$sessionId' | '/code/agents/applications/$idOrSlug/sessions' + | '/website/agents/applications/$idOrSlug/sessions' id: | '__root__' | '/' @@ -740,11 +1149,12 @@ export interface FileRouteTypes { | '/code/inbox' | '/folders/$folderId' | '/settings/$category' + | '/website/agents' | '/website/command-center' + | '/website/customize' | '/website/home' - | '/website/mcp-servers' + | '/website/inbox' | '/website/new' - | '/website/skills' | '/code/' | '/settings/' | '/website/' @@ -762,9 +1172,21 @@ export interface FileRouteTypes { | '/website/$channelId/history' | '/website/$channelId/inbox' | '/website/$channelId/new' + | '/website/agents/applications' + | '/website/agents/scouts' + | '/website/customize/mcp-servers' + | '/website/customize/skills' + | '/website/inbox/agents' + | '/website/inbox/dismissed' + | '/website/inbox/pulls' + | '/website/inbox/reports' + | '/website/inbox/runs' | '/code/agents/' | '/code/inbox/' | '/website/$channelId/' + | '/website/agents/' + | '/website/customize/' + | '/website/inbox/' | '/code/agents/applications/$idOrSlug' | '/code/agents/applications/approvals' | '/code/agents/scouts/$skillName' @@ -777,22 +1199,46 @@ export interface FileRouteTypes { | '/code/tasks/pending/$key' | '/website/$channelId/dashboards/$dashboardId' | '/website/$channelId/tasks/$taskId' + | '/website/agents/applications/$idOrSlug' + | '/website/agents/applications/approvals' + | '/website/agents/scouts/$skillName' + | '/website/agents/scouts/scratchpad' + | '/website/inbox/dismissed/$reportId' + | '/website/inbox/pulls/$reportId' + | '/website/inbox/reports/$reportId' + | '/website/inbox/runs/$reportId' | '/code/agents/applications/' | '/code/agents/scouts/' | '/code/inbox/dismissed/' | '/code/inbox/pulls/' | '/code/inbox/reports/' | '/code/inbox/runs/' + | '/website/agents/applications/' + | '/website/agents/scouts/' + | '/website/inbox/dismissed/' + | '/website/inbox/pulls/' + | '/website/inbox/reports/' + | '/website/inbox/runs/' | '/code/agents/applications/$idOrSlug/approvals' | '/code/agents/applications/$idOrSlug/chat' | '/code/agents/applications/$idOrSlug/configuration' | '/code/agents/applications/$idOrSlug/memory' | '/code/agents/applications/$idOrSlug/observability' | '/code/agents/applications/$idOrSlug/users' + | '/website/agents/applications/$idOrSlug/approvals' + | '/website/agents/applications/$idOrSlug/chat' + | '/website/agents/applications/$idOrSlug/configuration' + | '/website/agents/applications/$idOrSlug/memory' + | '/website/agents/applications/$idOrSlug/observability' + | '/website/agents/applications/$idOrSlug/users' | '/code/agents/applications/$idOrSlug/' | '/code/agents/scouts/$skillName/' + | '/website/agents/applications/$idOrSlug/' + | '/website/agents/scouts/$skillName/' | '/code/agents/applications/$idOrSlug/sessions/$sessionId' + | '/website/agents/applications/$idOrSlug/sessions/$sessionId' | '/code/agents/applications/$idOrSlug/sessions/' + | '/website/agents/applications/$idOrSlug/sessions/' fileRoutesById: FileRoutesById } export interface RootRouteChildren { @@ -871,13 +1317,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeIndexRouteImport parentRoute: typeof rootRouteImport } - '/website/skills': { - id: '/website/skills' - path: '/skills' - fullPath: '/website/skills' - preLoaderRoute: typeof WebsiteSkillsRouteImport - parentRoute: typeof WebsiteRoute - } '/website/new': { id: '/website/new' path: '/new' @@ -885,11 +1324,11 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof WebsiteNewRouteImport parentRoute: typeof WebsiteRoute } - '/website/mcp-servers': { - id: '/website/mcp-servers' - path: '/mcp-servers' - fullPath: '/website/mcp-servers' - preLoaderRoute: typeof WebsiteMcpServersRouteImport + '/website/inbox': { + id: '/website/inbox' + path: '/inbox' + fullPath: '/website/inbox' + preLoaderRoute: typeof WebsiteInboxRouteImport parentRoute: typeof WebsiteRoute } '/website/home': { @@ -899,6 +1338,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof WebsiteHomeRouteImport parentRoute: typeof WebsiteRoute } + '/website/customize': { + id: '/website/customize' + path: '/customize' + fullPath: '/website/customize' + preLoaderRoute: typeof WebsiteCustomizeRouteImport + parentRoute: typeof WebsiteRoute + } '/website/command-center': { id: '/website/command-center' path: '/command-center' @@ -906,6 +1352,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof WebsiteCommandCenterRouteImport parentRoute: typeof WebsiteRoute } + '/website/agents': { + id: '/website/agents' + path: '/agents' + fullPath: '/website/agents' + preLoaderRoute: typeof WebsiteAgentsRouteImport + parentRoute: typeof WebsiteRoute + } '/settings/$category': { id: '/settings/$category' path: '/settings/$category' @@ -948,6 +1401,27 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsRouteImport parentRoute: typeof rootRouteImport } + '/website/inbox/': { + id: '/website/inbox/' + path: '/' + fullPath: '/website/inbox/' + preLoaderRoute: typeof WebsiteInboxIndexRouteImport + parentRoute: typeof WebsiteInboxRoute + } + '/website/customize/': { + id: '/website/customize/' + path: '/' + fullPath: '/website/customize/' + preLoaderRoute: typeof WebsiteCustomizeIndexRouteImport + parentRoute: typeof WebsiteCustomizeRoute + } + '/website/agents/': { + id: '/website/agents/' + path: '/' + fullPath: '/website/agents/' + preLoaderRoute: typeof WebsiteAgentsIndexRouteImport + parentRoute: typeof WebsiteAgentsRoute + } '/website/$channelId/': { id: '/website/$channelId/' path: '/$channelId' @@ -969,6 +1443,69 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsIndexRouteImport parentRoute: typeof CodeAgentsRoute } + '/website/inbox/runs': { + id: '/website/inbox/runs' + path: '/runs' + fullPath: '/website/inbox/runs' + preLoaderRoute: typeof WebsiteInboxRunsRouteImport + parentRoute: typeof WebsiteInboxRoute + } + '/website/inbox/reports': { + id: '/website/inbox/reports' + path: '/reports' + fullPath: '/website/inbox/reports' + preLoaderRoute: typeof WebsiteInboxReportsRouteImport + parentRoute: typeof WebsiteInboxRoute + } + '/website/inbox/pulls': { + id: '/website/inbox/pulls' + path: '/pulls' + fullPath: '/website/inbox/pulls' + preLoaderRoute: typeof WebsiteInboxPullsRouteImport + parentRoute: typeof WebsiteInboxRoute + } + '/website/inbox/dismissed': { + id: '/website/inbox/dismissed' + path: '/dismissed' + fullPath: '/website/inbox/dismissed' + preLoaderRoute: typeof WebsiteInboxDismissedRouteImport + parentRoute: typeof WebsiteInboxRoute + } + '/website/inbox/agents': { + id: '/website/inbox/agents' + path: '/agents' + fullPath: '/website/inbox/agents' + preLoaderRoute: typeof WebsiteInboxAgentsRouteImport + parentRoute: typeof WebsiteInboxRoute + } + '/website/customize/skills': { + id: '/website/customize/skills' + path: '/skills' + fullPath: '/website/customize/skills' + preLoaderRoute: typeof WebsiteCustomizeSkillsRouteImport + parentRoute: typeof WebsiteCustomizeRoute + } + '/website/customize/mcp-servers': { + id: '/website/customize/mcp-servers' + path: '/mcp-servers' + fullPath: '/website/customize/mcp-servers' + preLoaderRoute: typeof WebsiteCustomizeMcpServersRouteImport + parentRoute: typeof WebsiteCustomizeRoute + } + '/website/agents/scouts': { + id: '/website/agents/scouts' + path: '/scouts' + fullPath: '/website/agents/scouts' + preLoaderRoute: typeof WebsiteAgentsScoutsRouteImport + parentRoute: typeof WebsiteAgentsRoute + } + '/website/agents/applications': { + id: '/website/agents/applications' + path: '/applications' + fullPath: '/website/agents/applications' + preLoaderRoute: typeof WebsiteAgentsApplicationsRouteImport + parentRoute: typeof WebsiteAgentsRoute + } '/website/$channelId/new': { id: '/website/$channelId/new' path: '/$channelId/new' @@ -1067,6 +1604,48 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsApplicationsRouteImport parentRoute: typeof CodeAgentsRoute } + '/website/inbox/runs/': { + id: '/website/inbox/runs/' + path: '/' + fullPath: '/website/inbox/runs/' + preLoaderRoute: typeof WebsiteInboxRunsIndexRouteImport + parentRoute: typeof WebsiteInboxRunsRoute + } + '/website/inbox/reports/': { + id: '/website/inbox/reports/' + path: '/' + fullPath: '/website/inbox/reports/' + preLoaderRoute: typeof WebsiteInboxReportsIndexRouteImport + parentRoute: typeof WebsiteInboxReportsRoute + } + '/website/inbox/pulls/': { + id: '/website/inbox/pulls/' + path: '/' + fullPath: '/website/inbox/pulls/' + preLoaderRoute: typeof WebsiteInboxPullsIndexRouteImport + parentRoute: typeof WebsiteInboxPullsRoute + } + '/website/inbox/dismissed/': { + id: '/website/inbox/dismissed/' + path: '/' + fullPath: '/website/inbox/dismissed/' + preLoaderRoute: typeof WebsiteInboxDismissedIndexRouteImport + parentRoute: typeof WebsiteInboxDismissedRoute + } + '/website/agents/scouts/': { + id: '/website/agents/scouts/' + path: '/' + fullPath: '/website/agents/scouts/' + preLoaderRoute: typeof WebsiteAgentsScoutsIndexRouteImport + parentRoute: typeof WebsiteAgentsScoutsRoute + } + '/website/agents/applications/': { + id: '/website/agents/applications/' + path: '/' + fullPath: '/website/agents/applications/' + preLoaderRoute: typeof WebsiteAgentsApplicationsIndexRouteImport + parentRoute: typeof WebsiteAgentsApplicationsRoute + } '/code/inbox/runs/': { id: '/code/inbox/runs/' path: '/' @@ -1109,6 +1688,62 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsApplicationsIndexRouteImport parentRoute: typeof CodeAgentsApplicationsRoute } + '/website/inbox/runs/$reportId': { + id: '/website/inbox/runs/$reportId' + path: '/$reportId' + fullPath: '/website/inbox/runs/$reportId' + preLoaderRoute: typeof WebsiteInboxRunsReportIdRouteImport + parentRoute: typeof WebsiteInboxRunsRoute + } + '/website/inbox/reports/$reportId': { + id: '/website/inbox/reports/$reportId' + path: '/$reportId' + fullPath: '/website/inbox/reports/$reportId' + preLoaderRoute: typeof WebsiteInboxReportsReportIdRouteImport + parentRoute: typeof WebsiteInboxReportsRoute + } + '/website/inbox/pulls/$reportId': { + id: '/website/inbox/pulls/$reportId' + path: '/$reportId' + fullPath: '/website/inbox/pulls/$reportId' + preLoaderRoute: typeof WebsiteInboxPullsReportIdRouteImport + parentRoute: typeof WebsiteInboxPullsRoute + } + '/website/inbox/dismissed/$reportId': { + id: '/website/inbox/dismissed/$reportId' + path: '/$reportId' + fullPath: '/website/inbox/dismissed/$reportId' + preLoaderRoute: typeof WebsiteInboxDismissedReportIdRouteImport + parentRoute: typeof WebsiteInboxDismissedRoute + } + '/website/agents/scouts/scratchpad': { + id: '/website/agents/scouts/scratchpad' + path: '/scratchpad' + fullPath: '/website/agents/scouts/scratchpad' + preLoaderRoute: typeof WebsiteAgentsScoutsScratchpadRouteImport + parentRoute: typeof WebsiteAgentsScoutsRoute + } + '/website/agents/scouts/$skillName': { + id: '/website/agents/scouts/$skillName' + path: '/$skillName' + fullPath: '/website/agents/scouts/$skillName' + preLoaderRoute: typeof WebsiteAgentsScoutsSkillNameRouteImport + parentRoute: typeof WebsiteAgentsScoutsRoute + } + '/website/agents/applications/approvals': { + id: '/website/agents/applications/approvals' + path: '/approvals' + fullPath: '/website/agents/applications/approvals' + preLoaderRoute: typeof WebsiteAgentsApplicationsApprovalsRouteImport + parentRoute: typeof WebsiteAgentsApplicationsRoute + } + '/website/agents/applications/$idOrSlug': { + id: '/website/agents/applications/$idOrSlug' + path: '/$idOrSlug' + fullPath: '/website/agents/applications/$idOrSlug' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugRouteImport + parentRoute: typeof WebsiteAgentsApplicationsRoute + } '/website/$channelId/tasks/$taskId': { id: '/website/$channelId/tasks/$taskId' path: '/$channelId/tasks/$taskId' @@ -1193,6 +1828,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsApplicationsIdOrSlugRouteImport parentRoute: typeof CodeAgentsApplicationsRoute } + '/website/agents/scouts/$skillName/': { + id: '/website/agents/scouts/$skillName/' + path: '/' + fullPath: '/website/agents/scouts/$skillName/' + preLoaderRoute: typeof WebsiteAgentsScoutsSkillNameIndexRouteImport + parentRoute: typeof WebsiteAgentsScoutsSkillNameRoute + } + '/website/agents/applications/$idOrSlug/': { + id: '/website/agents/applications/$idOrSlug/' + path: '/' + fullPath: '/website/agents/applications/$idOrSlug/' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugIndexRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } '/code/agents/scouts/$skillName/': { id: '/code/agents/scouts/$skillName/' path: '/' @@ -1207,6 +1856,48 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsApplicationsIdOrSlugIndexRouteImport parentRoute: typeof CodeAgentsApplicationsIdOrSlugRoute } + '/website/agents/applications/$idOrSlug/users': { + id: '/website/agents/applications/$idOrSlug/users' + path: '/users' + fullPath: '/website/agents/applications/$idOrSlug/users' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugUsersRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } + '/website/agents/applications/$idOrSlug/observability': { + id: '/website/agents/applications/$idOrSlug/observability' + path: '/observability' + fullPath: '/website/agents/applications/$idOrSlug/observability' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugObservabilityRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } + '/website/agents/applications/$idOrSlug/memory': { + id: '/website/agents/applications/$idOrSlug/memory' + path: '/memory' + fullPath: '/website/agents/applications/$idOrSlug/memory' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugMemoryRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } + '/website/agents/applications/$idOrSlug/configuration': { + id: '/website/agents/applications/$idOrSlug/configuration' + path: '/configuration' + fullPath: '/website/agents/applications/$idOrSlug/configuration' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugConfigurationRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } + '/website/agents/applications/$idOrSlug/chat': { + id: '/website/agents/applications/$idOrSlug/chat' + path: '/chat' + fullPath: '/website/agents/applications/$idOrSlug/chat' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugChatRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } + '/website/agents/applications/$idOrSlug/approvals': { + id: '/website/agents/applications/$idOrSlug/approvals' + path: '/approvals' + fullPath: '/website/agents/applications/$idOrSlug/approvals' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugApprovalsRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } '/code/agents/applications/$idOrSlug/users': { id: '/code/agents/applications/$idOrSlug/users' path: '/users' @@ -1249,6 +1940,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsApplicationsIdOrSlugApprovalsRouteImport parentRoute: typeof CodeAgentsApplicationsIdOrSlugRoute } + '/website/agents/applications/$idOrSlug/sessions/': { + id: '/website/agents/applications/$idOrSlug/sessions/' + path: '/sessions' + fullPath: '/website/agents/applications/$idOrSlug/sessions/' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugSessionsIndexRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } '/code/agents/applications/$idOrSlug/sessions/': { id: '/code/agents/applications/$idOrSlug/sessions/' path: '/sessions' @@ -1256,6 +1954,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof CodeAgentsApplicationsIdOrSlugSessionsIndexRouteImport parentRoute: typeof CodeAgentsApplicationsIdOrSlugRoute } + '/website/agents/applications/$idOrSlug/sessions/$sessionId': { + id: '/website/agents/applications/$idOrSlug/sessions/$sessionId' + path: '/sessions/$sessionId' + fullPath: '/website/agents/applications/$idOrSlug/sessions/$sessionId' + preLoaderRoute: typeof WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRouteImport + parentRoute: typeof WebsiteAgentsApplicationsIdOrSlugRoute + } '/code/agents/applications/$idOrSlug/sessions/$sessionId': { id: '/code/agents/applications/$idOrSlug/sessions/$sessionId' path: '/sessions/$sessionId' @@ -1266,12 +1971,210 @@ declare module '@tanstack/react-router' { } } +interface WebsiteAgentsApplicationsIdOrSlugRouteChildren { + WebsiteAgentsApplicationsIdOrSlugApprovalsRoute: typeof WebsiteAgentsApplicationsIdOrSlugApprovalsRoute + WebsiteAgentsApplicationsIdOrSlugChatRoute: typeof WebsiteAgentsApplicationsIdOrSlugChatRoute + WebsiteAgentsApplicationsIdOrSlugConfigurationRoute: typeof WebsiteAgentsApplicationsIdOrSlugConfigurationRoute + WebsiteAgentsApplicationsIdOrSlugMemoryRoute: typeof WebsiteAgentsApplicationsIdOrSlugMemoryRoute + WebsiteAgentsApplicationsIdOrSlugObservabilityRoute: typeof WebsiteAgentsApplicationsIdOrSlugObservabilityRoute + WebsiteAgentsApplicationsIdOrSlugUsersRoute: typeof WebsiteAgentsApplicationsIdOrSlugUsersRoute + WebsiteAgentsApplicationsIdOrSlugIndexRoute: typeof WebsiteAgentsApplicationsIdOrSlugIndexRoute + WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute: typeof WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute + WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute: typeof WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute +} + +const WebsiteAgentsApplicationsIdOrSlugRouteChildren: WebsiteAgentsApplicationsIdOrSlugRouteChildren = + { + WebsiteAgentsApplicationsIdOrSlugApprovalsRoute: + WebsiteAgentsApplicationsIdOrSlugApprovalsRoute, + WebsiteAgentsApplicationsIdOrSlugChatRoute: + WebsiteAgentsApplicationsIdOrSlugChatRoute, + WebsiteAgentsApplicationsIdOrSlugConfigurationRoute: + WebsiteAgentsApplicationsIdOrSlugConfigurationRoute, + WebsiteAgentsApplicationsIdOrSlugMemoryRoute: + WebsiteAgentsApplicationsIdOrSlugMemoryRoute, + WebsiteAgentsApplicationsIdOrSlugObservabilityRoute: + WebsiteAgentsApplicationsIdOrSlugObservabilityRoute, + WebsiteAgentsApplicationsIdOrSlugUsersRoute: + WebsiteAgentsApplicationsIdOrSlugUsersRoute, + WebsiteAgentsApplicationsIdOrSlugIndexRoute: + WebsiteAgentsApplicationsIdOrSlugIndexRoute, + WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute: + WebsiteAgentsApplicationsIdOrSlugSessionsSessionIdRoute, + WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute: + WebsiteAgentsApplicationsIdOrSlugSessionsIndexRoute, + } + +const WebsiteAgentsApplicationsIdOrSlugRouteWithChildren = + WebsiteAgentsApplicationsIdOrSlugRoute._addFileChildren( + WebsiteAgentsApplicationsIdOrSlugRouteChildren, + ) + +interface WebsiteAgentsApplicationsRouteChildren { + WebsiteAgentsApplicationsIdOrSlugRoute: typeof WebsiteAgentsApplicationsIdOrSlugRouteWithChildren + WebsiteAgentsApplicationsApprovalsRoute: typeof WebsiteAgentsApplicationsApprovalsRoute + WebsiteAgentsApplicationsIndexRoute: typeof WebsiteAgentsApplicationsIndexRoute +} + +const WebsiteAgentsApplicationsRouteChildren: WebsiteAgentsApplicationsRouteChildren = + { + WebsiteAgentsApplicationsIdOrSlugRoute: + WebsiteAgentsApplicationsIdOrSlugRouteWithChildren, + WebsiteAgentsApplicationsApprovalsRoute: + WebsiteAgentsApplicationsApprovalsRoute, + WebsiteAgentsApplicationsIndexRoute: WebsiteAgentsApplicationsIndexRoute, + } + +const WebsiteAgentsApplicationsRouteWithChildren = + WebsiteAgentsApplicationsRoute._addFileChildren( + WebsiteAgentsApplicationsRouteChildren, + ) + +interface WebsiteAgentsScoutsSkillNameRouteChildren { + WebsiteAgentsScoutsSkillNameIndexRoute: typeof WebsiteAgentsScoutsSkillNameIndexRoute +} + +const WebsiteAgentsScoutsSkillNameRouteChildren: WebsiteAgentsScoutsSkillNameRouteChildren = + { + WebsiteAgentsScoutsSkillNameIndexRoute: + WebsiteAgentsScoutsSkillNameIndexRoute, + } + +const WebsiteAgentsScoutsSkillNameRouteWithChildren = + WebsiteAgentsScoutsSkillNameRoute._addFileChildren( + WebsiteAgentsScoutsSkillNameRouteChildren, + ) + +interface WebsiteAgentsScoutsRouteChildren { + WebsiteAgentsScoutsSkillNameRoute: typeof WebsiteAgentsScoutsSkillNameRouteWithChildren + WebsiteAgentsScoutsScratchpadRoute: typeof WebsiteAgentsScoutsScratchpadRoute + WebsiteAgentsScoutsIndexRoute: typeof WebsiteAgentsScoutsIndexRoute +} + +const WebsiteAgentsScoutsRouteChildren: WebsiteAgentsScoutsRouteChildren = { + WebsiteAgentsScoutsSkillNameRoute: + WebsiteAgentsScoutsSkillNameRouteWithChildren, + WebsiteAgentsScoutsScratchpadRoute: WebsiteAgentsScoutsScratchpadRoute, + WebsiteAgentsScoutsIndexRoute: WebsiteAgentsScoutsIndexRoute, +} + +const WebsiteAgentsScoutsRouteWithChildren = + WebsiteAgentsScoutsRoute._addFileChildren(WebsiteAgentsScoutsRouteChildren) + +interface WebsiteAgentsRouteChildren { + WebsiteAgentsApplicationsRoute: typeof WebsiteAgentsApplicationsRouteWithChildren + WebsiteAgentsScoutsRoute: typeof WebsiteAgentsScoutsRouteWithChildren + WebsiteAgentsIndexRoute: typeof WebsiteAgentsIndexRoute +} + +const WebsiteAgentsRouteChildren: WebsiteAgentsRouteChildren = { + WebsiteAgentsApplicationsRoute: WebsiteAgentsApplicationsRouteWithChildren, + WebsiteAgentsScoutsRoute: WebsiteAgentsScoutsRouteWithChildren, + WebsiteAgentsIndexRoute: WebsiteAgentsIndexRoute, +} + +const WebsiteAgentsRouteWithChildren = WebsiteAgentsRoute._addFileChildren( + WebsiteAgentsRouteChildren, +) + +interface WebsiteCustomizeRouteChildren { + WebsiteCustomizeMcpServersRoute: typeof WebsiteCustomizeMcpServersRoute + WebsiteCustomizeSkillsRoute: typeof WebsiteCustomizeSkillsRoute + WebsiteCustomizeIndexRoute: typeof WebsiteCustomizeIndexRoute +} + +const WebsiteCustomizeRouteChildren: WebsiteCustomizeRouteChildren = { + WebsiteCustomizeMcpServersRoute: WebsiteCustomizeMcpServersRoute, + WebsiteCustomizeSkillsRoute: WebsiteCustomizeSkillsRoute, + WebsiteCustomizeIndexRoute: WebsiteCustomizeIndexRoute, +} + +const WebsiteCustomizeRouteWithChildren = + WebsiteCustomizeRoute._addFileChildren(WebsiteCustomizeRouteChildren) + +interface WebsiteInboxDismissedRouteChildren { + WebsiteInboxDismissedReportIdRoute: typeof WebsiteInboxDismissedReportIdRoute + WebsiteInboxDismissedIndexRoute: typeof WebsiteInboxDismissedIndexRoute +} + +const WebsiteInboxDismissedRouteChildren: WebsiteInboxDismissedRouteChildren = { + WebsiteInboxDismissedReportIdRoute: WebsiteInboxDismissedReportIdRoute, + WebsiteInboxDismissedIndexRoute: WebsiteInboxDismissedIndexRoute, +} + +const WebsiteInboxDismissedRouteWithChildren = + WebsiteInboxDismissedRoute._addFileChildren( + WebsiteInboxDismissedRouteChildren, + ) + +interface WebsiteInboxPullsRouteChildren { + WebsiteInboxPullsReportIdRoute: typeof WebsiteInboxPullsReportIdRoute + WebsiteInboxPullsIndexRoute: typeof WebsiteInboxPullsIndexRoute +} + +const WebsiteInboxPullsRouteChildren: WebsiteInboxPullsRouteChildren = { + WebsiteInboxPullsReportIdRoute: WebsiteInboxPullsReportIdRoute, + WebsiteInboxPullsIndexRoute: WebsiteInboxPullsIndexRoute, +} + +const WebsiteInboxPullsRouteWithChildren = + WebsiteInboxPullsRoute._addFileChildren(WebsiteInboxPullsRouteChildren) + +interface WebsiteInboxReportsRouteChildren { + WebsiteInboxReportsReportIdRoute: typeof WebsiteInboxReportsReportIdRoute + WebsiteInboxReportsIndexRoute: typeof WebsiteInboxReportsIndexRoute +} + +const WebsiteInboxReportsRouteChildren: WebsiteInboxReportsRouteChildren = { + WebsiteInboxReportsReportIdRoute: WebsiteInboxReportsReportIdRoute, + WebsiteInboxReportsIndexRoute: WebsiteInboxReportsIndexRoute, +} + +const WebsiteInboxReportsRouteWithChildren = + WebsiteInboxReportsRoute._addFileChildren(WebsiteInboxReportsRouteChildren) + +interface WebsiteInboxRunsRouteChildren { + WebsiteInboxRunsReportIdRoute: typeof WebsiteInboxRunsReportIdRoute + WebsiteInboxRunsIndexRoute: typeof WebsiteInboxRunsIndexRoute +} + +const WebsiteInboxRunsRouteChildren: WebsiteInboxRunsRouteChildren = { + WebsiteInboxRunsReportIdRoute: WebsiteInboxRunsReportIdRoute, + WebsiteInboxRunsIndexRoute: WebsiteInboxRunsIndexRoute, +} + +const WebsiteInboxRunsRouteWithChildren = + WebsiteInboxRunsRoute._addFileChildren(WebsiteInboxRunsRouteChildren) + +interface WebsiteInboxRouteChildren { + WebsiteInboxAgentsRoute: typeof WebsiteInboxAgentsRoute + WebsiteInboxDismissedRoute: typeof WebsiteInboxDismissedRouteWithChildren + WebsiteInboxPullsRoute: typeof WebsiteInboxPullsRouteWithChildren + WebsiteInboxReportsRoute: typeof WebsiteInboxReportsRouteWithChildren + WebsiteInboxRunsRoute: typeof WebsiteInboxRunsRouteWithChildren + WebsiteInboxIndexRoute: typeof WebsiteInboxIndexRoute +} + +const WebsiteInboxRouteChildren: WebsiteInboxRouteChildren = { + WebsiteInboxAgentsRoute: WebsiteInboxAgentsRoute, + WebsiteInboxDismissedRoute: WebsiteInboxDismissedRouteWithChildren, + WebsiteInboxPullsRoute: WebsiteInboxPullsRouteWithChildren, + WebsiteInboxReportsRoute: WebsiteInboxReportsRouteWithChildren, + WebsiteInboxRunsRoute: WebsiteInboxRunsRouteWithChildren, + WebsiteInboxIndexRoute: WebsiteInboxIndexRoute, +} + +const WebsiteInboxRouteWithChildren = WebsiteInboxRoute._addFileChildren( + WebsiteInboxRouteChildren, +) + interface WebsiteRouteChildren { + WebsiteAgentsRoute: typeof WebsiteAgentsRouteWithChildren WebsiteCommandCenterRoute: typeof WebsiteCommandCenterRoute + WebsiteCustomizeRoute: typeof WebsiteCustomizeRouteWithChildren WebsiteHomeRoute: typeof WebsiteHomeRoute - WebsiteMcpServersRoute: typeof WebsiteMcpServersRoute + WebsiteInboxRoute: typeof WebsiteInboxRouteWithChildren WebsiteNewRoute: typeof WebsiteNewRoute - WebsiteSkillsRoute: typeof WebsiteSkillsRoute WebsiteIndexRoute: typeof WebsiteIndexRoute WebsiteChannelIdArtifactsRoute: typeof WebsiteChannelIdArtifactsRoute WebsiteChannelIdCanvasesRoute: typeof WebsiteChannelIdCanvasesRoute @@ -1285,11 +2188,12 @@ interface WebsiteRouteChildren { } const WebsiteRouteChildren: WebsiteRouteChildren = { + WebsiteAgentsRoute: WebsiteAgentsRouteWithChildren, WebsiteCommandCenterRoute: WebsiteCommandCenterRoute, + WebsiteCustomizeRoute: WebsiteCustomizeRouteWithChildren, WebsiteHomeRoute: WebsiteHomeRoute, - WebsiteMcpServersRoute: WebsiteMcpServersRoute, + WebsiteInboxRoute: WebsiteInboxRouteWithChildren, WebsiteNewRoute: WebsiteNewRoute, - WebsiteSkillsRoute: WebsiteSkillsRoute, WebsiteIndexRoute: WebsiteIndexRoute, WebsiteChannelIdArtifactsRoute: WebsiteChannelIdArtifactsRoute, WebsiteChannelIdCanvasesRoute: WebsiteChannelIdCanvasesRoute, diff --git a/packages/ui/src/router/routes/website/agents.tsx b/packages/ui/src/router/routes/website/agents.tsx new file mode 100644 index 0000000000..2b18961495 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents.tsx @@ -0,0 +1,14 @@ +import { AgentBuilderDockLayout } from "@posthog/ui/features/agent-applications/agent-builder/AgentBuilderDockLayout"; +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents")({ + component: AgentsLayout, +}); + +function AgentsLayout() { + return ( + + + + ); +} diff --git a/packages/ui/src/router/routes/website/agents/applications.tsx b/packages/ui/src/router/routes/website/agents/applications.tsx new file mode 100644 index 0000000000..04f4c14509 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications.tsx @@ -0,0 +1,27 @@ +import { AGENT_PLATFORM_FLAG } from "@posthog/ui/features/agent-applications/featureFlag"; +import { useFeatureFlag } from "@posthog/ui/features/feature-flags/useFeatureFlag"; +import { Flex, Text } from "@radix-ui/themes"; +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/applications")({ + component: ApplicationsGate, +}); + +/** + * Gates the entire Applications surface (list + per-agent detail) behind the + * `agent-platform` flag. When disabled the tab is also hidden from the agents + * chrome; direct navigation here lands on this placeholder. + */ +function ApplicationsGate() { + const enabled = useFeatureFlag(AGENT_PLATFORM_FLAG); + if (!enabled) { + return ( + + + Agent applications aren't available yet. + + + ); + } + return ; +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug.tsx new file mode 100644 index 0000000000..da2449e327 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/applications/$idOrSlug")({ + component: Outlet, +}); diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/approvals.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/approvals.tsx new file mode 100644 index 0000000000..3ce4c43889 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/approvals.tsx @@ -0,0 +1,36 @@ +import { + AgentApprovalsPane, + type ApprovalFilter, +} from "@posthog/ui/features/agent-applications/components/AgentApprovalsPane"; +import { createFileRoute } from "@tanstack/react-router"; +import { useState } from "react"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/approvals", +)({ + validateSearch: (search: Record): { request?: string } => ({ + request: typeof search.request === "string" ? search.request : undefined, + }), + component: AgentApprovalsRoute, +}); + +function AgentApprovalsRoute() { + const { idOrSlug } = Route.useParams(); + const { request } = Route.useSearch(); + const navigate = Route.useNavigate(); + const [filter, setFilter] = useState("queued"); + + return ( + + navigate({ + search: (prev) => ({ ...prev, request: id ?? undefined }), + }) + } + filter={filter} + onFilterChange={setFilter} + /> + ); +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/chat.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/chat.tsx new file mode 100644 index 0000000000..ef5c7aeb80 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/chat.tsx @@ -0,0 +1,32 @@ +import { AgentChatPane } from "@posthog/ui/features/agent-applications/components/AgentChatPane"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/chat", +)({ + // `revision` routes this chat to a non-live revision (the pane mints a + // short-lived ingress JWT scoped to that revision; side effects still run + // for real, only the revision serving the request changes). `session` + // re-attaches a specific session on mount — set by rail clicks that cross + // revisions so the new mount resumes the right conversation instead of + // starting empty. + validateSearch: ( + search: Record, + ): { revision?: string; session?: string } => ({ + revision: typeof search.revision === "string" ? search.revision : undefined, + session: typeof search.session === "string" ? search.session : undefined, + }), + component: AgentChatRoute, +}); + +function AgentChatRoute() { + const { idOrSlug } = Route.useParams(); + const { revision, session } = Route.useSearch(); + return ( + + ); +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/configuration.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/configuration.tsx new file mode 100644 index 0000000000..bbfb028af0 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/configuration.tsx @@ -0,0 +1,40 @@ +import { AgentConfigurationPane } from "@posthog/ui/features/agent-applications/components/AgentConfigurationPane"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/configuration", +)({ + validateSearch: ( + search: Record, + ): { node?: string; revision?: string } => ({ + node: typeof search.node === "string" ? search.node : undefined, + revision: typeof search.revision === "string" ? search.revision : undefined, + }), + component: AgentConfigurationRoute, +}); + +function AgentConfigurationRoute() { + const { idOrSlug } = Route.useParams(); + const { node, revision } = Route.useSearch(); + const navigate = Route.useNavigate(); + + return ( + + navigate({ search: (prev) => ({ ...prev, node: next }) }) + } + selectedRevisionId={revision ?? null} + onSelectRevision={(revisionId) => + navigate({ search: (prev) => ({ ...prev, revision: revisionId }) }) + } + onOpenSession={(sessionId) => + navigate({ + to: "/website/agents/applications/$idOrSlug/sessions/$sessionId", + params: { idOrSlug, sessionId }, + }) + } + /> + ); +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/index.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/index.tsx new file mode 100644 index 0000000000..2abb7e54cc --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/index.tsx @@ -0,0 +1,13 @@ +import { AgentApplicationDetailView } from "@posthog/ui/features/agent-applications/components/AgentApplicationDetailView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/applications/$idOrSlug/")( + { + component: AgentApplicationDetailRoute, + }, +); + +function AgentApplicationDetailRoute() { + const { idOrSlug } = Route.useParams(); + return ; +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/memory.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/memory.tsx new file mode 100644 index 0000000000..eca4482be2 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/memory.tsx @@ -0,0 +1,13 @@ +import { AgentMemoryPane } from "@posthog/ui/features/agent-applications/components/AgentMemoryPane"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/memory", +)({ + component: AgentMemoryRoute, +}); + +function AgentMemoryRoute() { + const { idOrSlug } = Route.useParams(); + return ; +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/observability.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/observability.tsx new file mode 100644 index 0000000000..131c4a5309 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/observability.tsx @@ -0,0 +1,13 @@ +import { AgentObservabilityPane } from "@posthog/ui/features/agent-applications/components/AgentObservabilityPane"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/observability", +)({ + component: AgentObservabilityRoute, +}); + +function AgentObservabilityRoute() { + const { idOrSlug } = Route.useParams(); + return ; +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/sessions.$sessionId.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/sessions.$sessionId.tsx new file mode 100644 index 0000000000..bbc1128713 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/sessions.$sessionId.tsx @@ -0,0 +1,15 @@ +import { AgentSessionTranscriptView } from "@posthog/ui/features/agent-applications/components/AgentSessionTranscriptView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/sessions/$sessionId", +)({ + component: AgentSessionRoute, +}); + +function AgentSessionRoute() { + const { idOrSlug, sessionId } = Route.useParams(); + return ( + + ); +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/sessions.index.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/sessions.index.tsx new file mode 100644 index 0000000000..c37a22d8bc --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/sessions.index.tsx @@ -0,0 +1,13 @@ +import { AgentSessionsPane } from "@posthog/ui/features/agent-applications/components/AgentSessionsPane"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/sessions/", +)({ + component: AgentSessionsRoute, +}); + +function AgentSessionsRoute() { + const { idOrSlug } = Route.useParams(); + return ; +} diff --git a/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/users.tsx b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/users.tsx new file mode 100644 index 0000000000..d8b5a0b381 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/$idOrSlug/users.tsx @@ -0,0 +1,13 @@ +import { AgentUsersPane } from "@posthog/ui/features/agent-applications/components/AgentUsersPane"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute( + "/website/agents/applications/$idOrSlug/users", +)({ + component: AgentUsersRoute, +}); + +function AgentUsersRoute() { + const { idOrSlug } = Route.useParams(); + return ; +} diff --git a/packages/ui/src/router/routes/website/agents/applications/approvals.tsx b/packages/ui/src/router/routes/website/agents/applications/approvals.tsx new file mode 100644 index 0000000000..3592f0ddae --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/approvals.tsx @@ -0,0 +1,30 @@ +import { AgentFleetApprovalsPane } from "@posthog/ui/features/agent-applications/components/AgentFleetApprovalsPane"; +import type { ApprovalFilter } from "@posthog/ui/features/agent-applications/components/agentApprovalsFilters"; +import { createFileRoute } from "@tanstack/react-router"; +import { useState } from "react"; + +export const Route = createFileRoute("/website/agents/applications/approvals")({ + validateSearch: (search: Record): { request?: string } => ({ + request: typeof search.request === "string" ? search.request : undefined, + }), + component: AgentFleetApprovalsRoute, +}); + +function AgentFleetApprovalsRoute() { + const { request } = Route.useSearch(); + const navigate = Route.useNavigate(); + const [filter, setFilter] = useState("queued"); + + return ( + + navigate({ + search: (prev) => ({ ...prev, request: id ?? undefined }), + }) + } + filter={filter} + onFilterChange={setFilter} + /> + ); +} diff --git a/packages/ui/src/router/routes/website/agents/applications/index.tsx b/packages/ui/src/router/routes/website/agents/applications/index.tsx new file mode 100644 index 0000000000..188eefc04e --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/applications/index.tsx @@ -0,0 +1,6 @@ +import { AgentApplicationsListView } from "@posthog/ui/features/agent-applications/components/AgentApplicationsListView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/applications/")({ + component: AgentApplicationsListView, +}); diff --git a/packages/ui/src/router/routes/website/agents/index.tsx b/packages/ui/src/router/routes/website/agents/index.tsx new file mode 100644 index 0000000000..24699568bc --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/index.tsx @@ -0,0 +1,7 @@ +import { createFileRoute, redirect } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/")({ + beforeLoad: () => { + throw redirect({ to: "/website/agents/scouts" }); + }, +}); diff --git a/packages/ui/src/router/routes/website/agents/scouts.$skillName.index.tsx b/packages/ui/src/router/routes/website/agents/scouts.$skillName.index.tsx new file mode 100644 index 0000000000..129e60e1f3 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/scouts.$skillName.index.tsx @@ -0,0 +1,15 @@ +import { ScoutDetailView } from "@posthog/ui/features/scouts/components/ScoutDetailView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/scouts/$skillName/")({ + validateSearch: (search: Record): { finding?: string } => ({ + finding: typeof search.finding === "string" ? search.finding : undefined, + }), + component: ScoutDetailRoute, +}); + +function ScoutDetailRoute() { + const { skillName } = Route.useParams(); + const { finding } = Route.useSearch(); + return ; +} diff --git a/packages/ui/src/router/routes/website/agents/scouts.$skillName.tsx b/packages/ui/src/router/routes/website/agents/scouts.$skillName.tsx new file mode 100644 index 0000000000..88be29a355 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/scouts.$skillName.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/scouts/$skillName")({ + component: Outlet, +}); diff --git a/packages/ui/src/router/routes/website/agents/scouts.index.tsx b/packages/ui/src/router/routes/website/agents/scouts.index.tsx new file mode 100644 index 0000000000..9e2800dcb1 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/scouts.index.tsx @@ -0,0 +1,6 @@ +import { AgentsView } from "@posthog/ui/features/agents/components/AgentsView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/scouts/")({ + component: AgentsView, +}); diff --git a/packages/ui/src/router/routes/website/agents/scouts.scratchpad.tsx b/packages/ui/src/router/routes/website/agents/scouts.scratchpad.tsx new file mode 100644 index 0000000000..ab9f5b502f --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/scouts.scratchpad.tsx @@ -0,0 +1,6 @@ +import { ScratchpadView } from "@posthog/ui/features/scouts/components/ScratchpadView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/scouts/scratchpad")({ + component: ScratchpadView, +}); diff --git a/packages/ui/src/router/routes/website/agents/scouts.tsx b/packages/ui/src/router/routes/website/agents/scouts.tsx new file mode 100644 index 0000000000..d65924e6d6 --- /dev/null +++ b/packages/ui/src/router/routes/website/agents/scouts.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/agents/scouts")({ + component: Outlet, +}); diff --git a/packages/ui/src/router/routes/website/customize.tsx b/packages/ui/src/router/routes/website/customize.tsx new file mode 100644 index 0000000000..2753363cc3 --- /dev/null +++ b/packages/ui/src/router/routes/website/customize.tsx @@ -0,0 +1,6 @@ +import { CustomizeLayout } from "@posthog/ui/features/canvas/components/CustomizeLayout"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/customize")({ + component: CustomizeLayout, +}); diff --git a/packages/ui/src/router/routes/website/customize/index.tsx b/packages/ui/src/router/routes/website/customize/index.tsx new file mode 100644 index 0000000000..3d73e16cf8 --- /dev/null +++ b/packages/ui/src/router/routes/website/customize/index.tsx @@ -0,0 +1,9 @@ +import { createFileRoute, Navigate } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/customize/")({ + component: CustomizeIndexRedirect, +}); + +function CustomizeIndexRedirect() { + return ; +} diff --git a/packages/ui/src/router/routes/website/customize/mcp-servers.tsx b/packages/ui/src/router/routes/website/customize/mcp-servers.tsx new file mode 100644 index 0000000000..959da03c28 --- /dev/null +++ b/packages/ui/src/router/routes/website/customize/mcp-servers.tsx @@ -0,0 +1,6 @@ +import { McpServersView } from "@posthog/ui/features/mcp-servers/components/McpServersView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/customize/mcp-servers")({ + component: McpServersView, +}); diff --git a/packages/ui/src/router/routes/website/customize/skills.tsx b/packages/ui/src/router/routes/website/customize/skills.tsx new file mode 100644 index 0000000000..65537d71bd --- /dev/null +++ b/packages/ui/src/router/routes/website/customize/skills.tsx @@ -0,0 +1,6 @@ +import { SkillsView } from "@posthog/ui/features/skills/SkillsView"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/customize/skills")({ + component: SkillsView, +}); diff --git a/packages/ui/src/router/routes/website/inbox.tsx b/packages/ui/src/router/routes/website/inbox.tsx new file mode 100644 index 0000000000..1588b7eea5 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox.tsx @@ -0,0 +1,9 @@ +import { InboxView } from "@posthog/ui/features/inbox/components/InboxView"; +import { createFileRoute } from "@tanstack/react-router"; + +// Channels-space mirror of /code/inbox. Renders the same shared InboxView; the +// view's internal navigation is space-aware, so staying under /website keeps the +// channels chrome instead of bouncing to the Code view. +export const Route = createFileRoute("/website/inbox")({ + component: InboxView, +}); diff --git a/packages/ui/src/router/routes/website/inbox/agents.tsx b/packages/ui/src/router/routes/website/inbox/agents.tsx new file mode 100644 index 0000000000..b017d47a9a --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/agents.tsx @@ -0,0 +1,9 @@ +import { createFileRoute, Navigate } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/agents")({ + component: InboxAgentsRedirect, +}); + +function InboxAgentsRedirect() { + return ; +} diff --git a/packages/ui/src/router/routes/website/inbox/dismissed.$reportId.tsx b/packages/ui/src/router/routes/website/inbox/dismissed.$reportId.tsx new file mode 100644 index 0000000000..a2e8ca91c0 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/dismissed.$reportId.tsx @@ -0,0 +1,19 @@ +import type { SignalReport } from "@posthog/shared/types"; +import { DismissedReportDetail } from "@posthog/ui/features/inbox/components/DismissedReportDetail"; +import { getCachedInboxReportDetail } from "@posthog/ui/features/inbox/inboxQueries"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/dismissed/$reportId")({ + component: DismissedReportDetailRoute, + pendingComponent: () => null, + loader: ({ params }): SignalReport | null => + getCachedInboxReportDetail(params.reportId) ?? null, +}); + +function DismissedReportDetailRoute() { + const { reportId } = Route.useParams(); + const cachedReport = Route.useLoaderData(); + return ( + + ); +} diff --git a/packages/ui/src/router/routes/website/inbox/dismissed.index.tsx b/packages/ui/src/router/routes/website/inbox/dismissed.index.tsx new file mode 100644 index 0000000000..c05916ed0a --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/dismissed.index.tsx @@ -0,0 +1,6 @@ +import { DismissedTab } from "@posthog/ui/features/inbox/components/DismissedTab"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/dismissed/")({ + component: DismissedTab, +}); diff --git a/packages/ui/src/router/routes/website/inbox/dismissed.tsx b/packages/ui/src/router/routes/website/inbox/dismissed.tsx new file mode 100644 index 0000000000..e2229fad18 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/dismissed.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/dismissed")({ + component: Outlet, +}); diff --git a/packages/ui/src/router/routes/website/inbox/index.tsx b/packages/ui/src/router/routes/website/inbox/index.tsx new file mode 100644 index 0000000000..3dd9da486b --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/index.tsx @@ -0,0 +1,9 @@ +import { createFileRoute, Navigate } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/")({ + component: InboxIndexRedirect, +}); + +function InboxIndexRedirect() { + return ; +} diff --git a/packages/ui/src/router/routes/website/inbox/pulls.$reportId.tsx b/packages/ui/src/router/routes/website/inbox/pulls.$reportId.tsx new file mode 100644 index 0000000000..7ea6a01021 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/pulls.$reportId.tsx @@ -0,0 +1,17 @@ +import type { SignalReport } from "@posthog/shared/types"; +import { PullRequestDetail } from "@posthog/ui/features/inbox/components/PullRequestDetail"; +import { getCachedInboxReportDetail } from "@posthog/ui/features/inbox/inboxQueries"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/pulls/$reportId")({ + component: PullRequestDetailRoute, + pendingComponent: () => null, + loader: ({ params }): SignalReport | null => + getCachedInboxReportDetail(params.reportId) ?? null, +}); + +function PullRequestDetailRoute() { + const { reportId } = Route.useParams(); + const cachedReport = Route.useLoaderData(); + return ; +} diff --git a/packages/ui/src/router/routes/website/inbox/pulls.index.tsx b/packages/ui/src/router/routes/website/inbox/pulls.index.tsx new file mode 100644 index 0000000000..09b69f72f3 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/pulls.index.tsx @@ -0,0 +1,6 @@ +import { PullRequestsTab } from "@posthog/ui/features/inbox/components/PullRequestsTab"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/pulls/")({ + component: PullRequestsTab, +}); diff --git a/packages/ui/src/router/routes/website/inbox/pulls.tsx b/packages/ui/src/router/routes/website/inbox/pulls.tsx new file mode 100644 index 0000000000..379dd72681 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/pulls.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/pulls")({ + component: Outlet, +}); diff --git a/packages/ui/src/router/routes/website/inbox/reports.$reportId.tsx b/packages/ui/src/router/routes/website/inbox/reports.$reportId.tsx new file mode 100644 index 0000000000..846c5c2599 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/reports.$reportId.tsx @@ -0,0 +1,17 @@ +import type { SignalReport } from "@posthog/shared/types"; +import { ReportDetail } from "@posthog/ui/features/inbox/components/ReportDetail"; +import { getCachedInboxReportDetail } from "@posthog/ui/features/inbox/inboxQueries"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/reports/$reportId")({ + component: ReportDetailRoute, + pendingComponent: () => null, + loader: ({ params }): SignalReport | null => + getCachedInboxReportDetail(params.reportId) ?? null, +}); + +function ReportDetailRoute() { + const { reportId } = Route.useParams(); + const cachedReport = Route.useLoaderData(); + return ; +} diff --git a/packages/ui/src/router/routes/website/inbox/reports.index.tsx b/packages/ui/src/router/routes/website/inbox/reports.index.tsx new file mode 100644 index 0000000000..5ae1c29253 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/reports.index.tsx @@ -0,0 +1,6 @@ +import { ReportsTab } from "@posthog/ui/features/inbox/components/ReportsTab"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/reports/")({ + component: ReportsTab, +}); diff --git a/packages/ui/src/router/routes/website/inbox/reports.tsx b/packages/ui/src/router/routes/website/inbox/reports.tsx new file mode 100644 index 0000000000..8446b5dbdb --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/reports.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/reports")({ + component: Outlet, +}); diff --git a/packages/ui/src/router/routes/website/inbox/runs.$reportId.tsx b/packages/ui/src/router/routes/website/inbox/runs.$reportId.tsx new file mode 100644 index 0000000000..c99fd0a0b1 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/runs.$reportId.tsx @@ -0,0 +1,11 @@ +import { AgentRunDetail } from "@posthog/ui/features/inbox/components/AgentRunDetail"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/runs/$reportId")({ + component: RunDetailRoute, +}); + +function RunDetailRoute() { + const { reportId } = Route.useParams(); + return ; +} diff --git a/packages/ui/src/router/routes/website/inbox/runs.index.tsx b/packages/ui/src/router/routes/website/inbox/runs.index.tsx new file mode 100644 index 0000000000..3f9be2f385 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/runs.index.tsx @@ -0,0 +1,6 @@ +import { RunsTab } from "@posthog/ui/features/inbox/components/RunsTab"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/runs/")({ + component: RunsTab, +}); diff --git a/packages/ui/src/router/routes/website/inbox/runs.tsx b/packages/ui/src/router/routes/website/inbox/runs.tsx new file mode 100644 index 0000000000..d6896db9b5 --- /dev/null +++ b/packages/ui/src/router/routes/website/inbox/runs.tsx @@ -0,0 +1,5 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; + +export const Route = createFileRoute("/website/inbox/runs")({ + component: Outlet, +}); diff --git a/packages/ui/src/router/routes/website/mcp-servers.tsx b/packages/ui/src/router/routes/website/mcp-servers.tsx deleted file mode 100644 index 6c99cefc7e..0000000000 --- a/packages/ui/src/router/routes/website/mcp-servers.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { McpServersView } from "@posthog/ui/features/mcp-servers/components/McpServersView"; -import { createFileRoute } from "@tanstack/react-router"; - -// Channels-space mirror of /mcp-servers. Renders the same shared McpServersView -// so the page stays single-source; only the route entry is duplicated so -// navigating here keeps the channels chrome (rail + channel sidebar). -export const Route = createFileRoute("/website/mcp-servers")({ - component: McpServersView, -}); diff --git a/packages/ui/src/router/routes/website/skills.tsx b/packages/ui/src/router/routes/website/skills.tsx deleted file mode 100644 index e18f14d5e8..0000000000 --- a/packages/ui/src/router/routes/website/skills.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { SkillsView } from "@posthog/ui/features/skills/SkillsView"; -import { createFileRoute } from "@tanstack/react-router"; - -// Channels-space mirror of /skills. Renders the same shared SkillsView so the -// page stays single-source; only the route entry is duplicated so navigating -// here keeps the channels chrome (rail + channel sidebar). -export const Route = createFileRoute("/website/skills")({ - component: SkillsView, -}); diff --git a/packages/ui/src/router/useAppView.ts b/packages/ui/src/router/useAppView.ts index ec2fad08d3..75baf5b392 100644 --- a/packages/ui/src/router/useAppView.ts +++ b/packages/ui/src/router/useAppView.ts @@ -66,8 +66,12 @@ function deriveFromMatches(matches: Match[]): AppView { case "/website/home": return { type: "home" }; case "/code/inbox": + // Channels-space inbox mirror — same view type so the sidebar highlights + // the Inbox item identically in either space. + case "/website/inbox": return { type: "inbox" }; case "/code/agents": + case "/website/agents": return { type: "agents" }; case "/code/archived": return { type: "archived" }; @@ -75,22 +79,30 @@ function deriveFromMatches(matches: Match[]): AppView { case "/website/command-center": return { type: "command-center" }; case "/skills": - case "/website/skills": + // Channels-space Skills now lives inside the Customize page's secondary nav. + case "/website/customize/skills": return { type: "skills" }; case "/mcp-servers": - case "/website/mcp-servers": + case "/website/customize/mcp-servers": return { type: "mcp-servers" }; case "/settings/$category": case "/settings/": return { type: "settings" }; default: - if (last.routeId.startsWith("/code/inbox")) { + if ( + last.routeId.startsWith("/code/inbox") || + last.routeId.startsWith("/website/inbox") + ) { return { type: "inbox" }; } // /code/agents is now an Outlet layout; the view lives at the index // child (/code/agents/) and scout detail routes nest deeper, so match - // the whole subtree rather than only the bare layout route. - if (last.routeId.startsWith("/code/agents")) { + // the whole subtree rather than only the bare layout route. Same for the + // /website/agents channels-space mirror. + if ( + last.routeId.startsWith("/code/agents") || + last.routeId.startsWith("/website/agents") + ) { return { type: "agents" }; } return { type: "task-input" }; diff --git a/packages/ui/src/shell/GlobalEventHandlers.tsx b/packages/ui/src/shell/GlobalEventHandlers.tsx index 7c1552752c..83b26b857d 100644 --- a/packages/ui/src/shell/GlobalEventHandlers.tsx +++ b/packages/ui/src/shell/GlobalEventHandlers.tsx @@ -21,7 +21,7 @@ import { goBackInHistory, goForwardInHistory, navigateToFolderSettings, - navigateToInbox, + navigateToInboxInCurrentSpace, } from "@posthog/ui/router/navigationBridge"; import { useAppView } from "@posthog/ui/router/useAppView"; import { openTask, openTaskInput } from "@posthog/ui/router/useOpenTask"; @@ -170,7 +170,7 @@ export function GlobalEventHandlers({ useHotkeys(SHORTCUTS.TOGGLE_LEFT_SIDEBAR, toggleLeftSidebar, globalOptions); useHotkeys(SHORTCUTS.TOGGLE_REVIEW_PANEL, handleToggleReview, globalOptions); useHotkeys(SHORTCUTS.SHORTCUTS_SHEET, onToggleShortcutsSheet, globalOptions); - useHotkeys(SHORTCUTS.INBOX, navigateToInbox, globalOptions); + useHotkeys(SHORTCUTS.INBOX, navigateToInboxInCurrentSpace, globalOptions); useHotkeys(SHORTCUTS.PREV_TASK, handlePrevTask, globalOptions, [ handlePrevTask, ]);