Skip to content

Commit 2060d65

Browse files
authored
Merge pull request continuedev#3839 from continuedev/dallin/config-ui
Shared Config for non-YAML config options
2 parents 594c864 + 803bf83 commit 2060d65

File tree

49 files changed

+1077
-276
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1077
-276
lines changed

core/autocomplete/filtering/streamTransforms/StreamTransformPipeline.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ export class StreamTransformPipeline {
7676
const timeoutValue = await Telemetry.getValueForFeatureFlag(
7777
PosthogFeatureFlag.AutocompleteTimeout,
7878
);
79-
// helper.options.showWhateverWeHaveAtXMs ?? DEFAULT_AUTOCOMPLETE_OPTS.showWhateverWeHaveAtXMs
8079

8180
lineGenerator = showWhateverWeHaveAtXMs(lineGenerator, timeoutValue!);
8281

core/config/load.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,14 @@ import {
7070
defaultSlashCommandsVscode,
7171
} from "./default";
7272
import { getSystemPromptDotFile } from "./getSystemPromptDotFile";
73-
// import { isSupportedLanceDbCpuTarget } from "./util";
7473
import { useHub } from "../control-plane/env";
7574
import { localPathToUri } from "../util/pathToUri";
75+
import { modifyContinueConfigWithSharedConfig } from "./sharedConfig";
7676
import { validateConfig } from "./validation.js";
7777

78-
function resolveSerializedConfig(filepath: string): SerializedContinueConfig {
78+
export function resolveSerializedConfig(
79+
filepath: string,
80+
): SerializedContinueConfig {
7981
let content = fs.readFileSync(filepath, "utf8");
8082
const config = JSONC.parse(content) as unknown as SerializedContinueConfig;
8183
if (config.env && Array.isArray(config.env)) {
@@ -111,11 +113,10 @@ function loadSerializedConfig(
111113
overrideConfigJson: SerializedContinueConfig | undefined,
112114
ide: IDE,
113115
): ConfigResult<SerializedContinueConfig> {
114-
const configPath = getConfigJsonPath(ideType);
115116
let config: SerializedContinueConfig = overrideConfigJson!;
116117
if (!config) {
117118
try {
118-
config = resolveSerializedConfig(configPath);
119+
config = resolveSerializedConfig(getConfigJsonPath(ideType));
119120
} catch (e) {
120121
throw new Error(`Failed to parse config.json: ${e}`);
121122
}
@@ -135,16 +136,6 @@ function loadSerializedConfig(
135136
config.allowAnonymousTelemetry = true;
136137
}
137138

138-
// Deprecated getChatTitles property should be accounted for
139-
// This is noted in docs
140-
if (
141-
config.ui &&
142-
"getChatTitles" in config.ui &&
143-
config.ui.getChatTitles === false
144-
) {
145-
config.disableSessionTitles = true;
146-
}
147-
148139
if (ideSettings.remoteConfigServerUrl) {
149140
try {
150141
const remoteConfigJson = resolveSerializedConfig(
@@ -583,6 +574,7 @@ async function finalToBrowserConfig(
583574
experimental: final.experimental,
584575
docs: final.docs,
585576
tools: final.tools,
577+
tabAutocompleteOptions: final.tabAutocompleteOptions,
586578
usePlatform: await useHub(ide.getIdeSettings()),
587579
};
588580
}
@@ -767,7 +759,7 @@ async function buildConfigTsandReadConfigJs(ide: IDE, ideType: IdeType) {
767759
return readConfigJs();
768760
}
769761

770-
async function loadFullConfigNode(
762+
async function loadContinueConfigFromJson(
771763
ide: IDE,
772764
workspaceConfigs: ContinueRcJson[],
773765
ideSettings: IdeSettings,
@@ -799,8 +791,16 @@ async function loadFullConfigNode(
799791
serialized.systemMessage = systemPromptDotFile;
800792
}
801793

794+
// Apply shared config
795+
// TODO: override several of these values with user/org shared config
796+
const sharedConfig = new GlobalContext().getSharedConfig();
797+
const withShared = modifyContinueConfigWithSharedConfig(
798+
serialized,
799+
sharedConfig,
800+
);
801+
802802
// Convert serialized to intermediate config
803-
let intermediate = await serializedToIntermediateConfig(serialized, ide);
803+
let intermediate = await serializedToIntermediateConfig(withShared, ide);
804804

805805
// Apply config.ts to modify intermediate config
806806
const configJsContents = await buildConfigTsandReadConfigJs(ide, ideType);
@@ -877,6 +877,6 @@ async function loadFullConfigNode(
877877
export {
878878
finalToBrowserConfig,
879879
intermediateToFinalConfig,
880-
loadFullConfigNode,
880+
loadContinueConfigFromJson,
881881
type BrowserSerializedContinueConfig,
882882
};

core/config/migrateSharedConfig.ts

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import * as fs from "fs";
2+
3+
import * as JSONC from "comment-json";
4+
5+
import { IDE, SerializedContinueConfig } from "..";
6+
import { SharedConfigSchema } from "./sharedConfig";
7+
import { GlobalContext } from "../util/GlobalContext";
8+
import { editConfigJson } from "../util/paths";
9+
import { resolveSerializedConfig } from "./load";
10+
import { deduplicateArray } from "../util";
11+
12+
/*
13+
This migration function eliminates deprecated values from the json file
14+
And writes them to the shared config
15+
*/
16+
export function migrateJsonSharedConfig(filepath: string, ide: IDE): void {
17+
const globalContext = new GlobalContext();
18+
const currentSharedConfig = globalContext.getSharedConfig(); // for merging security concerns
19+
20+
try {
21+
let config = resolveSerializedConfig(filepath);
22+
const shareConfigUpdates: SharedConfigSchema = {};
23+
24+
let effected = false;
25+
26+
const { allowAnonymousTelemetry, ...withoutAllowTelemetry } = config;
27+
if (allowAnonymousTelemetry !== undefined) {
28+
if (currentSharedConfig.allowAnonymousTelemetry !== false) {
29+
// safe merge for security
30+
shareConfigUpdates.allowAnonymousTelemetry = allowAnonymousTelemetry;
31+
}
32+
config = withoutAllowTelemetry;
33+
effected = true;
34+
}
35+
36+
const { disableIndexing, ...withoutDisableIndexing } = config;
37+
if (disableIndexing !== undefined) {
38+
if (currentSharedConfig.disableIndexing !== true) {
39+
// safe merge for security
40+
shareConfigUpdates.disableIndexing = disableIndexing;
41+
}
42+
config = withoutDisableIndexing;
43+
effected = true;
44+
}
45+
46+
const { disableSessionTitles, ...withoutDisableSessionTitles } = config;
47+
if (config.disableSessionTitles !== undefined) {
48+
if (currentSharedConfig.disableSessionTitles !== true) {
49+
// safe merge for security
50+
shareConfigUpdates.disableSessionTitles = config.disableSessionTitles;
51+
}
52+
config = withoutDisableSessionTitles;
53+
effected = true;
54+
}
55+
56+
const { tabAutocompleteOptions, ...withoutAutocompleteOptions } = config;
57+
if (tabAutocompleteOptions !== undefined) {
58+
let migratedAutocomplete = { ...tabAutocompleteOptions };
59+
60+
const { useCache, ...withoutUseCache } = migratedAutocomplete;
61+
if (useCache !== undefined) {
62+
shareConfigUpdates.useAutocompleteCache = useCache;
63+
migratedAutocomplete = withoutUseCache;
64+
effected = true;
65+
}
66+
67+
const { multilineCompletions, ...withoutMultiline } =
68+
migratedAutocomplete;
69+
if (multilineCompletions !== undefined) {
70+
shareConfigUpdates.useAutocompleteMultilineCompletions =
71+
multilineCompletions;
72+
migratedAutocomplete = withoutMultiline;
73+
effected = true;
74+
}
75+
76+
const { disableInFiles, ...withoutDisableInFiles } = migratedAutocomplete;
77+
if (disableInFiles !== undefined) {
78+
if (currentSharedConfig.disableAutocompleteInFiles !== undefined) {
79+
// safe merge for security
80+
shareConfigUpdates.disableAutocompleteInFiles = deduplicateArray(
81+
[
82+
...currentSharedConfig.disableAutocompleteInFiles,
83+
...disableInFiles,
84+
],
85+
(a, b) => a === b,
86+
);
87+
} else {
88+
shareConfigUpdates.disableAutocompleteInFiles = disableInFiles;
89+
}
90+
shareConfigUpdates.disableAutocompleteInFiles = disableInFiles;
91+
migratedAutocomplete = withoutDisableInFiles;
92+
effected = true;
93+
}
94+
95+
if (Object.keys(migratedAutocomplete).length > 0) {
96+
config = {
97+
...withoutAutocompleteOptions,
98+
tabAutocompleteOptions: migratedAutocomplete,
99+
};
100+
} else {
101+
config = withoutAutocompleteOptions;
102+
}
103+
}
104+
105+
const { experimental, ...withoutExperimental } = config;
106+
if (experimental !== undefined) {
107+
let migratedExperimental = { ...experimental };
108+
109+
const { useChromiumForDocsCrawling, ...rest10 } = migratedExperimental;
110+
if (useChromiumForDocsCrawling !== undefined) {
111+
shareConfigUpdates.useChromiumForDocsCrawling =
112+
useChromiumForDocsCrawling;
113+
migratedExperimental = rest10;
114+
effected = true;
115+
}
116+
117+
const { promptPath, ...withoutPromptPath } = migratedExperimental;
118+
if (promptPath !== undefined) {
119+
shareConfigUpdates.promptPath = promptPath;
120+
migratedExperimental = withoutPromptPath;
121+
effected = true;
122+
}
123+
124+
const { readResponseTTS, ...withoutReadTTS } = migratedExperimental;
125+
if (readResponseTTS !== undefined) {
126+
shareConfigUpdates.readResponseTTS = readResponseTTS;
127+
migratedExperimental = withoutReadTTS;
128+
effected = true;
129+
}
130+
131+
if (Object.keys(migratedExperimental).length > 0) {
132+
config = {
133+
...withoutExperimental,
134+
experimental: migratedExperimental,
135+
};
136+
} else {
137+
config = withoutExperimental;
138+
}
139+
}
140+
141+
const { ui, ...withoutUI } = config;
142+
if (ui !== undefined) {
143+
let migratedUI = { ...ui };
144+
145+
const { codeBlockToolbarPosition, ...withoutToolbarPosition } =
146+
migratedUI;
147+
if (codeBlockToolbarPosition !== undefined) {
148+
shareConfigUpdates.codeBlockToolbarPosition = codeBlockToolbarPosition;
149+
migratedUI = withoutToolbarPosition;
150+
effected = true;
151+
}
152+
153+
const { fontSize, ...withoutFontSize } = migratedUI;
154+
if (fontSize !== undefined) {
155+
shareConfigUpdates.fontSize = fontSize;
156+
migratedUI = withoutFontSize;
157+
effected = true;
158+
}
159+
160+
const { codeWrap, ...withoutCodeWrap } = migratedUI;
161+
if (codeWrap !== undefined) {
162+
shareConfigUpdates.codeWrap = codeWrap;
163+
migratedUI = withoutCodeWrap;
164+
effected = true;
165+
}
166+
167+
const { displayRawMarkdown, ...withoutMD } = migratedUI;
168+
if (displayRawMarkdown !== undefined) {
169+
shareConfigUpdates.displayRawMarkdown = displayRawMarkdown;
170+
migratedUI = withoutMD;
171+
effected = true;
172+
}
173+
174+
const { showChatScrollbar, ...withoutShowChatScrollbar } = migratedUI;
175+
if (showChatScrollbar !== undefined) {
176+
shareConfigUpdates.showChatScrollbar = showChatScrollbar;
177+
migratedUI = withoutShowChatScrollbar;
178+
effected = true;
179+
}
180+
181+
// Ancient param to overwrite disableSessionTitles
182+
if ("getChatTitles" in migratedUI) {
183+
const { getChatTitles, ...withoutChatTitles } = migratedUI;
184+
if (getChatTitles === false) {
185+
shareConfigUpdates.disableSessionTitles = true;
186+
migratedUI = withoutChatTitles;
187+
effected = true;
188+
}
189+
}
190+
191+
if (Object.keys(migratedUI).length > 0) {
192+
config = {
193+
...withoutUI,
194+
ui: migratedUI,
195+
};
196+
} else {
197+
config = withoutUI;
198+
}
199+
}
200+
201+
if (effected) {
202+
new GlobalContext().updateSharedConfig(shareConfigUpdates);
203+
editConfigJson(() => config);
204+
void ide.showToast(
205+
"warning",
206+
"Migrated deprecated Continue JSON settings. Edit in the Settings Page",
207+
);
208+
}
209+
} catch (e) {
210+
throw new Error(`Migration: Failed to parse config.json: ${e}`);
211+
}
212+
}

core/config/profile/doLoadConfig.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ import { ControlPlaneClient } from "../../control-plane/client.js";
1717
import { getControlPlaneEnv } from "../../control-plane/env.js";
1818
import { TeamAnalytics } from "../../control-plane/TeamAnalytics.js";
1919
import ContinueProxy from "../../llm/llms/stubs/ContinueProxy";
20-
import { getConfigYamlPath } from "../../util/paths";
20+
import { getConfigJsonPath, getConfigYamlPath } from "../../util/paths";
2121
import { Telemetry } from "../../util/posthog";
2222
import { TTS } from "../../util/tts";
23-
import { loadFullConfigNode } from "../load";
23+
import { loadContinueConfigFromJson } from "../load";
2424
import { loadContinueConfigFromYaml } from "../yaml/loadYaml";
2525
import { PlatformConfigMetadata } from "./PlatformProfileLoader";
26+
import { migrateJsonSharedConfig } from "../migrateSharedConfig";
2627

2728
export default async function doLoadConfig(
2829
ide: IDE,
@@ -40,13 +41,20 @@ export default async function doLoadConfig(
4041
const ideSettings = await ideSettingsPromise;
4142
const workOsAccessToken = await controlPlaneClient.getAccessToken();
4243

44+
// Migrations for old config files
45+
// Removes
46+
const configJsonPath = getConfigJsonPath(ideInfo.ideType);
47+
if (fs.existsSync(configJsonPath)) {
48+
migrateJsonSharedConfig(configJsonPath, ide);
49+
}
50+
4351
const configYamlPath = getConfigYamlPath(ideInfo.ideType);
4452

4553
let newConfig: ContinueConfig | undefined;
4654
let errors: ConfigValidationError[] | undefined;
4755
let configLoadInterrupted = false;
4856

49-
if (fs.existsSync(configYamlPath) || overrideConfigYaml) {
57+
if (overrideConfigYaml || fs.existsSync(configYamlPath)) {
5058
const result = await loadContinueConfigFromYaml(
5159
ide,
5260
workspaceConfigs.map((c) => JSON.stringify(c)),
@@ -63,7 +71,7 @@ export default async function doLoadConfig(
6371
errors = result.errors;
6472
configLoadInterrupted = result.configLoadInterrupted;
6573
} else {
66-
const result = await loadFullConfigNode(
74+
const result = await loadContinueConfigFromJson(
6775
ide,
6876
workspaceConfigs,
6977
ideSettings,

0 commit comments

Comments
 (0)