From 2795c7325ded81ebb3ebfa063a5847c27313c7ef Mon Sep 17 00:00:00 2001 From: Dan Barr Date: Thu, 30 Jan 2025 18:09:38 -0500 Subject: [PATCH 1/4] Move integrations to their own section --- .gitignore | 1 + docs/about/changelog.md | 4 +- docs/features/_category_.yaml | 1 - docs/how-to/configure.md | 11 +-- docs/how-to/dashboard.md | 3 +- docs/how-to/install.md | 63 ++++++++++-------- docs/index.md | 9 ++- docs/integrations/_category_.yaml | 2 + .../aider.mdx} | 8 +-- .../cline.mdx} | 16 ++--- .../continue.mdx} | 19 +++--- .../copilot.mdx} | 12 ++-- docs/integrations/index.mdx | 8 +++ docs/partials/_aider-providers.mdx | 2 +- docs/partials/_cline-providers.mdx | 22 +++--- docs/quickstart-continue.mdx | 4 +- .../img/continue-codegate-version-dark.webp | Bin 30758 -> 0 bytes .../cline-codegate-version-dark.webp | Bin .../cline-codegate-version-light.webp | Bin .../cline-provider-anthropic-dark.webp | Bin .../cline-provider-anthropic-light.webp | Bin .../cline-provider-lmstudio-dark.webp | Bin .../cline-provider-lmstudio-light.webp | Bin .../cline-provider-ollama-dark.webp | Bin .../cline-provider-ollama-light.webp | Bin .../cline-provider-openai-dark.webp | Bin .../cline-provider-openai-light.webp | Bin .../cline-settings-dark.webp | Bin .../cline-settings-light.webp | Bin .../continue-codegate-version-dark.webp | Bin .../continue-codegate-version-light.webp | Bin .../continue-extension-dark.webp | Bin .../continue-extension-light.webp | Bin .../copilot-codegate-version-dark.webp | Bin .../copilot-codegate-version-light.webp | Bin .../lmstudio-server-dark.webp | Bin .../lmstudio-server-light.webp | Bin vercel.json | 9 +++ 38 files changed, 112 insertions(+), 82 deletions(-) create mode 100644 docs/integrations/_category_.yaml rename docs/{how-to/use-with-aider.mdx => integrations/aider.mdx} (92%) rename docs/{how-to/use-with-cline.mdx => integrations/cline.mdx} (87%) rename docs/{how-to/use-with-continue.mdx => integrations/continue.mdx} (96%) rename docs/{how-to/use-with-copilot.mdx => integrations/copilot.mdx} (96%) create mode 100644 docs/integrations/index.mdx delete mode 100644 static/img/continue-codegate-version-dark.webp rename static/img/{how-to => integrations}/cline-codegate-version-dark.webp (100%) rename static/img/{how-to => integrations}/cline-codegate-version-light.webp (100%) rename static/img/{how-to => integrations}/cline-provider-anthropic-dark.webp (100%) rename static/img/{how-to => integrations}/cline-provider-anthropic-light.webp (100%) rename static/img/{how-to => integrations}/cline-provider-lmstudio-dark.webp (100%) rename static/img/{how-to => integrations}/cline-provider-lmstudio-light.webp (100%) rename static/img/{how-to => integrations}/cline-provider-ollama-dark.webp (100%) rename static/img/{how-to => integrations}/cline-provider-ollama-light.webp (100%) rename static/img/{how-to => integrations}/cline-provider-openai-dark.webp (100%) rename static/img/{how-to => integrations}/cline-provider-openai-light.webp (100%) rename static/img/{how-to => integrations}/cline-settings-dark.webp (100%) rename static/img/{how-to => integrations}/cline-settings-light.webp (100%) rename static/img/{how-to => integrations}/continue-codegate-version-dark.webp (100%) rename static/img/{how-to => integrations}/continue-codegate-version-light.webp (100%) rename static/img/{how-to => integrations}/continue-extension-dark.webp (100%) rename static/img/{how-to => integrations}/continue-extension-light.webp (100%) rename static/img/{how-to => integrations}/copilot-codegate-version-dark.webp (100%) rename static/img/{how-to => integrations}/copilot-codegate-version-light.webp (100%) rename static/img/{how-to => integrations}/lmstudio-server-dark.webp (100%) rename static/img/{how-to => integrations}/lmstudio-server-light.webp (100%) create mode 100644 vercel.json diff --git a/.gitignore b/.gitignore index b2d6de3..ed3fe72 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +.vercel diff --git a/docs/about/changelog.md b/docs/about/changelog.md index eea0445..3f4834f 100644 --- a/docs/about/changelog.md +++ b/docs/about/changelog.md @@ -16,7 +16,7 @@ Related: [Upgrade CodeGate](../how-to/install.md#upgrade-codegate) - **Cline support** - 28 Jan, 2025\ CodeGate version 0.1.14 adds support for [Cline](https://github.com/cline/cline) with Anthropic, OpenAI, Ollama, and LM - Studio. See the [how-to guide](../how-to/use-with-cline.mdx) to learn more. + Studio. See the [how-to guide](../integrations/cline.mdx) to learn more. - **Workspaces** - 22 Jan, 2025\ Now available in CodeGate v0.1.12, workspaces help you organize and customize @@ -26,7 +26,7 @@ Related: [Upgrade CodeGate](../how-to/install.md#upgrade-codegate) - **Aider support** - 13 Jan, 2025\ CodeGate version 0.1.6 adds support for [aider](https://aider.chat/), an AI pair programmer in your terminal. See the - [how-to guide](../how-to/use-with-aider.mdx) to learn more. + [how-to guide](../integrations/aider.mdx) to learn more. - **Semantic versioning for container image** - 8 Jan, 2025\ Starting with v0.1.4, the CodeGate container image is published with semantic diff --git a/docs/features/_category_.yaml b/docs/features/_category_.yaml index 6d79419..45c66b3 100644 --- a/docs/features/_category_.yaml +++ b/docs/features/_category_.yaml @@ -1,3 +1,2 @@ label: 'Features' position: 30 -collapsed: false diff --git a/docs/how-to/configure.md b/docs/how-to/configure.md index 03b2cd5..66dac3b 100644 --- a/docs/how-to/configure.md +++ b/docs/how-to/configure.md @@ -7,12 +7,13 @@ sidebar_position: 20 ## Customize CodeGate's behavior The CodeGate container runs with default settings to support Ollama, Anthropic, -and OpenAI APIs with typical settings. To customize the behavior, you can supply +and OpenAI APIs with typical settings. To customize the behavior, you can add extra configuration parameters to the container as environment variables: ```bash {2} docker run --name codegate -d -p 8989:8989 -p 9090:9090 \ [-e KEY=VALUE ...] \ + --mount type=volume,src=codegate_volume,dst=/app/codegate_volume \ --restart unless-stopped ghcr.io/stacklok/codegate ``` @@ -41,9 +42,11 @@ To use OpenRouter, set the vLLM URL when you launch CodeGate: ```bash {2} docker run --name codegate -d -p 8989:8989 -p 9090:9090 \ -e CODEGATE_VLLM_URL=https://openrouter.ai/api \ + --mount type=volume,src=codegate_volume,dst=/app/codegate_volume \ --restart unless-stopped ghcr.io/stacklok/codegate ``` -Then, [configure the Continue IDE plugin](./use-with-continue.mdx) to access the -vLLM endpoint (`http://localhost:8989/vllm/`) along with the model you'd like to -use and your OpenRouter API key. +Then, +[configure the Continue IDE plugin](../integrations/continue.mdx?provider=vllm) +to use CodeGate's vLLM endpoint (`http://localhost:8989/vllm`) along with the +model you'd like to use and your OpenRouter API key. diff --git a/docs/how-to/dashboard.md b/docs/how-to/dashboard.md index 18914ec..34f2bac 100644 --- a/docs/how-to/dashboard.md +++ b/docs/how-to/dashboard.md @@ -36,10 +36,9 @@ browser. ## Persisting dashboard data {#persisting-dashboard-data} -To retain your prompt history and other dashboard metrics between restarts, +To retain your prompt history and workspace configurations between restarts, mount a persistent [Docker volume](https://docs.docker.com/engine/storage/volumes/) to the CodeGate -container. The volume destination must be `/app/codegate_volume` inside the container. This example creates a volume named `codegate_volume`: ```bash {2} diff --git a/docs/how-to/install.md b/docs/how-to/install.md index ad933c0..f1e50a3 100644 --- a/docs/how-to/install.md +++ b/docs/how-to/install.md @@ -27,10 +27,13 @@ docker run --name codegate -d -p 8989:8989 -p 9090:9090 -p 8990:8990 --mount typ Parameter reference: +- `--name codegate` - give the container a friendly name for easy reference - `-d` - start in detached (background) mode -- `-p 8989:8989` - bind the CodeGate API to port 8989 on your host +- `-p 8989:8989` - bind the CodeGate API to port 8989 on your host (required) - `-p 9090:9090` - bind the CodeGate web dashboard to port 9090 on your host + (recommended) - `-p 8990:8990` - bind the CodeGate secure HTTP proxy to port 8990 on your host + (required for Copilot) - `--mount ...` - mount a persistent Docker volume named `codegate_volume` to the required path in the container - `--restart unless-stopped` - restart CodeGate after a Docker or system @@ -40,33 +43,34 @@ More example run commands to run the container with the right parameters for your scenario are found below. To learn how to customize the CodeGate application settings, see [Configure CodeGate](./configure.md) -### Alternative run commands {#examples} +:::warning -Run with minimal functionality for use with **Continue**, **aider**, or -**Cline**: +If you omit the persistent volume mount, your +[workspace configurations](../features/workspaces.mdx) and prompt history are +lost when you stop or restart CodeGate. -```bash -docker run -d -p 8989:8989 -p 9090:9090 --restart unless-stopped ghcr.io/stacklok/codegate:latest -``` +::: + +### Alternative run commands {#examples} -**Mount a persistent volume** to the container (see -[Persisting dashboard data](./dashboard.md#persisting-dashboard-data)): +Run with minimal functionality for use with **Continue**, **aider**, or +**Cline** (omits the HTTP proxy port needed by Copilot): ```bash docker run --name codegate -d -p 8989:8989 -p 9090:9090 --mount type=volume,src=codegate_volume,dst=/app/codegate_volume --restart unless-stopped ghcr.io/stacklok/codegate:latest ``` -**Copilot support:** enable the HTTP proxy port and mount a persistent volume -(see [Use CodeGate with GitHub Copilot](./use-with-copilot.mdx)): +**Restrict ports:** Docker publishes ports to all interfaces on your host by +default. This example publishes only on your `localhost` interface: ```bash -docker run --name codegate -d -p 8989:8989 -p 9090:9090 -p 8990:8990 --mount type=volume,src=codegate_volume,dst=/app/codegate_volume --restart unless-stopped ghcr.io/stacklok/codegate:latest +docker run --name codegate -d -p 127.0.0.1:8989:8989 -p 127.0.0.1:9090:9090 -p 127.0.0.1:8990:8990 --mount type=volume,src=codegate_volume,dst=/app/codegate_volume --restart unless-stopped ghcr.io/stacklok/codegate:latest ``` **Install a specific version:** starting with v0.1.4 you can optionally run a specific version of CodeGate using sematic version tags: -- Patch version: `ghcr.io/stacklok/codegate:v0.1.4` (exact) +- Patch version: `ghcr.io/stacklok/codegate:v0.1.15` (exact) - Minor version: `ghcr.io/stacklok/codegate:v0.1` (latest v0.1.x release) - Major version: `ghcr.io/stacklok/codegate:v0` (latest v0.x.x release) @@ -91,12 +95,20 @@ CodeGate listens on several network ports: | 8989 | 8989 | CodeGate API | | 8990 | 8990 | Secure HTTP proxy (GitHub Copilot integration) | +Docker publishes ports to all network interfaces on your system by default. This +can unintentionally expose your CodeGate installation to other systems on the +same network. To restrict this, add `127.0.0.1` IP to the publish flags: + +- API: `-p 127.0.0.1:8989:8989` +- HTTPS proxy: `-p 127.0.0.1:8990:8990` +- Dashboard: `-p 127.0.0.1:9090:9090` + All of the commands in these docs assume the default ports. To use different listening ports, modify the `-p` flag(s): +- API: `-p YOUR_PORT:8989` +- HTTPS proxy: `-p YOUR_PORT:8990` - Dashboard: `-p YOUR_PORT:9090` -- CodeGate API: `-p YOUR_PORT:8989` -- Secure HTTP proxy: `-p YOUR_PORT:8990` :::note @@ -149,19 +161,16 @@ persistent volume. ## Next steps -Now that CodeGate is running, proceed to configure your IDE integration. - -- [Use CodeGate with aider](./use-with-aider.mdx) -- [Use CodeGate with Cline](./use-with-cline.mdx) -- [Use CodeGate with Continue](./use-with-continue.mdx) -- [Use CodeGate with GitHub Copilot](./use-with-copilot.mdx) +Now that CodeGate is running, proceed to +[configure your AI assistant/agent](../integrations/index.mdx). ## Remove CodeGate -If you decide to stop using CodeGate, follow the removal steps for your IDE -integration: +If you decide to stop using CodeGate, follow the removal steps for your +[integration](../integrations/index.mdx), then stop and remove the CodeGate +container and volume: -- [Remove CodeGate - aider](./use-with-aider.mdx#remove-codegate) -- [Remove CodeGate - Cline](./use-with-cline.mdx#remove-codegate) -- [Remove CodeGate - Continue](./use-with-continue.mdx#remove-codegate) -- [Remove CodeGate - GitHub Copilot](./use-with-copilot.mdx#remove-codegate) +```bash +docker stop codegate && docker rm codegate +docker volume rm codegate_volume +``` diff --git a/docs/index.md b/docs/index.md index b2b3abd..f570db5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -37,10 +37,10 @@ CodeGate supports several development environments and AI providers. AI coding assistants / IDEs: -- **[GitHub Copilot](./how-to/use-with-copilot.mdx)** with Visual Studio Code +- **[GitHub Copilot](./integrations/copilot.mdx)** with Visual Studio Code (JetBrains coming soon!) -- **[Continue](./how-to/use-with-continue.mdx)** with Visual Studio Code and +- **[Continue](./integrations/continue.mdx)** with Visual Studio Code and JetBrains IDEs CodeGate supports the following AI model providers with Continue: @@ -54,10 +54,9 @@ AI coding assistants / IDEs: - Anthropic - OpenAI -- **[Aider](./how-to/use-with-aider.mdx)** with Ollama and OpenAI-compatible - APIs +- **[Aider](./integrations/aider.mdx)** with Ollama and OpenAI-compatible APIs -- **[Cline](./how-to/use-with-cline.mdx)** with Visual Studio Code +- **[Cline](./integrations/cline.mdx)** with Visual Studio Code CodeGate supports Ollama, Anthropic, OpenAI-compatible APIs, and LM Studio with Cline. diff --git a/docs/integrations/_category_.yaml b/docs/integrations/_category_.yaml new file mode 100644 index 0000000..4820194 --- /dev/null +++ b/docs/integrations/_category_.yaml @@ -0,0 +1,2 @@ +label: 'Integrations' +position: 25 diff --git a/docs/how-to/use-with-aider.mdx b/docs/integrations/aider.mdx similarity index 92% rename from docs/how-to/use-with-aider.mdx rename to docs/integrations/aider.mdx index 9681c92..76c268b 100644 --- a/docs/how-to/use-with-aider.mdx +++ b/docs/integrations/aider.mdx @@ -1,8 +1,8 @@ --- title: Use CodeGate with aider -description: Configure aider for CodeGate -sidebar_label: Use with aider -sidebar_position: 90 +description: Configure aider to use CodeGate +sidebar_label: Aider +sidebar_position: 10 --- import AiderProviders from '../partials/_aider-providers.mdx'; @@ -40,7 +40,7 @@ a response like "CodeGate version 0.1.13": Learn more about CodeGate's features: -- [Access the dashboard](./dashboard.md) +- [Access the dashboard](../how-to/dashboard.md) - [CodeGate features](../features/index.mdx) ## Remove CodeGate diff --git a/docs/how-to/use-with-cline.mdx b/docs/integrations/cline.mdx similarity index 87% rename from docs/how-to/use-with-cline.mdx rename to docs/integrations/cline.mdx index d95344b..9b41693 100644 --- a/docs/how-to/use-with-cline.mdx +++ b/docs/integrations/cline.mdx @@ -1,8 +1,8 @@ --- title: Use CodeGate with Cline -description: Configure the Cline IDE extension -sidebar_label: Use with Cline -sidebar_position: 90 +description: Configure the Cline extension for VS Code +sidebar_label: Cline +sidebar_position: 20 --- import useBaseUrl from '@docusaurus/useBaseUrl'; @@ -50,8 +50,8 @@ To configure Cline to send requests through CodeGate: @@ -71,8 +71,8 @@ sidebar and type `codegate version`. You should receive a response like @@ -104,7 +104,7 @@ Here is an example of how to use the `requests` package: Learn more about CodeGate's features and how to use them: -- [Access the dashboard](./dashboard.md) +- [Access the dashboard](../how-to/dashboard.md) - [CodeGate features](../features/index.mdx) ## Remove CodeGate diff --git a/docs/how-to/use-with-continue.mdx b/docs/integrations/continue.mdx similarity index 96% rename from docs/how-to/use-with-continue.mdx rename to docs/integrations/continue.mdx index 9c0f765..f15b882 100644 --- a/docs/how-to/use-with-continue.mdx +++ b/docs/integrations/continue.mdx @@ -1,8 +1,8 @@ --- title: Use CodeGate with Continue description: Configure the Continue IDE plugin -sidebar_label: Use with Continue -sidebar_position: 100 +sidebar_label: Continue +sidebar_position: 30 --- import Tabs from '@theme/Tabs'; @@ -110,7 +110,7 @@ Below are examples of complete Continue configurations for each supported provider. Replace the values in ALL_CAPS. The configuration syntax is the same for VS Code and JetBrains IDEs. - + You need Ollama installed on your local system with the server running @@ -119,7 +119,7 @@ You need Ollama installed on your local system with the server running CodeGate connects to `http://host.docker.internal:11434` by default. If you changed the default Ollama server port or to connect to a remote Ollama instance, launch CodeGate with the `CODEGATE_OLLAMA_URL` environment variable -set to the correct URL. See [Configure CodeGate](./configure.md). +set to the correct URL. See [Configure CodeGate](../how-to/configure.md). Replace `MODEL_NAME` with the names of model(s) you have installed locally using `ollama pull`. See Continue's @@ -288,7 +288,8 @@ To use this provider, download your desired model file in GGUF format from the [Hugging Face library](https://huggingface.co/models?library=gguf&sort=trending). Then copy it into the `/app/codegate_volume/models` directory in the CodeGate container. To persist models between restarts, run CodeGate with a Docker volume -as shown in the [recommended configuration](./install.md#recommended-settings). +as shown in the +[recommended configuration](../how-to/install.md#recommended-settings). Example using huggingface-cli to download our recommended models for chat (at least a 7B model is recommended for best results) and autocomplete (a 1.5B or 3B @@ -340,7 +341,7 @@ running locally or access to a remote server to use this provider. CodeGate connects to `http://localhost:8000` by default. If you changed the default Ollama server port or to connect to a remote Ollama instance, launch CodeGate with the `CODEGATE_VLLM_URL` environment variable set to the correct -URL. See [Configure CodeGate](./configure.md). +URL. See [Configure CodeGate](../how-to/configure.md). A vLLM server hosts a single model. Continue automatically selects the available model, so the `model` parameter is not required. See Continue's @@ -385,8 +386,8 @@ Continue chat and type `codegate version`. You should receive a response like @@ -418,7 +419,7 @@ Here is an example of how to use the `requests` package: Learn more about CodeGate's features and how to use them: -- [Access the dashboard](./dashboard.md) +- [Access the dashboard](../how-to/dashboard.md) - [CodeGate features](../features/index.mdx) ## Remove CodeGate diff --git a/docs/how-to/use-with-copilot.mdx b/docs/integrations/copilot.mdx similarity index 96% rename from docs/how-to/use-with-copilot.mdx rename to docs/integrations/copilot.mdx index 637fa2f..27b1a90 100644 --- a/docs/how-to/use-with-copilot.mdx +++ b/docs/integrations/copilot.mdx @@ -1,8 +1,8 @@ --- title: Use CodeGate with GitHub Copilot -description: Configure the Copilot IDE plugin -sidebar_label: Use with GitHub Copilot -sidebar_position: 110 +description: Configure your IDE to proxy Copilot traffic +sidebar_label: GitHub Copilot +sidebar_position: 50 --- import Tabs from '@theme/Tabs'; @@ -242,8 +242,8 @@ Copilot chat and type `codegate version`. You should receive a response like @@ -275,7 +275,7 @@ Here is an example of how to use the `requests` package: Learn more about CodeGate's features and how to use them: -- [Access the dashboard](./dashboard.md) +- [Access the dashboard](../how-to/dashboard.md) - [CodeGate features](../features/index.mdx) ## Remove CodeGate diff --git a/docs/integrations/index.mdx b/docs/integrations/index.mdx new file mode 100644 index 0000000..30f314a --- /dev/null +++ b/docs/integrations/index.mdx @@ -0,0 +1,8 @@ +--- +title: CodeGate integrations +description: Integrate CodeGate with your favorite AI coding assistant +--- + +import DocCardList from '@theme/DocCardList'; + + diff --git a/docs/partials/_aider-providers.mdx b/docs/partials/_aider-providers.mdx index 9b2308d..16c3f1f 100644 --- a/docs/partials/_aider-providers.mdx +++ b/docs/partials/_aider-providers.mdx @@ -3,7 +3,7 @@ import TabItem from '@theme/TabItem'; import LocalModelRecommendation from './_local-model-recommendation.md'; - + You need an [OpenAI API](https://openai.com/api/) account to use this provider. diff --git a/docs/partials/_cline-providers.mdx b/docs/partials/_cline-providers.mdx index e1faf5f..a266102 100644 --- a/docs/partials/_cline-providers.mdx +++ b/docs/partials/_cline-providers.mdx @@ -5,7 +5,7 @@ import ThemedImage from '@theme/ThemedImage'; import LocalModelRecommendation from './_local-model-recommendation.md'; - + You need an [Anthropic API](https://www.anthropic.com/api) account to use this @@ -21,8 +21,8 @@ To enable CodeGate, enable **Use custom base URL** and enter @@ -42,8 +42,8 @@ To enable CodeGate, set the **Base URL** to `https://localhost:8989/openai`. @@ -70,8 +70,8 @@ locally using `ollama pull`. @@ -91,8 +91,8 @@ you'll use with CodeGate, open the **Load** tab on the right and increase the @@ -114,8 +114,8 @@ for example `lm_studio/qwen2.5-coder-7b-instruct`. diff --git a/docs/quickstart-continue.mdx b/docs/quickstart-continue.mdx index 8c80137..c7fc091 100644 --- a/docs/quickstart-continue.mdx +++ b/docs/quickstart-continue.mdx @@ -22,7 +22,7 @@ through Continue. In this tutorial, you'll use Ollama to run a code generation model on your local machine. If you have access to a provider like Anthropic or OpenAI, see -[Use CodeGate with Continue](./how-to/use-with-continue.mdx) for complete +[Use CodeGate with Continue](./integrations/continue.mdx) for complete configuration details, then skip ahead to [Explore CodeGate's features](#explore-codegates-features) in this tutorial. @@ -261,7 +261,7 @@ Check out the rest of the docs to learn more about [Features](./features/index.mdx). If you have access to a hosted LLM provider like Anthropic or OpenAI, see -[Configure Continue to use CodeGate](./how-to/use-with-continue.mdx#configure-continue-to-use-codegate) +[Configure Continue to use CodeGate](./integrations/continue.mdx#configure-continue-to-use-codegate) to learn how to use those instead of Ollama. Finally, we want to hear about your experiences using CodeGate. Join the diff --git a/static/img/continue-codegate-version-dark.webp b/static/img/continue-codegate-version-dark.webp deleted file mode 100644 index a6ab3e71f46bf69919142075bf3d873ab1958b98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30758 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

5%sEfn8m11v?f-tvHM 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 diff --git a/static/img/how-to/cline-codegate-version-dark.webp b/static/img/integrations/cline-codegate-version-dark.webp similarity index 100% rename from static/img/how-to/cline-codegate-version-dark.webp rename to static/img/integrations/cline-codegate-version-dark.webp diff --git a/static/img/how-to/cline-codegate-version-light.webp b/static/img/integrations/cline-codegate-version-light.webp similarity index 100% rename from static/img/how-to/cline-codegate-version-light.webp rename to static/img/integrations/cline-codegate-version-light.webp diff --git a/static/img/how-to/cline-provider-anthropic-dark.webp b/static/img/integrations/cline-provider-anthropic-dark.webp similarity index 100% rename from static/img/how-to/cline-provider-anthropic-dark.webp rename to static/img/integrations/cline-provider-anthropic-dark.webp diff --git a/static/img/how-to/cline-provider-anthropic-light.webp b/static/img/integrations/cline-provider-anthropic-light.webp similarity index 100% rename from static/img/how-to/cline-provider-anthropic-light.webp rename to static/img/integrations/cline-provider-anthropic-light.webp diff --git a/static/img/how-to/cline-provider-lmstudio-dark.webp b/static/img/integrations/cline-provider-lmstudio-dark.webp similarity index 100% rename from static/img/how-to/cline-provider-lmstudio-dark.webp rename to static/img/integrations/cline-provider-lmstudio-dark.webp diff --git a/static/img/how-to/cline-provider-lmstudio-light.webp b/static/img/integrations/cline-provider-lmstudio-light.webp similarity index 100% rename from static/img/how-to/cline-provider-lmstudio-light.webp rename to static/img/integrations/cline-provider-lmstudio-light.webp diff --git a/static/img/how-to/cline-provider-ollama-dark.webp b/static/img/integrations/cline-provider-ollama-dark.webp similarity index 100% rename from static/img/how-to/cline-provider-ollama-dark.webp rename to static/img/integrations/cline-provider-ollama-dark.webp diff --git a/static/img/how-to/cline-provider-ollama-light.webp b/static/img/integrations/cline-provider-ollama-light.webp similarity index 100% rename from static/img/how-to/cline-provider-ollama-light.webp rename to static/img/integrations/cline-provider-ollama-light.webp diff --git a/static/img/how-to/cline-provider-openai-dark.webp b/static/img/integrations/cline-provider-openai-dark.webp similarity index 100% rename from static/img/how-to/cline-provider-openai-dark.webp rename to static/img/integrations/cline-provider-openai-dark.webp diff --git a/static/img/how-to/cline-provider-openai-light.webp b/static/img/integrations/cline-provider-openai-light.webp similarity index 100% rename from static/img/how-to/cline-provider-openai-light.webp rename to static/img/integrations/cline-provider-openai-light.webp diff --git a/static/img/how-to/cline-settings-dark.webp b/static/img/integrations/cline-settings-dark.webp similarity index 100% rename from static/img/how-to/cline-settings-dark.webp rename to static/img/integrations/cline-settings-dark.webp diff --git a/static/img/how-to/cline-settings-light.webp b/static/img/integrations/cline-settings-light.webp similarity index 100% rename from static/img/how-to/cline-settings-light.webp rename to static/img/integrations/cline-settings-light.webp diff --git a/static/img/how-to/continue-codegate-version-dark.webp b/static/img/integrations/continue-codegate-version-dark.webp similarity index 100% rename from static/img/how-to/continue-codegate-version-dark.webp rename to static/img/integrations/continue-codegate-version-dark.webp diff --git a/static/img/how-to/continue-codegate-version-light.webp b/static/img/integrations/continue-codegate-version-light.webp similarity index 100% rename from static/img/how-to/continue-codegate-version-light.webp rename to static/img/integrations/continue-codegate-version-light.webp diff --git a/static/img/how-to/continue-extension-dark.webp b/static/img/integrations/continue-extension-dark.webp similarity index 100% rename from static/img/how-to/continue-extension-dark.webp rename to static/img/integrations/continue-extension-dark.webp diff --git a/static/img/how-to/continue-extension-light.webp b/static/img/integrations/continue-extension-light.webp similarity index 100% rename from static/img/how-to/continue-extension-light.webp rename to static/img/integrations/continue-extension-light.webp diff --git a/static/img/how-to/copilot-codegate-version-dark.webp b/static/img/integrations/copilot-codegate-version-dark.webp similarity index 100% rename from static/img/how-to/copilot-codegate-version-dark.webp rename to static/img/integrations/copilot-codegate-version-dark.webp diff --git a/static/img/how-to/copilot-codegate-version-light.webp b/static/img/integrations/copilot-codegate-version-light.webp similarity index 100% rename from static/img/how-to/copilot-codegate-version-light.webp rename to static/img/integrations/copilot-codegate-version-light.webp diff --git a/static/img/how-to/lmstudio-server-dark.webp b/static/img/integrations/lmstudio-server-dark.webp similarity index 100% rename from static/img/how-to/lmstudio-server-dark.webp rename to static/img/integrations/lmstudio-server-dark.webp diff --git a/static/img/how-to/lmstudio-server-light.webp b/static/img/integrations/lmstudio-server-light.webp similarity index 100% rename from static/img/how-to/lmstudio-server-light.webp rename to static/img/integrations/lmstudio-server-light.webp diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..3a0794d --- /dev/null +++ b/vercel.json @@ -0,0 +1,9 @@ +{ + "redirects": [ + { + "source": "/how-to/(use-with-):path(aider|cline|continue|copilot)", + "destination": "/integrations/:path", + "permanent": true + } + ] +} From cc7445bfcbf00c3714794271f94902a86808171d Mon Sep 17 00:00:00 2001 From: Dan Barr Date: Thu, 30 Jan 2025 18:16:48 -0500 Subject: [PATCH 2/4] Make sure every run command has a volume --- docs/how-to/dashboard.md | 1 + docs/integrations/copilot.mdx | 4 ++-- docs/quickstart-continue.mdx | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/how-to/dashboard.md b/docs/how-to/dashboard.md index 34f2bac..a900588 100644 --- a/docs/how-to/dashboard.md +++ b/docs/how-to/dashboard.md @@ -16,6 +16,7 @@ system when you launch CodeGate, for example: ```bash {2} docker run --name codegate -d -p 8989:8989 \ -p 9090:9090 \ + --mount type=volume,src=codegate_volume,dst=/app/codegate_volume \ --restart unless-stopped ghcr.io/stacklok/codegate:latest ``` diff --git a/docs/integrations/copilot.mdx b/docs/integrations/copilot.mdx index 27b1a90..d4dc294 100644 --- a/docs/integrations/copilot.mdx +++ b/docs/integrations/copilot.mdx @@ -48,8 +48,8 @@ first with `docker stop codegate && docker rm codegate`. is used to maintain a secure end-to-end connection with Copilot. To prevent the certificate from changing on each restart, launch CodeGate - with a persistent data volume. To do this, add a `--mount` parameter to your - `docker run` command: + with a persistent data volume. To do this, make sure your `docker run` + command includes the `--mount` parameter: `--mount type=volume,src=codegate_volume,dst=/app/codegate_volume` diff --git a/docs/quickstart-continue.mdx b/docs/quickstart-continue.mdx index c7fc091..0d97a3b 100644 --- a/docs/quickstart-continue.mdx +++ b/docs/quickstart-continue.mdx @@ -55,7 +55,7 @@ Download and run the container using Docker: ```bash docker pull ghcr.io/stacklok/codegate:latest -docker run --name codegate -d -p 8989:8989 -p 9090:9090 --restart unless-stopped ghcr.io/stacklok/codegate:latest +docker run --name codegate -d -p 8989:8989 -p 9090:9090 --mount type=volume,src=codegate_volume,dst=/app/codegate_volume --restart unless-stopped ghcr.io/stacklok/codegate:latest ``` This pulls the latest CodeGate image from the GitHub Container Registry and From 06a633bca2b815904771ea73623f82c288b5d90f Mon Sep 17 00:00:00 2001 From: Dan Barr Date: Thu, 30 Jan 2025 18:44:47 -0500 Subject: [PATCH 3/4] Minor edits --- docs/about/changelog.md | 19 ++++++++++--------- docs/about/contributing.md | 10 ++++++++-- docs/about/faq.md | 8 ++++---- docs/about/index.mdx | 2 +- docs/integrations/cline.mdx | 4 ++-- docs/integrations/index.mdx | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/docs/about/changelog.md b/docs/about/changelog.md index 3f4834f..9cd569b 100644 --- a/docs/about/changelog.md +++ b/docs/about/changelog.md @@ -13,20 +13,20 @@ Major features and changes are noted here. To review all updates, see the Related: [Upgrade CodeGate](../how-to/install.md#upgrade-codegate) -- **Cline support** - 28 Jan, 2025\ - CodeGate version 0.1.14 adds support for - [Cline](https://github.com/cline/cline) with Anthropic, OpenAI, Ollama, and LM - Studio. See the [how-to guide](../integrations/cline.mdx) to learn more. +- **New integration: Cline** - 28 Jan, 2025\ + CodeGate version 0.1.14 adds support for [Cline](https://cline.bot/) with + Anthropic, OpenAI, Ollama, and LM Studio. See the + [integration guide](../integrations/cline.mdx) to learn more. - **Workspaces** - 22 Jan, 2025\ Now available in CodeGate v0.1.12, workspaces help you organize and customize your AI-assisted development. Learn more in [Workspaces](../features/workspaces.mdx). -- **Aider support** - 13 Jan, 2025\ +- **New integration: aider** - 13 Jan, 2025\ CodeGate version 0.1.6 adds support for [aider](https://aider.chat/), an AI pair programmer in your terminal. See the - [how-to guide](../integrations/aider.mdx) to learn more. + [integration guide](../integrations/aider.mdx) to learn more. - **Semantic versioning for container image** - 8 Jan, 2025\ Starting with v0.1.4, the CodeGate container image is published with semantic @@ -35,11 +35,12 @@ Related: [Upgrade CodeGate](../how-to/install.md#upgrade-codegate) optionally pull using the major (`v0`), minor (`v0.1`), or patch version (`v0.1.4`) to explicitly control the version you're running. \ CodeGate is evolving quickly, so we still recommend pulling the `latest` tag - so you don't miss out on new features and updates to package risk data. + so you don't miss out on the newest features and updates. - **UI port change** - 7 Jan, 2025\ The internal port for the dashboard UI has changed from 80 to 9090 to resolve a permissions issue for Linux users. -- **Introducing CodeGate** - 17 Dec, 2024\ - Initial public launch of CodeGate! +- **Introducing CodeGate!** - 17 Dec, 2024\ + Initial public launch of CodeGate, with support for Continue and GitHub + Copilot. diff --git a/docs/about/contributing.md b/docs/about/contributing.md index 2794c38..0c118e0 100644 --- a/docs/about/contributing.md +++ b/docs/about/contributing.md @@ -1,6 +1,6 @@ --- title: Contributing -description: How to contribute to the project. +description: How to contribute to CodeGate sidebar_position: 30 --- @@ -25,7 +25,13 @@ general usage question, please ask in the `#codegate` channel on create a new issue in the [CodeGate GitHub repository](https://github.com/stacklok/codegate/issues). -## Contributing code +## Contributing code or docs + +CodeGate's code and docs are managed in several repositories: + +- Main repo: https://github.com/stacklok/codegate +- Dashboard UI: https://github.com/stacklok/codegate-ui +- Docs: https://github.com/stacklok/codegate-docs If you've found an issue you'd like to work on, you can contribute code to CodeGate by submitting a pull request. Before you submit a pull request, please diff --git a/docs/about/faq.md b/docs/about/faq.md index cf15f5b..5e0bccb 100644 --- a/docs/about/faq.md +++ b/docs/about/faq.md @@ -1,14 +1,14 @@ --- title: Frequently asked questions -description: Frequently asked questions about the CodeGate project. +description: Frequently asked questions about the CodeGate project sidebar_label: FAQ sidebar_position: 10 --- -### Does CodeGate replace my AI code assistant plugin? +### Does CodeGate replace my AI coding assistant or agent? -No, CodeGate works _with_ your AI code assistant, as a local intermediary -between your client and the LLM it's communicating with. +No, CodeGate works _with_ your AI coding tool, as a local intermediary between +your client and the LLM it's communicating with. ### Does CodeGate work with any other IDE plugins or coding assistants? diff --git a/docs/about/index.mdx b/docs/about/index.mdx index 6d6467c..6af1f49 100644 --- a/docs/about/index.mdx +++ b/docs/about/index.mdx @@ -1,6 +1,6 @@ --- title: About CodeGate -description: More information about the CodeGate project. +description: Learn more about the CodeGate project --- import DocCardList from '@theme/DocCardList'; diff --git a/docs/integrations/cline.mdx b/docs/integrations/cline.mdx index 9b41693..bef9b50 100644 --- a/docs/integrations/cline.mdx +++ b/docs/integrations/cline.mdx @@ -8,8 +8,8 @@ sidebar_position: 20 import useBaseUrl from '@docusaurus/useBaseUrl'; import ThemedImage from '@theme/ThemedImage'; -[Cline](https://github.com/cline/cline) is an autonomous coding agent for Visual -Studio Code that supports numerous API providers and models. +[Cline](https://cline.bot/) is an autonomous coding agent for Visual Studio Code +that supports numerous API providers and models. CodeGate works with the following AI model providers through Cline: diff --git a/docs/integrations/index.mdx b/docs/integrations/index.mdx index 30f314a..c50c16e 100644 --- a/docs/integrations/index.mdx +++ b/docs/integrations/index.mdx @@ -1,6 +1,6 @@ --- title: CodeGate integrations -description: Integrate CodeGate with your favorite AI coding assistant +description: Integrate CodeGate with your favorite AI coding tools --- import DocCardList from '@theme/DocCardList'; From 3493e8d877fccc55269aef1aa9803ef85023fd94 Mon Sep 17 00:00:00 2001 From: Dan Barr Date: Fri, 31 Jan 2025 11:24:00 -0500 Subject: [PATCH 4/4] Update Continue quickstart title --- docs/quickstart-continue.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/quickstart-continue.mdx b/docs/quickstart-continue.mdx index 0d97a3b..525b82a 100644 --- a/docs/quickstart-continue.mdx +++ b/docs/quickstart-continue.mdx @@ -1,7 +1,7 @@ --- -title: Quickstart guide - Continue -description: Get up and running with CodeGate and Continue -sidebar_label: Quickstart - Continue +title: Quickstart guide - Continue and Ollama +description: Get up and running with CodeGate, Continue, and Ollama +sidebar_label: Quickstart - Continue + Ollama sidebar_position: 10 --- @@ -12,8 +12,8 @@ import ThemedImage from '@theme/ThemedImage'; This guide will get you up and running with CodeGate in just a few minutes using Visual Studio Code, the open source Continue AI assistant, and a locally-hosted -LLM. By the end, you'll learn how CodeGate helps protect your privacy and -improve the security of your applications. +LLM using Ollama. By the end, you'll learn how CodeGate helps protect your +privacy and improve the security of your applications. :::info