Skip to content

Commit 3aca4b1

Browse files
committed
Initial commit
0 parents  commit 3aca4b1

File tree

187 files changed

+14602
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

187 files changed

+14602
-0
lines changed

.devcontainer/devcontainer.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "GitHub Copilot CLI for Beginners",
3+
"image": "mcr.microsoft.com/devcontainers/python:2-3.13-bullseye",
4+
"features": {
5+
"ghcr.io/devcontainers/features/github-cli:1": {},
6+
"ghcr.io/devcontainers/features/node:1": {}
7+
},
8+
"customizations": {
9+
"vscode": {
10+
"extensions": [
11+
"ms-python.python"
12+
]
13+
}
14+
},
15+
"postCreateCommand": "pip install pytest && npm install -g @github/copilot && gh extension install github/gh-copilot",
16+
"postStartCommand": "echo '✅ Python, pytest, GitHub CLI, and Copilot CLI are ready. Run: cd samples/book-app-project && python book_app.py help'"
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
name: hello-world
3+
description: A minimal agent example - responds with friendly, encouraging messages
4+
---
5+
6+
# Hello World Agent
7+
8+
You are a friendly assistant who responds with encouraging messages.
9+
10+
When the user asks for help, always:
11+
- Start with a positive greeting
12+
- Keep responses brief and helpful
13+
- End with an encouraging note
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
name: pytest-helper
3+
description: Testing specialist for Python projects using pytest
4+
tools: ["read", "edit", "search", "execute"]
5+
---
6+
7+
# Pytest Testing Specialist
8+
9+
You are a testing expert focused on pytest best practices.
10+
11+
## Your Expertise
12+
13+
- pytest fixtures and parametrize decorators
14+
- Mocking with monkeypatch and unittest.mock
15+
- Test organization (arrange/act/assert)
16+
- Edge case identification
17+
18+
## Testing Standards
19+
20+
- Test behavior, not implementation
21+
- Use descriptive test names: test_<what>_<condition>_<expected>
22+
- One assertion per test when possible
23+
- Use fixtures for shared setup
24+
- Always test: happy path, edge cases, error cases
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
name: python-reviewer
3+
description: Python code quality specialist for reviewing Python projects
4+
tools: ["read", "edit", "search"]
5+
---
6+
7+
# Python Code Reviewer
8+
9+
You are a Python specialist focused on code quality and best practices.
10+
11+
## Your Expertise
12+
13+
- Python 3.10+ features (dataclasses, type hints, match statements)
14+
- PEP 8 style compliance
15+
- Error handling patterns (try/except, custom exceptions)
16+
- File I/O and JSON handling best practices
17+
18+
## Code Standards
19+
20+
When reviewing, always check for:
21+
- Missing type hints on function signatures
22+
- Bare except clauses (should catch specific exceptions)
23+
- Mutable default arguments
24+
- Proper use of context managers (with statements)
25+
- Input validation completeness
26+
27+
## When Reviewing Code
28+
29+
Prioritize:
30+
- [CRITICAL] Security issues and data corruption risks
31+
- [HIGH] Missing error handling
32+
- [MEDIUM] Style and type hint issues
33+
- [LOW] Minor improvements

.github/dependabot.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "pip"
9+
directory: "/"
10+
schedule:
11+
interval: "daily"
12+
- package-ecosystem: "nuget"
13+
directory: "/"
14+
schedule:
15+
interval: "daily"
16+
- package-ecosystem: "npm"
17+
directory: "/"
18+
schedule:
19+
interval: "daily"

.github/scripts/create-tapes.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Generate .tape files from demos.json configuration
4+
*
5+
* Supports single-prompt and multi-prompt demos:
6+
* - "prompt": "text" → single prompt
7+
* - "prompts": ["a", "b"] → multi-prompt (default responseWait each)
8+
* - "prompts": [{ "text": "a", "responseWait": 10 }, "b"] → mixed with overrides
9+
*
10+
* Usage: npm run create:tapes
11+
*/
12+
13+
const { writeFileSync, mkdirSync, existsSync } = require('fs');
14+
const { join } = require('path');
15+
16+
const rootDir = join(__dirname, '..', '..');
17+
const config = require('./demos.json');
18+
19+
function generatePromptBlock(entry, defaultWait, index) {
20+
const text = typeof entry === 'string' ? entry : entry.text;
21+
const wait = (typeof entry === 'object' && entry.responseWait) || defaultWait;
22+
const agentSelect = typeof entry === 'object' && entry.agentSelect;
23+
const label = index != null ? `Prompt ${index + 1}` : 'Execute the prompt';
24+
25+
// Agent selection: type /agent, wait for picker, arrow down to agent, select
26+
if (agentSelect) {
27+
const arrowDown = (typeof entry === 'object' && entry.arrowDown) || 0;
28+
const arrowBlock = arrowDown > 0 ? `Down ${arrowDown}\nSleep 1s\n` : '';
29+
return `# ${label} - Select ${agentSelect} agent
30+
Type "${text}"
31+
Sleep 1s
32+
Enter
33+
34+
# Wait for agent picker
35+
Sleep 3s
36+
${arrowBlock}Enter
37+
38+
# Wait for agent to load
39+
Sleep ${wait}s`;
40+
}
41+
42+
// If prompt ends with a file reference (@path), the file picker will be open.
43+
// Need an extra Enter to select the file before submitting the prompt.
44+
const endsWithFileRef = /@\S+$/.test(text);
45+
const enterBlock = endsWithFileRef
46+
? 'Enter\nSleep 1s\nEnter'
47+
: 'Enter';
48+
49+
return `# ${label}
50+
Type "${text}"
51+
Sleep 2s
52+
${enterBlock}
53+
54+
# Wait for response
55+
Sleep ${wait}s`;
56+
}
57+
58+
function generateTapeContent(demo, settings) {
59+
const s = { ...settings, ...demo }; // Allow per-demo overrides
60+
61+
// Build prompt blocks from either "prompt" (single) or "prompts" (array)
62+
let promptBlocks;
63+
if (demo.prompts && Array.isArray(demo.prompts)) {
64+
promptBlocks = demo.prompts
65+
.map((entry, i) => generatePromptBlock(entry, s.responseWait, i))
66+
.join('\n\n');
67+
} else {
68+
promptBlocks = generatePromptBlock(demo.prompt, s.responseWait);
69+
}
70+
71+
return `# ${demo.chapter}: ${demo.description}
72+
# Auto-generated from demos.json - Real copilot execution
73+
74+
Output ${demo.name}.gif
75+
76+
Set FontSize ${s.fontSize}
77+
Set Width ${s.width}
78+
Set Height ${s.height}
79+
Set Theme "${s.theme}"
80+
Set Padding 20
81+
Set BorderRadius 8
82+
Set Margin 10
83+
Set MarginFill "#282a36"
84+
Set Framerate ${s.framerate}
85+
86+
# Human typing speed
87+
Set TypingSpeed ${s.typingSpeed}
88+
89+
# Launch copilot
90+
Type "copilot"
91+
Enter
92+
93+
# Wait for copilot to start
94+
Sleep ${s.startupWait}s
95+
96+
${promptBlocks}
97+
98+
# Exit cleanly
99+
Ctrl+C
100+
Sleep ${s.exitWait}s
101+
`;
102+
}
103+
104+
// Main
105+
console.log('📝 Creating tape files from demos.json...\n');
106+
107+
let created = 0;
108+
109+
for (const demo of config.demos) {
110+
const imagesDir = join(rootDir, demo.chapter, 'images');
111+
const tapePath = join(imagesDir, `${demo.name}.tape`);
112+
113+
// Ensure images directory exists
114+
if (!existsSync(imagesDir)) {
115+
mkdirSync(imagesDir, { recursive: true });
116+
console.log(` Created: ${demo.chapter}/images/`);
117+
}
118+
119+
// Generate tape content
120+
const content = generateTapeContent(demo, config.settings);
121+
122+
// Write tape file
123+
writeFileSync(tapePath, content);
124+
console.log(` ✓ ${demo.chapter}/images/${demo.name}.tape`);
125+
created++;
126+
}
127+
128+
console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
129+
console.log(`✓ Created ${created} tape file(s)`);
130+
console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
131+
console.log(`\nNext: npm run generate:vhs`);

.github/scripts/demos.json

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
{
2+
"settings": {
3+
"fontSize": 18,
4+
"width": 1000,
5+
"height": 600,
6+
"theme": "Dracula",
7+
"typingSpeed": "60ms",
8+
"framerate": 10,
9+
"startupWait": 5,
10+
"responseWait": 25,
11+
"exitWait": 2
12+
},
13+
"demos": [
14+
{
15+
"chapter": "00-quick-start",
16+
"name": "hello-demo",
17+
"description": "Say hello to Copilot and explore what it can help with",
18+
"prompt": "Say hello and tell me what you can help with"
19+
},
20+
{
21+
"chapter": "01-setup-and-first-steps",
22+
"name": "code-review-demo",
23+
"description": "Review a file for code quality issues and suggest improvements",
24+
"prompt": "Review @samples/book-app-project/book_app.py for code quality issues and suggest improvements"
25+
},
26+
{
27+
"chapter": "01-setup-and-first-steps",
28+
"name": "explain-code-demo",
29+
"description": "Explain what a Python file does in simple terms",
30+
"prompt": "Explain what @samples/book-app-project/books.py does in simple terms"
31+
},
32+
{
33+
"chapter": "01-setup-and-first-steps",
34+
"name": "generate-code-demo",
35+
"description": "Generate a Python function from a natural language description",
36+
"responseWait": 35,
37+
"prompt": "Write a Python function that takes a list of books and returns statistics: total count, number read, number unread, oldest and newest book"
38+
},
39+
{
40+
"chapter": "02-context-conversations",
41+
"name": "file-context-demo",
42+
"description": "Use @file to ask about a specific file",
43+
"prompt": "What does @samples/book-app-project/utils.py do? Summarize briefly."
44+
},
45+
{
46+
"chapter": "02-context-conversations",
47+
"name": "multi-file-demo",
48+
"description": "Reference multiple files to understand data flow",
49+
"prompt": "Compare @samples/book-app-project/book_app.py and @samples/book-app-project/books.py - how do they work together? What's the data flow?"
50+
},
51+
{
52+
"chapter": "02-context-conversations",
53+
"name": "multi-turn-demo",
54+
"description": "Multi-turn conversation building on previous context",
55+
"prompts": [
56+
"@samples/book-app-project/ Give me an overview of this project",
57+
"What are the main code quality issues?",
58+
{ "text": "Which issue should I fix first and show me how?", "responseWait": 45 }
59+
]
60+
},
61+
{
62+
"chapter": "03-development-workflows",
63+
"name": "code-review-demo",
64+
"description": "Workflow 1: Code Review - review a file for code quality",
65+
"responseWait": 30,
66+
"prompt": "Review @samples/book-app-project/book_app.py for code quality"
67+
},
68+
{
69+
"chapter": "03-development-workflows",
70+
"name": "refactor-demo",
71+
"description": "Workflow 2: Refactoring - refactor command handling to dictionary dispatch",
72+
"responseWait": 30,
73+
"prompt": "@samples/book-app-project/book_app.py Refactor the command handling to use a dictionary dispatch pattern instead of if/elif chains"
74+
},
75+
{
76+
"chapter": "03-development-workflows",
77+
"name": "fix-bug-demo",
78+
"description": "Workflow 3: Debugging - debug a search issue",
79+
"responseWait": 30,
80+
"prompt": "@samples/book-app-buggy/books_buggy.py Users report that searching for 'The Hobbit' returns no results even though it's in the data. Debug why."
81+
},
82+
{
83+
"chapter": "03-development-workflows",
84+
"name": "test-gen-demo",
85+
"description": "Workflow 4: Test Generation - generate comprehensive pytest tests",
86+
"responseWait": 60,
87+
"prompt": "@samples/book-app-project/books.py Generate comprehensive pytest tests. Include tests for: Adding books, Removing books, Finding by title, Finding by author, Marking as read, Edge cases with empty data"
88+
},
89+
{
90+
"chapter": "03-development-workflows",
91+
"name": "git-integration-demo",
92+
"description": "Workflow 5: Git Integration - generate a conventional commit message",
93+
"responseWait": 30,
94+
"prompt": "Generate a conventional commit message for: $(git diff --staged)"
95+
},
96+
{
97+
"chapter": "04-agents-custom-instructions",
98+
"name": "python-reviewer-demo",
99+
"description": "Agent-based Python code review for type hints, error handling, and PEP 8",
100+
"prompt": "As a Python code quality expert, review @samples/book-app-project/books.py for type hints, error handling, and PEP 8 compliance"
101+
},
102+
{
103+
"chapter": "05-skills",
104+
"name": "list-skills-demo",
105+
"description": "List available slash commands and skills",
106+
"responseWait": 25,
107+
"prompt": "What slash commands and skills are available? List the main ones."
108+
},
109+
{
110+
"chapter": "05-skills",
111+
"name": "skill-trigger-demo",
112+
"description": "Copilot detects and triggers a matching skill",
113+
"responseWait": 45,
114+
"prompt": "Review the book collection code for issues"
115+
},
116+
{
117+
"chapter": "06-mcp-servers",
118+
"name": "mcp-status-demo",
119+
"description": "Check connected MCP servers with /mcp show",
120+
"responseWait": 25,
121+
"prompt": "/mcp show"
122+
},
123+
{
124+
"chapter": "06-mcp-servers",
125+
"name": "mcp-workflow-demo",
126+
"description": "Multi-step MCP workflow with issues and code analysis",
127+
"prompts": [
128+
"List open issues on this repository",
129+
{ "text": "@samples/book-app-project/books.py What code handles the search functionality?", "responseWait": 20 },
130+
{ "text": "Based on the code, suggest improvements for the search feature", "responseWait": 30 }
131+
]
132+
},
133+
{
134+
"chapter": "07-putting-it-together",
135+
"name": "full-review-demo",
136+
"description": "Idea to merged PR: plan, implement, test a new feature",
137+
"prompts": [
138+
{ "text": "I need to add a 'list unread' command to the book app that shows only books where read is False. What files need to change?", "responseWait": 25 },
139+
{ "text": "/agent", "agentSelect": "python-reviewer", "arrowDown": 3, "responseWait": 3 },
140+
{ "text": "@samples/book-app-project/books.py Design a get_unread_books method. What is the best approach?", "responseWait": 30 },
141+
{ "text": "/agent", "agentSelect": "pytest-helper", "arrowDown": 2, "responseWait": 3 },
142+
{ "text": "@samples/book-app-project/tests/test_books.py Design test cases for filtering unread books.", "responseWait": 30 },
143+
{ "text": "Add a get_unread_books method to BookCollection in books.py. Add a 'list unread' command option in book_app.py. Update the help text in the show_help function.", "responseWait": 30 },
144+
{ "text": "Generate comprehensive tests for the new feature", "responseWait": 35 },
145+
{ "text": "/review", "responseWait": 25 },
146+
{ "text": "Create a pull request titled 'Feature: Add list unread books command'", "responseWait": 25 }
147+
]
148+
}
149+
]
150+
}

0 commit comments

Comments
 (0)