monacopilot 0.10.9 → 0.10.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -26
- package/build/index.d.mts +24 -41
- package/build/index.d.ts +24 -41
- package/build/index.js +15 -14
- package/build/index.mjs +16 -15
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -25,13 +25,15 @@
|
|
|
25
25
|
- [Filename](#filename)
|
|
26
26
|
- [Completions for Specific Technologies](#completions-for-specific-technologies)
|
|
27
27
|
- [Max Context Lines](#max-context-lines)
|
|
28
|
+
- [Handling Errors](#handling-errors)
|
|
29
|
+
- [Request Options](#request-options)
|
|
30
|
+
- [Custom Headers](#custom-headers)
|
|
28
31
|
- [Copilot Options](#copilot-options)
|
|
29
32
|
- [Changing the Provider and Model](#changing-the-provider-and-model)
|
|
30
|
-
- [Updating Provider and Model at Runtime](#updating-provider-and-model-at-runtime)
|
|
31
33
|
- [Custom Model](#custom-model)
|
|
32
34
|
- [Completion Request Options](#completion-request-options)
|
|
33
|
-
- [Custom Headers](#custom-headers)
|
|
34
|
-
|
|
35
|
+
- [Custom Headers for AI Model Requests](#custom-headers-for-ai-model-requests)
|
|
36
|
+
- [Using a Different Language for the API Handler](#using-a-different-language-for-the-api-handler)
|
|
35
37
|
- [Select and Edit](#select-and-edit)
|
|
36
38
|
- [Contributing](#contributing)
|
|
37
39
|
|
|
@@ -84,6 +86,8 @@ app.post('/complete', async (req, res) => {
|
|
|
84
86
|
app.listen(port);
|
|
85
87
|
```
|
|
86
88
|
|
|
89
|
+
If you prefer to use a different programming language for your API handler in cases where your backend is not in JavaScript, please refer to the section [Using a Different Language for the API Handler](#using-a-different-language-for-the-api-handler) for guidance on implementing the handler in your chosen language.
|
|
90
|
+
|
|
87
91
|
Now, Monacopilot is set up to send completion requests to the `/complete` endpoint and receive completions in response.
|
|
88
92
|
|
|
89
93
|
The `copilot.complete` method processes the request body sent by Monacopilot and returns the corresponding completion.
|
|
@@ -253,6 +257,39 @@ registerCompletion(monaco, editor, {
|
|
|
253
257
|
|
|
254
258
|
> **Note:** If you're using `Groq` as your provider, it's recommended to set `maxContextLines` to `60` or less due to its low rate limits and lack of pay-as-you-go pricing. However, `Groq` is expected to offer pay-as-you-go pricing in the near future.
|
|
255
259
|
|
|
260
|
+
### Request Options
|
|
261
|
+
|
|
262
|
+
You can customize the `fetch` request made by Monacopilot to the specified endpoint by using the `requestOptions` parameter in the `registerCompletion` function.
|
|
263
|
+
|
|
264
|
+
#### Custom Headers
|
|
265
|
+
|
|
266
|
+
You can include custom headers in the requests sent to the endpoint specified in the `registerCompletion` function.
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
registerCompletion(monaco, editor, {
|
|
270
|
+
endpoint: 'https://api.example.com/complete',
|
|
271
|
+
requestOptions: {
|
|
272
|
+
headers: {
|
|
273
|
+
'X-Custom-Header': 'custom-value',
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Handling Errors
|
|
280
|
+
|
|
281
|
+
You can handle errors that occur during completion requests by providing an `onError` function when calling `registerCompletion`. This allows you to customize error handling and logging based on your application's needs.
|
|
282
|
+
|
|
283
|
+
This will disable the default error handling and logging behavior of Monacopilot.
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
registerCompletion(monaco, editor, {
|
|
287
|
+
onError: error => {
|
|
288
|
+
console.error(error);
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
256
293
|
## Copilot Options
|
|
257
294
|
|
|
258
295
|
### Changing the Provider and Model
|
|
@@ -276,17 +313,6 @@ There are other providers and models available. Here is a list:
|
|
|
276
313
|
| OpenAI | `gpt-4o`, `gpt-4o-mini`, `o1-preview`, `o1-mini` |
|
|
277
314
|
| Anthropic | `claude-3.5-Sonnet`, `claude-3-opus`, `claude-3-sonnet`, `claude-3-haiku` |
|
|
278
315
|
|
|
279
|
-
#### Updating Provider and Model at Runtime
|
|
280
|
-
|
|
281
|
-
You can change the provider and model at runtime using the `setModel` method.
|
|
282
|
-
|
|
283
|
-
```javascript
|
|
284
|
-
copilot.setModel({
|
|
285
|
-
provider: 'anthropic',
|
|
286
|
-
model: 'claude-3-haiku',
|
|
287
|
-
});
|
|
288
|
-
```
|
|
289
|
-
|
|
290
316
|
### Custom Model
|
|
291
317
|
|
|
292
318
|
You can use a custom AI model that isn't built into Monacopilot by setting up a `model` when you create a new Copilot. This feature lets you connect to AI models from other services or your own custom-built models.
|
|
@@ -342,7 +368,7 @@ The `transformResponse` function must return an object with the `text` property.
|
|
|
342
368
|
|
|
343
369
|
## Completion Request Options
|
|
344
370
|
|
|
345
|
-
### Custom Headers
|
|
371
|
+
### Custom Headers for AI Model Requests
|
|
346
372
|
|
|
347
373
|
You can add custom headers to the provider's completion requests. For example, if you select `OpenAI` as your provider, you can add a custom header to the OpenAI completion requests made by Monacopilot.
|
|
348
374
|
|
|
@@ -390,16 +416,18 @@ copilot.complete({
|
|
|
390
416
|
|
|
391
417
|
The `customPrompt` function receives a `completionMetadata` object, which contains information about the current editor state and can be used to tailor the prompt.
|
|
392
418
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
|
396
|
-
|
|
|
397
|
-
| `
|
|
398
|
-
| `
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
401
|
-
| `
|
|
402
|
-
| `
|
|
419
|
+
##### Completion Metadata
|
|
420
|
+
|
|
421
|
+
| Property | Type | Description |
|
|
422
|
+
| ------------------ | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
423
|
+
| `language` | `string` | The programming language of the code. |
|
|
424
|
+
| `cursorPosition` | `{ lineNumber: number; column: number }` | The current cursor position in the editor. |
|
|
425
|
+
| `filename` | `string` or `undefined` | The name of the file being edited. Only available if you have provided the `filename` option in the `registerCompletion` function. |
|
|
426
|
+
| `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. |
|
|
427
|
+
| `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. |
|
|
428
|
+
| `textAfterCursor` | `string` | The text that appears after the cursor. |
|
|
429
|
+
| `textBeforeCursor` | `string` | The text that appears before the cursor. |
|
|
430
|
+
| `editorState` | `object` | An object containing the `completionMode` property. |
|
|
403
431
|
|
|
404
432
|
The `editorState.completionMode` can be one of the following:
|
|
405
433
|
|
|
@@ -432,7 +460,7 @@ const customPrompt = ({textBeforeCursor, textAfterCursor}) => ({
|
|
|
432
460
|
// Cursor position
|
|
433
461
|
${textAfterCursor}
|
|
434
462
|
|
|
435
|
-
Use modern React practices and hooks where appropriate. If you're adding new props, make sure to include proper TypeScript types. Please provide only the
|
|
463
|
+
Use modern React practices and hooks where appropriate. If you're adding new props, make sure to include proper TypeScript types. Please provide only the completed part of the code without additional comments or explanations.`,
|
|
436
464
|
});
|
|
437
465
|
|
|
438
466
|
copilot.complete({
|
|
@@ -442,6 +470,89 @@ copilot.complete({
|
|
|
442
470
|
|
|
443
471
|
By using a custom prompt, you can guide the model to generate completions that better fit your coding style, project requirements, or specific technologies you're working with.
|
|
444
472
|
|
|
473
|
+
## Using a Different Language for the API Handler
|
|
474
|
+
|
|
475
|
+
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. Here's a general approach to implement the handler in your preferred language:
|
|
476
|
+
|
|
477
|
+
1. Create an endpoint that accepts POST requests (e.g., `/complete`).
|
|
478
|
+
2. The endpoint should expect a JSON body containing completion metadata.
|
|
479
|
+
3. Use the metadata to construct a prompt for your AI model.
|
|
480
|
+
4. Send the prompt to your chosen AI model and get the completion.
|
|
481
|
+
5. Return a JSON response with the following structure:
|
|
482
|
+
|
|
483
|
+
```json
|
|
484
|
+
{
|
|
485
|
+
"completion": "Generated completion text"
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Or in case of an error:
|
|
490
|
+
|
|
491
|
+
```json
|
|
492
|
+
{
|
|
493
|
+
"completion": null,
|
|
494
|
+
"error": "Error message"
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Key Considerations
|
|
499
|
+
|
|
500
|
+
- The prompt should instruct the model to return only the completion text, without any additional formatting or explanations.
|
|
501
|
+
- The completion text should be ready for direct insertion into the editor.
|
|
502
|
+
|
|
503
|
+
Check out the [prompt.ts](https://github.com/arshad-yaseen/monacopilot/blob/main/src/helpers/completion/prompt.ts) file to see how Monacopilot generates the prompt. This will give you an idea of how to structure the prompt for your AI model to achieve the best completions.
|
|
504
|
+
|
|
505
|
+
### Metadata Overview
|
|
506
|
+
|
|
507
|
+
The request body's `completionMetadata` object contains essential information for crafting a prompt for the AI model to generate accurate completions. See the [Completion Metadata](#completion-metadata) section for more details.
|
|
508
|
+
|
|
509
|
+
### Example Implementation (Python with FastAPI)
|
|
510
|
+
|
|
511
|
+
Here's a basic example using Python and FastAPI:
|
|
512
|
+
|
|
513
|
+
```python
|
|
514
|
+
from fastapi import FastAPI, Request
|
|
515
|
+
|
|
516
|
+
app = FastAPI()
|
|
517
|
+
|
|
518
|
+
@app.post('/complete')
|
|
519
|
+
async def handle_completion(request: Request):
|
|
520
|
+
try:
|
|
521
|
+
body = await request.json()
|
|
522
|
+
metadata = body['completionMetadata']
|
|
523
|
+
|
|
524
|
+
prompt = f"""Please complete the following {metadata['language']} code:
|
|
525
|
+
|
|
526
|
+
{metadata['textBeforeCursor']}
|
|
527
|
+
<cursor>
|
|
528
|
+
{metadata['textAfterCursor']}
|
|
529
|
+
|
|
530
|
+
Use modern {metadata['language']} practices and hooks where appropriate. Please provide only the completed part of the
|
|
531
|
+
code without additional comments or explanations."""
|
|
532
|
+
|
|
533
|
+
# Simulate a response from a model
|
|
534
|
+
response = "Your model's response here"
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
'completion': response,
|
|
538
|
+
'error': None
|
|
539
|
+
}
|
|
540
|
+
except Exception as e:
|
|
541
|
+
return {
|
|
542
|
+
'completion': None,
|
|
543
|
+
'error': str(e)
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Now, Monacopilot is set up to send completion requests to the `/complete` endpoint and receive completions in response.
|
|
548
|
+
|
|
549
|
+
```javascript
|
|
550
|
+
registerCompletion(monaco, editor, {
|
|
551
|
+
endpoint: 'https://my-python-api.com/complete',
|
|
552
|
+
// ... other options
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
445
556
|
## Select and Edit
|
|
446
557
|
|
|
447
558
|
Select and Edit is a feature that allows you to select code from the editor and edit it inline with AI assistance.
|
package/build/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
2
|
+
import * as monaco_editor from 'monaco-editor';
|
|
2
3
|
|
|
3
4
|
type OpenAIModel = 'gpt-4o' | 'gpt-4o-mini' | 'o1-preview' | 'o1-mini';
|
|
4
5
|
type GroqModel = 'llama-3-70b';
|
|
@@ -54,20 +55,6 @@ type CustomCopilotModel = {
|
|
|
54
55
|
*/
|
|
55
56
|
transformResponse: CustomCopilotModelTransformResponse;
|
|
56
57
|
};
|
|
57
|
-
type SetModelOptions = {
|
|
58
|
-
/**
|
|
59
|
-
* The provider to set (e.g., 'openai', 'anthropic', 'groq').
|
|
60
|
-
*/
|
|
61
|
-
provider: CopilotProvider;
|
|
62
|
-
/**
|
|
63
|
-
* The model to use for copilot AI requests.
|
|
64
|
-
* This can be either:
|
|
65
|
-
* 1. A predefined model name (e.g. 'claude-3-opus'): Use this option if you want to use a model that is built into Monacopilot.
|
|
66
|
-
* If you choose this option, also set the `provider` property to the corresponding provider of the model.
|
|
67
|
-
* 2. A custom model configuration object: Use this option if you want to use a AI model from a third-party service or your own custom model.
|
|
68
|
-
*/
|
|
69
|
-
model: CopilotModel | CustomCopilotModel;
|
|
70
|
-
};
|
|
71
58
|
type CustomCopilotModelConfig = (apiKey: string, prompt: {
|
|
72
59
|
system: string;
|
|
73
60
|
user: string;
|
|
@@ -92,7 +79,6 @@ type CustomCopilotModelTransformResponse = (response: unknown) => {
|
|
|
92
79
|
*/
|
|
93
80
|
text: string | null;
|
|
94
81
|
/**
|
|
95
|
-
* The text generated by the custom model.
|
|
96
82
|
* @deprecated Use `text` instead. This property will be removed in a future version.
|
|
97
83
|
*/
|
|
98
84
|
completion: string | null;
|
|
@@ -158,11 +144,6 @@ interface RegisterCompletionOptions {
|
|
|
158
144
|
* etc.
|
|
159
145
|
*/
|
|
160
146
|
technologies?: Technologies;
|
|
161
|
-
/**
|
|
162
|
-
* @deprecated
|
|
163
|
-
* Use `relatedFiles` instead.
|
|
164
|
-
*/
|
|
165
|
-
externalContext?: RelatedFile[];
|
|
166
147
|
/**
|
|
167
148
|
* Helps to give more relevant completions based on the full context.
|
|
168
149
|
* You can include things like the contents/codes of other files in the same workspace.
|
|
@@ -177,6 +158,22 @@ interface RegisterCompletionOptions {
|
|
|
177
158
|
* since `Groq` does not implement pay-as-you-go pricing and has only low rate limits.
|
|
178
159
|
*/
|
|
179
160
|
maxContextLines?: number;
|
|
161
|
+
/**
|
|
162
|
+
* Additional options to include in the request sent to the endpoint specified in the `registerCompletion` function.
|
|
163
|
+
*/
|
|
164
|
+
requestOptions?: RegisterCompletionRequestOptions;
|
|
165
|
+
/**
|
|
166
|
+
* Callback function that is called when an error occurs during the completion request.
|
|
167
|
+
* This function allows you to handle errors gracefully and provide appropriate feedback to the user.
|
|
168
|
+
* @param error - The error object containing information about the encountered error.
|
|
169
|
+
*/
|
|
170
|
+
onError?: (error: Error) => void;
|
|
171
|
+
}
|
|
172
|
+
interface RegisterCompletionRequestOptions {
|
|
173
|
+
/**
|
|
174
|
+
* Custom headers to include in the request sent to the endpoint specified in the `registerCompletion` function.
|
|
175
|
+
*/
|
|
176
|
+
headers?: Record<string, string>;
|
|
180
177
|
}
|
|
181
178
|
interface CompletionRegistration {
|
|
182
179
|
/**
|
|
@@ -207,7 +204,7 @@ interface CompletionRequestBody {
|
|
|
207
204
|
}
|
|
208
205
|
interface CompletionRequestOptions {
|
|
209
206
|
/**
|
|
210
|
-
*
|
|
207
|
+
* Custom headers to include in the request to the AI provider.
|
|
211
208
|
*/
|
|
212
209
|
headers?: Record<string, string>;
|
|
213
210
|
/**
|
|
@@ -272,28 +269,14 @@ declare class Copilot {
|
|
|
272
269
|
private readonly apiKey;
|
|
273
270
|
private provider;
|
|
274
271
|
private model;
|
|
275
|
-
/**
|
|
276
|
-
* Initializes the Copilot instance with an API key and optional configuration.
|
|
277
|
-
* @param apiKey - The API key for the chosen provider.
|
|
278
|
-
* @param options - Optional configuration for the Copilot instance.
|
|
279
|
-
*/
|
|
280
272
|
constructor(apiKey: string, options?: CopilotOptions);
|
|
281
|
-
/**
|
|
282
|
-
* Validates the inputs provided to the constructor.
|
|
283
|
-
* Ensures the selected model is supported by the provider.
|
|
284
|
-
*/
|
|
285
273
|
private validateInputs;
|
|
286
|
-
/**
|
|
287
|
-
* Sends a completion request to the API and returns the completion.
|
|
288
|
-
* @param request - The completion request containing the body and options.
|
|
289
|
-
* @returns A promise resolving to the completion response or an error.
|
|
290
|
-
*/
|
|
291
274
|
complete(request: CompletionRequest): Promise<CompletionResponse>;
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
275
|
+
private generatePrompt;
|
|
276
|
+
private prepareRequestDetails;
|
|
277
|
+
private sendCompletionRequest;
|
|
278
|
+
private processCompletionResponse;
|
|
279
|
+
private handleCompletionError;
|
|
297
280
|
}
|
|
298
281
|
|
|
299
282
|
/**
|
|
@@ -307,6 +290,6 @@ declare const registerCompletion: (monaco: Monaco, editor: StandaloneCodeEditor,
|
|
|
307
290
|
/**
|
|
308
291
|
* @deprecated Use `registerCompletion` instead. This function will be removed in a future version.
|
|
309
292
|
*/
|
|
310
|
-
declare const registerCopilot: (monaco:
|
|
293
|
+
declare const registerCopilot: (monaco: typeof monaco_editor, editor: monaco_editor.editor.IStandaloneCodeEditor, options: RegisterCompletionOptions) => CompletionRegistration;
|
|
311
294
|
|
|
312
295
|
export { type CompletionMetadata, type CompletionRegistration, type CompletionRequest, type CompletionRequestBody, type CompletionRequestOptions, Copilot, type CopilotModel, type CopilotOptions, type CopilotProvider, type CustomCopilotModel, type CustomCopilotModelConfig, type CustomCopilotModelTransformResponse, type Monaco, type RegisterCompletionOptions, type StandaloneCodeEditor, registerCompletion, registerCopilot };
|
package/build/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
|
2
|
+
import * as monaco_editor from 'monaco-editor';
|
|
2
3
|
|
|
3
4
|
type OpenAIModel = 'gpt-4o' | 'gpt-4o-mini' | 'o1-preview' | 'o1-mini';
|
|
4
5
|
type GroqModel = 'llama-3-70b';
|
|
@@ -54,20 +55,6 @@ type CustomCopilotModel = {
|
|
|
54
55
|
*/
|
|
55
56
|
transformResponse: CustomCopilotModelTransformResponse;
|
|
56
57
|
};
|
|
57
|
-
type SetModelOptions = {
|
|
58
|
-
/**
|
|
59
|
-
* The provider to set (e.g., 'openai', 'anthropic', 'groq').
|
|
60
|
-
*/
|
|
61
|
-
provider: CopilotProvider;
|
|
62
|
-
/**
|
|
63
|
-
* The model to use for copilot AI requests.
|
|
64
|
-
* This can be either:
|
|
65
|
-
* 1. A predefined model name (e.g. 'claude-3-opus'): Use this option if you want to use a model that is built into Monacopilot.
|
|
66
|
-
* If you choose this option, also set the `provider` property to the corresponding provider of the model.
|
|
67
|
-
* 2. A custom model configuration object: Use this option if you want to use a AI model from a third-party service or your own custom model.
|
|
68
|
-
*/
|
|
69
|
-
model: CopilotModel | CustomCopilotModel;
|
|
70
|
-
};
|
|
71
58
|
type CustomCopilotModelConfig = (apiKey: string, prompt: {
|
|
72
59
|
system: string;
|
|
73
60
|
user: string;
|
|
@@ -92,7 +79,6 @@ type CustomCopilotModelTransformResponse = (response: unknown) => {
|
|
|
92
79
|
*/
|
|
93
80
|
text: string | null;
|
|
94
81
|
/**
|
|
95
|
-
* The text generated by the custom model.
|
|
96
82
|
* @deprecated Use `text` instead. This property will be removed in a future version.
|
|
97
83
|
*/
|
|
98
84
|
completion: string | null;
|
|
@@ -158,11 +144,6 @@ interface RegisterCompletionOptions {
|
|
|
158
144
|
* etc.
|
|
159
145
|
*/
|
|
160
146
|
technologies?: Technologies;
|
|
161
|
-
/**
|
|
162
|
-
* @deprecated
|
|
163
|
-
* Use `relatedFiles` instead.
|
|
164
|
-
*/
|
|
165
|
-
externalContext?: RelatedFile[];
|
|
166
147
|
/**
|
|
167
148
|
* Helps to give more relevant completions based on the full context.
|
|
168
149
|
* You can include things like the contents/codes of other files in the same workspace.
|
|
@@ -177,6 +158,22 @@ interface RegisterCompletionOptions {
|
|
|
177
158
|
* since `Groq` does not implement pay-as-you-go pricing and has only low rate limits.
|
|
178
159
|
*/
|
|
179
160
|
maxContextLines?: number;
|
|
161
|
+
/**
|
|
162
|
+
* Additional options to include in the request sent to the endpoint specified in the `registerCompletion` function.
|
|
163
|
+
*/
|
|
164
|
+
requestOptions?: RegisterCompletionRequestOptions;
|
|
165
|
+
/**
|
|
166
|
+
* Callback function that is called when an error occurs during the completion request.
|
|
167
|
+
* This function allows you to handle errors gracefully and provide appropriate feedback to the user.
|
|
168
|
+
* @param error - The error object containing information about the encountered error.
|
|
169
|
+
*/
|
|
170
|
+
onError?: (error: Error) => void;
|
|
171
|
+
}
|
|
172
|
+
interface RegisterCompletionRequestOptions {
|
|
173
|
+
/**
|
|
174
|
+
* Custom headers to include in the request sent to the endpoint specified in the `registerCompletion` function.
|
|
175
|
+
*/
|
|
176
|
+
headers?: Record<string, string>;
|
|
180
177
|
}
|
|
181
178
|
interface CompletionRegistration {
|
|
182
179
|
/**
|
|
@@ -207,7 +204,7 @@ interface CompletionRequestBody {
|
|
|
207
204
|
}
|
|
208
205
|
interface CompletionRequestOptions {
|
|
209
206
|
/**
|
|
210
|
-
*
|
|
207
|
+
* Custom headers to include in the request to the AI provider.
|
|
211
208
|
*/
|
|
212
209
|
headers?: Record<string, string>;
|
|
213
210
|
/**
|
|
@@ -272,28 +269,14 @@ declare class Copilot {
|
|
|
272
269
|
private readonly apiKey;
|
|
273
270
|
private provider;
|
|
274
271
|
private model;
|
|
275
|
-
/**
|
|
276
|
-
* Initializes the Copilot instance with an API key and optional configuration.
|
|
277
|
-
* @param apiKey - The API key for the chosen provider.
|
|
278
|
-
* @param options - Optional configuration for the Copilot instance.
|
|
279
|
-
*/
|
|
280
272
|
constructor(apiKey: string, options?: CopilotOptions);
|
|
281
|
-
/**
|
|
282
|
-
* Validates the inputs provided to the constructor.
|
|
283
|
-
* Ensures the selected model is supported by the provider.
|
|
284
|
-
*/
|
|
285
273
|
private validateInputs;
|
|
286
|
-
/**
|
|
287
|
-
* Sends a completion request to the API and returns the completion.
|
|
288
|
-
* @param request - The completion request containing the body and options.
|
|
289
|
-
* @returns A promise resolving to the completion response or an error.
|
|
290
|
-
*/
|
|
291
274
|
complete(request: CompletionRequest): Promise<CompletionResponse>;
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
275
|
+
private generatePrompt;
|
|
276
|
+
private prepareRequestDetails;
|
|
277
|
+
private sendCompletionRequest;
|
|
278
|
+
private processCompletionResponse;
|
|
279
|
+
private handleCompletionError;
|
|
297
280
|
}
|
|
298
281
|
|
|
299
282
|
/**
|
|
@@ -307,6 +290,6 @@ declare const registerCompletion: (monaco: Monaco, editor: StandaloneCodeEditor,
|
|
|
307
290
|
/**
|
|
308
291
|
* @deprecated Use `registerCompletion` instead. This function will be removed in a future version.
|
|
309
292
|
*/
|
|
310
|
-
declare const registerCopilot: (monaco:
|
|
293
|
+
declare const registerCopilot: (monaco: typeof monaco_editor, editor: monaco_editor.editor.IStandaloneCodeEditor, options: RegisterCompletionOptions) => CompletionRegistration;
|
|
311
294
|
|
|
312
295
|
export { type CompletionMetadata, type CompletionRegistration, type CompletionRequest, type CompletionRequestBody, type CompletionRequestOptions, Copilot, type CopilotModel, type CopilotOptions, type CopilotProvider, type CustomCopilotModel, type CustomCopilotModelConfig, type CustomCopilotModelTransformResponse, type Monaco, type RegisterCompletionOptions, type StandaloneCodeEditor, registerCompletion, registerCopilot };
|
package/build/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`),n=r.length;if(t>=n)return e;if(o.from==="end"){let
|
|
3
|
-
`.repeat(t):
|
|
4
|
-
`)}let i=r.slice(0,t);return i.every(
|
|
1
|
+
"use strict";var F=Object.defineProperty;var me=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var Ce=Object.prototype.hasOwnProperty;var ge=(e,t)=>{for(var o in t)F(e,o,{get:t[o],enumerable:!0})},he=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ue(t))!Ce.call(e,n)&&n!==o&&F(e,n,{get:()=>t[n],enumerable:!(r=me(t,n))||r.enumerable});return e};var fe=e=>he(F({},"__esModule",{value:!0}),e);var _e={};ge(_e,{Copilot:()=>L,registerCompletion:()=>Y,registerCopilot:()=>ce});module.exports=fe(_e);var _=["groq","openai","anthropic"],G={"llama-3-70b":"llama3-70b-8192","gpt-4o":"gpt-4o-2024-08-06","gpt-4o-mini":"gpt-4o-mini","claude-3.5-sonnet":"claude-3.5-sonnet-20240620","claude-3-opus":"claude-3-opus-20240229","claude-3-sonnet":"claude-3-sonnet-20240229","claude-3-haiku":"claude-3-haiku-20240307","o1-preview":"o1-preview","o1-mini":"o1-mini"},$={groq:["llama-3-70b"],openai:["gpt-4o","gpt-4o-mini","o1-preview","o1-mini"],anthropic:["claude-3.5-sonnet","claude-3-opus","claude-3-haiku","claude-3-sonnet"]},J="llama-3-70b",X="groq",z={groq:"https://api.groq.com/openai/v1/chat/completions",openai:"https://api.openai.com/v1/chat/completions",anthropic:"https://api.anthropic.com/v1/messages"},M=.1;var v=(e,t)=>{let o=null,r=null,n=(...i)=>new Promise((s,a)=>{o&&(clearTimeout(o),r&&r("Cancelled")),r=a,o=setTimeout(()=>{s(e(...i)),r=null},t)});return n.cancel=()=>{o&&(clearTimeout(o),r&&r("Cancelled"),o=null,r=null)},n},x=e=>!e||e.length===0?"":e.length===1?e[0]:`${e.slice(0,-1).join(", ")} and ${e.slice(-1)}`;var H=(e,t)=>t.getLineContent(e.lineNumber)[e.column-1];var b=(e,t)=>t.getLineContent(e.lineNumber).slice(e.column-1),f=(e,t)=>t.getLineContent(e.lineNumber).slice(0,e.column-1),Z=(e,t)=>t.getValueInRange({startLineNumber:1,startColumn:1,endLineNumber:e.lineNumber,endColumn:e.column}),Q=(e,t)=>t.getValueInRange({startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:t.getLineCount(),endColumn:t.getLineMaxColumn(t.getLineCount())}),U=(e,t,o={})=>{if(t<=0)return"";let r=e.split(`
|
|
2
|
+
`),n=r.length;if(t>=n)return e;if(o.from==="end"){let s=r.slice(-t);return s.every(a=>a==="")?`
|
|
3
|
+
`.repeat(t):s.join(`
|
|
4
|
+
`)}let i=r.slice(0,t);return i.every(s=>s==="")?`
|
|
5
5
|
`.repeat(t):i.join(`
|
|
6
|
-
`)};var
|
|
6
|
+
`)};var ee=async(e,t,o={})=>{let r={"Content-Type":"application/json",...o.headers},n=t==="POST"&&o.body?JSON.stringify(o.body):void 0,i=await fetch(e,{method:t,headers:r,body:n,signal:o.signal});if(!i.ok)throw new Error(`${i.statusText||o.fallbackError||"Network error"}`);return i.json()},Pe=(e,t)=>ee(e,"GET",t),Ee=(e,t,o)=>ee(e,"POST",{...o,body:t}),I={GET:Pe,POST:Ee};var te=(e,t)=>{let o=b(e,t).trim(),r=f(e,t).trim();return e.column<=3&&(o!==""||r!=="")};var Re="<user-current-cursor-position-is-here>",ye=e=>e==="javascript"?"JavaScript (ESNext)":e,xe=e=>`You are an expert ${ye(e.language)||x(e.technologies)} developer assistant with extensive experience in code completion and adhering to best coding practices. Your role is to provide precise and contextually relevant code completions without any errors, including syntax, punctuation, spaces, tabs, and line breaks. Focus on integrating seamlessly with the existing code and follow the user's instructions carefully.`,Te=e=>{let{filename:t="/",textBeforeCursor:o="",textAfterCursor:r="",relatedFiles:n,editorState:i}=e,p=`
|
|
7
7
|
<guidelines>
|
|
8
8
|
<instruction>${{continue:"Continue writing the code from where the cursor is positioned.",insert:"Insert the appropriate code snippet at the cursor position.",complete:"Provide the necessary code to complete the current statement or block."}[i.completionMode]}</instruction>
|
|
9
9
|
<steps>
|
|
@@ -17,29 +17,30 @@
|
|
|
17
17
|
<step>Return <strong>only</strong> the code required at the cursor position.</step>
|
|
18
18
|
</steps>
|
|
19
19
|
</guidelines>
|
|
20
|
-
`,
|
|
20
|
+
`,l=`
|
|
21
21
|
<context>
|
|
22
22
|
<current_file path="${t}">
|
|
23
23
|
<code>
|
|
24
|
-
${o}${
|
|
24
|
+
${o}${Re}${r}
|
|
25
25
|
</code>
|
|
26
26
|
</current_file>
|
|
27
27
|
</context>
|
|
28
|
-
`,m=n?.map(({path:
|
|
29
|
-
<related_file path="${
|
|
28
|
+
`,m=n?.map(({path:c,content:u})=>`
|
|
29
|
+
<related_file path="${c}">
|
|
30
30
|
<code>
|
|
31
|
-
${
|
|
31
|
+
${u}
|
|
32
32
|
</code>
|
|
33
33
|
</related_file>
|
|
34
34
|
`).join(`
|
|
35
35
|
`)||"";return`
|
|
36
36
|
<task>
|
|
37
37
|
${p}
|
|
38
|
-
${
|
|
38
|
+
${l}
|
|
39
39
|
${m}
|
|
40
40
|
</task>
|
|
41
|
-
`};function
|
|
41
|
+
`};function V(e){return{system:xe(e),user:Te(e)}}var oe={"claude-3.5-sonnet":8192,"claude-3-opus":4096,"claude-3-haiku":4096,"claude-3-sonnet":4096};var Oe={createRequestBody:(e,t)=>{let r=e==="o1-preview"||e==="o1-mini"?[{role:"user",content:t.user}]:[{role:"system",content:t.system},{role:"user",content:t.user}];return{model:W(e),temperature:M,messages:r}},createHeaders:e=>({"Content-Type":"application/json",Authorization:`Bearer ${e}`}),parseCompletion:e=>e.choices?.length?e.choices[0].message.content:null},Me={createRequestBody:(e,t)=>({model:W(e),temperature:M,messages:[{role:"system",content:t.system},{role:"user",content:t.user}]}),createHeaders:e=>({"Content-Type":"application/json",Authorization:`Bearer ${e}`}),parseCompletion:e=>e.choices?.length?e.choices[0].message.content:null},ve={createRequestBody:(e,t)=>({model:W(e),temperature:M,system:t.system,messages:[{role:"user",content:t.user}],max_tokens:be(e)}),createHeaders:e=>({"Content-Type":"application/json","x-api-key":e,"anthropic-version":"2023-06-01"}),parseCompletion:e=>!e.content||typeof e.content!="string"?null:e.content},j={openai:Oe,groq:Me,anthropic:ve},re=(e,t,o)=>j[t].createRequestBody(e,o),ne=(e,t)=>j[t].createHeaders(e),ie=(e,t)=>j[t].parseCompletion(e),W=e=>G[e],se=e=>z[e],be=e=>oe[e]||4096;var d=class d{constructor(){}static getInstance(){return d.instance}logError(t){let o,r;t instanceof Error?(o=t.message,r=t.stack):typeof t=="string"?o=t:o="An unknown error occurred";let n=`${d.RED}${d.BOLD}[MONACOPILOT ERROR] ${o}${d.RESET}`;return console.error(n),r&&console.error(`${d.RED}[MONACOPILOT ERROR] Stack trace:${d.RESET}
|
|
42
|
+
${r}`),{message:o,stack:r}}warn(t){console.warn(`${d.YELLOW}${d.BOLD}[MONACOPILOT WARN] ${t}${d.RESET}`)}log(t){console.log(`${d.BOLD}[MONACOPILOT] ${t}${d.RESET}`)}};d.instance=new d,d.RED="\x1B[31m",d.YELLOW="\x1B[33m",d.RESET="\x1B[0m",d.BOLD="\x1B[1m";var K=d,g=K.getInstance();var L=class{constructor(t,o={}){if(!t)throw new Error("Please provide an API key.");this.apiKey=t,this.provider=o.provider??X,this.model=o.model??J,this.validateInputs()}validateInputs(){if(!_.includes(this.provider))throw new Error(`Unsupported provider "${this.provider}". Please choose from: ${x(_)}. For custom models, provider specification is not needed.`);if(typeof this.model=="string"&&!$[this.provider].includes(this.model))throw new Error(`Model "${this.model}" is not supported by the "${this.provider}" provider. Supported models: ${x($[this.provider])}`)}async complete(t){let{body:o,options:r}=t,{completionMetadata:n}=o,{headers:i={},customPrompt:s}=r??{},a=this.generatePrompt(n,s),{endpoint:p,requestBody:l,headers:m}=this.prepareRequestDetails(a);try{let c=await this.sendCompletionRequest(p,l,{...m,...i});return this.processCompletionResponse(c)}catch(c){return this.handleCompletionError(c)}}generatePrompt(t,o){let r=V(t);return o?{...r,...o(t)}:r}prepareRequestDetails(t){let o=se(this.provider),r,n=ne(this.apiKey,this.provider);if(typeof this.model=="object"&&"config"in this.model){let i=this.model.config(this.apiKey,t);o=i.endpoint??o,r=i.body??{},n={...n,...i.headers}}else r=re(this.model,this.provider,t);return{endpoint:o,requestBody:r,headers:n}}async sendCompletionRequest(t,o,r){return I.POST(t,o,{headers:r})}processCompletionResponse(t){if(typeof this.model=="object"&&"transformResponse"in this.model){let o=this.model.transformResponse(t);return"completion"in o&&g.warn("The `completion` property in `transformResponse` function is deprecated. Please use `text` instead."),{completion:o.text??o.completion}}else return{completion:ie(t,this.provider)}}handleCompletionError(t){return{error:g.logError(t).message,completion:null}}};var A=class e{constructor(t){this.formattedCompletion="";this.formattedCompletion=t}static create(t){return new e(t)}setCompletion(t){return this.formattedCompletion=t,this}removeInvalidLineBreaks(){return this.formattedCompletion=this.formattedCompletion.trimEnd(),this}removeMarkdownCodeSyntax(){return this.formattedCompletion=this.removeMarkdownCodeBlocks(this.formattedCompletion),this}removeMarkdownCodeBlocks(t){let o=/```[\s\S]*?```/g,r=t,n;for(;(n=o.exec(t))!==null;){let i=n[0],s=i.split(`
|
|
42
43
|
`).slice(1,-1).join(`
|
|
43
|
-
`);r=r.replace(i,
|
|
44
|
+
`);r=r.replace(i,s)}return r.trim()}removeExcessiveNewlines(){return this.formattedCompletion=this.formattedCompletion.replace(/\n{3,}/g,`
|
|
44
45
|
|
|
45
|
-
`),this}build(){return this.formattedCompletion}};var
|
|
46
|
+
`),this}build(){return this.formattedCompletion}};var D=class{constructor(t,o){this.cursorPos=t,this.mdl=o}shouldProvideCompletions(){return!te(this.cursorPos,this.mdl)}};var S=class S{constructor(){this.cache=[]}get(t,o){return this.cache.filter(r=>this.isValidCacheItem(r,t,o))}add(t){let o=[...this.cache.slice(-(S.MAX_CACHE_SIZE-1)),t];this.cache=o}clear(){this.cache=[]}isValidCacheItem(t,o,r){let n=r.getValueInRange(t.range);return f(o,r).startsWith(t.textBeforeCursorInLine)&&this.isPositionValid(t,o,n)}isPositionValid(t,o,r){let{range:n,completion:i}=t,{startLineNumber:s,startColumn:a,endColumn:p}=n,{lineNumber:l,column:m}=o,c=l===s&&m===a,u=i.startsWith(r)&&l===s&&m>=a-r.length&&m<=p+r.length;return c||u}};S.MAX_CACHE_SIZE=10;var N=S;var Ie="application/json",w=async({mdl:e,pos:t,...o})=>{let{endpoint:r,requestOptions:n,onError:i}=o,{headers:s}=n??{};try{let{completion:a,error:p}=await I.POST(r,{completionMetadata:Le({pos:t,mdl:e,options:o})},{headers:{"Content-Type":Ie,...s},fallbackError:"Error while fetching completion item"});if(p)throw new Error(p);return a}catch(a){return i?i(a):g.logError(a),null}},Le=({pos:e,mdl:t,options:o})=>{let{filename:r,language:n,technologies:i,relatedFiles:s,maxContextLines:a}=o,p=Ae(e,t),m=!!s?.length?3:2,c=a?Math.floor(a/m):void 0,u=(R,y,q)=>{let O=R(e,t);return y?U(O,y,q):O},C=(R,y)=>!R||!y?R:R.map(({content:q,...O})=>({...O,content:U(q,y)})),E=u(Z,c,{from:"end"}),k=u(Q,c),de=C(s,c);return{filename:r,language:n,technologies:i,relatedFiles:de,textBeforeCursor:E,textAfterCursor:k,cursorPosition:e,editorState:{completionMode:p}}},Ae=(e,t)=>{let o=H(e,t),r=b(e,t);return o?"insert":r.trim()?"complete":"continue"};var le=(e,t,o)=>{if(!o)return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:e.lineNumber,endColumn:e.column};let r=t.getOffsetAt(e),n=t.getValue().substring(r),i=0,s=0,a=0,p=o.length,l=n.length;if(r>=t.getValue().length)return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:e.lineNumber,endColumn:e.column};if(l===0)return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:e.lineNumber,endColumn:e.column};let m=Math.min(p,l);for(let C=0;C<m&&o[C]===n[C];C++)i++;for(let C=1;C<=m;C++){let E=o.slice(-C),k=n.slice(0,C);E===k&&(s=C)}if(a=Math.max(i,s),a===0)for(let C=1;C<p;C++){let E=o.substring(C);if(n.startsWith(E)){a=p-C;break}}let c=r+a,u=t.getPositionAt(c);return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:u.lineNumber,endColumn:u.column}},ae=e=>A.create(e).removeMarkdownCodeSyntax().removeExcessiveNewlines().removeInvalidLineBreaks().build(),h=e=>({items:e,enableForwardStability:!0});var Ne=300,Se=600,we=0,Be={onTyping:v(w,Ne),onIdle:v(w,Se),onDemand:v(w,we)},B=new N,ke=async({mdl:e,pos:t,token:o,isCompletionAccepted:r,onShowCompletion:n,options:i})=>{let{trigger:s="onIdle",...a}=i;if(!new D(t,e).shouldProvideCompletions())return h([]);let p=B.get(t,e).map(l=>({insertText:l.completion,range:{...l.range,endColumn:t.column}}));if(p.length>0)return n(),h(p);if(o.isCancellationRequested||r)return h([]);try{let l=Be[s];o.onCancellationRequested(()=>{l.cancel()});let m=await l({mdl:e,pos:t,...a});if(m){let c=ae(m),u=le(t,e,c);return B.add({completion:c,range:u,textBeforeCursorInLine:f(t,e)}),n(),h([{insertText:c,range:u}])}}catch(l){return i.onError?i.onError(l):qe(l)||g.logError(l),h([])}return h([])},qe=e=>typeof e=="string"&&(e==="Cancelled"||e==="AbortError")||e instanceof Error&&(e.message==="Cancelled"||e.name==="AbortError"),pe=ke;var P=new WeakMap,T=null,Y=(e,t,o)=>{T&&T.deregister();let r=[],n={isCompletionAccepted:!1,isCompletionVisible:!1,isManualTrigger:!1};P.set(t,n),t.updateOptions({inlineSuggest:{enabled:!0,mode:"subwordSmart"}});try{let i=e.languages.registerInlineCompletionsProvider(o.language,{provideInlineCompletions:(p,l,m,c)=>{let u=P.get(t);if(!(!u||o.trigger==="onDemand"&&!u.isManualTrigger))return pe({mdl:p,pos:l,token:c,isCompletionAccepted:u.isCompletionAccepted,onShowCompletion:()=>{u.isCompletionVisible=!0,u.isManualTrigger=!1},options:o})},freeInlineCompletions:()=>{}});r.push(i);let s=t.onKeyDown(p=>{let l=P.get(t);if(!l)return;let m=p.keyCode===e.KeyCode.Tab||p.keyCode===e.KeyCode.RightArrow&&p.metaKey;l.isCompletionVisible&&m?(l.isCompletionAccepted=!0,l.isCompletionVisible=!1):l.isCompletionAccepted=!1});r.push(s);let a={deregister:()=>{r.forEach(p=>p.dispose()),B.clear(),P.delete(t),T=null},trigger:()=>Fe(t)};return T=a,a}catch(i){return o.onError?o.onError(i):g.logError(i),{deregister:()=>{r.forEach(s=>s.dispose()),P.delete(t),T=null},trigger:()=>{}}}},Fe=e=>{let t=P.get(e);if(!t){g.warn("Completion is not registered. Use `registerCompletion` to register completion first.");return}t.isManualTrigger=!0,e.trigger("keyboard","editor.action.inlineSuggest.trigger",{})},ce=(...e)=>(g.warn("The `registerCopilot` function is deprecated. Use `registerCompletion` instead."),Y(...e));0&&(module.exports={Copilot,registerCompletion,registerCopilot});
|
package/build/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
var
|
|
2
|
-
`),
|
|
3
|
-
`.repeat(t):
|
|
4
|
-
`)}let
|
|
5
|
-
`.repeat(t):
|
|
6
|
-
`)};var
|
|
1
|
+
var q=["groq","openai","anthropic"],K={"llama-3-70b":"llama3-70b-8192","gpt-4o":"gpt-4o-2024-08-06","gpt-4o-mini":"gpt-4o-mini","claude-3.5-sonnet":"claude-3.5-sonnet-20240620","claude-3-opus":"claude-3-opus-20240229","claude-3-sonnet":"claude-3-sonnet-20240229","claude-3-haiku":"claude-3-haiku-20240307","o1-preview":"o1-preview","o1-mini":"o1-mini"},F={groq:["llama-3-70b"],openai:["gpt-4o","gpt-4o-mini","o1-preview","o1-mini"],anthropic:["claude-3.5-sonnet","claude-3-opus","claude-3-haiku","claude-3-sonnet"]},Y="llama-3-70b",G="groq",J={groq:"https://api.groq.com/openai/v1/chat/completions",openai:"https://api.openai.com/v1/chat/completions",anthropic:"https://api.anthropic.com/v1/messages"},M=.1;var v=(e,t)=>{let o=null,r=null,i=(...n)=>new Promise((s,a)=>{o&&(clearTimeout(o),r&&r("Cancelled")),r=a,o=setTimeout(()=>{s(e(...n)),r=null},t)});return i.cancel=()=>{o&&(clearTimeout(o),r&&r("Cancelled"),o=null,r=null)},i},x=e=>!e||e.length===0?"":e.length===1?e[0]:`${e.slice(0,-1).join(", ")} and ${e.slice(-1)}`;var _=(e,t)=>t.getLineContent(e.lineNumber)[e.column-1];var b=(e,t)=>t.getLineContent(e.lineNumber).slice(e.column-1),f=(e,t)=>t.getLineContent(e.lineNumber).slice(0,e.column-1),X=(e,t)=>t.getValueInRange({startLineNumber:1,startColumn:1,endLineNumber:e.lineNumber,endColumn:e.column}),z=(e,t)=>t.getValueInRange({startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:t.getLineCount(),endColumn:t.getLineMaxColumn(t.getLineCount())}),$=(e,t,o={})=>{if(t<=0)return"";let r=e.split(`
|
|
2
|
+
`),i=r.length;if(t>=i)return e;if(o.from==="end"){let s=r.slice(-t);return s.every(a=>a==="")?`
|
|
3
|
+
`.repeat(t):s.join(`
|
|
4
|
+
`)}let n=r.slice(0,t);return n.every(s=>s==="")?`
|
|
5
|
+
`.repeat(t):n.join(`
|
|
6
|
+
`)};var Z=async(e,t,o={})=>{let r={"Content-Type":"application/json",...o.headers},i=t==="POST"&&o.body?JSON.stringify(o.body):void 0,n=await fetch(e,{method:t,headers:r,body:i,signal:o.signal});if(!n.ok)throw new Error(`${n.statusText||o.fallbackError||"Network error"}`);return n.json()},ce=(e,t)=>Z(e,"GET",t),de=(e,t,o)=>Z(e,"POST",{...o,body:t}),I={GET:ce,POST:de};var Q=(e,t)=>{let o=b(e,t).trim(),r=f(e,t).trim();return e.column<=3&&(o!==""||r!=="")};var me="<user-current-cursor-position-is-here>",ue=e=>e==="javascript"?"JavaScript (ESNext)":e,Ce=e=>`You are an expert ${ue(e.language)||x(e.technologies)} developer assistant with extensive experience in code completion and adhering to best coding practices. Your role is to provide precise and contextually relevant code completions without any errors, including syntax, punctuation, spaces, tabs, and line breaks. Focus on integrating seamlessly with the existing code and follow the user's instructions carefully.`,ge=e=>{let{filename:t="/",textBeforeCursor:o="",textAfterCursor:r="",relatedFiles:i,editorState:n}=e,p=`
|
|
7
7
|
<guidelines>
|
|
8
|
-
<instruction>${{continue:"Continue writing the code from where the cursor is positioned.",insert:"Insert the appropriate code snippet at the cursor position.",complete:"Provide the necessary code to complete the current statement or block."}[
|
|
8
|
+
<instruction>${{continue:"Continue writing the code from where the cursor is positioned.",insert:"Insert the appropriate code snippet at the cursor position.",complete:"Provide the necessary code to complete the current statement or block."}[n.completionMode]}</instruction>
|
|
9
9
|
<steps>
|
|
10
10
|
<step>Analyze the provided code and any related files thoroughly.</step>
|
|
11
11
|
<step>Ensure the generated code integrates seamlessly with the existing code.</step>
|
|
@@ -17,7 +17,7 @@ var B=["groq","openai","anthropic"],W={"llama-3-70b":"llama3-70b-8192","gpt-4o":
|
|
|
17
17
|
<step>Return <strong>only</strong> the code required at the cursor position.</step>
|
|
18
18
|
</steps>
|
|
19
19
|
</guidelines>
|
|
20
|
-
`,
|
|
20
|
+
`,l=`
|
|
21
21
|
<context>
|
|
22
22
|
<current_file path="${t}">
|
|
23
23
|
<code>
|
|
@@ -25,21 +25,22 @@ ${o}${me}${r}
|
|
|
25
25
|
</code>
|
|
26
26
|
</current_file>
|
|
27
27
|
</context>
|
|
28
|
-
`,m=
|
|
29
|
-
<related_file path="${
|
|
28
|
+
`,m=i?.map(({path:c,content:u})=>`
|
|
29
|
+
<related_file path="${c}">
|
|
30
30
|
<code>
|
|
31
|
-
${
|
|
31
|
+
${u}
|
|
32
32
|
</code>
|
|
33
33
|
</related_file>
|
|
34
34
|
`).join(`
|
|
35
35
|
`)||"";return`
|
|
36
36
|
<task>
|
|
37
37
|
${p}
|
|
38
|
-
${
|
|
38
|
+
${l}
|
|
39
39
|
${m}
|
|
40
40
|
</task>
|
|
41
|
-
`};function
|
|
41
|
+
`};function H(e){return{system:Ce(e),user:ge(e)}}var ee={"claude-3.5-sonnet":8192,"claude-3-opus":4096,"claude-3-haiku":4096,"claude-3-sonnet":4096};var he={createRequestBody:(e,t)=>{let r=e==="o1-preview"||e==="o1-mini"?[{role:"user",content:t.user}]:[{role:"system",content:t.system},{role:"user",content:t.user}];return{model:V(e),temperature:M,messages:r}},createHeaders:e=>({"Content-Type":"application/json",Authorization:`Bearer ${e}`}),parseCompletion:e=>e.choices?.length?e.choices[0].message.content:null},fe={createRequestBody:(e,t)=>({model:V(e),temperature:M,messages:[{role:"system",content:t.system},{role:"user",content:t.user}]}),createHeaders:e=>({"Content-Type":"application/json",Authorization:`Bearer ${e}`}),parseCompletion:e=>e.choices?.length?e.choices[0].message.content:null},Pe={createRequestBody:(e,t)=>({model:V(e),temperature:M,system:t.system,messages:[{role:"user",content:t.user}],max_tokens:Ee(e)}),createHeaders:e=>({"Content-Type":"application/json","x-api-key":e,"anthropic-version":"2023-06-01"}),parseCompletion:e=>!e.content||typeof e.content!="string"?null:e.content},U={openai:he,groq:fe,anthropic:Pe},te=(e,t,o)=>U[t].createRequestBody(e,o),oe=(e,t)=>U[t].createHeaders(e),re=(e,t)=>U[t].parseCompletion(e),V=e=>K[e],ne=e=>J[e],Ee=e=>ee[e]||4096;var d=class d{constructor(){}static getInstance(){return d.instance}logError(t){let o,r;t instanceof Error?(o=t.message,r=t.stack):typeof t=="string"?o=t:o="An unknown error occurred";let i=`${d.RED}${d.BOLD}[MONACOPILOT ERROR] ${o}${d.RESET}`;return console.error(i),r&&console.error(`${d.RED}[MONACOPILOT ERROR] Stack trace:${d.RESET}
|
|
42
|
+
${r}`),{message:o,stack:r}}warn(t){console.warn(`${d.YELLOW}${d.BOLD}[MONACOPILOT WARN] ${t}${d.RESET}`)}log(t){console.log(`${d.BOLD}[MONACOPILOT] ${t}${d.RESET}`)}};d.instance=new d,d.RED="\x1B[31m",d.YELLOW="\x1B[33m",d.RESET="\x1B[0m",d.BOLD="\x1B[1m";var j=d,g=j.getInstance();var W=class{constructor(t,o={}){if(!t)throw new Error("Please provide an API key.");this.apiKey=t,this.provider=o.provider??G,this.model=o.model??Y,this.validateInputs()}validateInputs(){if(!q.includes(this.provider))throw new Error(`Unsupported provider "${this.provider}". Please choose from: ${x(q)}. For custom models, provider specification is not needed.`);if(typeof this.model=="string"&&!F[this.provider].includes(this.model))throw new Error(`Model "${this.model}" is not supported by the "${this.provider}" provider. Supported models: ${x(F[this.provider])}`)}async complete(t){let{body:o,options:r}=t,{completionMetadata:i}=o,{headers:n={},customPrompt:s}=r??{},a=this.generatePrompt(i,s),{endpoint:p,requestBody:l,headers:m}=this.prepareRequestDetails(a);try{let c=await this.sendCompletionRequest(p,l,{...m,...n});return this.processCompletionResponse(c)}catch(c){return this.handleCompletionError(c)}}generatePrompt(t,o){let r=H(t);return o?{...r,...o(t)}:r}prepareRequestDetails(t){let o=ne(this.provider),r,i=oe(this.apiKey,this.provider);if(typeof this.model=="object"&&"config"in this.model){let n=this.model.config(this.apiKey,t);o=n.endpoint??o,r=n.body??{},i={...i,...n.headers}}else r=te(this.model,this.provider,t);return{endpoint:o,requestBody:r,headers:i}}async sendCompletionRequest(t,o,r){return I.POST(t,o,{headers:r})}processCompletionResponse(t){if(typeof this.model=="object"&&"transformResponse"in this.model){let o=this.model.transformResponse(t);return"completion"in o&&g.warn("The `completion` property in `transformResponse` function is deprecated. Please use `text` instead."),{completion:o.text??o.completion}}else return{completion:re(t,this.provider)}}handleCompletionError(t){return{error:g.logError(t).message,completion:null}}};var L=class e{constructor(t){this.formattedCompletion="";this.formattedCompletion=t}static create(t){return new e(t)}setCompletion(t){return this.formattedCompletion=t,this}removeInvalidLineBreaks(){return this.formattedCompletion=this.formattedCompletion.trimEnd(),this}removeMarkdownCodeSyntax(){return this.formattedCompletion=this.removeMarkdownCodeBlocks(this.formattedCompletion),this}removeMarkdownCodeBlocks(t){let o=/```[\s\S]*?```/g,r=t,i;for(;(i=o.exec(t))!==null;){let n=i[0],s=n.split(`
|
|
42
43
|
`).slice(1,-1).join(`
|
|
43
|
-
`);r=r.replace(
|
|
44
|
+
`);r=r.replace(n,s)}return r.trim()}removeExcessiveNewlines(){return this.formattedCompletion=this.formattedCompletion.replace(/\n{3,}/g,`
|
|
44
45
|
|
|
45
|
-
`),this}build(){return this.formattedCompletion}};var
|
|
46
|
+
`),this}build(){return this.formattedCompletion}};var A=class{constructor(t,o){this.cursorPos=t,this.mdl=o}shouldProvideCompletions(){return!Q(this.cursorPos,this.mdl)}};var N=class N{constructor(){this.cache=[]}get(t,o){return this.cache.filter(r=>this.isValidCacheItem(r,t,o))}add(t){let o=[...this.cache.slice(-(N.MAX_CACHE_SIZE-1)),t];this.cache=o}clear(){this.cache=[]}isValidCacheItem(t,o,r){let i=r.getValueInRange(t.range);return f(o,r).startsWith(t.textBeforeCursorInLine)&&this.isPositionValid(t,o,i)}isPositionValid(t,o,r){let{range:i,completion:n}=t,{startLineNumber:s,startColumn:a,endColumn:p}=i,{lineNumber:l,column:m}=o,c=l===s&&m===a,u=n.startsWith(r)&&l===s&&m>=a-r.length&&m<=p+r.length;return c||u}};N.MAX_CACHE_SIZE=10;var D=N;var Re="application/json",S=async({mdl:e,pos:t,...o})=>{let{endpoint:r,requestOptions:i,onError:n}=o,{headers:s}=i??{};try{let{completion:a,error:p}=await I.POST(r,{completionMetadata:ye({pos:t,mdl:e,options:o})},{headers:{"Content-Type":Re,...s},fallbackError:"Error while fetching completion item"});if(p)throw new Error(p);return a}catch(a){return n?n(a):g.logError(a),null}},ye=({pos:e,mdl:t,options:o})=>{let{filename:r,language:i,technologies:n,relatedFiles:s,maxContextLines:a}=o,p=xe(e,t),m=!!s?.length?3:2,c=a?Math.floor(a/m):void 0,u=(R,y,k)=>{let O=R(e,t);return y?$(O,y,k):O},C=(R,y)=>!R||!y?R:R.map(({content:k,...O})=>({...O,content:$(k,y)})),E=u(X,c,{from:"end"}),B=u(z,c),pe=C(s,c);return{filename:r,language:i,technologies:n,relatedFiles:pe,textBeforeCursor:E,textAfterCursor:B,cursorPosition:e,editorState:{completionMode:p}}},xe=(e,t)=>{let o=_(e,t),r=b(e,t);return o?"insert":r.trim()?"complete":"continue"};var ie=(e,t,o)=>{if(!o)return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:e.lineNumber,endColumn:e.column};let r=t.getOffsetAt(e),i=t.getValue().substring(r),n=0,s=0,a=0,p=o.length,l=i.length;if(r>=t.getValue().length)return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:e.lineNumber,endColumn:e.column};if(l===0)return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:e.lineNumber,endColumn:e.column};let m=Math.min(p,l);for(let C=0;C<m&&o[C]===i[C];C++)n++;for(let C=1;C<=m;C++){let E=o.slice(-C),B=i.slice(0,C);E===B&&(s=C)}if(a=Math.max(n,s),a===0)for(let C=1;C<p;C++){let E=o.substring(C);if(i.startsWith(E)){a=p-C;break}}let c=r+a,u=t.getPositionAt(c);return{startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:u.lineNumber,endColumn:u.column}},se=e=>L.create(e).removeMarkdownCodeSyntax().removeExcessiveNewlines().removeInvalidLineBreaks().build(),h=e=>({items:e,enableForwardStability:!0});var Oe=300,Me=600,ve=0,be={onTyping:v(S,Oe),onIdle:v(S,Me),onDemand:v(S,ve)},w=new D,Ie=async({mdl:e,pos:t,token:o,isCompletionAccepted:r,onShowCompletion:i,options:n})=>{let{trigger:s="onIdle",...a}=n;if(!new A(t,e).shouldProvideCompletions())return h([]);let p=w.get(t,e).map(l=>({insertText:l.completion,range:{...l.range,endColumn:t.column}}));if(p.length>0)return i(),h(p);if(o.isCancellationRequested||r)return h([]);try{let l=be[s];o.onCancellationRequested(()=>{l.cancel()});let m=await l({mdl:e,pos:t,...a});if(m){let c=se(m),u=ie(t,e,c);return w.add({completion:c,range:u,textBeforeCursorInLine:f(t,e)}),i(),h([{insertText:c,range:u}])}}catch(l){return n.onError?n.onError(l):Le(l)||g.logError(l),h([])}return h([])},Le=e=>typeof e=="string"&&(e==="Cancelled"||e==="AbortError")||e instanceof Error&&(e.message==="Cancelled"||e.name==="AbortError"),le=Ie;var P=new WeakMap,T=null,ae=(e,t,o)=>{T&&T.deregister();let r=[],i={isCompletionAccepted:!1,isCompletionVisible:!1,isManualTrigger:!1};P.set(t,i),t.updateOptions({inlineSuggest:{enabled:!0,mode:"subwordSmart"}});try{let n=e.languages.registerInlineCompletionsProvider(o.language,{provideInlineCompletions:(p,l,m,c)=>{let u=P.get(t);if(!(!u||o.trigger==="onDemand"&&!u.isManualTrigger))return le({mdl:p,pos:l,token:c,isCompletionAccepted:u.isCompletionAccepted,onShowCompletion:()=>{u.isCompletionVisible=!0,u.isManualTrigger=!1},options:o})},freeInlineCompletions:()=>{}});r.push(n);let s=t.onKeyDown(p=>{let l=P.get(t);if(!l)return;let m=p.keyCode===e.KeyCode.Tab||p.keyCode===e.KeyCode.RightArrow&&p.metaKey;l.isCompletionVisible&&m?(l.isCompletionAccepted=!0,l.isCompletionVisible=!1):l.isCompletionAccepted=!1});r.push(s);let a={deregister:()=>{r.forEach(p=>p.dispose()),w.clear(),P.delete(t),T=null},trigger:()=>Ae(t)};return T=a,a}catch(n){return o.onError?o.onError(n):g.logError(n),{deregister:()=>{r.forEach(s=>s.dispose()),P.delete(t),T=null},trigger:()=>{}}}},Ae=e=>{let t=P.get(e);if(!t){g.warn("Completion is not registered. Use `registerCompletion` to register completion first.");return}t.isManualTrigger=!0,e.trigger("keyboard","editor.action.inlineSuggest.trigger",{})},De=(...e)=>(g.warn("The `registerCopilot` function is deprecated. Use `registerCompletion` instead."),ae(...e));export{W as Copilot,ae as registerCompletion,De as registerCopilot};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "monacopilot",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.11",
|
|
4
4
|
"description": "AI auto-completion plugin for Monaco Editor",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"module": "./build/index.mjs",
|
|
@@ -16,29 +16,32 @@
|
|
|
16
16
|
"type-check": "tsc --noEmit",
|
|
17
17
|
"lint": "eslint . --ext .ts,.tsx --fix",
|
|
18
18
|
"lint:test-ui": "pnpm -C tests/ui lint",
|
|
19
|
+
"validate": "pnpm build && pnpm format && pnpm type-check && pnpm lint && pnpm lint:test-ui",
|
|
19
20
|
"format": "prettier --write .",
|
|
20
|
-
"pre-commit": "pnpm build && pnpm format && pnpm type-check && pnpm lint && pnpm lint:test-ui",
|
|
21
21
|
"release": "release-it"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@anthropic-ai/sdk": "^0.27.3",
|
|
25
25
|
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
|
|
26
26
|
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
|
27
|
+
"auto-changelog": "^2.5.0",
|
|
27
28
|
"eslint": "^8.57.0",
|
|
28
29
|
"groq-sdk": "^0.3.2",
|
|
29
30
|
"monaco-editor": "^0.52.0",
|
|
30
31
|
"openai": "^4.60.1",
|
|
31
32
|
"prettier": "^3.2.5",
|
|
32
|
-
"release-it": "^17.
|
|
33
|
+
"release-it": "^17.6.0",
|
|
33
34
|
"tsup": "^8.0.2",
|
|
34
35
|
"typescript": "^5.4.3",
|
|
35
36
|
"vitest": "^2.0.5"
|
|
36
37
|
},
|
|
37
38
|
"keywords": [
|
|
38
39
|
"monaco-editor",
|
|
40
|
+
"monaco",
|
|
39
41
|
"ai",
|
|
40
42
|
"auto-completion",
|
|
41
43
|
"code-completion",
|
|
44
|
+
"copilot",
|
|
42
45
|
"github-copilot"
|
|
43
46
|
],
|
|
44
47
|
"repository": {
|
|
@@ -53,5 +56,5 @@
|
|
|
53
56
|
}
|
|
54
57
|
],
|
|
55
58
|
"license": "MIT",
|
|
56
|
-
"author": "Arshad Yaseen <m@arshadyaseen.com>"
|
|
59
|
+
"author": "Arshad Yaseen <m@arshadyaseen.com> (https://arshadyaseen.com)"
|
|
57
60
|
}
|