Skip to content

Commit 5bc3fe9

Browse files
feat: Add gen ai org and project settings to Compass for CompassWeb usage COMPASS-8377 (#6434)
* limit increased and message improved for PROMPT_TOO_LONG * updating prompt_too_long error msg * updating test * initial ticket changes * entrypoint changed * prefProps for atlas org and atlas proj prefs * function name change * fixing base values * changing ui default back * comment nit * moving prop defs so defaults get set as part of userpreferences * updating tests * updating tests
1 parent d3ae895 commit 5bc3fe9

File tree

5 files changed

+157
-6
lines changed

5 files changed

+157
-6
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { createNoopLogger } from '@mongodb-js/compass-logging/provider';
2+
import { Preferences, type PreferencesAccess } from './preferences';
3+
import type { UserPreferences } from './preferences-schema';
4+
import { type AllPreferences } from './preferences-schema';
5+
import { InMemoryStorage } from './preferences-in-memory-storage';
6+
import { getActiveUser } from './utils';
7+
8+
export class CompassWebPreferencesAccess implements PreferencesAccess {
9+
private _preferences: Preferences;
10+
constructor(preferencesOverrides?: Partial<AllPreferences>) {
11+
this._preferences = new Preferences({
12+
logger: createNoopLogger(),
13+
preferencesStorage: new InMemoryStorage(preferencesOverrides),
14+
});
15+
}
16+
17+
savePreferences(_attributes: Partial<UserPreferences>) {
18+
// Only allow saving the optInDataExplorerGenAIFeatures preference.
19+
if (
20+
Object.keys(_attributes).length === 1 &&
21+
'optInDataExplorerGenAIFeatures' in _attributes
22+
) {
23+
return Promise.resolve(this._preferences.savePreferences(_attributes));
24+
}
25+
return Promise.resolve(this._preferences.getPreferences());
26+
}
27+
28+
refreshPreferences() {
29+
return Promise.resolve(this._preferences.getPreferences());
30+
}
31+
32+
getPreferences() {
33+
return this._preferences.getPreferences();
34+
}
35+
36+
ensureDefaultConfigurableUserPreferences() {
37+
return this._preferences.ensureDefaultConfigurableUserPreferences();
38+
}
39+
40+
getConfigurableUserPreferences() {
41+
return Promise.resolve(this._preferences.getConfigurableUserPreferences());
42+
}
43+
44+
getPreferenceStates() {
45+
return Promise.resolve(this._preferences.getPreferenceStates());
46+
}
47+
48+
onPreferenceValueChanged<K extends keyof AllPreferences>(
49+
preferenceName: K,
50+
callback: (value: AllPreferences[K]) => void
51+
) {
52+
return (
53+
this._preferences?.onPreferencesChanged?.(
54+
(preferences: Partial<AllPreferences>) => {
55+
if (Object.keys(preferences).includes(preferenceName)) {
56+
return callback((preferences as AllPreferences)[preferenceName]);
57+
}
58+
}
59+
) ??
60+
(() => {
61+
/* no fallback */
62+
})
63+
);
64+
}
65+
66+
createSandbox() {
67+
return Promise.resolve(
68+
new CompassWebPreferencesAccess(this.getPreferences())
69+
);
70+
}
71+
72+
getPreferencesUser() {
73+
return getActiveUser(this);
74+
}
75+
}

packages/compass-preferences-model/src/preferences-schema.ts

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export type UserConfigurablePreferences = PermanentFeatureFlags &
5656
| 'web-sandbox-atlas-local'
5757
| 'web-sandbox-atlas-dev'
5858
| 'web-sandbox-atlas';
59+
optInDataExplorerGenAIFeatures: boolean;
5960
// Features that are enabled by default in Compass, but are disabled in Data
6061
// Explorer
6162
enableExplainPlan: boolean;
@@ -92,7 +93,9 @@ export type InternalUserPreferences = {
9293

9394
// UserPreferences contains all preferences stored to disk.
9495
export type UserPreferences = UserConfigurablePreferences &
95-
InternalUserPreferences;
96+
InternalUserPreferences &
97+
AtlasOrgPreferences &
98+
AtlasProjectPreferences;
9699

97100
export type CliOnlyPreferences = {
98101
exportConnections?: string;
@@ -210,6 +213,15 @@ export type StoredPreferencesValidator = ReturnType<
210213

211214
export type StoredPreferences = z.output<StoredPreferencesValidator>;
212215

216+
export type AtlasProjectPreferences = {
217+
enableGenAIFeaturesAtlasProject: boolean;
218+
enableGenAISampleDocumentPassingOnAtlasProject: boolean;
219+
};
220+
221+
export type AtlasOrgPreferences = {
222+
enableGenAIFeaturesAtlasOrg: boolean;
223+
};
224+
213225
// Preference definitions
214226
const featureFlagsProps: Required<{
215227
[K in keyof FeatureFlags]: PreferenceDefinition<K>;
@@ -461,7 +473,10 @@ export const storedUserPreferencesProps: Required<{
461473
short: 'Enable AI Features',
462474
long: 'Allow the use of AI features in Compass which make requests to 3rd party services.',
463475
},
464-
deriveValue: deriveNetworkTrafficOptionState('enableGenAIFeatures'),
476+
deriveValue: deriveValueFromOtherPreferencesAsLogicalAnd(
477+
'enableGenAIFeatures',
478+
['enableGenAIFeaturesAtlasOrg', 'networkTraffic']
479+
),
465480
validator: z.boolean().default(true),
466481
type: 'boolean',
467482
},
@@ -679,6 +694,16 @@ export const storedUserPreferencesProps: Required<{
679694
.default('atlas'),
680695
type: 'string',
681696
},
697+
optInDataExplorerGenAIFeatures: {
698+
ui: true,
699+
cli: false,
700+
global: false,
701+
description: {
702+
short: 'User Opt-in for Data Explorer Gen AI Features',
703+
},
704+
validator: z.boolean().default(true),
705+
type: 'boolean',
706+
},
682707

683708
enableAtlasSearchIndexes: {
684709
ui: true,
@@ -861,6 +886,36 @@ export const storedUserPreferencesProps: Required<{
861886
validator: z.boolean().default(false),
862887
type: 'boolean',
863888
},
889+
enableGenAIFeaturesAtlasProject: {
890+
ui: false,
891+
cli: true,
892+
global: true,
893+
description: {
894+
short: 'Enable Gen AI Features on Atlas Project Level',
895+
},
896+
validator: z.boolean().default(true),
897+
type: 'boolean',
898+
},
899+
enableGenAISampleDocumentPassingOnAtlasProject: {
900+
ui: false,
901+
cli: true,
902+
global: true,
903+
description: {
904+
short: 'Enable Gen AI Sample Document Passing on Atlas Project Level',
905+
},
906+
validator: z.boolean().default(true),
907+
type: 'boolean',
908+
},
909+
enableGenAIFeaturesAtlasOrg: {
910+
ui: false,
911+
cli: true,
912+
global: true,
913+
description: {
914+
short: 'Enable Gen AI Features on Atlas Org Level',
915+
},
916+
validator: z.boolean().default(true),
917+
type: 'boolean',
918+
},
864919

865920
...allFeatureFlagsProps,
866921
};
@@ -1027,6 +1082,21 @@ function deriveNetworkTrafficOptionState<K extends keyof AllPreferences>(
10271082
});
10281083
}
10291084

1085+
/** Helper for deriving value/state for preferences from other preferences */
1086+
function deriveValueFromOtherPreferencesAsLogicalAnd<
1087+
K extends keyof AllPreferences
1088+
>(property: K, preferencesToDeriveFrom: K[]): DeriveValueFunction<boolean> {
1089+
return (v, s) => ({
1090+
value: v(property) && preferencesToDeriveFrom.every((p) => v(p)),
1091+
state:
1092+
s(property) ??
1093+
(preferencesToDeriveFrom.every((p) => v(p))
1094+
? preferencesToDeriveFrom.map((p) => s(p)).filter(Boolean)?.[0] ??
1095+
'derived'
1096+
: undefined),
1097+
});
1098+
}
1099+
10301100
/** Helper for defining how to derive value/state for feature-restricting preferences */
10311101
function deriveFeatureRestrictingOptionsState<K extends keyof AllPreferences>(
10321102
property: K

packages/compass-preferences-model/src/preferences.spec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ describe('Preferences class', function () {
132132
expect(states).to.deep.equal({
133133
trackUsageStatistics: 'set-global',
134134
enableMaps: 'set-cli',
135+
enableGenAIFeatures: 'derived',
135136
...expectedReleasedFeatureFlagsStates,
136137
});
137138
});
@@ -163,7 +164,6 @@ describe('Preferences class', function () {
163164
enableDevTools: 'set-global',
164165
networkTraffic: 'set-global',
165166
trackUsageStatistics: 'set-global',
166-
enableGenAIFeatures: 'set-global',
167167
enableMaps: 'set-cli',
168168
enableShell: 'set-cli',
169169
readOnly: 'set-global',
@@ -185,6 +185,7 @@ describe('Preferences class', function () {
185185

186186
expect(states).to.deep.equal({
187187
readOnly: 'set-global',
188+
enableGenAIFeatures: 'derived',
188189
...expectedReleasedFeatureFlagsStates,
189190
});
190191
});
@@ -227,8 +228,8 @@ describe('Preferences class', function () {
227228
},
228229
{
229230
networkTraffic: false,
230-
enableGenAIFeatures: false,
231231
enableMaps: false,
232+
enableGenAIFeatures: false,
232233
enableFeedbackPanel: false,
233234
trackUsageStatistics: false,
234235
autoUpdates: false,
@@ -250,6 +251,7 @@ describe('Preferences class', function () {
250251
},
251252
hardcoded: {
252253
networkTraffic: false,
254+
enableGenAIFeatures: false,
253255
},
254256
});
255257
const result = preferences.getPreferences();
@@ -294,13 +296,15 @@ describe('Preferences class', function () {
294296

295297
expect(mainPreferencesStates).to.deep.equal({
296298
trackUsageStatistics: 'set-global',
299+
enableGenAIFeatures: 'derived',
297300
enableMaps: 'set-cli',
298301
...expectedReleasedFeatureFlagsStates,
299302
});
300303

301304
const sandboxPreferencesStates = sandbox.getPreferenceStates();
302305
expect(sandboxPreferencesStates).to.deep.equal({
303306
enableDevTools: 'derived',
307+
enableGenAIFeatures: 'derived',
304308
trackUsageStatistics: 'set-global',
305309
enableMaps: 'set-cli',
306310
enableShell: 'derived',

packages/compass-preferences-model/src/provider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './react';
22
export { ReadOnlyPreferenceAccess } from './read-only-preferences-access';
3+
export { CompassWebPreferencesAccess } from './compass-web-preferences-access';
34
export {
45
useIsAIFeatureEnabled,
56
isAIFeatureEnabled,

packages/compass-web/src/entrypoint.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import {
3939
} from '@mongodb-js/compass-databases-collections';
4040
import {
4141
PreferencesProvider,
42-
ReadOnlyPreferenceAccess,
42+
CompassWebPreferencesAccess,
4343
} from 'compass-preferences-model/provider';
4444
import type { AllPreferences } from 'compass-preferences-model/provider';
4545
import FieldStorePlugin from '@mongodb-js/compass-field-store';
@@ -262,7 +262,7 @@ const CompassWeb = ({
262262
});
263263

264264
const preferencesAccess = useRef(
265-
new ReadOnlyPreferenceAccess({
265+
new CompassWebPreferencesAccess({
266266
maxTimeMS: 10_000,
267267
enableExplainPlan: true,
268268
enableAggregationBuilderRunPipeline: true,
@@ -279,6 +279,7 @@ const CompassWeb = ({
279279
enableShell: false,
280280
enableCreatingNewConnections: false,
281281
enableGlobalWrites: false,
282+
optInDataExplorerGenAIFeatures: false,
282283
...initialPreferences,
283284
})
284285
);

0 commit comments

Comments
 (0)