@valtown/codemirror-codeium
Version:
codemirror integration for codeium
95 lines • 3.48 kB
JavaScript
import { createPromiseClient } from "@connectrpc/connect";
import { LanguageServerService } from "./api/proto/exa/language_server_pb/language_server_connect.js";
import { createConnectTransport } from "@connectrpc/connect-web";
// This is the same as the monaco editor example
const transport = createConnectTransport({
baseUrl: "https://web-backend.codeium.com",
useBinaryFormat: true,
});
const client = createPromiseClient(LanguageServerService, transport);
let sessionId;
try {
/**
* Note that this won't be available in 'insecure contexts',
* websites served under HTTP not HTTPS, but those are rare.
* And it'll work in localhost for development.
*/
sessionId = crypto.randomUUID();
}
catch {
// When not in a secure context
// https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid
function uuidv4() {
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => (+c ^ (crypto.getRandomValues(new Uint8Array(1))[0] ?? 0) & 15 >> +c / 4).toString(16));
}
sessionId = uuidv4();
}
export async function getCodeiumCompletions({ text, cursorOffset, config, otherDocuments, }) {
return (await client.getCompletions({
metadata: {
ideName: "web",
ideVersion: "0.0.5",
extensionName: "@valtown/codemirror-codeium",
extensionVersion: "1.0.0",
apiKey: config.apiKey,
sessionId: sessionId,
authSource: config.authSource,
},
document: {
text: text,
cursorOffset: BigInt(cursorOffset),
language: config.language,
// TODO: not sure why we have both language and
// editorlanguage
// The types don't like this here, but it works.
editorLanguage: "typescript",
lineEnding: "\n",
},
editorOptions: {
tabSize: 2n,
insertSpaces: true,
},
otherDocuments: otherDocuments,
multilineConfig: undefined,
}, {
// signal,
headers: {
Authorization: `Basic ${config.apiKey}-${sessionId}`,
},
}));
}
/**
* Make the body of the response a bit easier to work with:
* turn a BigInt into an int in the response so that it can
* be used with CodeMirror directly, and avoid using some
* complex kinds of completions.
*/
export function completionsToChangeSpec(completions) {
return completions.completionItems.map((item) => {
/**
* Add absolute offsets for the suggestion text insertions
* so that we can add matching decorations.
*/
let combinedOffset = 0;
return item.completionParts
.filter((part) => {
// Type 3 overwrites existing text. Maybe we need this eventually,
// but not right now and it usually is duplicative.
return part.type !== 3;
})
.map((part) => {
const offset = Number(part.offset);
const text = part.type === 2 ? `\n${part.text}` : part.text;
const res = {
absoluteStartPos: combinedOffset + offset,
absoluteEndPos: combinedOffset + offset + text.length,
from: offset,
to: offset,
insert: text,
};
combinedOffset += text.length;
return res;
});
});
}
//# sourceMappingURL=codeium.js.map