Skip to content

Commit 1bf69fe

Browse files
authored
feat(copilot): add chat skills, instructions and when-gates for language model tools (#1643)
- Gate all 10 language model tools with `when` clauses so they only register when the Java Language Server is ready, and (for active-debug-session-only tools) when an active `java` debug session is in progress. This avoids loading failures and reduces the noise Copilot sees from this extension's tool catalog when the tools cannot actually run. - Contribute a `chatInstructions` file (`javaDebugContext.instructions.md`) with a keyword-rich, on-demand description (no `applyTo`, to avoid burning context on every Java edit) that tells Copilot to activate the deferred Java debug tools via `tool_search_tool_regex` and routes the user request to one of the two skills below. - Contribute two `chatSkills`, split by user-habit telemetry (launch/stop is ~52% of tool usage; inspection/step is ~28%): - `java-launch-troubleshooting` — start/stop a Java program and diagnose launch failures (mainClass missing, classpath, build errors, project not detected). Gated by `javaLSReady` so it is discoverable any time in a Java workspace. - `java-debug-inspection` — inspect variables, walk the stack, list threads, evaluate expressions, step in/over/out, continue, and manage breakpoints in an active Java debug session. Gated by `javaLSReady && inDebugMode && debugType == 'java'` so it only appears once a Java debug session is alive — keeping it reactive, not proactive.
1 parent da84f11 commit 1bf69fe

4 files changed

Lines changed: 150 additions & 0 deletions

File tree

package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,7 @@
10111011
],
10121012
"icon": "$(debug-alt)",
10131013
"canBeReferencedInPrompt": true,
1014+
"when": "javaLSReady",
10141015
"inputSchema": {
10151016
"type": "object",
10161017
"properties": {
@@ -1062,6 +1063,7 @@
10621063
],
10631064
"icon": "$(debug-breakpoint)",
10641065
"canBeReferencedInPrompt": true,
1066+
"when": "javaLSReady",
10651067
"inputSchema": {
10661068
"type": "object",
10671069
"properties": {
@@ -1105,6 +1107,7 @@
11051107
],
11061108
"icon": "$(debug-step-over)",
11071109
"canBeReferencedInPrompt": true,
1110+
"when": "javaLSReady && inDebugMode && debugType == 'java'",
11081111
"inputSchema": {
11091112
"type": "object",
11101113
"properties": {
@@ -1142,6 +1145,7 @@
11421145
],
11431146
"icon": "$(symbol-variable)",
11441147
"canBeReferencedInPrompt": true,
1148+
"when": "javaLSReady && inDebugMode && debugType == 'java'",
11451149
"inputSchema": {
11461150
"type": "object",
11471151
"properties": {
@@ -1183,6 +1187,7 @@
11831187
],
11841188
"icon": "$(call-hierarchy)",
11851189
"canBeReferencedInPrompt": true,
1190+
"when": "javaLSReady && inDebugMode && debugType == 'java'",
11861191
"inputSchema": {
11871192
"type": "object",
11881193
"properties": {
@@ -1212,6 +1217,7 @@
12121217
],
12131218
"icon": "$(symbol-method)",
12141219
"canBeReferencedInPrompt": true,
1220+
"when": "javaLSReady && inDebugMode && debugType == 'java'",
12151221
"inputSchema": {
12161222
"type": "object",
12171223
"properties": {
@@ -1257,6 +1263,7 @@
12571263
],
12581264
"icon": "$(list-tree)",
12591265
"canBeReferencedInPrompt": true,
1266+
"when": "javaLSReady && inDebugMode && debugType == 'java'",
12601267
"inputSchema": {
12611268
"type": "object",
12621269
"properties": {},
@@ -1275,6 +1282,7 @@
12751282
],
12761283
"icon": "$(debug-breakpoint-unverified)",
12771284
"canBeReferencedInPrompt": true,
1285+
"when": "javaLSReady",
12781286
"inputSchema": {
12791287
"type": "object",
12801288
"properties": {
@@ -1303,6 +1311,7 @@
13031311
],
13041312
"icon": "$(debug-stop)",
13051313
"canBeReferencedInPrompt": true,
1314+
"when": "javaLSReady && inDebugMode && debugType == 'java'",
13061315
"inputSchema": {
13071316
"type": "object",
13081317
"properties": {
@@ -1330,12 +1339,29 @@
13301339
],
13311340
"icon": "$(info)",
13321341
"canBeReferencedInPrompt": true,
1342+
"when": "javaLSReady",
13331343
"inputSchema": {
13341344
"type": "object",
13351345
"properties": {},
13361346
"required": []
13371347
}
13381348
}
1349+
],
1350+
"chatSkills": [
1351+
{
1352+
"path": "./resources/skills/java-launch-troubleshooting/SKILL.md",
1353+
"when": "javaLSReady"
1354+
},
1355+
{
1356+
"path": "./resources/skills/java-debug-inspection/SKILL.md",
1357+
"when": "javaLSReady && inDebugMode && debugType == 'java'"
1358+
}
1359+
],
1360+
"chatInstructions": [
1361+
{
1362+
"path": "./resources/instruments/javaDebugContext.instructions.md",
1363+
"when": "javaLSReady"
1364+
}
13391365
]
13401366
},
13411367
"scripts": {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
description: Use when the user wants to run, launch, start, debug, verify, or step through a Java program (main class, Spring Boot, JAR, Maven, Gradle); or when inspecting variables, stack frames, threads, evaluating expressions, or managing breakpoints in a Java debug session.
3+
---
4+
5+
For Java run/launch/debug/inspection requests, prefer the Java debug language model tools over generic shell commands (`mvn exec:java`, `gradle run`, raw `java -cp …`). These tools are contributed by the `Debugger for Java` extension and are deferred — activate them with `tool_search_tool_regex` using pattern `java_breakpoint|debug` before first use, then call them by name.
6+
7+
## Pick the right skill
8+
9+
| User intent | Load skill | Typical tools |
10+
|---|---|---|
11+
| Run / launch / start / stop a Java program, diagnose launch failures (build error, classpath, mainClass missing) | `java-launch-troubleshooting` | `debug_java_application`, `get_debug_session_info`, `stop_debug_session` |
12+
| Inspect a Java program that is already being debugged: read variables, evaluate expressions, walk the stack, step in/over/out, continue, set or remove breakpoints | `java-debug-inspection` | `get_debug_variables`, `get_debug_stack_trace`, `evaluate_debug_expression`, `get_debug_threads`, `debug_step_operation`, `set_java_breakpoint`, `remove_java_breakpoints` |
13+
14+
If both apply (e.g. "launch and break on entry of `Main.foo`"), load `java-launch-troubleshooting` first, then `java-debug-inspection` after the session is active.
15+
16+
Fall back to `run_in_terminal` only when `debug_java_application` returns "Java Language Server not ready" or "project not detected".
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
name: java-debug-inspection
3+
description: Use when inspecting a Java program that is already being debugged — read local variables, walk the call stack, list threads, evaluate expressions, step in/over/out, continue execution, or set / remove breakpoints in an active Java debug session. NOT for starting, launching, or stopping a debug session — use `java-launch-troubleshooting` for that.
4+
---
5+
6+
# Java Debug Inspection
7+
8+
Use this skill when a Java debug session is already active (the user has launched the program with `debug_java_application` or via the VS Code Run/Debug UI) and they want to **observe or steer the running program**. Typical user phrases:
9+
10+
- "what's the value of `user.id` right now?", "show me the local variables"
11+
- "evaluate `list.size()`", "what does `service.findById(42)` return at this frame?"
12+
- "show the stack trace", "what threads are running?", "go up one frame"
13+
- "step in", "step over", "step out", "continue", "resume"
14+
- "set a breakpoint at `OrderService.placeOrder`", "remove the breakpoint on line 42"
15+
16+
If no debug session is active, this skill should not be used — load `java-launch-troubleshooting` first to start one.
17+
18+
## Tools
19+
20+
These language model tools are contributed by the `Debugger for Java` extension and are deferred. Activate them with `tool_search_tool_regex` using pattern `java_breakpoint|debug` before first use.
21+
22+
| Tool | Purpose |
23+
|---|---|
24+
| `get_debug_variables` | Read local variables, fields, and watched expressions in the current frame. |
25+
| `get_debug_stack_trace` | List call-stack frames for the focused (or specified) thread. |
26+
| `get_debug_threads` | List all threads in the session with state (running, stopped, terminated). |
27+
| `evaluate_debug_expression` | Evaluate an arbitrary Java expression in the context of the focused frame. |
28+
| `debug_step_operation` | Step in, step over, step out, or continue. Requires the program to be paused. |
29+
| `set_java_breakpoint` | Set a line / method / exception breakpoint. Works at any time during the session. |
30+
| `remove_java_breakpoints` | Remove one or more breakpoints by ID or location. |
31+
32+
## Preferred Workflow
33+
34+
1. **Confirm session state.** If the user asks to step or evaluate an expression, the program must be paused (typically at a breakpoint). If unsure, call `get_debug_session_info` from `java-launch-troubleshooting` to check, or list threads with `get_debug_threads`.
35+
2. **Inspect first, then act.** For "what's the value of X" — call `get_debug_variables` or `evaluate_debug_expression`. Do not guess from source code.
36+
3. **Step / continue.** For "step over" / "step in" / "step out" / "continue", call `debug_step_operation` with the matching action. After each step, re-read variables or stack as needed.
37+
4. **Breakpoints.** For "set a breakpoint at …", call `set_java_breakpoint` with the file URI + line, or fully qualified method signature, or exception class. For "remove the breakpoint at …", call `remove_java_breakpoints`.
38+
5. **Report precisely.** Quote the exact value or stack frame returned by the tool — do not paraphrase.
39+
40+
## Common Pitfalls
41+
42+
| Symptom | Likely cause | Fix |
43+
|---|---|---|
44+
| `debug_step_operation` returns "thread is not paused" | The program is running, not stopped at a breakpoint | Ask the user to add a breakpoint first, or wait for the next stop event |
45+
| `evaluate_debug_expression` returns `<no active frame>` | No focused stack frame, often because the session just resumed | Re-call `get_debug_stack_trace` to refocus a frame |
46+
| `get_debug_variables` returns empty for a parameter | Compilation without `-g` (no local variable table) | Inform user; offer to inspect via `evaluate_debug_expression` instead |
47+
| Step in jumps into JDK internals | Default step filters disabled | Suggest enabling `java.debug.settings.stepping.skipClasses` |
48+
49+
## When NOT to Use This Skill
50+
51+
- The user wants to *start* a Java program (no session yet) → use `java-launch-troubleshooting`
52+
- The user wants to *stop* the session → use `stop_debug_session` from `java-launch-troubleshooting`
53+
- The program is a non-Java language → do not load this skill
54+
- The user is editing source code without an active debug session → do nothing
55+
56+
## Fallback
57+
58+
If a tool returns "Java Language Server not ready" or repeats the same error twice, report the raw error to the user and stop calling debug tools for the current turn. Do not retry more than twice.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
name: java-launch-troubleshooting
3+
description: Use when the user wants to run, launch, start, restart, or stop a Java program (main class, Spring Boot, JAR, Maven, Gradle), or diagnose launch failures (mainClass missing, classpath unresolved, compile failure, "project not detected", `ClassNotFoundException` at startup). NOT for inspecting variables, stepping, or setting breakpoints in an already-running debug session — use `java-debug-inspection` for that.
4+
---
5+
6+
# Java Launch Troubleshooting
7+
8+
Use this skill when the user wants to **start or stop** a Java program, or when an attempted launch fails. Typical user phrases:
9+
10+
- "run this main class", "start the app", "launch the Spring Boot project", "run the jar"
11+
- "stop the debug session", "kill the running app"
12+
- prior `run_in_terminal` failed with `ClassNotFoundException`, `mainClass is not set`, `Could not find or load main class`, `Could not resolve classpath`
13+
- the user changed `pom.xml` / `build.gradle` and the app no longer starts
14+
15+
## Tools
16+
17+
These language model tools are contributed by the `Debugger for Java` extension and are deferred. Activate them with `tool_search_tool_regex` using pattern `java_breakpoint|debug` before first use.
18+
19+
| Tool | Purpose |
20+
|---|---|
21+
| `debug_java_application` | Build + resolve classpath + start JVM. Returns precise compile and classpath errors. |
22+
| `get_debug_session_info` | Check whether a debug session is already running and its status. |
23+
| `stop_debug_session` | Stop a running Java debug session cleanly. |
24+
25+
## Preferred Workflow
26+
27+
1. **Confirm intent.** Is the user trying to *run / start / launch / stop* a Java program (use this skill) or just edit code (do not load this skill)?
28+
2. **Check existing session.** Call `get_debug_session_info` first. If a session is already running for the target, do not launch a second one.
29+
3. **Launch.** Call `debug_java_application` with `target` = the fully qualified main class or JAR, and `workspacePath` = the project root containing `pom.xml`, `build.gradle`, or `.classpath`. Let `skipBuild` default to `false` so the tool handles compilation.
30+
4. **Read the error.** If `debug_java_application` fails, the error message is structured (mainClass missing, classpath unresolved, build failure with line number). Use it to suggest a fix — do not retry with `run_in_terminal`.
31+
5. **Stop when done.** When the user says "stop", "kill it", or has the answer they need, call `stop_debug_session`.
32+
33+
## Common Failure Modes
34+
35+
| Symptom from `debug_java_application` | Likely cause | Suggested fix |
36+
|---|---|---|
37+
| `mainClass is not configured` / `mainClass missing` | Project has no `launch.json`, and the file has no `public static void main` | Ask user which class to launch, or generate `launch.json` |
38+
| `Could not resolve classpath` | Maven/Gradle import has not completed, or `pom.xml` has unresolved dependencies | Wait for Java Language Server import, then ask user to run `Java: Clean Java Language Server Workspace` |
39+
| `Compilation failed` with file:line | Source code has a compile error | Fix the reported error in the source file, do not retry the launch |
40+
| `Project not detected` | `workspacePath` does not contain a build file | Re-check `workspacePath`; for multi-module projects, use the module root, not the repo root |
41+
42+
## When NOT to Use This Skill
43+
44+
- The user is editing or refactoring Java code without running it → do nothing
45+
- The user is already inside a live debug session and wants to inspect variables, evaluate expressions, walk the stack, step, or set / remove breakpoints → use `java-debug-inspection` instead, do not re-launch
46+
- The program is a non-Java language → do not load this skill
47+
48+
## Fallback
49+
50+
If `debug_java_application` returns `Java Language Server not ready` or repeats the same error twice, fall back to `run_in_terminal` with the appropriate `mvn` or `gradle` command and report the raw output to the user. Do not retry the debug tool more than twice.

0 commit comments

Comments
 (0)