├── .github └── workflows │ ├── deploy.yml │ └── test.yml ├── .gitignore ├── ARCHITECTURE.md ├── LICENSE ├── README.md ├── biome.json ├── buf.gen.yaml ├── buf.lock ├── buf.yaml ├── demo ├── demo.css ├── index.html └── index.ts ├── exa ├── codeium_common_pb │ └── codeium_common.proto └── language_server_pb │ └── language_server.proto ├── package-lock.json ├── package.json ├── src ├── annotations.ts ├── api │ └── proto │ │ └── exa │ │ ├── codeium_common_pb │ │ └── codeium_common_pb.ts │ │ └── language_server_pb │ │ ├── language_server_connect.ts │ │ └── language_server_pb.ts ├── codeium.ts ├── commands.ts ├── completionDecoration.ts ├── completionRequester.ts ├── config.ts ├── defaultCycleWidget.ts ├── effects.ts ├── plugin.ts ├── requestCompletion.ts └── types.ts ├── tsconfig.json └── vite.config.js /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: read 10 | pages: write 11 | id-token: write 12 | 13 | jobs: 14 | build: 15 | name: Build 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Checkout repo 20 | uses: actions/checkout@v3 21 | 22 | - name: Setup Node 23 | uses: actions/setup-node@v3 24 | 25 | - name: Install dependencies 26 | uses: bahmutov/npm-install@v1 27 | 28 | - name: Build project 29 | run: npm run pages 30 | - name: Setup Pages 31 | uses: actions/configure-pages@v3 32 | - name: Upload artifact 33 | uses: actions/upload-pages-artifact@v2 34 | with: 35 | path: "./demo/dist" 36 | - name: Deploy to GitHub Pages 37 | id: deployment 38 | uses: actions/deploy-pages@v2 39 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | name: Test 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - name: Checkout repo 12 | uses: actions/checkout@v4 13 | 14 | - name: Setup Node 15 | uses: actions/setup-node@v4 16 | with: 17 | node-version: 20 18 | 19 | - name: Install dependencies 20 | uses: bahmutov/npm-install@v1 21 | 22 | - run: npm run tsc 23 | - run: npm run test 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .DS_Store 4 | .tshy-build 5 | -------------------------------------------------------------------------------- /ARCHITECTURE.md: -------------------------------------------------------------------------------- 1 | # Architecture 2 | 3 | This module requests autocompletions of code from [Codeium](https://codeium.com/), 4 | shows "ghost text" for them, and allows users to accept them by clicking 5 | or hitting Tab. 6 | 7 | ## Ghost text 8 | 9 | The way that this shows ghost text is quite different from how [codemirror-copilot](https://github.com/asadm/codemirror-copilot) does it, and is derived from the code 10 | in [modeling-app](https://github.com/KittyCAD/modeling-app), which is then derived 11 | from the code in [Cursor](https://cursor.sh/). 12 | 13 | In codemirror-copilot, ghost text is [based on widgets](https://github.com/asadm/codemirror-copilot/blob/09e737a3da8449d5d7f0b5cd8266688afaf3baa5/packages/codemirror-copilot/src/inline-suggestion.ts#L60-L75) - 14 | displaying a [CodeMirror widget](https://codemirror.net/docs/ref/#view.Decoration^widget) 15 | inline with text. This is simple, but has the drawbacks of the ghost 16 | text being non-highlighted, and ghost text does not create additional 17 | line numbers in the line gutter, if there is one. 18 | 19 | In this module, ghost text is added to the real text in the editor, but 20 | we use an [addToHistory](https://codemirror.net/docs/ref/#state.Transaction^addToHistory) 21 | annotation to ensure that it is not added to history. This produces ghost 22 | text that looks more cohesive with the rest of the design of the editor, 23 | but it has the drawback of producing events that upstream consumers 24 | might confuse with user edits. We provide the `copilotIgnore` annotation 25 | and the `shouldTakeUpdate` method to help with this potential confusion. 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2024, Val Town 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | Contains parts of modeling-app, licensed under the MIT License, 18 | Copyright (c) 2023 The Zoo Authors 19 | 20 | Contains parts of Cursor, licensed under the MIT License, 21 | Copyright (c) 2023 Cursor AI, Inc. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # codemirror-codeium 2 | 3 | [![npm](https://img.shields.io/npm/v/@valtown/codemirror-codeium)](https://www.npmjs.com/package/@valtown/codemirror-codeium) 4 | 5 | ```mermaid 6 | flowchart TD 7 | Keystroke --> SetTimeout 8 | Keystroke -->|ignoreUpdate| Cancelled 9 | SetTimeout -->|edits| Cancelled 10 | SetTimeout --> GetCompletions 11 | GetCompletions -->|edits| Cancelled 12 | X[ ] -->|focusChanged| Cancelled 13 | GetCompletions --> DispatchEdits 14 | DispatchEdits -->|mousedown| Cancelled 15 | DispatchEdits --> SameKeyCommand 16 | SameKeyCommand -->|tab| AcceptSuggestionCommand 17 | ``` 18 | 19 | _Very experimental and unofficial_ 20 | 21 | Copilot-like ghost text code from [modeling-app](https://github.com/KittyCAD/modeling-app) 22 | by [Jess Frazelle](https://github.com/jessfraz) and based on [Cursor](https://cursor.sh/). 23 | 24 | ## Documentation 25 | 26 | See the [demo source code](https://github.com/val-town/codemirror-codeium/tree/main/demo) for 27 | a reference to how it's used. 28 | 29 | ```ts 30 | import { copilotPlugin } from "@valtown/codemirror-codeium"; 31 | 32 | // This is a CodeMirror extension 33 | copilotPlugin(); 34 | ``` 35 | 36 | ### CSS 37 | 38 | This adds a `.ghostText` class to CodeMirror decorations for the AI-written 39 | text. You can add your own style for this class. The demo uses this style: 40 | 41 | ```css 42 | .cm-ghostText, 43 | .cm-ghostText * { 44 | opacity: 0.6; 45 | filter: grayscale(20%); 46 | cursor: pointer; 47 | } 48 | 49 | .cm-ghostText:hover { 50 | background: #eee; 51 | } 52 | ``` 53 | 54 | ### Architecture 55 | 56 | This makes requests against the [Codeium](https://codeium.com/) hosted product, 57 | using their Protocol Buffer-based interface. That's what the `buf` and `connectrpc` 58 | modules are doing - generating and using bindings to their service. 59 | 60 | The extension is a composite of facets, decorations, state fields, and more 61 | that are encapsulated. 62 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.8.1/schema.json", 3 | "organizeImports": { 4 | "enabled": true 5 | }, 6 | "formatter": { 7 | "indentStyle": "space" 8 | }, 9 | "files": { 10 | "ignore": ["dist/*"] 11 | }, 12 | "linter": { 13 | "enabled": true, 14 | "rules": { 15 | "recommended": true, 16 | "style": { 17 | "noNonNullAssertion": "info" 18 | }, 19 | "suspicious": { 20 | "noExplicitAny": "info" 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /buf.gen.yaml: -------------------------------------------------------------------------------- 1 | # buf.gen.yaml defines a local generation template. 2 | # For details, see https://docs.buf.build/configuration/v1/buf-gen-yaml 3 | version: v1 4 | plugins: 5 | - plugin: buf.build/bufbuild/es:v1.4.2 6 | out: src/api/proto 7 | opt: 8 | - target=ts 9 | - plugin: buf.build/connectrpc/es:v1.1.3 10 | out: src/api/proto 11 | opt: 12 | - target=ts 13 | -------------------------------------------------------------------------------- /buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: envoyproxy 6 | repository: protoc-gen-validate 7 | commit: 71881f09a0c5420a9545a07987a86728 8 | digest: shake256:d320bbf06653b1b2b45a1f95bfa82bf7b998221a777a042708c50d6f86a30d1a85b50c5704c597142d9b308280efe1295d39d76d1abea5f7046d3df4c8cc3cef 9 | -------------------------------------------------------------------------------- /buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | deps: 3 | - buf.build/envoyproxy/protoc-gen-validate 4 | build: 5 | excludes: 6 | - node_modules 7 | lint: 8 | use: 9 | - DEFAULT 10 | except: 11 | - PACKAGE_VERSION_SUFFIX 12 | allow_comment_ignores: true 13 | breaking: 14 | except: 15 | - FILE_NO_DELETE 16 | -------------------------------------------------------------------------------- /demo/demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: sans-serif; 4 | background: #eee; 5 | color: #333; 6 | } 7 | 8 | * { 9 | box-sizing: border-box; 10 | } 11 | 12 | h1 { 13 | margin: 0; 14 | } 15 | 16 | h2 { 17 | font-weight: normal; 18 | font-size: 18px; 19 | } 20 | 21 | p { 22 | line-height: 1.5; 23 | } 24 | 25 | a { 26 | color: blue; 27 | } 28 | 29 | a:hover { 30 | color: green; 31 | } 32 | 33 | .cm-editor { 34 | border: 1px solid #000; 35 | } 36 | 37 | main { 38 | max-width: 640px; 39 | min-height: 100vh; 40 | margin: 0 auto; 41 | background: #fff; 42 | padding: 20px; 43 | border-left: 1px solid #aaa; 44 | border-right: 1px solid #aaa; 45 | } 46 | 47 | .cm-ghostText, 48 | .cm-ghostText * { 49 | opacity: 0.6; 50 | filter: grayscale(20%); 51 | cursor: pointer; 52 | } 53 | 54 | .cm-ghostText:hover { 55 | background: #eee; 56 | } 57 | 58 | .cm-codeium-cycle { 59 | font-size: 9px; 60 | background-color: #eee; 61 | padding: 2px; 62 | border-radius: 2px; 63 | display: inline-block; 64 | } 65 | 66 | .cm-codeium-cycle-key { 67 | font-size: 9px; 68 | font-family: monospace; 69 | display: inline-block; 70 | padding: 2px; 71 | border-radius: 2px; 72 | border: none; 73 | background-color: lightblue; 74 | margin-left: 5px; 75 | } 76 | 77 | .cm-codeium-cycle-key:hover { 78 | background-color: deepskyblue; 79 | } 80 | 81 | .cm-codeium-cycle-explanation { 82 | font-family: monospace; 83 | display: inline-block; 84 | padding: 2px; 85 | } 86 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | codemirror-codeium demo 7 | 8 | 9 | 10 |
11 |

12 | codemirror-codeium 15 |

16 |

by val.town

17 |

18 | ⚠️ Hella experimental, very unofficial. Type in the box and it'll give 19 | you AI autocompletions powered by Codeium. 20 |

21 | 22 |

TypeScript AI autocompletion

23 |
24 | 25 |

Python AI autocompletion

26 |
27 | 28 |

TypeScript AI autocompletion (cmd+k to trigger completion)

29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /demo/index.ts: -------------------------------------------------------------------------------- 1 | import { EditorView, basicSetup } from "codemirror"; 2 | import { javascript } from "@codemirror/lang-javascript"; 3 | import { 4 | codeiumOtherDocumentsConfig, 5 | startCompletion, 6 | Language, 7 | copilotPlugin, 8 | } from "../src/plugin.js"; 9 | import { python } from "@codemirror/lang-python"; 10 | import { keymap } from "@codemirror/view"; 11 | 12 | new EditorView({ 13 | doc: "// Factorial function", 14 | extensions: [ 15 | basicSetup, 16 | javascript({ 17 | typescript: true, 18 | jsx: true, 19 | }), 20 | codeiumOtherDocumentsConfig.of({ 21 | override: () => [ 22 | { 23 | absolutePath: "https://esm.town/v/foo.ts", 24 | text: `export const foo = 10; 25 | 26 | const hiddenValue = "https://macwright.com/"`, 27 | language: Language.TYPESCRIPT, 28 | editorLanguage: "typescript", 29 | }, 30 | ], 31 | }), 32 | copilotPlugin({ 33 | apiKey: "d49954eb-cfba-4992-980f-d8fb37f0e942", 34 | shouldComplete(context) { 35 | if (context.tokenBefore(["String"])) { 36 | return true; 37 | } 38 | const match = context.matchBefore(/(@(?:\w*))(?:[./](\w*))?/); 39 | return !match; 40 | }, 41 | }), 42 | ], 43 | parent: document.querySelector("#editor")!, 44 | }); 45 | 46 | new EditorView({ 47 | doc: "// Factorial function (explicit trigger)", 48 | extensions: [ 49 | basicSetup, 50 | javascript({ 51 | typescript: true, 52 | jsx: true, 53 | }), 54 | codeiumOtherDocumentsConfig.of({ 55 | override: () => [ 56 | { 57 | absolutePath: "https://esm.town/v/foo.ts", 58 | text: `export const foo = 10; 59 | 60 | const hiddenValue = "https://macwright.com/"`, 61 | language: Language.TYPESCRIPT, 62 | editorLanguage: "typescript", 63 | }, 64 | ], 65 | }), 66 | copilotPlugin({ 67 | apiKey: "d49954eb-cfba-4992-980f-d8fb37f0e942", 68 | shouldComplete(context) { 69 | if (context.tokenBefore(["String"])) { 70 | return true; 71 | } 72 | const match = context.matchBefore(/(@(?:\w*))(?:[./](\w*))?/); 73 | return !match; 74 | }, 75 | alwaysOn: false, 76 | }), 77 | keymap.of([ 78 | { 79 | key: "Cmd-k", 80 | run: startCompletion, 81 | }, 82 | ]), 83 | ], 84 | parent: document.querySelector("#editor-explicit")!, 85 | }); 86 | 87 | new EditorView({ 88 | doc: "def hi_python():", 89 | extensions: [ 90 | basicSetup, 91 | python(), 92 | copilotPlugin({ 93 | apiKey: "d49954eb-cfba-4992-980f-d8fb37f0e942", 94 | language: Language.PYTHON, 95 | }), 96 | ], 97 | parent: document.querySelector("#editor-python")!, 98 | }); 99 | -------------------------------------------------------------------------------- /exa/codeium_common_pb/codeium_common.proto: -------------------------------------------------------------------------------- 1 | // Copyright Exafunction, Inc. 2 | 3 | syntax = "proto3"; 4 | 5 | package exa.codeium_common_pb; 6 | 7 | import "google/protobuf/duration.proto"; 8 | import "google/protobuf/timestamp.proto"; 9 | import "validate/validate.proto"; 10 | 11 | option go_package = "github.com/Exafunction/Exafunction/exa/codeium_common_pb"; 12 | 13 | enum ExperimentKey { 14 | UNSPECIFIED = 0; 15 | JUPYTER_FORMAT = 77; 16 | } 17 | 18 | // Next ID: 12, Previous field: entropy. 19 | message Completion { 20 | string completion_id = 1; 21 | string text = 2; 22 | string prefix = 3; 23 | string stop = 4; 24 | double score = 5; 25 | repeated uint64 tokens = 6; 26 | repeated string decoded_tokens = 7; 27 | repeated double probabilities = 8; 28 | repeated double adjusted_probabilities = 9; 29 | uint64 generated_length = 10; 30 | } 31 | 32 | // Authentication source for users on the cloud service. 33 | enum AuthSource { 34 | AUTH_SOURCE_CODEIUM = 0; 35 | } 36 | 37 | // Next ID: 15, Previous field: url. 38 | message Metadata { 39 | string ide_name = 1 [(validate.rules).string.min_len = 1]; 40 | string ide_version = 7 [(validate.rules).string.min_len = 1]; 41 | string extension_name = 12; 42 | string extension_version = 2 [(validate.rules).string.min_len = 1]; 43 | string api_key = 3 [(validate.rules).string.uuid = true]; 44 | // Regex derived from https://stackoverflow.com/a/48300605. 45 | // TODO(prem): Should this be mandatory? 46 | string locale = 4 [(validate.rules).string = { 47 | ignore_empty: true, 48 | pattern: "^[A-Za-z]{2,4}([_-][A-Za-z]{4})?([_-]([A-Za-z]{2}|[0-9]{3}))?$" 49 | }]; 50 | // UID identifying a single session for the given user. 51 | string session_id = 10; 52 | 53 | // Used purely in language server to cancel in flight requests. 54 | // If request_id is 0, then the request is not cancelable. 55 | // This should be a strictly monotonically increasing number 56 | // for the duration of a session. 57 | uint64 request_id = 9; 58 | 59 | // Browser-specific information. 60 | string user_agent = 13; 61 | string url = 14 [(validate.rules).string = { 62 | ignore_empty: true, 63 | uri: true 64 | }]; 65 | 66 | // Authentication source information. 67 | AuthSource auth_source = 15; 68 | } 69 | 70 | // Next ID: 3, Previous field: insert_spaces. 71 | message EditorOptions { 72 | uint64 tab_size = 1 [(validate.rules).uint64.gt = 0]; 73 | bool insert_spaces = 2; 74 | } 75 | 76 | message Event { 77 | EventType event_type = 1; 78 | string event_json = 2; 79 | int64 timestamp_unix_ms = 3; 80 | } 81 | 82 | enum EventType { 83 | EVENT_TYPE_UNSPECIFIED = 0; 84 | EVENT_TYPE_ENABLE_CODEIUM = 1; 85 | EVENT_TYPE_DISABLE_CODEIUM = 2; 86 | EVENT_TYPE_SHOW_PREVIOUS_COMPLETION = 3; 87 | EVENT_TYPE_SHOW_NEXT_COMPLETION = 4; 88 | } 89 | 90 | enum CompletionSource { 91 | COMPLETION_SOURCE_UNSPECIFIED = 0; 92 | COMPLETION_SOURCE_TYPING_AS_SUGGESTED = 1; 93 | COMPLETION_SOURCE_CACHE = 2; 94 | COMPLETION_SOURCE_NETWORK = 3; 95 | } 96 | 97 | // Every time this list is updated, we should be redeploying the API server 98 | // since it uses the string representation for BQ. 99 | enum Language { 100 | LANGUAGE_UNSPECIFIED = 0; 101 | LANGUAGE_C = 1; 102 | LANGUAGE_CLOJURE = 2; 103 | LANGUAGE_COFFEESCRIPT = 3; 104 | LANGUAGE_CPP = 4; 105 | LANGUAGE_CSHARP = 5; 106 | LANGUAGE_CSS = 6; 107 | LANGUAGE_CUDACPP = 7; 108 | LANGUAGE_DOCKERFILE = 8; 109 | LANGUAGE_GO = 9; 110 | LANGUAGE_GROOVY = 10; 111 | LANGUAGE_HANDLEBARS = 11; 112 | LANGUAGE_HASKELL = 12; 113 | LANGUAGE_HCL = 13; 114 | LANGUAGE_HTML = 14; 115 | LANGUAGE_INI = 15; 116 | LANGUAGE_JAVA = 16; 117 | LANGUAGE_JAVASCRIPT = 17; 118 | LANGUAGE_JSON = 18; 119 | LANGUAGE_JULIA = 19; 120 | LANGUAGE_KOTLIN = 20; 121 | LANGUAGE_LATEX = 21; 122 | LANGUAGE_LESS = 22; 123 | LANGUAGE_LUA = 23; 124 | LANGUAGE_MAKEFILE = 24; 125 | LANGUAGE_MARKDOWN = 25; 126 | LANGUAGE_OBJECTIVEC = 26; 127 | LANGUAGE_OBJECTIVECPP = 27; 128 | LANGUAGE_PERL = 28; 129 | LANGUAGE_PHP = 29; 130 | LANGUAGE_PLAINTEXT = 30; 131 | LANGUAGE_PROTOBUF = 31; 132 | LANGUAGE_PBTXT = 32; 133 | LANGUAGE_PYTHON = 33; 134 | LANGUAGE_R = 34; 135 | LANGUAGE_RUBY = 35; 136 | LANGUAGE_RUST = 36; 137 | LANGUAGE_SASS = 37; 138 | LANGUAGE_SCALA = 38; 139 | LANGUAGE_SCSS = 39; 140 | LANGUAGE_SHELL = 40; 141 | LANGUAGE_SQL = 41; 142 | LANGUAGE_STARLARK = 42; 143 | LANGUAGE_SWIFT = 43; 144 | LANGUAGE_TSX = 44; 145 | LANGUAGE_TYPESCRIPT = 45; 146 | LANGUAGE_VISUALBASIC = 46; 147 | LANGUAGE_VUE = 47; 148 | LANGUAGE_XML = 48; 149 | LANGUAGE_XSL = 49; 150 | LANGUAGE_YAML = 50; 151 | LANGUAGE_SVELTE = 51; 152 | LANGUAGE_TOML = 52; 153 | LANGUAGE_DART = 53; 154 | LANGUAGE_RST = 54; 155 | LANGUAGE_OCAML = 55; 156 | LANGUAGE_CMAKE = 56; 157 | LANGUAGE_PASCAL = 57; 158 | LANGUAGE_ELIXIR = 58; 159 | LANGUAGE_FSHARP = 59; 160 | LANGUAGE_LISP = 60; 161 | LANGUAGE_MATLAB = 61; 162 | LANGUAGE_POWERSHELL = 62; 163 | LANGUAGE_SOLIDITY = 63; 164 | LANGUAGE_ADA = 64; 165 | LANGUAGE_OCAML_INTERFACE = 65; 166 | } 167 | -------------------------------------------------------------------------------- /exa/language_server_pb/language_server.proto: -------------------------------------------------------------------------------- 1 | // Copyright Exafunction, Inc. 2 | 3 | syntax = "proto3"; 4 | 5 | package exa.language_server_pb; 6 | 7 | import "exa/codeium_common_pb/codeium_common.proto"; 8 | import "validate/validate.proto"; 9 | 10 | option go_package = "github.com/Exafunction/Exafunction/exa/language_server_pb"; 11 | 12 | service LanguageServerService { 13 | rpc GetCompletions(GetCompletionsRequest) returns (GetCompletionsResponse) {} 14 | rpc AcceptCompletion(AcceptCompletionRequest) returns (AcceptCompletionResponse) {} 15 | rpc GetAuthToken(GetAuthTokenRequest) returns (GetAuthTokenResponse) {} 16 | } 17 | 18 | message MultilineConfig { 19 | // Multiline model threshold. 0-1, higher = more single line, lower = more multiline, 20 | // 0.0 = only_multiline, default is 0.5 21 | float threshold = 1; 22 | } 23 | 24 | // Next ID: 9, Previous field: disable_cache. 25 | message GetCompletionsRequest { 26 | codeium_common_pb.Metadata metadata = 1 [(validate.rules).message.required = true]; 27 | Document document = 2 [(validate.rules).message.required = true]; 28 | codeium_common_pb.EditorOptions editor_options = 3 [(validate.rules).message.required = true]; 29 | repeated Document other_documents = 5; 30 | ExperimentConfig experiment_config = 7; 31 | 32 | string model_name = 10; 33 | MultilineConfig multiline_config = 13; 34 | } 35 | 36 | // Next ID: 5, Previous field: latency_info. 37 | message GetCompletionsResponse { 38 | State state = 1; 39 | repeated CompletionItem completion_items = 2; 40 | } 41 | 42 | // Next ID: 3, Previous field: completion_id. 43 | message AcceptCompletionRequest { 44 | codeium_common_pb.Metadata metadata = 1 [(validate.rules).message.required = true]; 45 | string completion_id = 2; 46 | } 47 | 48 | // Next ID: 1, Previous field: N/A. 49 | message AcceptCompletionResponse {} 50 | 51 | // Next ID: 1, Previous field: N/A. 52 | message GetAuthTokenRequest {} 53 | 54 | // Next ID: 3, Previous field: uuid. 55 | message GetAuthTokenResponse { 56 | string auth_token = 1; 57 | string uuid = 2; 58 | } 59 | 60 | /*****************************************************************************/ 61 | /* Helper Messages */ 62 | /*****************************************************************************/ 63 | 64 | message DocumentPosition { 65 | // 0-indexed. Measured in UTF-8 bytes. 66 | uint64 row = 1; 67 | // 0-indexed. Measured in UTF-8 bytes. 68 | uint64 col = 2; 69 | } 70 | 71 | // Next ID: 9, Previous field: cursor_position. 72 | message Document { 73 | string absolute_path = 1; 74 | // Path relative to the root of the workspace. 75 | string relative_path = 2; 76 | string text = 3; 77 | // Language ID provided by the editor. 78 | string editor_language = 4 [(validate.rules).string.min_len = 1]; 79 | // Language enum standardized across editors. 80 | codeium_common_pb.Language language = 5; 81 | // Measured in number of UTF-8 bytes. 82 | uint64 cursor_offset = 6; 83 | // May be present instead of cursor_offset. 84 | DocumentPosition cursor_position = 8; 85 | // \n or \r\n, if known. 86 | string line_ending = 7 [(validate.rules).string = { 87 | in: [ 88 | "", 89 | "\n", 90 | "\r\n" 91 | ] 92 | }]; 93 | } 94 | 95 | message ExperimentConfig { 96 | repeated codeium_common_pb.ExperimentKey force_enable_experiments = 1 [(validate.rules).repeated.unique = true]; 97 | } 98 | 99 | enum CodeiumState { 100 | CODEIUM_STATE_UNSPECIFIED = 0; 101 | CODEIUM_STATE_INACTIVE = 1; 102 | CODEIUM_STATE_PROCESSING = 2; 103 | CODEIUM_STATE_SUCCESS = 3; 104 | CODEIUM_STATE_WARNING = 4; 105 | CODEIUM_STATE_ERROR = 5; 106 | } 107 | 108 | // Next ID: 3, Previous field: message. 109 | message State { 110 | CodeiumState state = 1; 111 | string message = 2; 112 | } 113 | 114 | enum LineType { 115 | LINE_TYPE_UNSPECIFIED = 0; 116 | LINE_TYPE_SINGLE = 1; 117 | LINE_TYPE_MULTI = 2; 118 | } 119 | 120 | // Next ID: 5, Previous field: end_position. 121 | message Range { 122 | uint64 start_offset = 1; 123 | uint64 end_offset = 2; 124 | DocumentPosition start_position = 3; 125 | DocumentPosition end_position = 4; 126 | } 127 | 128 | message Suffix { 129 | // Text to insert after the cursor when accepting the completion. 130 | string text = 1; 131 | // Cursor position delta (as signed offset) from the end of the inserted 132 | // completion (including the suffix). 133 | int64 delta_cursor_offset = 2; 134 | } 135 | 136 | enum CompletionPartType { 137 | COMPLETION_PART_TYPE_UNSPECIFIED = 0; 138 | // Single-line completion parts that appear within an existing line of text. 139 | COMPLETION_PART_TYPE_INLINE = 1; 140 | // Possibly multi-line completion parts that appear below an existing line of text. 141 | COMPLETION_PART_TYPE_BLOCK = 2; 142 | // Like COMPLETION_PART_TYPE_INLINE, but overwrites the existing text. 143 | COMPLETION_PART_TYPE_INLINE_MASK = 3; 144 | } 145 | 146 | // Represents a contiguous part of the completion text that is not 147 | // already in the document. 148 | // Next ID: 4, Previous field: prefix. 149 | message CompletionPart { 150 | string text = 1; 151 | // Offset in the original document where the part starts. For block 152 | // parts, this is always the end of the line before the block. 153 | uint64 offset = 2; 154 | CompletionPartType type = 3; 155 | // The section of the original line that came before this part. Only valid for 156 | // COMPLETION_PART_TYPE_INLINE. 157 | string prefix = 4; 158 | // In the case of COMPLETION_PART_TYPE_BLOCK, represents the line it is below. 159 | uint64 line = 5; 160 | } 161 | 162 | // Next ID: 9, Previous field: completion_parts. 163 | message CompletionItem { 164 | codeium_common_pb.Completion completion = 1; 165 | Suffix suffix = 5; 166 | Range range = 2; 167 | codeium_common_pb.CompletionSource source = 3; 168 | repeated CompletionPart completion_parts = 8; 169 | } 170 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@valtown/codemirror-codeium", 3 | "version": "1.1.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@valtown/codemirror-codeium", 9 | "version": "1.1.1", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@bufbuild/protobuf": "^1.10.0", 13 | "@connectrpc/connect": "^1.4.0", 14 | "@connectrpc/connect-web": "^1.4.0" 15 | }, 16 | "devDependencies": { 17 | "@biomejs/biome": "^1.8.1", 18 | "@bufbuild/buf": "^1.36.0", 19 | "@codemirror/lang-javascript": "^6.2.2", 20 | "@codemirror/lang-python": "^6.1.5", 21 | "codemirror": "^6", 22 | "typescript": "^5.4.3", 23 | "vite": "^5.2.7" 24 | }, 25 | "engines": { 26 | "node": "*" 27 | }, 28 | "peerDependencies": { 29 | "@codemirror/autocomplete": "^6", 30 | "@codemirror/state": "^6", 31 | "@codemirror/view": "^6" 32 | } 33 | }, 34 | "node_modules/@biomejs/biome": { 35 | "version": "1.8.3", 36 | "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.3.tgz", 37 | "integrity": "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==", 38 | "dev": true, 39 | "hasInstallScript": true, 40 | "bin": { 41 | "biome": "bin/biome" 42 | }, 43 | "engines": { 44 | "node": ">=14.21.3" 45 | }, 46 | "funding": { 47 | "type": "opencollective", 48 | "url": "https://opencollective.com/biome" 49 | }, 50 | "optionalDependencies": { 51 | "@biomejs/cli-darwin-arm64": "1.8.3", 52 | "@biomejs/cli-darwin-x64": "1.8.3", 53 | "@biomejs/cli-linux-arm64": "1.8.3", 54 | "@biomejs/cli-linux-arm64-musl": "1.8.3", 55 | "@biomejs/cli-linux-x64": "1.8.3", 56 | "@biomejs/cli-linux-x64-musl": "1.8.3", 57 | "@biomejs/cli-win32-arm64": "1.8.3", 58 | "@biomejs/cli-win32-x64": "1.8.3" 59 | } 60 | }, 61 | "node_modules/@biomejs/cli-darwin-arm64": { 62 | "version": "1.8.3", 63 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.3.tgz", 64 | "integrity": "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==", 65 | "cpu": [ 66 | "arm64" 67 | ], 68 | "dev": true, 69 | "optional": true, 70 | "os": [ 71 | "darwin" 72 | ], 73 | "engines": { 74 | "node": ">=14.21.3" 75 | } 76 | }, 77 | "node_modules/@biomejs/cli-darwin-x64": { 78 | "version": "1.8.3", 79 | "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.3.tgz", 80 | "integrity": "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==", 81 | "cpu": [ 82 | "x64" 83 | ], 84 | "dev": true, 85 | "optional": true, 86 | "os": [ 87 | "darwin" 88 | ], 89 | "engines": { 90 | "node": ">=14.21.3" 91 | } 92 | }, 93 | "node_modules/@biomejs/cli-linux-arm64": { 94 | "version": "1.8.3", 95 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.3.tgz", 96 | "integrity": "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==", 97 | "cpu": [ 98 | "arm64" 99 | ], 100 | "dev": true, 101 | "optional": true, 102 | "os": [ 103 | "linux" 104 | ], 105 | "engines": { 106 | "node": ">=14.21.3" 107 | } 108 | }, 109 | "node_modules/@biomejs/cli-linux-arm64-musl": { 110 | "version": "1.8.3", 111 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.3.tgz", 112 | "integrity": "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==", 113 | "cpu": [ 114 | "arm64" 115 | ], 116 | "dev": true, 117 | "optional": true, 118 | "os": [ 119 | "linux" 120 | ], 121 | "engines": { 122 | "node": ">=14.21.3" 123 | } 124 | }, 125 | "node_modules/@biomejs/cli-linux-x64": { 126 | "version": "1.8.3", 127 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.3.tgz", 128 | "integrity": "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==", 129 | "cpu": [ 130 | "x64" 131 | ], 132 | "dev": true, 133 | "optional": true, 134 | "os": [ 135 | "linux" 136 | ], 137 | "engines": { 138 | "node": ">=14.21.3" 139 | } 140 | }, 141 | "node_modules/@biomejs/cli-linux-x64-musl": { 142 | "version": "1.8.3", 143 | "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.3.tgz", 144 | "integrity": "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==", 145 | "cpu": [ 146 | "x64" 147 | ], 148 | "dev": true, 149 | "optional": true, 150 | "os": [ 151 | "linux" 152 | ], 153 | "engines": { 154 | "node": ">=14.21.3" 155 | } 156 | }, 157 | "node_modules/@biomejs/cli-win32-arm64": { 158 | "version": "1.8.3", 159 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.3.tgz", 160 | "integrity": "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==", 161 | "cpu": [ 162 | "arm64" 163 | ], 164 | "dev": true, 165 | "optional": true, 166 | "os": [ 167 | "win32" 168 | ], 169 | "engines": { 170 | "node": ">=14.21.3" 171 | } 172 | }, 173 | "node_modules/@biomejs/cli-win32-x64": { 174 | "version": "1.8.3", 175 | "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz", 176 | "integrity": "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==", 177 | "cpu": [ 178 | "x64" 179 | ], 180 | "dev": true, 181 | "optional": true, 182 | "os": [ 183 | "win32" 184 | ], 185 | "engines": { 186 | "node": ">=14.21.3" 187 | } 188 | }, 189 | "node_modules/@bufbuild/buf": { 190 | "version": "1.36.0", 191 | "resolved": "https://registry.npmjs.org/@bufbuild/buf/-/buf-1.36.0.tgz", 192 | "integrity": "sha512-IhUx4aSlCGGD9wJQMsccs+jYsLowdbVPLtJnjJJvLWjxvatKV224iuKn6jP930k0rvejt/c6n/0sSWVu12zksQ==", 193 | "dev": true, 194 | "hasInstallScript": true, 195 | "bin": { 196 | "buf": "bin/buf", 197 | "protoc-gen-buf-breaking": "bin/protoc-gen-buf-breaking", 198 | "protoc-gen-buf-lint": "bin/protoc-gen-buf-lint" 199 | }, 200 | "engines": { 201 | "node": ">=12" 202 | }, 203 | "optionalDependencies": { 204 | "@bufbuild/buf-darwin-arm64": "1.36.0", 205 | "@bufbuild/buf-darwin-x64": "1.36.0", 206 | "@bufbuild/buf-linux-aarch64": "1.36.0", 207 | "@bufbuild/buf-linux-x64": "1.36.0", 208 | "@bufbuild/buf-win32-arm64": "1.36.0", 209 | "@bufbuild/buf-win32-x64": "1.36.0" 210 | } 211 | }, 212 | "node_modules/@bufbuild/buf-darwin-arm64": { 213 | "version": "1.36.0", 214 | "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.36.0.tgz", 215 | "integrity": "sha512-0sXbTAedj9KY7NSHbf4536SLQKjV4yhlREw44f9mV9kGFI3Jr2Dj1z8UDzB80Ti3YFgpVu2BbcOMXIDzQ6dleA==", 216 | "cpu": [ 217 | "arm64" 218 | ], 219 | "dev": true, 220 | "optional": true, 221 | "os": [ 222 | "darwin" 223 | ], 224 | "engines": { 225 | "node": ">=12" 226 | } 227 | }, 228 | "node_modules/@bufbuild/buf-darwin-x64": { 229 | "version": "1.36.0", 230 | "resolved": "https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.36.0.tgz", 231 | "integrity": "sha512-zKuE+awq1Bslv7WcJ5Rq2npCxAGeEFnQJ4tAMD0RjY8MZ9SjJRETmngU0xGeFdh/FM91+A8f8JehXtUX4D5/3g==", 232 | "cpu": [ 233 | "x64" 234 | ], 235 | "dev": true, 236 | "optional": true, 237 | "os": [ 238 | "darwin" 239 | ], 240 | "engines": { 241 | "node": ">=12" 242 | } 243 | }, 244 | "node_modules/@bufbuild/buf-linux-aarch64": { 245 | "version": "1.36.0", 246 | "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.36.0.tgz", 247 | "integrity": "sha512-GaDGNezX2i2P2bpCwMwjhhoJcu0CKnFzK3c3loS7ErP9e+y3D+AubHkB+Y5MVnmzlV65GD7HcwWnygeUI1rBSg==", 248 | "cpu": [ 249 | "arm64" 250 | ], 251 | "dev": true, 252 | "optional": true, 253 | "os": [ 254 | "linux" 255 | ], 256 | "engines": { 257 | "node": ">=12" 258 | } 259 | }, 260 | "node_modules/@bufbuild/buf-linux-x64": { 261 | "version": "1.36.0", 262 | "resolved": "https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.36.0.tgz", 263 | "integrity": "sha512-gF2itk9vZrEYvHX1TobPdwDxh16DGTbfN4W5X66BUDKTZmdgctWBDRrj15UfAZO9oSjEc3oMQM+HkoWkOtsCxw==", 264 | "cpu": [ 265 | "x64" 266 | ], 267 | "dev": true, 268 | "optional": true, 269 | "os": [ 270 | "linux" 271 | ], 272 | "engines": { 273 | "node": ">=12" 274 | } 275 | }, 276 | "node_modules/@bufbuild/buf-win32-arm64": { 277 | "version": "1.36.0", 278 | "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.36.0.tgz", 279 | "integrity": "sha512-YQDM6hnk4gj4KNrC/rJGLeplD9Lntf2J6b9E1xIlJ7YfMLkXKt72iXT351lLUygN4MNjVhdWTP+GU+tdqMrfPQ==", 280 | "cpu": [ 281 | "arm64" 282 | ], 283 | "dev": true, 284 | "optional": true, 285 | "os": [ 286 | "win32" 287 | ], 288 | "engines": { 289 | "node": ">=12" 290 | } 291 | }, 292 | "node_modules/@bufbuild/buf-win32-x64": { 293 | "version": "1.36.0", 294 | "resolved": "https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.36.0.tgz", 295 | "integrity": "sha512-qp+TuO7mHDBpJf/CtMZmIM77txcoUhGJpbjSkW+4WGpcPtwmNtQqciTYqLHXwlBVDSq9GhxpNTyx/W+kXCJS/g==", 296 | "cpu": [ 297 | "x64" 298 | ], 299 | "dev": true, 300 | "optional": true, 301 | "os": [ 302 | "win32" 303 | ], 304 | "engines": { 305 | "node": ">=12" 306 | } 307 | }, 308 | "node_modules/@bufbuild/protobuf": { 309 | "version": "1.10.0", 310 | "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.0.tgz", 311 | "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==" 312 | }, 313 | "node_modules/@codemirror/autocomplete": { 314 | "version": "6.18.0", 315 | "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.0.tgz", 316 | "integrity": "sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==", 317 | "dependencies": { 318 | "@codemirror/language": "^6.0.0", 319 | "@codemirror/state": "^6.0.0", 320 | "@codemirror/view": "^6.17.0", 321 | "@lezer/common": "^1.0.0" 322 | }, 323 | "peerDependencies": { 324 | "@codemirror/language": "^6.0.0", 325 | "@codemirror/state": "^6.0.0", 326 | "@codemirror/view": "^6.0.0", 327 | "@lezer/common": "^1.0.0" 328 | } 329 | }, 330 | "node_modules/@codemirror/commands": { 331 | "version": "6.6.0", 332 | "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz", 333 | "integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==", 334 | "dev": true, 335 | "dependencies": { 336 | "@codemirror/language": "^6.0.0", 337 | "@codemirror/state": "^6.4.0", 338 | "@codemirror/view": "^6.27.0", 339 | "@lezer/common": "^1.1.0" 340 | } 341 | }, 342 | "node_modules/@codemirror/lang-javascript": { 343 | "version": "6.2.2", 344 | "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz", 345 | "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==", 346 | "dev": true, 347 | "dependencies": { 348 | "@codemirror/autocomplete": "^6.0.0", 349 | "@codemirror/language": "^6.6.0", 350 | "@codemirror/lint": "^6.0.0", 351 | "@codemirror/state": "^6.0.0", 352 | "@codemirror/view": "^6.17.0", 353 | "@lezer/common": "^1.0.0", 354 | "@lezer/javascript": "^1.0.0" 355 | } 356 | }, 357 | "node_modules/@codemirror/lang-python": { 358 | "version": "6.1.6", 359 | "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz", 360 | "integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==", 361 | "dev": true, 362 | "dependencies": { 363 | "@codemirror/autocomplete": "^6.3.2", 364 | "@codemirror/language": "^6.8.0", 365 | "@codemirror/state": "^6.0.0", 366 | "@lezer/common": "^1.2.1", 367 | "@lezer/python": "^1.1.4" 368 | } 369 | }, 370 | "node_modules/@codemirror/language": { 371 | "version": "6.10.2", 372 | "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz", 373 | "integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==", 374 | "dependencies": { 375 | "@codemirror/state": "^6.0.0", 376 | "@codemirror/view": "^6.23.0", 377 | "@lezer/common": "^1.1.0", 378 | "@lezer/highlight": "^1.0.0", 379 | "@lezer/lr": "^1.0.0", 380 | "style-mod": "^4.0.0" 381 | } 382 | }, 383 | "node_modules/@codemirror/lint": { 384 | "version": "6.8.1", 385 | "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz", 386 | "integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==", 387 | "dev": true, 388 | "dependencies": { 389 | "@codemirror/state": "^6.0.0", 390 | "@codemirror/view": "^6.0.0", 391 | "crelt": "^1.0.5" 392 | } 393 | }, 394 | "node_modules/@codemirror/search": { 395 | "version": "6.5.6", 396 | "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", 397 | "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", 398 | "dev": true, 399 | "dependencies": { 400 | "@codemirror/state": "^6.0.0", 401 | "@codemirror/view": "^6.0.0", 402 | "crelt": "^1.0.5" 403 | } 404 | }, 405 | "node_modules/@codemirror/state": { 406 | "version": "6.4.1", 407 | "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", 408 | "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" 409 | }, 410 | "node_modules/@codemirror/view": { 411 | "version": "6.30.0", 412 | "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.30.0.tgz", 413 | "integrity": "sha512-96Nmn8OeLh6aONQprIeYk8hGVnEuYpWuxKSkdsODOx9hWPxyuyZGvmvxV/JmLsp+CubMO1PsLaN5TNNgrl0UrQ==", 414 | "dependencies": { 415 | "@codemirror/state": "^6.4.0", 416 | "style-mod": "^4.1.0", 417 | "w3c-keyname": "^2.2.4" 418 | } 419 | }, 420 | "node_modules/@connectrpc/connect": { 421 | "version": "1.4.0", 422 | "resolved": "https://registry.npmjs.org/@connectrpc/connect/-/connect-1.4.0.tgz", 423 | "integrity": "sha512-vZeOkKaAjyV4+RH3+rJZIfDFJAfr+7fyYr6sLDKbYX3uuTVszhFe9/YKf5DNqrDb5cKdKVlYkGn6DTDqMitAnA==", 424 | "peerDependencies": { 425 | "@bufbuild/protobuf": "^1.4.2" 426 | } 427 | }, 428 | "node_modules/@connectrpc/connect-web": { 429 | "version": "1.4.0", 430 | "resolved": "https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-1.4.0.tgz", 431 | "integrity": "sha512-13aO4psFbbm7rdOFGV0De2Za64DY/acMspgloDlcOKzLPPs0yZkhp1OOzAQeiAIr7BM/VOHIA3p8mF0inxCYTA==", 432 | "peerDependencies": { 433 | "@bufbuild/protobuf": "^1.4.2", 434 | "@connectrpc/connect": "1.4.0" 435 | } 436 | }, 437 | "node_modules/@esbuild/aix-ppc64": { 438 | "version": "0.21.5", 439 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 440 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 441 | "cpu": [ 442 | "ppc64" 443 | ], 444 | "dev": true, 445 | "optional": true, 446 | "os": [ 447 | "aix" 448 | ], 449 | "engines": { 450 | "node": ">=12" 451 | } 452 | }, 453 | "node_modules/@esbuild/android-arm": { 454 | "version": "0.21.5", 455 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 456 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 457 | "cpu": [ 458 | "arm" 459 | ], 460 | "dev": true, 461 | "optional": true, 462 | "os": [ 463 | "android" 464 | ], 465 | "engines": { 466 | "node": ">=12" 467 | } 468 | }, 469 | "node_modules/@esbuild/android-arm64": { 470 | "version": "0.21.5", 471 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 472 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 473 | "cpu": [ 474 | "arm64" 475 | ], 476 | "dev": true, 477 | "optional": true, 478 | "os": [ 479 | "android" 480 | ], 481 | "engines": { 482 | "node": ">=12" 483 | } 484 | }, 485 | "node_modules/@esbuild/android-x64": { 486 | "version": "0.21.5", 487 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 488 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 489 | "cpu": [ 490 | "x64" 491 | ], 492 | "dev": true, 493 | "optional": true, 494 | "os": [ 495 | "android" 496 | ], 497 | "engines": { 498 | "node": ">=12" 499 | } 500 | }, 501 | "node_modules/@esbuild/darwin-arm64": { 502 | "version": "0.21.5", 503 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 504 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 505 | "cpu": [ 506 | "arm64" 507 | ], 508 | "dev": true, 509 | "optional": true, 510 | "os": [ 511 | "darwin" 512 | ], 513 | "engines": { 514 | "node": ">=12" 515 | } 516 | }, 517 | "node_modules/@esbuild/darwin-x64": { 518 | "version": "0.21.5", 519 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 520 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 521 | "cpu": [ 522 | "x64" 523 | ], 524 | "dev": true, 525 | "optional": true, 526 | "os": [ 527 | "darwin" 528 | ], 529 | "engines": { 530 | "node": ">=12" 531 | } 532 | }, 533 | "node_modules/@esbuild/freebsd-arm64": { 534 | "version": "0.21.5", 535 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 536 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 537 | "cpu": [ 538 | "arm64" 539 | ], 540 | "dev": true, 541 | "optional": true, 542 | "os": [ 543 | "freebsd" 544 | ], 545 | "engines": { 546 | "node": ">=12" 547 | } 548 | }, 549 | "node_modules/@esbuild/freebsd-x64": { 550 | "version": "0.21.5", 551 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 552 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 553 | "cpu": [ 554 | "x64" 555 | ], 556 | "dev": true, 557 | "optional": true, 558 | "os": [ 559 | "freebsd" 560 | ], 561 | "engines": { 562 | "node": ">=12" 563 | } 564 | }, 565 | "node_modules/@esbuild/linux-arm": { 566 | "version": "0.21.5", 567 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 568 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 569 | "cpu": [ 570 | "arm" 571 | ], 572 | "dev": true, 573 | "optional": true, 574 | "os": [ 575 | "linux" 576 | ], 577 | "engines": { 578 | "node": ">=12" 579 | } 580 | }, 581 | "node_modules/@esbuild/linux-arm64": { 582 | "version": "0.21.5", 583 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 584 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 585 | "cpu": [ 586 | "arm64" 587 | ], 588 | "dev": true, 589 | "optional": true, 590 | "os": [ 591 | "linux" 592 | ], 593 | "engines": { 594 | "node": ">=12" 595 | } 596 | }, 597 | "node_modules/@esbuild/linux-ia32": { 598 | "version": "0.21.5", 599 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 600 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 601 | "cpu": [ 602 | "ia32" 603 | ], 604 | "dev": true, 605 | "optional": true, 606 | "os": [ 607 | "linux" 608 | ], 609 | "engines": { 610 | "node": ">=12" 611 | } 612 | }, 613 | "node_modules/@esbuild/linux-loong64": { 614 | "version": "0.21.5", 615 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 616 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 617 | "cpu": [ 618 | "loong64" 619 | ], 620 | "dev": true, 621 | "optional": true, 622 | "os": [ 623 | "linux" 624 | ], 625 | "engines": { 626 | "node": ">=12" 627 | } 628 | }, 629 | "node_modules/@esbuild/linux-mips64el": { 630 | "version": "0.21.5", 631 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 632 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 633 | "cpu": [ 634 | "mips64el" 635 | ], 636 | "dev": true, 637 | "optional": true, 638 | "os": [ 639 | "linux" 640 | ], 641 | "engines": { 642 | "node": ">=12" 643 | } 644 | }, 645 | "node_modules/@esbuild/linux-ppc64": { 646 | "version": "0.21.5", 647 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 648 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 649 | "cpu": [ 650 | "ppc64" 651 | ], 652 | "dev": true, 653 | "optional": true, 654 | "os": [ 655 | "linux" 656 | ], 657 | "engines": { 658 | "node": ">=12" 659 | } 660 | }, 661 | "node_modules/@esbuild/linux-riscv64": { 662 | "version": "0.21.5", 663 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 664 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 665 | "cpu": [ 666 | "riscv64" 667 | ], 668 | "dev": true, 669 | "optional": true, 670 | "os": [ 671 | "linux" 672 | ], 673 | "engines": { 674 | "node": ">=12" 675 | } 676 | }, 677 | "node_modules/@esbuild/linux-s390x": { 678 | "version": "0.21.5", 679 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 680 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 681 | "cpu": [ 682 | "s390x" 683 | ], 684 | "dev": true, 685 | "optional": true, 686 | "os": [ 687 | "linux" 688 | ], 689 | "engines": { 690 | "node": ">=12" 691 | } 692 | }, 693 | "node_modules/@esbuild/linux-x64": { 694 | "version": "0.21.5", 695 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 696 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 697 | "cpu": [ 698 | "x64" 699 | ], 700 | "dev": true, 701 | "optional": true, 702 | "os": [ 703 | "linux" 704 | ], 705 | "engines": { 706 | "node": ">=12" 707 | } 708 | }, 709 | "node_modules/@esbuild/netbsd-x64": { 710 | "version": "0.21.5", 711 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 712 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 713 | "cpu": [ 714 | "x64" 715 | ], 716 | "dev": true, 717 | "optional": true, 718 | "os": [ 719 | "netbsd" 720 | ], 721 | "engines": { 722 | "node": ">=12" 723 | } 724 | }, 725 | "node_modules/@esbuild/openbsd-x64": { 726 | "version": "0.21.5", 727 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 728 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 729 | "cpu": [ 730 | "x64" 731 | ], 732 | "dev": true, 733 | "optional": true, 734 | "os": [ 735 | "openbsd" 736 | ], 737 | "engines": { 738 | "node": ">=12" 739 | } 740 | }, 741 | "node_modules/@esbuild/sunos-x64": { 742 | "version": "0.21.5", 743 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 744 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 745 | "cpu": [ 746 | "x64" 747 | ], 748 | "dev": true, 749 | "optional": true, 750 | "os": [ 751 | "sunos" 752 | ], 753 | "engines": { 754 | "node": ">=12" 755 | } 756 | }, 757 | "node_modules/@esbuild/win32-arm64": { 758 | "version": "0.21.5", 759 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 760 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 761 | "cpu": [ 762 | "arm64" 763 | ], 764 | "dev": true, 765 | "optional": true, 766 | "os": [ 767 | "win32" 768 | ], 769 | "engines": { 770 | "node": ">=12" 771 | } 772 | }, 773 | "node_modules/@esbuild/win32-ia32": { 774 | "version": "0.21.5", 775 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 776 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 777 | "cpu": [ 778 | "ia32" 779 | ], 780 | "dev": true, 781 | "optional": true, 782 | "os": [ 783 | "win32" 784 | ], 785 | "engines": { 786 | "node": ">=12" 787 | } 788 | }, 789 | "node_modules/@esbuild/win32-x64": { 790 | "version": "0.21.5", 791 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 792 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 793 | "cpu": [ 794 | "x64" 795 | ], 796 | "dev": true, 797 | "optional": true, 798 | "os": [ 799 | "win32" 800 | ], 801 | "engines": { 802 | "node": ">=12" 803 | } 804 | }, 805 | "node_modules/@lezer/common": { 806 | "version": "1.2.1", 807 | "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", 808 | "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" 809 | }, 810 | "node_modules/@lezer/highlight": { 811 | "version": "1.2.0", 812 | "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", 813 | "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", 814 | "dependencies": { 815 | "@lezer/common": "^1.0.0" 816 | } 817 | }, 818 | "node_modules/@lezer/javascript": { 819 | "version": "1.4.17", 820 | "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.17.tgz", 821 | "integrity": "sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==", 822 | "dev": true, 823 | "dependencies": { 824 | "@lezer/common": "^1.2.0", 825 | "@lezer/highlight": "^1.1.3", 826 | "@lezer/lr": "^1.3.0" 827 | } 828 | }, 829 | "node_modules/@lezer/lr": { 830 | "version": "1.4.2", 831 | "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", 832 | "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", 833 | "dependencies": { 834 | "@lezer/common": "^1.0.0" 835 | } 836 | }, 837 | "node_modules/@lezer/python": { 838 | "version": "1.1.14", 839 | "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.14.tgz", 840 | "integrity": "sha512-ykDOb2Ti24n76PJsSa4ZoDF0zH12BSw1LGfQXCYJhJyOGiFTfGaX0Du66Ze72R+u/P35U+O6I9m8TFXov1JzsA==", 841 | "dev": true, 842 | "dependencies": { 843 | "@lezer/common": "^1.2.0", 844 | "@lezer/highlight": "^1.0.0", 845 | "@lezer/lr": "^1.0.0" 846 | } 847 | }, 848 | "node_modules/@rollup/rollup-android-arm-eabi": { 849 | "version": "4.20.0", 850 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz", 851 | "integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==", 852 | "cpu": [ 853 | "arm" 854 | ], 855 | "dev": true, 856 | "optional": true, 857 | "os": [ 858 | "android" 859 | ] 860 | }, 861 | "node_modules/@rollup/rollup-android-arm64": { 862 | "version": "4.20.0", 863 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz", 864 | "integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==", 865 | "cpu": [ 866 | "arm64" 867 | ], 868 | "dev": true, 869 | "optional": true, 870 | "os": [ 871 | "android" 872 | ] 873 | }, 874 | "node_modules/@rollup/rollup-darwin-arm64": { 875 | "version": "4.20.0", 876 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz", 877 | "integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==", 878 | "cpu": [ 879 | "arm64" 880 | ], 881 | "dev": true, 882 | "optional": true, 883 | "os": [ 884 | "darwin" 885 | ] 886 | }, 887 | "node_modules/@rollup/rollup-darwin-x64": { 888 | "version": "4.20.0", 889 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz", 890 | "integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==", 891 | "cpu": [ 892 | "x64" 893 | ], 894 | "dev": true, 895 | "optional": true, 896 | "os": [ 897 | "darwin" 898 | ] 899 | }, 900 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 901 | "version": "4.20.0", 902 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz", 903 | "integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==", 904 | "cpu": [ 905 | "arm" 906 | ], 907 | "dev": true, 908 | "optional": true, 909 | "os": [ 910 | "linux" 911 | ] 912 | }, 913 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 914 | "version": "4.20.0", 915 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz", 916 | "integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==", 917 | "cpu": [ 918 | "arm" 919 | ], 920 | "dev": true, 921 | "optional": true, 922 | "os": [ 923 | "linux" 924 | ] 925 | }, 926 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 927 | "version": "4.20.0", 928 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz", 929 | "integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==", 930 | "cpu": [ 931 | "arm64" 932 | ], 933 | "dev": true, 934 | "optional": true, 935 | "os": [ 936 | "linux" 937 | ] 938 | }, 939 | "node_modules/@rollup/rollup-linux-arm64-musl": { 940 | "version": "4.20.0", 941 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz", 942 | "integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==", 943 | "cpu": [ 944 | "arm64" 945 | ], 946 | "dev": true, 947 | "optional": true, 948 | "os": [ 949 | "linux" 950 | ] 951 | }, 952 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 953 | "version": "4.20.0", 954 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz", 955 | "integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==", 956 | "cpu": [ 957 | "ppc64" 958 | ], 959 | "dev": true, 960 | "optional": true, 961 | "os": [ 962 | "linux" 963 | ] 964 | }, 965 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 966 | "version": "4.20.0", 967 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz", 968 | "integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==", 969 | "cpu": [ 970 | "riscv64" 971 | ], 972 | "dev": true, 973 | "optional": true, 974 | "os": [ 975 | "linux" 976 | ] 977 | }, 978 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 979 | "version": "4.20.0", 980 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz", 981 | "integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==", 982 | "cpu": [ 983 | "s390x" 984 | ], 985 | "dev": true, 986 | "optional": true, 987 | "os": [ 988 | "linux" 989 | ] 990 | }, 991 | "node_modules/@rollup/rollup-linux-x64-gnu": { 992 | "version": "4.20.0", 993 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz", 994 | "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==", 995 | "cpu": [ 996 | "x64" 997 | ], 998 | "dev": true, 999 | "optional": true, 1000 | "os": [ 1001 | "linux" 1002 | ] 1003 | }, 1004 | "node_modules/@rollup/rollup-linux-x64-musl": { 1005 | "version": "4.20.0", 1006 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz", 1007 | "integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==", 1008 | "cpu": [ 1009 | "x64" 1010 | ], 1011 | "dev": true, 1012 | "optional": true, 1013 | "os": [ 1014 | "linux" 1015 | ] 1016 | }, 1017 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 1018 | "version": "4.20.0", 1019 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz", 1020 | "integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==", 1021 | "cpu": [ 1022 | "arm64" 1023 | ], 1024 | "dev": true, 1025 | "optional": true, 1026 | "os": [ 1027 | "win32" 1028 | ] 1029 | }, 1030 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 1031 | "version": "4.20.0", 1032 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz", 1033 | "integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==", 1034 | "cpu": [ 1035 | "ia32" 1036 | ], 1037 | "dev": true, 1038 | "optional": true, 1039 | "os": [ 1040 | "win32" 1041 | ] 1042 | }, 1043 | "node_modules/@rollup/rollup-win32-x64-msvc": { 1044 | "version": "4.20.0", 1045 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz", 1046 | "integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==", 1047 | "cpu": [ 1048 | "x64" 1049 | ], 1050 | "dev": true, 1051 | "optional": true, 1052 | "os": [ 1053 | "win32" 1054 | ] 1055 | }, 1056 | "node_modules/@types/estree": { 1057 | "version": "1.0.5", 1058 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 1059 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 1060 | "dev": true 1061 | }, 1062 | "node_modules/codemirror": { 1063 | "version": "6.0.1", 1064 | "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", 1065 | "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", 1066 | "dev": true, 1067 | "dependencies": { 1068 | "@codemirror/autocomplete": "^6.0.0", 1069 | "@codemirror/commands": "^6.0.0", 1070 | "@codemirror/language": "^6.0.0", 1071 | "@codemirror/lint": "^6.0.0", 1072 | "@codemirror/search": "^6.0.0", 1073 | "@codemirror/state": "^6.0.0", 1074 | "@codemirror/view": "^6.0.0" 1075 | } 1076 | }, 1077 | "node_modules/crelt": { 1078 | "version": "1.0.6", 1079 | "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", 1080 | "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", 1081 | "dev": true 1082 | }, 1083 | "node_modules/esbuild": { 1084 | "version": "0.21.5", 1085 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 1086 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 1087 | "dev": true, 1088 | "hasInstallScript": true, 1089 | "bin": { 1090 | "esbuild": "bin/esbuild" 1091 | }, 1092 | "engines": { 1093 | "node": ">=12" 1094 | }, 1095 | "optionalDependencies": { 1096 | "@esbuild/aix-ppc64": "0.21.5", 1097 | "@esbuild/android-arm": "0.21.5", 1098 | "@esbuild/android-arm64": "0.21.5", 1099 | "@esbuild/android-x64": "0.21.5", 1100 | "@esbuild/darwin-arm64": "0.21.5", 1101 | "@esbuild/darwin-x64": "0.21.5", 1102 | "@esbuild/freebsd-arm64": "0.21.5", 1103 | "@esbuild/freebsd-x64": "0.21.5", 1104 | "@esbuild/linux-arm": "0.21.5", 1105 | "@esbuild/linux-arm64": "0.21.5", 1106 | "@esbuild/linux-ia32": "0.21.5", 1107 | "@esbuild/linux-loong64": "0.21.5", 1108 | "@esbuild/linux-mips64el": "0.21.5", 1109 | "@esbuild/linux-ppc64": "0.21.5", 1110 | "@esbuild/linux-riscv64": "0.21.5", 1111 | "@esbuild/linux-s390x": "0.21.5", 1112 | "@esbuild/linux-x64": "0.21.5", 1113 | "@esbuild/netbsd-x64": "0.21.5", 1114 | "@esbuild/openbsd-x64": "0.21.5", 1115 | "@esbuild/sunos-x64": "0.21.5", 1116 | "@esbuild/win32-arm64": "0.21.5", 1117 | "@esbuild/win32-ia32": "0.21.5", 1118 | "@esbuild/win32-x64": "0.21.5" 1119 | } 1120 | }, 1121 | "node_modules/fsevents": { 1122 | "version": "2.3.3", 1123 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1124 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1125 | "dev": true, 1126 | "hasInstallScript": true, 1127 | "optional": true, 1128 | "os": [ 1129 | "darwin" 1130 | ], 1131 | "engines": { 1132 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1133 | } 1134 | }, 1135 | "node_modules/nanoid": { 1136 | "version": "3.3.7", 1137 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 1138 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 1139 | "dev": true, 1140 | "funding": [ 1141 | { 1142 | "type": "github", 1143 | "url": "https://github.com/sponsors/ai" 1144 | } 1145 | ], 1146 | "bin": { 1147 | "nanoid": "bin/nanoid.cjs" 1148 | }, 1149 | "engines": { 1150 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1151 | } 1152 | }, 1153 | "node_modules/picocolors": { 1154 | "version": "1.0.1", 1155 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 1156 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", 1157 | "dev": true 1158 | }, 1159 | "node_modules/postcss": { 1160 | "version": "8.4.41", 1161 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", 1162 | "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", 1163 | "dev": true, 1164 | "funding": [ 1165 | { 1166 | "type": "opencollective", 1167 | "url": "https://opencollective.com/postcss/" 1168 | }, 1169 | { 1170 | "type": "tidelift", 1171 | "url": "https://tidelift.com/funding/github/npm/postcss" 1172 | }, 1173 | { 1174 | "type": "github", 1175 | "url": "https://github.com/sponsors/ai" 1176 | } 1177 | ], 1178 | "dependencies": { 1179 | "nanoid": "^3.3.7", 1180 | "picocolors": "^1.0.1", 1181 | "source-map-js": "^1.2.0" 1182 | }, 1183 | "engines": { 1184 | "node": "^10 || ^12 || >=14" 1185 | } 1186 | }, 1187 | "node_modules/rollup": { 1188 | "version": "4.20.0", 1189 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz", 1190 | "integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==", 1191 | "dev": true, 1192 | "dependencies": { 1193 | "@types/estree": "1.0.5" 1194 | }, 1195 | "bin": { 1196 | "rollup": "dist/bin/rollup" 1197 | }, 1198 | "engines": { 1199 | "node": ">=18.0.0", 1200 | "npm": ">=8.0.0" 1201 | }, 1202 | "optionalDependencies": { 1203 | "@rollup/rollup-android-arm-eabi": "4.20.0", 1204 | "@rollup/rollup-android-arm64": "4.20.0", 1205 | "@rollup/rollup-darwin-arm64": "4.20.0", 1206 | "@rollup/rollup-darwin-x64": "4.20.0", 1207 | "@rollup/rollup-linux-arm-gnueabihf": "4.20.0", 1208 | "@rollup/rollup-linux-arm-musleabihf": "4.20.0", 1209 | "@rollup/rollup-linux-arm64-gnu": "4.20.0", 1210 | "@rollup/rollup-linux-arm64-musl": "4.20.0", 1211 | "@rollup/rollup-linux-powerpc64le-gnu": "4.20.0", 1212 | "@rollup/rollup-linux-riscv64-gnu": "4.20.0", 1213 | "@rollup/rollup-linux-s390x-gnu": "4.20.0", 1214 | "@rollup/rollup-linux-x64-gnu": "4.20.0", 1215 | "@rollup/rollup-linux-x64-musl": "4.20.0", 1216 | "@rollup/rollup-win32-arm64-msvc": "4.20.0", 1217 | "@rollup/rollup-win32-ia32-msvc": "4.20.0", 1218 | "@rollup/rollup-win32-x64-msvc": "4.20.0", 1219 | "fsevents": "~2.3.2" 1220 | } 1221 | }, 1222 | "node_modules/source-map-js": { 1223 | "version": "1.2.0", 1224 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", 1225 | "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", 1226 | "dev": true, 1227 | "engines": { 1228 | "node": ">=0.10.0" 1229 | } 1230 | }, 1231 | "node_modules/style-mod": { 1232 | "version": "4.1.2", 1233 | "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", 1234 | "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" 1235 | }, 1236 | "node_modules/typescript": { 1237 | "version": "5.5.4", 1238 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", 1239 | "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", 1240 | "dev": true, 1241 | "bin": { 1242 | "tsc": "bin/tsc", 1243 | "tsserver": "bin/tsserver" 1244 | }, 1245 | "engines": { 1246 | "node": ">=14.17" 1247 | } 1248 | }, 1249 | "node_modules/vite": { 1250 | "version": "5.3.5", 1251 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz", 1252 | "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==", 1253 | "dev": true, 1254 | "dependencies": { 1255 | "esbuild": "^0.21.3", 1256 | "postcss": "^8.4.39", 1257 | "rollup": "^4.13.0" 1258 | }, 1259 | "bin": { 1260 | "vite": "bin/vite.js" 1261 | }, 1262 | "engines": { 1263 | "node": "^18.0.0 || >=20.0.0" 1264 | }, 1265 | "funding": { 1266 | "url": "https://github.com/vitejs/vite?sponsor=1" 1267 | }, 1268 | "optionalDependencies": { 1269 | "fsevents": "~2.3.3" 1270 | }, 1271 | "peerDependencies": { 1272 | "@types/node": "^18.0.0 || >=20.0.0", 1273 | "less": "*", 1274 | "lightningcss": "^1.21.0", 1275 | "sass": "*", 1276 | "stylus": "*", 1277 | "sugarss": "*", 1278 | "terser": "^5.4.0" 1279 | }, 1280 | "peerDependenciesMeta": { 1281 | "@types/node": { 1282 | "optional": true 1283 | }, 1284 | "less": { 1285 | "optional": true 1286 | }, 1287 | "lightningcss": { 1288 | "optional": true 1289 | }, 1290 | "sass": { 1291 | "optional": true 1292 | }, 1293 | "stylus": { 1294 | "optional": true 1295 | }, 1296 | "sugarss": { 1297 | "optional": true 1298 | }, 1299 | "terser": { 1300 | "optional": true 1301 | } 1302 | } 1303 | }, 1304 | "node_modules/w3c-keyname": { 1305 | "version": "2.2.8", 1306 | "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", 1307 | "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" 1308 | } 1309 | } 1310 | } 1311 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@valtown/codemirror-codeium", 3 | "version": "1.1.1", 4 | "description": "codemirror integration for codeium", 5 | "scripts": { 6 | "dev": "vite", 7 | "generate": "buf generate", 8 | "tsc": "tsc --noEmit", 9 | "test": "biome lint", 10 | "test:watch": "vitest", 11 | "pages": "vite build", 12 | "build": "tsc --build", 13 | "prepare": "npm run build" 14 | }, 15 | "main": "./dist/plugin.js", 16 | "types": "./dist/plugin.d.ts", 17 | "keywords": [ 18 | "codemirror", 19 | "typescript", 20 | "ts" 21 | ], 22 | "author": "Val Town", 23 | "license": "ISC", 24 | "peerDependencies": { 25 | "@codemirror/autocomplete": "^6", 26 | "@codemirror/state": "^6", 27 | "@codemirror/view": "^6" 28 | }, 29 | "devDependencies": { 30 | "@biomejs/biome": "^1.8.1", 31 | "@bufbuild/buf": "^1.36.0", 32 | "@codemirror/lang-javascript": "^6.2.2", 33 | "@codemirror/lang-python": "^6.1.5", 34 | "codemirror": "^6", 35 | "typescript": "^5.4.3", 36 | "vite": "^5.2.7" 37 | }, 38 | "files": [ 39 | "dist" 40 | ], 41 | "type": "module", 42 | "engines": { 43 | "node": "*" 44 | }, 45 | "dependencies": { 46 | "@bufbuild/protobuf": "^1.10.0", 47 | "@connectrpc/connect": "^1.4.0", 48 | "@connectrpc/connect-web": "^1.4.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/annotations.ts: -------------------------------------------------------------------------------- 1 | import { Annotation } from "@codemirror/state"; 2 | 3 | export const copilotEvent = Annotation.define(); 4 | 5 | /** 6 | * Annotation that signals to upstream integrations 7 | * that this transaction should not be included 8 | * in history or treated otherwise as a user edit. 9 | */ 10 | export const copilotIgnore = Annotation.define(); 11 | -------------------------------------------------------------------------------- /src/api/proto/exa/codeium_common_pb/codeium_common_pb.ts: -------------------------------------------------------------------------------- 1 | // Copyright Exafunction, Inc. 2 | 3 | // @generated by protoc-gen-es v1.4.2 with parameter "target=ts" 4 | // @generated from file exa/codeium_common_pb/codeium_common.proto (package exa.codeium_common_pb, syntax proto3) 5 | /* eslint-disable */ 6 | // @ts-nocheck 7 | 8 | import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; 9 | import { Message, proto3, protoInt64 } from "@bufbuild/protobuf"; 10 | 11 | /** 12 | * @generated from enum exa.codeium_common_pb.ExperimentKey 13 | */ 14 | export enum ExperimentKey { 15 | /** 16 | * @generated from enum value: UNSPECIFIED = 0; 17 | */ 18 | UNSPECIFIED = 0, 19 | 20 | /** 21 | * @generated from enum value: JUPYTER_FORMAT = 77; 22 | */ 23 | JUPYTER_FORMAT = 77, 24 | } 25 | // Retrieve enum metadata with: proto3.getEnumType(ExperimentKey) 26 | proto3.util.setEnumType(ExperimentKey, "exa.codeium_common_pb.ExperimentKey", [ 27 | { no: 0, name: "UNSPECIFIED" }, 28 | { no: 77, name: "JUPYTER_FORMAT" }, 29 | ]); 30 | 31 | /** 32 | * Authentication source for users on the cloud service. 33 | * 34 | * @generated from enum exa.codeium_common_pb.AuthSource 35 | */ 36 | export enum AuthSource { 37 | /** 38 | * @generated from enum value: AUTH_SOURCE_CODEIUM = 0; 39 | */ 40 | CODEIUM = 0, 41 | } 42 | // Retrieve enum metadata with: proto3.getEnumType(AuthSource) 43 | proto3.util.setEnumType(AuthSource, "exa.codeium_common_pb.AuthSource", [ 44 | { no: 0, name: "AUTH_SOURCE_CODEIUM" }, 45 | ]); 46 | 47 | /** 48 | * @generated from enum exa.codeium_common_pb.EventType 49 | */ 50 | export enum EventType { 51 | /** 52 | * @generated from enum value: EVENT_TYPE_UNSPECIFIED = 0; 53 | */ 54 | UNSPECIFIED = 0, 55 | 56 | /** 57 | * @generated from enum value: EVENT_TYPE_ENABLE_CODEIUM = 1; 58 | */ 59 | ENABLE_CODEIUM = 1, 60 | 61 | /** 62 | * @generated from enum value: EVENT_TYPE_DISABLE_CODEIUM = 2; 63 | */ 64 | DISABLE_CODEIUM = 2, 65 | 66 | /** 67 | * @generated from enum value: EVENT_TYPE_SHOW_PREVIOUS_COMPLETION = 3; 68 | */ 69 | SHOW_PREVIOUS_COMPLETION = 3, 70 | 71 | /** 72 | * @generated from enum value: EVENT_TYPE_SHOW_NEXT_COMPLETION = 4; 73 | */ 74 | SHOW_NEXT_COMPLETION = 4, 75 | } 76 | // Retrieve enum metadata with: proto3.getEnumType(EventType) 77 | proto3.util.setEnumType(EventType, "exa.codeium_common_pb.EventType", [ 78 | { no: 0, name: "EVENT_TYPE_UNSPECIFIED" }, 79 | { no: 1, name: "EVENT_TYPE_ENABLE_CODEIUM" }, 80 | { no: 2, name: "EVENT_TYPE_DISABLE_CODEIUM" }, 81 | { no: 3, name: "EVENT_TYPE_SHOW_PREVIOUS_COMPLETION" }, 82 | { no: 4, name: "EVENT_TYPE_SHOW_NEXT_COMPLETION" }, 83 | ]); 84 | 85 | /** 86 | * @generated from enum exa.codeium_common_pb.CompletionSource 87 | */ 88 | export enum CompletionSource { 89 | /** 90 | * @generated from enum value: COMPLETION_SOURCE_UNSPECIFIED = 0; 91 | */ 92 | UNSPECIFIED = 0, 93 | 94 | /** 95 | * @generated from enum value: COMPLETION_SOURCE_TYPING_AS_SUGGESTED = 1; 96 | */ 97 | TYPING_AS_SUGGESTED = 1, 98 | 99 | /** 100 | * @generated from enum value: COMPLETION_SOURCE_CACHE = 2; 101 | */ 102 | CACHE = 2, 103 | 104 | /** 105 | * @generated from enum value: COMPLETION_SOURCE_NETWORK = 3; 106 | */ 107 | NETWORK = 3, 108 | } 109 | // Retrieve enum metadata with: proto3.getEnumType(CompletionSource) 110 | proto3.util.setEnumType(CompletionSource, "exa.codeium_common_pb.CompletionSource", [ 111 | { no: 0, name: "COMPLETION_SOURCE_UNSPECIFIED" }, 112 | { no: 1, name: "COMPLETION_SOURCE_TYPING_AS_SUGGESTED" }, 113 | { no: 2, name: "COMPLETION_SOURCE_CACHE" }, 114 | { no: 3, name: "COMPLETION_SOURCE_NETWORK" }, 115 | ]); 116 | 117 | /** 118 | * Every time this list is updated, we should be redeploying the API server 119 | * since it uses the string representation for BQ. 120 | * 121 | * @generated from enum exa.codeium_common_pb.Language 122 | */ 123 | export enum Language { 124 | /** 125 | * @generated from enum value: LANGUAGE_UNSPECIFIED = 0; 126 | */ 127 | UNSPECIFIED = 0, 128 | 129 | /** 130 | * @generated from enum value: LANGUAGE_C = 1; 131 | */ 132 | C = 1, 133 | 134 | /** 135 | * @generated from enum value: LANGUAGE_CLOJURE = 2; 136 | */ 137 | CLOJURE = 2, 138 | 139 | /** 140 | * @generated from enum value: LANGUAGE_COFFEESCRIPT = 3; 141 | */ 142 | COFFEESCRIPT = 3, 143 | 144 | /** 145 | * @generated from enum value: LANGUAGE_CPP = 4; 146 | */ 147 | CPP = 4, 148 | 149 | /** 150 | * @generated from enum value: LANGUAGE_CSHARP = 5; 151 | */ 152 | CSHARP = 5, 153 | 154 | /** 155 | * @generated from enum value: LANGUAGE_CSS = 6; 156 | */ 157 | CSS = 6, 158 | 159 | /** 160 | * @generated from enum value: LANGUAGE_CUDACPP = 7; 161 | */ 162 | CUDACPP = 7, 163 | 164 | /** 165 | * @generated from enum value: LANGUAGE_DOCKERFILE = 8; 166 | */ 167 | DOCKERFILE = 8, 168 | 169 | /** 170 | * @generated from enum value: LANGUAGE_GO = 9; 171 | */ 172 | GO = 9, 173 | 174 | /** 175 | * @generated from enum value: LANGUAGE_GROOVY = 10; 176 | */ 177 | GROOVY = 10, 178 | 179 | /** 180 | * @generated from enum value: LANGUAGE_HANDLEBARS = 11; 181 | */ 182 | HANDLEBARS = 11, 183 | 184 | /** 185 | * @generated from enum value: LANGUAGE_HASKELL = 12; 186 | */ 187 | HASKELL = 12, 188 | 189 | /** 190 | * @generated from enum value: LANGUAGE_HCL = 13; 191 | */ 192 | HCL = 13, 193 | 194 | /** 195 | * @generated from enum value: LANGUAGE_HTML = 14; 196 | */ 197 | HTML = 14, 198 | 199 | /** 200 | * @generated from enum value: LANGUAGE_INI = 15; 201 | */ 202 | INI = 15, 203 | 204 | /** 205 | * @generated from enum value: LANGUAGE_JAVA = 16; 206 | */ 207 | JAVA = 16, 208 | 209 | /** 210 | * @generated from enum value: LANGUAGE_JAVASCRIPT = 17; 211 | */ 212 | JAVASCRIPT = 17, 213 | 214 | /** 215 | * @generated from enum value: LANGUAGE_JSON = 18; 216 | */ 217 | JSON = 18, 218 | 219 | /** 220 | * @generated from enum value: LANGUAGE_JULIA = 19; 221 | */ 222 | JULIA = 19, 223 | 224 | /** 225 | * @generated from enum value: LANGUAGE_KOTLIN = 20; 226 | */ 227 | KOTLIN = 20, 228 | 229 | /** 230 | * @generated from enum value: LANGUAGE_LATEX = 21; 231 | */ 232 | LATEX = 21, 233 | 234 | /** 235 | * @generated from enum value: LANGUAGE_LESS = 22; 236 | */ 237 | LESS = 22, 238 | 239 | /** 240 | * @generated from enum value: LANGUAGE_LUA = 23; 241 | */ 242 | LUA = 23, 243 | 244 | /** 245 | * @generated from enum value: LANGUAGE_MAKEFILE = 24; 246 | */ 247 | MAKEFILE = 24, 248 | 249 | /** 250 | * @generated from enum value: LANGUAGE_MARKDOWN = 25; 251 | */ 252 | MARKDOWN = 25, 253 | 254 | /** 255 | * @generated from enum value: LANGUAGE_OBJECTIVEC = 26; 256 | */ 257 | OBJECTIVEC = 26, 258 | 259 | /** 260 | * @generated from enum value: LANGUAGE_OBJECTIVECPP = 27; 261 | */ 262 | OBJECTIVECPP = 27, 263 | 264 | /** 265 | * @generated from enum value: LANGUAGE_PERL = 28; 266 | */ 267 | PERL = 28, 268 | 269 | /** 270 | * @generated from enum value: LANGUAGE_PHP = 29; 271 | */ 272 | PHP = 29, 273 | 274 | /** 275 | * @generated from enum value: LANGUAGE_PLAINTEXT = 30; 276 | */ 277 | PLAINTEXT = 30, 278 | 279 | /** 280 | * @generated from enum value: LANGUAGE_PROTOBUF = 31; 281 | */ 282 | PROTOBUF = 31, 283 | 284 | /** 285 | * @generated from enum value: LANGUAGE_PBTXT = 32; 286 | */ 287 | PBTXT = 32, 288 | 289 | /** 290 | * @generated from enum value: LANGUAGE_PYTHON = 33; 291 | */ 292 | PYTHON = 33, 293 | 294 | /** 295 | * @generated from enum value: LANGUAGE_R = 34; 296 | */ 297 | R = 34, 298 | 299 | /** 300 | * @generated from enum value: LANGUAGE_RUBY = 35; 301 | */ 302 | RUBY = 35, 303 | 304 | /** 305 | * @generated from enum value: LANGUAGE_RUST = 36; 306 | */ 307 | RUST = 36, 308 | 309 | /** 310 | * @generated from enum value: LANGUAGE_SASS = 37; 311 | */ 312 | SASS = 37, 313 | 314 | /** 315 | * @generated from enum value: LANGUAGE_SCALA = 38; 316 | */ 317 | SCALA = 38, 318 | 319 | /** 320 | * @generated from enum value: LANGUAGE_SCSS = 39; 321 | */ 322 | SCSS = 39, 323 | 324 | /** 325 | * @generated from enum value: LANGUAGE_SHELL = 40; 326 | */ 327 | SHELL = 40, 328 | 329 | /** 330 | * @generated from enum value: LANGUAGE_SQL = 41; 331 | */ 332 | SQL = 41, 333 | 334 | /** 335 | * @generated from enum value: LANGUAGE_STARLARK = 42; 336 | */ 337 | STARLARK = 42, 338 | 339 | /** 340 | * @generated from enum value: LANGUAGE_SWIFT = 43; 341 | */ 342 | SWIFT = 43, 343 | 344 | /** 345 | * @generated from enum value: LANGUAGE_TSX = 44; 346 | */ 347 | TSX = 44, 348 | 349 | /** 350 | * @generated from enum value: LANGUAGE_TYPESCRIPT = 45; 351 | */ 352 | TYPESCRIPT = 45, 353 | 354 | /** 355 | * @generated from enum value: LANGUAGE_VISUALBASIC = 46; 356 | */ 357 | VISUALBASIC = 46, 358 | 359 | /** 360 | * @generated from enum value: LANGUAGE_VUE = 47; 361 | */ 362 | VUE = 47, 363 | 364 | /** 365 | * @generated from enum value: LANGUAGE_XML = 48; 366 | */ 367 | XML = 48, 368 | 369 | /** 370 | * @generated from enum value: LANGUAGE_XSL = 49; 371 | */ 372 | XSL = 49, 373 | 374 | /** 375 | * @generated from enum value: LANGUAGE_YAML = 50; 376 | */ 377 | YAML = 50, 378 | 379 | /** 380 | * @generated from enum value: LANGUAGE_SVELTE = 51; 381 | */ 382 | SVELTE = 51, 383 | 384 | /** 385 | * @generated from enum value: LANGUAGE_TOML = 52; 386 | */ 387 | TOML = 52, 388 | 389 | /** 390 | * @generated from enum value: LANGUAGE_DART = 53; 391 | */ 392 | DART = 53, 393 | 394 | /** 395 | * @generated from enum value: LANGUAGE_RST = 54; 396 | */ 397 | RST = 54, 398 | 399 | /** 400 | * @generated from enum value: LANGUAGE_OCAML = 55; 401 | */ 402 | OCAML = 55, 403 | 404 | /** 405 | * @generated from enum value: LANGUAGE_CMAKE = 56; 406 | */ 407 | CMAKE = 56, 408 | 409 | /** 410 | * @generated from enum value: LANGUAGE_PASCAL = 57; 411 | */ 412 | PASCAL = 57, 413 | 414 | /** 415 | * @generated from enum value: LANGUAGE_ELIXIR = 58; 416 | */ 417 | ELIXIR = 58, 418 | 419 | /** 420 | * @generated from enum value: LANGUAGE_FSHARP = 59; 421 | */ 422 | FSHARP = 59, 423 | 424 | /** 425 | * @generated from enum value: LANGUAGE_LISP = 60; 426 | */ 427 | LISP = 60, 428 | 429 | /** 430 | * @generated from enum value: LANGUAGE_MATLAB = 61; 431 | */ 432 | MATLAB = 61, 433 | 434 | /** 435 | * @generated from enum value: LANGUAGE_POWERSHELL = 62; 436 | */ 437 | POWERSHELL = 62, 438 | 439 | /** 440 | * @generated from enum value: LANGUAGE_SOLIDITY = 63; 441 | */ 442 | SOLIDITY = 63, 443 | 444 | /** 445 | * @generated from enum value: LANGUAGE_ADA = 64; 446 | */ 447 | ADA = 64, 448 | 449 | /** 450 | * @generated from enum value: LANGUAGE_OCAML_INTERFACE = 65; 451 | */ 452 | OCAML_INTERFACE = 65, 453 | } 454 | // Retrieve enum metadata with: proto3.getEnumType(Language) 455 | proto3.util.setEnumType(Language, "exa.codeium_common_pb.Language", [ 456 | { no: 0, name: "LANGUAGE_UNSPECIFIED" }, 457 | { no: 1, name: "LANGUAGE_C" }, 458 | { no: 2, name: "LANGUAGE_CLOJURE" }, 459 | { no: 3, name: "LANGUAGE_COFFEESCRIPT" }, 460 | { no: 4, name: "LANGUAGE_CPP" }, 461 | { no: 5, name: "LANGUAGE_CSHARP" }, 462 | { no: 6, name: "LANGUAGE_CSS" }, 463 | { no: 7, name: "LANGUAGE_CUDACPP" }, 464 | { no: 8, name: "LANGUAGE_DOCKERFILE" }, 465 | { no: 9, name: "LANGUAGE_GO" }, 466 | { no: 10, name: "LANGUAGE_GROOVY" }, 467 | { no: 11, name: "LANGUAGE_HANDLEBARS" }, 468 | { no: 12, name: "LANGUAGE_HASKELL" }, 469 | { no: 13, name: "LANGUAGE_HCL" }, 470 | { no: 14, name: "LANGUAGE_HTML" }, 471 | { no: 15, name: "LANGUAGE_INI" }, 472 | { no: 16, name: "LANGUAGE_JAVA" }, 473 | { no: 17, name: "LANGUAGE_JAVASCRIPT" }, 474 | { no: 18, name: "LANGUAGE_JSON" }, 475 | { no: 19, name: "LANGUAGE_JULIA" }, 476 | { no: 20, name: "LANGUAGE_KOTLIN" }, 477 | { no: 21, name: "LANGUAGE_LATEX" }, 478 | { no: 22, name: "LANGUAGE_LESS" }, 479 | { no: 23, name: "LANGUAGE_LUA" }, 480 | { no: 24, name: "LANGUAGE_MAKEFILE" }, 481 | { no: 25, name: "LANGUAGE_MARKDOWN" }, 482 | { no: 26, name: "LANGUAGE_OBJECTIVEC" }, 483 | { no: 27, name: "LANGUAGE_OBJECTIVECPP" }, 484 | { no: 28, name: "LANGUAGE_PERL" }, 485 | { no: 29, name: "LANGUAGE_PHP" }, 486 | { no: 30, name: "LANGUAGE_PLAINTEXT" }, 487 | { no: 31, name: "LANGUAGE_PROTOBUF" }, 488 | { no: 32, name: "LANGUAGE_PBTXT" }, 489 | { no: 33, name: "LANGUAGE_PYTHON" }, 490 | { no: 34, name: "LANGUAGE_R" }, 491 | { no: 35, name: "LANGUAGE_RUBY" }, 492 | { no: 36, name: "LANGUAGE_RUST" }, 493 | { no: 37, name: "LANGUAGE_SASS" }, 494 | { no: 38, name: "LANGUAGE_SCALA" }, 495 | { no: 39, name: "LANGUAGE_SCSS" }, 496 | { no: 40, name: "LANGUAGE_SHELL" }, 497 | { no: 41, name: "LANGUAGE_SQL" }, 498 | { no: 42, name: "LANGUAGE_STARLARK" }, 499 | { no: 43, name: "LANGUAGE_SWIFT" }, 500 | { no: 44, name: "LANGUAGE_TSX" }, 501 | { no: 45, name: "LANGUAGE_TYPESCRIPT" }, 502 | { no: 46, name: "LANGUAGE_VISUALBASIC" }, 503 | { no: 47, name: "LANGUAGE_VUE" }, 504 | { no: 48, name: "LANGUAGE_XML" }, 505 | { no: 49, name: "LANGUAGE_XSL" }, 506 | { no: 50, name: "LANGUAGE_YAML" }, 507 | { no: 51, name: "LANGUAGE_SVELTE" }, 508 | { no: 52, name: "LANGUAGE_TOML" }, 509 | { no: 53, name: "LANGUAGE_DART" }, 510 | { no: 54, name: "LANGUAGE_RST" }, 511 | { no: 55, name: "LANGUAGE_OCAML" }, 512 | { no: 56, name: "LANGUAGE_CMAKE" }, 513 | { no: 57, name: "LANGUAGE_PASCAL" }, 514 | { no: 58, name: "LANGUAGE_ELIXIR" }, 515 | { no: 59, name: "LANGUAGE_FSHARP" }, 516 | { no: 60, name: "LANGUAGE_LISP" }, 517 | { no: 61, name: "LANGUAGE_MATLAB" }, 518 | { no: 62, name: "LANGUAGE_POWERSHELL" }, 519 | { no: 63, name: "LANGUAGE_SOLIDITY" }, 520 | { no: 64, name: "LANGUAGE_ADA" }, 521 | { no: 65, name: "LANGUAGE_OCAML_INTERFACE" }, 522 | ]); 523 | 524 | /** 525 | * Next ID: 12, Previous field: entropy. 526 | * 527 | * @generated from message exa.codeium_common_pb.Completion 528 | */ 529 | export class Completion extends Message { 530 | /** 531 | * @generated from field: string completion_id = 1; 532 | */ 533 | completionId = ""; 534 | 535 | /** 536 | * @generated from field: string text = 2; 537 | */ 538 | text = ""; 539 | 540 | /** 541 | * @generated from field: string prefix = 3; 542 | */ 543 | prefix = ""; 544 | 545 | /** 546 | * @generated from field: string stop = 4; 547 | */ 548 | stop = ""; 549 | 550 | /** 551 | * @generated from field: double score = 5; 552 | */ 553 | score = 0; 554 | 555 | /** 556 | * @generated from field: repeated uint64 tokens = 6; 557 | */ 558 | tokens: bigint[] = []; 559 | 560 | /** 561 | * @generated from field: repeated string decoded_tokens = 7; 562 | */ 563 | decodedTokens: string[] = []; 564 | 565 | /** 566 | * @generated from field: repeated double probabilities = 8; 567 | */ 568 | probabilities: number[] = []; 569 | 570 | /** 571 | * @generated from field: repeated double adjusted_probabilities = 9; 572 | */ 573 | adjustedProbabilities: number[] = []; 574 | 575 | /** 576 | * @generated from field: uint64 generated_length = 10; 577 | */ 578 | generatedLength = protoInt64.zero; 579 | 580 | constructor(data?: PartialMessage) { 581 | super(); 582 | proto3.util.initPartial(data, this); 583 | } 584 | 585 | static readonly runtime: typeof proto3 = proto3; 586 | static readonly typeName = "exa.codeium_common_pb.Completion"; 587 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 588 | { no: 1, name: "completion_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 589 | { no: 2, name: "text", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 590 | { no: 3, name: "prefix", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 591 | { no: 4, name: "stop", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 592 | { no: 5, name: "score", kind: "scalar", T: 1 /* ScalarType.DOUBLE */ }, 593 | { no: 6, name: "tokens", kind: "scalar", T: 4 /* ScalarType.UINT64 */, repeated: true }, 594 | { no: 7, name: "decoded_tokens", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true }, 595 | { no: 8, name: "probabilities", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, repeated: true }, 596 | { no: 9, name: "adjusted_probabilities", kind: "scalar", T: 1 /* ScalarType.DOUBLE */, repeated: true }, 597 | { no: 10, name: "generated_length", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 598 | ]); 599 | 600 | static fromBinary(bytes: Uint8Array, options?: Partial): Completion { 601 | return new Completion().fromBinary(bytes, options); 602 | } 603 | 604 | static fromJson(jsonValue: JsonValue, options?: Partial): Completion { 605 | return new Completion().fromJson(jsonValue, options); 606 | } 607 | 608 | static fromJsonString(jsonString: string, options?: Partial): Completion { 609 | return new Completion().fromJsonString(jsonString, options); 610 | } 611 | 612 | static equals(a: Completion | PlainMessage | undefined, b: Completion | PlainMessage | undefined): boolean { 613 | return proto3.util.equals(Completion, a, b); 614 | } 615 | } 616 | 617 | /** 618 | * Next ID: 15, Previous field: url. 619 | * 620 | * @generated from message exa.codeium_common_pb.Metadata 621 | */ 622 | export class Metadata extends Message { 623 | /** 624 | * @generated from field: string ide_name = 1; 625 | */ 626 | ideName = ""; 627 | 628 | /** 629 | * @generated from field: string ide_version = 7; 630 | */ 631 | ideVersion = ""; 632 | 633 | /** 634 | * @generated from field: string extension_name = 12; 635 | */ 636 | extensionName = ""; 637 | 638 | /** 639 | * @generated from field: string extension_version = 2; 640 | */ 641 | extensionVersion = ""; 642 | 643 | /** 644 | * @generated from field: string api_key = 3; 645 | */ 646 | apiKey = ""; 647 | 648 | /** 649 | * Regex derived from https://stackoverflow.com/a/48300605. 650 | * TODO(prem): Should this be mandatory? 651 | * 652 | * @generated from field: string locale = 4; 653 | */ 654 | locale = ""; 655 | 656 | /** 657 | * UID identifying a single session for the given user. 658 | * 659 | * @generated from field: string session_id = 10; 660 | */ 661 | sessionId = ""; 662 | 663 | /** 664 | * Used purely in language server to cancel in flight requests. 665 | * If request_id is 0, then the request is not cancelable. 666 | * This should be a strictly monotonically increasing number 667 | * for the duration of a session. 668 | * 669 | * @generated from field: uint64 request_id = 9; 670 | */ 671 | requestId = protoInt64.zero; 672 | 673 | /** 674 | * Browser-specific information. 675 | * 676 | * @generated from field: string user_agent = 13; 677 | */ 678 | userAgent = ""; 679 | 680 | /** 681 | * @generated from field: string url = 14; 682 | */ 683 | url = ""; 684 | 685 | /** 686 | * Authentication source information. 687 | * 688 | * @generated from field: exa.codeium_common_pb.AuthSource auth_source = 15; 689 | */ 690 | authSource = AuthSource.CODEIUM; 691 | 692 | constructor(data?: PartialMessage) { 693 | super(); 694 | proto3.util.initPartial(data, this); 695 | } 696 | 697 | static readonly runtime: typeof proto3 = proto3; 698 | static readonly typeName = "exa.codeium_common_pb.Metadata"; 699 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 700 | { no: 1, name: "ide_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 701 | { no: 7, name: "ide_version", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 702 | { no: 12, name: "extension_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 703 | { no: 2, name: "extension_version", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 704 | { no: 3, name: "api_key", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 705 | { no: 4, name: "locale", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 706 | { no: 10, name: "session_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 707 | { no: 9, name: "request_id", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 708 | { no: 13, name: "user_agent", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 709 | { no: 14, name: "url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 710 | { no: 15, name: "auth_source", kind: "enum", T: proto3.getEnumType(AuthSource) }, 711 | ]); 712 | 713 | static fromBinary(bytes: Uint8Array, options?: Partial): Metadata { 714 | return new Metadata().fromBinary(bytes, options); 715 | } 716 | 717 | static fromJson(jsonValue: JsonValue, options?: Partial): Metadata { 718 | return new Metadata().fromJson(jsonValue, options); 719 | } 720 | 721 | static fromJsonString(jsonString: string, options?: Partial): Metadata { 722 | return new Metadata().fromJsonString(jsonString, options); 723 | } 724 | 725 | static equals(a: Metadata | PlainMessage | undefined, b: Metadata | PlainMessage | undefined): boolean { 726 | return proto3.util.equals(Metadata, a, b); 727 | } 728 | } 729 | 730 | /** 731 | * Next ID: 3, Previous field: insert_spaces. 732 | * 733 | * @generated from message exa.codeium_common_pb.EditorOptions 734 | */ 735 | export class EditorOptions extends Message { 736 | /** 737 | * @generated from field: uint64 tab_size = 1; 738 | */ 739 | tabSize = protoInt64.zero; 740 | 741 | /** 742 | * @generated from field: bool insert_spaces = 2; 743 | */ 744 | insertSpaces = false; 745 | 746 | constructor(data?: PartialMessage) { 747 | super(); 748 | proto3.util.initPartial(data, this); 749 | } 750 | 751 | static readonly runtime: typeof proto3 = proto3; 752 | static readonly typeName = "exa.codeium_common_pb.EditorOptions"; 753 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 754 | { no: 1, name: "tab_size", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 755 | { no: 2, name: "insert_spaces", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, 756 | ]); 757 | 758 | static fromBinary(bytes: Uint8Array, options?: Partial): EditorOptions { 759 | return new EditorOptions().fromBinary(bytes, options); 760 | } 761 | 762 | static fromJson(jsonValue: JsonValue, options?: Partial): EditorOptions { 763 | return new EditorOptions().fromJson(jsonValue, options); 764 | } 765 | 766 | static fromJsonString(jsonString: string, options?: Partial): EditorOptions { 767 | return new EditorOptions().fromJsonString(jsonString, options); 768 | } 769 | 770 | static equals(a: EditorOptions | PlainMessage | undefined, b: EditorOptions | PlainMessage | undefined): boolean { 771 | return proto3.util.equals(EditorOptions, a, b); 772 | } 773 | } 774 | 775 | /** 776 | * @generated from message exa.codeium_common_pb.Event 777 | */ 778 | export class Event extends Message { 779 | /** 780 | * @generated from field: exa.codeium_common_pb.EventType event_type = 1; 781 | */ 782 | eventType = EventType.UNSPECIFIED; 783 | 784 | /** 785 | * @generated from field: string event_json = 2; 786 | */ 787 | eventJson = ""; 788 | 789 | /** 790 | * @generated from field: int64 timestamp_unix_ms = 3; 791 | */ 792 | timestampUnixMs = protoInt64.zero; 793 | 794 | constructor(data?: PartialMessage) { 795 | super(); 796 | proto3.util.initPartial(data, this); 797 | } 798 | 799 | static readonly runtime: typeof proto3 = proto3; 800 | static readonly typeName = "exa.codeium_common_pb.Event"; 801 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 802 | { no: 1, name: "event_type", kind: "enum", T: proto3.getEnumType(EventType) }, 803 | { no: 2, name: "event_json", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 804 | { no: 3, name: "timestamp_unix_ms", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, 805 | ]); 806 | 807 | static fromBinary(bytes: Uint8Array, options?: Partial): Event { 808 | return new Event().fromBinary(bytes, options); 809 | } 810 | 811 | static fromJson(jsonValue: JsonValue, options?: Partial): Event { 812 | return new Event().fromJson(jsonValue, options); 813 | } 814 | 815 | static fromJsonString(jsonString: string, options?: Partial): Event { 816 | return new Event().fromJsonString(jsonString, options); 817 | } 818 | 819 | static equals(a: Event | PlainMessage | undefined, b: Event | PlainMessage | undefined): boolean { 820 | return proto3.util.equals(Event, a, b); 821 | } 822 | } 823 | 824 | -------------------------------------------------------------------------------- /src/api/proto/exa/language_server_pb/language_server_connect.ts: -------------------------------------------------------------------------------- 1 | // Copyright Exafunction, Inc. 2 | 3 | // @generated by protoc-gen-connect-es v1.1.3 with parameter "target=ts" 4 | // @generated from file exa/language_server_pb/language_server.proto (package exa.language_server_pb, syntax proto3) 5 | /* eslint-disable */ 6 | // @ts-nocheck 7 | 8 | import { AcceptCompletionRequest, AcceptCompletionResponse, GetAuthTokenRequest, GetAuthTokenResponse, GetCompletionsRequest, GetCompletionsResponse } from "./language_server_pb.js"; 9 | import { MethodKind } from "@bufbuild/protobuf"; 10 | 11 | /** 12 | * @generated from service exa.language_server_pb.LanguageServerService 13 | */ 14 | export const LanguageServerService = { 15 | typeName: "exa.language_server_pb.LanguageServerService", 16 | methods: { 17 | /** 18 | * @generated from rpc exa.language_server_pb.LanguageServerService.GetCompletions 19 | */ 20 | getCompletions: { 21 | name: "GetCompletions", 22 | I: GetCompletionsRequest, 23 | O: GetCompletionsResponse, 24 | kind: MethodKind.Unary, 25 | }, 26 | /** 27 | * @generated from rpc exa.language_server_pb.LanguageServerService.AcceptCompletion 28 | */ 29 | acceptCompletion: { 30 | name: "AcceptCompletion", 31 | I: AcceptCompletionRequest, 32 | O: AcceptCompletionResponse, 33 | kind: MethodKind.Unary, 34 | }, 35 | /** 36 | * @generated from rpc exa.language_server_pb.LanguageServerService.GetAuthToken 37 | */ 38 | getAuthToken: { 39 | name: "GetAuthToken", 40 | I: GetAuthTokenRequest, 41 | O: GetAuthTokenResponse, 42 | kind: MethodKind.Unary, 43 | }, 44 | } 45 | } as const; 46 | 47 | -------------------------------------------------------------------------------- /src/api/proto/exa/language_server_pb/language_server_pb.ts: -------------------------------------------------------------------------------- 1 | // Copyright Exafunction, Inc. 2 | 3 | // @generated by protoc-gen-es v1.4.2 with parameter "target=ts" 4 | // @generated from file exa/language_server_pb/language_server.proto (package exa.language_server_pb, syntax proto3) 5 | /* eslint-disable */ 6 | // @ts-nocheck 7 | 8 | import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; 9 | import { Message, proto3, protoInt64 } from "@bufbuild/protobuf"; 10 | import { Completion, CompletionSource, EditorOptions, ExperimentKey, Language, Metadata } from "../codeium_common_pb/codeium_common_pb.js"; 11 | 12 | /** 13 | * @generated from enum exa.language_server_pb.CodeiumState 14 | */ 15 | export enum CodeiumState { 16 | /** 17 | * @generated from enum value: CODEIUM_STATE_UNSPECIFIED = 0; 18 | */ 19 | UNSPECIFIED = 0, 20 | 21 | /** 22 | * @generated from enum value: CODEIUM_STATE_INACTIVE = 1; 23 | */ 24 | INACTIVE = 1, 25 | 26 | /** 27 | * @generated from enum value: CODEIUM_STATE_PROCESSING = 2; 28 | */ 29 | PROCESSING = 2, 30 | 31 | /** 32 | * @generated from enum value: CODEIUM_STATE_SUCCESS = 3; 33 | */ 34 | SUCCESS = 3, 35 | 36 | /** 37 | * @generated from enum value: CODEIUM_STATE_WARNING = 4; 38 | */ 39 | WARNING = 4, 40 | 41 | /** 42 | * @generated from enum value: CODEIUM_STATE_ERROR = 5; 43 | */ 44 | ERROR = 5, 45 | } 46 | // Retrieve enum metadata with: proto3.getEnumType(CodeiumState) 47 | proto3.util.setEnumType(CodeiumState, "exa.language_server_pb.CodeiumState", [ 48 | { no: 0, name: "CODEIUM_STATE_UNSPECIFIED" }, 49 | { no: 1, name: "CODEIUM_STATE_INACTIVE" }, 50 | { no: 2, name: "CODEIUM_STATE_PROCESSING" }, 51 | { no: 3, name: "CODEIUM_STATE_SUCCESS" }, 52 | { no: 4, name: "CODEIUM_STATE_WARNING" }, 53 | { no: 5, name: "CODEIUM_STATE_ERROR" }, 54 | ]); 55 | 56 | /** 57 | * @generated from enum exa.language_server_pb.LineType 58 | */ 59 | export enum LineType { 60 | /** 61 | * @generated from enum value: LINE_TYPE_UNSPECIFIED = 0; 62 | */ 63 | UNSPECIFIED = 0, 64 | 65 | /** 66 | * @generated from enum value: LINE_TYPE_SINGLE = 1; 67 | */ 68 | SINGLE = 1, 69 | 70 | /** 71 | * @generated from enum value: LINE_TYPE_MULTI = 2; 72 | */ 73 | MULTI = 2, 74 | } 75 | // Retrieve enum metadata with: proto3.getEnumType(LineType) 76 | proto3.util.setEnumType(LineType, "exa.language_server_pb.LineType", [ 77 | { no: 0, name: "LINE_TYPE_UNSPECIFIED" }, 78 | { no: 1, name: "LINE_TYPE_SINGLE" }, 79 | { no: 2, name: "LINE_TYPE_MULTI" }, 80 | ]); 81 | 82 | /** 83 | * @generated from enum exa.language_server_pb.CompletionPartType 84 | */ 85 | export enum CompletionPartType { 86 | /** 87 | * @generated from enum value: COMPLETION_PART_TYPE_UNSPECIFIED = 0; 88 | */ 89 | UNSPECIFIED = 0, 90 | 91 | /** 92 | * Single-line completion parts that appear within an existing line of text. 93 | * 94 | * @generated from enum value: COMPLETION_PART_TYPE_INLINE = 1; 95 | */ 96 | INLINE = 1, 97 | 98 | /** 99 | * Possibly multi-line completion parts that appear below an existing line of text. 100 | * 101 | * @generated from enum value: COMPLETION_PART_TYPE_BLOCK = 2; 102 | */ 103 | BLOCK = 2, 104 | 105 | /** 106 | * Like COMPLETION_PART_TYPE_INLINE, but overwrites the existing text. 107 | * 108 | * @generated from enum value: COMPLETION_PART_TYPE_INLINE_MASK = 3; 109 | */ 110 | INLINE_MASK = 3, 111 | } 112 | // Retrieve enum metadata with: proto3.getEnumType(CompletionPartType) 113 | proto3.util.setEnumType(CompletionPartType, "exa.language_server_pb.CompletionPartType", [ 114 | { no: 0, name: "COMPLETION_PART_TYPE_UNSPECIFIED" }, 115 | { no: 1, name: "COMPLETION_PART_TYPE_INLINE" }, 116 | { no: 2, name: "COMPLETION_PART_TYPE_BLOCK" }, 117 | { no: 3, name: "COMPLETION_PART_TYPE_INLINE_MASK" }, 118 | ]); 119 | 120 | /** 121 | * @generated from message exa.language_server_pb.MultilineConfig 122 | */ 123 | export class MultilineConfig extends Message { 124 | /** 125 | * Multiline model threshold. 0-1, higher = more single line, lower = more multiline, 126 | * 0.0 = only_multiline, default is 0.5 127 | * 128 | * @generated from field: float threshold = 1; 129 | */ 130 | threshold = 0; 131 | 132 | constructor(data?: PartialMessage) { 133 | super(); 134 | proto3.util.initPartial(data, this); 135 | } 136 | 137 | static readonly runtime: typeof proto3 = proto3; 138 | static readonly typeName = "exa.language_server_pb.MultilineConfig"; 139 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 140 | { no: 1, name: "threshold", kind: "scalar", T: 2 /* ScalarType.FLOAT */ }, 141 | ]); 142 | 143 | static fromBinary(bytes: Uint8Array, options?: Partial): MultilineConfig { 144 | return new MultilineConfig().fromBinary(bytes, options); 145 | } 146 | 147 | static fromJson(jsonValue: JsonValue, options?: Partial): MultilineConfig { 148 | return new MultilineConfig().fromJson(jsonValue, options); 149 | } 150 | 151 | static fromJsonString(jsonString: string, options?: Partial): MultilineConfig { 152 | return new MultilineConfig().fromJsonString(jsonString, options); 153 | } 154 | 155 | static equals(a: MultilineConfig | PlainMessage | undefined, b: MultilineConfig | PlainMessage | undefined): boolean { 156 | return proto3.util.equals(MultilineConfig, a, b); 157 | } 158 | } 159 | 160 | /** 161 | * Next ID: 9, Previous field: disable_cache. 162 | * 163 | * @generated from message exa.language_server_pb.GetCompletionsRequest 164 | */ 165 | export class GetCompletionsRequest extends Message { 166 | /** 167 | * @generated from field: exa.codeium_common_pb.Metadata metadata = 1; 168 | */ 169 | metadata?: Metadata; 170 | 171 | /** 172 | * @generated from field: exa.language_server_pb.Document document = 2; 173 | */ 174 | document?: Document; 175 | 176 | /** 177 | * @generated from field: exa.codeium_common_pb.EditorOptions editor_options = 3; 178 | */ 179 | editorOptions?: EditorOptions; 180 | 181 | /** 182 | * @generated from field: repeated exa.language_server_pb.Document other_documents = 5; 183 | */ 184 | otherDocuments: Document[] = []; 185 | 186 | /** 187 | * @generated from field: exa.language_server_pb.ExperimentConfig experiment_config = 7; 188 | */ 189 | experimentConfig?: ExperimentConfig; 190 | 191 | /** 192 | * @generated from field: string model_name = 10; 193 | */ 194 | modelName = ""; 195 | 196 | /** 197 | * @generated from field: exa.language_server_pb.MultilineConfig multiline_config = 13; 198 | */ 199 | multilineConfig?: MultilineConfig; 200 | 201 | constructor(data?: PartialMessage) { 202 | super(); 203 | proto3.util.initPartial(data, this); 204 | } 205 | 206 | static readonly runtime: typeof proto3 = proto3; 207 | static readonly typeName = "exa.language_server_pb.GetCompletionsRequest"; 208 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 209 | { no: 1, name: "metadata", kind: "message", T: Metadata }, 210 | { no: 2, name: "document", kind: "message", T: Document }, 211 | { no: 3, name: "editor_options", kind: "message", T: EditorOptions }, 212 | { no: 5, name: "other_documents", kind: "message", T: Document, repeated: true }, 213 | { no: 7, name: "experiment_config", kind: "message", T: ExperimentConfig }, 214 | { no: 10, name: "model_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 215 | { no: 13, name: "multiline_config", kind: "message", T: MultilineConfig }, 216 | ]); 217 | 218 | static fromBinary(bytes: Uint8Array, options?: Partial): GetCompletionsRequest { 219 | return new GetCompletionsRequest().fromBinary(bytes, options); 220 | } 221 | 222 | static fromJson(jsonValue: JsonValue, options?: Partial): GetCompletionsRequest { 223 | return new GetCompletionsRequest().fromJson(jsonValue, options); 224 | } 225 | 226 | static fromJsonString(jsonString: string, options?: Partial): GetCompletionsRequest { 227 | return new GetCompletionsRequest().fromJsonString(jsonString, options); 228 | } 229 | 230 | static equals(a: GetCompletionsRequest | PlainMessage | undefined, b: GetCompletionsRequest | PlainMessage | undefined): boolean { 231 | return proto3.util.equals(GetCompletionsRequest, a, b); 232 | } 233 | } 234 | 235 | /** 236 | * Next ID: 5, Previous field: latency_info. 237 | * 238 | * @generated from message exa.language_server_pb.GetCompletionsResponse 239 | */ 240 | export class GetCompletionsResponse extends Message { 241 | /** 242 | * @generated from field: exa.language_server_pb.State state = 1; 243 | */ 244 | state?: State; 245 | 246 | /** 247 | * @generated from field: repeated exa.language_server_pb.CompletionItem completion_items = 2; 248 | */ 249 | completionItems: CompletionItem[] = []; 250 | 251 | constructor(data?: PartialMessage) { 252 | super(); 253 | proto3.util.initPartial(data, this); 254 | } 255 | 256 | static readonly runtime: typeof proto3 = proto3; 257 | static readonly typeName = "exa.language_server_pb.GetCompletionsResponse"; 258 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 259 | { no: 1, name: "state", kind: "message", T: State }, 260 | { no: 2, name: "completion_items", kind: "message", T: CompletionItem, repeated: true }, 261 | ]); 262 | 263 | static fromBinary(bytes: Uint8Array, options?: Partial): GetCompletionsResponse { 264 | return new GetCompletionsResponse().fromBinary(bytes, options); 265 | } 266 | 267 | static fromJson(jsonValue: JsonValue, options?: Partial): GetCompletionsResponse { 268 | return new GetCompletionsResponse().fromJson(jsonValue, options); 269 | } 270 | 271 | static fromJsonString(jsonString: string, options?: Partial): GetCompletionsResponse { 272 | return new GetCompletionsResponse().fromJsonString(jsonString, options); 273 | } 274 | 275 | static equals(a: GetCompletionsResponse | PlainMessage | undefined, b: GetCompletionsResponse | PlainMessage | undefined): boolean { 276 | return proto3.util.equals(GetCompletionsResponse, a, b); 277 | } 278 | } 279 | 280 | /** 281 | * Next ID: 3, Previous field: completion_id. 282 | * 283 | * @generated from message exa.language_server_pb.AcceptCompletionRequest 284 | */ 285 | export class AcceptCompletionRequest extends Message { 286 | /** 287 | * @generated from field: exa.codeium_common_pb.Metadata metadata = 1; 288 | */ 289 | metadata?: Metadata; 290 | 291 | /** 292 | * @generated from field: string completion_id = 2; 293 | */ 294 | completionId = ""; 295 | 296 | constructor(data?: PartialMessage) { 297 | super(); 298 | proto3.util.initPartial(data, this); 299 | } 300 | 301 | static readonly runtime: typeof proto3 = proto3; 302 | static readonly typeName = "exa.language_server_pb.AcceptCompletionRequest"; 303 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 304 | { no: 1, name: "metadata", kind: "message", T: Metadata }, 305 | { no: 2, name: "completion_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 306 | ]); 307 | 308 | static fromBinary(bytes: Uint8Array, options?: Partial): AcceptCompletionRequest { 309 | return new AcceptCompletionRequest().fromBinary(bytes, options); 310 | } 311 | 312 | static fromJson(jsonValue: JsonValue, options?: Partial): AcceptCompletionRequest { 313 | return new AcceptCompletionRequest().fromJson(jsonValue, options); 314 | } 315 | 316 | static fromJsonString(jsonString: string, options?: Partial): AcceptCompletionRequest { 317 | return new AcceptCompletionRequest().fromJsonString(jsonString, options); 318 | } 319 | 320 | static equals(a: AcceptCompletionRequest | PlainMessage | undefined, b: AcceptCompletionRequest | PlainMessage | undefined): boolean { 321 | return proto3.util.equals(AcceptCompletionRequest, a, b); 322 | } 323 | } 324 | 325 | /** 326 | * Next ID: 1, Previous field: N/A. 327 | * 328 | * @generated from message exa.language_server_pb.AcceptCompletionResponse 329 | */ 330 | export class AcceptCompletionResponse extends Message { 331 | constructor(data?: PartialMessage) { 332 | super(); 333 | proto3.util.initPartial(data, this); 334 | } 335 | 336 | static readonly runtime: typeof proto3 = proto3; 337 | static readonly typeName = "exa.language_server_pb.AcceptCompletionResponse"; 338 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 339 | ]); 340 | 341 | static fromBinary(bytes: Uint8Array, options?: Partial): AcceptCompletionResponse { 342 | return new AcceptCompletionResponse().fromBinary(bytes, options); 343 | } 344 | 345 | static fromJson(jsonValue: JsonValue, options?: Partial): AcceptCompletionResponse { 346 | return new AcceptCompletionResponse().fromJson(jsonValue, options); 347 | } 348 | 349 | static fromJsonString(jsonString: string, options?: Partial): AcceptCompletionResponse { 350 | return new AcceptCompletionResponse().fromJsonString(jsonString, options); 351 | } 352 | 353 | static equals(a: AcceptCompletionResponse | PlainMessage | undefined, b: AcceptCompletionResponse | PlainMessage | undefined): boolean { 354 | return proto3.util.equals(AcceptCompletionResponse, a, b); 355 | } 356 | } 357 | 358 | /** 359 | * Next ID: 1, Previous field: N/A. 360 | * 361 | * @generated from message exa.language_server_pb.GetAuthTokenRequest 362 | */ 363 | export class GetAuthTokenRequest extends Message { 364 | constructor(data?: PartialMessage) { 365 | super(); 366 | proto3.util.initPartial(data, this); 367 | } 368 | 369 | static readonly runtime: typeof proto3 = proto3; 370 | static readonly typeName = "exa.language_server_pb.GetAuthTokenRequest"; 371 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 372 | ]); 373 | 374 | static fromBinary(bytes: Uint8Array, options?: Partial): GetAuthTokenRequest { 375 | return new GetAuthTokenRequest().fromBinary(bytes, options); 376 | } 377 | 378 | static fromJson(jsonValue: JsonValue, options?: Partial): GetAuthTokenRequest { 379 | return new GetAuthTokenRequest().fromJson(jsonValue, options); 380 | } 381 | 382 | static fromJsonString(jsonString: string, options?: Partial): GetAuthTokenRequest { 383 | return new GetAuthTokenRequest().fromJsonString(jsonString, options); 384 | } 385 | 386 | static equals(a: GetAuthTokenRequest | PlainMessage | undefined, b: GetAuthTokenRequest | PlainMessage | undefined): boolean { 387 | return proto3.util.equals(GetAuthTokenRequest, a, b); 388 | } 389 | } 390 | 391 | /** 392 | * Next ID: 3, Previous field: uuid. 393 | * 394 | * @generated from message exa.language_server_pb.GetAuthTokenResponse 395 | */ 396 | export class GetAuthTokenResponse extends Message { 397 | /** 398 | * @generated from field: string auth_token = 1; 399 | */ 400 | authToken = ""; 401 | 402 | /** 403 | * @generated from field: string uuid = 2; 404 | */ 405 | uuid = ""; 406 | 407 | constructor(data?: PartialMessage) { 408 | super(); 409 | proto3.util.initPartial(data, this); 410 | } 411 | 412 | static readonly runtime: typeof proto3 = proto3; 413 | static readonly typeName = "exa.language_server_pb.GetAuthTokenResponse"; 414 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 415 | { no: 1, name: "auth_token", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 416 | { no: 2, name: "uuid", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 417 | ]); 418 | 419 | static fromBinary(bytes: Uint8Array, options?: Partial): GetAuthTokenResponse { 420 | return new GetAuthTokenResponse().fromBinary(bytes, options); 421 | } 422 | 423 | static fromJson(jsonValue: JsonValue, options?: Partial): GetAuthTokenResponse { 424 | return new GetAuthTokenResponse().fromJson(jsonValue, options); 425 | } 426 | 427 | static fromJsonString(jsonString: string, options?: Partial): GetAuthTokenResponse { 428 | return new GetAuthTokenResponse().fromJsonString(jsonString, options); 429 | } 430 | 431 | static equals(a: GetAuthTokenResponse | PlainMessage | undefined, b: GetAuthTokenResponse | PlainMessage | undefined): boolean { 432 | return proto3.util.equals(GetAuthTokenResponse, a, b); 433 | } 434 | } 435 | 436 | /** 437 | * @generated from message exa.language_server_pb.DocumentPosition 438 | */ 439 | export class DocumentPosition extends Message { 440 | /** 441 | * 0-indexed. Measured in UTF-8 bytes. 442 | * 443 | * @generated from field: uint64 row = 1; 444 | */ 445 | row = protoInt64.zero; 446 | 447 | /** 448 | * 0-indexed. Measured in UTF-8 bytes. 449 | * 450 | * @generated from field: uint64 col = 2; 451 | */ 452 | col = protoInt64.zero; 453 | 454 | constructor(data?: PartialMessage) { 455 | super(); 456 | proto3.util.initPartial(data, this); 457 | } 458 | 459 | static readonly runtime: typeof proto3 = proto3; 460 | static readonly typeName = "exa.language_server_pb.DocumentPosition"; 461 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 462 | { no: 1, name: "row", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 463 | { no: 2, name: "col", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 464 | ]); 465 | 466 | static fromBinary(bytes: Uint8Array, options?: Partial): DocumentPosition { 467 | return new DocumentPosition().fromBinary(bytes, options); 468 | } 469 | 470 | static fromJson(jsonValue: JsonValue, options?: Partial): DocumentPosition { 471 | return new DocumentPosition().fromJson(jsonValue, options); 472 | } 473 | 474 | static fromJsonString(jsonString: string, options?: Partial): DocumentPosition { 475 | return new DocumentPosition().fromJsonString(jsonString, options); 476 | } 477 | 478 | static equals(a: DocumentPosition | PlainMessage | undefined, b: DocumentPosition | PlainMessage | undefined): boolean { 479 | return proto3.util.equals(DocumentPosition, a, b); 480 | } 481 | } 482 | 483 | /** 484 | * Next ID: 9, Previous field: cursor_position. 485 | * 486 | * @generated from message exa.language_server_pb.Document 487 | */ 488 | export class Document extends Message { 489 | /** 490 | * @generated from field: string absolute_path = 1; 491 | */ 492 | absolutePath = ""; 493 | 494 | /** 495 | * Path relative to the root of the workspace. 496 | * 497 | * @generated from field: string relative_path = 2; 498 | */ 499 | relativePath = ""; 500 | 501 | /** 502 | * @generated from field: string text = 3; 503 | */ 504 | text = ""; 505 | 506 | /** 507 | * Language ID provided by the editor. 508 | * 509 | * @generated from field: string editor_language = 4; 510 | */ 511 | editorLanguage = ""; 512 | 513 | /** 514 | * Language enum standardized across editors. 515 | * 516 | * @generated from field: exa.codeium_common_pb.Language language = 5; 517 | */ 518 | language = Language.UNSPECIFIED; 519 | 520 | /** 521 | * Measured in number of UTF-8 bytes. 522 | * 523 | * @generated from field: uint64 cursor_offset = 6; 524 | */ 525 | cursorOffset = protoInt64.zero; 526 | 527 | /** 528 | * May be present instead of cursor_offset. 529 | * 530 | * @generated from field: exa.language_server_pb.DocumentPosition cursor_position = 8; 531 | */ 532 | cursorPosition?: DocumentPosition; 533 | 534 | /** 535 | * \n or \r\n, if known. 536 | * 537 | * @generated from field: string line_ending = 7; 538 | */ 539 | lineEnding = ""; 540 | 541 | constructor(data?: PartialMessage) { 542 | super(); 543 | proto3.util.initPartial(data, this); 544 | } 545 | 546 | static readonly runtime: typeof proto3 = proto3; 547 | static readonly typeName = "exa.language_server_pb.Document"; 548 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 549 | { no: 1, name: "absolute_path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 550 | { no: 2, name: "relative_path", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 551 | { no: 3, name: "text", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 552 | { no: 4, name: "editor_language", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 553 | { no: 5, name: "language", kind: "enum", T: proto3.getEnumType(Language) }, 554 | { no: 6, name: "cursor_offset", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 555 | { no: 8, name: "cursor_position", kind: "message", T: DocumentPosition }, 556 | { no: 7, name: "line_ending", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 557 | ]); 558 | 559 | static fromBinary(bytes: Uint8Array, options?: Partial): Document { 560 | return new Document().fromBinary(bytes, options); 561 | } 562 | 563 | static fromJson(jsonValue: JsonValue, options?: Partial): Document { 564 | return new Document().fromJson(jsonValue, options); 565 | } 566 | 567 | static fromJsonString(jsonString: string, options?: Partial): Document { 568 | return new Document().fromJsonString(jsonString, options); 569 | } 570 | 571 | static equals(a: Document | PlainMessage | undefined, b: Document | PlainMessage | undefined): boolean { 572 | return proto3.util.equals(Document, a, b); 573 | } 574 | } 575 | 576 | /** 577 | * @generated from message exa.language_server_pb.ExperimentConfig 578 | */ 579 | export class ExperimentConfig extends Message { 580 | /** 581 | * @generated from field: repeated exa.codeium_common_pb.ExperimentKey force_enable_experiments = 1; 582 | */ 583 | forceEnableExperiments: ExperimentKey[] = []; 584 | 585 | constructor(data?: PartialMessage) { 586 | super(); 587 | proto3.util.initPartial(data, this); 588 | } 589 | 590 | static readonly runtime: typeof proto3 = proto3; 591 | static readonly typeName = "exa.language_server_pb.ExperimentConfig"; 592 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 593 | { no: 1, name: "force_enable_experiments", kind: "enum", T: proto3.getEnumType(ExperimentKey), repeated: true }, 594 | ]); 595 | 596 | static fromBinary(bytes: Uint8Array, options?: Partial): ExperimentConfig { 597 | return new ExperimentConfig().fromBinary(bytes, options); 598 | } 599 | 600 | static fromJson(jsonValue: JsonValue, options?: Partial): ExperimentConfig { 601 | return new ExperimentConfig().fromJson(jsonValue, options); 602 | } 603 | 604 | static fromJsonString(jsonString: string, options?: Partial): ExperimentConfig { 605 | return new ExperimentConfig().fromJsonString(jsonString, options); 606 | } 607 | 608 | static equals(a: ExperimentConfig | PlainMessage | undefined, b: ExperimentConfig | PlainMessage | undefined): boolean { 609 | return proto3.util.equals(ExperimentConfig, a, b); 610 | } 611 | } 612 | 613 | /** 614 | * Next ID: 3, Previous field: message. 615 | * 616 | * @generated from message exa.language_server_pb.State 617 | */ 618 | export class State extends Message { 619 | /** 620 | * @generated from field: exa.language_server_pb.CodeiumState state = 1; 621 | */ 622 | state = CodeiumState.UNSPECIFIED; 623 | 624 | /** 625 | * @generated from field: string message = 2; 626 | */ 627 | message = ""; 628 | 629 | constructor(data?: PartialMessage) { 630 | super(); 631 | proto3.util.initPartial(data, this); 632 | } 633 | 634 | static readonly runtime: typeof proto3 = proto3; 635 | static readonly typeName = "exa.language_server_pb.State"; 636 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 637 | { no: 1, name: "state", kind: "enum", T: proto3.getEnumType(CodeiumState) }, 638 | { no: 2, name: "message", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 639 | ]); 640 | 641 | static fromBinary(bytes: Uint8Array, options?: Partial): State { 642 | return new State().fromBinary(bytes, options); 643 | } 644 | 645 | static fromJson(jsonValue: JsonValue, options?: Partial): State { 646 | return new State().fromJson(jsonValue, options); 647 | } 648 | 649 | static fromJsonString(jsonString: string, options?: Partial): State { 650 | return new State().fromJsonString(jsonString, options); 651 | } 652 | 653 | static equals(a: State | PlainMessage | undefined, b: State | PlainMessage | undefined): boolean { 654 | return proto3.util.equals(State, a, b); 655 | } 656 | } 657 | 658 | /** 659 | * Next ID: 5, Previous field: end_position. 660 | * 661 | * @generated from message exa.language_server_pb.Range 662 | */ 663 | export class Range extends Message { 664 | /** 665 | * @generated from field: uint64 start_offset = 1; 666 | */ 667 | startOffset = protoInt64.zero; 668 | 669 | /** 670 | * @generated from field: uint64 end_offset = 2; 671 | */ 672 | endOffset = protoInt64.zero; 673 | 674 | /** 675 | * @generated from field: exa.language_server_pb.DocumentPosition start_position = 3; 676 | */ 677 | startPosition?: DocumentPosition; 678 | 679 | /** 680 | * @generated from field: exa.language_server_pb.DocumentPosition end_position = 4; 681 | */ 682 | endPosition?: DocumentPosition; 683 | 684 | constructor(data?: PartialMessage) { 685 | super(); 686 | proto3.util.initPartial(data, this); 687 | } 688 | 689 | static readonly runtime: typeof proto3 = proto3; 690 | static readonly typeName = "exa.language_server_pb.Range"; 691 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 692 | { no: 1, name: "start_offset", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 693 | { no: 2, name: "end_offset", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 694 | { no: 3, name: "start_position", kind: "message", T: DocumentPosition }, 695 | { no: 4, name: "end_position", kind: "message", T: DocumentPosition }, 696 | ]); 697 | 698 | static fromBinary(bytes: Uint8Array, options?: Partial): Range { 699 | return new Range().fromBinary(bytes, options); 700 | } 701 | 702 | static fromJson(jsonValue: JsonValue, options?: Partial): Range { 703 | return new Range().fromJson(jsonValue, options); 704 | } 705 | 706 | static fromJsonString(jsonString: string, options?: Partial): Range { 707 | return new Range().fromJsonString(jsonString, options); 708 | } 709 | 710 | static equals(a: Range | PlainMessage | undefined, b: Range | PlainMessage | undefined): boolean { 711 | return proto3.util.equals(Range, a, b); 712 | } 713 | } 714 | 715 | /** 716 | * @generated from message exa.language_server_pb.Suffix 717 | */ 718 | export class Suffix extends Message { 719 | /** 720 | * Text to insert after the cursor when accepting the completion. 721 | * 722 | * @generated from field: string text = 1; 723 | */ 724 | text = ""; 725 | 726 | /** 727 | * Cursor position delta (as signed offset) from the end of the inserted 728 | * completion (including the suffix). 729 | * 730 | * @generated from field: int64 delta_cursor_offset = 2; 731 | */ 732 | deltaCursorOffset = protoInt64.zero; 733 | 734 | constructor(data?: PartialMessage) { 735 | super(); 736 | proto3.util.initPartial(data, this); 737 | } 738 | 739 | static readonly runtime: typeof proto3 = proto3; 740 | static readonly typeName = "exa.language_server_pb.Suffix"; 741 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 742 | { no: 1, name: "text", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 743 | { no: 2, name: "delta_cursor_offset", kind: "scalar", T: 3 /* ScalarType.INT64 */ }, 744 | ]); 745 | 746 | static fromBinary(bytes: Uint8Array, options?: Partial): Suffix { 747 | return new Suffix().fromBinary(bytes, options); 748 | } 749 | 750 | static fromJson(jsonValue: JsonValue, options?: Partial): Suffix { 751 | return new Suffix().fromJson(jsonValue, options); 752 | } 753 | 754 | static fromJsonString(jsonString: string, options?: Partial): Suffix { 755 | return new Suffix().fromJsonString(jsonString, options); 756 | } 757 | 758 | static equals(a: Suffix | PlainMessage | undefined, b: Suffix | PlainMessage | undefined): boolean { 759 | return proto3.util.equals(Suffix, a, b); 760 | } 761 | } 762 | 763 | /** 764 | * Represents a contiguous part of the completion text that is not 765 | * already in the document. 766 | * Next ID: 4, Previous field: prefix. 767 | * 768 | * @generated from message exa.language_server_pb.CompletionPart 769 | */ 770 | export class CompletionPart extends Message { 771 | /** 772 | * @generated from field: string text = 1; 773 | */ 774 | text = ""; 775 | 776 | /** 777 | * Offset in the original document where the part starts. For block 778 | * parts, this is always the end of the line before the block. 779 | * 780 | * @generated from field: uint64 offset = 2; 781 | */ 782 | offset = protoInt64.zero; 783 | 784 | /** 785 | * @generated from field: exa.language_server_pb.CompletionPartType type = 3; 786 | */ 787 | type = CompletionPartType.UNSPECIFIED; 788 | 789 | /** 790 | * The section of the original line that came before this part. Only valid for 791 | * COMPLETION_PART_TYPE_INLINE. 792 | * 793 | * @generated from field: string prefix = 4; 794 | */ 795 | prefix = ""; 796 | 797 | /** 798 | * In the case of COMPLETION_PART_TYPE_BLOCK, represents the line it is below. 799 | * 800 | * @generated from field: uint64 line = 5; 801 | */ 802 | line = protoInt64.zero; 803 | 804 | constructor(data?: PartialMessage) { 805 | super(); 806 | proto3.util.initPartial(data, this); 807 | } 808 | 809 | static readonly runtime: typeof proto3 = proto3; 810 | static readonly typeName = "exa.language_server_pb.CompletionPart"; 811 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 812 | { no: 1, name: "text", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 813 | { no: 2, name: "offset", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 814 | { no: 3, name: "type", kind: "enum", T: proto3.getEnumType(CompletionPartType) }, 815 | { no: 4, name: "prefix", kind: "scalar", T: 9 /* ScalarType.STRING */ }, 816 | { no: 5, name: "line", kind: "scalar", T: 4 /* ScalarType.UINT64 */ }, 817 | ]); 818 | 819 | static fromBinary(bytes: Uint8Array, options?: Partial): CompletionPart { 820 | return new CompletionPart().fromBinary(bytes, options); 821 | } 822 | 823 | static fromJson(jsonValue: JsonValue, options?: Partial): CompletionPart { 824 | return new CompletionPart().fromJson(jsonValue, options); 825 | } 826 | 827 | static fromJsonString(jsonString: string, options?: Partial): CompletionPart { 828 | return new CompletionPart().fromJsonString(jsonString, options); 829 | } 830 | 831 | static equals(a: CompletionPart | PlainMessage | undefined, b: CompletionPart | PlainMessage | undefined): boolean { 832 | return proto3.util.equals(CompletionPart, a, b); 833 | } 834 | } 835 | 836 | /** 837 | * Next ID: 9, Previous field: completion_parts. 838 | * 839 | * @generated from message exa.language_server_pb.CompletionItem 840 | */ 841 | export class CompletionItem extends Message { 842 | /** 843 | * @generated from field: exa.codeium_common_pb.Completion completion = 1; 844 | */ 845 | completion?: Completion; 846 | 847 | /** 848 | * @generated from field: exa.language_server_pb.Suffix suffix = 5; 849 | */ 850 | suffix?: Suffix; 851 | 852 | /** 853 | * @generated from field: exa.language_server_pb.Range range = 2; 854 | */ 855 | range?: Range; 856 | 857 | /** 858 | * @generated from field: exa.codeium_common_pb.CompletionSource source = 3; 859 | */ 860 | source = CompletionSource.UNSPECIFIED; 861 | 862 | /** 863 | * @generated from field: repeated exa.language_server_pb.CompletionPart completion_parts = 8; 864 | */ 865 | completionParts: CompletionPart[] = []; 866 | 867 | constructor(data?: PartialMessage) { 868 | super(); 869 | proto3.util.initPartial(data, this); 870 | } 871 | 872 | static readonly runtime: typeof proto3 = proto3; 873 | static readonly typeName = "exa.language_server_pb.CompletionItem"; 874 | static readonly fields: FieldList = proto3.util.newFieldList(() => [ 875 | { no: 1, name: "completion", kind: "message", T: Completion }, 876 | { no: 5, name: "suffix", kind: "message", T: Suffix }, 877 | { no: 2, name: "range", kind: "message", T: Range }, 878 | { no: 3, name: "source", kind: "enum", T: proto3.getEnumType(CompletionSource) }, 879 | { no: 8, name: "completion_parts", kind: "message", T: CompletionPart, repeated: true }, 880 | ]); 881 | 882 | static fromBinary(bytes: Uint8Array, options?: Partial): CompletionItem { 883 | return new CompletionItem().fromBinary(bytes, options); 884 | } 885 | 886 | static fromJson(jsonValue: JsonValue, options?: Partial): CompletionItem { 887 | return new CompletionItem().fromJson(jsonValue, options); 888 | } 889 | 890 | static fromJsonString(jsonString: string, options?: Partial): CompletionItem { 891 | return new CompletionItem().fromJsonString(jsonString, options); 892 | } 893 | 894 | static equals(a: CompletionItem | PlainMessage | undefined, b: CompletionItem | PlainMessage | undefined): boolean { 895 | return proto3.util.equals(CompletionItem, a, b); 896 | } 897 | } 898 | 899 | -------------------------------------------------------------------------------- /src/codeium.ts: -------------------------------------------------------------------------------- 1 | import { createPromiseClient } from "@connectrpc/connect"; 2 | import { LanguageServerService } from "./api/proto/exa/language_server_pb/language_server_connect.js"; 3 | import { createConnectTransport } from "@connectrpc/connect-web"; 4 | import type { 5 | Document, 6 | GetCompletionsResponse, 7 | } from "./api/proto/exa/language_server_pb/language_server_pb.js"; 8 | import type { CodeiumConfig } from "./config.js"; 9 | import type { PartialMessage } from "@bufbuild/protobuf"; 10 | import type { SimpleChangeSpec } from "./types.js"; 11 | 12 | // This is the same as the monaco editor example 13 | const transport = createConnectTransport({ 14 | baseUrl: "https://web-backend.codeium.com", 15 | useBinaryFormat: true, 16 | }); 17 | 18 | const client = createPromiseClient(LanguageServerService, transport); 19 | 20 | let sessionId: string; 21 | try { 22 | /** 23 | * Note that this won't be available in 'insecure contexts', 24 | * websites served under HTTP not HTTPS, but those are rare. 25 | * And it'll work in localhost for development. 26 | */ 27 | sessionId = crypto.randomUUID(); 28 | } catch { 29 | // When not in a secure context 30 | // https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid 31 | function uuidv4() { 32 | return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => 33 | (+c ^ (crypto.getRandomValues(new Uint8Array(1))[0] ?? 0) & 15 >> +c / 4).toString(16) 34 | ); 35 | } 36 | sessionId = uuidv4(); 37 | } 38 | 39 | export async function getCodeiumCompletions({ 40 | text, 41 | cursorOffset, 42 | config, 43 | otherDocuments, 44 | }: { 45 | text: string; 46 | cursorOffset: number; 47 | config: CodeiumConfig; 48 | otherDocuments: PartialMessage[]; 49 | }) { 50 | return (await client.getCompletions( 51 | { 52 | metadata: { 53 | ideName: "web", 54 | ideVersion: "0.0.5", 55 | extensionName: "@valtown/codemirror-codeium", 56 | extensionVersion: "1.0.0", 57 | apiKey: config.apiKey, 58 | sessionId: sessionId, 59 | authSource: config.authSource, 60 | }, 61 | document: { 62 | text: text, 63 | cursorOffset: BigInt(cursorOffset), 64 | language: config.language, 65 | // TODO: not sure why we have both language and 66 | // editorlanguage 67 | // The types don't like this here, but it works. 68 | editorLanguage: "typescript", 69 | lineEnding: "\n", 70 | }, 71 | editorOptions: { 72 | tabSize: 2n, 73 | insertSpaces: true, 74 | }, 75 | otherDocuments: otherDocuments, 76 | multilineConfig: undefined, 77 | }, 78 | { 79 | // signal, 80 | headers: { 81 | Authorization: `Basic ${config.apiKey}-${sessionId}`, 82 | }, 83 | }, 84 | // TODO: why doesn't this work by default? 85 | )) as GetCompletionsResponse; 86 | } 87 | 88 | /** 89 | * Make the body of the response a bit easier to work with: 90 | * turn a BigInt into an int in the response so that it can 91 | * be used with CodeMirror directly, and avoid using some 92 | * complex kinds of completions. 93 | */ 94 | export function completionsToChangeSpec( 95 | completions: GetCompletionsResponse, 96 | ): SimpleChangeSpec[][] { 97 | return completions.completionItems.map((item) => { 98 | /** 99 | * Add absolute offsets for the suggestion text insertions 100 | * so that we can add matching decorations. 101 | */ 102 | let combinedOffset = 0; 103 | return item.completionParts 104 | .filter((part) => { 105 | // Type 3 overwrites existing text. Maybe we need this eventually, 106 | // but not right now and it usually is duplicative. 107 | return part.type !== 3; 108 | }) 109 | .map((part): SimpleChangeSpec => { 110 | const offset = Number(part.offset); 111 | const text = part.type === 2 ? `\n${part.text}` : part.text; 112 | const res: SimpleChangeSpec = { 113 | absoluteStartPos: combinedOffset + offset, 114 | absoluteEndPos: combinedOffset + offset + text.length, 115 | from: offset, 116 | to: offset, 117 | insert: text, 118 | }; 119 | combinedOffset += text.length; 120 | return res; 121 | }); 122 | }); 123 | } 124 | -------------------------------------------------------------------------------- /src/commands.ts: -------------------------------------------------------------------------------- 1 | import { Transaction, EditorSelection, ChangeSet } from "@codemirror/state"; 2 | import type { Command, EditorView } from "@codemirror/view"; 3 | import { copilotEvent, copilotIgnore } from "./annotations.js"; 4 | import { completionDecoration } from "./completionDecoration.js"; 5 | import { 6 | acceptSuggestion, 7 | addSuggestions, 8 | clearSuggestion, 9 | } from "./effects.js"; 10 | import { requestCompletion } from "./requestCompletion.js"; 11 | 12 | /** 13 | * Accepting a suggestion: we remove the ghost text, which 14 | * was not part of CodeMirror history, and then re-add it, 15 | * making sure that it _is_ added to history, and we remove 16 | * the Decoration that was making that ghost text look ghostly. 17 | */ 18 | export function acceptSuggestionCommand(view: EditorView) { 19 | // We delete the ghost text and insert the suggestion. 20 | // We also set the cursor to the end of the suggestion. 21 | const stateField = view.state.field(completionDecoration); 22 | 23 | if (!stateField) { 24 | return false; 25 | } 26 | 27 | const reverseReverseChangeSet = stateField.reverseChangeSet?.invert( 28 | view.state.doc, 29 | ); 30 | 31 | // This is removing the previous ghost text. 32 | view.dispatch({ 33 | changes: stateField.reverseChangeSet, 34 | effects: acceptSuggestion.of(null), 35 | annotations: [ 36 | // Tell upstream integrations to ignore this 37 | // change. 38 | copilotIgnore.of(null), 39 | // Tell ourselves not to request a completion 40 | // because of this change. 41 | copilotEvent.of(null), 42 | // Don't add this to history. 43 | Transaction.addToHistory.of(false), 44 | ], 45 | }); 46 | 47 | let lastIndex = 0; 48 | reverseReverseChangeSet?.iterChangedRanges((_fromA, _toA, _fromB, toB) => { 49 | lastIndex = toB; 50 | }); 51 | 52 | view.dispatch({ 53 | changes: reverseReverseChangeSet, 54 | selection: EditorSelection.cursor(lastIndex), 55 | annotations: [copilotEvent.of(null), Transaction.addToHistory.of(true)], 56 | }); 57 | 58 | return true; 59 | } 60 | 61 | /** 62 | * Cycle through suggested AI completed code. 63 | */ 64 | export const nextSuggestionCommand: Command = (view: EditorView) => { 65 | const { state } = view; 66 | // We delete the suggestion, then carry through with the original keypress 67 | const stateField = state.field(completionDecoration); 68 | 69 | if (!stateField) { 70 | return false; 71 | } 72 | 73 | const { changeSpecs } = stateField; 74 | 75 | if (changeSpecs.length < 2) { 76 | return false; 77 | } 78 | 79 | // Loop through next suggestion. 80 | const index = (stateField.index + 1) % changeSpecs.length; 81 | const nextSpec = changeSpecs.at(index); 82 | if (!nextSpec) { 83 | return false; 84 | } 85 | 86 | /** 87 | * First, get the original document, by applying the stored 88 | * reverse changeset against the currently-displayed document. 89 | */ 90 | const originalDocument = stateField.reverseChangeSet.apply(state.doc); 91 | 92 | /** 93 | * Get the changeset that we will apply that will 94 | * 95 | * 1. Reverse the currently-displayed suggestion, to get us back to 96 | * the original document 97 | * 2. Apply the next suggestion. 98 | * 99 | * It does both in the same changeset, so there is no flickering. 100 | */ 101 | const reverseCurrentSuggestionAndApplyNext = ChangeSet.of( 102 | stateField.reverseChangeSet, 103 | state.doc.length, 104 | ).compose(ChangeSet.of(nextSpec, originalDocument.length)); 105 | 106 | /** 107 | * Generate the next changeset 108 | */ 109 | const nextSet = ChangeSet.of(nextSpec, originalDocument.length); 110 | const reverseChangeSet = nextSet.invert(originalDocument); 111 | 112 | view.dispatch({ 113 | changes: reverseCurrentSuggestionAndApplyNext, 114 | effects: addSuggestions.of({ 115 | index, 116 | reverseChangeSet, 117 | changeSpecs, 118 | }), 119 | annotations: [ 120 | // Tell upstream integrations to ignore this 121 | // change. 122 | copilotIgnore.of(null), 123 | // Tell ourselves not to request a completion 124 | // because of this change. 125 | copilotEvent.of(null), 126 | // Don't add this to history. 127 | Transaction.addToHistory.of(false), 128 | ], 129 | }); 130 | 131 | return true; 132 | }; 133 | 134 | /** 135 | * Rejecting a suggestion: this looks at the currently-shown suggestion 136 | * and reverses it, clears the suggestion, and makes sure 137 | * that we don't add that clearing transaction to history and we don't 138 | * trigger a new suggestion because of it. 139 | */ 140 | export function rejectSuggestionCommand(view: EditorView) { 141 | // We delete the suggestion, then carry through with the original keypress 142 | const stateField = view.state.field(completionDecoration); 143 | 144 | if (!stateField) { 145 | return false; 146 | } 147 | 148 | view.dispatch({ 149 | changes: stateField.reverseChangeSet, 150 | effects: clearSuggestion.of(null), 151 | annotations: [ 152 | // Tell upstream integrations to ignore this 153 | // change. This was never really in the document 154 | // in the first place - we were just showing ghost text. 155 | copilotIgnore.of(null), 156 | copilotEvent.of(null), 157 | Transaction.addToHistory.of(false), 158 | ], 159 | }); 160 | 161 | return false; 162 | } 163 | 164 | // TODO: this isn't full reimplemented yet. 165 | export function sameKeyCommand(view: EditorView, key: string) { 166 | // When we type a key that is the same as the first letter of the suggestion, we delete the first letter of the suggestion and carry through with the original keypress 167 | const stateField = view.state.field(completionDecoration); 168 | 169 | if (!stateField) { 170 | return false; 171 | } 172 | 173 | if (key === "Tab") { 174 | return acceptSuggestionCommand(view); 175 | } 176 | return rejectSuggestionCommand(view); 177 | } 178 | 179 | export const startCompletion: Command = (view: EditorView) => { 180 | requestCompletion(view); 181 | return true; 182 | }; 183 | -------------------------------------------------------------------------------- /src/completionDecoration.ts: -------------------------------------------------------------------------------- 1 | import { 2 | StateField, 3 | type EditorState, 4 | type Transaction, 5 | } from "@codemirror/state"; 6 | import { Decoration, EditorView } from "@codemirror/view"; 7 | import { 8 | addSuggestions, 9 | acceptSuggestion, 10 | clearSuggestion, 11 | } from "./effects.js"; 12 | import type { CompletionState } from "./types.js"; 13 | import { codeiumConfig } from "./config.js"; 14 | 15 | const ghostMark = Decoration.mark({ class: "cm-ghostText" }); 16 | 17 | /** 18 | * Note that the completion _text_ is not actually a decoration! 19 | * The text is very real, and actually inserted into the editor. 20 | * The completion decoration is just a decoration that matches 21 | * the same range as the completion text, and changes how it looks. 22 | */ 23 | export const completionDecoration = StateField.define({ 24 | create(_state: EditorState) { 25 | return null; 26 | }, 27 | update(state: CompletionState, transaction: Transaction) { 28 | const config = transaction.state.facet(codeiumConfig); 29 | for (const effect of transaction.effects) { 30 | if (effect.is(addSuggestions)) { 31 | const { changeSpecs, index } = effect.value; 32 | 33 | // NOTE: here we're adjusting the decoration range 34 | // to refer to locations in the document _after_ we've 35 | // inserted the text. 36 | const ranges = changeSpecs[index]!.map((suggestionRange) => { 37 | const range = ghostMark.range( 38 | suggestionRange.absoluteStartPos, 39 | suggestionRange.absoluteEndPos, 40 | ); 41 | return range; 42 | }); 43 | const widgetPos = ranges.at(-1)?.to; 44 | 45 | const decorations = Decoration.set([ 46 | ...ranges, 47 | ...(widgetPos !== undefined && 48 | changeSpecs.length > 1 && 49 | config.widgetClass 50 | ? [ 51 | Decoration.widget({ 52 | widget: new config.widgetClass(index, changeSpecs.length), 53 | side: 1, 54 | }).range(widgetPos), 55 | ] 56 | : []), 57 | ]); 58 | 59 | return { 60 | index, 61 | decorations, 62 | changeSpecs, 63 | reverseChangeSet: effect.value.reverseChangeSet, 64 | }; 65 | } 66 | if (effect.is(acceptSuggestion)) { 67 | return null; 68 | } 69 | if (effect.is(clearSuggestion)) { 70 | return null; 71 | } 72 | } 73 | 74 | if (state) { 75 | // If we ever have a state that is being updated, 76 | // map it through the new changes to avoid the potential 77 | // of a mismatch between it and the new document and new 78 | // document length 79 | return { 80 | ...state, 81 | decorations: state.decorations.map(transaction.changes), 82 | reverseChangeSet: state.reverseChangeSet.map(transaction.changes), 83 | }; 84 | } 85 | 86 | return state; 87 | }, 88 | provide: (field) => 89 | EditorView.decorations.from(field, (value) => { 90 | return value?.decorations || Decoration.none; 91 | }), 92 | }); 93 | -------------------------------------------------------------------------------- /src/completionRequester.ts: -------------------------------------------------------------------------------- 1 | import { CompletionContext, completionStatus } from "@codemirror/autocomplete"; 2 | import { EditorView, type ViewUpdate } from "@codemirror/view"; 3 | import { acceptSuggestion, clearSuggestion } from "./effects.js"; 4 | import { completionDecoration } from "./completionDecoration.js"; 5 | import { copilotEvent } from "./annotations.js"; 6 | import { codeiumConfig } from "./config.js"; 7 | import { requestCompletion } from "./requestCompletion.js"; 8 | 9 | /** 10 | * To request a completion, the document needs to have been 11 | * updated and the update should not have been because 12 | * of accepting or clearing a suggestion. 13 | */ 14 | function shouldRequestCompletion(update: ViewUpdate) { 15 | return ( 16 | update.docChanged && 17 | !update.transactions.some((tr) => 18 | tr.effects.some((e) => e.is(acceptSuggestion) || e.is(clearSuggestion)), 19 | ) 20 | ); 21 | } 22 | 23 | /** 24 | * Don't request a completion if we've already 25 | * done so, or it's a copilot event we're responding 26 | * to, or if the view is not focused. 27 | */ 28 | function shouldIgnoreUpdate(update: ViewUpdate) { 29 | // not focused 30 | if (!update.view.hasFocus) return true; 31 | 32 | // contains ghost text 33 | if (update.state.field(completionDecoration)) return true; 34 | 35 | // is autocompleting 36 | if (completionStatus(update.state) === "active") return true; 37 | 38 | // bad update 39 | for (const tr of update.transactions) { 40 | if (tr.annotation(copilotEvent) !== undefined) { 41 | return true; 42 | } 43 | } 44 | } 45 | 46 | /** 47 | * A view plugin that requests completions from the server after a delay 48 | */ 49 | export function completionRequester() { 50 | let timeout: number | null = null; 51 | let lastPos = 0; 52 | 53 | return EditorView.updateListener.of((update: ViewUpdate) => { 54 | const config = update.view.state.facet(codeiumConfig); 55 | if (!config.alwaysOn) return; 56 | 57 | if (!shouldRequestCompletion(update)) return; 58 | 59 | // Cancel the previous timeout 60 | if (timeout) { 61 | clearTimeout(timeout); 62 | } 63 | 64 | if (shouldIgnoreUpdate(update)) { 65 | return; 66 | } 67 | 68 | // Get the current position and source 69 | const state = update.state; 70 | const pos = state.selection.main.head; 71 | 72 | // If we've configured a custom rule for when to show completions 73 | // and that rule says no, don't offer completions. 74 | if ( 75 | config.shouldComplete && 76 | !config.shouldComplete( 77 | new CompletionContext(update.view.state, pos, false), 78 | ) 79 | ) { 80 | return; 81 | } 82 | 83 | // Set a new timeout to request completion 84 | timeout = setTimeout(async () => { 85 | // Check if the position has changed 86 | if (pos !== lastPos) return; 87 | 88 | await requestCompletion(update.view, lastPos); 89 | }, config.timeout); 90 | 91 | // Update the last position 92 | lastPos = pos; 93 | }); 94 | } 95 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import { Facet, combineConfig } from "@codemirror/state"; 2 | import { Language } from "./api/proto/exa/codeium_common_pb/codeium_common_pb.js"; 3 | import type { Document } from "./api/proto/exa/language_server_pb/language_server_pb.js"; 4 | import type { PartialMessage } from "@bufbuild/protobuf"; 5 | import type { CompletionContext } from "@codemirror/autocomplete"; 6 | import { DefaultCycleWidget } from "./defaultCycleWidget.js"; 7 | 8 | export interface CodeiumConfig { 9 | /** 10 | * Codeium API key 11 | */ 12 | apiKey: string; 13 | 14 | /** 15 | * The programming language of the given document. 16 | */ 17 | language?: Language; 18 | /** 19 | * Time in millseconds after typing to fetch 20 | * completions from codeium 21 | */ 22 | timeout?: number; 23 | 24 | authSource?: number; 25 | 26 | /** 27 | * An optional method that lets you decide whether Codeium 28 | * should be triggered at a particular place in a document. 29 | * 30 | * Might be useful for if you're fighting with overlapping 31 | * autocomplete sources. 32 | */ 33 | shouldComplete?: (context: CompletionContext) => boolean; 34 | 35 | /** 36 | * The class for the widget that is shown at the end a suggestion 37 | * when there are multiple suggestions to cycle through. 38 | */ 39 | widgetClass?: typeof DefaultCycleWidget | null; 40 | 41 | /** 42 | * Always request completions after a delay 43 | */ 44 | alwaysOn?: boolean; 45 | } 46 | 47 | export const codeiumConfig = Facet.define< 48 | CodeiumConfig, 49 | Required 50 | >({ 51 | combine(configs) { 52 | return combineConfig>( 53 | configs, 54 | { 55 | language: Language.TYPESCRIPT, 56 | timeout: 150, 57 | widgetClass: DefaultCycleWidget, 58 | alwaysOn: true, 59 | }, 60 | {}, 61 | ); 62 | }, 63 | }); 64 | 65 | type OtherDocuments = PartialMessage[]; 66 | 67 | export interface CodeiumOtherDocumentsConfig { 68 | override?: () => Promise | OtherDocuments; 69 | } 70 | 71 | /** 72 | * Configuration for other documents included with the completion 73 | * request. Adding other documents helps you get more accurate 74 | * suggestions by adding context. 75 | */ 76 | export const codeiumOtherDocumentsConfig = Facet.define< 77 | CodeiumOtherDocumentsConfig, 78 | Required 79 | >({ 80 | combine(configs) { 81 | return combineConfig>( 82 | configs, 83 | { 84 | override: () => [], 85 | }, 86 | {}, 87 | ); 88 | }, 89 | }); 90 | -------------------------------------------------------------------------------- /src/defaultCycleWidget.ts: -------------------------------------------------------------------------------- 1 | import { WidgetType } from "@codemirror/view"; 2 | 3 | /** 4 | * Shown at the end of a suggestion if there are multiple 5 | * suggestions to cycle through. 6 | */ 7 | export class DefaultCycleWidget extends WidgetType { 8 | index: number; 9 | total: number; 10 | 11 | constructor(index: number, total: number) { 12 | super(); 13 | this.index = index; 14 | this.total = total; 15 | } 16 | 17 | toDOM() { 18 | const wrap = document.createElement("span"); 19 | wrap.setAttribute("aria-hidden", "true"); 20 | wrap.className = "cm-codeium-cycle"; 21 | const words = wrap.appendChild(document.createElement("span")); 22 | words.className = "cm-codeium-cycle-explanation"; 23 | words.innerText = `${this.index + 1}/${this.total}`; 24 | const key = wrap.appendChild(document.createElement("button")); 25 | key.className = "cm-codeium-cycle-key"; 26 | key.innerText = "→ (Ctrl ])"; 27 | key.dataset.action = "codeium-cycle"; 28 | return wrap; 29 | } 30 | 31 | ignoreEvent() { 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/effects.ts: -------------------------------------------------------------------------------- 1 | import { StateEffect } from "@codemirror/state"; 2 | import type { AddSuggestionsState } from "./types.js"; 3 | 4 | // Effects to tell StateEffect what to do with GhostText 5 | export const addSuggestions = StateEffect.define(); 6 | export const acceptSuggestion = StateEffect.define(); 7 | export const clearSuggestion = StateEffect.define(); 8 | -------------------------------------------------------------------------------- /src/plugin.ts: -------------------------------------------------------------------------------- 1 | import { EditorView, keymap, type ViewUpdate } from "@codemirror/view"; 2 | import { type Extension, Prec } from "@codemirror/state"; 3 | import { completionDecoration } from "./completionDecoration.js"; 4 | import { completionRequester } from "./completionRequester.js"; 5 | import { 6 | sameKeyCommand, 7 | rejectSuggestionCommand, 8 | acceptSuggestionCommand, 9 | nextSuggestionCommand, 10 | startCompletion, 11 | } from "./commands.js"; 12 | import { 13 | type CodeiumConfig, 14 | type CodeiumOtherDocumentsConfig, 15 | codeiumConfig, 16 | codeiumOtherDocumentsConfig, 17 | } from "./config.js"; 18 | import { Language } from "./api/proto/exa/codeium_common_pb/codeium_common_pb.js"; 19 | import { copilotIgnore } from "./annotations.js"; 20 | 21 | /** 22 | * Clicking a completion accepts it. This figures out 23 | * whether a given click event is within the completion's area. 24 | */ 25 | function isDecorationClicked(view: EditorView): boolean { 26 | let inRange = false; 27 | const head = view.state.selection.asSingle().ranges.at(0)?.head; 28 | const stateField = view.state.field(completionDecoration); 29 | if (head !== undefined && stateField) { 30 | stateField.decorations?.between(head, head, () => { 31 | inRange = true; 32 | }); 33 | return inRange; 34 | } 35 | return false; 36 | } 37 | 38 | /** 39 | * Handles the behavior in which if you have a completion like 40 | * 41 | * foo|bar 42 | * 43 | * (the cursor is at |) and you type an x, it rejects 44 | * the completion because that isn't part of the suggested 45 | * code. 46 | */ 47 | function completionPlugin() { 48 | return EditorView.domEventHandlers({ 49 | keydown(event, view) { 50 | // Ideally, we handle infighting between 51 | // the nextSuggestionCommand and this handler 52 | // by using precedence, but I can't get that to work 53 | // yet. 54 | if (event.key === "]" && event.ctrlKey) { 55 | return false; 56 | } 57 | if ( 58 | event.key !== "Shift" && 59 | event.key !== "Control" && 60 | event.key !== "Alt" && 61 | event.key !== "Meta" 62 | ) { 63 | return sameKeyCommand(view, event.key); 64 | } 65 | return false; 66 | }, 67 | mouseup(event, view) { 68 | const target = event.target as HTMLElement; 69 | if ( 70 | target.nodeName === "BUTTON" && 71 | target.dataset.action === "codeium-cycle" 72 | ) { 73 | nextSuggestionCommand(view); 74 | event.stopPropagation(); 75 | event.preventDefault(); 76 | return true; 77 | } 78 | if (isDecorationClicked(view)) { 79 | return acceptSuggestionCommand(view); 80 | } 81 | return rejectSuggestionCommand(view); 82 | }, 83 | }); 84 | } 85 | 86 | /** 87 | * Next completion map 88 | */ 89 | function nextCompletionPlugin() { 90 | return keymap.of([ 91 | { 92 | key: "Ctrl-]", 93 | run: nextSuggestionCommand, 94 | }, 95 | ]); 96 | } 97 | 98 | /** 99 | * Changing the editor's focus - blurring it by clicking outside - 100 | * rejects the suggestion 101 | */ 102 | function viewCompletionPlugin() { 103 | return EditorView.updateListener.of((update) => { 104 | if (update.focusChanged) { 105 | rejectSuggestionCommand(update.view); 106 | } 107 | }); 108 | } 109 | 110 | export { 111 | Language, 112 | copilotIgnore, 113 | codeiumConfig, 114 | codeiumOtherDocumentsConfig, 115 | nextSuggestionCommand, 116 | startCompletion, 117 | type CodeiumOtherDocumentsConfig, 118 | type CodeiumConfig, 119 | }; 120 | 121 | /** 122 | * A combination of configuration, the keymap, the 123 | * requester - as a composite extension for simplicity. 124 | */ 125 | export function copilotPlugin(config: CodeiumConfig): Extension { 126 | return [ 127 | codeiumConfig.of(config), 128 | completionDecoration, 129 | Prec.highest(nextCompletionPlugin()), 130 | Prec.highest(viewCompletionPlugin()), 131 | Prec.high(completionPlugin()), 132 | completionRequester(), 133 | ]; 134 | } 135 | 136 | /** 137 | * Returns false if this ViewUpdate is just the plugin 138 | * adding or removing ghost text, and it should not be 139 | * considered when saving this CodeMirror state into other 140 | * systems, like draft recovery. 141 | */ 142 | export function shouldTakeUpdate(update: ViewUpdate) { 143 | for (const tr of update.transactions) { 144 | if (tr.annotation(copilotIgnore) !== undefined) { 145 | return false; 146 | } 147 | } 148 | return true; 149 | } 150 | -------------------------------------------------------------------------------- /src/requestCompletion.ts: -------------------------------------------------------------------------------- 1 | import { completionStatus } from "@codemirror/autocomplete"; 2 | import { ChangeSet, Transaction } from "@codemirror/state"; 3 | import type { EditorView } from "@codemirror/view"; 4 | import { completionsToChangeSpec, getCodeiumCompletions } from "./codeium.js"; 5 | import { addSuggestions } from "./effects.js"; 6 | import { copilotEvent, copilotIgnore } from "./annotations.js"; 7 | import { codeiumConfig, codeiumOtherDocumentsConfig } from "./config.js"; 8 | 9 | /** 10 | * Inner 'requestCompletion' API, which can optionally 11 | * be run all the time if you set `alwaysOn` 12 | */ 13 | export async function requestCompletion(view: EditorView, lastPos?: number) { 14 | const config = view.state.facet(codeiumConfig); 15 | const { override } = view.state.facet(codeiumOtherDocumentsConfig); 16 | 17 | const otherDocuments = await override(); 18 | 19 | // Get the current position and source 20 | const state = view.state; 21 | const pos = state.selection.main.head; 22 | const source = state.doc.toString(); 23 | 24 | // Request completion from the server 25 | try { 26 | const completionResult = await getCodeiumCompletions({ 27 | text: source, 28 | cursorOffset: pos, 29 | config, 30 | otherDocuments, 31 | }); 32 | 33 | if (!completionResult || completionResult.completionItems.length === 0) { 34 | return; 35 | } 36 | 37 | // Check if the position is still the same. If 38 | // it has changed, ignore the code that we just 39 | // got from the API and don't show anything. 40 | if ( 41 | !( 42 | (lastPos === undefined || pos === lastPos) && 43 | completionStatus(view.state) !== "active" && 44 | view.hasFocus 45 | ) 46 | ) { 47 | return; 48 | } 49 | 50 | // Dispatch an effect to add the suggestion 51 | // If the completion starts before the end of the line, 52 | // check the end of the line with the end of the completion 53 | const changeSpecs = completionsToChangeSpec(completionResult); 54 | 55 | const index = 0; 56 | const firstSpec = changeSpecs.at(index); 57 | if (!firstSpec) return; 58 | const insertChangeSet = ChangeSet.of(firstSpec, state.doc.length); 59 | const reverseChangeSet = insertChangeSet.invert(state.doc); 60 | 61 | view.dispatch({ 62 | changes: insertChangeSet, 63 | effects: addSuggestions.of({ 64 | index, 65 | reverseChangeSet, 66 | changeSpecs, 67 | }), 68 | annotations: [ 69 | copilotIgnore.of(null), 70 | copilotEvent.of(null), 71 | Transaction.addToHistory.of(false), 72 | ], 73 | }); 74 | } catch (error) { 75 | console.warn("copilot completion failed", error); 76 | // Javascript wait for 300ms for some reason is necessary here. 77 | // TODO - FIGURE OUT WHY THIS RESOLVES THE BUG 78 | 79 | await new Promise((resolve) => setTimeout(resolve, 300)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import type { Range, ChangeSet } from "@codemirror/state"; 2 | import type { Decoration, DecorationSet } from "@codemirror/view"; 3 | 4 | /** 5 | * We dispatch an effect that updates the CompletionState. 6 | * CompletionState is null if no completions are displayed. 7 | */ 8 | export type CompletionState = null | { 9 | index: number; 10 | reverseChangeSet: ChangeSet; 11 | changeSpecs: SimpleChangeSpec[][]; 12 | decorations: DecorationSet; 13 | }; 14 | 15 | export type AddSuggestionsState = { 16 | reverseChangeSet: ChangeSet; 17 | changeSpecs: SimpleChangeSpec[][]; 18 | index: number; 19 | }; 20 | 21 | export interface GhostText { 22 | text: string; 23 | displayPos: number; 24 | startPos: number; 25 | endGhostText: number; 26 | endPos: number; 27 | decorations: DecorationSet; 28 | } 29 | 30 | /** 31 | * This is one of the variants of a ChangeSpec, 32 | * plus the absoluteStartPos and absoluteEndPos 33 | * properties. 34 | */ 35 | export type SimpleChangeSpec = { 36 | absoluteStartPos: number; 37 | absoluteEndPos: number; 38 | from: number; 39 | to: number; 40 | insert: string; 41 | }; 42 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationMap": true, 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "inlineSources": true, 8 | "jsx": "react", 9 | "module": "nodenext", 10 | "moduleResolution": "nodenext", 11 | "noUncheckedIndexedAccess": true, 12 | "resolveJsonModule": true, 13 | "skipLibCheck": true, 14 | "sourceMap": true, 15 | "strict": true, 16 | "target": "es2022", 17 | "rootDir": "./src", 18 | "outDir": "./dist" 19 | }, 20 | "exclude": ["./demo", "./dist"] 21 | } 22 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('vite').UserConfig} */ 2 | export default { 3 | root: process.env.VITEST ? "." : "demo", 4 | outDir: "build", 5 | base: "/codemirror-codeium/", 6 | }; 7 | --------------------------------------------------------------------------------