Skip to content

Commit

Permalink
Merge pull request #5 from copilot-extensions/upgrade-copilot-extensi…
Browse files Browse the repository at this point in the history
…on-sdk

fix: upgrade `@copilot-extensions/preview-sdk` to v2
  • Loading branch information
gr2m authored Sep 6, 2024
2 parents 5f10049 + 7d5dd21 commit b9f4741
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 63 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"license": "ISC",
"description": "",
"dependencies": {
"@copilot-extensions/preview-sdk": "^1.0.0",
"@copilot-extensions/preview-sdk": "^2.6.1",
"express": "^4.19.2",
"openai": "^4.55.0"
},
Expand All @@ -22,4 +22,4 @@
"tsx": "^4.18.0",
"typescript": "^5.5.4"
}
}
}
99 changes: 73 additions & 26 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,53 @@
import express from "express";
import { createServer, IncomingMessage } from "node:http";

import { verifyAndParseRequest } from "@copilot-extensions/preview-sdk";
import OpenAI from "openai";
import { verifySignatureMiddleware } from "./validate-signature.js";

import { describeModel } from "./functions/describe-model.js";
import { executeModel } from "./functions/execute-model.js";
import { listModels } from "./functions/list-models.js";
import { RunnerResponse } from "./functions.js";
import { recommendModel } from "./functions/recommend-model.js";
import { ModelsAPI } from "./models-api.js";
const app = express();

app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
const server = createServer(async (request, response) => {
if (request.method === "GET") {
response.statusCode = 200;
response.end(`OK`);
return;
}

const body = await getBody(request);

let verifyAndParseRequestResult: Awaited<ReturnType<typeof verifyAndParseRequest>>;
const apiKey = request.headers["x-github-token"] as string;
try {
const signature = request.headers["github-public-key-signature"] as string;
const keyID = request.headers["github-public-key-identifier"] as string;
verifyAndParseRequestResult = await verifyAndParseRequest(body, signature, keyID, {
token: apiKey,
});
} catch (err) {
console.error(err);
response.statusCode = 401
response.end("Unauthorized");
return
}

const { isValidRequest, payload } = verifyAndParseRequestResult

if (!isValidRequest) {
console.log("Signature verification failed");
response.statusCode = 401
response.end("Unauthorized");
}

console.log("Signature verified");

// Use the GitHub API token sent in the request
const apiKey = req.get("X-GitHub-Token");
if (!apiKey) {
res.status(400).end();
response.statusCode = 400
response.end()
return;
}

Expand Down Expand Up @@ -50,8 +84,8 @@ app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
"<-- END OF LIST OF MODELS -->",
].join("\n"),
},
...req.body.messages,
].concat(req.body.messages);
...payload.messages,
].concat(payload.messages);

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

for await (const chunk of stream) {
const chunkStr = "data: " + JSON.stringify(chunk) + "\n\n";
res.write(chunkStr);
response.write(chunkStr);
}
res.write("data: [DONE]\n\n");
res.end();
response.write("data: [DONE]\n\n");
response.end();
return;
}

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

console.log("\t with args", args);
const func = new funcClass(modelsAPI);
functionCallRes = await func.execute(req.body.messages, args);
// @ts-expect-error - TODO @gr2m - type incompatibility between @openai/api and @copilot-extensions/preview-sdk
functionCallRes = await func.execute(payload.messages, args);
} catch (err) {
console.error(err);
res.status(500).end();
response.statusCode = 500
response.end();
return;
}
console.timeEnd("function-exec");
Expand All @@ -123,23 +160,33 @@ app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {
console.time("streaming");
for await (const chunk of stream) {
const chunkStr = "data: " + JSON.stringify(chunk) + "\n\n";
res.write(chunkStr);
response.write(chunkStr);
}
res.write("data: [DONE]\n\n");
response.write("data: [DONE]\n\n");
console.timeEnd("streaming");
res.end();
response.end();
} catch (err) {
console.error(err);
res.status(500).end();
response.statusCode = 500
response.end()
}
});

// Health check
app.get("/", (req, res) => {
res.send("OK");
});
const port = process.env.PORT || "3000"
server.listen(port);
console.log(`Server running at http://localhost:${port}`);

const port = Number(process.env.PORT || "3000");
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
function getBody(request: IncomingMessage): Promise<string> {
return new Promise((resolve) => {
const bodyParts: any[] = [];
let body;
request
.on("data", (chunk) => {
bodyParts.push(chunk);
})
.on("end", () => {
body = Buffer.concat(bodyParts).toString();
resolve(body);
});
});
}
31 changes: 0 additions & 31 deletions src/validate-signature.ts

This file was deleted.

0 comments on commit b9f4741

Please sign in to comment.