Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions app/api/evaluations/[id]/improve-prompt/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,8 @@ export async function POST(
try {
const { id } = await params;

let userBody: Record<string, unknown> = {};
try {
const parsed = await request.json();
if (parsed && typeof parsed === "object") {
userBody = parsed as Record<string, unknown>;
}
} catch {
userBody = {};
}

const payload = {
...userBody,
callback_url: userBody.callback_url ?? resolveCallbackUrl(request),
callback_url: resolveCallbackUrl(request),
};

const { status, data } = await apiClient(
Expand Down
35 changes: 26 additions & 9 deletions app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import {
SlidersIcon,
ChatIcon,
ChartBarIcon,
WarningTriangleIcon,
} from "@/app/components/icons";
import { InfoTooltip } from "@/app/components/ui";
import { MenuItem, SidebarProps } from "@/app/lib/types/nav";
import { LoginModal } from "@/app/components/auth";
import { Branding, UserMenuPopover } from "@/app/components/user-menu";
Expand Down Expand Up @@ -144,6 +146,7 @@ export default function Sidebar({
submenu: item.submenu,
gateDescription: item.gateDescription,
featureFlag: item.featureFlag,
disabledReason: item.disabledReason,
}));

const getGateDescription = (name: string): string => {
Expand Down Expand Up @@ -182,7 +185,8 @@ export default function Sidebar({
const hasSubmenu = item.submenu && item.submenu.length > 0;
const isExpanded = expandedMenus[item.name];
const isActive = activeRoute === item.route;
const gated = isItemGated(item);
const isDisabled = !!item.disabledReason;
const gated = !isDisabled && isItemGated(item);

const hasActiveChild =
hasSubmenu &&
Expand All @@ -194,8 +198,9 @@ export default function Sidebar({
);

return (
<div key={item.name}>
<div key={item.name} className="relative">
<button
disabled={isDisabled}
onMouseEnter={(e) =>
gated && handleGateEnter(item.name, e.currentTarget)
}
Expand All @@ -208,13 +213,15 @@ export default function Sidebar({
router.push(item.route);
}
}}
className={`w-full text-left px-3 py-2 rounded-lg text-[14px] flex items-center gap-2.5 transition-all duration-150 border cursor-pointer ${
isActive
? "bg-accent-primary/15 text-accent-primary font-semibold border-transparent"
: hasActiveChild
? "bg-transparent text-accent-primary font-semibold border-transparent"
: "bg-transparent text-text-secondary font-medium border-transparent hover:bg-neutral-100 hover:text-text-primary"
}`}
className={`w-full text-left px-3 py-2 rounded-lg text-[14px] flex items-center gap-2.5 transition-all duration-150 border ${
isDisabled
? "bg-transparent text-text-secondary font-medium border-transparent opacity-50 cursor-not-allowed"
: isActive
? "bg-accent-primary/15 text-accent-primary font-semibold border-transparent"
: hasActiveChild
? "bg-transparent text-accent-primary font-semibold border-transparent"
: "bg-transparent text-text-secondary font-medium border-transparent hover:bg-neutral-100 hover:text-text-primary"
} ${isDisabled ? "" : "cursor-pointer"}`}
>
<span
className={
Expand All @@ -232,6 +239,16 @@ export default function Sidebar({
/>
)}
</button>
{isDisabled && (
<span className="absolute right-3 top-1/2 -translate-y-1/2">
<InfoTooltip
text={item.disabledReason}
icon={
<WarningTriangleIcon className="w-4 h-4 text-amber-500" />
}
/>
</span>
)}

{hasSubmenu && isExpanded && !gated && (
<div className="ml-5 mt-1 space-y-0.5 overflow-hidden border-l-2 border-border pl-3 animate-[slideDown_0.15s_ease-out]">
Expand Down
5 changes: 3 additions & 2 deletions app/components/ui/InfoTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import { TooltipIcon } from "@/app/components/icons";

interface InfoTooltipProps {
text: ReactNode;
icon?: ReactNode;
}

export default function InfoTooltip({ text }: InfoTooltipProps) {
export default function InfoTooltip({ text, icon }: InfoTooltipProps) {
const [visible, setVisible] = useState(false);
const [positioned, setPositioned] = useState(false);
const [position, setPosition] = useState({ top: 0, left: 0 });
Expand Down Expand Up @@ -65,7 +66,7 @@ export default function InfoTooltip({ text }: InfoTooltipProps) {
onBlur={() => setVisible(false)}
className="w-4 h-4 rounded-full text-[10px] font-bold flex items-center justify-center leading-none select-none cursor-pointer"
>
<TooltipIcon className="w-4 h-4 text-[#99B3C1]" />
{icon ?? <TooltipIcon className="w-4 h-4 text-[#99B3C1]" />}
</button>
{visible &&
createPortal(
Expand Down
2 changes: 2 additions & 0 deletions app/lib/navConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export const NAV_ITEMS: NavItemConfig[] = [
route: "/guardrails",
icon: "shield",
gateDescription: "Log in to manage guardrails and validators.",
disabledReason:
"Guardrails is temporarily disabled. We're making significant backend changes and things aren't in sync yet — it will be re-enabled once everything is aligned. To explore Guardrails, please contact the Kaapi team.",
},
{
name: "Chat",
Expand Down
2 changes: 2 additions & 0 deletions app/lib/types/nav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface NavItemConfig {
gateDescription?: string;
superuserOnly?: boolean;
featureFlag?: FeatureFlagKey;
disabledReason?: string;
}

export interface SubMenuItem {
Expand All @@ -30,6 +31,7 @@ export interface MenuItem {
submenu?: SubMenuItem[];
gateDescription?: string;
featureFlag?: FeatureFlagKey;
disabledReason?: string;
}

export interface SidebarProps {
Expand Down
11 changes: 11 additions & 0 deletions middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ const FEATURE_GATED_PREFIXES: Array<{
flag: FeatureFlagKey;
}> = [{ prefix: "/assessment", flag: FeatureFlag.ASSESSMENT }];

// Temporarily disabled while backend changes are being synced; keep in sync with `disabledReason` in navConfig.
const DISABLED_PREFIXES = ["/guardrails"];

const GUEST_ONLY_ROUTES = new Set<string>(["/keystore"]);

const HOME_ROUTE = "/chat";
Expand Down Expand Up @@ -57,6 +60,14 @@ export function middleware(request: NextRequest) {
const isAuthenticated = hasApiKey || role === "superuser" || role === "user";
const isSuperuser = role === "superuser";

if (
DISABLED_PREFIXES.some(
(prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`),
)
) {
return redirectHome(request);
}

if (GUEST_ONLY_ROUTES.has(pathname)) {
if (isAuthenticated) {
return redirectHome(request);
Expand Down
Loading