-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs(examples): hello world, prompt #84
Changes from 27 commits
fc01ac5
01315e3
97db5cc
54c7182
b3cec6a
6b0300c
0d5663a
fbb3721
514fa22
5d36cb4
76493da
82fef70
e5f95f3
a91d03b
67160bc
7799456
a86354c
373f42a
7e058b9
01f1a0e
037f7ab
a577333
6bc910d
0fcccbf
d10e4ed
45ead22
7057fd2
cc0ad34
55a290b
7aba451
f46d975
1db7290
4f59a32
dd6093a
5c4aadf
6a0551d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
node_modules | ||
coverage | ||
examples/**/package-lock.json | ||
node_modules |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { createServer } from "node:http"; | ||
|
||
import { | ||
createTextEvent, | ||
createDoneEvent, | ||
} from "@copilot-extensions/preview-sdk"; | ||
|
||
const server = createServer((request, ressponse) => { | ||
console.log(`Received [${request.method}] to [${request.url}]`); | ||
if (request.method === "GET") { | ||
return ressponse.end("ok"); | ||
} | ||
|
||
ressponse.write(createTextEvent("Hello, world!")); | ||
ressponse.end(createDoneEvent()); | ||
}); | ||
|
||
const PORT = process.env.PORT || 3000; | ||
server.listen(PORT, () => { | ||
console.log(`Server is running on port ${PORT}`); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"private": true, | ||
"type": "module", | ||
"scripts": { | ||
"start": "node index.js", | ||
"watch": "node --watch index.js" | ||
}, | ||
"dependencies": { | ||
"@copilot-extensions/preview-sdk": "latest" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,111 @@ | ||||||
import { createServer } from 'node:http'; | ||||||
import { Octokit } from "@octokit"; | ||||||
gr2m marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
import { | ||||||
createAckEvent, | ||||||
createDoneEvent, | ||||||
createTextEvent, | ||||||
parseRequestBody, | ||||||
prompt, | ||||||
verifyRequestByKeyId | ||||||
} from "@copilot-extensions/preview-sdk"; | ||||||
|
||||||
|
||||||
// Define the handler function | ||||||
const handler = async (request, response) => { | ||||||
|
||||||
if (request.method !== 'POST') { | ||||||
// Handle other request methods if necessary | ||||||
response.writeHead(405, { 'Content-Type': 'text/plain' }); | ||||||
console.log(`Method ${request.method} not allowed`); | ||||||
|
||||||
response.end('Method Not Allowed'); | ||||||
} | ||||||
gr2m marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
console.log('Received POST request'); | ||||||
|
||||||
// get a token to use | ||||||
const tokenForUser = request.headers['x-github-token']; | ||||||
|
||||||
// get the user information with the token | ||||||
const octokit = new Octokit({ auth: tokenForUser }); | ||||||
const user = await octokit.request("GET /user"); | ||||||
const userHandle = user.data.login | ||||||
|
||||||
// Collect incoming data chunks to use in the `on("end")` event | ||||||
let body = ''; | ||||||
request.on('data', chunk => { | ||||||
body += chunk.toString(); | ||||||
}); | ||||||
|
||||||
// Parse the collected data once the request ends | ||||||
request.on('end', async () => { | ||||||
try { | ||||||
const payloadIsVerified = await verifyRequestByKeyId( | ||||||
request.body, | ||||||
gr2m marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
signature, | ||||||
keyId, | ||||||
{ | ||||||
token: process.env.GITHUB_TOKEN, | ||||||
}, | ||||||
); | ||||||
|
||||||
if (!payloadIsVerified) { | ||||||
console.error('Request verification failed'); | ||||||
response.writeHead(401, { 'Content-Type': 'text/plain' }); | ||||||
response.end('Request could not be verified'); | ||||||
return; | ||||||
} | ||||||
|
||||||
// start sending the response back to Copilot | ||||||
console.log('Handling response'); | ||||||
// write the acknowledge event to let Copilot know we are handling the request | ||||||
// this will also show the message "Copilot is responding" in the chat | ||||||
response.write(createAckEvent()); | ||||||
|
||||||
// parse the incoming body as that has the information we need to handle the request / user prompt | ||||||
const payload = parseRequestBody(body); | ||||||
|
||||||
// start writing text in the response | ||||||
const textEvent = createTextEvent(`Hello ${userHandle}, \n\n`); | ||||||
response.write(textEvent); | ||||||
// add new lines to mark the difference between the fixed text and the dynamic text | ||||||
response.write("\n\n"); | ||||||
gr2m marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
// get an authentication token to use | ||||||
const tokenForUser = request.headers['x-github-token']; | ||||||
|
||||||
console.log('Calling the GitHub Copilot API with the user prompt'); | ||||||
// the prompt to forward to the Copilot API is the last message in the payload | ||||||
const payload_message = payload.messages[payload.messages.length - 1]; | ||||||
const result = await prompt(payload_message.content, { | ||||||
system: "you talk like a pirate", // extra instructions for the prompt, the "you are a helpful assistant" is already set in the SDK | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "you are a helpful assistant" is just the default. If you want it to be part of your system prompt then you have to include it in your custom onew
Suggested change
|
||||||
messages: payload.messages, // we are giving the prompt the existing messages in this chat conversation | ||||||
token: tokenForUser | ||||||
}); | ||||||
|
||||||
// write the prompt response back to Copilot | ||||||
// note that this is only send when the entire response from the Copilot API is ready | ||||||
response.write(createTextEvent(result.message.content)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is a |
||||||
|
||||||
// write the done event to let Copilot know we are done handling the request | ||||||
response.end(createDoneEvent()); | ||||||
console.log('Response sent'); | ||||||
} | ||||||
catch (error) { | ||||||
console.error('Error:', error); | ||||||
response.writeHead(500, { 'Content-Type': 'text/plain' }); | ||||||
response.end('Internal Server Error'); | ||||||
} | ||||||
}); | ||||||
}; | ||||||
|
||||||
// Create an HTTP server | ||||||
const server = http.createServer(handler); | ||||||
|
||||||
// Define the port to listen on | ||||||
const PORT = 3000; | ||||||
|
||||||
// Start the server | ||||||
server.listen(PORT, () => { | ||||||
console.log(`Server is listening on port ${PORT}`); | ||||||
}); |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,12 @@ | ||||||
{ | ||||||
"private": true, | ||||||
"type": "module", | ||||||
"scripts": { | ||||||
"start": "node index.js", | ||||||
"watch": "node --watch index.js" | ||||||
}, | ||||||
"dependencies": { | ||||||
"@copilot-extensions/preview-sdk": "latest", | ||||||
"@octokit": "latest" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't use
Suggested change
|
||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
This folder contains examples to show how you can use the Copilot Agent SDK in your own projects. | ||
Keep in mind that the SDK is in preview, so things might be changed already! | ||
|
||
If you find any issues or have any questions, please let us know by opening an issue, pull requests welcome (please read the (contribution guidelines)[../CONTRIBUTING.md] first). | ||
|
||
# Examples | ||
Here's an overview of the examples in this folder: | ||
- 1-hello-world: A simple example that responds to all prompts with a message: "Hello, world!" | ||
- 2-handle-prompt: An example that responds to prompts with a message: "Hello, world!" and then forwards the prompt to the Copilot API. The response from the Copilot API is then sent back to the user. | ||
|
||
## Running the examples | ||
These examples are setup so that you can run them inside a GitHub Codespace. To do so, follow these steps: | ||
1. Open the GitHub Codespace by clicking the "Code" button in the top right of the repository and selecting "Open with Codespaces". | ||
2. Once the Codespace is open, you can run the examples by running the following command in the terminal: | ||
```sh | ||
# go to the correct folder | ||
cd examples/<example-name> | ||
# install dependencies | ||
npm install | ||
# run the example | ||
npm run start | ||
``` | ||
|
||
> [!IMPORTANT] | ||
> By default, the examples will run on port 3000 and ports in Codespaces are private by default. If you want to access the examples from your browser, you'll need to make the port public. To do so, click on the "Ports" tab in the Codespace and right click, Go to "Port Visibility" next to port 3000 and set it to `public`. Do be aware that this will make the port accessible to anyone with the link to your Codespace. The port visibility setting is not saved when the Codespace is stopped, so you'll need to set it again if you restart the Codespace or node. The url does stay the same as long as the Codespace is not deleted. | ||
|
||
> [!TIP] | ||
> Don't forget to set the Codespace url (with the port) in your GitHub App that you are using. The Copilot backend needs to be able to reach your Codespace to send messages to your extension. If your app is not running, the port is not public, or the codespace is stopped, the extension will not work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does node support a
--watch
flag now?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
woah today I learned, thanks!
https://nodejs.org/api/cli.html#--watch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot told me it was available!