Skip to content

Commit 40c8533

Browse files
committed
feat: relocate codeium api request from server to client
As part of this, I had to build the protobuf file into a set of "json definitions" that I could more easily include in a javascript bundle vs the raw bytes of a proto file.
1 parent 07ca468 commit 40c8533

10 files changed

Lines changed: 566 additions & 58 deletions

File tree

packages/api/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@
3131
"depcheck": "^1.4.7",
3232
"drizzle-orm": "^0.33.0",
3333
"express": "^4.20.0",
34-
"long": "^5.2.3",
3534
"marked": "catalog:",
3635
"posthog-node": "^4.2.0",
37-
"protobufjs": "^7.4.0",
3836
"ws": "catalog:",
3937
"zod": "catalog:"
4038
},

packages/api/server/http.mts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
exportSrcmdText,
1515
} from '../session.mjs';
1616
import { generateCells, generateSrcbook, healthcheck } from '../ai/generate.mjs';
17-
import { runCodiumAiAutocomplete } from '../ai/autocomplete/index.mjs';
1817
import {
1918
getConfig,
2019
updateConfig,
@@ -348,21 +347,6 @@ router.post('/feedback', cors(), async (req, res) => {
348347
return res.json({ success: result.ok });
349348
});
350349

351-
router.options('/ai-autocomplete', cors());
352-
router.post('/ai-autocomplete', cors(), async (req, res) => {
353-
const { source, cursorOffset } = req.body;
354-
const config = await getConfig();
355-
356-
let result;
357-
try {
358-
result = await runCodiumAiAutocomplete(config.codeiumApiKey, source, cursorOffset);
359-
} catch (err) {
360-
console.error('Error running ai autocomplete:', err);
361-
return res.json({ error: true });
362-
}
363-
return res.json({ error: false, result });
364-
});
365-
366350
type NpmSearchResult = {
367351
package: {
368352
name: string;

packages/web/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@
2727
"clsx": "^2.1.1",
2828
"codemirror": "^6.0.1",
2929
"codemirror-copilot": "^0.0.7",
30+
"long": "^5.2.3",
3031
"lucide-react": "^0.439.0",
3132
"marked": "catalog:",
33+
"protobufjs": "^7.4.0",
3234
"react": "^18.3.1",
3335
"react-dom": "^18.3.1",
3436
"react-dropzone": "^14.2.3",

packages/web/src/components/cells/code.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import { SessionChannel } from '@/clients/websocket';
1818
import { useCells } from '@srcbook/components/src/components/use-cell';
1919
import { mapCMLocationToTsServer, mapTsServerLocationToCM } from './util';
2020
import { toast } from 'sonner';
21-
import { getFileContent, runCodiumAiAutocomplete } from '@/lib/server';
21+
import { getFileContent } from '@/lib/server';
22+
import { runCodiumAiAutocomplete } from '@/lib/ai-autocomplete';
2223
import { tsHover } from '@/components/cells/hover';
2324
import { autocompletion } from '@codemirror/autocomplete';
2425
import { type Diagnostic, linter } from '@codemirror/lint';
@@ -137,7 +138,7 @@ export default function ControlledCodeCell(props: Props) {
137138
const [prompt, setPrompt] = useState('');
138139
const [newSource, setNewSource] = useState('');
139140
const [fullscreen, setFullscreen] = useState(false);
140-
const { aiEnabled } = useSettings();
141+
const { aiEnabled, codeiumApiKey } = useSettings();
141142

142143
const [isModalOpen, setIsModalOpen] = useState(false);
143144
const [modalContent, setModalContent] = useState('');
@@ -384,17 +385,17 @@ export default function ControlledCodeCell(props: Props) {
384385
inlineCopilot(async (prefix, suffix) => {
385386
let response;
386387
try {
387-
response = await runCodiumAiAutocomplete(prefix+suffix, prefix.length);
388+
response = await runCodiumAiAutocomplete(
389+
codeiumApiKey ?? null,
390+
prefix+suffix,
391+
prefix.length,
392+
);
388393
} catch (err) {
389394
console.error('Error fetching ai autocomplete suggestion:', err);
390395
return "";
391396
}
392397

393-
if (response.error) {
394-
return "";
395-
}
396-
397-
const completionItems = response.result.completionItems ?? [];
398+
const completionItems = response.completionItems ?? [];
398399
const mostLikelyCompletionScore = Math.min(...completionItems.map(item => item.completion.score));
399400
const mostLikelyCompletion = completionItems.find(item => item.completion.score === mostLikelyCompletionScore);
400401

File renamed without changes.

packages/api/ai/autocomplete/index.mts renamed to packages/web/src/lib/ai-autocomplete/index.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import path from 'node:path';
21
import protobuf from 'protobufjs';
32
import Long from 'long';
43
import { type CodiumCompletionResult } from "@srcbook/shared";
54

5+
import languageServerProto from "./language-server-proto";
6+
67
// NOTE: this EDITOR_API_KEY value was just included as a raw string in
78
// @codeium/react-code-editor. This seems to not be a secret?
89
const EDITOR_API_KEY = 'd49954eb-cfba-4992-980f-d8fb37f0e942';
9-
const LANGUAGE_SERVER_PROTO_FILE_PATH = path.join(__dirname, "language_server.proto");
1010

1111
export async function runCodiumAiAutocomplete(
12-
apiKey: string | null,
12+
optionalApiKey: string | null,
1313
source: string,
1414
cursorOffset: number,
1515
): Promise<CodiumCompletionResult> {
16-
const protos = await protobuf.load(LANGUAGE_SERVER_PROTO_FILE_PATH)
17-
const GetCompletionsRequest = protos.lookupType("GetCompletionsRequest");
18-
const Metadata = protos.lookupType("Metadata");
19-
const DocumentInfo = protos.lookupType("Document");
20-
const EditorOptions = protos.lookupType("EditorOptions");
21-
const Language = protos.lookupEnum("Language");
22-
const GetCompletionsResponse = protos.lookupType("GetCompletionsResponse");
16+
const protos = protobuf.Root.fromJSON(languageServerProto as protobuf.INamespace);
17+
const GetCompletionsRequest = protos.lookupType("exa.language_server_pb.GetCompletionsRequest");
18+
const Metadata = protos.lookupType("exa.codeium_common_pb.Metadata");
19+
const DocumentInfo = protos.lookupType("exa.language_server_pb.Document");
20+
const EditorOptions = protos.lookupType("exa.codeium_common_pb.EditorOptions");
21+
const Language = protos.lookupEnum("exa.codeium_common_pb.Language");
22+
const GetCompletionsResponse = protos.lookupType("exa.language_server_pb.GetCompletionsResponse");
2323

2424
const sessionId = `react-editor-${crypto.randomUUID()}`;
25-
const apiKey = apiKey ?? EDITOR_API_KEY;
25+
const apiKey = optionalApiKey ?? EDITOR_API_KEY;
2626

2727
const payload = {
2828
otherDocuments: [],
@@ -74,5 +74,5 @@ export async function runCodiumAiAutocomplete(
7474
// console.log(item.completion.text);
7575
// }
7676

77-
return responseBody;
77+
return responseBody.toJSON();
7878
}

0 commit comments

Comments
 (0)