Skip to content

Commit 8ace056

Browse files
committed
fix: filter function variables
1 parent a6c36b4 commit 8ace056

File tree

9 files changed

+86
-42
lines changed

9 files changed

+86
-42
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ dist
66
score_tally.txt
77
coverage
88
.nyc_output
9+
Issues.md

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ serverReady: {
8282

8383
## [0.0.16] - 2025-11-20
8484

85-
**Documentation:** Clarified that `variableFilter` values are exact, case-sensitive variable names (no regex support). Removed prior regex-style examples (`^(user|session)$`, `^order_`) from README and replaced with explicit name lists. Added note that `resume_debug_session` breakpoints may omit `variableFilter` (optional) while `start_debugger_with_breakpoints` requires it per breakpoint to keep responses compact.
85+
**Documentation:** Clarified that `variableFilter` values are exact, case-sensitive variable names (no regex support). Removed prior regex-style examples (`^(user|session)$`, `^order_`) from README and replaced with explicit name lists. Added note that `resumeDebugSession` breakpoints may omit `variableFilter` (optional) while `startDebugSessionWithBreakpoints` requires it per breakpoint to keep responses compact.
8686

8787
**Added:** Expanded README action guidance (difference between `break`, `capture`, `stopDebugging`), release workflow steps, and improved examples for capture interpolation.
8888

Issues.md

Lines changed: 0 additions & 7 deletions
This file was deleted.

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ Use GitHub Copilot (or any LM-enabled workflow in VS Code) to start, inspect, an
66

77
The extension contributes Language Model Tools that Copilot can invoke:
88

9-
1. **Start Debugger** (`start_debugger_with_breakpoints`) – Launch a configured debug session and wait for the first breakpoint. You must supply at least one breakpoint, but `variableFilter` is optional: include it to narrow captured variables, omit it for a pure pause (`break` / `stopDebugging`) or automatic capture-all (`capture` action).
10-
2. **Resume Debug Session** (`resume_debug_session`) – Continue execution of an existing paused session and optionally wait for the next stop (new breakpoints added during resume may omit `variableFilter` if you only need a pause, but include it for scoped variable output or interpolation).
11-
3. **Get Variables** (`get_variables`) – Retrieve all variables in the current top stack frame scopes.
12-
4. **Expand Variable** (`expand_variable`) – Drill into a single variable to inspect its immediate children.
13-
5. **Evaluate Expression** (`evaluate_expression`) – Run an arbitrary expression (like the Debug Console) in the paused stack frame.
14-
6. **Stop Debug Session** (`stop_debug_session`) – Terminate matching debug sessions when you’re done.
9+
1. **Start Debugger** (`startDebugSessionWithBreakpoints`) – Launch a configured debug session and wait for the first breakpoint. You must supply at least one breakpoint, but `variableFilter` is optional: include it to narrow captured variables, omit it for a pure pause (`break` / `stopDebugging`) or automatic capture-all (`capture` action).
10+
2. **Resume Debug Session** (`resumeDebugSession`) – Continue execution of an existing paused session and optionally wait for the next stop (new breakpoints added during resume may omit `variableFilter` if you only need a pause, but include it for scoped variable output or interpolation).
11+
3. **Get Variables** (`getVariables`) – Retrieve all variables in the current top stack frame scopes.
12+
4. **Expand Variable** (`expandVariable`) – Drill into a single variable to inspect its immediate children.
13+
5. **Evaluate Expression** (`evaluateExpression`) – Run an arbitrary expression (like the Debug Console) in the paused stack frame.
14+
6. **Stop Debug Session** (`stopDebugSession`) – Terminate matching debug sessions when you’re done.
1515

1616
All tools return structured data that Copilot can reason over (JSON-like text parts containing call stacks, variables, and metadata).
1717

@@ -110,7 +110,7 @@ Default : `false`
110110

111111
The repo already ships with a workspace-level Run on Save configuration (see `.vscode/settings.json`) that fires `npm run update` any time `package.json` is saved. Just install the [Run on Save](https://marketplace.visualstudio.com/items?itemName=emeraldwalk.RunOnSave) extension when VS Code recommends it and the tables will stay in sync automatically.
112112

113-
> **Important (updated):** `start_debugger_with_breakpoints` requires at least one breakpoint. `variableFilter` is **only required** when you want a _subset_ of variables for a `capture` action. If you set `action: "capture"` and omit `variableFilter`, the tool auto-captures the first `captureMaxVariables` locals (case‑sensitive exact names) to reduce friction. For `break` or `stopDebugging` actions, omit `variableFilter` for a pure pause without variable output.
113+
> **Important (updated):** `startDebugSessionWithBreakpoints` requires at least one breakpoint. `variableFilter` is **only required** when you want a _subset_ of variables for a `capture` action. If you set `action: "capture"` and omit `variableFilter`, the tool auto-captures the first `captureMaxVariables` locals (case‑sensitive exact names) to reduce friction. For `break` or `stopDebugging` actions, omit `variableFilter` for a pure pause without variable output.
114114
115115
### Entry Timeout Diagnostics
116116

package.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"bugs": {
1515
"url": "https://github.com/dkattan/Copilot-Breakpoint-Debugger/issues"
1616
},
17-
"when": "debugState == 'running'",
17+
"when": "debugState == 'running'",
1818
"keywords": [
1919
"copilot",
2020
"debug",
@@ -118,8 +118,8 @@
118118
}
119119
},
120120
"languageModelTools": [
121-
{
122-
"name": "startDebugSessionWithBreakpoints",
121+
{
122+
"name": "startDebugSessionWithBreakpoints",
123123
"displayName": "Start Debugger",
124124
"toolReferenceName": "startDebugSessionWithBreakpoints",
125125
"canBeReferencedInPrompt": true,
@@ -328,8 +328,8 @@
328328
]
329329
}
330330
},
331-
{
332-
"name": "resumeDebugSession",
331+
{
332+
"name": "resumeDebugSession",
333333
"displayName": "Resume Debug Session",
334334
"toolReferenceName": "resumeDebugSession",
335335
"canBeReferencedInPrompt": true,
@@ -404,8 +404,8 @@
404404
]
405405
}
406406
},
407-
{
408-
"name": "getVariables",
407+
{
408+
"name": "getVariables",
409409
"displayName": "Get Variables",
410410
"toolReferenceName": "getVariables",
411411
"canBeReferencedInPrompt": true,
@@ -416,8 +416,8 @@
416416
"properties": {}
417417
}
418418
},
419-
{
420-
"name": "expandVariable",
419+
{
420+
"name": "expandVariable",
421421
"displayName": "Expand Variable",
422422
"toolReferenceName": "expandVariable",
423423
"canBeReferencedInPrompt": true,
@@ -436,8 +436,8 @@
436436
]
437437
}
438438
},
439-
{
440-
"name": "evaluateExpression",
439+
{
440+
"name": "evaluateExpression",
441441
"displayName": "Evaluate Expression",
442442
"toolReferenceName": "evaluateExpression",
443443
"canBeReferencedInPrompt": true,
@@ -460,8 +460,8 @@
460460
]
461461
}
462462
},
463-
{
464-
"name": "stopDebugSession",
463+
{
464+
"name": "stopDebugSession",
465465
"displayName": "Stop Debug Session",
466466
"toolReferenceName": "stopDebugSession",
467467
"canBeReferencedInPrompt": true,

src/debugUtils.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,18 @@ export class DAPHelpers {
115115
if (!variablesResponse?.variables) {
116116
return [];
117117
}
118-
return variablesResponse.variables.map((v: Variable) => ({
118+
const filtered = variablesResponse.variables.filter((v: Variable) => {
119+
const type = v.type?.toLowerCase();
120+
if (type === "function") {
121+
return false;
122+
}
123+
if (!type && typeof v.value === "string") {
124+
// Some adapters omit type but include a "function ..." value string.
125+
return !v.value.startsWith("function");
126+
}
127+
return true;
128+
});
129+
return filtered.map((v: Variable) => ({
119130
name: v.evaluateName || v.name,
120131
value: v.value,
121132
type: v.type,

src/extension.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@ export const activate = extension.activate;
1919
export const deactivate = extension.deactivate;
2020

2121
function registerTools(context: vscode.ExtensionContext) {
22-
context.subscriptions.push(
23-
vscode.lm.registerTool(
24-
"start_debugger_with_breakpoints",
25-
new StartDebuggerTool()
26-
),
27-
vscode.lm.registerTool(
28-
"resume_debug_session",
29-
new ResumeDebugSessionTool()
30-
),
31-
vscode.lm.registerTool("get_variables", new GetVariablesTool()),
32-
vscode.lm.registerTool("expand_variable", new ExpandVariableTool()),
33-
vscode.lm.registerTool("evaluate_expression", new EvaluateExpressionTool()),
34-
vscode.lm.registerTool("stop_debug_session", new StopDebugSessionTool()),
22+
context.subscriptions.push(
23+
vscode.lm.registerTool(
24+
"startDebugSessionWithBreakpoints",
25+
new StartDebuggerTool()
26+
),
27+
vscode.lm.registerTool(
28+
"resumeDebugSession",
29+
new ResumeDebugSessionTool()
30+
),
31+
vscode.lm.registerTool("getVariables", new GetVariablesTool()),
32+
vscode.lm.registerTool("expandVariable", new ExpandVariableTool()),
33+
vscode.lm.registerTool("evaluateExpression", new EvaluateExpressionTool()),
34+
vscode.lm.registerTool("stopDebugSession", new StopDebugSessionTool()),
3535

3636
vscode.commands.registerCommand(
3737
"copilotBreakpointDebugger.startAndWaitManual",

src/test/debugUtils.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,40 @@ describe("debugUtils - DAPHelpers", () => {
232232
assert.strictEqual(found, null, "Should not find non-existent variable");
233233
});
234234

235+
it("filters function-typed variables from capture", async () => {
236+
const functionBlockLine = 28; // console.log after numberVar/fnVar definitions
237+
const context = await startDebuggingAndWaitForStop(
238+
Object.assign({}, baseParams, {
239+
sessionName: "",
240+
breakpointConfig: {
241+
breakpoints: [
242+
{
243+
path: scriptPath,
244+
line: functionBlockLine,
245+
action: "break" as const,
246+
variableFilter: ["numberVar", "fnVar"],
247+
},
248+
],
249+
},
250+
})
251+
);
252+
253+
const activeSession = vscode.debug.activeDebugSession;
254+
assert.ok(activeSession, "No active debug session");
255+
256+
const capturedNames = context.scopeVariables.flatMap((scope) =>
257+
scope.variables.map((v) => v.name)
258+
);
259+
assert.ok(
260+
capturedNames.includes("numberVar"),
261+
"Expected numberVar to be captured"
262+
);
263+
assert.ok(
264+
!capturedNames.includes("fnVar"),
265+
"Function-typed variable fnVar should be filtered out"
266+
);
267+
});
268+
235269
it("getDebugContext works in active session", async () => {
236270
await startDebuggingAndWaitForStop(
237271
Object.assign({}, baseParams, {

test-workspace/b/test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@ console.log('Completed loop');
2121
setTimeout(() => {
2222
console.log('Exiting after idle wait.');
2323
}, 3000);
24+
25+
// Function-type variable for filtering behavior tests
26+
const numberVar = 42;
27+
const fnVar = () => numberVar;
28+
console.log('Function var test', numberVar, typeof fnVar);

0 commit comments

Comments
 (0)