Skip to content
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

Merged
merged 36 commits into from
Sep 17, 2024
Merged

Conversation

rajbos
Copy link
Contributor

@rajbos rajbos commented Sep 13, 2024

See the conversation in #83

  • Adding examples folder with easy to start projects (see README in that folder)
  • Example 1: hello world
  • Example 2: handle the user prompt by sending it to the Copilot API and returning the result

Copy link
Collaborator

@gr2m gr2m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

early feedback, I haven't looked at the handle prompt example yet.

I would suggest we remove 1- prefixes, the names should stay on their own

},
"scripts": {
"start": "node index.js",
"watch": "node --watch index.js"
Copy link
Collaborator

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

Copy link
Collaborator

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

Copy link
Contributor Author

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!

examples/1-hello-world/package.json Outdated Show resolved Hide resolved
examples/1-hello-world/package.json Outdated Show resolved Hide resolved
examples/1-hello-world/package.json Outdated Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if we should commit lock files for the examples, they might just create a lot of noise

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point, I'll remove them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

examples/1-hello-world/index.js Outdated Show resolved Hide resolved
} from "@copilot-extensions/preview-sdk";

const server = createServer((request, ressponse) => {
console.log(`Received [${request.method}]`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should log out both the method and the URL

Suggested change
console.log(`Received [${request.method}]`);
console.log(`Received ${request.method} ${request.url}`);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you removed the brackets as well. It's a preference of mine to be able to differentiate between fixed text and variable text, and makes it really easy to see when a value is empty.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can leave in the brackets if you prefer. But values cannot be empty in this context

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@rajbos
Copy link
Contributor Author

rajbos commented Sep 13, 2024

early feedback, I haven't looked at the handle prompt example yet.

I would suggest we remove 1- prefixes, the names should stay on their own

I was aiming for having a very logical way of knowing where to start and gradually add more complex examples. Numbering them helps so that you do not need to search in the README.

package.json Outdated
@@ -21,6 +21,7 @@
"license": "MIT",
"description": "JavaScript SDK for Copilot Extensions",
"dependencies": {
"@copilot-extensions/preview-sdk": "^4.0.3",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you add this dependency on itself intentionally? If yes, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, probably ran an npm install command at the wrong folder. Removed it!

Copy link
Contributor Author

@rajbos rajbos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved feedback comments in the code

examples/1-hello-world/index.js Outdated Show resolved Hide resolved
} from "@copilot-extensions/preview-sdk";

const server = createServer((request, ressponse) => {
console.log(`Received [${request.method}]`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

package.json Outdated
@@ -21,6 +21,7 @@
"license": "MIT",
"description": "JavaScript SDK for Copilot Extensions",
"dependencies": {
"@copilot-extensions/preview-sdk": "^4.0.3",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, probably ran an npm install command at the wrong folder. Removed it!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Copy link
Collaborator

@gr2m gr2m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for all the comments. If you prefer, we can merge it as is and do a follow up pull request to discuss further, or leave out the 2nd example folder and do it in a separate pull request

.gitignore Outdated Show resolved Hide resolved
examples/2-handle-prompt/index.js Outdated Show resolved Hide resolved
@@ -0,0 +1,100 @@
import http from 'http';
import { Octokit } from "@octokit/rest";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use @octokit/rest, use octokit instead. I know Copilot likes to recommend @octokit/rest because it's been around longer, but it's a legacy SDK. octokit is the official all-batteries-included SDK for GitHub's API now

examples/2-handle-prompt/index.js Outdated Show resolved Hide resolved

// Define the handler function
const handler = async (request, response) => {
if (request.method === 'POST') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would reverse condition and do an early return to avoid indentation

Suggested change
if (request.method === 'POST') {
if (request.method !== 'POST') {

Comment on lines 36 to 37
// header to indicate the state
response.writeHead(200, { 'Content-Type': 'application/json' });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is needed. The content is not valid JSON code anyway

Comment on lines 42 to 43
// parse the incoming body as that has the information we need to handle the request / user prompt
const payload = parseRequestBody(body);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would create a separate method to read the body text instead of moving all the core logic into the request.on('end', async () => { handler. And in this example, we should verify the payload using https://github.com/copilot-extensions/preview-sdk.js/?tab=readme-ov-file#async-verifyrequestbykeyidrawbody-signature-keyid-requestoptions

Comment on lines 48 to 49
// add new lines to mark the difference between the fixed text and the dynamic text
response.write("\n\n");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the new lines are included in textEvent

Suggested change
// add new lines to mark the difference between the fixed text and the dynamic text
response.write("\n\n");

Comment on lines 51 to 52
// add a first system prompt for the payload.messages to add instructions
payload.messages.unshift({ role: "system", content: "You are a helpful assistant that talks like a pirate." });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WE are doing this system message unshifting inside prompt already

https://github.com/copilot-extensions/preview-sdk.js/blob/b7063d6f46af712f3ea884e409a5cb8dbe505a70/lib/prompt.js#L15C9-L25

Suggested change
// add a first system prompt for the payload.messages to add instructions
payload.messages.unshift({ role: "system", content: "You are a helpful assistant that talks like a pirate." });

const payload_message = payload.messages[payload.messages.length - 1];
const result = await prompt(payload_message.content, {
messages: payload.messages, // we are giving the prompt the existing messages in this chat conversation
model: "gpt-4",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setting model is optional, we default it to gp-4o right now

const DEFAULT_MODEL = "gpt-4o";

@rajbos
Copy link
Contributor Author

rajbos commented Sep 14, 2024

@gr2m , I've addressed most of the feedback but moving the body parsing logic out of the on_end event. Please go over the comments and close them if the feedback has been handled adequately 😄.

Copy link
Collaborator

@gr2m gr2m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if you had a chance to test the apps once you applied all the remaining requested changes. If not I can do that too

examples/2-handle-prompt/index.js Outdated Show resolved Hide resolved
examples/2-handle-prompt/index.js Outdated Show resolved Hide resolved
examples/2-handle-prompt/index.js Outdated Show resolved Hide resolved
examples/2-handle-prompt/index.js Outdated Show resolved Hide resolved
// 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
system: "you talk like a pirate", // extra instructions for the prompt, the "you are a helpful assistant" is already set in the SDK
system: "You are a helpful assistant. You talk like a pirate",

Comment on lines 86 to 88
// 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));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a prompt.stream API but we can do a separate example for that if you like?

},
"dependencies": {
"@copilot-extensions/preview-sdk": "latest",
"@octokit": "latest"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use latest for external dependencies.

Suggested change
"@octokit": "latest"
"octokit": "^4.0.2"

@gr2m
Copy link
Collaborator

gr2m commented Sep 17, 2024

We have a live stream today that I think might draw some interest, I think it would be great to finish this up by then:
https://nickyt.live/#2024-09-17-gregor-martynus%2c%20staff%20software%20engineer%20at%20github

I'll address my remarks to get the PR merged, we can do follow up PRs aftewards

@gr2m gr2m self-assigned this Sep 17, 2024
@gr2m gr2m marked this pull request as ready for review September 17, 2024 16:08
@gr2m gr2m changed the title Adding example projects to help users get started docs(examples): hello world, prompt Sep 17, 2024
Copy link
Collaborator

@gr2m gr2m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for getting an examples/ folder started, this will be tremendously helpful. I should have started out with that 🙏🏼

@gr2m gr2m merged commit f61a49d into copilot-extensions:main Sep 17, 2024
3 checks passed
Copy link

🎉 This PR is included in version 5.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants