Compare commits

..

1 Commits

Author SHA1 Message Date
Dane Urban
d35a5c49d8 ci script 2026-02-23 13:41:10 -08:00
5 changed files with 23 additions and 161 deletions

View File

@@ -3,8 +3,8 @@ set -e
cleanup() {
echo "Error occurred. Cleaning up..."
docker stop onyx_postgres onyx_vespa onyx_redis onyx_minio 2>/dev/null || true
docker rm onyx_postgres onyx_vespa onyx_redis onyx_minio 2>/dev/null || true
docker stop onyx_postgres onyx_vespa onyx_redis onyx_minio onyx_code_interpreter 2>/dev/null || true
docker rm onyx_postgres onyx_vespa onyx_redis onyx_minio onyx_code_interpreter 2>/dev/null || true
}
# Trap errors and output a message, then cleanup
@@ -20,8 +20,8 @@ MINIO_VOLUME=${4:-""} # Default is empty if not provided
# Stop and remove the existing containers
echo "Stopping and removing existing containers..."
docker stop onyx_postgres onyx_vespa onyx_redis onyx_minio 2>/dev/null || true
docker rm onyx_postgres onyx_vespa onyx_redis onyx_minio 2>/dev/null || true
docker stop onyx_postgres onyx_vespa onyx_redis onyx_minio onyx_code_interpreter 2>/dev/null || true
docker rm onyx_postgres onyx_vespa onyx_redis onyx_minio onyx_code_interpreter 2>/dev/null || true
# Start the PostgreSQL container with optional volume
echo "Starting PostgreSQL container..."
@@ -55,6 +55,10 @@ else
docker run --detach --name onyx_minio --publish 9004:9000 --publish 9005:9001 -e MINIO_ROOT_USER=minioadmin -e MINIO_ROOT_PASSWORD=minioadmin minio/minio server /data --console-address ":9001"
fi
# Start the Code Interpreter container
echo "Starting Code Interpreter container..."
docker run --detach --name onyx_code_interpreter --publish 8000:8000 --user root -v /var/run/docker.sock:/var/run/docker.sock onyxdotapp/code-interpreter:latest bash ./entrypoint.sh code-interpreter-api
# Ensure alembic runs in the correct directory (backend/)
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
PARENT_DIR="$(dirname "$SCRIPT_DIR")"

View File

@@ -1,13 +1,8 @@
"use client";
import { useCallback, useEffect, useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { MinimalPersonaSnapshot } from "@/app/admin/assistants/interfaces";
import { useOnboardingState } from "@/refresh-components/onboarding/useOnboardingState";
function getOnboardingCompletedKey(userId: string): string {
return `onyx:onboardingCompleted:${userId}`;
}
interface UseShowOnboardingParams {
liveAssistant: MinimalPersonaSnapshot | undefined;
isLoadingProviders: boolean;
@@ -26,15 +21,6 @@ export function useShowOnboarding({
userId,
}: UseShowOnboardingParams) {
const [showOnboarding, setShowOnboarding] = useState(false);
const [onboardingDismissed, setOnboardingDismissed] = useState(false);
// Read localStorage once userId is available to check if onboarding was dismissed
useEffect(() => {
if (userId === undefined) return;
const dismissed =
localStorage.getItem(getOnboardingCompletedKey(userId)) === "true";
setOnboardingDismissed(dismissed);
}, [userId]);
// Initialize onboarding state
const {
@@ -52,23 +38,13 @@ export function useShowOnboarding({
// Show onboarding only if no LLM providers are configured.
// Skip entirely if user has existing chat sessions.
useEffect(() => {
// If onboarding was previously dismissed, never show it again
if (onboardingDismissed) {
setShowOnboarding(false);
return;
}
// Wait for data to load
if (isLoadingProviders || isLoadingChatSessions || userId === undefined) {
return;
}
// Only check once per user — but allow self-correction from true→false
// when provider data arrives (e.g. after a transient fetch error).
// Only check once per user
if (hasCheckedOnboardingForUserId.current === userId) {
if (showOnboarding && hasAnyProvider && onboardingState.stepIndex === 0) {
setShowOnboarding(false);
}
return;
}
hasCheckedOnboardingForUserId.current = userId;
@@ -87,24 +63,18 @@ export function useShowOnboarding({
hasAnyProvider,
chatSessionsCount,
userId,
showOnboarding,
onboardingDismissed,
onboardingState.stepIndex,
]);
const dismissOnboarding = useCallback(() => {
if (userId === undefined) return;
const hideOnboarding = () => {
setShowOnboarding(false);
setOnboardingDismissed(true);
localStorage.setItem(getOnboardingCompletedKey(userId), "true");
}, [userId]);
};
const hideOnboarding = dismissOnboarding;
const finishOnboarding = dismissOnboarding;
const finishOnboarding = () => {
setShowOnboarding(false);
};
return {
showOnboarding,
onboardingDismissed,
onboardingState,
onboardingActions,
llmDescriptors,

View File

@@ -17,13 +17,11 @@ const mockActions = {
reset: jest.fn(),
};
let mockStepIndex = 0;
jest.mock("@/refresh-components/onboarding/useOnboardingState", () => ({
useOnboardingState: () => ({
state: {
currentStep: OnboardingStep.Welcome,
stepIndex: mockStepIndex,
stepIndex: 0,
totalSteps: 3,
data: {},
isButtonActive: true,
@@ -62,8 +60,6 @@ function renderUseShowOnboarding(
describe("useShowOnboarding", () => {
beforeEach(() => {
jest.clearAllMocks();
localStorage.clear();
mockStepIndex = 0;
});
it("returns showOnboarding=false while providers are loading", () => {
@@ -111,7 +107,7 @@ describe("useShowOnboarding", () => {
expect(result.current.showOnboarding).toBe(false);
});
it("self-corrects showOnboarding to false when providers arrive late", () => {
it("only evaluates once per userId", () => {
const { result, rerender } = renderUseShowOnboarding({
hasAnyProvider: false,
chatSessionsCount: 0,
@@ -119,7 +115,7 @@ describe("useShowOnboarding", () => {
});
expect(result.current.showOnboarding).toBe(true);
// Re-render with same userId but provider data now available
// Re-render with same userId but different provider state
rerender({
liveAssistant: undefined,
isLoadingProviders: false,
@@ -129,32 +125,7 @@ describe("useShowOnboarding", () => {
userId: "user-1",
});
// Should correct to false — providers exist, no need for LLM setup flow
expect(result.current.showOnboarding).toBe(false);
});
it("does not self-correct when user has advanced past Welcome step", () => {
const { result, rerender } = renderUseShowOnboarding({
hasAnyProvider: false,
chatSessionsCount: 0,
userId: "user-1",
});
expect(result.current.showOnboarding).toBe(true);
// Simulate user advancing past Welcome (e.g. they configured an LLM provider)
mockStepIndex = 1;
// Re-render with same userId but provider data now available
rerender({
liveAssistant: undefined,
isLoadingProviders: false,
hasAnyProvider: true,
isLoadingChatSessions: false,
chatSessionsCount: 0,
userId: "user-1",
});
// Should stay true — user is actively using onboarding
// Should still be true because it was already evaluated for this userId
expect(result.current.showOnboarding).toBe(true);
});
@@ -215,83 +186,4 @@ describe("useShowOnboarding", () => {
expect(result.current.onboardingActions).toBeDefined();
expect(result.current.llmDescriptors).toEqual([]);
});
describe("localStorage persistence", () => {
it("finishOnboarding sets localStorage flag and onboardingDismissed", () => {
const { result } = renderUseShowOnboarding({
hasAnyProvider: false,
chatSessionsCount: 0,
});
expect(result.current.showOnboarding).toBe(true);
expect(result.current.onboardingDismissed).toBe(false);
act(() => {
result.current.finishOnboarding();
});
expect(result.current.showOnboarding).toBe(false);
expect(result.current.onboardingDismissed).toBe(true);
expect(localStorage.getItem("onyx:onboardingCompleted:user-1")).toBe(
"true"
);
});
it("hideOnboarding sets localStorage flag and onboardingDismissed", () => {
const { result } = renderUseShowOnboarding({
hasAnyProvider: false,
chatSessionsCount: 0,
});
act(() => {
result.current.hideOnboarding();
});
expect(result.current.onboardingDismissed).toBe(true);
expect(localStorage.getItem("onyx:onboardingCompleted:user-1")).toBe(
"true"
);
});
it("showOnboarding stays false when localStorage flag is set", () => {
localStorage.setItem("onyx:onboardingCompleted:user-1", "true");
const { result } = renderUseShowOnboarding({
hasAnyProvider: false,
chatSessionsCount: 0,
});
expect(result.current.showOnboarding).toBe(false);
expect(result.current.onboardingDismissed).toBe(true);
});
it("onboardingDismissed is false when localStorage flag is not set", () => {
const { result } = renderUseShowOnboarding();
expect(result.current.onboardingDismissed).toBe(false);
});
it("dismissal for user-1 does not suppress onboarding for user-2", () => {
const { result: result1 } = renderUseShowOnboarding({
hasAnyProvider: false,
chatSessionsCount: 0,
userId: "1",
});
expect(result1.current.showOnboarding).toBe(true);
act(() => {
result1.current.finishOnboarding();
});
expect(result1.current.onboardingDismissed).toBe(true);
expect(localStorage.getItem("onyx:onboardingCompleted:1")).toBe("true");
// user-2 should still see onboarding
const { result: result2 } = renderUseShowOnboarding({
hasAnyProvider: false,
chatSessionsCount: 0,
userId: "2",
});
expect(result2.current.showOnboarding).toBe(true);
expect(result2.current.onboardingDismissed).toBe(false);
expect(localStorage.getItem("onyx:onboardingCompleted:2")).toBeNull();
});
});
});

View File

@@ -51,7 +51,7 @@ export default function NonAdminStep() {
<>
{showHeader && (
<div
className="flex items-center justify-between w-full min-h-11 py-1 pl-3 pr-2 bg-background-tint-00 rounded-16 shadow-01 mb-2"
className="flex items-center justify-between w-full max-w-[800px] min-h-11 py-1 pl-3 pr-2 bg-background-tint-00 rounded-16 shadow-01 mb-2"
aria-label="non-admin-confirmation"
>
<div className="flex items-center gap-1">

View File

@@ -228,7 +228,6 @@ export default function AppPage({ firstMessage }: ChatPageProps) {
const {
showOnboarding,
onboardingDismissed,
onboardingState,
onboardingActions,
llmDescriptors,
@@ -464,7 +463,7 @@ export default function AppPage({ firstMessage }: ChatPageProps) {
currentMessageFiles,
deepResearch: deepResearchEnabled,
});
if (showOnboarding || !onboardingDismissed) {
if (showOnboarding) {
finishOnboarding();
}
},
@@ -474,7 +473,6 @@ export default function AppPage({ firstMessage }: ChatPageProps) {
currentMessageFiles,
deepResearchEnabled,
showOnboarding,
onboardingDismissed,
finishOnboarding,
]
);
@@ -508,7 +506,7 @@ export default function AppPage({ firstMessage }: ChatPageProps) {
currentMessageFiles,
deepResearch: deepResearchEnabled,
});
if (showOnboarding || !onboardingDismissed) {
if (showOnboarding) {
finishOnboarding();
}
return;
@@ -529,7 +527,6 @@ export default function AppPage({ firstMessage }: ChatPageProps) {
currentMessageFiles,
deepResearchEnabled,
showOnboarding,
onboardingDismissed,
finishOnboarding,
]
);
@@ -807,8 +804,7 @@ export default function AppPage({ firstMessage }: ChatPageProps) {
{/* OnboardingUI */}
{(appFocus.isNewSession() || appFocus.isAgent()) &&
!classification &&
(showOnboarding || !user?.personalization?.name) &&
!onboardingDismissed && (
(showOnboarding || !user?.personalization?.name) && (
<OnboardingFlow
showOnboarding={showOnboarding}
handleHideOnboarding={hideOnboarding}