Skip to content

dbeaver/pro#9532 Support user AI credentials - #4624

Open
yagudin10 wants to merge 39 commits into
develfrom
dbeaver/pro#9532-user-ai-credentials
Open

dbeaver/pro#9532 Support user AI credentials#4624
yagudin10 wants to merge 39 commits into
develfrom
dbeaver/pro#9532-user-ai-credentials

Conversation

@yagudin10

Copy link
Copy Markdown
Member

Closes dbeaver/pro#9532

Summary

  • expose generic per-profile credential mutations and profile status through GraphQL
  • store user credentials in private secret storage with a CE session fallback
  • apply user credentials only to effective runtime profiles and add regression tests

Testing

  • WebAIProfileCredentialsTest was run from IntelliJ
  • full Tycho build was not run

@codacy-production

codacy-production Bot commented Sep 2, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 5 critical · 1 minor

Alerts:
⚠ 6 issues (≤ 0 issues of at least minor severity)

Results:
6 new issues

Category Results
Documentation 1 minor
Security 5 critical

View in Codacy

🟢 Metrics 468 complexity · 6 duplication

Metric Results
Complexity 468
Duplication 6

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

sergeyteleshev and others added 27 commits September 2, 2026 14:35
@sergeyteleshev
sergeyteleshev requested a lite review from Copilot September 8, 2026 14:53
@sergeyteleshev
sergeyteleshev force-pushed the dbeaver/pro#9532-user-ai-credentials branch from 243d74b to 3700a52 Compare September 8, 2026 14:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a few confirmed functional issues (session-credentials lookup, inconsistent profile scope state, and click bubbling causing unintended profile selection) that should be fixed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds per-user AI profile credentials support across the CloudBeaver stack: GraphQL exposes profile global/credentialsSaved and a credentials mutation; the server stores user credentials in private secret storage (with session fallback) and applies them only to effective runtime profiles; the frontend introduces new AI Profiles plugins and UI surfaces for managing/entering credentials in both administration and user profile/AI chat flows.

Changes:

  • Introduced aiSaveProfileCredentials GraphQL mutation and extended AI profile fields (global, credentialsSaved) end-to-end (schema + core-sdk queries + frontend resources).
  • Added new frontend packages for AI profiles, administration UI, and user profile integration; refactored existing AI administration/chat to use shared profile resources.
  • Implemented server-side user credential storage (secret storage + session fallback) and applied effective profiles during AI chat execution; added regression tests.
File summaries
File Description
webapp/yarn.lock Updates workspace dependency graph to include new AI profile packages and TS CSS modules plugin.
webapp/packages/plugin-set-common/tsconfig.json Adds TS project references for new AI profile packages.
webapp/packages/plugin-set-common/src/index.ts Registers new AI profile modules in the common plugin set.
webapp/packages/plugin-set-common/package.json Declares dependencies on new AI profile packages.
webapp/packages/plugin-ai/src/module.ts Registers new AISettingsResource in plugin-ai DI.
webapp/packages/plugin-ai/src/index.ts Exports AISettingsResource from plugin-ai public API.
webapp/packages/plugin-ai/src/AISettingsResource.ts Adds shared resource for loading/saving AI settings via GraphQL.
webapp/packages/plugin-ai/package.json Trims unused React/MobX deps from plugin-ai package.
webapp/packages/plugin-ai-user-profile/tsconfig.json New TS project config for user-profile AI credentials UI package.
webapp/packages/plugin-ai-user-profile/src/module.ts Registers user profile AI tab + credentials panel services and localization.
webapp/packages/plugin-ai-user-profile/src/LocaleService.ts Adds locale provider for the new user-profile AI package.
webapp/packages/plugin-ai-user-profile/src/locales/zh.ts Adds zh translations for user AI profiles UI.
webapp/packages/plugin-ai-user-profile/src/locales/ru.ts Adds ru translations for user AI profiles UI.
webapp/packages/plugin-ai-user-profile/src/locales/fr.ts Adds fr translations for user AI profiles UI.
webapp/packages/plugin-ai-user-profile/src/locales/en.ts Adds en translations for user AI profiles UI.
webapp/packages/plugin-ai-user-profile/src/index.ts New entrypoint for user-profile AI package.
webapp/packages/plugin-ai-user-profile/src/components/AIUserProfilesTable.tsx Displays profiles with credential status and opens credentials editor.
webapp/packages/plugin-ai-user-profile/src/components/AIProfilesPanel.tsx User profile panel to list/refresh available AI profiles.
webapp/packages/plugin-ai-user-profile/src/components/AIProfileCredentialsPanel.tsx Options panel form wrapper for editing per-profile user credentials.
webapp/packages/plugin-ai-user-profile/src/components/AIProfileCredentialsFields.tsx Credential input + reset action for a selected profile.
webapp/packages/plugin-ai-user-profile/src/AIUserProfileBootstrap.ts Adds “AI Profiles” tab to user profile when available.
webapp/packages/plugin-ai-user-profile/src/AIProfileCredentialsPanelService.ts Manages credentials panel open/close and unsaved-changes flow.
webapp/packages/plugin-ai-user-profile/src/AIProfileCredentialsForm/IAIProfileCredentialsFormState.ts Defines form state shape for profile credentials editing.
webapp/packages/plugin-ai-user-profile/src/AIProfileCredentialsForm/IAIProfileCredentialsFormProps.ts Defines form props type for credentials form.
webapp/packages/plugin-ai-user-profile/src/AIProfileCredentialsForm/getAIProfileCredentialsFormPart.ts Wires credentials form part via data context/DI.
webapp/packages/plugin-ai-user-profile/src/AIProfileCredentialsForm/AIProfileCredentialsFormTabBootstrap.ts Registers credentials tab/part in the credentials form.
webapp/packages/plugin-ai-user-profile/src/AIProfileCredentialsForm/AIProfileCredentialsFormPart.ts Implements load/save logic for user token credentials.
webapp/packages/plugin-ai-user-profile/src/AI_PROFILES_TAB_ID.ts Defines tab id constant for user “AI Profiles” tab.
webapp/packages/plugin-ai-user-profile/package.json Adds new workspace package for user profile integration.
webapp/packages/plugin-ai-user-profile/.gitignore Adds package-level ignores for build artifacts.
webapp/packages/plugin-ai-profiles/tsconfig.json New TS project config for shared AI profiles package.
webapp/packages/plugin-ai-profiles/src/module.ts Registers shared AI profiles resource, credentials dialog service, localization.
webapp/packages/plugin-ai-profiles/src/LocaleService.ts Adds locale provider for shared AI profiles UI strings.
webapp/packages/plugin-ai-profiles/src/locales/zh.ts Adds zh translations for shared AI profile UI/credentials dialog.
webapp/packages/plugin-ai-profiles/src/locales/ru.ts Adds ru translations for shared AI profile UI/credentials dialog.
webapp/packages/plugin-ai-profiles/src/locales/fr.ts Adds fr translations for shared AI profile UI/credentials dialog.
webapp/packages/plugin-ai-profiles/src/locales/en.ts Adds en translations for shared AI profile UI/credentials dialog.
webapp/packages/plugin-ai-profiles/src/locales/de.ts Adds de translations for shared AI profile UI/credentials dialog.
webapp/packages/plugin-ai-profiles/src/index.ts Exposes shared AI profiles APIs (resource/table/credentials dialog).
webapp/packages/plugin-ai-profiles/src/AIProfilesTableLazy.ts Adds lazy import wrapper for shared profiles table.
webapp/packages/plugin-ai-profiles/src/AIProfilesTable.tsx Shared profiles table component (scope + selection + click behaviors).
webapp/packages/plugin-ai-profiles/src/AIProfilesTable.module.css Styling for shared profiles table.
webapp/packages/plugin-ai-profiles/src/AIProfilesResource.ts Frontend resource for profiles list + saving/resetting user credentials.
webapp/packages/plugin-ai-profiles/src/AIProfileCredentials/IAIProfileCredentialsDialogPayload.ts Dialog payload type for credentials dialog.
webapp/packages/plugin-ai-profiles/src/AIProfileCredentials/AIProfileCredentialsUtils.ts Helpers to detect whether user credentials are supported/required.
webapp/packages/plugin-ai-profiles/src/AIProfileCredentials/AIProfileCredentialsService.ts Service to open credentials dialog and determine support/requiredness.
webapp/packages/plugin-ai-profiles/src/AIProfileCredentials/AIProfileCredentialsDialogLazy.ts Lazy wrapper for credentials dialog component.
webapp/packages/plugin-ai-profiles/src/AIProfileCredentials/AIProfileCredentialsDialog.tsx Credentials dialog UI and save/reset flows.
webapp/packages/plugin-ai-profiles/src/AI_PROFILES_TABLE_ROW_HEIGHT.ts Shared constant for table row height.
webapp/packages/plugin-ai-profiles/package.json Adds new workspace package for shared AI profiles primitives.
webapp/packages/plugin-ai-profiles/.gitignore Adds package-level ignore for build output.
webapp/packages/plugin-ai-profiles-administration/tsconfig.json New TS project config for AI profiles administration UI package.
webapp/packages/plugin-ai-profiles-administration/src/module.ts Registers admin profiles UI bootstraps/resources/services.
webapp/packages/plugin-ai-profiles-administration/src/LocaleService.ts Adds locale provider for admin profiles UI package.
webapp/packages/plugin-ai-profiles-administration/src/locales/ru.ts Adds ru translations for admin profiles UI.
webapp/packages/plugin-ai-profiles-administration/src/locales/fr.ts Adds fr translations for admin profiles UI.
webapp/packages/plugin-ai-profiles-administration/src/locales/en.ts Adds en translations for admin profiles UI.
webapp/packages/plugin-ai-profiles-administration/src/locales/de.ts Adds de translations for admin profiles UI.
webapp/packages/plugin-ai-profiles-administration/src/index.ts New entrypoint exporting admin bootstrap.
webapp/packages/plugin-ai-profiles-administration/src/AIProfilesTabPanel.tsx Admin tab panel wrapper for profiles UI.
webapp/packages/plugin-ai-profiles-administration/src/AIProfilesAdministrationBootstrap.ts Adds “Profiles” sub-tab into AI administration navigation.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/utils/prepareProperties.ts Builds minimal changed property map and filters password placeholders.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/utils/getObjectPropertiesValues.ts Converts property info arrays into object value maps.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/useAIProfilesTable.ts Table actions (delete confirmation includes credential deletion warning).
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfilesToolsPanel.module.css Styles for admin profiles tools panel.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfilesPanel.tsx Refactors admin profiles panel to use shared profiles/settings resources.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfilesAdministrationTable.tsx Uses shared AIProfilesTable for administration listing.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/Options/getAIProfileFormPart.ts Injects shared AIProfilesResource + credentials service into form part.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/Options/AIProfileSchema.ts Extends profile schema with global flag.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/Options/AIProfilePropertiesForm.tsx Extracted reusable properties form wrapper.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/Options/AIProfileOptions.tsx Adds scope selector and adjusts model/property handling for user credentials profiles.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/Options/AIProfileFormPart.ts Handles global/user scope state, validation, and config mapping for profile save.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/IAIProfileFormState.ts Defines form state for admin profile editor.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/IAIProfileFormProps.ts Defines props typing for admin profile form.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/AIProfileFormTabBootstrap.ts Registers “options” tab for admin profile form panel.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/AIProfileFormService.ts Adds admin profile form service using options panel + unsaved changes confirmation.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/AIProfileFormPanel.tsx Adjusts save UX (close panel after successful create).
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/AIProfileForm.tsx Adds lazy-loaded admin profile form container.
webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIEnginePropertiesResource.ts Adds loadModels API to engine properties resource.
webapp/packages/plugin-ai-profiles-administration/package.json Adds new workspace package for AI profiles administration UI.
webapp/packages/plugin-ai-profiles-administration/.gitignore Adds package-level ignore for build output.
webapp/packages/plugin-ai-chat/tsconfig.json Adds reference to shared AI profiles package.
webapp/packages/plugin-ai-chat/src/module.ts Removes now-redundant AIChatProfilesResource registration.
webapp/packages/plugin-ai-chat/src/locales/zh.ts Adds translations for “edit credentials” in chat profile menu.
webapp/packages/plugin-ai-chat/src/locales/ru.ts Adds translations for “edit credentials” in chat profile menu.
webapp/packages/plugin-ai-chat/src/locales/it.ts Adds translations for “edit credentials” in chat profile menu.
webapp/packages/plugin-ai-chat/src/locales/en.ts Adds translations for “edit credentials” in chat profile menu.
webapp/packages/plugin-ai-chat/src/AIChatProfilesResource.ts Removes deprecated chat-specific profiles resource.
webapp/packages/plugin-ai-chat/src/AIChat/AIChatMessage/AIChatMessageService.ts Prompts for credentials when required before sending message.
webapp/packages/plugin-ai-chat/src/AIChat/AIChatConversation/AIChatConversationsResource.ts Outdates conversations when referenced profiles are deleted.
webapp/packages/plugin-ai-chat/src/AIChat/AIChatConversation/AIChatConversationScope/AIChatConversationScope.tsx Uses shared AI profiles resource to populate profile list.
webapp/packages/plugin-ai-chat/src/AIChat/AIChatConversation/AIChatConversationScope/AIChatConversationProfile.tsx Adds credentials prompt/edit UI per profile in chat menu.
webapp/packages/plugin-ai-chat/package.json Adds dependency on shared AI profiles package.
webapp/packages/plugin-ai-administration/tsconfig.json Updates references to use shared AI profiles package.
webapp/packages/plugin-ai-administration/src/module.ts Removes AI profiles/settings resources from AI admin module (now shared packages).
webapp/packages/plugin-ai-administration/src/locales/ru.ts Removes profile-management translations now owned by profiles admin package.
webapp/packages/plugin-ai-administration/src/locales/fr.ts Removes profile-management translations now owned by profiles admin package.
webapp/packages/plugin-ai-administration/src/locales/en.ts Removes profile-management translations now owned by profiles admin package.
webapp/packages/plugin-ai-administration/src/locales/de.ts Removes profile-management translations now owned by profiles admin package.
webapp/packages/plugin-ai-administration/src/index.ts Exports AISettingsService from plugin-ai-administration.
webapp/packages/plugin-ai-administration/src/AISettingsService.ts Minor typing improvement (dispose(): void).
webapp/packages/plugin-ai-administration/src/AISettingsResource.ts Removes old admin-only settings resource (moved to plugin-ai).
webapp/packages/plugin-ai-administration/src/AISettingsForm/getAdministrationAISettingsFormInfoPart.ts Switches to shared AI settings/profiles resources.
webapp/packages/plugin-ai-administration/src/AISettingsForm/AdministrationAISettingsInfoPart.ts Switches to shared AI settings/profiles resources.
webapp/packages/plugin-ai-administration/src/AIProfiles/AIProfilesTable.tsx Removes old admin profiles table implementation (replaced by shared one).
webapp/packages/plugin-ai-administration/src/AIProfiles/AIProfilesResource.ts Removes old admin profiles resource (replaced by shared one).
webapp/packages/plugin-ai-administration/src/AIAdministrationTabsService.ts Removes old profiles tab wiring from base AI administration package.
webapp/packages/plugin-ai-administration/src/AIAdministrationProfilesTabPanel.tsx Removes old profiles tab panel.
webapp/packages/plugin-ai-administration/src/AIAdministrationPage.tsx Switches to shared AI profiles resource.
webapp/packages/plugin-ai-administration/package.json Replaces deps with shared AI profiles package; adds CSS modules TS plugin.
webapp/packages/core-sdk/src/queries/ai/updateAiProfile.gql Adds global to updated admin profile result selection.
webapp/packages/core-sdk/src/queries/ai/saveAiProfileCredentials.gql Adds credentials mutation operation.
webapp/packages/core-sdk/src/queries/ai/getAiProfiles.gql Adds global and credentialsSaved to profile list query.
webapp/packages/core-sdk/src/queries/ai/createAiProfile.gql Adds global to created admin profile result selection.
webapp/packages/core-blocks/src/FormControls/RadioGroup.tsx Improves RadioGroup labeling support (label/labelledBy/aria-label).
webapp/packages/core-blocks/src/FormControls/RadioGroup.module.css Adds label styling for RadioGroup when using label.
webapp/common-react/@dbeaver/react-data-grid/src/DataGridHeaderCellContext.ts Extends DataGrid header context with getHeaderMinWidth.
webapp/common-react/@dbeaver/react-data-grid/src/DataGrid.tsx Threads getHeaderMinWidth into column minWidth.
server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java Adds new AI credentials regression test to CE test suite.
server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/service/ai/WebAIProfileCredentialsTest.java New unit test covering saving/updating/clearing credentials + session fallback.
server/test/io.cloudbeaver.test.platform/META-INF/MANIFEST.MF Adds AI service bundle dependency for new tests.
server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/WebAIUtils.java Applies effective profile (with user credentials) and validates configuration per conversation.
server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/WebAIProfileCredentials.java Implements per-user AI profile credential storage and effective profile resolution.
server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/model/WebAIConfigurationProfile.java Exposes global and credentialsSaved for GraphQL profile info.
server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/model/inputs/WebAIProfileCredentialsInput.java Adds GraphQL input model for profile credentials properties.
server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/gql/WebServiceBindingAI.java Binds GraphQL mutation aiSaveProfileCredentials.
server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/gql/WebServiceAI.java Implements credentials mutation + applies effective profile in AI flows; cleans up credentials on profile changes/deletes.
server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/gql/DBWServiceAI.java Adds service interface method for saving profile credentials (secure parameter).
server/bundles/io.cloudbeaver.service.ai/schema/service.ai.graphqls Extends schema with global/credentialsSaved and credentials mutation input/field.
server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/session/WebUserContext.java Fixes synchronization/initialization guard for secret controller.
server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/VoidSecretController.java Updates copyright year and ensures secret controller reports 0 features.
Review details

Suppressed comments (1)

webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/Options/AIProfileFormPart.ts:91

  • When user credentials are not supported, changeEngine forces this.state.global = true but doesn’t update this.state.properties.global accordingly. This can leave state inconsistent (e.g., radio shows “global” while properties still contain global: false) and may affect dirty-state detection and subsequent saves/model loads.
  • Files reviewed: 121/131 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

const { data: currentScope } = useResource(AIChatConversationScope, AIChatConversationScopeResource, conversation.id);
const { data: profiles } = useResource(AIChatConversationScope, AIChatProfilesResource, undefined);
const { data: profileList } = useResource(AIChatConversationScope, AIProfilesResource, CachedMapAllKey);
const profiles = profileList.filter(isNotNullDefined);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to reassign, just use aiProfilesResource.data because we only use it once here

instead of const { data: profileList } = useResource
->
const profiles = aiProfilesResource.data.filter...


async processSendMessageAction(conversationId: string, action: () => Promise<IAiSendChatMessageInfo>) {
const conversation = await this.aiChatConversationsResource.load(conversationId);
const profileId = conversation.profile;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its better to subscribe to onMessageSend executor. Check profile credentials and interupt if needed

So we dont mix logic here
The best way to do it from some profile service

const propertiesLoader = useResource(AIProfileOptions, AIEnginePropertiesResource, part.state.engineId || null);
const propertiesInfo = propertiesLoader.data ?? [];
const usesUserCredentials = !part.state.global;
const configurableProperties = propertiesInfo

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's slightly difficult to read through. Maybe it would be better to add a few additional variables or simplify the checks to make it easier to read.

const configurableProperties = propertiesInfo
  .filter(({ id }) => {
    if (id === 'global') {return false};
    if (id === 'token') {return !usesUserCredentials;}

    return true;
  })
  .map(property =>
    property.id === 'token'
      ? { ...property, required: true }
      : property
  );


const names = deletionList.map(id => `"${this.aiProfilesResource.get(id)?.name ?? id}"`).join(', ');
const message = `${translate('plugin_ai_administration_profile_delete_confirmation')}${names}.\n\n${translate('ui_are_you_sure')}`;
const deletesUserCredentials = deletionList.some(id => this.aiProfilesResource.get(id)?.global === false);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> shouldDeleteUserCredentials ?


import { AIProfilesPanel } from './AIProfiles/AIProfilesPanel.js';

export const AIProfilesTabPanel = observer(function AIProfilesTabPanel() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we dont this this component

const notificationService = useService(NotificationService);
const aiProfilesResource = useService(AIProfilesResource);
const [tokenRef] = useFocus<HTMLInputElement>({ autofocus: true });
const state = useObservableRef<CredentialsDialogState>(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its okay to use two use state instead of useObservableRef here as we have pretty simple state here

{ token: observable.ref, processing: observable.ref },
false,
);
const credentialsSaved = aiProfilesResource.get(payload.profileId)?.credentialsSaved ?? false;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably we should use aiProfilesResource as it is and access profile via .data to trigger suspense

) {}

async open(profileId: string): Promise<DialogResult<void>> {
const [profile] = await Promise.all([this.aiProfilesResource.load(profileId), this.aiEnginesResource.load()]);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this perfomance optimization?

For the better readbility we can write it like this

const profile = await this.aiProfilesResource.load(profileId);

if (!profile) {
  this.notificationService.logError({ title: 'plugin_ai_credentials_profile_not_found' });
  return { status: DialogueStateResult.Rejected };
}

const engine = await this.aiEnginesResource.load(profile.engineId);


import type { AIProfile } from '../AIProfilesResource.js';

export function supportsUserCredentials(properties: ReadonlyArray<{ id?: string; features: readonly string[] }>): boolean {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we can inline these two functions

* you may not use this file except in compliance with the License.
*/

export interface IAIProfileCredentialsDialogPayload {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need separate file for this interface?

* you may not use this file except in compliance with the License.
*/

.table {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this duplicates styles of the AdministrationTable.module.css, probably should move them to public part

devnaumov
devnaumov previously approved these changes Sep 10, 2026
devnaumov
devnaumov previously approved these changes Sep 11, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

One or more issues must be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (5)

server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/WebAIProfileCredentials.java:92

  • The new runtime boundary that clones a configured profile and injects the saved credentials is not covered by WebAIProfileCredentialsTest; the current tests only exercise save/status, validation, clearing, and the fallback store. Add a regression test that calls getEffectiveProfile, verifies the token is injected into the returned profile, and verifies the configured source profile remains unchanged.
    public static AIConfigurationProfile getEffectiveProfile(

server/bundles/io.cloudbeaver.service.ai/src/io/cloudbeaver/service/ai/WebAIProfileCredentials.java:223

  • The session fallback is keyed by profile ID, but this additional identity check requires the exact same AIConfigurationProfile instance. Saving uses getInstance().getSettings(), while runtime lookup uses getStaticSettings(), and a reload can create a new object; then areCredentialsSaved and getEffectiveProfile ignore the session token and report credentials as missing. Match the stored profile by ID (or rely on the attribute key) instead.
            if (sessionCredentials != null && sessionCredentials.profile() == profile) {

webapp/packages/plugin-ai-chat/src/AIChat/AIChatConversation/AIChatConversationScope/AIChatConversationProfile.tsx:103

  • The edit button is inside the MenuItemRadio, so its click bubbles to the parent onClick and invokes selectProfile as well as editCredentials. Editing a non-current unconfigured profile can therefore switch the conversation and open a second credentials dialog. Stop propagation from this button (or move it outside the radio item) before opening the editor.
    webapp/packages/plugin-ai-profiles-administration/src/AIProfiles/AIProfileForm/Options/AIProfileFormPart.ts:152
  • AIProfilesResource now loads getAiProfiles, whose AIConfigurationProfileInfo has no configuration; only the admin create/update result contains that field. Existing profiles therefore initialize with empty engine properties here, so opening and saving one can blank its current settings. loadProperties(...) already fetched the profile-specific property values, so use those values (or an admin-specific query) to initialize this state.
    webapp/packages/plugin-ai-user-profile/src/components/AIProfileCredentialsFields.tsx:52
  • Resetting the resource does not reset the form part's local token state. If a user has typed a token and then clicks Reset, the credential is removed server-side but the Save button remains enabled with the old token, so clicking Save immediately re-creates the credential that was just reset. Clear/reset the form part state after the reset succeeds (as the dialog variant already does).
  • Files reviewed: 122/132 changed files
  • Comments generated: 3
  • Review effort level: Lite

}

const conversation = await this.aiChatConversationsResource.load(data.conversationId);
const profile = conversation.profile ? await this.aiProfilesResource.load(conversation.profile) : undefined;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants