Skip to content

Commit b9f4741

Browse files
authoredSep 6, 2024
Merge pull request #5 from copilot-extensions/upgrade-copilot-extension-sdk
fix: upgrade `@copilot-extensions/preview-sdk` to v2
2 parents 5f10049 + 7d5dd21 commit b9f4741

File tree

4 files changed

+79
-63
lines changed

4 files changed

+79
-63
lines changed
 

‎package-lock.json

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"license": "ISC",
1313
"description": "",
1414
"dependencies": {
15-
"@copilot-extensions/preview-sdk": "^1.0.0",
15+
"@copilot-extensions/preview-sdk": "^2.6.1",
1616
"express": "^4.19.2",
1717
"openai": "^4.55.0"
1818
},
@@ -22,4 +22,4 @@
2222
"tsx": "^4.18.0",
2323
"typescript": "^5.5.4"
2424
}
25-
}
25+
}

‎src/index.ts

+73-26
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,53 @@
1-
import express from "express";
1+
import { createServer, IncomingMessage } from "node:http";
2+
3+
import { verifyAndParseRequest } from "@copilot-extensions/preview-sdk";
24
import OpenAI from "openai";
3-
import { verifySignatureMiddleware } from "./validate-signature.js";
5+
46
import { describeModel } from "./functions/describe-model.js";
57
import { executeModel } from "./functions/execute-model.js";
68
import { listModels } from "./functions/list-models.js";
79
import { RunnerResponse } from "./functions.js";
810
import { recommendModel } from "./functions/recommend-model.js";
911
import { ModelsAPI } from "./models-api.js";
10-
const app = express();
1112

12-
app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
13+
const server = createServer(async (request, response) => {
14+
if (request.method === "GET") {
15+
response.statusCode = 200;
16+
response.end(`OK`);
17+
return;
18+
}
19+
20+
const body = await getBody(request);
21+
22+
let verifyAndParseRequestResult: Awaited<ReturnType<typeof verifyAndParseRequest>>;
23+
const apiKey = request.headers["x-github-token"] as string;
24+
try {
25+
const signature = request.headers["github-public-key-signature"] as string;
26+
const keyID = request.headers["github-public-key-identifier"] as string;
27+
verifyAndParseRequestResult = await verifyAndParseRequest(body, signature, keyID, {
28+
token: apiKey,
29+
});
30+
} catch (err) {
31+
console.error(err);
32+
response.statusCode = 401
33+
response.end("Unauthorized");
34+
return
35+
}
36+
37+
const { isValidRequest, payload } = verifyAndParseRequestResult
38+
39+
if (!isValidRequest) {
40+
console.log("Signature verification failed");
41+
response.statusCode = 401
42+
response.end("Unauthorized");
43+
}
44+
45+
console.log("Signature verified");
46+
1347
// Use the GitHub API token sent in the request
14-
const apiKey = req.get("X-GitHub-Token");
1548
if (!apiKey) {
16-
res.status(400).end();
49+
response.statusCode = 400
50+
response.end()
1751
return;
1852
}
1953

@@ -50,8 +84,8 @@ app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
5084
"<-- END OF LIST OF MODELS -->",
5185
].join("\n"),
5286
},
53-
...req.body.messages,
54-
].concat(req.body.messages);
87+
...payload.messages,
88+
].concat(payload.messages);
5589

5690
console.time("tool-call");
5791
const toolCaller = await capiClient.chat.completions.create({
@@ -74,15 +108,16 @@ app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
74108
const stream = await capiClient.chat.completions.create({
75109
stream: true,
76110
model: "gpt-4",
77-
messages: req.body.messages,
111+
// @ts-expect-error - TODO @gr2m - type incompatibility between @openai/api and @copilot-extensions/preview-sdk
112+
messages: payload.messages,
78113
});
79114

80115
for await (const chunk of stream) {
81116
const chunkStr = "data: " + JSON.stringify(chunk) + "\n\n";
82-
res.write(chunkStr);
117+
response.write(chunkStr);
83118
}
84-
res.write("data: [DONE]\n\n");
85-
res.end();
119+
response.write("data: [DONE]\n\n");
120+
response.end();
86121
return;
87122
}
88123

@@ -102,10 +137,12 @@ app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
102137

103138
console.log("\t with args", args);
104139
const func = new funcClass(modelsAPI);
105-
functionCallRes = await func.execute(req.body.messages, args);
140+
// @ts-expect-error - TODO @gr2m - type incompatibility between @openai/api and @copilot-extensions/preview-sdk
141+
functionCallRes = await func.execute(payload.messages, args);
106142
} catch (err) {
107143
console.error(err);
108-
res.status(500).end();
144+
response.statusCode = 500
145+
response.end();
109146
return;
110147
}
111148
console.timeEnd("function-exec");
@@ -123,23 +160,33 @@ app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
123160
console.time("streaming");
124161
for await (const chunk of stream) {
125162
const chunkStr = "data: " + JSON.stringify(chunk) + "\n\n";
126-
res.write(chunkStr);
163+
response.write(chunkStr);
127164
}
128-
res.write("data: [DONE]\n\n");
165+
response.write("data: [DONE]\n\n");
129166
console.timeEnd("streaming");
130-
res.end();
167+
response.end();
131168
} catch (err) {
132169
console.error(err);
133-
res.status(500).end();
170+
response.statusCode = 500
171+
response.end()
134172
}
135173
});
136174

137-
// Health check
138-
app.get("/", (req, res) => {
139-
res.send("OK");
140-
});
175+
const port = process.env.PORT || "3000"
176+
server.listen(port);
177+
console.log(`Server running at http://localhost:${port}`);
141178

142-
const port = Number(process.env.PORT || "3000");
143-
app.listen(port, () => {
144-
console.log(`Server is running on http://localhost:${port}`);
145-
});
179+
function getBody(request: IncomingMessage): Promise<string> {
180+
return new Promise((resolve) => {
181+
const bodyParts: any[] = [];
182+
let body;
183+
request
184+
.on("data", (chunk) => {
185+
bodyParts.push(chunk);
186+
})
187+
.on("end", () => {
188+
body = Buffer.concat(bodyParts).toString();
189+
resolve(body);
190+
});
191+
});
192+
}

‎src/validate-signature.ts

-31
This file was deleted.

0 commit comments

Comments
 (0)
Failed to load comments.