Skip to content

Commit

Permalink
Merge pull request #3724 from continuedev/nate/platform
Browse files Browse the repository at this point in the history
Nate/platform
  • Loading branch information
sestinj authored Jan 16, 2025
2 parents ec93b3f + 6254d03 commit 87accb6
Show file tree
Hide file tree
Showing 91 changed files with 2,318 additions and 396 deletions.
28 changes: 16 additions & 12 deletions .github/workflows/pr_checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

install-gui:
needs: [ install-root, install-core ]
needs: [install-root, install-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -157,7 +157,7 @@ jobs:
npx tsc --noEmit
binary-checks:
needs: [ install-root, install-core ]
needs: [install-root, install-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -193,7 +193,7 @@ jobs:
npx tsc --noEmit
install-vscode:
needs: [ install-root, install-core ]
needs: [install-root, install-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -274,10 +274,15 @@ jobs:
run: |
cd core
npm test
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}

vscode-get-test-file-matrix:
runs-on: ubuntu-latest
needs: [ install-root, install-vscode ]
needs: [install-root, install-vscode]
outputs:
test_file_matrix: ${{ steps.vscode-get-test-file-matrix.outputs.test_file_matrix }}
steps:
Expand Down Expand Up @@ -306,7 +311,7 @@ jobs:
vscode-package-extension:
runs-on: ubuntu-latest
needs: [ install-vscode, install-core ]
needs: [install-vscode, install-core]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down Expand Up @@ -338,7 +343,7 @@ jobs:

vscode-download-e2e-dependencies:
runs-on: ubuntu-latest
needs: [ install-vscode, install-core ]
needs: [install-vscode, install-core]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down Expand Up @@ -370,7 +375,7 @@ jobs:
path: extensions/vscode/e2e/storage

vscode-e2e-tests:
name: ${{ matrix.test_file }}"
name: ${{ matrix.test_file }} (${{ matrix.command }})
needs:
[
vscode-download-e2e-dependencies,
Expand All @@ -384,6 +389,7 @@ jobs:
fail-fast: false
matrix:
test_file: ${{ fromJson(needs.vscode-get-test-file-matrix.outputs.test_file_matrix) }}
command: ["e2e:ci:run", "e2e:ci:run-yaml"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down Expand Up @@ -432,7 +438,7 @@ jobs:
- name: Run e2e tests
run: |
cd extensions/vscode
TEST_FILE="${{ matrix.test_file }}" npm run e2e:ci:run
TEST_FILE="${{ matrix.test_file }}" npm run ${{ matrix.command }}
env:
DISPLAY: :99
Expand All @@ -445,7 +451,7 @@ jobs:
path: extensions/vscode/e2e/storage/screenshots

gui-tests:
needs: [ install-gui, install-core ]
needs: [install-gui, install-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -476,7 +482,7 @@ jobs:
npm test
jetbrains-tests:
needs: [ install-root, core-checks ]
needs: [install-root, core-checks]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -573,5 +579,3 @@ jobs:
name: jb-failure-report
path: |
${{ github.workspace }}/extensions/intellij/build/reports
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
"outFiles": ["${workspaceFolder}/extensions/vscode/out/extension.js"],
"preLaunchTask": "vscode-extension:build",
"env": {
// "CONTROL_PLANE_ENV": "local",
"CONTINUE_GLOBAL_DIR": "${workspaceFolder}/extensions/.continue-debug"
// "staging" for the preview deployment "CONTINUE_GLOBAL_DIR": "${workspaceFolder}/extensions/.continue-debug"
// "local" for entirely local development of control plane/proxy
// "CONTROL_PLANE_ENV": "staging"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion binary/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/config/ConfigHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe.skip("Test the ConfigHandler and E2E config loading", () => {
expect(profiles[0].id).toBe("local");

const currentProfile = testConfigHandler.currentProfile;
expect(currentProfile.profileId).toBe("local");
expect(currentProfile.profileDescription.id).toBe("local");
});

test("should load the default config successfully", async () => {
Expand Down
99 changes: 80 additions & 19 deletions core/config/ConfigHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@ import Ollama from "../llm/llms/Ollama.js";
import { GlobalContext } from "../util/GlobalContext.js";
import { getConfigJsonPath } from "../util/paths.js";

import { ConfigResult } from "./load.js";
import { ConfigResult } from "@continuedev/config-yaml";
import { pathToFileURL } from "url";
import { controlPlaneEnv } from "../control-plane/env.js";
import { usePlatform } from "../control-plane/flags.js";
import {
LOCAL_ONBOARDING_CHAT_MODEL,
ONBOARDING_LOCAL_MODEL_TITLE,
} from "./onboarding.js";
import ControlPlaneProfileLoader from "./profile/ControlPlaneProfileLoader.js";
import LocalProfileLoader from "./profile/LocalProfileLoader.js";
import PlatformProfileLoader from "./profile/PlatformProfileLoader.js";
import {
ProfileDescription,
ProfileLifecycleManager,
} from "./ProfileLifecycleManager.js";
import { pathToFileURL } from "url";

export type { ProfileDescription };

Expand Down Expand Up @@ -57,7 +60,7 @@ export class ConfigHandler {
writeLog,
);
this.profiles = [new ProfileLifecycleManager(localProfileLoader)];
this.selectedProfileId = localProfileLoader.profileId;
this.selectedProfileId = localProfileLoader.description.id;

// Always load local profile immediately in case control plane doesn't load
try {
Expand All @@ -77,39 +80,40 @@ export class ConfigHandler {

get currentProfile() {
return (
this.profiles.find((p) => p.profileId === this.selectedProfileId) ??
this.fallbackProfile
this.profiles.find(
(p) => p.profileDescription.id === this.selectedProfileId,
) ?? this.fallbackProfile
);
}

get inactiveProfiles() {
return this.profiles.filter((p) => p.profileId !== this.selectedProfileId);
return this.profiles.filter(
(p) => p.profileDescription.id !== this.selectedProfileId,
);
}

async openConfigProfile(profileId?: string) {
let openProfileId = profileId || this.selectedProfileId;
if (openProfileId === "local") {
await this.ide.openFile(pathToFileURL(getConfigJsonPath()).toString());
} else {
await this.ide.openUrl(
"https://app.continue.dev/",
// `https://app.continue.dev/workspaces/${openProfileId}/chat`,
);
await this.ide.openUrl(`${controlPlaneEnv.APP_URL}${openProfileId}`);
}
}

private async fetchControlPlaneProfiles() {
private async loadPlatformProfiles() {
// Get the profiles and create their lifecycle managers
this.controlPlaneClient
.listWorkspaces()
.then(async (workspaces) => {
.listAssistants()
.then(async (assistants) => {
this.profiles = this.profiles.filter(
(profile) => profile.profileId === "local",
(profile) => profile.profileDescription.id === "local",
);
workspaces.forEach((workspace) => {
const profileLoader = new ControlPlaneProfileLoader(
workspace.id,
workspace.name,
assistants.forEach((assistant) => {
const profileLoader = new PlatformProfileLoader(
assistant.configResult,
assistant.ownerSlug,
assistant.packageSlug,
this.controlPlaneClient,
this.ide,
this.ideSettingsPromise,
Expand Down Expand Up @@ -141,10 +145,67 @@ export class ConfigHandler {
}
})
.catch((e) => {
console.error(e);
console.error("Failed to list assistants: ", e);
});
}

private platformProfilesRefreshInterval: NodeJS.Timeout | undefined;

private async fetchControlPlaneProfiles() {
if (usePlatform()) {
clearInterval(this.platformProfilesRefreshInterval);
await this.loadPlatformProfiles();
this.platformProfilesRefreshInterval = setInterval(
this.loadPlatformProfiles.bind(this),
PlatformProfileLoader.RELOAD_INTERVAL,
);
} else {
this.controlPlaneClient
.listWorkspaces()
.then(async (workspaces) => {
this.profiles = this.profiles.filter(
(profile) => profile.profileDescription.id === "local",
);
workspaces.forEach((workspace) => {
const profileLoader = new ControlPlaneProfileLoader(
workspace.id,
workspace.name,
this.controlPlaneClient,
this.ide,
this.ideSettingsPromise,
this.writeLog,
this.reloadConfig.bind(this),
);
this.profiles.push(new ProfileLifecycleManager(profileLoader));
});

this.notifyProfileListeners(
this.profiles.map((profile) => profile.profileDescription),
);

// Check the last selected workspace, and reload if it isn't local
const workspaceId = await this.getWorkspaceId();
const lastSelectedWorkspaceIds =
this.globalContext.get("lastSelectedProfileForWorkspace") ?? {};
const selectedWorkspaceId = lastSelectedWorkspaceIds[workspaceId];
if (selectedWorkspaceId) {
this.selectedProfileId = selectedWorkspaceId;
await this.loadConfig();
} else {
// Otherwise we stick with local profile, and record choice
lastSelectedWorkspaceIds[workspaceId] = this.selectedProfileId;
this.globalContext.update(
"lastSelectedProfileForWorkspace",
lastSelectedWorkspaceIds,
);
}
})
.catch((e) => {
console.error(e);
});
}
}

async setSelectedProfile(profileId: string) {
this.selectedProfileId = profileId;
const result = await this.loadConfig();
Expand Down
27 changes: 7 additions & 20 deletions core/config/ProfileLifecycleManager.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { ConfigResult, ConfigValidationError } from "@continuedev/config-yaml";
import {
BrowserSerializedContinueConfig,
ContinueConfig,
IContextProvider,
} from "../index.js";

import { ConfigResult, finalToBrowserConfig } from "./load.js";
import { finalToBrowserConfig } from "./load.js";
import { IProfileLoader } from "./profile/IProfileLoader.js";

export interface ProfileDescription {
title: string;
id: string;
errors: ConfigValidationError[] | undefined;
}

export class ProfileLifecycleManager {
Expand All @@ -19,19 +21,8 @@ export class ProfileLifecycleManager {

constructor(private readonly profileLoader: IProfileLoader) {}

get profileId() {
return this.profileLoader.profileId;
}

get profileTitle() {
return this.profileLoader.profileTitle;
}

get profileDescription(): ProfileDescription {
return {
title: this.profileTitle,
id: this.profileId,
};
return this.profileLoader.description;
}

clearConfig() {
Expand Down Expand Up @@ -71,14 +62,10 @@ export class ProfileLifecycleManager {
result.config.contextProviders = (
result.config.contextProviders ?? []
).concat(additionalContextProviders);

this.savedConfigResult = result;
resolve(result);
} else if (result.errors) {
reject(
`Error in config.json: ${result.errors.map((item) => item.message).join(" | ")}`,
);
}

this.savedConfigResult = result;
resolve(result);
});

// Wait for the config promise to resolve
Expand Down
13 changes: 5 additions & 8 deletions core/config/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ import {
getEsbuildBinaryPath,
} from "../util/paths";

import { ConfigResult, ConfigValidationError } from "@continuedev/config-yaml";
import { usePlatform } from "../control-plane/flags";
import {
defaultContextProvidersJetBrains,
defaultContextProvidersVsCode,
Expand All @@ -70,13 +72,7 @@ import {
} from "./default";
import { getSystemPromptDotFile } from "./getSystemPromptDotFile";
// import { isSupportedLanceDbCpuTarget } from "./util";
import { ConfigValidationError, validateConfig } from "./validation.js";

export interface ConfigResult<T> {
config: T | undefined;
errors: ConfigValidationError[] | undefined;
configLoadInterrupted: boolean;
}
import { validateConfig } from "./validation.js";

function resolveSerializedConfig(filepath: string): SerializedContinueConfig {
let content = fs.readFileSync(filepath, "utf8");
Expand Down Expand Up @@ -229,7 +225,7 @@ function isModelDescription(
return (llm as ModelDescription).title !== undefined;
}

function isContextProviderWithParams(
export function isContextProviderWithParams(
contextProvider: CustomContextProvider | ContextProviderWithParams,
): contextProvider is ContextProviderWithParams {
return (contextProvider as ContextProviderWithParams).name !== undefined;
Expand Down Expand Up @@ -582,6 +578,7 @@ function finalToBrowserConfig(
experimental: final.experimental,
docs: final.docs,
tools: final.tools,
usePlatform: usePlatform(),
};
}

Expand Down
Loading

0 comments on commit 87accb6

Please sign in to comment.