Skip to content

Commit 6cd321b

Browse files
Merge branch 'main' into docs/python-system-message-customization
2 parents 16ee68e + 460b48a commit 6cd321b

2,635 files changed

Lines changed: 439023 additions & 73275 deletions

File tree

Some content is hidden

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

.gitattributes

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44
nodejs/src/generated/* eol=lf linguist-generated=true
55
dotnet/src/Generated/* eol=lf linguist-generated=true
66
python/copilot/generated/* eol=lf linguist-generated=true
7-
go/generated_session_events.go eol=lf linguist-generated=true
8-
go/rpc/generated_rpc.go eol=lf linguist-generated=true
7+
go/zsession_events.go eol=lf linguist-generated=true
8+
go/zsession_encoding.go eol=lf linguist-generated=true
9+
go/rpc/zrpc.go eol=lf linguist-generated=true
10+
go/rpc/zrpc_encoding.go eol=lf linguist-generated=true

.githooks/pre-commit

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/sh
2+
#
3+
# Pre-commit hook that runs Spotless check on the Java SDK when Java source
4+
# files are staged. Only triggers if changes exist under java/src/.
5+
#
6+
# To install this hook, run from the repository root:
7+
# git config core.hooksPath .githooks
8+
#
9+
10+
# Only run Spotless if staged changes include Java source files under java/src/
11+
if ! git diff --cached --name-only | grep -q '^java/src/'; then
12+
exit 0
13+
fi
14+
15+
echo "Running Spotless check on java/ ..."
16+
17+
# Run spotless check from the java directory
18+
(cd java && mvn spotless:check -q)
19+
20+
if [ $? -ne 0 ]; then
21+
echo ""
22+
echo "❌ Spotless check failed!"
23+
echo " Run 'cd java && mvn spotless:apply' to fix formatting issues."
24+
echo ""
25+
exit 1
26+
fi
27+
28+
echo "✓ Spotless check passed"
29+
exit 0
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
name: "Java Test Report"
2+
description: "Generate and publish test reports with summary for Java SDK tests."
3+
inputs:
4+
report-path:
5+
description: "Path to the test report XML files (glob pattern)"
6+
required: false
7+
default: "java/target/{surefire-reports*,failsafe-reports}/TEST-*.xml"
8+
jacoco-path:
9+
description: "Path to the JaCoCo XML report"
10+
required: false
11+
default: "java/target/site/jacoco-coverage/jacoco.xml"
12+
jacoco-csv-path:
13+
description: "Path to the JaCoCo CSV report"
14+
required: false
15+
default: "java/target/site/jacoco-coverage/jacoco.csv"
16+
check-name:
17+
description: "Name for the check run"
18+
required: false
19+
default: "Java SDK Test Results"
20+
title:
21+
description: "Title for the test report summary"
22+
required: false
23+
default: "Copilot Java SDK :: Test Results"
24+
runs:
25+
using: "composite"
26+
steps:
27+
- name: Generate Test Summary
28+
shell: bash
29+
run: |
30+
echo "## 🧪 ${{ inputs.title }}" >> $GITHUB_STEP_SUMMARY
31+
echo "" >> $GITHUB_STEP_SUMMARY
32+
33+
if ls ${{ inputs.report-path }} 1>/dev/null 2>&1; then
34+
TESTS_RUN=$(grep -h "tests=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*tests="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
35+
FAILURES=$(grep -h "failures=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*failures="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
36+
ERRORS=$(grep -h "errors=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*errors="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
37+
SKIPPED=$(grep -h "skipped=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*skipped="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
38+
39+
TESTS_RUN=${TESTS_RUN:-0}
40+
FAILURES=${FAILURES:-0}
41+
ERRORS=${ERRORS:-0}
42+
SKIPPED=${SKIPPED:-0}
43+
PASSED=$((TESTS_RUN - FAILURES - ERRORS - SKIPPED))
44+
45+
if [ "$FAILURES" -eq 0 ] && [ "$ERRORS" -eq 0 ]; then
46+
echo "### ✅ All tests passed!" >> $GITHUB_STEP_SUMMARY
47+
else
48+
echo "### ❌ Some tests failed" >> $GITHUB_STEP_SUMMARY
49+
fi
50+
51+
echo "" >> $GITHUB_STEP_SUMMARY
52+
echo "| Metric | Count |" >> $GITHUB_STEP_SUMMARY
53+
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
54+
echo "| ✅ Passed | $PASSED |" >> $GITHUB_STEP_SUMMARY
55+
echo "| ❌ Failed | $FAILURES |" >> $GITHUB_STEP_SUMMARY
56+
echo "| 💥 Errors | $ERRORS |" >> $GITHUB_STEP_SUMMARY
57+
echo "| ⏭️ Skipped | $SKIPPED |" >> $GITHUB_STEP_SUMMARY
58+
echo "| 📊 Total | $TESTS_RUN |" >> $GITHUB_STEP_SUMMARY
59+
60+
echo "" >> $GITHUB_STEP_SUMMARY
61+
echo "### Test Classes" >> $GITHUB_STEP_SUMMARY
62+
echo "" >> $GITHUB_STEP_SUMMARY
63+
echo "| Class | Tests | Passed | Failed | Errors | Time |" >> $GITHUB_STEP_SUMMARY
64+
echo "|-------|-------|--------|--------|--------|------|" >> $GITHUB_STEP_SUMMARY
65+
66+
for file in ${{ inputs.report-path }}; do
67+
if [ -f "$file" ]; then
68+
CLASS=$(basename "$file" .xml | sed 's/TEST-//')
69+
T=$(grep -m 1 -o 'tests="[0-9]*"' "$file" | sed 's/[^0-9]//g')
70+
F=$(grep -m 1 -o 'failures="[0-9]*"' "$file" | sed 's/[^0-9]//g')
71+
E=$(grep -m 1 -o 'errors="[0-9]*"' "$file" | sed 's/[^0-9]//g')
72+
TIME=$(grep -m 1 -o 'time="[0-9.]*"' "$file" | sed 's/[^0-9.]//g')
73+
P=$((T - F - E))
74+
75+
STATUS="✅"
76+
if [ "${F:-0}" -gt 0 ] || [ "${E:-0}" -gt 0 ]; then
77+
STATUS="❌"
78+
fi
79+
80+
echo "| $STATUS $CLASS | ${T:-0} | ${P:-0} | ${F:-0} | ${E:-0} | ${TIME:-0}s |" >> $GITHUB_STEP_SUMMARY
81+
fi
82+
done
83+
else
84+
echo "⚠️ No test reports found at ${{ inputs.report-path }}" >> $GITHUB_STEP_SUMMARY
85+
fi
86+
87+
- name: Generate Coverage Summary
88+
shell: bash
89+
run: |
90+
JACOCO_XML="${{ inputs.jacoco-path }}"
91+
JACOCO_CSV="${{ inputs.jacoco-csv-path }}"
92+
93+
if [ -f "$JACOCO_XML" ]; then
94+
echo "" >> $GITHUB_STEP_SUMMARY
95+
echo "## 📊 Code Coverage" >> $GITHUB_STEP_SUMMARY
96+
echo "" >> $GITHUB_STEP_SUMMARY
97+
98+
# JaCoCo XML may be on a single line - split it for parsing
99+
# Extract report-level counters (last occurrence of each type before </report>)
100+
extract_counter() {
101+
local type=$1
102+
local field=$2
103+
# Split XML on > to get one tag per line, find counter, extract value
104+
sed 's/>/>\n/g' "$JACOCO_XML" | grep "<counter type=\"$type\"" | tail -1 | sed "s/.*$field=\"\([0-9]*\)\".*/\1/"
105+
}
106+
107+
INSTR_MISSED=$(extract_counter "INSTRUCTION" "missed")
108+
INSTR_COVERED=$(extract_counter "INSTRUCTION" "covered")
109+
110+
BRANCH_MISSED=$(extract_counter "BRANCH" "missed")
111+
BRANCH_COVERED=$(extract_counter "BRANCH" "covered")
112+
113+
LINE_MISSED=$(extract_counter "LINE" "missed")
114+
LINE_COVERED=$(extract_counter "LINE" "covered")
115+
116+
METHOD_MISSED=$(extract_counter "METHOD" "missed")
117+
METHOD_COVERED=$(extract_counter "METHOD" "covered")
118+
119+
CLASS_MISSED=$(extract_counter "CLASS" "missed")
120+
CLASS_COVERED=$(extract_counter "CLASS" "covered")
121+
122+
# Calculate percentages
123+
calc_pct() {
124+
local covered=$1
125+
local missed=$2
126+
if [ -n "$covered" ] && [ -n "$missed" ]; then
127+
local total=$((covered + missed))
128+
if [ "$total" -gt 0 ]; then
129+
echo "scale=1; $covered * 100 / $total" | bc
130+
else
131+
echo "0"
132+
fi
133+
else
134+
echo "N/A"
135+
fi
136+
}
137+
138+
INSTR_PCT=$(calc_pct "${INSTR_COVERED:-0}" "${INSTR_MISSED:-0}")
139+
BRANCH_PCT=$(calc_pct "${BRANCH_COVERED:-0}" "${BRANCH_MISSED:-0}")
140+
LINE_PCT=$(calc_pct "${LINE_COVERED:-0}" "${LINE_MISSED:-0}")
141+
METHOD_PCT=$(calc_pct "${METHOD_COVERED:-0}" "${METHOD_MISSED:-0}")
142+
CLASS_PCT=$(calc_pct "${CLASS_COVERED:-0}" "${CLASS_MISSED:-0}")
143+
144+
echo "| Metric | Covered | Missed | Coverage |" >> $GITHUB_STEP_SUMMARY
145+
echo "|--------|---------|--------|----------|" >> $GITHUB_STEP_SUMMARY
146+
echo "| 📝 Instructions | ${INSTR_COVERED:-0} | ${INSTR_MISSED:-0} | ${INSTR_PCT}% |" >> $GITHUB_STEP_SUMMARY
147+
echo "| 🌿 Branches | ${BRANCH_COVERED:-0} | ${BRANCH_MISSED:-0} | ${BRANCH_PCT}% |" >> $GITHUB_STEP_SUMMARY
148+
echo "| 📏 Lines | ${LINE_COVERED:-0} | ${LINE_MISSED:-0} | ${LINE_PCT}% |" >> $GITHUB_STEP_SUMMARY
149+
echo "| 🔧 Methods | ${METHOD_COVERED:-0} | ${METHOD_MISSED:-0} | ${METHOD_PCT}% |" >> $GITHUB_STEP_SUMMARY
150+
echo "| 📦 Classes | ${CLASS_COVERED:-0} | ${CLASS_MISSED:-0} | ${CLASS_PCT}% |" >> $GITHUB_STEP_SUMMARY
151+
152+
if [ -f "$JACOCO_CSV" ]; then
153+
extract_instruction_scope() {
154+
local scope=$1
155+
awk -F',' -v scope="$scope" -v generated_prefix="com.github.copilot.generated" '
156+
NR > 1 {
157+
is_generated = index($2, generated_prefix) == 1
158+
if ((scope == "generated" && is_generated) ||
159+
(scope == "handwritten" && !is_generated)) {
160+
missed += $4
161+
covered += $5
162+
}
163+
}
164+
END { print covered + 0 "," missed + 0 }
165+
' "$JACOCO_CSV"
166+
}
167+
168+
IFS=, read -r HANDWRITTEN_COVERED HANDWRITTEN_MISSED <<< "$(extract_instruction_scope handwritten)"
169+
IFS=, read -r GENERATED_COVERED GENERATED_MISSED <<< "$(extract_instruction_scope generated)"
170+
HANDWRITTEN_PCT=$(calc_pct "${HANDWRITTEN_COVERED:-0}" "${HANDWRITTEN_MISSED:-0}")
171+
GENERATED_PCT=$(calc_pct "${GENERATED_COVERED:-0}" "${GENERATED_MISSED:-0}")
172+
173+
echo "" >> $GITHUB_STEP_SUMMARY
174+
echo "### Coverage by Code Origin (Instructions)" >> $GITHUB_STEP_SUMMARY
175+
echo "" >> $GITHUB_STEP_SUMMARY
176+
echo "| Origin | Covered | Missed | Coverage |" >> $GITHUB_STEP_SUMMARY
177+
echo "|--------|---------|--------|----------|" >> $GITHUB_STEP_SUMMARY
178+
echo "| ✍️ Handwritten | ${HANDWRITTEN_COVERED:-0} | ${HANDWRITTEN_MISSED:-0} | ${HANDWRITTEN_PCT}% |" >> $GITHUB_STEP_SUMMARY
179+
echo "| 🤖 Generated | ${GENERATED_COVERED:-0} | ${GENERATED_MISSED:-0} | ${GENERATED_PCT}% |" >> $GITHUB_STEP_SUMMARY
180+
fi
181+
else
182+
echo "" >> $GITHUB_STEP_SUMMARY
183+
echo "## 📊 Code Coverage" >> $GITHUB_STEP_SUMMARY
184+
echo "" >> $GITHUB_STEP_SUMMARY
185+
echo "⚠️ No JaCoCo report found at $JACOCO_XML" >> $GITHUB_STEP_SUMMARY
186+
fi

.github/actions/setup-copilot/action.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,30 @@ runs:
88
using: "composite"
99
steps:
1010
- uses: actions/setup-node@v6
11+
if: runner.os != 'Windows'
1112
with:
1213
cache: "npm"
1314
cache-dependency-path: "./nodejs/package-lock.json"
1415
node-version: 22
16+
- uses: actions/setup-node@v6
17+
if: runner.os == 'Windows'
18+
with:
19+
node-version: 22
1520
- name: Install dependencies
1621
run: npm --prefix "$(pwd)/nodejs" ci --ignore-scripts
1722
shell: bash
1823
- name: Set CLI path
1924
id: cli-path
20-
run: echo "path=$(pwd)/nodejs/node_modules/@github/copilot/index.js" >> $GITHUB_OUTPUT
25+
run: |
26+
# As of CLI 1.0.64-1 the @github/copilot package is a thin loader; the
27+
# runnable index.js ships in the installed platform package
28+
# (e.g. @github/copilot-linux-x64). Exactly one is installed.
29+
cli_path=$(ls "$(pwd)"/nodejs/node_modules/@github/copilot-*/index.js 2>/dev/null | head -n1)
30+
if [ -z "$cli_path" ]; then
31+
echo "Could not find @github/copilot platform package (index.js) under nodejs/node_modules" >&2
32+
exit 1
33+
fi
34+
echo "path=$cli_path" >> $GITHUB_OUTPUT
2135
shell: bash
2236
- name: Verify CLI works
2337
run: node ${{ steps.cli-path.outputs.path }} --version

.github/agents/docs-maintenance.agent.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ cat nodejs/src/types.ts | grep -A 10 "export interface ExportSessionOptions"
344344
- `CopilotClient` constructor options: `cliPath`, `cliUrl`, `useStdio`, `port`, `logLevel`, `autoStart`, `env`, `githubToken`, `useLoggedInUser`
345345
- `createSession()` config: `model`, `tools`, `hooks`, `systemMessage`, `mcpServers`, `availableTools`, `excludedTools`, `streaming`, `reasoningEffort`, `provider`, `infiniteSessions`, `customAgents`, `workingDirectory`
346346
- `CopilotSession` methods: `send()`, `sendAndWait()`, `getMessages()`, `disconnect()`, `abort()`, `on()`, `once()`, `off()`
347-
- Hook names: `onPreToolUse`, `onPostToolUse`, `onUserPromptSubmitted`, `onSessionStart`, `onSessionEnd`, `onErrorOccurred`
347+
- Hook names: `onPreToolUse`, `onPostToolUse`, `onPostToolUseFailure`, `onUserPromptSubmitted`, `onSessionStart`, `onSessionEnd`, `onErrorOccurred`
348348

349349
#### Python Validation
350350

@@ -353,16 +353,16 @@ cat nodejs/src/types.ts | grep -A 10 "export interface ExportSessionOptions"
353353
grep -E "^\s+async def [a-z]" python/copilot/client.py python/copilot/session.py
354354

355355
# Key types
356-
cat python/copilot/types.py | grep -A 20 "class CopilotClientOptions"
357-
cat python/copilot/types.py | grep -A 30 "class SessionConfig"
358-
cat python/copilot/types.py | grep -A 15 "class SessionHooks"
356+
cat python/copilot/client.py | grep -A 20 "class _CopilotClientOptions"
357+
cat python/copilot/client.py | grep -A 80 "async def create_session"
358+
cat python/copilot/session.py | grep -A 15 "class SessionHooks"
359359
```
360360

361361
**Must match (snake_case):**
362362
- `CopilotClient` options: `cli_path`, `cli_url`, `use_stdio`, `port`, `log_level`, `auto_start`, `env`, `github_token`, `use_logged_in_user`
363363
- `create_session()` config keys: `model`, `tools`, `hooks`, `system_message`, `mcp_servers`, `available_tools`, `excluded_tools`, `streaming`, `reasoning_effort`, `provider`, `infinite_sessions`, `custom_agents`, `working_directory`
364364
- `CopilotSession` methods: `send()`, `send_and_wait()`, `get_messages()`, `disconnect()`, `abort()`, `export_session()`
365-
- Hook names: `on_pre_tool_use`, `on_post_tool_use`, `on_user_prompt_submitted`, `on_session_start`, `on_session_end`, `on_error_occurred`
365+
- Hook names: `on_pre_tool_use`, `on_post_tool_use`, `on_post_tool_use_failure`, `on_user_prompt_submitted`, `on_session_start`, `on_session_end`, `on_error_occurred`
366366

367367
#### Go Validation
368368

@@ -377,10 +377,10 @@ cat go/types.go | grep -A 15 "type SessionHooks struct"
377377
```
378378

379379
**Must match (PascalCase for exported):**
380-
- `ClientOptions` fields: `CLIPath`, `CLIUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `Env`, `GithubToken`, `UseLoggedInUser`
380+
- `ClientOptions` fields: `CLIPath`, `CLIUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `Env`, `GitHubToken`, `UseLoggedInUser`
381381
- `SessionConfig` fields: `Model`, `Tools`, `Hooks`, `SystemMessage`, `MCPServers`, `AvailableTools`, `ExcludedTools`, `Streaming`, `ReasoningEffort`, `Provider`, `InfiniteSessions`, `CustomAgents`, `WorkingDirectory`
382382
- `Session` methods: `Send()`, `SendAndWait()`, `GetMessages()`, `Disconnect()`, `Abort()`, `ExportSession()`
383-
- Hook fields: `OnPreToolUse`, `OnPostToolUse`, `OnUserPromptSubmitted`, `OnSessionStart`, `OnSessionEnd`, `OnErrorOccurred`
383+
- Hook fields: `OnPreToolUse`, `OnPostToolUse`, `OnPostToolUseFailure`, `OnUserPromptSubmitted`, `OnSessionStart`, `OnSessionEnd`, `OnErrorOccurred`
384384

385385
#### .NET Validation
386386

@@ -395,10 +395,10 @@ cat dotnet/src/Types.cs | grep -A 15 "public class SessionHooks"
395395
```
396396

397397
**Must match (PascalCase):**
398-
- `CopilotClientOptions` properties: `CliPath`, `CliUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `Environment`, `GithubToken`, `UseLoggedInUser`
398+
- `CopilotClientOptions` properties: `CliPath`, `CliUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `Environment`, `GitHubToken`, `UseLoggedInUser`
399399
- `SessionConfig` properties: `Model`, `Tools`, `Hooks`, `SystemMessage`, `McpServers`, `AvailableTools`, `ExcludedTools`, `Streaming`, `ReasoningEffort`, `Provider`, `InfiniteSessions`, `CustomAgents`, `WorkingDirectory`
400400
- `CopilotSession` methods: `SendAsync()`, `SendAndWaitAsync()`, `GetMessagesAsync()`, `DisposeAsync()`, `AbortAsync()`, `ExportSessionAsync()`
401-
- Hook properties: `OnPreToolUse`, `OnPostToolUse`, `OnUserPromptSubmitted`, `OnSessionStart`, `OnSessionEnd`, `OnErrorOccurred`
401+
- Hook properties: `OnPreToolUse`, `OnPostToolUse`, `OnPostToolUseFailure`, `OnUserPromptSubmitted`, `OnSessionStart`, `OnSessionEnd`, `OnErrorOccurred`
402402

403403
#### Common Sample Errors to Check
404404

.github/aw/actions-lock.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@
1515
"version": "v8",
1616
"sha": "ed597411d8f924073f98dfc5c65a23a2325f34cd"
1717
},
18+
"actions/github-script@v9.0.0": {
19+
"repo": "actions/github-script",
20+
"version": "v9.0.0",
21+
"sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3"
22+
},
1823
"actions/upload-artifact@v7.0.0": {
1924
"repo": "actions/upload-artifact",
2025
"version": "v7.0.0",
2126
"sha": "bbbca2ddaa5d8feaa63e36b76fdaad77386f024f"
2227
},
23-
"github/gh-aw-actions/setup@v0.67.4": {
28+
"github/gh-aw-actions/setup@v0.77.5": {
2429
"repo": "github/gh-aw-actions/setup",
25-
"version": "v0.67.4",
26-
"sha": "9d6ae06250fc0ec536a0e5f35de313b35bad7246"
30+
"version": "v0.77.5",
31+
"sha": "3ea13c02d765410340d533515cb31a7eef2baaf0"
2732
},
2833
"github/gh-aw/actions/setup@v0.52.1": {
2934
"repo": "github/gh-aw/actions/setup",
Lines changed: 18 additions & 0 deletions
Loading
Lines changed: 18 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)