--- url: /guides/browser-only.md --- # Browser-Only Implementation :::warning **Security Warning**: This exposes your API keys in client-side code and is not secure. Use only for testing, internal tools, or when security is not a concern. For production applications accessible to the public, we strongly recommend using the server-side approach described in the [Quick Start](/) guide. ::: ## Overview While Monacopilot's recommended architecture separates client and server responsibilities to keep your API keys secure, you might have scenarios where a browser-only implementation is preferred. This guide shows how to implement Monacopilot entirely in the browser without a separate server endpoint. ## Implementation The key to a browser-only implementation is using the `requestHandler` option with `CompletionCopilot` directly in your client code: ```javascript import { registerCompletion, CompletionCopilot } from 'monacopilot'; // Create the copilot instance directly in the browser const copilot = new CompletionCopilot('YOUR_API_KEY', { provider: 'mistral', model: 'codestral', }); registerCompletion(monaco, editor, { language: 'javascript', // Use requestHandler instead of endpoint requestHandler: async ({ body }) => { const completion = await copilot.complete({ body }); return completion; }, }); ``` --- --- url: /configuration/request-options.md --- # Completion Request Options Configure how completion requests are made to the LLM provider. ## AI Request Handler You can override the default fetch behavior when making requests to the LLM provider by providing a custom `aiRequestHandler`. This allows you to use your own HTTP client or add custom logic such as authentication, retry mechanisms, or request/response transformation. ```javascript copilot.complete({ options: { aiRequestHandler: async ({ endpoint, body, headers }) => { const response = await fetch(endpoint, { method: 'POST', headers: { ...headers, 'X-Custom-Header': 'value' }, body: JSON.stringify(body), }) if (!response.ok) { throw new Error("Failed to get completion") } return response.json() }, }, }); ``` --- --- url: /configuration/copilot-options.md --- # Copilot Options Configure your `CompletionCopilot` instance with different providers, models and custom options to get the best code completions for your needs. ## Changing the Provider and Model You can specify a different provider and model by setting the `provider` and `model` parameters in the `CompletionCopilot` instance. ```javascript const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); ``` Currently, Monacopilot supports the following providers and models: | Provider | Model | Notes | API Key | | -------- | ----------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | | mistral | `codestral` | Provides accurate code completions using Fill-in-the-Middle (FIM) technology with fast response time | [Get Mistral API Key](https://console.mistral.ai/api-keys) | :::info Monacopilot includes only code completion models as built-in options, such as Codestral by Mistral. General-purpose chat models like GPTs or Claude are not included, as they are slower and less accurate for code completion tasks. Currently, Codestral is the only built-in model, but more will be added as they become available. However, you can still use any other model, including OpenAI GPTs, Claude, or others—by using the [Custom Model](/advanced/custom-model) feature. ::: --- --- url: /advanced/cross-language.md --- # Cross-Language API Handler Implementation While the example in this documentation uses JavaScript/Node.js (which is recommended), you can set up the API handler in any language or framework. For JavaScript, Monacopilot provides a built-in function that handles all the necessary steps, such as generating the prompt, sending it to the model, and processing the response. However, if you're using a different language, you'll need to implement these steps manually. ## Implementation Steps 1. Create an endpoint that accepts POST requests (e.g., `/code-completion`). 2. The endpoint should expect a JSON body containing completion metadata. 3. Use the metadata to construct a prompt for your LLM. 4. Send the prompt to your chosen LLM and get the completion. 5. Return a JSON response with the following structure: ```json { "completion": "Generated completion text" } ``` Or in case of an error: ```json { "completion": null, "error": "Error message" } ``` ## Key Considerations * The prompt should instruct the model to return only the completion text, without any additional formatting or explanations. * The completion text should be ready for direct insertion into the editor. Check out the [prompt.ts](https://github.com/arshad-yaseen/monacopilot/blob/main/packages/monacopilot/src/prompt.ts) file to see how Monacopilot generates the prompt. This will give you an idea of how to structure the prompt for your LLM to achieve the best completions. ## Metadata Overview The request body's `completionMetadata` object contains essential information for crafting a prompt for the LLM to generate accurate completions. See the [Completion Metadata](/advanced/custom-prompt#completion-metadata) section for more details. ## Example Implementation (Python with FastAPI) Here's a basic example using Python and FastAPI: ```python [fastapi-example.py] from fastapi import FastAPI, Request app = FastAPI() @app.post('/code-completion') async def handle_completion(request: Request): try: body = await request.json() metadata = body['completionMetadata'] prompt = f"""Please complete the following {metadata['language']} code: {metadata['textBeforeCursor']} {metadata['textAfterCursor']} Use modern {metadata['language']} practices and hooks where appropriate. Please provide only the completed part of the code without additional comments or explanations.""" # Simulate a response from a model response = "Your model's response here" return { 'completion': response, 'error': None } except Exception as e: return { 'completion': None, 'error': str(e) } ``` Now, Monacopilot is set up to send completion requests to the `/code-completion` endpoint and receive completions in response. ```javascript registerCompletion(monaco, editor, { endpoint: 'https://my-python-api.com/code-completion', // ... other options }); ``` --- --- url: /advanced/custom-model.md --- # Custom Model You can use a custom LLM that isn't built into Monacopilot by setting up a `model` when you create a new CompletionCopilot. This feature lets you connect to LLMs from other services or your own custom-built models. ## Example ```javascript const copilot = new CompletionCopilot(undefined, { // You don't need to set the provider if you are using a custom model. // provider: "openai", model: async prompt => { const response = await fetch( 'https://api.openai.com/v1/chat/completions', { method: 'POST', headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model: 'gpt-4o', messages: [ {role: 'system', content: prompt.context}, { role: 'user', content: `${prompt.instruction}\n\n${prompt.fileContent}`, }, ], temperature: 0.2, max_tokens: 256, }), }, ); const data = await response.json(); return { text: data.choices[0].message.content, }; }, }); ``` ## Implementation The `model` option accepts an async function with the following signature: ```typescript type CustomCopilotModel = (prompt: PromptData) => Promise; type CustomModelResponse = { /** The generated text content, or null if no text was generated */ text: string | null; }; ``` ### Prompt Data Structure The `prompt` parameter passed to the model function has the following structure: ```typescript interface PromptData { /** * Contextual information about the code environment * @example filename, technologies, etc. */ context: string; /** * Instructions for the AI model on how to generate the completion */ instruction: string; /** * The content of the file being edited */ fileContent: string; } ``` ## Model Accuracy Considerations When using a custom model, the accuracy of completions becomes your responsibility. Monacopilot's built-in models like Codestral support Fill-in-the-Middle (FIM) capabilities, which significantly enhances completion accuracy by understanding both the prefix and suffix context. If your custom model doesn't support FIM, you may need to: * Improve the prompt engineering to compensate * Use a higher-quality model For best results, consider using code-optimized models when available. ## Editor Integration Options When registering your completion with Monaco editor, there are some options especially relevant for custom models: ```javascript registerCompletion(editor, { // Disable follow-up completions for general-purpose models allowFollowUpCompletions: false, // other options... }); ``` ### [allowFollowUpCompletions](/configuration/register-options.html#follow-up-completions) This option controls whether new follow-up completions are automatically triggered after accepting a completion. Set it to `false` when: * Using general-purpose models like GPT-4o * Working with models that don't have FIM capabilities * Experiencing poor quality follow-up suggestions Leave it enabled (`true`) when: * Using custom models that have FIM capabilities * Working with code-completion-optimized models ## Client SDKs Example You can use client SDKs for various AI providers to simplify integration with your custom model. The following example demonstrates how to use the Anthropic SDK to connect Claude models to Monacopilot. ```javascript import Anthropic from '@anthropic-ai/sdk'; const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY, }); const copilot = new CompletionCopilot(undefined, { model: async prompt => { const completion = await anthropic.messages.create({ model: 'claude-3-5-haiku-latest', max_tokens: 1024, messages: [ {role: 'system', content: prompt.context}, { role: 'user', content: `${prompt.instruction}\n\n${prompt.fileContent}`, }, ], temperature: 0.1, }); return { text: completion.content[0].text, }; }, }); ``` ## Working with Different Models When working with different models, you'll need to format the prompt data appropriately for your specific model: * For chat-based models (OpenAI, Anthropic, etc.): ```javascript // OpenAI format messages: [ {role: 'system', content: prompt.context}, { role: 'user', content: `${prompt.instruction}\n\n${prompt.fileContent}`, }, ]; // Anthropic format system: prompt.context, messages: [ { role: 'user', content: `${prompt.instruction}\n\n${prompt.fileContent}`, }, ]; ``` * For completion-based models: ```javascript // Single prompt format prompt: `Context: ${prompt.context}\nFile: ${prompt.fileContent}\nTask: ${prompt.instruction}`; ``` --- --- url: /advanced/custom-prompt.md --- # Custom Prompt You can customize the prompt used for code completions by providing a `customPrompt` function in the options parameter of the `copilot.complete` method. This allows you to tailor how the AI completes your code based on your specific needs. ## Usage ```javascript copilot.complete({ options: { customPrompt: completionMetadata => ({ context: 'Your custom codebase context information here', instruction: 'Your custom instructions for code completion here', fileContent: 'Your representation of file with cursor position', }), }, }); ``` The `context`, `instruction`, and `fileContent` properties in the `customPrompt` function are all optional. If you omit any of these properties, the default values for those fields will be used. ## Parameters The `customPrompt` function receives a `completionMetadata` object, which contains information about the current editor state and can be used to tailor the prompt. ### Completion Metadata | Property | Type | Description | | ------------------ | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` or `undefined` | The programming language of the code being completed. | | `cursorPosition` | `{ lineNumber: number; column: number }` | The current cursor position where the completion should begin. | | `filename` | `string` or `undefined` | The name of the file being edited. Only available if you have provided the `filename` option in the `registerCompletion` function. | | `technologies` | `string[]` or `undefined` | An array of technologies used in the project. Only available if you have provided the `technologies` option in the `registerCompletion` function. | | `relatedFiles` | `object[]` or `undefined` | An array of objects containing the `path` and `content` of related files. Only available if you have provided the `relatedFiles` option in the `registerCompletion` function. | | `textAfterCursor` | `string` | The text that appears after the cursor position. | | `textBeforeCursor` | `string` | The text that appears before the cursor position. | ## Return Value Structure The `customPrompt` function should return a `PromptData` object (or a partial one) with the following properties: | Property | Type | Description | | ------------- | ----------------------- | --------------------------------------------------------------------------------------------- | | `context` | `string` or `undefined` | Information about the codebase context, including technologies, filename, language, etc. | | `instruction` | `string` or `undefined` | Instructions for how the AI should complete the code after the cursor position. | | `fileContent` | `string` or `undefined` | The representation of the file content showing where the cursor is positioned for completion. | ## Example Here's an example of a custom prompt for completing React component code: ```javascript const customPrompt = ({ textBeforeCursor, textAfterCursor, language, filename, technologies, }) => ({ context: `You're working with a ${language} file named ${filename || 'unnamed'} in a project using ${technologies?.join(', ') || 'React'}.`, instruction: 'Complete the code after the cursor position with appropriate React syntax. Ensure the code follows modern React best practices and matches the style of the existing code.', fileContent: `${textBeforeCursor}[CURSOR]${textAfterCursor}`, }); copilot.complete({ options: {customPrompt}, }); ``` ## Partial Customization You can customize just one aspect of the prompt while letting the system handle the rest: ```javascript // Only customize the instruction for code completion copilot.complete({ options: { customPrompt: metadata => ({ instruction: 'Complete this code with an efficient algorithm that handles edge cases.', }), }, }); // Only customize the context based on project information copilot.complete({ options: { customPrompt: ({language, technologies, filename}) => ({ context: `This is a ${language} file named ${filename} in a project using ${technologies?.join(', ')}. The code follows a functional programming paradigm with strict typing.`, }), }, }); ``` By using a custom prompt, you can guide the AI to complete your code in ways that better match your coding style, project requirements, or specific technologies you're working with. For additional `completionMetadata` needs, please [open an issue](https://github.com/arshad-yaseen/monacopilot/issues/new). --- --- url: /advanced/custom-request-handler.md --- # Custom Request Handler You can customize how requests are sent to your completion endpoint by using the `requestHandler` option when registering your completion. Instead of Monacopilot handling the request, you take control of the entire request process, allowing you to add custom headers, authentication tokens, or modify the request body before sending it to your endpoint. ## Example ```javascript registerCompletion(monaco, editor, { language: 'javascript', requestHandler: async ({ body }) => { const response = await fetch('https://your-api-url.com/code-completion', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Custom-Header': 'custom-value' }, body: JSON.stringify({ ...body, additionalData: { userId: 'user-123', projectId: 'project-456' } }) }); return await response.json(); } }); ``` ## Server-Side Implementation Your server endpoint will receive the modified request with your custom headers and body: ```javascript app.post('/code-completion', async (req, res) => { const authToken = req.headers.authorization; const customHeader = req.headers['x-custom-header']; const { additionalData } = req.body; const completion = await copilot.complete({ body: req.body, }); res.json(completion); }); ``` ## Return Format The `requestHandler` function must return a response object with the right format: ```javascript // If using CompletionCopilot in your endpoint // Simply return the response from your endpoint return await response.json(); // If implementing a custom solution // Return an object with either completion or error return { completion: "your completion text", // Text to insert in the editor error: "error message" // Optional error message }; ``` When using the standard `copilot.complete()` in your endpoint, you don't need to modify the response structure - just return the JSON response directly. For custom implementations, ensure you return an object with a `completion` property containing the text to insert into the editor. --- --- url: /examples/gatsby.md --- # Gatsby Learn how to integrate Monacopilot with Gatsby. ## Installation First, install the required dependencies: ::: code-group ```bash [npm] npm install monacopilot @monaco-editor/react ``` ```bash [yarn] yarn add monacopilot @monaco-editor/react ``` ```bash [pnpm] pnpm add monacopilot @monaco-editor/react ``` ```bash [bun] bun add monacopilot @monaco-editor/react ``` ::: ## Implementation ### API Function Gatsby supports serverless functions placed under the `/src/api` directory. Create a function for completions in `src/api/code-completion.ts`: ```typescript [src/api/code-completion.ts] import type {GatsbyFunctionRequest, GatsbyFunctionResponse} from 'gatsby'; import {CompletionCopilot, type CompletionRequestBody} from 'monacopilot'; const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY!, { provider: 'mistral', model: 'codestral', }); export async function handler( req: GatsbyFunctionRequest, res: GatsbyFunctionResponse, ) { if (req.method !== 'POST') { res.status(405).json({error: 'Method not allowed'}); return; } try { const body: CompletionRequestBody = JSON.parse(req.body); const completion = await copilot.complete({body}); res.status(200).json(completion); } catch (error) { res.status(500).json({error: 'Internal Server Error', details: error}); } } ``` ### Editor Component Create an Editor component: ```typescript [src/components/Editor.tsx] import { useEffect, useRef } from "react"; import MonacoEditor from "@monaco-editor/react"; import { registerCompletion, type CompletionRegistration, type Monaco, type StandaloneCodeEditor, } from "monacopilot"; export default function Editor() { const completionRef = useRef(null); const handleMount = (editor: StandaloneCodeEditor, monaco: Monaco) => { completionRef.current = registerCompletion(monaco, editor, { endpoint: "/api/code-completion", language: "javascript", }); }; useEffect(() => { return () => { completionRef.current?.deregister(); }; }, []); return ; } ``` ### Page Component Create your page component: ```typescript [src/pages/index.tsx] import * as React from "react"; import Editor from "../components/Editor"; export default function IndexPage() { return (

Monacopilot Gatsby Example

); } ``` ### Environment Variables Create a `.env` file in your project root: ```bash [.env] MISTRAL_API_KEY=your_mistral_api_key_here ``` Obtain your Mistral API Key from the [Mistral AI Console](https://console.mistral.ai/api-keys). Monacopilot supports multiple AI providers and models. For details on available options and configuration, see the [Changing the Provider and Model](/configuration/copilot-options#changing-the-provider-and-model) documentation. ## Running the Example 1. Install dependencies: ::: code-group ```bash [npm] npm install ``` ```bash [yarn] yarn ``` ```bash [pnpm] pnpm install ``` ```bash [bun] bun install ``` ::: 2. Start the development server: ::: code-group ```bash [npm] npm run develop ``` ```bash [yarn] yarn develop ``` ```bash [pnpm] pnpm develop ``` ```bash [bun] bun develop ``` ::: 3. Open `http://localhost:8000` in your browser. You should now see a Monaco Editor with AI-powered completions working! --- --- url: /examples/nextjs.md --- # Next.js Learn how to integrate Monacopilot with Next.js using either the App Router or Pages Router. ## Installation First, install the required dependencies: ::: code-group ```bash [npm] npm install monacopilot @monaco-editor/react ``` ```bash [yarn] yarn add monacopilot @monaco-editor/react ``` ```bash [pnpm] pnpm add monacopilot @monaco-editor/react ``` ```bash [bun] bun add monacopilot @monaco-editor/react ``` ::: ## Implementation ### API Route First, create an API route to handle completion requests: ::: code-group ```ts [App Router] // app/api/code-completion/route.ts import {NextRequest, NextResponse} from 'next/server'; import {CompletionCopilot, type CompletionRequestBody} from 'monacopilot'; const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); export async function POST(req: NextRequest) { const body: CompletionRequestBody = await req.json(); const completion = await copilot.complete({ body, }); return NextResponse.json(completion, {status: 200}); } ``` ```ts [Pages Router] // pages/api/code-completion.ts import {NextApiRequest, NextApiResponse} from 'next'; import {CompletionCopilot} from 'monacopilot'; const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); export default async function handler( req: NextApiRequest, res: NextApiResponse, ) { const completion = await copilot.complete({ body: req.body, }); res.status(200).json(completion); } ``` ::: ### Editor Component Create a Editor component: ```tsx [components/Editor.tsx] 'use client'; import {useEffect, useRef} from 'react'; import MonacoEditor from '@monaco-editor/react'; import { registerCompletion, type CompletionRegistration, type Monaco, type StandaloneCodeEditor, } from 'monacopilot'; export default function Editor() { const completionRef = useRef(null); const handleMount = (editor: StandaloneCodeEditor, monaco: Monaco) => { completionRef.current = registerCompletion(monaco, editor, { endpoint: '/api/code-completion', language: 'javascript', }); }; useEffect(() => { return () => { completionRef.current?.deregister(); }; }, []); return ( ); } ``` ### Page Component Use the Editor component in your page: ::: code-group ```tsx [App Router] // app/page.tsx import Editor from '@/components/Editor'; export default function Home() { return (

Monacopilot Next.js Example

); } ``` ```tsx [Pages Router] // pages/index.tsx import Editor from '@/components/Editor'; export default function Home() { return (

Monacopilot Next.js Example

); } ``` ::: ### Environment Variables Create a `.env.local` file in your project root: ```bash [.env.local] MISTRAL_API_KEY=your_mistral_api_key_here ``` Obtain your Mistral API Key from the [Mistral AI Console](https://console.mistral.ai/api-keys). Monacopilot supports multiple AI providers and models. For details on available options and configuration, see the [Changing the Provider and Model](/configuration/copilot-options#changing-the-provider-and-model) documentation. ## Running the Example 1. Install dependencies: ::: code-group ```bash [npm] npm install ``` ```bash [yarn] yarn ``` ```bash [pnpm] pnpm install ``` ```bash [bun] bun install ``` ::: 2. Start the development server: ::: code-group ```bash [npm] npm run dev ``` ```bash [yarn] yarn dev ``` ```bash [pnpm] pnpm dev ``` ```bash [bun] bun dev ``` ::: 3. Open `http://localhost:3000` in your browser. You should now see a Monaco Editor with AI-powered completions working! --- --- url: /configuration/register-options.md --- # Register Completion Options The `registerCompletion` function accepts several options that allow you to customize how code completions are triggered and displayed in your Monaco Editor. This guide covers all the available options and their usage. ## Trigger Mode The `trigger` option determines when the completion service provides code completions. You can choose between receiving suggestions/completions in real-time as you type or after a brief pause. ```javascript registerCompletion(monaco, editor, { trigger: 'onTyping', }); ``` | Trigger | Description | Notes | | -------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `'onIdle'` (default) | Provides completions after a brief pause in typing. | This approach is less resource-intensive, as it only initiates a request when the editor is idle. | | `'onTyping'` | Provides completions in real-time as you type. | | | `'onDemand'` | Does not provide completions automatically. | Completions are triggered manually using the `trigger` function from the `registerCompletion` return. This allows for precise control over when completions are provided. | [OnTyping Demo](https://github.com/user-attachments/assets/22c2ce44-334c-4963-b853-01b890b8e39f) ::: tip If you are using `mistral` models with the `onTyping` trigger, it is recommended to use Mistral's pay-as-you-go plan. This ensures you will never hit rate limit errors and allows you to experience super fast and accurate completions. ::: ## Manually Trigger Completions If you prefer not to trigger completions automatically (e.g., on typing or on idle), you can trigger completions manually. This is useful in scenarios where you want to control when completions are provided, such as through a button click or a keyboard shortcut. ```javascript const completion = registerCompletion(monaco, editor, { trigger: 'onDemand', }); completion.trigger(); ``` To set up manual triggering, configure the `trigger` option to `'onDemand'`. This disables automatic completions, allowing you to call the `completion.trigger()` method explicitly when needed. ### Trigger Completions with a Keyboard Shortcut You can set up completions to trigger when the `Ctrl+Shift+Space` keyboard shortcut is pressed. ```javascript const completion = registerCompletion(monaco, editor, { trigger: 'onDemand', }); editor.addCommand( monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Space, () => { completion.trigger(); }, ); ``` ### Trigger Completions with an Editor Action You can add a custom editor action to trigger completions manually. ![Editor Action Demo](https://i.postimg.cc/pTNQ3k6J/editor-action-demo.png) ```javascript const completion = registerCompletion(monaco, editor, { trigger: 'onDemand', }); monaco.editor.addEditorAction({ id: 'monacopilot.triggerCompletion', label: 'Complete Code', contextMenuGroupId: 'navigation', keybindings: [ monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Space, ], run: () => { completion.trigger(); }, }); ``` ## Multi-File Context Improve Copilot's suggestions by providing code context from other files in your project. This helps Copilot understand your broader codebase and offer more relevant completions. ```javascript registerCompletion(monaco, editor, { relatedFiles: [ { path: './utils.js', // The exact path you'd use when importing content: 'export const reverse = (str) => str.split("").reverse().join("")', }, ], }); ``` The `path` value should match how you actually import the file in your code. After registering, when you type `const isPalindrome = `, Copilot will suggest code that properly imports and uses the `reverse` function from your utils.js file. ## Filename Specify the name of the file being edited to receive more contextually relevant completions. ```javascript registerCompletion(monaco, editor, { filename: 'utils.js', // e.g., "index.js", "utils/objects.js" }); ``` Now, the completions will be more relevant to the file's context. ## Completions for Specific Technologies Enable completions tailored to specific technologies by using the `technologies` option. ```javascript registerCompletion(monaco, editor, { technologies: ['react', 'next.js', 'tailwindcss'], }); ``` This configuration will provide completions relevant to React, Next.js, and Tailwind CSS. ## Dynamically Updating Options You can dynamically update completion options after registration using the `updateOptions` method at runtime without needing deregister and register again. ```javascript const completion = registerCompletion(monaco, editor, { language: 'javascript', endpoint: '/api/code-completion', }); // Later, update options when needed: completion.updateOptions((currentOptions) => ({ relatedFiles: [ ...currentOptions.relatedFiles, { path: './newFile.js', content: 'export function newFunction() { return "hello world"; }', }, ], })); ``` The `updateOptions` method accepts a callback function that receives the current options and returns a partial options object containing only the properties you want to update. ## Max Context Lines To manage potentially lengthy code in your editor, you can limit the number of lines included in the completion request using the `maxContextLines` option. By default, this is set to `100` lines. For example, if there's a chance that the code in your editor may exceed `500` lines, you don't need to provide all those lines to the model. This would increase costs due to the huge number of input tokens. You can adjust `maxContextLines` based on how accurate you want the completions to be and how much you're willing to pay for the model. ```javascript registerCompletion(monaco, editor, { maxContextLines: 60, }); ``` ## Caching Completions Monacopilot caches completions by default, reusing cached completions when the context and cursor position match while editing (default: `true`). To disable caching: ```javascript registerCompletion(monaco, editor, { enableCaching: false, }); ``` ## Follow-Up Completions By default, Monacopilot will automatically generate a new completion immediately after the user accepts a completion. This feature, controlled by the `allowFollowUpCompletions` option, enhances productivity by providing a continuous flow of suggestions (default: `true`). To disable follow-up completions: ```javascript registerCompletion(monaco, editor, { allowFollowUpCompletions: false, }); ``` When disabled, the system will not automatically generate new completions after accepting one, giving you more control over when completions appear. ## Handling Errors When an error occurs during the completion process or requests, Monacopilot will log it to the console by default rather than throwing errors. This ensures smooth editing even when completions are unavailable. You can provide this callback to handle errors yourself, which will disable the default console logging. ```javascript registerCompletion(monaco, editor, { onError: error => { console.error(error); }, }); ``` ## Completion Event Handlers The editor provides several events to handle completion suggestions. These events allow you to respond to different stages of the completion process, such as when a suggestion is shown or accepted by the user. ### `onCompletionShown` This event is triggered when a completion suggestion is shown to the user. You can use this event to log or perform actions when a suggestion is displayed. ```javascript registerCompletion(monaco, editor, { // ... other options onCompletionShown: (completion, range) => { console.log('Completion suggestion:', {completion, range}); }, }); ``` **Parameters:** * `completion`: The completion text that is being shown * `range`: The editor range object where the completion will be inserted ### `onCompletionAccepted` Event triggered when a completion suggestion is accepted by the user. ```javascript registerCompletion(monaco, editor, { // ... other options onCompletionAccepted: () => { console.log('Completion accepted'); }, }); ``` ### `onCompletionRejected` Event triggered when a completion suggestion is rejected by the user. ```javascript registerCompletion(monaco, editor, { // ... other options onCompletionRejected: () => { console.log('Completion rejected'); }, }); ``` ### `onCompletionRequested` Event triggered when a completion is requested, before it is fetched. This allows you to track when completion requests are initiated and access the request parameters. ```javascript registerCompletion(monaco, editor, { // ... other options onCompletionRequested: params => { console.log('Completion requested:', { endpoint: params.endpoint, metadata: params.body.completionMetadata, }); }, }); ``` **Parameters:** * `params`: An object containing: * `endpoint`: The endpoint where the completion request will be sent * `body`: The request body containing completion metadata ### `onCompletionRequestFinished` Event triggered when a completion request has received a response. This allows you to access both the request parameters and the response received. ```javascript registerCompletion(monaco, editor, { // ... other options onCompletionRequestFinished: (params, response) => { console.log('Completion request finished:', { endpoint: params.endpoint, metadata: params.body.completionMetadata, completion: response.completion }); }, }); ``` **Parameters:** * `params`: The parameters that were used for the completion request, including the endpoint and request body * `response`: The response from the completion request, which includes the completion text ## Conditional Completion Triggering Control when completions are triggered based on custom conditions using the `triggerIf` option. ```javascript registerCompletion(monaco, editor, { // ... other options triggerIf: ({text, position, triggerType}) => { // Only trigger completions when cursor is at the beginning of a line return position.column === 1; }, }); ``` The `triggerIf` function receives: * `text`: The current text in the editor * `position`: The current cursor position * `triggerType`: The type of trigger that initiated the completion ('onIdle', 'onTyping', or 'onDemand') Return `true` to allow the completion or `false` to prevent it. --- --- url: /examples/remix.md --- # Remix Learn how to integrate Monacopilot with Remix. ## Installation First, install the required dependencies: ::: code-group ```bash [npm] npm install monacopilot @monaco-editor/react ``` ```bash [yarn] yarn add monacopilot @monaco-editor/react ``` ```bash [pnpm] pnpm add monacopilot @monaco-editor/react ``` ```bash [bun] bun add monacopilot @monaco-editor/react ``` ::: ## Implementation ### API Route Create a route handler for completions: ```tsx [app/routes/code-completion.tsx] import {json, type ActionFunctionArgs} from '@remix-run/node'; import {CompletionCopilot, type CompletionRequestBody} from 'monacopilot'; const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); export const action = async ({request}: ActionFunctionArgs) => { const body: CompletionRequestBody = await request.json(); const completion = await copilot.complete({body}); return json(completion); }; ``` ### Editor Component Create a Editor component in: ```tsx [app/components/Editor.tsx] import {useEffect, useRef} from 'react'; import MonacoEditor from '@monaco-editor/react'; import { registerCompletion, type CompletionRegistration, type Monaco, type StandaloneCodeEditor, } from 'monacopilot'; export default function Editor() { const completionRef = useRef(null); const handleMount = (editor: StandaloneCodeEditor, monaco: Monaco) => { completionRef.current = registerCompletion(monaco, editor, { endpoint: '/code-completion', language: 'javascript', }); }; useEffect(() => { return () => { completionRef.current?.deregister(); }; }, []); return ; } ``` ### Page Component Create your page component: ```tsx [app/routes/_index.tsx] import Editor from '~/components/Editor'; export default function Index() { return (

Monacopilot Remix Example

); } ``` ### Environment Variables Create a `.env` file in your project root: ```bash [.env] MISTRAL_API_KEY=your_mistral_api_key_here ``` Obtain your Mistral API Key from the [Mistral AI Console](https://console.mistral.ai/api-keys). Monacopilot supports multiple AI providers and models. For details on available options and configuration, see the [Changing the Provider and Model](/configuration/copilot-options#changing-the-provider-and-model) documentation. Obtain your Mistral API Key from the [Mistral AI Console](https://console.mistral.ai/api-keys). ## Running the Example 1. Install dependencies: ::: code-group ```bash [npm] npm install ``` ```bash [yarn] yarn ``` ```bash [pnpm] pnpm install ``` ```bash [bun] bun install ``` ::: 2. Start the development server: ::: code-group ```bash [npm] npm run dev ``` ```bash [yarn] yarn dev ``` ```bash [pnpm] pnpm dev ``` ```bash [bun] bun dev ``` ::: 3. Open `http://localhost:3000` in your browser. You should now see a Monaco Editor with AI-powered completions working! --- --- url: /examples/sveltekit.md --- # SvelteKit Learn how to integrate Monacopilot with SvelteKit. ## Installation First, install the required dependencies in your SvelteKit project: ::: code-group ```bash [npm] npm install monacopilot @monaco-editor/loader monaco-editor ``` ```bash [yarn] yarn add monacopilot @monaco-editor/loader monaco-editor ``` ```bash [pnpm] pnpm add monacopilot @monaco-editor/loader monaco-editor ``` ```bash [bun] bun add monacopilot @monaco-editor/loader monaco-editor ``` ::: These packages include: * `monacopilot`: Provides AI-powered code completions. * `@monaco-editor/loader`: Loads the Monaco Editor using the loader method. * `monaco-editor`: The core Monaco Editor library. ## Implementation ### API Route Create an API route to handle code completion requests from Monacopilot. In SvelteKit, API routes are defined in the `src/routes` directory using `+server.ts` files. Create a file at `src/routes/api/code-completion/+server.ts`: ```typescript [src/routes/api/code-completion/+server.ts] import {json} from '@sveltejs/kit'; import type {RequestHandler} from '@sveltejs/kit'; import {MISTRAL_API_KEY} from '$env/static/private'; import {CompletionCopilot, type CompletionRequestBody} from 'monacopilot'; const copilot = new CompletionCopilot(MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); export const POST: RequestHandler = async ({request}) => { const body: CompletionRequestBody = await request.json(); const completion = await copilot.complete({body}); return json(completion); }; ``` Ensure that `MISTRAL_API_KEY` is set in your environment variables (see the Environment Variables section below). ### Editor Component Create a Svelte component to integrate the Monaco Editor with Monacopilot: ```html [src/lib/components/Editor.svelte]
``` This component: * Uses `@monaco-editor/loader` to load the Monaco Editor dynamically. * Creates an editor instance with an initial JavaScript code snippet. * Registers Monacopilot's completion provider, pointing to the `/api/code-completion` endpoint. * Cleans up resources when the component is destroyed to prevent memory leaks. ### Page Component Use the Editor component in a SvelteKit page. Create or modify `src/routes/+page.svelte`: ```html [src/routes/+page.svelte]

Monacopilot SvelteKit Example

``` ### Environment Variables Create a `.env` file in your project root: ```bash [.env] MISTRAL_API_KEY=your_mistral_api_key_here ``` Obtain your Mistral API key from the [Mistral AI Console](https://console.mistral.ai/api-keys). Monacopilot supports multiple AI providers and models. For details on available options and configuration, see the [Changing the Provider and Model](/configuration/copilot-options#changing-the-provider-and-model) documentation. ## Running the Example 1. Install dependencies: ::: code-group ```bash [npm] npm install ``` ```bash [yarn] yarn ``` ```bash [pnpm] pnpm install ``` ```bash [bun] bun install ``` ::: 2. Start the development server: ::: code-group ```bash [npm] npm run dev ``` ```bash [yarn] yarn dev ``` ```bash [pnpm] pnpm run dev ``` ```bash [bun] bun dev ``` ::: 3. Open `http://localhost:5173` (or the port specified in your terminal) in your browser. You should now see a Monaco Editor with AI-powered code completions powered by Monacopilot! --- --- url: /examples/tanstack-start.md --- # TanStack Start Learn how to integrate Monacopilot with TanStack Start. ## Installation First, install the required dependencies: ::: code-group ```bash [npm] npm install monacopilot @monaco-editor/react ``` ```bash [yarn] yarn add monacopilot @monaco-editor/react ``` ```bash [pnpm] pnpm add monacopilot @monaco-editor/react ``` ```bash [bun] bun add monacopilot @monaco-editor/react ``` ::: ## Implementation ### API Route First, create an API route to handle completion requests. In TanStack Start, we'll create this in your `src/routes/api` directory: ```ts [src/routes/api/code-completion.ts] import { createServerFileRoute } from '@tanstack/react-start/server' import { json } from '@tanstack/react-start' import { CompletionCopilot, type CompletionRequestBody } from 'monacopilot' const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); export const ServerRoute = createServerFileRoute('/api/code-completion') .methods({ POST: async ({ request }) => { const body: CompletionRequestBody = await request.json(); const completion = await copilot.complete({ body, }); return json(completion); }, }); ``` ### Editor Component Create an Editor component: ```tsx [components/Editor.tsx] import { useEffect, useRef } from 'react' import MonacoEditor from '@monaco-editor/react' import { registerCompletion, type CompletionRegistration, type Monaco, type StandaloneCodeEditor, } from 'monacopilot' export default function Editor() { const completionRef = useRef(null) const handleMount = (editor: StandaloneCodeEditor, monaco: Monaco) => { completionRef.current = registerCompletion(monaco, editor, { endpoint: '/api/code-completion', language: 'javascript', }) } useEffect(() => { return () => { completionRef.current?.deregister() } }, []) return ( ) } ``` ### Page Component Use the Editor component anywhere in your app, in this case we'll use it in the home page. ```tsx [src/routes/index.tsx] import { createFileRoute } from '@tanstack/react-router' import Editor from '~/components/Editor' export const Route = createFileRoute('/')({ component: Home, }) function Home() { return (

Monacopilot TanStack Start Example

) } ``` ### Environment Variables Create a `.env.local` file in your project root: ```bash [.env.local] MISTRAL_API_KEY=your_mistral_api_key_here ``` Obtain your Mistral API Key from the [Mistral AI Console](https://console.mistral.ai/api-keys). Monacopilot supports multiple AI providers and models. For details on available options and configuration, see the [Changing the Provider and Model](/configuration/copilot-options#changing-the-provider-and-model) documentation. ## Running the Example 1. Install dependencies: ::: code-group ```bash [npm] npm install ``` ```bash [yarn] yarn ``` ```bash [pnpm] pnpm install ``` ```bash [bun] bun install ``` ::: 2. Start the development server: ::: code-group ```bash [npm] npm run dev ``` ```bash [yarn] yarn dev ``` ```bash [pnpm] pnpm dev ``` ```bash [bun] bun dev ``` ::: 3. Open your browser and navigate to `http://localhost:3000`. You should see the editor with AI auto-completions. --- --- url: /guides/upgrade-to-v1.md --- ::: info This guide is for those who have already installed and are using monacopilot with a version older than v1 and want to upgrade to monacopilot's stable new major v1 release. For newcomers, you can skip this. ::: # Upgrading to Monacopilot `v1.0.0` With the release of v1.0.0, Monacopilot now delivers faster, more accurate code completions powered by Mistral's Codestral model. This guide will help you quickly update your existing implementation. ## Breaking Changes * **Provider Optimization**: Previous general-purpose chat models have been replaced with Mistral's specialized `codestral` model, which is specifically designed for code completion. This model leverages Fill-in-the-Middle (FIM) technology to deliver significantly faster and super accurate completions. * **Enhanced Customization API**: The interfaces for custom prompts and custom models have been completely redesigned to provide more flexibility and better performance. These changes enable more sophisticated integrations while maintaining a clean developer experience. ## Update Steps ### 1. Update your dependencies ```bash npm install monacopilot@1.0.0 ``` ### 2. Update your server-side code Replace your existing CompletionCopilot configuration: ```javascript // Before const copilot = new CompletionCopilot(process.env.OPENAI_API_KEY, { provider: 'openai', model: 'gpt-4o', }); // After const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); ``` For more information about available providers and models, see the [Copilot Options](/configuration/copilot-options) documentation. ### 3. Update your environment variables Create or update your API key: ``` # Before OPENAI_API_KEY=your_openai_api_key_here # After MISTRAL_API_KEY=your_mistral_api_key_here ``` You can obtain a Mistral API key from the [Mistral AI Console](https://console.mistral.ai/api-keys). ### 4. Update Custom Prompt Implementation (If Used) If you use the custom prompt feature, the interface has changed: ```javascript // Before copilot.complete({ options: { customPrompt: metadata => ({ system: 'Your custom system prompt here', user: 'Your custom user prompt here', }), }, }); // After copilot.complete({ options: { customPrompt: metadata => ({ context: 'Information about the codebase context', instruction: 'Instructions for code completion', fileContent: 'File content with cursor position', }), }, }); ``` For detailed information about the new custom prompt format, see the [Custom Prompt API](/advanced/custom-prompt) documentation. ### 5. Update Custom Model Integration (If Used) If you use a custom model configuration, update to the new interface: ```javascript // Before const copilot = new CompletionCopilot(API_KEY, { model: { config: (apiKey, prompt) => ({ endpoint: 'https://your-api-endpoint.com', body: { inputs: prompt.user, // other parameters }, // headers }), transformResponse: response => ({text: response.generated_text}), }, }); // After const copilot = new CompletionCopilot(API_KEY, { model: { config: (apiKey, prompt) => ({ endpoint: 'https://your-api-endpoint.com', body: { // The prompt now has context, instruction, and fileContent inputs: `${prompt.context}\n\n${prompt.instruction}\n\n${prompt.fileContent}`, // other parameters }, // headers }), transformResponse: response => ({text: response.generated_text}), }, }); ``` For complete details on implementing custom models, see the [Custom Model Integration](/advanced/custom-model) documentation. --- --- url: /examples/vanilla-js.md --- # Vanilla JavaScript This guide demonstrates how to integrate Monacopilot with a vanilla JavaScript project without any framework or build tool. ### Project Structure ``` project/ ├── index.html # Main HTML file with the Monaco Editor ├── app.js # Frontend JavaScript to initialize editor and Monacopilot ├── server.js # Backend server to handle code completion requests ├── .env # Environment variables for API keys └── package.json # Project dependencies ``` ## Implementation Steps #### Create HTML File Create the main HTML structure that loads Monaco Editor and Monacopilot: ```html [index.html] Monacopilot Example
``` #### Create Frontend Code Initialize Monaco Editor and register Monacopilot for code completions: ```javascript [app.js] require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.55.1/min/vs', }, }); require(['vs/editor/editor.main'], function () { const editor = monaco.editor.create(document.getElementById('editor'), { value: '// Start coding...\n', language: 'javascript', theme: 'vs-dark', }); const completion = monacopilot.registerCompletion(monaco, editor, { language: 'javascript', // URL to the API endpoint we'll create in server.js below endpoint: 'http://localhost:3000/code-completion', }); window.addEventListener('beforeunload', () => { completion.deregister(); }); }); ``` #### Create Backend Server Implement an API handler to process completion requests from the editor: ```typescript [server.js] require('dotenv').config(); const cors = require('cors'); const express = require('express'); const {CompletionCopilot} = require('monacopilot'); const app = express(); app.use(cors()); app.use(express.json()); const copilot = new CompletionCopilot(process.env.MISTRAL_API_KEY, { provider: 'mistral', model: 'codestral', }); app.post('/code-completion', async (req, res) => { const completion = await copilot.complete({body: req.body}); res.json(completion); }); app.listen(process.env.PORT || 3000, () => { console.log(`Server is running on port ${process.env.PORT || 3000}`); }); ``` ::: info You can use any backend framework or programming language for your API handler, as long as it can receive HTTP requests and return JSON responses. For non-JavaScript implementations, see the [Cross-Language API Handler](/advanced/cross-language) Implementation documentation. ::: #### Set Environment Variables Configure your API keys: ```bash [.env] MISTRAL_API_KEY=your_api_key_here ``` Obtain your Mistral API Key from the [Mistral AI Console](https://console.mistral.ai/api-keys). Monacopilot supports multiple AI providers and models. For details on available options and configuration, see the [Changing the Provider and Model](/configuration/copilot-options.html#changing-the-provider-and-model) documentation. ## Installation and Setup Install the required dependencies: ```bash npm init -y npm install express cors monacopilot dotenv ``` ### Running the Application 1. Start the backend server: ```bash node server.js ``` 2. Open `index.html` in a browser or serve it using a local server: ```bash npx serve ``` ## Production Considerations * Update the endpoint URL in `app.js` to point to your production API URL when deploying to production