diff --git a/apps/onboarding/viewsets.py b/apps/onboarding/viewsets.py index 0d451a6..150a09f 100644 --- a/apps/onboarding/viewsets.py +++ b/apps/onboarding/viewsets.py @@ -23,11 +23,17 @@ class OnboardingFlowViewSet(ModelViewSet): def get_queryset(self): user = self.request.user - return OnboardingFlow.objects.filter( + queryset = OnboardingFlow.objects.filter( Q(role__organization__owner=user) | Q(role__organization__members=user) ).distinct() + role_uuid = self.request.query_params.get('role') + if role_uuid: + queryset = queryset.filter(role__uuid=role_uuid) + + return queryset.order_by('-created_at') + def destroy(self, request, *args, **kwargs): flow = self.get_object() @@ -87,8 +93,15 @@ class OnboardingSessionViewSet(ModelViewSet): def get_queryset(self): user = self.request.user if user.is_manager: - return OnboardingSession.objects.filter(role__organization__members=user).distinct() - return OnboardingSession.objects.filter(user=user) + queryset = OnboardingSession.objects.filter(role__organization__members=user).distinct() + else: + queryset = OnboardingSession.objects.filter(user=user) + + role_uuid = self.request.query_params.get('role') + if role_uuid: + queryset = queryset.filter(role__uuid=role_uuid) + + return queryset.order_by('-created_at') @action(detail=True, methods=['post'], url_path='interact') def interact(self, request, uuid=None): diff --git a/gpu_server.py b/gpu_server.py index 3dc2572..36f33e2 100644 --- a/gpu_server.py +++ b/gpu_server.py @@ -70,6 +70,15 @@ async def lifespan(app: FastAPI): app = FastAPI(title="Agentic GPU Node", lifespan=lifespan) +@app.get("/health") +async def health(): + return { + "status": "ok", + "embedding_ready": state.get("embed_model") is not None, + "llm_ready": state.get("llm") is not None, + } + + def pad_and_normalize(embeddings: torch.Tensor) -> torch.Tensor: """Standardizes vector dimensions to 1536 for pgvector compatibility.""" curr_dim = embeddings.shape[1] @@ -190,7 +199,14 @@ async def semantic_chunk(request: Request): @app.post("/v1/chat/completions") async def chat_completions(request: Request): """Unified LLM completion endpoint compatible with OpenAI-style requests.""" - data = await request.json() + try: + data = await request.json() + except Exception as e: + raw_body = await request.body() + preview = raw_body[:500].decode("utf-8", errors="replace") + logger.error(f"Invalid JSON payload for chat completions: {e}; body_preview={preview}") + raise HTTPException(status_code=400, detail="Invalid JSON payload") + messages = data.get("messages", []) stream = data.get("stream", False) diff --git a/site/src/views/OnboardingView.vue b/site/src/views/OnboardingView.vue index d169ea2..7c5abdb 100644 --- a/site/src/views/OnboardingView.vue +++ b/site/src/views/OnboardingView.vue @@ -59,13 +59,25 @@ type SessionSummary = { role?: string | { uuid?: string } } +type FlowSummary = { + uuid: string + role?: string | { uuid?: string } +} + const getSessionRoleUuid = (sessionData: SessionSummary): string | undefined => { if (typeof sessionData.role === 'string') return sessionData.role return sessionData.role?.uuid } +const getFlowRoleUuid = (flowData: FlowSummary): string | undefined => { + if (typeof flowData.role === 'string') return flowData.role + return flowData.role?.uuid +} + const findCompletedSessionForRole = async (): Promise => { - const sessionRes = await apiClient.get(API.onboardingSessions()) + const sessionRes = await apiClient.get(API.onboardingSessions(), { + params: { role: roleId.value }, + }) return ( sessionRes.data.find( (item) => item.status === 'completed' && getSessionRoleUuid(item) === roleId.value, @@ -134,7 +146,14 @@ const initOnboarding = async () => { }) if (response.data && response.data.length > 0) { - flowDetails.value = response.data[0] + const matchingFlow = response.data.find((item) => getFlowRoleUuid(item) === roleId.value) + if (!matchingFlow) { + flowDetails.value = null + session.value = null + return + } + + flowDetails.value = matchingFlow const completedSession = await findCompletedSessionForRole() if (completedSession) { @@ -144,7 +163,7 @@ const initOnboarding = async () => { return } - await loadFlow(response.data[0].uuid) + await loadFlow(matchingFlow.uuid) } else { if (!generationHandled.value) { await startAgenticGeneration() @@ -192,6 +211,21 @@ watch( }, ) +watch( + () => roleId.value, + async () => { + flowDetails.value = null + session.value = null + currentPageIndex.value = 0 + generationHandled.value = false + isAutoGenerating.value = false + Object.keys(formState).forEach((k) => delete formState[k]) + agentStore.disconnect() + agentStore.clearLog() + await initOnboarding() + }, +) + const loadFlow = async (flowUuid: string) => { const response = await apiClient.get(API.onboardingFlow(flowUuid)) flowDetails.value = response.data