Skip to content

Commit

Permalink
Merge pull request #3 from copilot-extensions/sdk
Browse files Browse the repository at this point in the history
refactor: use `@copilot-extensions/preview-sdk`
  • Loading branch information
JasonEtco authored Aug 27, 2024
2 parents ff1aeda + aff2804 commit 0c81f57
Show file tree
Hide file tree
Showing 10 changed files with 553 additions and 570 deletions.
1,025 changes: 521 additions & 504 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
{
"name": "gh-models",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node dist/index.js",
"build": "tsc",
"dev": "nodemon src/index.ts"
"dev": "tsx --watch src/index.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@copilot-extensions/preview-sdk": "^1.0.0",
"express": "^4.19.2",
"openai": "^4.55.0"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^22.1.0",
"nodemon": "^3.1.4",
"ts-node": "^10.9.2",
"tsx": "^4.18.0",
"typescript": "^5.5.4"
}
}
}
2 changes: 1 addition & 1 deletion src/functions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import OpenAI from "openai";
import { ModelsAPI } from "./models-api";
import { ModelsAPI } from "./models-api.js";

// defaultModel is the model used for internal calls - for tool calling,
// or just for chat completions.
Expand Down
2 changes: 1 addition & 1 deletion src/functions/describe-model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import OpenAI from "openai";
import { RunnerResponse, defaultModel, Tool } from "../functions";
import { RunnerResponse, defaultModel, Tool } from "../functions.js";

export class describeModel extends Tool {
static definition = {
Expand Down
2 changes: 1 addition & 1 deletion src/functions/execute-model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import OpenAI from "openai";
import { RunnerResponse, Tool } from "../functions";
import { RunnerResponse, Tool } from "../functions.js";

type MessageWithReferences = OpenAI.ChatCompletionMessageParam & {
copilot_references: Reference[];
Expand Down
2 changes: 1 addition & 1 deletion src/functions/list-models.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import OpenAI from "openai";
import { RunnerResponse, defaultModel, Tool } from "../functions";
import { RunnerResponse, defaultModel, Tool } from "../functions.js";

export class listModels extends Tool {
static definition = {
Expand Down
2 changes: 1 addition & 1 deletion src/functions/recommend-model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import OpenAI from "openai";
import { RunnerResponse, defaultModel, Tool } from "../functions";
import { RunnerResponse, defaultModel, Tool } from "../functions.js";

export class recommendModel extends Tool {
static definition = {
Expand Down
14 changes: 7 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import express from "express";
import OpenAI from "openai";
import { verifySignatureMiddleware } from "./validate-signature";
import { describeModel } from "./functions/describe-model";
import { executeModel } from "./functions/execute-model";
import { listModels } from "./functions/list-models";
import { RunnerResponse } from "./functions";
import { recommendModel } from "./functions/recommend-model";
import { ModelsAPI } from "./models-api";
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) => {
Expand Down
55 changes: 10 additions & 45 deletions src/validate-signature.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
import express, { type Request, Response, NextFunction } from "express";
import crypto from "crypto";

const GITHUB_KEYS_URI = "https://api.github.com/meta/public_keys/copilot_api";

interface GitHubKeysPayload {
public_keys: Array<{
key: string;
key_identifier: string;
is_current: boolean;
}>;
}
import { verify } from "@copilot-extensions/preview-sdk";

export async function verifySignatureMiddleware(
req: Request,
Expand All @@ -21,7 +11,15 @@ export async function verifySignatureMiddleware(
const signature = req.get("GitHub-Public-Key-Signature") as string;
const keyID = req.get("GitHub-Public-Key-Identifier") as string;
const tokenForUser = req.get("X-GitHub-Token") as string;
await verifySignature(req.body, signature, keyID, tokenForUser);
const verified = await verify(req.body, signature, keyID, {
token: tokenForUser,
});
if (!verified) {
console.log("Signature verification failed");
return res.status(401).send("Unauthorized");
}

console.log("Signature verified");

req.body = JSON.parse(req.body.toString("utf-8"));
next();
Expand All @@ -31,36 +29,3 @@ export async function verifySignatureMiddleware(
}
});
}

async function verifySignature(
payload: string,
signature: string,
keyID: string,
tokenForUser: string | null
): Promise<void> {
if (typeof payload !== "string" || payload.length === 0) {
throw new Error("Invalid payload");
}
if (typeof signature !== "string" || signature.length === 0) {
throw new Error("Invalid signature");
}
if (typeof keyID !== "string" || keyID.length === 0) {
throw new Error("Invalid keyID");
}

const keys = (await fetch(GITHUB_KEYS_URI, {
method: "GET",
headers: {
Authorization: `Bearer ${tokenForUser}`,
},
}).then((res) => res.json())) as GitHubKeysPayload;
const publicKey = keys.public_keys.find((k) => k.key_identifier === keyID);
if (!publicKey) {
throw new Error("No public key found matching key identifier");
}

const verify = crypto.createVerify("SHA256").update(payload);
if (!verify.verify(publicKey.key, signature, "base64")) {
throw new Error("Signature does not match payload");
}
}
9 changes: 5 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "./src",
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
}

0 comments on commit 0c81f57

Please sign in to comment.