diff --git a/.cspell.json b/.cspell.json index a9e8d9f..2bf7a11 100644 --- a/.cspell.json +++ b/.cspell.json @@ -4,6 +4,7 @@ "files": [ "**/*.{js,vue,md,html,css,bash}", ".github/**/*.md", + ".github/skills/**/*.bash", ".devcontainer/**/*.bash" ], "ignorePaths": [ @@ -28,6 +29,7 @@ "prettier", "setsid", "streetsidesoftware", + "toplevel", "vite", "vitejs", "vuejs", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 38dd9e4..b4c29c4 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,6 +10,9 @@ "vncPort": "5901" } }, + "remoteEnv": { + "PATH": "${containerEnv:PATH}:/workspaces/Vue3-WebDev-Kit/bin" + }, "portsAttributes": { "8000": { "label": "http", @@ -31,7 +34,8 @@ "streetsidesoftware.code-spell-checker", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", - "yzhang.markdown-all-in-one" + "yzhang.markdown-all-in-one", + "crimson206.vscode-command-server" ], "settings": { "editor.formatOnSave": true, diff --git a/.devcontainer/postAttach.bash b/.devcontainer/postAttach.bash index 2ef99a0..8375fd4 100755 --- a/.devcontainer/postAttach.bash +++ b/.devcontainer/postAttach.bash @@ -3,13 +3,15 @@ for i in {1..15}; do # check for webserver using curl VNC_RUNNING=$(curl -Is http://localhost:6901 2> /dev/null | grep "HTTP/1.1 200 OK") WEB_SERVER_RUNNING=$(curl -Is http://localhost:8000 2> /dev/null | grep "HTTP/1.0 200 OK") + COMMAND_SERVER_RUNNING=$(curl -Is http://localhost:3000 2> /dev/null | grep "HTTP/1.1 200 OK") - # If both the web server and VNC server are running, print a message and exit - if [ -n "$VNC_RUNNING" ] && [ -n "$WEB_SERVER_RUNNING" ]; then + # If all servers are running, print a message and exit + if [ -n "$VNC_RUNNING" ] && [ -n "$WEB_SERVER_RUNNING" ] && [ -n "$COMMAND_SERVER_RUNNING" ]; then echo "" echo "" echo "Web server found at http://localhost:8000." echo "noVNC server found at http://localhost:6901." + echo "VSCode command server found." echo "" echo "*****************************************" echo "The Vue3 WebDev Kit is now ready for use." diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 72c92ff..d8641bb 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,4 +1,4 @@ -## Co-Pilot Pull Request Reviews +## Copilot Pull Request Reviews - When reviewing a pull request read the body of the pull request and identify the "Type of Work" and the "Topic". - If no "Type of Work" or "Topic" is checked in the task list or more than one "Type of Work" or more than one "Topic" is checked, leave a comment on the pull request asking the author to check exactly one "Type of Work" and exactly one "Topic" and do not perform a review. diff --git a/.gitignore b/.gitignore index a917fb2..ebb1bea 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ yarn-error.log* pnpm-debug.log* lerna-debug.log* +**/chat.json +**/processed-chat.txt + node_modules flashword/dist dist-ssr diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5e73623..2ad5a10 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,7 +110,7 @@ Use the following steps when working through a tutorial.

2.

- Watch the tutorial step-by-step and build the artifact. + Follow the tutorial step-by-step and build the artifact. For video tutorials, pause and rewind the video as frequently as necessary for you to follow along and add the code that is shown to your project. @@ -138,7 +138,7 @@ Use the following steps when working through a tutorial. 5. Navigate to the page that you want to view in the directory structure (e.g. for tutorial 01 click `web-projects` and then `first-website`). - 6. Once your page is open in a browser tab, reloading the page will display the effect of any changes you make. + 6. Use the reload button in the browser to update your page when you have made changes.
@@ -217,7 +217,7 @@ Use the following steps when working through a tutorial. -

+

2.

@@ -231,7 +231,7 @@ Use the following steps when working through a tutorial. 4. Pick the model to be used from the popup in the bottom left of the "Add a comment" box. 5. Click the "Start new session" button. 6. Copilot will to respond in a comment on your pull request. - +  

@@ -342,7 +342,21 @@ Working on the extension tasks is very similar to working on the tutorial tasks.

-5. ▷ [Push your feature branch](#push-feature-branch) to GitHub. +5. +

+ Log your Copilot chat (if you used AI). + + If you used Copilot and AI in your last commit, use the steps below to log the prompts that you used into a comment on your pull request. Note re-logging the same chat updates the previous comment by adding new prompts to it. + + 1. Run the `log-chat.bash` command in the terminal. + 2. Click "OK" or press the Enter/Return key to accept the default path for the chat log. It doesn't matter where this log is stored, it will be deleted after it is posted to your pull request. + ![The chat log path dialog with the "OK" button.](./docs/images/chat-log-path.png) + 3. Review the output in the terminal and visit you PR on GitHub to ensure that your chat log has been posted to a comment. +
+ +

+ +6. ▷ [Push your feature branch](#push-feature-branch) to GitHub. ### Completing an Extension diff --git a/bin/log-chat.bash b/bin/log-chat.bash new file mode 100755 index 0000000..6fea6e6 --- /dev/null +++ b/bin/log-chat.bash @@ -0,0 +1,12 @@ +#!/bin/bash + +REPO_ROOT=$(git rev-parse --show-toplevel) +cd "$REPO_ROOT/bin/log-chat" || exit 1 + +./openPR.bash && \ +./cleanUp.bash && \ +./exportChatLog.bash && \ +./processChatJson.bash && \ +./createComment.bash + +./cleanUp.bash \ No newline at end of file diff --git a/bin/log-chat/cleanUp.bash b/bin/log-chat/cleanUp.bash new file mode 100755 index 0000000..08a50b6 --- /dev/null +++ b/bin/log-chat/cleanUp.bash @@ -0,0 +1,18 @@ +#!/bin/bash + +REPO_ROOT=$(git rev-parse --show-toplevel) + +# Delete any chat.json logs that are found in the repository. +# Search recursively from the repository root to find all chat.json files +CHAT_LOGS=$(find "$REPO_ROOT" -name "chat.json" -type f) +if [ -n "$CHAT_LOGS" ]; then + echo "Deleting chat.json file(s)." + rm -f $CHAT_LOGS +fi + +# Delete any processed-chat.txt files that are found in the repository. +PROCESSED_CHAT_LOGS=$(find "$REPO_ROOT" -name "processed-chat.txt" -type f) +if [ -n "$PROCESSED_CHAT_LOGS" ]; then + echo "Deleting processed-chat.txt file(s)." + rm -f $PROCESSED_CHAT_LOGS +fi \ No newline at end of file diff --git a/bin/log-chat/createComment.bash b/bin/log-chat/createComment.bash new file mode 100755 index 0000000..775ecf3 --- /dev/null +++ b/bin/log-chat/createComment.bash @@ -0,0 +1,79 @@ +#!/bin/bash + +REPO_ROOT=$(git rev-parse --show-toplevel) + +# Get the current branch name +CURRENT_BRANCH=$(git branch --show-current) + +# Find the open pull request for the current branch +PR_NUMBER=$(gh pr list --head "$CURRENT_BRANCH" --state open --json number --jq '.[0].number' 2>/dev/null) + +if [ -z "$PR_NUMBER" ]; then + echo "Error: No open pull request found for branch $CURRENT_BRANCH." + exit 1 +fi + +# Find the chat.json file +CHAT_LOG=$(find "$REPO_ROOT" -name "chat.json" -type f | head -n 1) + +if [ -z "$CHAT_LOG" ]; then + echo "Error: chat.json not found. Be sure to export the chat log." + exit 1 +fi + +# Find the ID of the first request in the chat.json file +CHAT_HASH=$(jq -r '.requests[0].requestId' "$CHAT_LOG") + +# Find the processed-chat.txt file +PROCESSED_CHAT_FILE=$(find "$REPO_ROOT" -name "processed-chat.txt" -type f | head -n 1) + +if [ -z "$PROCESSED_CHAT_FILE" ]; then + echo "Exported chat logs were not found." + echo "Be sure to export the chat log to a location within the repository." + exit 1 +fi + +PROMPTS=$(cat "$PROCESSED_CHAT_FILE") + +# Search the comments for the hidden message ID +EXISTING_COMMENT=$(gh pr view "$PR_NUMBER" --json comments --jq ".comments[] | select(.body | contains(\"\"))" | head -n 1) + +TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S") + +if [ -n "$EXISTING_COMMENT" ]; then + # If comment found, update it + COMMENT_ID=$(echo "$EXISTING_COMMENT" | jq -r '.id') + + # Retain the original creation time + ORIGINAL_TIME=$(echo "$EXISTING_COMMENT" | jq -r '.body' | grep -oP 'Created: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}') + if [ -n "$ORIGINAL_TIME" ]; then + TIME_LINE="$ORIGINAL_TIME" + else + TIME_LINE="Created: $TIMESTAMP" + fi + + # Construct new body + NEW_BODY=$(cat < + +$PROMPTS +EOF +) + + gh api graphql -f query='mutation($id: ID!, $body: String!) { updateIssueComment(input: {id: $id, body: $body}) { issueComment { id } } }' -f id="$COMMENT_ID" -f body="$NEW_BODY" --silent + echo "Updated existing Copilot Chat Log comment on PR #$PR_NUMBER." +else + # Otherwise create a new comment + NEW_BODY=$(cat < + +$PROMPTS +EOF +) + gh pr comment "$PR_NUMBER" --body "$NEW_BODY" 2> /dev/null + echo "Created new Copilot Chat Log comment on PR #$PR_NUMBER." +fi diff --git a/bin/log-chat/exportChatLog.bash b/bin/log-chat/exportChatLog.bash new file mode 100755 index 0000000..26dcb89 --- /dev/null +++ b/bin/log-chat/exportChatLog.bash @@ -0,0 +1,25 @@ +#!/bin/bash + +REPO_ROOT=$(git rev-parse --show-toplevel) + +echo "Exporting chat log. Press Enter or click OK to accept default location." +curl -s -o /dev/null -X POST http://localhost:3000/execute \ + -H "Content-Type: application/json" \ + -d '{"command": "workbench.action.chat.export"}' 2> /dev/null + +# Make sure the chat log was saved in the repository. +CHAT_LOGS=$(find "$REPO_ROOT" -name "chat.json" -type f) +if [ -z "$CHAT_LOGS" ]; then + echo "No chat.json files found in the repository." + echo "Be sure to export the chat log somewhere in the repository." + exit 1 +fi + +# Display a message if the chat log is empty. +if grep -q '"requests": \[\]$' "$CHAT_LOGS"; then + echo "You seem to have exported an empty chat log." + echo "Be sure to have a chat open when you use the /log-prompts skill." + exit 1 +fi + +exit 0 \ No newline at end of file diff --git a/bin/log-chat/openPR.bash b/bin/log-chat/openPR.bash new file mode 100755 index 0000000..60289b3 --- /dev/null +++ b/bin/log-chat/openPR.bash @@ -0,0 +1,98 @@ +#!/bin/bash + +REPO_ROOT=$(git rev-parse --show-toplevel) + +# Get the current branch name +CURRENT_BRANCH=$(git branch --show-current) + +# Check if we're on a branch (not in detached HEAD state) +if [ -z "$CURRENT_BRANCH" ]; then + echo "Your current branch is in a detached HEAD state." + echo "Please switch to a branch and try again." + exit 1 +fi + +# Check if there's already an open pull request for this branch +EXISTING_PR=$(gh pr list --head "$CURRENT_BRANCH" --state open --json number --jq '.[0].number' 2>/dev/null) + +if [ -n "$EXISTING_PR" ]; then + echo "Open pull request found for branch: $CURRENT_BRANCH (PR #$EXISTING_PR)" + exit 0 +fi + +# No PR exists, prompt the user +echo "" +echo "No open pull request was found for branch: $CURRENT_BRANCH" +read -p "Do you want to create a pull request now? (y/n) " -r +echo "" + +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Try again when you have created a pull request." + exit 1 +fi + +# Read PULL_REQUEST_TEMPLATE.md and extract options dynamically +TEMPLATE_FILE="$REPO_ROOT/.github/PULL_REQUEST_TEMPLATE.md" + +if [ ! -f "$TEMPLATE_FILE" ]; then + echo "Error: $TEMPLATE_FILE not found" + exit 1 +fi + +# Extract Type of Work options (between "### Type of Work" and "### Topic") +mapfile -t TYPE_OPTIONS < <(sed -n '/^### Type of Work/,/^### Topic/p' "$TEMPLATE_FILE" | grep -oP '(?<=- \[ \] - )\S+' | grep -v '^$') + +# Extract Topic options (between "### Topic" and "### Time Estimate") +mapfile -t TOPIC_OPTIONS < <(sed -n '/^### Topic/,/^### Time Estimate/p' "$TEMPLATE_FILE" | grep -oP '(?<=- \[ \] - ).+' | sed 's/^[[:space:]]*//') + +# Ask for Type of Work +while true; do + echo "" + echo "Select Type of Work:" + for i in "${!TYPE_OPTIONS[@]}"; do + echo "$((i + 1))) ${TYPE_OPTIONS[$i]}" + done + read -p "Enter your choice (1-${#TYPE_OPTIONS[@]}): " -r TYPE_CHOICE + + if [[ $TYPE_CHOICE =~ ^[0-9]+$ ]] && [ "$TYPE_CHOICE" -ge 1 ] && [ "$TYPE_CHOICE" -le ${#TYPE_OPTIONS[@]} ]; then + TYPE_OF_WORK="${TYPE_OPTIONS[$((TYPE_CHOICE - 1))]}" + break + fi + echo "Invalid choice. Please try again." +done + +# Ask for Topic +while true; do + echo "" + echo "Select Topic:" + for i in "${!TOPIC_OPTIONS[@]}"; do + echo "$((i + 1))) ${TOPIC_OPTIONS[$i]}" + done + read -p "Enter your choice (1-${#TOPIC_OPTIONS[@]}): " -r TOPIC_CHOICE + + if [[ $TOPIC_CHOICE =~ ^[0-9]+$ ]] && [ "$TOPIC_CHOICE" -ge 1 ] && [ "$TOPIC_CHOICE" -le ${#TOPIC_OPTIONS[@]} ]; then + TOPIC="${TOPIC_OPTIONS[$((TOPIC_CHOICE - 1))]}" + break + fi + echo "Invalid choice. Please try again." +done + +# Check if the active branch has any commits +COMMIT_COUNT=$(git rev-list --count main..$CURRENT_BRANCH 2>/dev/null || echo "0") + +if [ "$COMMIT_COUNT" -eq 0 ]; then + # No commits on this branch, create an empty commit + COMMIT_MESSAGE="Starting $TYPE_OF_WORK - $TOPIC" + git commit --allow-empty -m "$COMMIT_MESSAGE" 2> /dev/null +fi + +# Create the PR with a title that includes the Type of Work and Topic +PR_TITLE="$TYPE_OF_WORK - $TOPIC" + +# Read the PULL_REQUEST_TEMPLATE and check the selected Type of Work and Topic +PR_BODY=$(cat "$TEMPLATE_FILE" | sed "s/- \[ \] - $TYPE_OF_WORK/- [X] - $TYPE_OF_WORK/" | sed "s/- \[ \] - $TOPIC/- [X] - $TOPIC/") + +git push upstream "$CURRENT_BRANCH" 2> /dev/null +gh pr create --base main --head "$CURRENT_BRANCH" --title "$PR_TITLE" --body "$PR_BODY" 2> /dev/null + +echo "New pull request created for branch: $CURRENT_BRANCH" \ No newline at end of file diff --git a/bin/log-chat/processChatJson.bash b/bin/log-chat/processChatJson.bash new file mode 100755 index 0000000..5fa6eb6 --- /dev/null +++ b/bin/log-chat/processChatJson.bash @@ -0,0 +1,18 @@ +#!/bin/bash + +# Path to your JSON file +REPO_ROOT=$(git rev-parse --show-toplevel) +CHAT_LOG=$(find "$REPO_ROOT" -name "chat.json" -type f) +CHAT_LOG_DIR=$(dirname "$CHAT_LOG") +POST_PROCESSED_CHAT_LOG="$CHAT_LOG_DIR/processed-chat.txt" + +# Copy the message texts into the processed-chat.txt file. + +jq -j '.requests[].message.text + "\u0000"' "$CHAT_LOG" | while IFS= read -r -d '' msg; do + echo "---" >> "$POST_PROCESSED_CHAT_LOG" + echo "" >> "$POST_PROCESSED_CHAT_LOG" + echo "$msg" >> "$POST_PROCESSED_CHAT_LOG" + echo "" >> "$POST_PROCESSED_CHAT_LOG" +done + +echo --- >> "$POST_PROCESSED_CHAT_LOG" \ No newline at end of file diff --git a/docs/QuickReference.md b/docs/QuickReference.md index 718007a..7bcabfc 100644 --- a/docs/QuickReference.md +++ b/docs/QuickReference.md @@ -2,15 +2,18 @@ ## Workflow Steps -The following are the main activities that you will need to do when working on this kit. Each links takes you to the appropriate section of the `CONTRIBUTING.md`] file. +The following are the main activities that you will need to do when working on this kit. Each links takes you to the appropriate section of the [`CONTRIBUTING.md`] file or other sources as appropriate. - [Starting a Tutorial](../CONTRIBUTING.md#starting-a-tutorial) - [Working on Tutorial Tasks](../CONTRIBUTING.md#working-on-tutorial-tasks) + - [Coauthor Attribution Generator](https://coauthors.me/generator) - [Completing a Tutorial](../CONTRIBUTING.md#completing-a-tutorial) - [Pausing your Work](../CONTRIBUTING.md#pausing-your-work) - [Resuming your Work](../CONTRIBUTING.md#resuming-your-work) - [Starting an Extension](../CONTRIBUTING.md#starting-an-extension) - [Working on Extension Tasks](../CONTRIBUTING.md#working-on-extension-tasks) + - [Including AI Attributions](./AttributionTrailers.md) + - [Logging Copilot Chats](../CONTRIBUTING.md#log-copilot-chat) - [Completing an Extension](../CONTRIBUTING.md#completing-an-extension) ## Keyboard Shortcuts @@ -33,10 +36,12 @@ The following are the main activities that you will need to do when working on t ### Browser -| Windows/Linux | MacOS | Action | -| ----------------------- | ------------------------- | -------------------------- | -| `F12` | `F12` | Toggle the Developer Tools | -| `Ctrl + Shift + Delete` | ⌘`+ Shift + Delete` | Clear browsing history. | +| Windows/Linux | MacOS | Action | +| ----------------------- | ------------------------- | --------------------------- | +| `Ctrl + R` | ⌘`+ R` | Standard refresh | +| `Ctrl + Shift + R` | ⌘`+ Shift + R` | Hard refresh (bypass cache) | +| `F12` | `F12` | Toggle the Developer Tools | +| `Ctrl + Shift + Delete` | ⌘`+ Shift + Delete` | Clear browsing history | ## Git Commands @@ -55,5 +60,3 @@ The following are the main activities that you will need to do when working on t | `git push origin ` | Push the branch named `` to your GitHub space. | ## Miscellaneous - -- [Coauthors Generator](https://coauthors.me/generator) diff --git a/docs/images/chat-log-path.png b/docs/images/chat-log-path.png new file mode 100644 index 0000000..8a7bca9 Binary files /dev/null and b/docs/images/chat-log-path.png differ