diff --git a/api/controllers/console/auth/oauth_server.py b/api/controllers/console/auth/oauth_server.py index 6f728d96e37..fe297c6c725 100644 --- a/api/controllers/console/auth/oauth_server.py +++ b/api/controllers/console/auth/oauth_server.py @@ -57,6 +57,7 @@ class OAuthProviderTokenResponse(BaseModel): class OAuthProviderAccountResponse(BaseModel): + id: str name: str email: str avatar: str | None = None @@ -252,6 +253,7 @@ class OAuthServerUserAccountApi(Resource): def post(self, oauth_provider_app: OAuthProviderApp, account: Account): return jsonable_encoder( { + "id": account.id, "name": account.name, "email": account.email, "avatar": account.avatar, diff --git a/api/tests/unit_tests/controllers/console/auth/test_oauth_server.py b/api/tests/unit_tests/controllers/console/auth/test_oauth_server.py index 2477f537a47..7a03e089e9d 100644 --- a/api/tests/unit_tests/controllers/console/auth/test_oauth_server.py +++ b/api/tests/unit_tests/controllers/console/auth/test_oauth_server.py @@ -7,6 +7,7 @@ from controllers.console.auth.oauth_server import ( OAuthProviderAppResponse, OAuthProviderRequest, OAuthServerAppApi, + OAuthServerUserAccountApi, OAuthServerUserAuthorizeApi, ) from models import Account @@ -52,6 +53,16 @@ def test_oauth_authorize_uses_injected_current_user() -> None: assert response == {"code": "authorization-code"} +def test_oauth_account_returns_stable_account_id() -> None: + api = OAuthServerUserAccountApi() + method = unwrap(api.post) + account = _make_account() + + response = method(api, _make_oauth_provider_app(), account) + + assert response["id"] == "account-1" + + def test_oauth_provider_app_response_requires_auto_authorize() -> None: # A missing field must fail validation instead of silently defaulting: # an optional field would surface as `undefined` in the generated TS diff --git a/packages/contracts/generated/api/console/oauth/types.gen.ts b/packages/contracts/generated/api/console/oauth/types.gen.ts index 075b41f75d3..2108c56280d 100644 --- a/packages/contracts/generated/api/console/oauth/types.gen.ts +++ b/packages/contracts/generated/api/console/oauth/types.gen.ts @@ -41,6 +41,7 @@ export type OAuthClientPayload = { export type OAuthProviderAccountResponse = { avatar?: string | null email: string + id: string interface_language: string name: string timezone: string diff --git a/packages/contracts/generated/api/console/oauth/zod.gen.ts b/packages/contracts/generated/api/console/oauth/zod.gen.ts index d632f0a2124..960d1e429c3 100644 --- a/packages/contracts/generated/api/console/oauth/zod.gen.ts +++ b/packages/contracts/generated/api/console/oauth/zod.gen.ts @@ -61,6 +61,7 @@ export const zOAuthClientPayload = z.object({ export const zOAuthProviderAccountResponse = z.object({ avatar: z.string().nullish(), email: z.string(), + id: z.string(), interface_language: z.string(), name: z.string(), timezone: z.string(), diff --git a/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx b/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx index d8ad419c527..fab2b9d3820 100644 --- a/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx +++ b/web/features/new-rag/__tests__/knowledge-space-shell.spec.tsx @@ -115,9 +115,13 @@ describe('KnowledgeSpaceShell', () => { }) it.each([ + ['/datasets/new/space-1', 'dataset.newKnowledge.overviewTitle'], ['/datasets/new/space-1/sources', 'dataset.newKnowledge.sources'], ['/datasets/new/space-1/sources/new', 'dataset.newKnowledge.addSource'], ['/datasets/new/space-1/documents', 'dataset.newKnowledge.documents'], + ['/datasets/new/space-1/retrieval', 'dataset.newKnowledge.retrievalTest.title'], + ['/datasets/new/space-1/quality', 'dataset.newKnowledge.quality'], + ['/datasets/new/space-1/settings', 'common.datasetMenus.settings'], ])('identifies the current detail page for %s', async (pathname, pageTitle) => { pathnameMock.value = pathname queryMock.data = { diff --git a/web/features/new-rag/knowledge-space-shell.tsx b/web/features/new-rag/knowledge-space-shell.tsx index 2b414eeb90f..0e5ca52cde1 100644 --- a/web/features/new-rag/knowledge-space-shell.tsx +++ b/web/features/new-rag/knowledge-space-shell.tsx @@ -71,10 +71,18 @@ function retrievalModeFromProfile(modelProfile: unknown) { const knowledgeSpacePageTitle = ( pathname: string, t: ReturnType>['t'], + tCommon: ReturnType>['t'], ) => { - if (pathname.includes('/sources/new')) return t(($) => $['newKnowledge.addSource']) - if (pathname.includes('/sources')) return t(($) => $['newKnowledge.sources']) - if (pathname.includes('/documents')) return t(($) => $['newKnowledge.documents']) + const [, root, view, , section, detail] = pathname.split('/') + if (root !== 'datasets' || view !== 'new') return t(($) => $.knowledge) + + if (!section) return t(($) => $['newKnowledge.overviewTitle']) + if (section === 'sources' && detail === 'new') return t(($) => $['newKnowledge.addSource']) + if (section === 'sources') return t(($) => $['newKnowledge.sources']) + if (section === 'documents') return t(($) => $['newKnowledge.documents']) + if (section === 'retrieval') return t(($) => $['newKnowledge.retrievalTest.title']) + if (section === 'quality') return t(($) => $['newKnowledge.quality']) + if (section === 'settings') return tCommon(($) => $['datasetMenus.settings']) return t(($) => $.knowledge) } @@ -133,7 +141,7 @@ export function KnowledgeSpaceShell({ knowledgeSpaceQuery.data?.technical_summary?.name ?? t(($) => $.knowledge) const modelProfile = knowledgeSpaceQuery.data?.technical_summary?.model_profile const retrievalMode = retrievalModeFromProfile(modelProfile) - const pageTitle = knowledgeSpacePageTitle(pathname, t) + const pageTitle = knowledgeSpacePageTitle(pathname, t, tCommon) const documentTitle = `${pageTitle} ยท ${knowledgeSpaceName}` const documentTitleOwnedByChild = isDocumentDetailPath(pathname) &&