Skip to content

Commit 452da6e

Browse files
committed
remove rule injection during onboarding
1 parent 19e1dc0 commit 452da6e

File tree

3 files changed

+16
-216
lines changed

3 files changed

+16
-216
lines changed

extensions/cli/src/config.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,14 @@ import {
77
import {
88
Configuration,
99
DefaultApi,
10-
DefaultApiInterface,
1110
} from "@continuedev/sdk/dist/api/dist/index.js";
1211

1312
import {
1413
AuthConfig,
1514
getAccessToken,
1615
getOrganizationId,
1716
} from "./auth/workos.js";
18-
import { loadConfiguration } from "./configLoader.js";
1917
import { env } from "./env.js";
20-
import { MCPService } from "./services/MCPService.js";
2118

2219
/**
2320
* Creates an LLM API instance from a ModelConfig and auth configuration
@@ -96,23 +93,3 @@ export function getApiClient(
9693
}),
9794
);
9895
}
99-
100-
export async function initialize(
101-
authConfig: AuthConfig,
102-
configPath: string | undefined,
103-
): Promise<{
104-
config: AssistantUnrolled;
105-
llmApi: BaseLlmApi;
106-
model: ModelConfig;
107-
mcpService: MCPService;
108-
apiClient: DefaultApiInterface;
109-
}> {
110-
const apiClient = getApiClient(authConfig?.accessToken);
111-
const result = await loadConfiguration(authConfig, configPath, apiClient);
112-
const config = result.config;
113-
const [llmApi, model] = getLlmApi(config, authConfig);
114-
const mcpService = new MCPService();
115-
await mcpService.initialize(config, false);
116-
117-
return { config, llmApi, model, mcpService, apiClient };
118-
}

extensions/cli/src/onboarding.ts

Lines changed: 15 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
import * as fs from "fs";
22
import * as path from "path";
33

4-
import { AssistantUnrolled, ModelConfig } from "@continuedev/config-yaml";
5-
import { BaseLlmApi } from "@continuedev/openai-adapters";
6-
import { DefaultApiInterface } from "@continuedev/sdk/dist/api/dist/index.js";
74
import chalk from "chalk";
85

9-
import { AuthConfig, isAuthenticated, login } from "./auth/workos.js";
10-
import { initialize } from "./config.js";
6+
import { login } from "./auth/workos.js";
117
import { env } from "./env.js";
12-
import { processRule } from "./hubLoader.js";
13-
import { MCPService } from "./services/MCPService.js";
148
import {
159
getApiKeyValidationError,
1610
isValidAnthropicApiKey,
@@ -20,15 +14,6 @@ import { updateAnthropicModelInYaml } from "./util/yamlConfigUpdater.js";
2014

2115
const CONFIG_PATH = path.join(env.continueHome, "config.yaml");
2216

23-
export interface OnboardingResult {
24-
config: AssistantUnrolled;
25-
llmApi: BaseLlmApi;
26-
model: ModelConfig;
27-
mcpService: MCPService;
28-
apiClient: DefaultApiInterface;
29-
wasOnboarded: boolean;
30-
}
31-
3217
export async function checkHasAcceptableModel(
3318
configPath: string,
3419
): Promise<boolean> {
@@ -61,21 +46,18 @@ export async function createOrUpdateConfig(apiKey: string): Promise<void> {
6146

6247
export async function runOnboardingFlow(
6348
configPath: string | undefined,
64-
authConfig: AuthConfig,
65-
): Promise<OnboardingResult> {
49+
): Promise<boolean> {
6650
// Step 1: Check if --config flag is provided
6751
if (configPath !== undefined) {
68-
const result = await initialize(authConfig, configPath);
69-
return { ...result, wasOnboarded: false };
52+
return false;
7053
}
7154

7255
// Step 2: Check for CONTINUE_USE_BEDROCK environment variable first (before test env check)
7356
if (process.env.CONTINUE_USE_BEDROCK === "1") {
7457
console.log(
7558
chalk.blue("✓ Using AWS Bedrock (CONTINUE_USE_BEDROCK detected)"),
7659
);
77-
const result = await initialize(authConfig, CONFIG_PATH);
78-
return { ...result, wasOnboarded: true };
60+
return true;
7961
}
8062

8163
// Step 3: Check if we're in a test/CI environment - if so, skip interactive prompts
@@ -92,13 +74,11 @@ export async function runOnboardingFlow(
9274
console.log(chalk.blue("✓ Using ANTHROPIC_API_KEY from environment"));
9375
await createOrUpdateConfig(process.env.ANTHROPIC_API_KEY);
9476
console.log(chalk.gray(` Config saved to: ${CONFIG_PATH}`));
95-
const result = await initialize(authConfig, CONFIG_PATH);
96-
return { ...result, wasOnboarded: false };
77+
return false;
9778
}
9879

9980
// Otherwise return a minimal working configuration
100-
const result = await initialize(authConfig, undefined);
101-
return { ...result, wasOnboarded: false };
81+
return false;
10282
}
10383

10484
// Step 4: Present user with two options
@@ -114,13 +94,8 @@ export async function runOnboardingFlow(
11494
);
11595

11696
if (choice === "1" || choice === "") {
117-
const newAuthConfig = await login();
118-
119-
const { ensureOrganization } = await import("./auth/workos.js");
120-
const finalAuthConfig = await ensureOrganization(newAuthConfig);
121-
122-
const result = await initialize(finalAuthConfig, undefined);
123-
return { ...result, wasOnboarded: true };
97+
await login();
98+
return true;
12499
} else if (choice === "2") {
125100
const apiKey = await question(
126101
chalk.white("\nEnter your Anthropic API key: "),
@@ -135,89 +110,12 @@ export async function runOnboardingFlow(
135110
chalk.green(`✓ Config file updated successfully at ${CONFIG_PATH}`),
136111
);
137112

138-
const result = await initialize(authConfig, CONFIG_PATH);
139-
return { ...result, wasOnboarded: true };
113+
return true;
140114
} else {
141115
throw new Error(`Invalid choice. Please select "1" or "2"`);
142116
}
143117
}
144118

145-
export async function runNormalFlow(
146-
authConfig: AuthConfig,
147-
configPath?: string,
148-
rules?: string[],
149-
): Promise<OnboardingResult> {
150-
// Step 1: Check if --config flag is provided
151-
if (configPath !== undefined) {
152-
// Empty string is invalid and should be treated as an error
153-
if (configPath === "") {
154-
throw new Error(
155-
`Failed to load config from "": Config path cannot be empty`,
156-
);
157-
}
158-
159-
try {
160-
const result = await initialize(authConfig, configPath);
161-
// Inject rules into the config if provided
162-
if (rules && rules.length > 0) {
163-
result.config = await injectRulesIntoConfig(result.config, rules);
164-
}
165-
return { ...result, wasOnboarded: false };
166-
} catch (error) {
167-
// If user explicitly provided --config flag, fail loudly instead of falling back
168-
const errorMessage =
169-
error instanceof Error ? error.message : String(error);
170-
throw new Error(
171-
`Failed to load config from "${configPath}": ${errorMessage}`,
172-
);
173-
}
174-
}
175-
176-
// Step 2: If user is logged in, look for first assistant in selected org
177-
if (isAuthenticated()) {
178-
try {
179-
const result = await initialize(authConfig, undefined);
180-
// Inject rules into the config if provided
181-
if (rules && rules.length > 0) {
182-
result.config = await injectRulesIntoConfig(result.config, rules);
183-
}
184-
return { ...result, wasOnboarded: false };
185-
} catch {
186-
// Silently ignore errors when loading default assistant
187-
}
188-
}
189-
190-
// Step 3: Look for local ~/.continue/config.yaml
191-
if (fs.existsSync(CONFIG_PATH)) {
192-
try {
193-
const result = await initialize(authConfig, CONFIG_PATH);
194-
// Inject rules into the config if provided
195-
if (rules && rules.length > 0) {
196-
result.config = await injectRulesIntoConfig(result.config, rules);
197-
}
198-
return { ...result, wasOnboarded: false };
199-
} catch {
200-
console.log(chalk.yellow("⚠ Invalid config file found"));
201-
}
202-
}
203-
204-
// Step 4: Look for ANTHROPIC_API_KEY in environment
205-
if (process.env.ANTHROPIC_API_KEY) {
206-
console.log(chalk.blue("✓ Using ANTHROPIC_API_KEY from environment"));
207-
await createOrUpdateConfig(process.env.ANTHROPIC_API_KEY);
208-
console.log(chalk.gray(` Config saved to: ${CONFIG_PATH}`));
209-
const result = await initialize(authConfig, CONFIG_PATH);
210-
// Inject rules into the config if provided
211-
if (rules && rules.length > 0) {
212-
result.config = await injectRulesIntoConfig(result.config, rules);
213-
}
214-
return { ...result, wasOnboarded: false };
215-
}
216-
217-
// Step 5: Fall back to onboarding flow
218-
return runOnboardingFlow(configPath, authConfig);
219-
}
220-
221119
export async function isFirstTime(): Promise<boolean> {
222120
return !fs.existsSync(path.join(env.continueHome, ".onboarding_complete"));
223121
}
@@ -233,82 +131,13 @@ export async function markOnboardingComplete(): Promise<void> {
233131
fs.writeFileSync(flagPath, new Date().toISOString());
234132
}
235133

236-
/**
237-
* Process rules and inject them into the assistant config
238-
* @param config - The assistant config to modify
239-
* @param rules - Array of rule specifications to process and inject
240-
* @returns The modified config with injected rules
241-
*/
242-
async function injectRulesIntoConfig(
243-
config: AssistantUnrolled,
244-
rules: string[],
245-
): Promise<AssistantUnrolled> {
246-
if (!rules || rules.length === 0) {
247-
return config;
248-
}
249-
250-
const processedRules: string[] = [];
251-
for (const ruleSpec of rules) {
252-
try {
253-
const processedRule = await processRule(ruleSpec);
254-
processedRules.push(processedRule);
255-
} catch (error: any) {
256-
console.warn(
257-
chalk.yellow(
258-
`Warning: Failed to process rule "${ruleSpec}": ${error.message}`,
259-
),
260-
);
261-
}
262-
}
263-
264-
if (processedRules.length === 0) {
265-
return config;
266-
}
267-
268-
// Clone the config to avoid mutating the original
269-
const modifiedConfig = { ...config };
270-
271-
// Add processed rules to the config's rules array
272-
// Each processed rule is a string, which is a valid Rule type
273-
const existingRules = modifiedConfig.rules || [];
274-
modifiedConfig.rules = [...existingRules, ...processedRules];
275-
276-
return modifiedConfig;
277-
}
278-
279-
export async function initializeWithOnboarding(
280-
authConfig: AuthConfig,
281-
configPath: string | undefined,
282-
rules?: string[],
283-
) {
134+
export async function initializeWithOnboarding(configPath: string | undefined) {
284135
const firstTime = await isFirstTime();
285136

286-
if (firstTime) {
287-
const onboardingResult = await runOnboardingFlow(configPath, authConfig);
288-
if (onboardingResult.wasOnboarded) {
289-
await markOnboardingComplete();
290-
}
291-
// Inject rules into the config if provided (for onboarding flow which doesn't handle rules directly)
292-
if (rules && rules.length > 0 && !onboardingResult.wasOnboarded) {
293-
onboardingResult.config = await injectRulesIntoConfig(
294-
onboardingResult.config,
295-
rules,
296-
);
297-
}
298-
} else {
299-
// when running normal flow, initialize (remote) config asynchronously
300-
void (async () => {
301-
const onboardingResult = await runNormalFlow(
302-
authConfig,
303-
configPath,
304-
rules,
305-
);
306-
if (rules && rules.length > 0) {
307-
onboardingResult.config = await injectRulesIntoConfig(
308-
onboardingResult.config,
309-
rules,
310-
);
311-
}
312-
})();
137+
if (!firstTime) return;
138+
139+
const wasOnboarded = await runOnboardingFlow(configPath);
140+
if (wasOnboarded) {
141+
await markOnboardingComplete();
313142
}
314143
}

extensions/cli/src/services/index.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { loadAuthConfig } from "../auth/workos.js";
21
import { initializeWithOnboarding } from "../onboarding.js";
32
import { logger } from "../util/logger.js";
43

@@ -54,12 +53,7 @@ export async function initializeServices(initOptions: ServiceInitOptions = {}) {
5453

5554
// Handle onboarding for TUI mode (headless: false) unless explicitly skipped
5655
if (!initOptions.headless && !initOptions.skipOnboarding) {
57-
const authConfig = loadAuthConfig();
58-
await initializeWithOnboarding(
59-
authConfig,
60-
commandOptions.config,
61-
commandOptions.rule,
62-
);
56+
await initializeWithOnboarding(commandOptions.config);
6357
}
6458

6559
// Handle ANTHROPIC_API_KEY in headless mode when no config path is provided

0 commit comments

Comments
 (0)