Skip to content

Commit 0c81f57

Browse files
authoredAug 27, 2024
Merge pull request #3 from copilot-extensions/sdk
refactor: use `@copilot-extensions/preview-sdk`
2 parents ff1aeda + aff2804 commit 0c81f57

10 files changed

+553
-570
lines changed
 

‎package-lock.json

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

‎package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
{
22
"name": "gh-models",
33
"version": "1.0.0",
4-
"main": "index.js",
4+
"type": "module",
55
"scripts": {
66
"start": "node dist/index.js",
77
"build": "tsc",
8-
"dev": "nodemon src/index.ts"
8+
"dev": "tsx --watch src/index.ts"
99
},
1010
"keywords": [],
1111
"author": "",
1212
"license": "ISC",
1313
"description": "",
1414
"dependencies": {
15+
"@copilot-extensions/preview-sdk": "^1.0.0",
1516
"express": "^4.19.2",
1617
"openai": "^4.55.0"
1718
},
1819
"devDependencies": {
1920
"@types/express": "^4.17.21",
2021
"@types/node": "^22.1.0",
21-
"nodemon": "^3.1.4",
22-
"ts-node": "^10.9.2",
22+
"tsx": "^4.18.0",
2323
"typescript": "^5.5.4"
2424
}
25-
}
25+
}

‎src/functions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import OpenAI from "openai";
2-
import { ModelsAPI } from "./models-api";
2+
import { ModelsAPI } from "./models-api.js";
33

44
// defaultModel is the model used for internal calls - for tool calling,
55
// or just for chat completions.

‎src/functions/describe-model.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import OpenAI from "openai";
2-
import { RunnerResponse, defaultModel, Tool } from "../functions";
2+
import { RunnerResponse, defaultModel, Tool } from "../functions.js";
33

44
export class describeModel extends Tool {
55
static definition = {

‎src/functions/execute-model.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import OpenAI from "openai";
2-
import { RunnerResponse, Tool } from "../functions";
2+
import { RunnerResponse, Tool } from "../functions.js";
33

44
type MessageWithReferences = OpenAI.ChatCompletionMessageParam & {
55
copilot_references: Reference[];

‎src/functions/list-models.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import OpenAI from "openai";
2-
import { RunnerResponse, defaultModel, Tool } from "../functions";
2+
import { RunnerResponse, defaultModel, Tool } from "../functions.js";
33

44
export class listModels extends Tool {
55
static definition = {

‎src/functions/recommend-model.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import OpenAI from "openai";
2-
import { RunnerResponse, defaultModel, Tool } from "../functions";
2+
import { RunnerResponse, defaultModel, Tool } from "../functions.js";
33

44
export class recommendModel extends Tool {
55
static definition = {

‎src/index.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import express from "express";
22
import OpenAI from "openai";
3-
import { verifySignatureMiddleware } from "./validate-signature";
4-
import { describeModel } from "./functions/describe-model";
5-
import { executeModel } from "./functions/execute-model";
6-
import { listModels } from "./functions/list-models";
7-
import { RunnerResponse } from "./functions";
8-
import { recommendModel } from "./functions/recommend-model";
9-
import { ModelsAPI } from "./models-api";
3+
import { verifySignatureMiddleware } from "./validate-signature.js";
4+
import { describeModel } from "./functions/describe-model.js";
5+
import { executeModel } from "./functions/execute-model.js";
6+
import { listModels } from "./functions/list-models.js";
7+
import { RunnerResponse } from "./functions.js";
8+
import { recommendModel } from "./functions/recommend-model.js";
9+
import { ModelsAPI } from "./models-api.js";
1010
const app = express();
1111

1212
app.post("/", verifySignatureMiddleware, express.json(), async (req, res) => {

‎src/validate-signature.ts

+10-45
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
11
import express, { type Request, Response, NextFunction } from "express";
2-
import crypto from "crypto";
3-
4-
const GITHUB_KEYS_URI = "https://api.github.com/meta/public_keys/copilot_api";
5-
6-
interface GitHubKeysPayload {
7-
public_keys: Array<{
8-
key: string;
9-
key_identifier: string;
10-
is_current: boolean;
11-
}>;
12-
}
2+
import { verify } from "@copilot-extensions/preview-sdk";
133

144
export async function verifySignatureMiddleware(
155
req: Request,
@@ -21,7 +11,15 @@ export async function verifySignatureMiddleware(
2111
const signature = req.get("GitHub-Public-Key-Signature") as string;
2212
const keyID = req.get("GitHub-Public-Key-Identifier") as string;
2313
const tokenForUser = req.get("X-GitHub-Token") as string;
24-
await verifySignature(req.body, signature, keyID, tokenForUser);
14+
const verified = await verify(req.body, signature, keyID, {
15+
token: tokenForUser,
16+
});
17+
if (!verified) {
18+
console.log("Signature verification failed");
19+
return res.status(401).send("Unauthorized");
20+
}
21+
22+
console.log("Signature verified");
2523

2624
req.body = JSON.parse(req.body.toString("utf-8"));
2725
next();
@@ -31,36 +29,3 @@ export async function verifySignatureMiddleware(
3129
}
3230
});
3331
}
34-
35-
async function verifySignature(
36-
payload: string,
37-
signature: string,
38-
keyID: string,
39-
tokenForUser: string | null
40-
): Promise<void> {
41-
if (typeof payload !== "string" || payload.length === 0) {
42-
throw new Error("Invalid payload");
43-
}
44-
if (typeof signature !== "string" || signature.length === 0) {
45-
throw new Error("Invalid signature");
46-
}
47-
if (typeof keyID !== "string" || keyID.length === 0) {
48-
throw new Error("Invalid keyID");
49-
}
50-
51-
const keys = (await fetch(GITHUB_KEYS_URI, {
52-
method: "GET",
53-
headers: {
54-
Authorization: `Bearer ${tokenForUser}`,
55-
},
56-
}).then((res) => res.json())) as GitHubKeysPayload;
57-
const publicKey = keys.public_keys.find((k) => k.key_identifier === keyID);
58-
if (!publicKey) {
59-
throw new Error("No public key found matching key identifier");
60-
}
61-
62-
const verify = crypto.createVerify("SHA256").update(payload);
63-
if (!verify.verify(publicKey.key, signature, "base64")) {
64-
throw new Error("Signature does not match payload");
65-
}
66-
}

‎tsconfig.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"compilerOptions": {
3-
"target": "es2016",
4-
"module": "commonjs",
3+
"target": "ES2020",
4+
"module": "NodeNext",
5+
"moduleResolution": "NodeNext",
56
"rootDir": "./src",
67
"outDir": "./dist",
78
"esModuleInterop": true,
8-
"forceConsistentCasingInFileNames": true,
9+
"forceConsistentCasingInFileNames": true,
910
"strict": true,
1011
"skipLibCheck": true
1112
}
12-
}
13+
}

0 commit comments

Comments
 (0)
Failed to load comments.