From 1d327acacae94088e565f8e256235694688167b0 Mon Sep 17 00:00:00 2001 From: thorwebdev Date: Mon, 27 Mar 2023 18:32:51 +0800 Subject: [PATCH] feat: Add ChatGPT Plugin template. --- supabase/functions/chatgpt-plugin/README.md | 13 ++++ .../chatgpt-plugin/generate_openapi_spec.ts | 20 ++++++ supabase/functions/chatgpt-plugin/index.ts | 69 +++++++++++++++++++ .../functions/chatgpt-plugin/manifest.json | 18 +++++ .../functions/chatgpt-plugin/openapi.json | 56 +++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 supabase/functions/chatgpt-plugin/README.md create mode 100644 supabase/functions/chatgpt-plugin/generate_openapi_spec.ts create mode 100644 supabase/functions/chatgpt-plugin/index.ts create mode 100644 supabase/functions/chatgpt-plugin/manifest.json create mode 100644 supabase/functions/chatgpt-plugin/openapi.json diff --git a/supabase/functions/chatgpt-plugin/README.md b/supabase/functions/chatgpt-plugin/README.md new file mode 100644 index 0000000..ef5200f --- /dev/null +++ b/supabase/functions/chatgpt-plugin/README.md @@ -0,0 +1,13 @@ +# Build a ChatGPT Plugin + +## Generate openapi spec + +```bash +deno run -A supabase/functions/chatgpt-plugin/generate_openapi_spec.ts +``` + +## Deploy function + +```bash +supabase functions deploy chatgpt-plugin --no-verify-jwt +``` diff --git a/supabase/functions/chatgpt-plugin/generate_openapi_spec.ts b/supabase/functions/chatgpt-plugin/generate_openapi_spec.ts new file mode 100644 index 0000000..bb7fc99 --- /dev/null +++ b/supabase/functions/chatgpt-plugin/generate_openapi_spec.ts @@ -0,0 +1,20 @@ +import swaggerJsdoc from "npm:swagger-jsdoc@6.2.8"; + +const options = { + definition: { + openapi: "3.0.1", + info: { + title: "TODO Plugin", + description: `A plugin that allows the user to create and manage a TODO list using ChatGPT. If you do not know the user's username, ask them first before making queries to the plugin. Otherwise, use the username "global".`, + version: "1.0.0", + }, + }, + apis: ["./supabase/functions/chatgpt-plugin/index.ts"], // files containing annotations as above +}; + +const openapiSpecification = swaggerJsdoc(options); +const openapiString = JSON.stringify(openapiSpecification, null, 2); +const encoder = new TextEncoder(); +const data = encoder.encode(openapiString); +await Deno.writeFile("./supabase/functions/chatgpt-plugin/openapi.json", data); +console.log(openapiString); diff --git a/supabase/functions/chatgpt-plugin/index.ts b/supabase/functions/chatgpt-plugin/index.ts new file mode 100644 index 0000000..635a247 --- /dev/null +++ b/supabase/functions/chatgpt-plugin/index.ts @@ -0,0 +1,69 @@ +import { Application, Router } from "oak"; +import manifest from "./manifest.json" assert { type: "json" }; +import openapi from "./openapi.json" assert { type: "json" }; + +console.log("Hello from `chatgpt-plugin` Function!"); + +const _TODOS: { [key: string]: Array } = { + global: ["test this plugin template"], +}; + +/** + * @openapi + * components: + * schemas: + * getTodosResponse: + * type: object + * properties: + * todos: + * type: array + * items: + * type: string + * description: The list of todos. + */ + +const router = new Router(); +router + .get("/chatgpt-plugin", (ctx) => { + ctx.response.body = + "Building ChatGPT plugins with Supabase Edge Functions!"; + }) + /** + * @openapi + * /todos/{username}: + * get: + * operationId: getTodos + * summary: Get the list of todos + * parameters: + * - in: path + * name: username + * schema: + * type: string + * required: true + * description: The name of the user. + * responses: + * 200: + * description: OK + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/getTodosResponse' + */ + .get("/chatgpt-plugin/todos/:username", (ctx) => { + const username = ctx.params.username; + ctx.response.body = _TODOS[username] ?? []; + }) + .get("/chatgpt-plugin/.well-known/ai-plugin.json", (ctx) => { + ctx.response.type = "text/json"; + ctx.response.body = JSON.stringify(manifest); + }) + .get("/chatgpt-plugin/openapi.json", (ctx) => { + ctx.response.type = "text/json"; + ctx.response.body = JSON.stringify(openapi); + }); + +const app = new Application(); +app.use(router.routes()); +app.use(router.allowedMethods()); + +await app.listen({ port: 8000 }); diff --git a/supabase/functions/chatgpt-plugin/manifest.json b/supabase/functions/chatgpt-plugin/manifest.json new file mode 100644 index 0000000..4d6c803 --- /dev/null +++ b/supabase/functions/chatgpt-plugin/manifest.json @@ -0,0 +1,18 @@ +{ + "schema_version": "v1", + "name_for_human": "TODO Plugin (no auth)", + "name_for_model": "todo", + "description_for_human": "Plugin for managing a TODO list, you can add, remove and view your TODOs.", + "description_for_model": "Plugin for managing a TODO list, you can add, remove and view your TODOs.", + "auth": { + "type": "none" + }, + "api": { + "type": "openapi", + "url": "PLUGIN_HOSTNAME/openapi.json", + "is_user_authenticated": false + }, + "logo_url": "PLUGIN_HOSTNAME/logo.png", + "contact_email": "dummy@email.com", + "legal_info_url": "http://www.example.com/legal" +} diff --git a/supabase/functions/chatgpt-plugin/openapi.json b/supabase/functions/chatgpt-plugin/openapi.json new file mode 100644 index 0000000..332c773 --- /dev/null +++ b/supabase/functions/chatgpt-plugin/openapi.json @@ -0,0 +1,56 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "TODO Plugin", + "description": "A plugin that allows the user to create and manage a TODO list using ChatGPT. If you do not know the user's username, ask them first before making queries to the plugin. Otherwise, use the username \"global\".", + "version": "1.0.0" + }, + "paths": { + "/todos/{username}": { + "get": { + "operationId": "getTodos", + "summary": "Get the list of todos", + "parameters": [ + { + "in": "path", + "name": "username", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the user." + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/getTodosResponse" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "getTodosResponse": { + "type": "object", + "properties": { + "todos": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The list of todos." + } + } + } + } + }, + "tags": [] +} \ No newline at end of file