|
| 1 | +# Copilot Extension Dreamcode |
| 2 | + |
| 3 | +Dream code is code that is not real. Its purpose is to create the most user-friendly SDK APIs from the perspectives of developers who want to build GitHub Extensions using JavaScript/Typescript. |
| 4 | + |
| 5 | +Please, any questions/feedback/feelings are welcome. This is a safe space. Please file issues or jump right in and start pull requests. |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- Event-based API for receiving and responding to messages |
| 10 | +- Automated Payload verification |
| 11 | +- High-level APIs for different types of responses (text, confirmation, references, etc.) |
| 12 | +- High-level API for interacting with models |
| 13 | + |
| 14 | +## API |
| 15 | + |
| 16 | +```js |
| 17 | +import { createServer } from "http"; |
| 18 | + |
| 19 | +import { |
| 20 | + CopilotExtension, |
| 21 | + createNodeMiddleware, |
| 22 | +} from "@octokit/copilot-extension"; |
| 23 | + |
| 24 | +const copilotExtension = new CopilotExtension({ |
| 25 | + agent: "my-app-name", |
| 26 | + prompt: { |
| 27 | + defaultModel: "gpt-4o", |
| 28 | + }, |
| 29 | +}); |
| 30 | + |
| 31 | +copilotExtension.on( |
| 32 | + "message", |
| 33 | + async ({ message, octokit, prompt, respond, log }) => { |
| 34 | + log.info("Received a message:", message.content); |
| 35 | + |
| 36 | + const { data: user } = await octokit.request("GET /user"); |
| 37 | + await respond.text(`Hello, ${user.login}!`); |
| 38 | + |
| 39 | + await respond.confirmation({ |
| 40 | + title: "Would you like to hear a joke?", |
| 41 | + message: "I have a joke about construction, but I'm still working on it.", |
| 42 | + id: "joke", |
| 43 | + // optional |
| 44 | + meta: { |
| 45 | + other: "data", |
| 46 | + }, |
| 47 | + }); |
| 48 | + } |
| 49 | +); |
| 50 | + |
| 51 | +// https://github.com/github/copilot-partners/blob/6d1cde3a1abb147da53f1a39864661dc824d40b5/docs/confirmations.md |
| 52 | +copilotExtension.on( |
| 53 | + "confirmation", |
| 54 | + async ({ confirmation, octokit, prompt, respond, log }) => { |
| 55 | + if (confirmation.id === "joke") { |
| 56 | + if (confirmation.state === "dismissed") { |
| 57 | + await respond.text("Okay, maybe next time!"); |
| 58 | + return; |
| 59 | + } |
| 60 | + |
| 61 | + await respond.text( |
| 62 | + prompt.stream("Please tell me a joke about Mona Lisa, Github's mascot.") |
| 63 | + ); |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + log.warn("Received an unknown confirmation:", confirmation.id); |
| 68 | + await respond.text("Hmm, something went wrong. Please try again later."); |
| 69 | + } |
| 70 | +); |
| 71 | + |
| 72 | +createServer(createNodeMiddleware(copilotExtension)).listen(3000); |
| 73 | +copilotExtension.log.info("Listening on http://localhost:3000"); |
| 74 | +``` |
| 75 | + |
| 76 | +## Notes |
| 77 | + |
| 78 | +Regarding the context passed to event handlers |
| 79 | + |
| 80 | +- `message` / `confirmation` / etc are objects as received by the user |
| 81 | +- `octokit` is a pre-authenticated octokit instance |
| 82 | +- `prompt` is based on my work at https://github.com/github/gr2m-projects/blob/167/github-models/167-github-models/README.md. A simple API to interact with GitHub models. |
| 83 | +- `respond` is an API to send different types of responses to the user |
| 84 | +- `log` is the logger as we use it in Octokit. See https://github.com/octokit/core.js?tab=readme-ov-file#logging |
| 85 | + |
| 86 | +On how to receive the events (transport layer) |
| 87 | + |
| 88 | +- `createNodeMiddleware` is something we have currently built into some of the Octokit SDKs, e.g. https://github.com/octokit/app.js?tab=readme-ov-file#createnodemiddlewareapp-options. However, I think we will move these out into separate packages, such as `@octokit/webhooks-middleware-node`, etc. But for now, we can just assume that we ship with it by default. We can also add other middlewares for Netlify/Vercel edge functions, lambda, etc. |
0 commit comments