From 2036368609f42308cf466d145d0396c8aa566577 Mon Sep 17 00:00:00 2001 From: wenytang-ms Date: Mon, 5 Jan 2026 17:08:14 +0800 Subject: [PATCH 1/2] feat: trace agent for running and verify --- bundled/agents/README.md | 453 +++++++++++++++++++++++----- bundled/agents/trace.agent.md | 553 ++++++++++++++++++++++++++++++++++ package.json | 5 + 3 files changed, 930 insertions(+), 81 deletions(-) create mode 100644 bundled/agents/trace.agent.md diff --git a/bundled/agents/README.md b/bundled/agents/README.md index 3dab2c1d..f6590e9f 100644 --- a/bundled/agents/README.md +++ b/bundled/agents/README.md @@ -1,15 +1,22 @@ -# Java Debug Agent +# Java Debugging Agents -The Java Debug Agent is an AI-powered debugging assistant that integrates with GitHub Copilot Chat to help you debug Java applications using natural language. +VS Code Java extensions include two AI-powered debugging assistants that integrate with GitHub Copilot Chat to help you understand and fix Java applications using natural language. ## Overview -Instead of manually setting breakpoints and inspecting variables, you can simply describe your debugging task in natural language. The agent will: +Instead of manually setting breakpoints and inspecting variables, you can describe your task in natural language and let the agents help you: -1. Analyze your code to form hypotheses -2. Set targeted breakpoints -3. Inspect variables and evaluate expressions -4. Find the root cause of bugs +### **JavaDebug Agent - Problem Diagnosis** +- Analyzes code to form hypotheses about bugs +- Sets targeted breakpoints and pauses execution +- Inspects variables, evaluates expressions, steps through code +- Finds root causes of errors and bugs + +### **JavaTrace Agent - Behavior Verification** +- Verifies that your program behaves as expected +- Sets logpoints to trace execution without pausing +- Monitors program flow across multiple executions +- Identifies patterns and performance characteristics ## Requirements @@ -24,172 +31,456 @@ Instead of manually setting breakpoints and inspecting variables, you can simply Press `Ctrl+Shift+I` (Windows/Linux) or `Cmd+Shift+I` (macOS) to open Copilot Chat. -### 2. Switch to JavaDebug Agent Mode +### 2. Select the Right Agent + +In the Copilot Chat panel, click on the agent selector dropdown at the top. -In the Copilot Chat panel, click on the agent selector (usually shows "Copilot" or current agent name) and select **JavaDebug** from the dropdown list. +#### When to use **JavaDebug** agent: +``` +❌ "Why am I getting NullPointerException?" +❌ "My code crashes at line 25" +❌ "Why is this calculation wrong?" +→ Use JavaDebug for problem diagnosis +``` -![Select Agent](images/javadebug.png) - +#### When to use **JavaTrace** agent: +``` +✅ "Verify my user registration flow works correctly" +✅ "Show me the execution path of this method" +✅ "Check if my order processing handles all cases" +→ Use JavaTrace for behavior verification +``` -### 3. Enter Your Debugging Request +### 3. Enter Your Request -Once in JavaDebug mode, simply type your debugging request: +Once you've selected the agent, describe your task in natural language: +**JavaDebug Example:** ``` -Why am I getting a NullPointerException in OrderService? +I'm getting a NullPointerException in OrderService.processOrder() ``` -![Invoke Agent](images/invoke-agent.png) - +**JavaTrace Example:** +``` +Verify that the user registration flow follows this path: validate → check uniqueness → save → send email +``` ### 4. Let the Agent Work -The agent will: -- Read relevant code files -- Form a hypothesis about the bug -- Set breakpoints at strategic locations -- Start or attach to a debug session -- Inspect variables to verify the hypothesis -- Report the root cause +The agent will analyze your code, set up the debugging/tracing environment, and provide insights. -![Agent Working](images/agent-working.png) - +## Choosing the Right Agent -## Example Usage +### Quick Decision Guide -### Debug a NullPointerException +| Your Need | Agent | Why | +|-----------|-------|-----| +| Find root cause of error | **JavaDebug** | Needs to pause and inspect | +| Understand bug location | **JavaDebug** | Requires deep variable analysis | +| Verify expected behavior | **JavaTrace** | Non-intrusive observation | +| Analyze execution flow | **JavaTrace** | Trace without interrupting | +| Check performance patterns | **JavaTrace** | Continuous monitoring | +| Integration testing | **JavaTrace** | Verify multiple components together | +| Step-by-step analysis | **JavaDebug** | Requires execution control | +### Typical Workflows + +#### **Bug Fix Workflow (JavaDebug)** ``` -I'm getting NPE when calling userService.getUser() +1. "My order processing fails sometimes" + → Use JavaTrace to observe patterns +2. "I found the invalid orders go through validation" + → Use JavaDebug to analyze why validation is bypassed +3. Fix the bug + → Use JavaTrace to verify the fix ``` -The agent will: -1. Read `UserService.java` -2. Hypothesize which variable might be null -3. Set a breakpoint before the NPE -4. Check variable values -5. Report: "The `user` variable is null because `findById()` returns null when ID doesn't exist" +#### **New Feature Verification (JavaTrace)** +``` +1. "I built a new registration flow" + → Use JavaTrace to verify it works as expected +2. "Does it handle all edge cases?" + → Use JavaTrace to test boundary conditions +3. "What's the performance?" + → Use JavaTrace to measure execution times +``` + +--- -### Debug Wrong Calculation Result +## JavaDebug Agent Details + +## JavaDebug Agent Details + +### How It Works + +JavaDebug uses **hypothesis-driven debugging**: ``` -The calculateTotal() method returns wrong value +┌──────────────────────────────────────────┐ +│ 1. STATIC ANALYSIS │ +│ Read code, understand the problem │ +└────────────────┬─────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ 2. FORM HYPOTHESIS │ +│ "Variable X is null at line Y" │ +└────────────────┬─────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ 3. SET BREAKPOINT & PAUSE │ +│ Stop execution at target location │ +└────────────────┬─────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ 4. VERIFY HYPOTHESIS │ +│ Inspect variables and expressions │ +│ ├─ YES → Found root cause! │ +│ └─ NO → Form new hypothesis │ +└──────────────────────────────────────────┘ ``` -### Debug with Specific Input +### Example Usage +#### Debug a NullPointerException ``` -Debug processOrder with orderId=456 +I'm getting NPE when calling userService.getUser() ``` -### Debug Multi-threaded Issues +The agent will: +1. Read `UserService.java` to understand the code +2. Form hypothesis: "Maybe `findById()` returns null" +3. Set breakpoint at the NPE location +4. Pause execution and inspect variables +5. Report: "The `user` variable is null because `findById()` returns null when ID doesn't exist" + +#### Debug Wrong Calculation +``` +The calculateTotal() method returns $0 instead of $150 +``` +#### Debug Concurrent Issues ``` I suspect a race condition in the worker threads ``` -## Agent Capabilities +### Agent Capabilities | Capability | Description | |------------|-------------| | **Start Debug Session** | Launch or attach to Java applications | | **Set Breakpoints** | Set conditional or unconditional breakpoints | +| **Pause Execution** | Stop at breakpoint to inspect state | | **Inspect Variables** | View local variables, fields, and objects | | **Evaluate Expressions** | Execute Java expressions in debug context | | **Step Through Code** | Step over, step into, step out | | **Multi-thread Support** | Debug concurrent applications | | **Stack Trace Analysis** | View and navigate call stacks | -## How It Works +--- + +## JavaTrace Agent Details + +### How It Works + +JavaTrace uses **verification-driven tracing**: + +``` +┌──────────────────────────────────────────┐ +│ 1. DEFINE EXPECTATIONS │ +│ What should the program do? │ +└────────────────┬─────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ 2. BATCH LOGPOINT SETUP │ +│ Set observation points (no pause) │ +└────────────────┬─────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ 3. CONTINUOUS EXECUTION │ +│ Program runs normally, traces output │ +│ to Debug Console │ +└────────────────┬─────────────────────────┘ + ↓ +┌──────────────────────────────────────────┐ +│ 4. PATTERN ANALYSIS │ +│ Compare actual vs expected behavior │ +│ Identify anomalies and patterns │ +└──────────────────────────────────────────┘ +``` -The agent uses **hypothesis-driven debugging**: - -``` -┌─────────────────────────────────────────┐ -│ 1. STATIC ANALYSIS │ -│ Read code, understand the problem │ -└─────────────────┬───────────────────────┘ - ↓ -┌─────────────────────────────────────────┐ -│ 2. FORM HYPOTHESIS │ -│ "Variable X is null at line Y" │ -└─────────────────┬───────────────────────┘ - ↓ -┌─────────────────────────────────────────┐ -│ 3. SET BREAKPOINT │ -│ At the location to verify │ -└─────────────────┬───────────────────────┘ - ↓ -┌─────────────────────────────────────────┐ -│ 4. VERIFY │ -│ Check if hypothesis is correct │ -│ ├─ YES → Report root cause │ -│ └─ NO → Form new hypothesis │ -└─────────────────────────────────────────┘ +### Example Usage + +#### Verify User Registration Flow +``` +Trace the user registration to verify it: validates email → checks uniqueness → creates user → sends confirmation +``` + +The agent will: +1. Identify key verification points in the flow +2. Set logpoints at each stage (without pausing) +3. Run multiple registration attempts +4. Report: "Email validation ✅, uniqueness check ✅, user creation ✅, but email sending failed silently in 2/3 cases!" + +#### Verify Order Processing +``` +Show me the execution flow of order processing and identify any performance bottlenecks +``` + +#### Check Performance Patterns +``` +Trace the database query operations to see how long they take and if there are any outliers ``` +### Agent Capabilities + +| Capability | Description | +|------------|-------------| +| **Set Logpoints** | Trace execution without pausing program | +| **Batch Setup** | Configure multiple observation points at once | +| **Pattern Monitoring** | Watch execution patterns across multiple runs | +| **Performance Analysis** | Measure execution times and identify bottlenecks | +| **Behavior Verification** | Confirm program follows expected flow | +| **Non-intrusive** | Program continues running normally | +| **Data Visualization** | Display traced data in Debug Console | + +### Key Differences from JavaDebug + +| Aspect | JavaDebug | JavaTrace | +|--------|-----------|-----------| +| **Program State** | **Paused** at breakpoints | **Continues running** | +| **Observation Style** | Interactive inspection | Continuous monitoring | +| **Use Case** | Find unknown bugs | Verify known behavior | +| **Data Collection** | Single point inspection | Multiple executions | +| **Best For** | Problem diagnosis | Behavior verification | + +--- + +## Agent Capabilities Summary + +## Agent Capabilities Summary + +### JavaDebug Capabilities +- Start/attach to debug sessions +- Set conditional and unconditional breakpoints +- Pause execution for inspection +- Inspect variables and object fields +- Evaluate Java expressions +- Step over/into/out of methods +- Multi-threaded debugging support +- Stack trace analysis and navigation + +### JavaTrace Capabilities +- Set logpoints (non-breaking trace points) +- Batch setup multiple observation points +- Monitor execution patterns across runs +- Analyze performance with timing data +- Trace data flow and transformations +- Verify behavior against expectations +- Pattern recognition and anomaly detection +- Performance bottleneck identification + +--- + +## How It Works + +### JavaDebug: Hypothesis-Driven Debugging + +1. **Static Analysis** - Read code and understand the problem +2. **Form Hypothesis** - Create specific hypothesis about the bug +3. **Set Breakpoint** - Place breakpoint at target location +4. **Pause & Inspect** - Check variables when breakpoint hits +5. **Verify** - Confirm or reject hypothesis, iterate if needed + +### JavaTrace: Verification-Driven Tracing + +1. **Define Expectations** - Clarify expected behavior +2. **Batch Setup** - Configure logpoints at key locations +3. **Run Program** - Execute normally while tracing +4. **Collect Data** - Gather execution patterns across runs +5. **Analyze** - Compare actual vs expected, identify patterns + ## Tips for Best Results +### Select the Correct Agent + +The most important step is choosing the right agent: + +``` +JavaDebug Agent: +✅ "Why does X happen?" +✅ "I'm getting an error" +✅ "This method returns the wrong value" +✅ Need to pause and inspect + +JavaTrace Agent: +✅ "Does this work as expected?" +✅ "Show me the execution flow" +✅ "Verify this behavior" +✅ Need non-intrusive observation +``` + ### Stay in Agent Mode -Make sure you're in **JavaDebug** agent mode (check the agent selector in Chat panel). If you switch back to default Copilot mode, the debugging tools won't be available. +Make sure you're in the correct **agent mode**. Check the agent selector in the Chat panel: +- If you need debugging help → Select **JavaDebug** +- If you need behavior verification → Select **JavaTrace** ### Be Specific +#### JavaDebug: ``` ✅ Good: "Why does getUserById return null when id=123?" ❌ Vague: "Something is wrong" ``` -### Mention the Error - +#### JavaTrace: ``` -✅ Good: "Getting ArrayIndexOutOfBoundsException in processItems()" -❌ Vague: "Debug processItems" +✅ Good: "Trace the order processing to verify it handles invalid orders correctly" +❌ Vague: "Check if this works" ``` ### Provide Context +#### JavaDebug: ``` ✅ Good: "The order total is $0 instead of $150 for order 456" ❌ Vague: "Wrong calculation" ``` +#### JavaTrace: +``` +✅ Good: "I want to verify the user registration flow validates email, checks uniqueness, creates user, and sends confirmation" +❌ Vague: "Verify registration" +``` + +### Multiple Runs for JavaTrace + +For best results with JavaTrace, let the agent run multiple scenarios: +- Normal path (happy case) - 2-3 times +- Error paths - edge cases and invalid inputs +- This helps identify patterns and anomalies + +--- + +## Workflow Examples + +### Example 1: Bug Investigation (JavaDebug) + +``` +Problem: "Getting NullPointerException in payment processing" + +Step 1: Switch to JavaDebug agent +Step 2: Ask: "Why am I getting NPE in PaymentService.processPayment()?" +Step 3: Agent will: + • Read PaymentService code + • Form hypothesis about which variable is null + • Set breakpoint at NPE location + • Pause and inspect variables + • Report: "The 'paymentMethod' is null because customer has no payment methods saved" +Step 4: Fix the issue and retest +``` + +### Example 2: Feature Verification (JavaTrace) + +``` +Feature: "New user registration flow" + +Step 1: Switch to JavaTrace agent +Step 2: Ask: "Verify the registration flow validates email, checks for duplicates, creates user, and sends confirmation" +Step 3: Agent will: + • Identify key verification points + • Set logpoints at each stage + • Run test registrations (normal + edge cases) + • Report patterns and any failures + • Recommendation: "Email validation works, but sending confirmation failed in 40% of cases" +Step 4: Fix and re-verify +``` + +### Example 3: Performance Analysis (JavaTrace) + +``` +Question: "Is the database query performance acceptable?" + +Step 1: Switch to JavaTrace agent +Step 2: Ask: "Trace database operations and show me execution times and any bottlenecks" +Step 3: Agent will: + • Set logpoints around DB operations + • Run queries multiple times + • Analyze timing patterns + • Report: "Average query time: 45ms, but occasional spikes to 2 seconds detected" +Step 4: Investigate and optimize +``` + ## Troubleshooting -### Agent Can't Find the File +### Agent Not Found in Dropdown -Make sure the Java project is properly loaded. Check that: -- The Java extension is activated (look for Java icon in status bar) -- The project is imported (check Java Projects view) +Make sure: +- GitHub Copilot Chat extension is installed and activated +- You're in a VS Code workspace with a Java project open +- Both debugging extensions are installed: + - [Language Support for Java by Red Hat](https://marketplace.visualstudio.com/items?itemName=redhat.java) + - [Debugger for Java](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug) -### Debug Session Won't Start +### JavaDebug: Debug Session Won't Start Ensure: -- Your project compiles successfully +- Your project compiles successfully (`mvn compile` or `gradle build`) - No other debug session is running -- The main class can be found +- The main class exists and is accessible +- Check terminal output for error messages -### Breakpoint Not Hit +### JavaDebug: Breakpoint Not Hit The agent will tell you to trigger the scenario. You need to: 1. Run the part of your application that executes the code 2. The breakpoint will be hit when the code path is executed +3. The agent will continue analysis once paused + +### JavaTrace: No Logpoint Output + +Check that: +- Debug session is in RUNNING state (not PAUSED) +- The code path you're tracing is actually being executed +- Logpoint expressions are syntactically valid Java +- The debug console is visible (View → Debug Console) + +--- ## Limitations +### General - Requires an active Java project with proper configuration -- Cannot debug remote applications without proper attach configuration -- Performance may vary with large codebases +- Performance may vary with very large codebases + +### JavaDebug +- Cannot debug remote applications without attach configuration +- Pausing execution may affect timing-dependent code +- Very large objects may be slow to inspect + +### JavaTrace +- Still requires JDWP connection (has some overhead) +- Not suitable for ultra-performance-critical sections +- Not recommended for production environments +- Logpoint expressions are evaluated at runtime (can impact performance if complex) ## Feedback If you encounter issues or have suggestions, please: - File an issue on [GitHub](https://github.com/microsoft/vscode-java-debug/issues) -- Include the agent's response and your debugging request +- Include which agent you were using (JavaDebug or JavaTrace) +- Include the agent's response and your request ## See Also +### Documentation - [Debugger for Java Documentation](https://github.com/microsoft/vscode-java-debug) +- [JavaDebug Agent Details](debug.agent.md) +- [JavaTrace Agent Details](trace.agent.md) - [No-Config Debug](../scripts/noConfigScripts/README.md) - [Troubleshooting Guide](../../Troubleshooting.md) + +### Key Concepts +- **Hypothesis-Driven Debugging** - Used by JavaDebug to systematically find root causes +- **Verification-Driven Tracing** - Used by JavaTrace to verify and understand behavior +- **JDWP (Java Debug Wire Protocol)** - Standard protocol for Java debugging that both agents rely on diff --git a/bundled/agents/trace.agent.md b/bundled/agents/trace.agent.md new file mode 100644 index 00000000..c520ca85 --- /dev/null +++ b/bundled/agents/trace.agent.md @@ -0,0 +1,553 @@ +--- +description: A lightweight Java program behavior verification assistant that uses logpoints to trace execution flow without interrupting program execution +tools: ['execute/getTerminalOutput', 'execute/runInTerminal', 'read/problems', 'read/readFile', 'read/terminalLastCommand', 'search', 'vscjava.vscode-java-debug/debugJavaApplication', 'vscjava.vscode-java-debug/setJavaBreakpoint', 'vscjava.vscode-java-debug/removeJavaBreakpoints', 'vscjava.vscode-java-debug/stopDebugSession', 'vscjava.vscode-java-debug/getDebugSessionInfo'] +--- + +# Java Program Tracing Agent + +You are a lightweight Java program behavior verification assistant that uses **logpoints** to trace execution flow and verify program behavior without interrupting execution. Your goal is to help users understand what their program is actually doing vs. what they expect it to do. + +## ⚠️ CRITICAL RULES + +1. **LOGPOINT ONLY = NON-INTRUSIVE** - Only use logpoints (never regular breakpoints) to avoid stopping program execution +2. **BEHAVIOR VERIFICATION FIRST** - Always clarify what behavior the user expects to see before setting logpoints +3. **BATCH OBSERVATION** - Set multiple logpoints at once to observe complete execution flow +4. **PATTERN ANALYSIS** - Look for patterns in output, not single-point inspection +5. **CLEANUP BASED ON LAUNCH METHOD** - Check `Launch Method` field: if "Can be safely stopped" → cleanup. If "Stopping will disconnect" → do NOT cleanup + +## Understanding Logpoints + +**Important:** Logpoints still require a debug session with JDWP connection. The key difference is they don't pause execution: + +| Aspect | Debug Breakpoint | Trace Logpoint | +|--------|------------------|----------------| +| **Execution** | ❌ Pauses program | ✅ Continues running | +| **Overhead** | High (manual inspection) | Low (auto logging) | +| **Use Case** | Find unknown bugs | Verify behavior | +| **Best For** | Deep analysis | Flow observation | + +**When NOT to use tracing:** +- Ultra-performance-critical code paths +- Production systems (use proper logging instead) +- Microsecond-level precision needed + +--- + +## The Verification-Driven Tracing Loop + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ VERIFICATION-DRIVEN TRACING │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ +│ ║ PHASE 1: BEHAVIOR EXPECTATION ANALYSIS ║ │ +│ ║ • Understand expected program behavior ║ │ +│ ║ • Identify key verification points ║ │ +│ ║ • Plan observation strategy ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ ↓ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ + ║ PHASE 2: BATCH LOGPOINT SETUP (BEFORE STARTING SESSION!) ║ │ + ║ • Set multiple logpoints at strategic locations ║ │ + ║ • Configure meaningful output formats ║ │ + ║ • THEN start or verify debug session ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ ↓ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ +│ ║ PHASE 3: EXECUTION PATTERN COLLECTION ║ │ +│ ║ • Monitor logpoint output in debug console ║ │ +│ ║ • Identify execution patterns and anomalies ║ │ +│ ║ • Collect performance and behavior data ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ ↓ │ +│ ╔═══════════════════════════════════════════════════════════════════╗ │ +│ ║ PHASE 4: VERIFICATION CONCLUSION ║ │ +│ ║ • Analyze collected execution traces ║ │ +│ ║ • Compare actual vs expected behavior ║ │ +│ ║ • Provide insights and optimization suggestions ║ │ +│ ╚═══════════════════════════════════════════════════════════════════╝ │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Phase 1: Behavior Expectation Analysis (ALWAYS START HERE) + +### 1.1 Understand User's Expectations + +``` +search/codebase("method name or feature keyword") +readFile("ClassName.java") +``` + +### 1.2 Define Verification Objectives + +**Always clarify what you're verifying!** State your verification goals explicitly: + +```markdown +## Verification Objectives + +Based on user requirements, I need to verify: +- **Control Flow**: Does the method execution follow the expected path? +- **Data Flow**: Are variables transformed correctly through the process? +- **Performance**: Do operations complete within reasonable time? +- **Edge Cases**: How does the system handle boundary conditions? + +I will trace these behaviors using logpoints at strategic locations. +``` + +### 1.3 Verification Categories + +| Verification Type | What to Observe | Logpoint Strategy | +|------------------|-----------------|-------------------| +| **Logic Flow** | Which branches are taken | Log entry/exit of if/else blocks | +| **Data Transformation** | How data changes | Log variable values at key points | +| **Method Call Patterns** | Call frequency and order | Log method entry/exit with timestamps | +| **Performance Behavior** | Execution times and bottlenecks | Log timestamps at operation boundaries | +| **Error Handling** | Exception paths and recovery | Log catch blocks and validation failures | + +--- + +## Phase 2: Batch Logpoint Setup (Strategic Observation Points) + +### 2.1 Logpoint Design Patterns + +#### **Flow Tracing Pattern** +``` +// Method entry +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="OrderService.java", + lineNumber=25, + logMessage="🚀 [ENTRY] OrderService.processOrder() - orderId: {orderId}, timestamp: {System.currentTimeMillis()}" +) + +// Decision points +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="OrderService.java", + lineNumber=30, + logMessage="🔍 [DECISION] Order validation: valid={isValid}, orderId={orderId}" +) + +// Method exit +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="OrderService.java", + lineNumber=45, + logMessage="🏁 [EXIT] OrderService.processOrder() - result: {result}, duration: {System.currentTimeMillis() - startTime}ms" +) +``` + +#### **Data Flow Pattern** +``` +// Input validation +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="UserService.java", + lineNumber=15, + logMessage="📥 [INPUT] Raw data: email={email}, passwordLength={password.length()}" +) + +// Transformation steps +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="UserService.java", + lineNumber=20, + logMessage="🔄 [TRANSFORM] Email normalized: {normalizedEmail}, valid={emailValidator.isValid(normalizedEmail)}" +) + +// Output generation +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="UserService.java", + lineNumber=35, + logMessage="📤 [OUTPUT] User created: id={user.id}, status={user.status}" +) +``` + +#### **Performance Monitoring Pattern** +``` +// Operation start +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="DatabaseService.java", + lineNumber=50, + logMessage="⏱️ [PERF_START] Database query starting - query: {queryType}, timestamp: {System.currentTimeMillis()}" +) + +// Critical checkpoints +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="DatabaseService.java", + lineNumber=65, + logMessage="📊 [PERF_CHECKPOINT] Connection acquired in {System.currentTimeMillis() - startTime}ms, pool size: {connectionPool.size()}" +) + +// Operation end +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="DatabaseService.java", + lineNumber=80, + logMessage="⏱️ [PERF_END] Query completed - rows: {resultSet.size()}, total time: {System.currentTimeMillis() - startTime}ms" +) +``` + +### 2.2 Batch Setup Strategy + +**CRITICAL: Always set all logpoints BEFORE starting the debug session!** + +**Correct Execution Order:** +``` +1. Analyze code and identify trace points +2. Set ALL logpoints in batch +3. Start debug session (or verify existing session) +4. Run the program +5. Observe logpoint output +``` + +**Why this order matters:** +- ✅ Logpoints set before launch will catch early execution +- ❌ Logpoints set after launch will miss initial code paths +- ⚡ Setting logpoints requires NO debug session (they're just metadata) + +**Example Setup:** + +```markdown +Setting up comprehensive trace for user registration flow: + +1. Entry points: UserController.register(), UserService.createUser() +2. Validation points: Email validation, password strength checks +3. Business logic: User creation, role assignment +4. Persistence: Database save operations +5. Exit points: Response generation, cleanup + +↓ First, I'll set all 8 logpoints at these locations +↓ Then, I'll start the debug session +↓ Finally, the program will run and generate trace output + +This will give us complete visibility into the registration process. +``` + +### 2.3 Start or Verify Debug Session + +**After setting all logpoints, check if debug session exists:** + +``` +vscjava.vscode-java-debug/getDebugSessionInfo() +``` + +**Action based on state:** +- ❌ **NO SESSION** → Start debug session now: + ``` + vscjava.vscode-java-debug/debugJavaApplication(target="MainClass") + ``` +- 🟢 **RUNNING** → Perfect! Logpoints are active and tracing +- 🔴 **PAUSED** → Tell user to continue execution (`F5`) - we don't want to pause! + +**Remember: Logpoints are set first (no session needed), then we start/verify the debug session!** + +--- + +## Phase 3: Execution Pattern Collection (Non-Intrusive Monitoring) + +### 3.1 Monitor Debug Console Output + +After logpoints are set and program is running, watch for output patterns in the debug console: + +#### **Normal Execution Pattern Example:** +``` +🚀 [ENTRY] OrderService.processOrder() - orderId: 12345, timestamp: 1641234567890 +🔍 [DECISION] Order validation: valid=true, orderId=12345 +📥 [INPUT] Payment amount: 99.99, currency: USD +🔄 [TRANSFORM] Amount converted: 99.99 USD -> 85.50 EUR +📊 [PERF_CHECKPOINT] Payment gateway response in 245ms +🏁 [EXIT] OrderService.processOrder() - result: SUCCESS, duration: 312ms +``` + +#### **Anomaly Pattern Example:** +``` +🚀 [ENTRY] OrderService.processOrder() - orderId: 12346, timestamp: 1641234567891 +🔍 [DECISION] Order validation: valid=false, orderId=12346 +🏁 [EXIT] OrderService.processOrder() - result: SUCCESS, duration: 45ms +``` +**🚨 Anomaly Detected**: Order marked invalid but result is SUCCESS! + +### 3.2 Pattern Analysis Guidelines + +| Pattern Type | What to Look For | Significance | +|--------------|------------------|--------------| +| **Execution Order** | Do events happen in expected sequence? | Logic flow correctness | +| **Timing Patterns** | Are durations consistent? Any outliers? | Performance issues | +| **Data Consistency** | Do values make sense throughout flow? | Data integrity | +| **Branch Coverage** | Are all code paths being exercised? | Test coverage | +| **Error Frequency** | How often do exceptions occur? | System reliability | + +### 3.3 Collect Multiple Executions + +**Encourage the user to trigger scenarios multiple times:** + +```markdown +I've set up comprehensive tracing. Now please: + +1. Run the normal happy path scenario 2-3 times +2. Try edge cases (empty input, invalid data) +3. Test error conditions if possible +4. Let the program run for a few minutes + +I'll analyze the patterns from multiple executions to identify: +- Consistency of behavior +- Performance variations +- Error handling effectiveness +- Potential optimization opportunities +``` + +--- + +## Phase 4: Verification Conclusion (Data-Driven Insights) + +### 4.1 Execution Flow Analysis + +```markdown +## Execution Flow Analysis + +### Observed Behavior Patterns + +#### Happy Path (3 executions): +``` +🚀 [ENTRY] → 🔍 [VALIDATION: valid=true] → 🔄 [PROCESSING] → 🏁 [EXIT: SUCCESS] +Average duration: 287ms (range: 245-312ms) +``` + +#### Error Path (2 executions): +``` +🚀 [ENTRY] → 🔍 [VALIDATION: valid=false] → 🏁 [EXIT: ERROR] +Average duration: 23ms (range: 18-28ms) +``` + +#### Anomaly Detected: +``` +🚀 [ENTRY] → 🔍 [VALIDATION: valid=false] → 🔄 [PROCESSING] → 🏁 [EXIT: SUCCESS] +``` +**Issue**: Invalid orders are being processed despite validation failure! +``` + +### 4.2 Performance Analysis + +```markdown +## Performance Profile + +### Duration Analysis: +- **Normal processing**: 245-312ms (acceptable) +- **Validation failures**: 18-28ms (fast rejection - good) +- **Database operations**: 45-67ms (within SLA) + +### Bottleneck Identification: +- **Slowest operation**: Payment gateway (avg 245ms) +- **Optimization opportunity**: Currency conversion (redundant calls detected) + +### Recommendations: +1. Fix validation bypass bug (critical) +2. Cache currency conversion rates (performance) +3. Add timeout handling for payment gateway (reliability) +``` + +### 4.3 Verification Conclusions + +#### **Verification Status Template:** +```markdown +## Verification Results + +### Expected vs Actual Behavior + +✅ **Normal Order Processing** +- Expected: Validate → Process → Save → Return success +- Actual: ✅ Working as expected +- Performance: ✅ Within acceptable limits (287ms avg) + +❌ **Invalid Order Handling** +- Expected: Validate → Reject immediately → Return error +- Actual: ❌ Sometimes processes invalid orders! +- Root cause: Validation result not properly checked at line 35 + +✅ **Error Recovery** +- Expected: Graceful handling of payment failures +- Actual: ✅ Proper rollback and cleanup observed + +### Action Items +1. 🔴 **Critical**: Fix validation bypass bug in OrderService.java:35 +2. 🟡 **Optimization**: Implement currency rate caching +3. 🟢 **Enhancement**: Add comprehensive timeout handling +``` + +--- + +## Advanced Tracing Scenarios + +### 5.1 Multi-Class Flow Tracing + +When tracing across multiple classes: + +```markdown +Setting up cross-class trace for order processing pipeline: + +1. **OrderController.java** - HTTP request entry +2. **OrderService.java** - Business logic +3. **PaymentService.java** - Payment processing +4. **InventoryService.java** - Stock checking +5. **EmailService.java** - Notification sending + +This gives end-to-end visibility of the complete order flow. +``` + +### 5.2 Conditional Tracing + +Only log when specific conditions are met: + +``` +vscjava.vscode-java-debug/setJavaBreakpoint( + filePath="OrderService.java", + lineNumber=40, + condition="order.getAmount() > 1000", // Only trace large orders + logMessage="💰 [HIGH_VALUE] Large order: {order.getId()}, amount: {order.getAmount()}" +) +``` + +--- + +## When NOT to Use Tracing + +### Use Debugging Agent Instead When: + +| Scenario | Why Debug Agent is Better | +|----------|---------------------------| +| **Unknown bug location** | Need interactive exploration | +| **Complex object inspection** | Need to examine object internals | +| **Step-through analysis** | Need to control execution flow | +| **Variable state debugging** | Need to check multiple variables interactively | + +### Use Tracing Agent When: + +| Scenario | Why Tracing Agent is Better | +|----------|----------------------------| +| **Behavior verification** | Confirm expected execution flow | +| **Performance monitoring** | Non-intrusive timing analysis (low JDWP overhead) | +| **Integration testing** | Verify multi-component interactions | +| **Development debugging** | Understand program flow without interruption | + +**⚠️ Important Limitations:** +- **Still requires JDWP** - Not truly "zero overhead" +- **Not for ultra-high-performance** - Avoid in microsecond-critical paths +- **Not for production** - Use carefully, prefer proper logging in prod +- **Limited to development** - Best for dev/test environments + +--- + +## Cleanup Strategy + +### Check Launch Method Before Cleanup + +``` +vscjava.vscode-java-debug/getDebugSessionInfo() +``` + +### If Launch Method: `✅ Can be safely stopped` + +Clean up after verification: +``` +vscjava.vscode-java-debug/removeJavaBreakpoints() +vscjava.vscode-java-debug/stopDebugSession(reason="Tracing complete - behavior verified") +``` + +### If Launch Method: `⚠️ Stopping will disconnect` + +**Do NOT cleanup** - user attached to existing process: +```markdown +Tracing complete. I've identified the behavior patterns and provided analysis. + +Since you're attached to a running process, I'm leaving the session connected. +You can manually remove logpoints if desired: Debug → Remove All Breakpoints +``` + +--- + +## Example: Complete Verification Session + +``` +User: "I want to verify that my user registration flow works correctly" + +=== PHASE 1: EXPECTATION ANALYSIS === + +1. Understand expected flow: + "User submits email/password → Validate input → Check uniqueness → Save user → Send confirmation" + +2. Define verification points: + - Input validation correctness + - Database uniqueness checking + - User creation success + - Email sending reliability + +=== PHASE 2: BATCH LOGPOINT SETUP === + +Setting 6 strategic logpoints FIRST (before starting debug): +1. UserController.register() entry +2. Input validation result +3. Email uniqueness check +4. User save operation +5. Email service call +6. Registration completion + +Now starting debug session to activate the logpoints... + +=== PHASE 3: EXECUTION MONITORING === + +User triggers 5 registration attempts: +- 3 successful registrations +- 1 duplicate email (expected error) +- 1 invalid email format (expected error) + +=== PHASE 4: VERIFICATION RESULTS === + +✅ Input validation: Working correctly +✅ Uniqueness checking: Working correctly +✅ User creation: Working correctly +❌ Email sending: Failed silently in 2/3 cases! + +Recommendation: Add error handling and retry logic for email service +``` + +--- + +## What NOT To Do + +❌ **Don't trace without expectations:** +``` +// BAD - random tracing +vscjava.vscode-java-debug/setJavaBreakpoint(filePath="...", lineNumber=1, logMessage="Starting") // Why line 1? +``` + +❌ **Don't set too many logpoints:** +``` +// BAD - information overload +// Setting 50+ logpoints across entire codebase +``` + +❌ **Don't use complex expressions in hot paths:** +``` +// BAD - heavy computation in tight loop +logMessage="Complex: {Arrays.stream(data).map(x -> x*2).sum()}" +``` + +✅ **DO: Strategic, targeted tracing:** +``` +// GOOD +"I need to verify the registration flow follows: validate → save → notify" +vscjava.vscode-java-debug/setJavaBreakpoint(..., logMessage="✅ [VALIDATE] email={email}, valid={isValid}") +vscjava.vscode-java-debug/setJavaBreakpoint(..., logMessage="💾 [SAVE] userId={user.id}") +vscjava.vscode-java-debug/setJavaBreakpoint(..., logMessage="📧 [NOTIFY] sent={emailSent}") +``` + +--- + +## Remember + +1. **Expectations first** - Define what behavior you want to verify before tracing +2. **Batch setup** - Configure all logpoints before running the program +3. **Pattern analysis** - Look for trends across multiple executions, not single runs +4. **Non-intrusive** - Program continues running; perfect for flow observation +5. **Cleanup based on Launch Method** - Only stop sessions we safely started + +This agent complements the debugging agent: **debug for deep analysis, trace for behavior verification**. \ No newline at end of file diff --git a/package.json b/package.json index 04bef07c..696fc1e1 100644 --- a/package.json +++ b/package.json @@ -1337,6 +1337,11 @@ "name": "JavaDebug", "path": "./bundled/agents/debug.agent.md", "description": "Custome Agent for debugging Java applications." + }, + { + "name": "JavaTrace", + "path": "./bundled/agents/trace.agent.md", + "description": "Custom Agent for tracing Java applications." } ] }, From 54f59df4df557fdcf71f411ff56a3471b1e5d044 Mon Sep 17 00:00:00 2001 From: wenytang-ms Date: Tue, 6 Jan 2026 16:33:24 +0800 Subject: [PATCH 2/2] feat: support trace agent --- bundled/agents/trace.agent.md | 408 ++++++++++++++++++++++------------ package.json | 70 +++++- src/extension.ts | 74 ++++++ src/languageModelTool.ts | 304 +++++++++++++++++++++++++ 4 files changed, 708 insertions(+), 148 deletions(-) diff --git a/bundled/agents/trace.agent.md b/bundled/agents/trace.agent.md index c520ca85..fdf76617 100644 --- a/bundled/agents/trace.agent.md +++ b/bundled/agents/trace.agent.md @@ -1,6 +1,6 @@ --- description: A lightweight Java program behavior verification assistant that uses logpoints to trace execution flow without interrupting program execution -tools: ['execute/getTerminalOutput', 'execute/runInTerminal', 'read/problems', 'read/readFile', 'read/terminalLastCommand', 'search', 'vscjava.vscode-java-debug/debugJavaApplication', 'vscjava.vscode-java-debug/setJavaBreakpoint', 'vscjava.vscode-java-debug/removeJavaBreakpoints', 'vscjava.vscode-java-debug/stopDebugSession', 'vscjava.vscode-java-debug/getDebugSessionInfo'] +tools: ['read/problems', 'read/readFile', 'search', 'vscjava.vscode-java-debug/startDebugWithLaunchConfig', 'vscjava.vscode-java-debug/setJavaBreakpoint', 'vscjava.vscode-java-debug/removeJavaBreakpoints', 'vscjava.vscode-java-debug/stopDebugSession', 'vscjava.vscode-java-debug/getDebugSessionInfo', 'vscjava.vscode-java-debug/getDebugConsoleOutput'] --- # Java Program Tracing Agent @@ -13,7 +13,9 @@ You are a lightweight Java program behavior verification assistant that uses **l 2. **BEHAVIOR VERIFICATION FIRST** - Always clarify what behavior the user expects to see before setting logpoints 3. **BATCH OBSERVATION** - Set multiple logpoints at once to observe complete execution flow 4. **PATTERN ANALYSIS** - Look for patterns in output, not single-point inspection -5. **CLEANUP BASED ON LAUNCH METHOD** - Check `Launch Method` field: if "Can be safely stopped" → cleanup. If "Stopping will disconnect" → do NOT cleanup +5. **LAUNCH.JSON REQUIRED** - **ALWAYS use startDebugWithLaunchConfig to start debug session**. Requires .vscode/launch.json with Java configurations. If user doesn't have launch.json, guide them to create one. +6. **LOGPOINT PLACEMENT** - **CRITICAL: Set logpoints on the line AFTER variable assignment/operation**, not on the line where variable is declared. Variables are not available until the line completes execution. +7. **CLEANUP BASED ON LAUNCH METHOD** - Check `Launch Method` field: if "Can be safely stopped" → cleanup. If "Stopping will disconnect" → do NOT cleanup ## Understanding Logpoints @@ -48,15 +50,16 @@ You are a lightweight Java program behavior verification assistant that uses **l │ ╚═══════════════════════════════════════════════════════════════════╝ │ │ ↓ │ │ ╔═══════════════════════════════════════════════════════════════════╗ │ - ║ PHASE 2: BATCH LOGPOINT SETUP (BEFORE STARTING SESSION!) ║ │ - ║ • Set multiple logpoints at strategic locations ║ │ - ║ • Configure meaningful output formats ║ │ - ║ • THEN start or verify debug session ║ │ +│ ║ PHASE 2: BATCH LOGPOINT SETUP (BEFORE STARTING SESSION!) ║ │ +│ ║ • Set multiple logpoints at strategic locations ║ │ +│ ║ • Configure meaningful output formats ║ │ +│ ║ • CHECK for .vscode/launch.json (REQUIRED!) ║ │ +│ ║ • Start session with startDebugWithLaunchConfig ║ │ │ ╚═══════════════════════════════════════════════════════════════════╝ │ │ ↓ │ │ ╔═══════════════════════════════════════════════════════════════════╗ │ │ ║ PHASE 3: EXECUTION PATTERN COLLECTION ║ │ -│ ║ • Monitor logpoint output in debug console ║ │ +│ ║ • Monitor logpoint output via getDebugConsoleOutput ║ │ │ ║ • Identify execution patterns and anomalies ║ │ │ ║ • Collect performance and behavior data ║ │ │ ╚═══════════════════════════════════════════════════════════════════╝ │ @@ -114,76 +117,94 @@ I will trace these behaviors using logpoints at strategic locations. ### 2.1 Logpoint Design Patterns -#### **Flow Tracing Pattern** +**⚠️ CRITICAL: Logpoint Line Number Rules** + +```java +// WRONG - Logpoint on variable declaration line +int userId = 123; // Line 10 - Variable NOT available yet on this line! +↑ DON'T set logpoint here + +// CORRECT - Logpoint AFTER variable is assigned +int userId = 123; // Line 10 - Variable assigned +String userName = getUser(userId); // Line 11 - Set logpoint HERE to see userId +↑ Set logpoint on line 11 to observe userId value + +// Example with method entry +public void processOrder(int orderId) { // Line 25 - Method signature + // Line 26 - First executable line, set logpoint HERE + Order order = findOrder(orderId); // Line 27 + ↑ Set logpoint on line 27 to see orderId parameter +} ``` -// Method entry -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="OrderService.java", - lineNumber=25, - logMessage="🚀 [ENTRY] OrderService.processOrder() - orderId: {orderId}, timestamp: {System.currentTimeMillis()}" -) -// Decision points -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="OrderService.java", - lineNumber=30, - logMessage="🔍 [DECISION] Order validation: valid={isValid}, orderId={orderId}" -) +**Rule: Always set logpoint on the line AFTER the variable/operation you want to observe.** -// Method exit -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="OrderService.java", - lineNumber=45, - logMessage="🏁 [EXIT] OrderService.processOrder() - result: {result}, duration: {System.currentTimeMillis() - startTime}ms" -) +#### **Flow Tracing Pattern** + +**Goal**: Trace method entry → decision points → exit + +```java +public void processOrder(int orderId) { // Line 25 + logger.info("Processing order: " + orderId); // Line 26 ← Set logpoint: [ENTRY] + boolean isValid = validateOrder(orderId); // Line 27 + if (isValid) { // Line 28 ← Set logpoint: [DECISION] + saveOrder(orderId); // Line 29 + } + return; // Line 31 ← Set logpoint: [EXIT] +} ``` -#### **Data Flow Pattern** +**Logpoint setup:** +``` +Line 26: "🚀 [ENTRY] processOrder() - orderId: {orderId}" +Line 28: "🔍 [DECISION] Order validation: valid={isValid}" +Line 31: "🏁 [EXIT] processOrder() completed" ``` -// Input validation -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="UserService.java", - lineNumber=15, - logMessage="📥 [INPUT] Raw data: email={email}, passwordLength={password.length()}" -) -// Transformation steps -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="UserService.java", - lineNumber=20, - logMessage="🔄 [TRANSFORM] Email normalized: {normalizedEmail}, valid={emailValidator.isValid(normalizedEmail)}" -) +#### **Data Flow Pattern** -// Output generation -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="UserService.java", - lineNumber=35, - logMessage="📤 [OUTPUT] User created: id={user.id}, status={user.status}" -) +**Goal**: Track data transformation through processing steps + +```java +public User createUser(String email, String password) { // Line 15 + String normalizedEmail = email.toLowerCase().trim(); // Line 16 + boolean isValid = emailValidator.isValid(normalizedEmail); // Line 17 ← [INPUT] + if (!isValid) { // Line 18 ← [VALIDATE] + throw new ValidationException("Invalid email"); + } + User user = new User(normalizedEmail, password); // Line 21 + user.setStatus("ACTIVE"); // Line 22 ← [OUTPUT] + return user; // Line 23 +} ``` -#### **Performance Monitoring Pattern** +**Logpoint setup:** +``` +Line 17: "📥 [INPUT] Raw: {email}, normalized: {normalizedEmail}" +Line 18: "🔄 [VALIDATE] Email valid: {isValid}" +Line 22: "📤 [OUTPUT] User created: id={user.getId()}" ``` -// Operation start -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="DatabaseService.java", - lineNumber=50, - logMessage="⏱️ [PERF_START] Database query starting - query: {queryType}, timestamp: {System.currentTimeMillis()}" -) -// Critical checkpoints -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="DatabaseService.java", - lineNumber=65, - logMessage="📊 [PERF_CHECKPOINT] Connection acquired in {System.currentTimeMillis() - startTime}ms, pool size: {connectionPool.size()}" -) +#### **Performance Monitoring Pattern** -// Operation end -vscjava.vscode-java-debug/setJavaBreakpoint( - filePath="DatabaseService.java", - lineNumber=80, - logMessage="⏱️ [PERF_END] Query completed - rows: {resultSet.size()}, total time: {System.currentTimeMillis() - startTime}ms" -) +**Goal**: Measure operation timing and identify bottlenecks + +```java +public List executeQuery(String queryType) { // Line 50 + long startTime = System.currentTimeMillis(); // Line 51 + Connection conn = connectionPool.getConnection(); // Line 52 ← [PERF_START] + ResultSet resultSet = conn.executeQuery(queryType); // Line 53 ← [CHECKPOINT] + List results = processResults(resultSet); // Line 54 + long endTime = System.currentTimeMillis(); // Line 55 + return results; // Line 56 ← [PERF_END] +} +``` + +**Logpoint setup:** +``` +Line 52: "⏱️ [START] Query: {queryType}, time: {startTime}" +Line 53: "📊 [CHECKPOINT] Connection: {System.currentTimeMillis() - startTime}ms" +Line 56: "⏱️ [END] Total: {endTime - startTime}ms, rows: {results.size()}" ``` ### 2.2 Batch Setup Strategy @@ -231,13 +252,71 @@ vscjava.vscode-java-debug/getDebugSessionInfo() ``` **Action based on state:** -- ❌ **NO SESSION** → Start debug session now: +- ❌ **NO SESSION** → Start debug session using launch.json: + + **📋 Check for launch.json (REQUIRED)** ``` - vscjava.vscode-java-debug/debugJavaApplication(target="MainClass") + Use read/readFile to verify .vscode/launch.json exists: + readFile(".vscode/launch.json") ``` + + **✅ If launch.json EXISTS → Start debug session:** + ``` + vscjava.vscode-java-debug/startDebugWithLaunchConfig( + workspacePath="/absolute/path/to/workspace" + // configName is optional - will use first Java config if omitted + ) + ``` + + **Benefits of using launch.json:** + - ✅ Respects user's configured VM args, environment variables, classpath + - ✅ Equivalent to user pressing F5 (expected behavior) + - ✅ Supports complex configurations (multi-module projects, special JVM flags) + - ✅ Consistent with user's workflow and project setup + + **❌ If launch.json DOES NOT EXIST → Guide user to create it:** + ```markdown + I need a launch.json configuration to start the debug session for tracing. + + To create one: + 1. Open "Run and Debug" view (Ctrl+Shift+D / Cmd+Shift+D) + 2. Click "create a launch.json file" + 3. Select "Java" as the environment + 4. Choose your main class or let VS Code detect it + + Or you can create .vscode/launch.json manually with: + { + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch App", + "request": "launch", + "mainClass": "com.example.Main" + } + ] + } + + Once you've created launch.json, let me know and I'll start the trace. + ``` + - 🟢 **RUNNING** → Perfect! Logpoints are active and tracing - 🔴 **PAUSED** → Tell user to continue execution (`F5`) - we don't want to pause! +**⚠️ STARTUP FLOW:** +``` +STEP 1: Check if debug session exists + ↓ +STEP 2: If NO SESSION → Check for .vscode/launch.json + ↓ +STEP 3: If launch.json exists + → Call startDebugWithLaunchConfig(workspacePath) + ↓ + If launch.json does NOT exist + → Guide user to create launch.json + → Wait for user confirmation before proceeding +``` + **Remember: Logpoints are set first (no session needed), then we start/verify the debug session!** --- @@ -246,7 +325,67 @@ vscjava.vscode-java-debug/getDebugSessionInfo() ### 3.1 Monitor Debug Console Output -After logpoints are set and program is running, watch for output patterns in the debug console: +**✅ CORRECT: Logpoint output goes to Debug Console (captured via DebugAdapterTracker)** + +After logpoints are set and program runs, **use the getDebugConsoleOutput tool to retrieve output:** + +``` +vscjava.vscode-java-debug/getDebugConsoleOutput() +``` + +**How to get debug console output:** + +1. **Set logpoints BEFORE starting debug session** - This ensures all output is captured from the start +2. **Start debug session** - Use startDebugWithLaunchConfig +3. **Wait for program to run** - Let logpoints trigger during execution (2-5 seconds typically) +4. **Retrieve output** - Call getDebugConsoleOutput to fetch all logged messages + +**Usage patterns:** + +``` +// Get all output from current session +vscjava.vscode-java-debug/getDebugConsoleOutput() + +// Get last 50 lines only +vscjava.vscode-java-debug/getDebugConsoleOutput(maxLines=50) + +// Filter output by text pattern +vscjava.vscode-java-debug/getDebugConsoleOutput(filter="OrderService") + +// Read from specific ended session +vscjava.vscode-java-debug/getDebugConsoleOutput(sessionId="session-123") +``` + +**⚠️ IMPORTANT: Output capture relies on DebugAdapterTracker** +- Output is captured automatically from DAP protocol messages +- Cache survives 5 minutes after session ends +- If no output appears, check diagnostic information in tool result +- Logpoint output has category `[console]`, stdout/stderr have `[stdout]`/`[stderr]` + +### 3.2 Troubleshooting: No Output Captured + +If `getDebugConsoleOutput` returns no output, the tool provides diagnostic information: + +**Common issues and solutions:** + +| Issue | Solution | +|-------|----------| +| **"No debug session output available"** | No session started yet. Call `startDebugWithLaunchConfig` first | +| **"No console output captured (ACTIVE)"** | Program hasn't reached logpoint code yet. Wait 2-3 seconds and retry | +| **"Session in cache: No"** | Session was never created. Check if debug session actually started | +| **"Output lines captured: 0"** | Logpoints not triggered. Verify code executes the path with logpoints | +| **No `[console]` category** | Only stdout/stderr captured, no logpoints. Verify logpoints are set correctly | + +**Best Practice Workflow:** +``` +1. Set all logpoints FIRST (before starting session) +2. Start debug session +3. Wait 3-5 seconds for program to execute +4. Call getDebugConsoleOutput +5. If empty, check diagnostic info and retry after waiting +``` + +After logpoints are set and program is running, watch for output patterns: #### **Normal Execution Pattern Example:** ``` @@ -301,77 +440,64 @@ I'll analyze the patterns from multiple executions to identify: ### 4.1 Execution Flow Analysis -```markdown -## Execution Flow Analysis +**Template for analyzing observed behavior:** -### Observed Behavior Patterns +**Observed Behavior Patterns:** -#### Happy Path (3 executions): -``` -🚀 [ENTRY] → 🔍 [VALIDATION: valid=true] → 🔄 [PROCESSING] → 🏁 [EXIT: SUCCESS] -Average duration: 287ms (range: 245-312ms) -``` +**Happy Path (3 executions):** +- Flow: 🚀 [ENTRY] → 🔍 [VALIDATION: valid=true] → 🔄 [PROCESSING] → 🏁 [EXIT: SUCCESS] +- Duration: Average 287ms (range: 245-312ms) -#### Error Path (2 executions): -``` -🚀 [ENTRY] → 🔍 [VALIDATION: valid=false] → 🏁 [EXIT: ERROR] -Average duration: 23ms (range: 18-28ms) -``` +**Error Path (2 executions):** +- Flow: 🚀 [ENTRY] → 🔍 [VALIDATION: valid=false] → 🏁 [EXIT: ERROR] +- Duration: Average 23ms (range: 18-28ms) -#### Anomaly Detected: -``` -🚀 [ENTRY] → 🔍 [VALIDATION: valid=false] → 🔄 [PROCESSING] → 🏁 [EXIT: SUCCESS] -``` -**Issue**: Invalid orders are being processed despite validation failure! -``` +**Anomaly Detected:** +- Flow: 🚀 [ENTRY] → 🔍 [VALIDATION: valid=false] → 🔄 [PROCESSING] → 🏁 [EXIT: SUCCESS] +- Issue: Invalid orders are being processed despite validation failure! ### 4.2 Performance Analysis -```markdown -## Performance Profile +**Template for performance reporting:** -### Duration Analysis: -- **Normal processing**: 245-312ms (acceptable) -- **Validation failures**: 18-28ms (fast rejection - good) -- **Database operations**: 45-67ms (within SLA) +**Duration Analysis:** +- Normal processing: 245-312ms (acceptable) +- Validation failures: 18-28ms (fast rejection - good) +- Database operations: 45-67ms (within SLA) -### Bottleneck Identification: -- **Slowest operation**: Payment gateway (avg 245ms) -- **Optimization opportunity**: Currency conversion (redundant calls detected) +**Bottleneck Identification:** +- Slowest operation: Payment gateway (avg 245ms) +- Optimization opportunity: Currency conversion (redundant calls detected) -### Recommendations: -1. Fix validation bypass bug (critical) -2. Cache currency conversion rates (performance) -3. Add timeout handling for payment gateway (reliability) -``` +**Recommendations:** +1. 🔴 Critical: Fix validation bypass bug in OrderService.java:35 +2. 🟡 Optimization: Cache currency conversion rates +3. 🟢 Enhancement: Add timeout handling for payment gateway ### 4.3 Verification Conclusions -#### **Verification Status Template:** -```markdown -## Verification Results +**Template for final verification report:** -### Expected vs Actual Behavior +**Expected vs Actual Behavior:** ✅ **Normal Order Processing** - Expected: Validate → Process → Save → Return success -- Actual: ✅ Working as expected -- Performance: ✅ Within acceptable limits (287ms avg) +- Actual: Working as expected +- Performance: Within acceptable limits (287ms avg) -❌ **Invalid Order Handling** +❌ **Invalid Order Handling** - Expected: Validate → Reject immediately → Return error -- Actual: ❌ Sometimes processes invalid orders! +- Actual: Sometimes processes invalid orders! - Root cause: Validation result not properly checked at line 35 ✅ **Error Recovery** -- Expected: Graceful handling of payment failures -- Actual: ✅ Proper rollback and cleanup observed +- Expected: Graceful handling of payment failures +- Actual: Proper rollback and cleanup observed -### Action Items -1. 🔴 **Critical**: Fix validation bypass bug in OrderService.java:35 -2. 🟡 **Optimization**: Implement currency rate caching -3. 🟢 **Enhancement**: Add comprehensive timeout handling -``` +**Action Items:** +1. 🔴 Critical: Fix validation bypass bug in OrderService.java:35 +2. 🟡 Optimization: Implement currency rate caching +3. 🟢 Enhancement: Add comprehensive timeout handling --- @@ -466,48 +592,36 @@ You can manually remove logpoints if desired: Debug → Remove All Breakpoints ## Example: Complete Verification Session -``` -User: "I want to verify that my user registration flow works correctly" - -=== PHASE 1: EXPECTATION ANALYSIS === +**User Request**: "I want to verify that my user registration flow works correctly" -1. Understand expected flow: - "User submits email/password → Validate input → Check uniqueness → Save user → Send confirmation" +**PHASE 1: EXPECTATION ANALYSIS** +1. Expected flow: User submits email/password → Validate input → Check uniqueness → Save user → Send confirmation +2. Verification points: Input validation, uniqueness checking, user creation, email sending -2. Define verification points: - - Input validation correctness - - Database uniqueness checking - - User creation success - - Email sending reliability +**PHASE 2: BATCH LOGPOINT SETUP** +Setting 6 strategic logpoints (before starting debug): +- UserController.register() entry +- Input validation result +- Email uniqueness check +- User save operation +- Email service call +- Registration completion -=== PHASE 2: BATCH LOGPOINT SETUP === - -Setting 6 strategic logpoints FIRST (before starting debug): -1. UserController.register() entry -2. Input validation result -3. Email uniqueness check -4. User save operation -5. Email service call -6. Registration completion - -Now starting debug session to activate the logpoints... - -=== PHASE 3: EXECUTION MONITORING === +Then start debug session to activate logpoints. +**PHASE 3: EXECUTION MONITORING** User triggers 5 registration attempts: - 3 successful registrations - 1 duplicate email (expected error) - 1 invalid email format (expected error) -=== PHASE 4: VERIFICATION RESULTS === +**PHASE 4: VERIFICATION RESULTS** +- ✅ Input validation: Working correctly +- ✅ Uniqueness checking: Working correctly +- ✅ User creation: Working correctly +- ❌ Email sending: Failed silently in 2/3 cases! -✅ Input validation: Working correctly -✅ Uniqueness checking: Working correctly -✅ User creation: Working correctly -❌ Email sending: Failed silently in 2/3 cases! - -Recommendation: Add error handling and retry logic for email service -``` +**Recommendation**: Add error handling and retry logic for email service --- diff --git a/package.json b/package.json index 696fc1e1..209442e7 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,9 @@ "onDebugResolve:java", "onCommand:JavaDebug.SpecifyProgramArgs", "onCommand:JavaDebug.PickJavaProcess", - "onLanguageModelTool:debug_java_application" + "onLanguageModelTool:debug_java_application", + "onLanguageModelTool:start_debug_with_launch_config", + "onLanguageModelTool:get_debug_console_output" ], "main": "./dist/extension", "contributes": { @@ -1330,6 +1332,72 @@ "properties": {}, "required": [] } + }, + { + "name": "start_debug_with_launch_config", + "displayName": "Start Debug with Launch Config", + "modelDescription": "Start a debug session using an existing launch.json configuration. This respects user's debug settings (VM args, environment variables, etc.) and is equivalent to pressing F5. PREFERRED over debug_java_application when launch.json exists. Automatically detects Java launch configurations in .vscode/launch.json. Can optionally specify a configuration name, or uses the first Java config by default. Use this for trace agent to honor user's project setup.", + "toolReferenceName": "startDebugWithLaunchConfig", + "tags": [ + "java", + "debug", + "launch", + "F5", + "configuration", + "start" + ], + "icon": "$(debug-start)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "workspacePath": { + "type": "string", + "description": "Absolute path to the workspace folder containing .vscode/launch.json" + }, + "configName": { + "type": "string", + "description": "Optional: Name of the specific launch configuration to use. If omitted, uses the first Java launch configuration found." + } + }, + "required": [ + "workspacePath" + ] + } + }, + { + "name": "get_debug_console_output", + "displayName": "Get Debug Console Output", + "modelDescription": "Retrieve output from the Debug Console including logpoint messages, program stdout/stderr, and debug adapter messages. CRITICAL for trace agent to verify logpoint output and analyze program behavior. Returns console output from active or recently ended sessions. Supports reading from specific sessions or most recent session. Supports filtering by text pattern and limiting output lines.", + "toolReferenceName": "getDebugConsoleOutput", + "tags": [ + "java", + "debug", + "console", + "output", + "logpoint", + "trace" + ], + "icon": "$(output)", + "canBeReferencedInPrompt": true, + "inputSchema": { + "type": "object", + "properties": { + "maxLines": { + "type": "number", + "description": "Optional: Maximum number of lines to return (default: 100). Returns the most recent lines." + }, + "filter": { + "type": "string", + "description": "Optional: Filter output by text pattern. Only lines containing this text will be returned." + }, + "sessionId": { + "type": "string", + "description": "Optional: Specific debug session ID to read from. If not provided, uses active session or most recent session. Useful for reading output after session ends." + } + }, + "required": [] + } } ], "chatAgents": [ diff --git a/src/extension.ts b/src/extension.ts index e3a75eb0..cf19d865 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -31,6 +31,10 @@ import { registerBreakpointCommands } from "./breakpointCommands"; import { registerVariableMenuCommands } from "./variableMenu"; import { promisify } from "util"; +// Global cache for debug console output +export const debugConsoleOutputCache = new Map(); +const MAX_CONSOLE_LINES_PER_SESSION = 1000; // Limit cache size + export async function activate(context: vscode.ExtensionContext): Promise { await initializeFromJsonFile(context.asAbsolutePath("./package.json")); await initExpService(context); @@ -198,6 +202,76 @@ function registerDebugEventListener(context: vscode.ExtensionContext) { handleUserNotification(customEvent); } })); + + // Clean up cache when debug session ends (delayed to allow reading after session ends) + context.subscriptions.push(vscode.debug.onDidTerminateDebugSession((session) => { + if (session.type === JAVA_LANGID) { + // Keep cache for 5 minutes after session ends to allow agent to read output + setTimeout(() => { + debugConsoleOutputCache.delete(session.id); + }, 5 * 60 * 1000); // 5 minutes + } + })); + + // Register Debug Adapter Tracker to capture output events + // This is the CORRECT way to capture Debug Console output + // onDidReceiveDebugSessionCustomEvent only captures custom events, not standard DAP output events + context.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory('java', { + createDebugAdapterTracker(session: vscode.DebugSession): vscode.ProviderResult { + // Initialize cache for this session immediately + const sessionId = session.id; + if (!debugConsoleOutputCache.has(sessionId)) { + debugConsoleOutputCache.set(sessionId, []); + sendInfo('', { + operationName: 'debugConsoleOutput.sessionCreated', + sessionId, + sessionName: session.name + }); + } + + return { + onDidSendMessage(message: any): void { + // Capture all messages sent FROM debug adapter TO VS Code + // Standard DAP output events have: type='event', event='output' + if (message.type === 'event' && message.event === 'output') { + const output = message.body?.output; + const category = message.body?.category; // stdout, stderr, console, telemetry + + if (output && typeof output === 'string') { + const outputs = debugConsoleOutputCache.get(sessionId)!; + + // Add category prefix for better filtering + const prefixedOutput = category ? `[${category}] ${output}` : output; + outputs.push(prefixedOutput); + + // Limit cache size to prevent memory issues + if (outputs.length > MAX_CONSOLE_LINES_PER_SESSION) { + outputs.shift(); // Remove oldest entry + } + + sendInfo('', { + operationName: 'debugConsoleOutput.captured', + sessionId, + category: category || 'unknown', + outputLength: output.length, + totalCached: outputs.length + }); + } + } + }, + onWillReceiveMessage(message: any): void { + // Also log messages sent FROM VS Code TO debug adapter (for debugging) + if (message.type === 'request' && message.command === 'setBreakpoints') { + sendInfo('', { + operationName: 'debugConsoleOutput.breakpointsSet', + sessionId, + hasLogpoints: message.arguments?.breakpoints?.some((bp: any) => bp.logMessage) || false + }); + } + } + }; + } + })); } function handleUserNotification(customEvent: vscode.DebugSessionCustomEvent) { diff --git a/src/languageModelTool.ts b/src/languageModelTool.ts index ad803d25..43974272 100644 --- a/src/languageModelTool.ts +++ b/src/languageModelTool.ts @@ -861,6 +861,17 @@ interface StopDebugSessionInput { reason?: string; } +interface StartDebugWithLaunchConfigInput { + workspacePath: string; + configName?: string; // Optional: specific config name from launch.json +} + +interface GetDebugConsoleOutputInput { + maxLines?: number; // Optional: limit number of lines returned + filter?: string; // Optional: filter output by text pattern + sessionId?: string; // Optional: specific session ID to read from +} + // eslint-disable-next-line @typescript-eslint/no-empty-interface type GetDebugSessionInfoInput = Record; @@ -1561,6 +1572,177 @@ export function registerDebugSessionTools(_context: vscode.ExtensionContext): vs }; disposables.push(lmApi.registerTool('get_debug_session_info', getDebugSessionInfoTool)); + // Tool 11: Start Debug with Launch Config + const startDebugWithLaunchConfigTool: LanguageModelTool = { + async invoke(options: { input: StartDebugWithLaunchConfigInput }, _token: vscode.CancellationToken): Promise { + try { + const result = await startDebugWithLaunchConfig(options.input); + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(result) + ]); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to start debug with launch config: ${errorMessage}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('start_debug_with_launch_config', startDebugWithLaunchConfigTool)); + + // Tool 12: Get Debug Console Output + const getDebugConsoleOutputTool: LanguageModelTool = { + async invoke(options: { input: GetDebugConsoleOutputInput }, _token: vscode.CancellationToken): Promise { + try { + // Import the cache from extension.ts + const { debugConsoleOutputCache } = await import('./extension'); + + let targetSessionId: string | undefined; + let sessionName: string = 'Unknown'; + + // Collect diagnostic information + const activeSessions = vscode.debug.activeDebugSession ? [vscode.debug.activeDebugSession] : []; + const cachedSessions = Array.from(debugConsoleOutputCache.keys()); + + // Determine which session to read from + if (options.input.sessionId) { + // Use specified session ID + targetSessionId = options.input.sessionId; + sessionName = `Session ${targetSessionId}`; + } else if (vscode.debug.activeDebugSession) { + // Use active session + targetSessionId = vscode.debug.activeDebugSession.id; + sessionName = vscode.debug.activeDebugSession.name; + } else if (debugConsoleOutputCache.size > 0) { + // No active session, use the most recent session in cache + const sessions = Array.from(debugConsoleOutputCache.keys()); + targetSessionId = sessions[sessions.length - 1]; + sessionName = `Most recent session (${targetSessionId})`; + } else { + // No sessions available at all - provide diagnostic info + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + '❌ No debug session output available.\n\n' + + '**Diagnostic Information:**\n' + + `• Active debug sessions: ${activeSessions.length}\n` + + `• Cached sessions: ${cachedSessions.length}\n` + + `• Cache entries: ${debugConsoleOutputCache.size}\n\n` + + '**This could mean:**\n' + + '• No debug session has been started yet\n' + + '• All session output has been cleaned up\n' + + '• Session ended too long ago (cache timeout: 5 minutes)\n' + + '• DebugAdapterTracker not capturing output (check extension logs)\n\n' + + '**Troubleshooting:**\n' + + '1. Start debug session using startDebugWithLaunchConfig\n' + + '2. Set logpoints BEFORE starting the session\n' + + '3. Let the program run and trigger logpoints\n' + + '4. Check VS Code Debug Console for output\n' + + '5. Call this tool again after logpoints trigger' + ) + ]); + } + + // At this point targetSessionId is guaranteed to be defined + if (!targetSessionId) { + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart('❌ Internal error: Unable to determine session ID.') + ]); + } + + const outputs = debugConsoleOutputCache.get(targetSessionId) || []; + + if (outputs.length === 0) { + const isActive = vscode.debug.activeDebugSession?.id === targetSessionId; + const hasCache = debugConsoleOutputCache.has(targetSessionId); + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart( + `ℹ️ No console output captured for "${sessionName}" (${isActive ? '🟢 ACTIVE' : '⚪ ENDED'})\n\n` + + `**Diagnostic Information:**\n` + + `• Session in cache: ${hasCache ? '✅ Yes' : '❌ No'}\n` + + `• Session status: ${isActive ? 'Running' : 'Ended'}\n` + + `• Output lines captured: 0\n` + + `• All cached sessions: ${Array.from(debugConsoleOutputCache.keys()).join(', ')}\n\n` + + `**Possible reasons:**\n` + + `• The program hasn't produced any output yet\n` + + `• Logpoints haven't been triggered (check if code executed)\n` + + `• The program is still starting up\n` + + `• Logpoints were set AFTER program already executed that code\n` + + `• Output is going to stdout/stderr instead of Debug Console\n\n` + + (isActive ? + `**Next steps (Session is ACTIVE):**\n` + + `1. Verify logpoints are set correctly (check Debug sidebar)\n` + + `2. Trigger the code path with logpoints\n` + + `3. Check VS Code Debug Console for output\n` + + `4. Wait 2-3 seconds and call this tool again` : + `**Next steps (Session has ENDED):**\n` + + `1. The session ended without producing output\n` + + `2. Set logpoints BEFORE starting debug session\n` + + `3. Start a new debug session\n` + + `4. Ensure code with logpoints executes`) + ) + ]); + } + + // Apply filter if specified + let filteredOutputs = outputs; + if (options.input.filter) { + const filterLower = options.input.filter.toLowerCase(); + filteredOutputs = outputs.filter(line => line.toLowerCase().includes(filterLower)); + } + + // Apply max lines limit + const maxLines = options.input.maxLines || 100; + const limitedOutputs = filteredOutputs.slice(-maxLines); // Get last N lines + + const outputText = limitedOutputs.join(''); + const totalLines = outputs.length; + const filteredCount = filteredOutputs.length; + const displayedCount = limitedOutputs.length; + const isActive = vscode.debug.activeDebugSession?.id === targetSessionId; + + // Count output by category + const categoryCounts: { [key: string]: number } = {}; + outputs.forEach(line => { + const match = line.match(/^\[([^\]]+)\]/); + const category = match ? match[1] : 'uncategorized'; + categoryCounts[category] = (categoryCounts[category] || 0) + 1; + }); + + let summary = `📋 Debug Console Output (${sessionName})\n`; + summary += `Status: ${isActive ? '🟢 ACTIVE' : '⚪ ENDED'}\n`; + summary += `Session ID: ${targetSessionId}\n`; + summary += `═══════════════════════════════════════════\n`; + summary += `Total lines: ${totalLines}\n`; + summary += `Categories: ${Object.keys(categoryCounts).map(cat => `${cat}(${categoryCounts[cat]})`).join(', ')}\n`; + + if (options.input.filter) { + summary += `Filtered lines: ${filteredCount} (filter: "${options.input.filter}")\n`; + } + + summary += `Displayed: ${displayedCount} ${displayedCount < filteredCount ? '(last ' + displayedCount + ' lines)' : ''}\n`; + summary += `═══════════════════════════════════════════\n\n`; + + // Add helpful hints if no console category found + if (!categoryCounts['console'] && totalLines > 0) { + summary += `⚠️ **Note:** No [console] category output detected. ` + + `Logpoints should produce [console] category output.\n` + + `If you see [stdout] or [stderr], those are System.out/System.err, not logpoints.\n\n`; + } + + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(summary + outputText) + ]); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return new (vscode as any).LanguageModelToolResult([ + new (vscode as any).LanguageModelTextPart(`✗ Failed to get debug console output: ${errorMessage}`) + ]); + } + } + }; + disposables.push(lmApi.registerTool('get_debug_console_output', getDebugConsoleOutputTool)); + return disposables; } @@ -1575,3 +1757,125 @@ function matchWildcard(text: string, pattern: string): boolean { function escapeRegex(str: string): string { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } + +// ============================================================================ +// Launch Configuration Tool +// ============================================================================ + +/** + * Starts a debug session using launch.json configuration. + * This respects user's existing debug configurations and is equivalent to pressing F5. + */ +async function startDebugWithLaunchConfig(input: StartDebugWithLaunchConfigInput): Promise { + const workspaceUri = vscode.Uri.file(input.workspacePath); + const workspaceFolder = vscode.workspace.getWorkspaceFolder(workspaceUri); + + if (!workspaceFolder) { + return `✗ Cannot find workspace folder for ${input.workspacePath}`; + } + + // Check if launch.json exists + const launchJsonPath = path.join(input.workspacePath, '.vscode', 'launch.json'); + if (!fs.existsSync(launchJsonPath)) { + return `✗ No launch.json found at ${launchJsonPath}.\n\n` + + `To use this tool, you need a launch.json file. You can:\n` + + `1. Create one manually in .vscode/launch.json\n` + + `2. Use VS Code's "Run and Debug" view to generate one\n` + + `3. Or use the debug_java_application tool as a fallback`; + } + + // Read and parse launch.json + let launchConfig: any; + try { + const launchJsonContent = fs.readFileSync(launchJsonPath, 'utf-8'); + // Remove comments from JSON (launch.json often has comments) + const jsonWithoutComments = launchJsonContent.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, ''); + launchConfig = JSON.parse(jsonWithoutComments); + } catch (error) { + return `✗ Failed to parse launch.json: ${error instanceof Error ? error.message : String(error)}`; + } + + const configurations = launchConfig.configurations || []; + if (configurations.length === 0) { + return `✗ No debug configurations found in launch.json`; + } + + // Find Java debug configurations + const javaConfigs = configurations.filter((config: any) => + config.type === 'java' && config.request === 'launch' + ); + + if (javaConfigs.length === 0) { + return `✗ No Java launch configurations found in launch.json.\n\n` + + `Found ${configurations.length} configuration(s), but none are Java launch configs.\n` + + `Please add a Java debug configuration or use debug_java_application tool instead.`; + } + + // Determine which config to use + let configToUse: any; + if (input.configName) { + // Use specified config name + configToUse = javaConfigs.find((config: any) => config.name === input.configName); + if (!configToUse) { + const availableNames = javaConfigs.map((c: any) => c.name).join(', '); + return `✗ Configuration "${input.configName}" not found.\n\n` + + `Available Java configurations: ${availableNames}`; + } + } else { + // Use the first Java launch config + configToUse = javaConfigs[0]; + } + + // Clean up any existing Java debug session + const existingSession = vscode.debug.activeDebugSession; + if (existingSession && existingSession.type === 'java') { + try { + await vscode.debug.stopDebugging(existingSession); + await new Promise(resolve => setTimeout(resolve, 500)); + } catch (error) { + // Ignore cleanup errors + } + } + + // Start debugging using the configuration name + // This is equivalent to selecting the config in UI and pressing F5 + sendInfo('', { + operationName: 'languageModelTool.startDebugWithLaunchConfig', + configName: configToUse.name, + workspacePath: input.workspacePath + }); + + try { + const started = await vscode.debug.startDebugging(workspaceFolder, configToUse.name); + + if (!started) { + return `✗ Failed to start debug session with configuration "${configToUse.name}".\n\n` + + `This might be due to:\n` + + `• Configuration errors in launch.json\n` + + `• Missing dependencies or compilation errors\n` + + `• Invalid mainClass or other settings\n\n` + + `Check the Debug Console for error messages.`; + } + + // Wait a bit for session to start and be detected + await new Promise(resolve => setTimeout(resolve, 1000)); + + const session = vscode.debug.activeDebugSession; + if (session && session.type === 'java') { + return `✓ Debug session started successfully using launch.json configuration "${configToUse.name}".\n` + + `Session ID: ${session.id}\n` + + `Session Name: ${session.name}\n\n` + + `The debugger is attached and ready. Any breakpoints/logpoints you set will be active.`; + } else { + return `⚠️ Debug command sent using configuration "${configToUse.name}", but session not immediately detected.\n\n` + + `The application may still be starting. Use get_debug_session_info() to check if session is now active.`; + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return `✗ Error starting debug session: ${errorMessage}\n\n` + + `Check your launch.json configuration and ensure:\n` + + `• The mainClass is correct\n` + + `• The project is compiled\n` + + `• All required settings are valid`; + } +}