mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-28 16:38:17 -05:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27b72062f2 | ||
|
|
e0dfae5732 | ||
|
|
9a79a8d257 | ||
|
|
7df867d645 | ||
|
|
a9bf08748b | ||
|
|
d855f79874 |
@@ -21,7 +21,7 @@ from backend.data.model import CredentialsMetaInput
|
|||||||
from backend.integrations.creds_manager import IntegrationCredentialsManager
|
from backend.integrations.creds_manager import IntegrationCredentialsManager
|
||||||
from backend.integrations.webhooks.graph_lifecycle_hooks import on_graph_activate
|
from backend.integrations.webhooks.graph_lifecycle_hooks import on_graph_activate
|
||||||
from backend.util.clients import get_scheduler_client
|
from backend.util.clients import get_scheduler_client
|
||||||
from backend.util.exceptions import DatabaseError, NotFoundError
|
from backend.util.exceptions import DatabaseError, InvalidInputError, NotFoundError
|
||||||
from backend.util.json import SafeJson
|
from backend.util.json import SafeJson
|
||||||
from backend.util.models import Pagination
|
from backend.util.models import Pagination
|
||||||
from backend.util.settings import Config
|
from backend.util.settings import Config
|
||||||
@@ -64,11 +64,11 @@ async def list_library_agents(
|
|||||||
|
|
||||||
if page < 1 or page_size < 1:
|
if page < 1 or page_size < 1:
|
||||||
logger.warning(f"Invalid pagination: page={page}, page_size={page_size}")
|
logger.warning(f"Invalid pagination: page={page}, page_size={page_size}")
|
||||||
raise DatabaseError("Invalid pagination input")
|
raise InvalidInputError("Invalid pagination input")
|
||||||
|
|
||||||
if search_term and len(search_term.strip()) > 100:
|
if search_term and len(search_term.strip()) > 100:
|
||||||
logger.warning(f"Search term too long: {repr(search_term)}")
|
logger.warning(f"Search term too long: {repr(search_term)}")
|
||||||
raise DatabaseError("Search term is too long")
|
raise InvalidInputError("Search term is too long")
|
||||||
|
|
||||||
where_clause: prisma.types.LibraryAgentWhereInput = {
|
where_clause: prisma.types.LibraryAgentWhereInput = {
|
||||||
"userId": user_id,
|
"userId": user_id,
|
||||||
@@ -175,7 +175,7 @@ async def list_favorite_library_agents(
|
|||||||
|
|
||||||
if page < 1 or page_size < 1:
|
if page < 1 or page_size < 1:
|
||||||
logger.warning(f"Invalid pagination: page={page}, page_size={page_size}")
|
logger.warning(f"Invalid pagination: page={page}, page_size={page_size}")
|
||||||
raise DatabaseError("Invalid pagination input")
|
raise InvalidInputError("Invalid pagination input")
|
||||||
|
|
||||||
where_clause: prisma.types.LibraryAgentWhereInput = {
|
where_clause: prisma.types.LibraryAgentWhereInput = {
|
||||||
"userId": user_id,
|
"userId": user_id,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import logging
|
|
||||||
from typing import Literal, Optional
|
from typing import Literal, Optional
|
||||||
|
|
||||||
import autogpt_libs.auth as autogpt_auth_lib
|
import autogpt_libs.auth as autogpt_auth_lib
|
||||||
@@ -6,15 +5,11 @@ from fastapi import APIRouter, Body, HTTPException, Query, Security, status
|
|||||||
from fastapi.responses import Response
|
from fastapi.responses import Response
|
||||||
from prisma.enums import OnboardingStep
|
from prisma.enums import OnboardingStep
|
||||||
|
|
||||||
import backend.api.features.store.exceptions as store_exceptions
|
|
||||||
from backend.data.onboarding import complete_onboarding_step
|
from backend.data.onboarding import complete_onboarding_step
|
||||||
from backend.util.exceptions import DatabaseError, NotFoundError
|
|
||||||
|
|
||||||
from .. import db as library_db
|
from .. import db as library_db
|
||||||
from .. import model as library_model
|
from .. import model as library_model
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/agents",
|
prefix="/agents",
|
||||||
tags=["library", "private"],
|
tags=["library", "private"],
|
||||||
@@ -26,10 +21,6 @@ router = APIRouter(
|
|||||||
"",
|
"",
|
||||||
summary="List Library Agents",
|
summary="List Library Agents",
|
||||||
response_model=library_model.LibraryAgentResponse,
|
response_model=library_model.LibraryAgentResponse,
|
||||||
responses={
|
|
||||||
200: {"description": "List of library agents"},
|
|
||||||
500: {"description": "Server error", "content": {"application/json": {}}},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
async def list_library_agents(
|
async def list_library_agents(
|
||||||
user_id: str = Security(autogpt_auth_lib.get_user_id),
|
user_id: str = Security(autogpt_auth_lib.get_user_id),
|
||||||
@@ -53,43 +44,19 @@ async def list_library_agents(
|
|||||||
) -> library_model.LibraryAgentResponse:
|
) -> library_model.LibraryAgentResponse:
|
||||||
"""
|
"""
|
||||||
Get all agents in the user's library (both created and saved).
|
Get all agents in the user's library (both created and saved).
|
||||||
|
|
||||||
Args:
|
|
||||||
user_id: ID of the authenticated user.
|
|
||||||
search_term: Optional search term to filter agents by name/description.
|
|
||||||
filter_by: List of filters to apply (favorites, created by user).
|
|
||||||
sort_by: List of sorting criteria (created date, updated date).
|
|
||||||
page: Page number to retrieve.
|
|
||||||
page_size: Number of agents per page.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A LibraryAgentResponse containing agents and pagination metadata.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HTTPException: If a server/database error occurs.
|
|
||||||
"""
|
"""
|
||||||
try:
|
return await library_db.list_library_agents(
|
||||||
return await library_db.list_library_agents(
|
user_id=user_id,
|
||||||
user_id=user_id,
|
search_term=search_term,
|
||||||
search_term=search_term,
|
sort_by=sort_by,
|
||||||
sort_by=sort_by,
|
page=page,
|
||||||
page=page,
|
page_size=page_size,
|
||||||
page_size=page_size,
|
)
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Could not list library agents for user #{user_id}: {e}")
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
||||||
detail=str(e),
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/favorites",
|
"/favorites",
|
||||||
summary="List Favorite Library Agents",
|
summary="List Favorite Library Agents",
|
||||||
responses={
|
|
||||||
500: {"description": "Server error", "content": {"application/json": {}}},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
async def list_favorite_library_agents(
|
async def list_favorite_library_agents(
|
||||||
user_id: str = Security(autogpt_auth_lib.get_user_id),
|
user_id: str = Security(autogpt_auth_lib.get_user_id),
|
||||||
@@ -106,30 +73,12 @@ async def list_favorite_library_agents(
|
|||||||
) -> library_model.LibraryAgentResponse:
|
) -> library_model.LibraryAgentResponse:
|
||||||
"""
|
"""
|
||||||
Get all favorite agents in the user's library.
|
Get all favorite agents in the user's library.
|
||||||
|
|
||||||
Args:
|
|
||||||
user_id: ID of the authenticated user.
|
|
||||||
page: Page number to retrieve.
|
|
||||||
page_size: Number of agents per page.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
A LibraryAgentResponse containing favorite agents and pagination metadata.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HTTPException: If a server/database error occurs.
|
|
||||||
"""
|
"""
|
||||||
try:
|
return await library_db.list_favorite_library_agents(
|
||||||
return await library_db.list_favorite_library_agents(
|
user_id=user_id,
|
||||||
user_id=user_id,
|
page=page,
|
||||||
page=page,
|
page_size=page_size,
|
||||||
page_size=page_size,
|
)
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Could not list favorite library agents for user #{user_id}: {e}")
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
||||||
detail=str(e),
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{library_agent_id}", summary="Get Library Agent")
|
@router.get("/{library_agent_id}", summary="Get Library Agent")
|
||||||
@@ -162,10 +111,6 @@ async def get_library_agent_by_graph_id(
|
|||||||
summary="Get Agent By Store ID",
|
summary="Get Agent By Store ID",
|
||||||
tags=["store", "library"],
|
tags=["store", "library"],
|
||||||
response_model=library_model.LibraryAgent | None,
|
response_model=library_model.LibraryAgent | None,
|
||||||
responses={
|
|
||||||
200: {"description": "Library agent found"},
|
|
||||||
404: {"description": "Agent not found"},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
async def get_library_agent_by_store_listing_version_id(
|
async def get_library_agent_by_store_listing_version_id(
|
||||||
store_listing_version_id: str,
|
store_listing_version_id: str,
|
||||||
@@ -174,32 +119,15 @@ async def get_library_agent_by_store_listing_version_id(
|
|||||||
"""
|
"""
|
||||||
Get Library Agent from Store Listing Version ID.
|
Get Library Agent from Store Listing Version ID.
|
||||||
"""
|
"""
|
||||||
try:
|
return await library_db.get_library_agent_by_store_version_id(
|
||||||
return await library_db.get_library_agent_by_store_version_id(
|
store_listing_version_id, user_id
|
||||||
store_listing_version_id, user_id
|
)
|
||||||
)
|
|
||||||
except NotFoundError as e:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
|
||||||
detail=str(e),
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Could not fetch library agent from store version ID: {e}")
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
||||||
detail=str(e),
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
@router.post(
|
||||||
"",
|
"",
|
||||||
summary="Add Marketplace Agent",
|
summary="Add Marketplace Agent",
|
||||||
status_code=status.HTTP_201_CREATED,
|
status_code=status.HTTP_201_CREATED,
|
||||||
responses={
|
|
||||||
201: {"description": "Agent added successfully"},
|
|
||||||
404: {"description": "Store listing version not found"},
|
|
||||||
500: {"description": "Server error"},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
async def add_marketplace_agent_to_library(
|
async def add_marketplace_agent_to_library(
|
||||||
store_listing_version_id: str = Body(embed=True),
|
store_listing_version_id: str = Body(embed=True),
|
||||||
@@ -210,59 +138,19 @@ async def add_marketplace_agent_to_library(
|
|||||||
) -> library_model.LibraryAgent:
|
) -> library_model.LibraryAgent:
|
||||||
"""
|
"""
|
||||||
Add an agent from the marketplace to the user's library.
|
Add an agent from the marketplace to the user's library.
|
||||||
|
|
||||||
Args:
|
|
||||||
store_listing_version_id: ID of the store listing version to add.
|
|
||||||
user_id: ID of the authenticated user.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
library_model.LibraryAgent: Agent added to the library
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HTTPException(404): If the listing version is not found.
|
|
||||||
HTTPException(500): If a server/database error occurs.
|
|
||||||
"""
|
"""
|
||||||
try:
|
agent = await library_db.add_store_agent_to_library(
|
||||||
agent = await library_db.add_store_agent_to_library(
|
store_listing_version_id=store_listing_version_id,
|
||||||
store_listing_version_id=store_listing_version_id,
|
user_id=user_id,
|
||||||
user_id=user_id,
|
)
|
||||||
)
|
if source != "onboarding":
|
||||||
if source != "onboarding":
|
await complete_onboarding_step(user_id, OnboardingStep.MARKETPLACE_ADD_AGENT)
|
||||||
await complete_onboarding_step(
|
return agent
|
||||||
user_id, OnboardingStep.MARKETPLACE_ADD_AGENT
|
|
||||||
)
|
|
||||||
return agent
|
|
||||||
|
|
||||||
except store_exceptions.AgentNotFoundError as e:
|
|
||||||
logger.warning(
|
|
||||||
f"Could not find store listing version {store_listing_version_id} "
|
|
||||||
"to add to library"
|
|
||||||
)
|
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
|
|
||||||
except DatabaseError as e:
|
|
||||||
logger.error(f"Database error while adding agent to library: {e}", e)
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
||||||
detail={"message": str(e), "hint": "Inspect DB logs for details."},
|
|
||||||
) from e
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Unexpected error while adding agent to library: {e}")
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
||||||
detail={
|
|
||||||
"message": str(e),
|
|
||||||
"hint": "Check server logs for more information.",
|
|
||||||
},
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
@router.patch(
|
@router.patch(
|
||||||
"/{library_agent_id}",
|
"/{library_agent_id}",
|
||||||
summary="Update Library Agent",
|
summary="Update Library Agent",
|
||||||
responses={
|
|
||||||
200: {"description": "Agent updated successfully"},
|
|
||||||
500: {"description": "Server error"},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
async def update_library_agent(
|
async def update_library_agent(
|
||||||
library_agent_id: str,
|
library_agent_id: str,
|
||||||
@@ -271,52 +159,21 @@ async def update_library_agent(
|
|||||||
) -> library_model.LibraryAgent:
|
) -> library_model.LibraryAgent:
|
||||||
"""
|
"""
|
||||||
Update the library agent with the given fields.
|
Update the library agent with the given fields.
|
||||||
|
|
||||||
Args:
|
|
||||||
library_agent_id: ID of the library agent to update.
|
|
||||||
payload: Fields to update (auto_update_version, is_favorite, etc.).
|
|
||||||
user_id: ID of the authenticated user.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HTTPException(500): If a server/database error occurs.
|
|
||||||
"""
|
"""
|
||||||
try:
|
return await library_db.update_library_agent(
|
||||||
return await library_db.update_library_agent(
|
library_agent_id=library_agent_id,
|
||||||
library_agent_id=library_agent_id,
|
user_id=user_id,
|
||||||
user_id=user_id,
|
auto_update_version=payload.auto_update_version,
|
||||||
auto_update_version=payload.auto_update_version,
|
graph_version=payload.graph_version,
|
||||||
graph_version=payload.graph_version,
|
is_favorite=payload.is_favorite,
|
||||||
is_favorite=payload.is_favorite,
|
is_archived=payload.is_archived,
|
||||||
is_archived=payload.is_archived,
|
settings=payload.settings,
|
||||||
settings=payload.settings,
|
)
|
||||||
)
|
|
||||||
except NotFoundError as e:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
|
||||||
detail=str(e),
|
|
||||||
) from e
|
|
||||||
except DatabaseError as e:
|
|
||||||
logger.error(f"Database error while updating library agent: {e}")
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
||||||
detail={"message": str(e), "hint": "Verify DB connection."},
|
|
||||||
) from e
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Unexpected error while updating library agent: {e}")
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
||||||
detail={"message": str(e), "hint": "Check server logs."},
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
@router.delete(
|
@router.delete(
|
||||||
"/{library_agent_id}",
|
"/{library_agent_id}",
|
||||||
summary="Delete Library Agent",
|
summary="Delete Library Agent",
|
||||||
responses={
|
|
||||||
204: {"description": "Agent deleted successfully"},
|
|
||||||
404: {"description": "Agent not found"},
|
|
||||||
500: {"description": "Server error"},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
async def delete_library_agent(
|
async def delete_library_agent(
|
||||||
library_agent_id: str,
|
library_agent_id: str,
|
||||||
@@ -324,28 +181,11 @@ async def delete_library_agent(
|
|||||||
) -> Response:
|
) -> Response:
|
||||||
"""
|
"""
|
||||||
Soft-delete the specified library agent.
|
Soft-delete the specified library agent.
|
||||||
|
|
||||||
Args:
|
|
||||||
library_agent_id: ID of the library agent to delete.
|
|
||||||
user_id: ID of the authenticated user.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
204 No Content if successful.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HTTPException(404): If the agent does not exist.
|
|
||||||
HTTPException(500): If a server/database error occurs.
|
|
||||||
"""
|
"""
|
||||||
try:
|
await library_db.delete_library_agent(
|
||||||
await library_db.delete_library_agent(
|
library_agent_id=library_agent_id, user_id=user_id
|
||||||
library_agent_id=library_agent_id, user_id=user_id
|
)
|
||||||
)
|
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
|
||||||
except NotFoundError as e:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
|
||||||
detail=str(e),
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/{library_agent_id}/fork", summary="Fork Library Agent")
|
@router.post("/{library_agent_id}/fork", summary="Fork Library Agent")
|
||||||
|
|||||||
@@ -118,21 +118,6 @@ async def test_get_library_agents_success(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_get_library_agents_error(mocker: pytest_mock.MockFixture, test_user_id: str):
|
|
||||||
mock_db_call = mocker.patch("backend.api.features.library.db.list_library_agents")
|
|
||||||
mock_db_call.side_effect = Exception("Test error")
|
|
||||||
|
|
||||||
response = client.get("/agents?search_term=test")
|
|
||||||
assert response.status_code == 500
|
|
||||||
mock_db_call.assert_called_once_with(
|
|
||||||
user_id=test_user_id,
|
|
||||||
search_term="test",
|
|
||||||
sort_by=library_model.LibraryAgentSort.UPDATED_AT,
|
|
||||||
page=1,
|
|
||||||
page_size=15,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_favorite_library_agents_success(
|
async def test_get_favorite_library_agents_success(
|
||||||
mocker: pytest_mock.MockFixture,
|
mocker: pytest_mock.MockFixture,
|
||||||
@@ -190,23 +175,6 @@ async def test_get_favorite_library_agents_success(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_get_favorite_library_agents_error(
|
|
||||||
mocker: pytest_mock.MockFixture, test_user_id: str
|
|
||||||
):
|
|
||||||
mock_db_call = mocker.patch(
|
|
||||||
"backend.api.features.library.db.list_favorite_library_agents"
|
|
||||||
)
|
|
||||||
mock_db_call.side_effect = Exception("Test error")
|
|
||||||
|
|
||||||
response = client.get("/agents/favorites")
|
|
||||||
assert response.status_code == 500
|
|
||||||
mock_db_call.assert_called_once_with(
|
|
||||||
user_id=test_user_id,
|
|
||||||
page=1,
|
|
||||||
page_size=15,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_add_agent_to_library_success(
|
def test_add_agent_to_library_success(
|
||||||
mocker: pytest_mock.MockFixture, test_user_id: str
|
mocker: pytest_mock.MockFixture, test_user_id: str
|
||||||
):
|
):
|
||||||
@@ -258,19 +226,3 @@ def test_add_agent_to_library_success(
|
|||||||
store_listing_version_id="test-version-id", user_id=test_user_id
|
store_listing_version_id="test-version-id", user_id=test_user_id
|
||||||
)
|
)
|
||||||
mock_complete_onboarding.assert_awaited_once()
|
mock_complete_onboarding.assert_awaited_once()
|
||||||
|
|
||||||
|
|
||||||
def test_add_agent_to_library_error(mocker: pytest_mock.MockFixture, test_user_id: str):
|
|
||||||
mock_db_call = mocker.patch(
|
|
||||||
"backend.api.features.library.db.add_store_agent_to_library"
|
|
||||||
)
|
|
||||||
mock_db_call.side_effect = Exception("Test error")
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/agents", json={"store_listing_version_id": "test-version-id"}
|
|
||||||
)
|
|
||||||
assert response.status_code == 500
|
|
||||||
assert "detail" in response.json() # Verify error response structure
|
|
||||||
mock_db_call.assert_called_once_with(
|
|
||||||
store_listing_version_id="test-version-id", user_id=test_user_id
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -454,6 +454,7 @@ async def backfill_all_content_types(batch_size: int = 10) -> dict[str, Any]:
|
|||||||
total_processed = 0
|
total_processed = 0
|
||||||
total_success = 0
|
total_success = 0
|
||||||
total_failed = 0
|
total_failed = 0
|
||||||
|
all_errors: dict[str, int] = {} # Aggregate errors across all content types
|
||||||
|
|
||||||
# Process content types in explicit order
|
# Process content types in explicit order
|
||||||
processing_order = [
|
processing_order = [
|
||||||
@@ -499,23 +500,12 @@ async def backfill_all_content_types(batch_size: int = 10) -> dict[str, Any]:
|
|||||||
success = sum(1 for result in results if result is True)
|
success = sum(1 for result in results if result is True)
|
||||||
failed = len(results) - success
|
failed = len(results) - success
|
||||||
|
|
||||||
# Aggregate unique errors to avoid Sentry spam
|
# Aggregate errors across all content types
|
||||||
if failed > 0:
|
if failed > 0:
|
||||||
# Group errors by type and message
|
|
||||||
error_summary: dict[str, int] = {}
|
|
||||||
for result in results:
|
for result in results:
|
||||||
if isinstance(result, Exception):
|
if isinstance(result, Exception):
|
||||||
error_key = f"{type(result).__name__}: {str(result)}"
|
error_key = f"{type(result).__name__}: {str(result)}"
|
||||||
error_summary[error_key] = error_summary.get(error_key, 0) + 1
|
all_errors[error_key] = all_errors.get(error_key, 0) + 1
|
||||||
|
|
||||||
# Log aggregated error summary
|
|
||||||
error_details = ", ".join(
|
|
||||||
f"{error} ({count}x)" for error, count in error_summary.items()
|
|
||||||
)
|
|
||||||
logger.error(
|
|
||||||
f"{content_type.value}: {failed}/{len(results)} embeddings failed. "
|
|
||||||
f"Errors: {error_details}"
|
|
||||||
)
|
|
||||||
|
|
||||||
results_by_type[content_type.value] = {
|
results_by_type[content_type.value] = {
|
||||||
"processed": len(missing_items),
|
"processed": len(missing_items),
|
||||||
@@ -542,6 +532,13 @@ async def backfill_all_content_types(batch_size: int = 10) -> dict[str, Any]:
|
|||||||
"error": str(e),
|
"error": str(e),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Log aggregated errors once at the end
|
||||||
|
if all_errors:
|
||||||
|
error_details = ", ".join(
|
||||||
|
f"{error} ({count}x)" for error, count in all_errors.items()
|
||||||
|
)
|
||||||
|
logger.error(f"Embedding backfill errors: {error_details}")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"by_type": results_by_type,
|
"by_type": results_by_type,
|
||||||
"totals": {
|
"totals": {
|
||||||
|
|||||||
@@ -261,18 +261,36 @@ async def get_onboarding_agents(
|
|||||||
return await get_recommended_agents(user_id)
|
return await get_recommended_agents(user_id)
|
||||||
|
|
||||||
|
|
||||||
|
class OnboardingStatusResponse(pydantic.BaseModel):
|
||||||
|
"""Response for onboarding status check."""
|
||||||
|
|
||||||
|
is_onboarding_enabled: bool
|
||||||
|
is_chat_enabled: bool
|
||||||
|
|
||||||
|
|
||||||
@v1_router.get(
|
@v1_router.get(
|
||||||
"/onboarding/enabled",
|
"/onboarding/enabled",
|
||||||
summary="Is onboarding enabled",
|
summary="Is onboarding enabled",
|
||||||
tags=["onboarding", "public"],
|
tags=["onboarding", "public"],
|
||||||
|
response_model=OnboardingStatusResponse,
|
||||||
)
|
)
|
||||||
async def is_onboarding_enabled(
|
async def is_onboarding_enabled(
|
||||||
user_id: Annotated[str, Security(get_user_id)],
|
user_id: Annotated[str, Security(get_user_id)],
|
||||||
) -> bool:
|
) -> OnboardingStatusResponse:
|
||||||
# If chat is enabled for user, skip legacy onboarding
|
# Check if chat is enabled for user
|
||||||
if await is_feature_enabled(Flag.CHAT, user_id, False):
|
is_chat_enabled = await is_feature_enabled(Flag.CHAT, user_id, False)
|
||||||
return False
|
|
||||||
return await onboarding_enabled()
|
# If chat is enabled, skip legacy onboarding
|
||||||
|
if is_chat_enabled:
|
||||||
|
return OnboardingStatusResponse(
|
||||||
|
is_onboarding_enabled=False,
|
||||||
|
is_chat_enabled=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
return OnboardingStatusResponse(
|
||||||
|
is_onboarding_enabled=await onboarding_enabled(),
|
||||||
|
is_chat_enabled=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@v1_router.post(
|
@v1_router.post(
|
||||||
|
|||||||
@@ -135,6 +135,12 @@ class GraphValidationError(ValueError):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidInputError(ValueError):
|
||||||
|
"""Raised when user input validation fails (e.g., search term too long)"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class DatabaseError(Exception):
|
class DatabaseError(Exception):
|
||||||
"""Raised when there is an error interacting with the database"""
|
"""Raised when there is an error interacting with the database"""
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
import { LoadingSpinner } from "@/components/atoms/LoadingSpinner/LoadingSpinner";
|
import { LoadingSpinner } from "@/components/atoms/LoadingSpinner/LoadingSpinner";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { resolveResponse, shouldShowOnboarding } from "@/app/api/helpers";
|
import { resolveResponse, getOnboardingStatus } from "@/app/api/helpers";
|
||||||
import { getV1OnboardingState } from "@/app/api/__generated__/endpoints/onboarding/onboarding";
|
import { getV1OnboardingState } from "@/app/api/__generated__/endpoints/onboarding/onboarding";
|
||||||
|
import { getHomepageRoute } from "@/lib/constants";
|
||||||
|
|
||||||
export default function OnboardingPage() {
|
export default function OnboardingPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -11,10 +12,13 @@ export default function OnboardingPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function redirectToStep() {
|
async function redirectToStep() {
|
||||||
try {
|
try {
|
||||||
// Check if onboarding is enabled
|
// Check if onboarding is enabled (also gets chat flag for redirect)
|
||||||
const isEnabled = await shouldShowOnboarding();
|
const { shouldShowOnboarding, isChatEnabled } =
|
||||||
if (!isEnabled) {
|
await getOnboardingStatus();
|
||||||
router.replace("/");
|
const homepageRoute = getHomepageRoute(isChatEnabled);
|
||||||
|
|
||||||
|
if (!shouldShowOnboarding) {
|
||||||
|
router.replace(homepageRoute);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +26,7 @@ export default function OnboardingPage() {
|
|||||||
|
|
||||||
// Handle completed onboarding
|
// Handle completed onboarding
|
||||||
if (onboarding.completedSteps.includes("GET_RESULTS")) {
|
if (onboarding.completedSteps.includes("GET_RESULTS")) {
|
||||||
router.replace("/");
|
router.replace(homepageRoute);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
|
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
|
||||||
|
import { getHomepageRoute } from "@/lib/constants";
|
||||||
import BackendAPI from "@/lib/autogpt-server-api";
|
import BackendAPI from "@/lib/autogpt-server-api";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
import { shouldShowOnboarding } from "@/app/api/helpers";
|
import { getOnboardingStatus } from "@/app/api/helpers";
|
||||||
|
|
||||||
// Handle the callback to complete the user session login
|
// Handle the callback to complete the user session login
|
||||||
export async function GET(request: Request) {
|
export async function GET(request: Request) {
|
||||||
@@ -25,11 +26,15 @@ export async function GET(request: Request) {
|
|||||||
const api = new BackendAPI();
|
const api = new BackendAPI();
|
||||||
await api.createUser();
|
await api.createUser();
|
||||||
|
|
||||||
if (await shouldShowOnboarding()) {
|
// Get onboarding status from backend (includes chat flag evaluated for this user)
|
||||||
|
const { shouldShowOnboarding, isChatEnabled } =
|
||||||
|
await getOnboardingStatus();
|
||||||
|
if (shouldShowOnboarding) {
|
||||||
next = "/onboarding";
|
next = "/onboarding";
|
||||||
revalidatePath("/onboarding", "layout");
|
revalidatePath("/onboarding", "layout");
|
||||||
} else {
|
} else {
|
||||||
revalidatePath("/", "layout");
|
next = getHomepageRoute(isChatEnabled);
|
||||||
|
revalidatePath(next, "layout");
|
||||||
}
|
}
|
||||||
} catch (createUserError) {
|
} catch (createUserError) {
|
||||||
console.error("Error creating user:", createUserError);
|
console.error("Error creating user:", createUserError);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
|
import { getHomepageRoute } from "@/lib/constants";
|
||||||
import BackendAPI from "@/lib/autogpt-server-api";
|
import BackendAPI from "@/lib/autogpt-server-api";
|
||||||
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
|
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
|
||||||
import { loginFormSchema } from "@/types/auth";
|
import { loginFormSchema } from "@/types/auth";
|
||||||
import * as Sentry from "@sentry/nextjs";
|
import * as Sentry from "@sentry/nextjs";
|
||||||
import { shouldShowOnboarding } from "../../api/helpers";
|
import { getOnboardingStatus } from "../../api/helpers";
|
||||||
|
|
||||||
export async function login(email: string, password: string) {
|
export async function login(email: string, password: string) {
|
||||||
try {
|
try {
|
||||||
@@ -36,11 +37,15 @@ export async function login(email: string, password: string) {
|
|||||||
const api = new BackendAPI();
|
const api = new BackendAPI();
|
||||||
await api.createUser();
|
await api.createUser();
|
||||||
|
|
||||||
const onboarding = await shouldShowOnboarding();
|
// Get onboarding status from backend (includes chat flag evaluated for this user)
|
||||||
|
const { shouldShowOnboarding, isChatEnabled } = await getOnboardingStatus();
|
||||||
|
const next = shouldShowOnboarding
|
||||||
|
? "/onboarding"
|
||||||
|
: getHomepageRoute(isChatEnabled);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
onboarding,
|
next,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
|
|||||||
@@ -97,13 +97,8 @@ export function useLoginPage() {
|
|||||||
throw new Error(result.error || "Login failed");
|
throw new Error(result.error || "Login failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextUrl) {
|
// Prefer URL's next parameter, then use backend-determined route
|
||||||
router.replace(nextUrl);
|
router.replace(nextUrl || result.next || homepageRoute);
|
||||||
} else if (result.onboarding) {
|
|
||||||
router.replace("/onboarding");
|
|
||||||
} else {
|
|
||||||
router.replace(homepageRoute);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast({
|
toast({
|
||||||
title:
|
title:
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
|
|||||||
import { signupFormSchema } from "@/types/auth";
|
import { signupFormSchema } from "@/types/auth";
|
||||||
import * as Sentry from "@sentry/nextjs";
|
import * as Sentry from "@sentry/nextjs";
|
||||||
import { isWaitlistError, logWaitlistError } from "../../api/auth/utils";
|
import { isWaitlistError, logWaitlistError } from "../../api/auth/utils";
|
||||||
import { shouldShowOnboarding } from "../../api/helpers";
|
import { getOnboardingStatus } from "../../api/helpers";
|
||||||
|
|
||||||
export async function signup(
|
export async function signup(
|
||||||
email: string,
|
email: string,
|
||||||
password: string,
|
password: string,
|
||||||
confirmPassword: string,
|
confirmPassword: string,
|
||||||
agreeToTerms: boolean,
|
agreeToTerms: boolean,
|
||||||
isChatEnabled: boolean,
|
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const parsed = signupFormSchema.safeParse({
|
const parsed = signupFormSchema.safeParse({
|
||||||
@@ -59,8 +58,9 @@ export async function signup(
|
|||||||
await supabase.auth.setSession(data.session);
|
await supabase.auth.setSession(data.session);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isOnboardingEnabled = await shouldShowOnboarding();
|
// Get onboarding status from backend (includes chat flag evaluated for this user)
|
||||||
const next = isOnboardingEnabled
|
const { shouldShowOnboarding, isChatEnabled } = await getOnboardingStatus();
|
||||||
|
const next = shouldShowOnboarding
|
||||||
? "/onboarding"
|
? "/onboarding"
|
||||||
: getHomepageRoute(isChatEnabled);
|
: getHomepageRoute(isChatEnabled);
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ export function useSignupPage() {
|
|||||||
data.password,
|
data.password,
|
||||||
data.confirmPassword,
|
data.confirmPassword,
|
||||||
data.agreeToTerms,
|
data.agreeToTerms,
|
||||||
isChatEnabled === true,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
|||||||
@@ -175,9 +175,12 @@ export async function resolveResponse<
|
|||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function shouldShowOnboarding() {
|
export async function getOnboardingStatus() {
|
||||||
const isEnabled = await resolveResponse(getV1IsOnboardingEnabled());
|
const status = await resolveResponse(getV1IsOnboardingEnabled());
|
||||||
const onboarding = await resolveResponse(getV1OnboardingState());
|
const onboarding = await resolveResponse(getV1OnboardingState());
|
||||||
const isCompleted = onboarding.completedSteps.includes("CONGRATS");
|
const isCompleted = onboarding.completedSteps.includes("CONGRATS");
|
||||||
return isEnabled && !isCompleted;
|
return {
|
||||||
|
shouldShowOnboarding: status.is_onboarding_enabled && !isCompleted,
|
||||||
|
isChatEnabled: status.is_chat_enabled,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3339,7 +3339,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"tags": ["v2", "library", "private"],
|
"tags": ["v2", "library", "private"],
|
||||||
"summary": "List Library Agents",
|
"summary": "List Library Agents",
|
||||||
"description": "Get all agents in the user's library (both created and saved).\n\nArgs:\n user_id: ID of the authenticated user.\n search_term: Optional search term to filter agents by name/description.\n filter_by: List of filters to apply (favorites, created by user).\n sort_by: List of sorting criteria (created date, updated date).\n page: Page number to retrieve.\n page_size: Number of agents per page.\n\nReturns:\n A LibraryAgentResponse containing agents and pagination metadata.\n\nRaises:\n HTTPException: If a server/database error occurs.",
|
"description": "Get all agents in the user's library (both created and saved).",
|
||||||
"operationId": "getV2List library agents",
|
"operationId": "getV2List library agents",
|
||||||
"security": [{ "HTTPBearerJWT": [] }],
|
"security": [{ "HTTPBearerJWT": [] }],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@@ -3394,7 +3394,7 @@
|
|||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "List of library agents",
|
"description": "Successful Response",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@@ -3413,17 +3413,13 @@
|
|||||||
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Server error",
|
|
||||||
"content": { "application/json": {} }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"post": {
|
"post": {
|
||||||
"tags": ["v2", "library", "private"],
|
"tags": ["v2", "library", "private"],
|
||||||
"summary": "Add Marketplace Agent",
|
"summary": "Add Marketplace Agent",
|
||||||
"description": "Add an agent from the marketplace to the user's library.\n\nArgs:\n store_listing_version_id: ID of the store listing version to add.\n user_id: ID of the authenticated user.\n\nReturns:\n library_model.LibraryAgent: Agent added to the library\n\nRaises:\n HTTPException(404): If the listing version is not found.\n HTTPException(500): If a server/database error occurs.",
|
"description": "Add an agent from the marketplace to the user's library.",
|
||||||
"operationId": "postV2Add marketplace agent",
|
"operationId": "postV2Add marketplace agent",
|
||||||
"security": [{ "HTTPBearerJWT": [] }],
|
"security": [{ "HTTPBearerJWT": [] }],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
@@ -3438,7 +3434,7 @@
|
|||||||
},
|
},
|
||||||
"responses": {
|
"responses": {
|
||||||
"201": {
|
"201": {
|
||||||
"description": "Agent added successfully",
|
"description": "Successful Response",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": { "$ref": "#/components/schemas/LibraryAgent" }
|
"schema": { "$ref": "#/components/schemas/LibraryAgent" }
|
||||||
@@ -3448,7 +3444,6 @@
|
|||||||
"401": {
|
"401": {
|
||||||
"$ref": "#/components/responses/HTTP401NotAuthenticatedError"
|
"$ref": "#/components/responses/HTTP401NotAuthenticatedError"
|
||||||
},
|
},
|
||||||
"404": { "description": "Store listing version not found" },
|
|
||||||
"422": {
|
"422": {
|
||||||
"description": "Validation Error",
|
"description": "Validation Error",
|
||||||
"content": {
|
"content": {
|
||||||
@@ -3456,8 +3451,7 @@
|
|||||||
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"500": { "description": "Server error" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3511,7 +3505,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"tags": ["v2", "library", "private"],
|
"tags": ["v2", "library", "private"],
|
||||||
"summary": "List Favorite Library Agents",
|
"summary": "List Favorite Library Agents",
|
||||||
"description": "Get all favorite agents in the user's library.\n\nArgs:\n user_id: ID of the authenticated user.\n page: Page number to retrieve.\n page_size: Number of agents per page.\n\nReturns:\n A LibraryAgentResponse containing favorite agents and pagination metadata.\n\nRaises:\n HTTPException: If a server/database error occurs.",
|
"description": "Get all favorite agents in the user's library.",
|
||||||
"operationId": "getV2List favorite library agents",
|
"operationId": "getV2List favorite library agents",
|
||||||
"security": [{ "HTTPBearerJWT": [] }],
|
"security": [{ "HTTPBearerJWT": [] }],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@@ -3563,10 +3557,6 @@
|
|||||||
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"500": {
|
|
||||||
"description": "Server error",
|
|
||||||
"content": { "application/json": {} }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3588,7 +3578,7 @@
|
|||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "Library agent found",
|
"description": "Successful Response",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@@ -3604,7 +3594,6 @@
|
|||||||
"401": {
|
"401": {
|
||||||
"$ref": "#/components/responses/HTTP401NotAuthenticatedError"
|
"$ref": "#/components/responses/HTTP401NotAuthenticatedError"
|
||||||
},
|
},
|
||||||
"404": { "description": "Agent not found" },
|
|
||||||
"422": {
|
"422": {
|
||||||
"description": "Validation Error",
|
"description": "Validation Error",
|
||||||
"content": {
|
"content": {
|
||||||
@@ -3620,7 +3609,7 @@
|
|||||||
"delete": {
|
"delete": {
|
||||||
"tags": ["v2", "library", "private"],
|
"tags": ["v2", "library", "private"],
|
||||||
"summary": "Delete Library Agent",
|
"summary": "Delete Library Agent",
|
||||||
"description": "Soft-delete the specified library agent.\n\nArgs:\n library_agent_id: ID of the library agent to delete.\n user_id: ID of the authenticated user.\n\nReturns:\n 204 No Content if successful.\n\nRaises:\n HTTPException(404): If the agent does not exist.\n HTTPException(500): If a server/database error occurs.",
|
"description": "Soft-delete the specified library agent.",
|
||||||
"operationId": "deleteV2Delete library agent",
|
"operationId": "deleteV2Delete library agent",
|
||||||
"security": [{ "HTTPBearerJWT": [] }],
|
"security": [{ "HTTPBearerJWT": [] }],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@@ -3636,11 +3625,9 @@
|
|||||||
"description": "Successful Response",
|
"description": "Successful Response",
|
||||||
"content": { "application/json": { "schema": {} } }
|
"content": { "application/json": { "schema": {} } }
|
||||||
},
|
},
|
||||||
"204": { "description": "Agent deleted successfully" },
|
|
||||||
"401": {
|
"401": {
|
||||||
"$ref": "#/components/responses/HTTP401NotAuthenticatedError"
|
"$ref": "#/components/responses/HTTP401NotAuthenticatedError"
|
||||||
},
|
},
|
||||||
"404": { "description": "Agent not found" },
|
|
||||||
"422": {
|
"422": {
|
||||||
"description": "Validation Error",
|
"description": "Validation Error",
|
||||||
"content": {
|
"content": {
|
||||||
@@ -3648,8 +3635,7 @@
|
|||||||
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"500": { "description": "Server error" }
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"get": {
|
"get": {
|
||||||
@@ -3690,7 +3676,7 @@
|
|||||||
"patch": {
|
"patch": {
|
||||||
"tags": ["v2", "library", "private"],
|
"tags": ["v2", "library", "private"],
|
||||||
"summary": "Update Library Agent",
|
"summary": "Update Library Agent",
|
||||||
"description": "Update the library agent with the given fields.\n\nArgs:\n library_agent_id: ID of the library agent to update.\n payload: Fields to update (auto_update_version, is_favorite, etc.).\n user_id: ID of the authenticated user.\n\nRaises:\n HTTPException(500): If a server/database error occurs.",
|
"description": "Update the library agent with the given fields.",
|
||||||
"operationId": "patchV2Update library agent",
|
"operationId": "patchV2Update library agent",
|
||||||
"security": [{ "HTTPBearerJWT": [] }],
|
"security": [{ "HTTPBearerJWT": [] }],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@@ -3713,7 +3699,7 @@
|
|||||||
},
|
},
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "Agent updated successfully",
|
"description": "Successful Response",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": { "$ref": "#/components/schemas/LibraryAgent" }
|
"schema": { "$ref": "#/components/schemas/LibraryAgent" }
|
||||||
@@ -3730,8 +3716,7 @@
|
|||||||
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"500": { "description": "Server error" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4540,8 +4525,7 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "boolean",
|
"$ref": "#/components/schemas/OnboardingStatusResponse"
|
||||||
"title": "Response Getv1Is Onboarding Enabled"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8745,6 +8729,19 @@
|
|||||||
"title": "OAuthApplicationPublicInfo",
|
"title": "OAuthApplicationPublicInfo",
|
||||||
"description": "Public information about an OAuth application (for consent screen)"
|
"description": "Public information about an OAuth application (for consent screen)"
|
||||||
},
|
},
|
||||||
|
"OnboardingStatusResponse": {
|
||||||
|
"properties": {
|
||||||
|
"is_onboarding_enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Is Onboarding Enabled"
|
||||||
|
},
|
||||||
|
"is_chat_enabled": { "type": "boolean", "title": "Is Chat Enabled" }
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"required": ["is_onboarding_enabled", "is_chat_enabled"],
|
||||||
|
"title": "OnboardingStatusResponse",
|
||||||
|
"description": "Response for onboarding status check."
|
||||||
|
},
|
||||||
"OnboardingStep": {
|
"OnboardingStep": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
|||||||
Reference in New Issue
Block a user