debug-run 0.5.6 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/debug-run/SKILL.md +19 -0
- package/.gitattributes +3 -0
- package/README.md +29 -0
- package/dist/index.cjs +362 -23
- package/package.json +2 -2
|
@@ -34,6 +34,25 @@ Check available adapters:
|
|
|
34
34
|
npx debug-run list-adapters
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
## Installing the Skill
|
|
38
|
+
|
|
39
|
+
To install this skill for AI coding assistants:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Install to Claude Code (~/.claude/skills/)
|
|
43
|
+
npx debug-run install-skill --claude
|
|
44
|
+
|
|
45
|
+
# Install to GitHub Copilot (~/.copilot/skills/)
|
|
46
|
+
npx debug-run install-skill --copilot
|
|
47
|
+
|
|
48
|
+
# Install to project directory (for project-specific skills)
|
|
49
|
+
npx debug-run install-skill --claude --project
|
|
50
|
+
npx debug-run install-skill --copilot --project
|
|
51
|
+
|
|
52
|
+
# Install to custom directory
|
|
53
|
+
npx debug-run install-skill --dir /path/to/skills
|
|
54
|
+
```
|
|
55
|
+
|
|
37
56
|
## Language-Specific Guides
|
|
38
57
|
|
|
39
58
|
For detailed setup, examples, and troubleshooting for each language:
|
package/.gitattributes
ADDED
package/README.md
CHANGED
|
@@ -178,6 +178,35 @@ debug-run outputs newline-delimited JSON (NDJSON) events:
|
|
|
178
178
|
{"type":"session_end","summary":{"breakpointsHit":1,"duration":1234}}
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
+
### Breakpoint Set Event (with Diagnostics)
|
|
182
|
+
|
|
183
|
+
When a breakpoint cannot be verified (e.g., source mapping issues, missing debug symbols), the event includes actionable diagnostics:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"type": "breakpoint_set",
|
|
188
|
+
"id": 1,
|
|
189
|
+
"file": "src/handler.ts",
|
|
190
|
+
"line": 45,
|
|
191
|
+
"verified": false,
|
|
192
|
+
"message": "Could not resolve source location",
|
|
193
|
+
"diagnostics": {
|
|
194
|
+
"requestedFile": "src/handler.ts",
|
|
195
|
+
"requestedLine": 45,
|
|
196
|
+
"adapterMessage": "Could not resolve source location",
|
|
197
|
+
"suggestions": [
|
|
198
|
+
"Ensure \"sourceMap\": true in tsconfig.json",
|
|
199
|
+
"Rebuild with source maps: tsc --sourceMap (or your build command)",
|
|
200
|
+
"Verify .map files exist in your output directory (e.g., dist/**/*.map)"
|
|
201
|
+
],
|
|
202
|
+
"adapterType": "node",
|
|
203
|
+
"fileExtension": ".ts"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Suggestions are context-aware based on the adapter and file type.
|
|
209
|
+
|
|
181
210
|
### Breakpoint Hit Event
|
|
182
211
|
|
|
183
212
|
```json
|
package/dist/index.cjs
CHANGED
|
@@ -3356,6 +3356,13 @@ function findVsdbg() {
|
|
|
3356
3356
|
return null;
|
|
3357
3357
|
}
|
|
3358
3358
|
function findDebugpy() {
|
|
3359
|
+
const debugpyExt = findExtension("ms-python.debugpy");
|
|
3360
|
+
if (debugpyExt) {
|
|
3361
|
+
const debugpyPath = path3.join(debugpyExt, "bundled", "libs", "debugpy");
|
|
3362
|
+
if ((0, import_node_fs2.existsSync)(debugpyPath)) {
|
|
3363
|
+
return debugpyPath;
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3359
3366
|
const pythonExt = findExtension("ms-python.python");
|
|
3360
3367
|
if (pythonExt) {
|
|
3361
3368
|
const possiblePaths = [
|
|
@@ -3517,6 +3524,16 @@ var debugpyAdapter = {
|
|
|
3517
3524
|
get args() {
|
|
3518
3525
|
return ["-m", "debugpy.adapter"];
|
|
3519
3526
|
},
|
|
3527
|
+
get env() {
|
|
3528
|
+
if (cachedSource === "vscode" && cachedDebugpyPath) {
|
|
3529
|
+
const debugpyParentDir = path5.dirname(cachedDebugpyPath);
|
|
3530
|
+
const existingPythonPath = process.env.PYTHONPATH || "";
|
|
3531
|
+
return {
|
|
3532
|
+
PYTHONPATH: existingPythonPath ? `${debugpyParentDir}:${existingPythonPath}` : debugpyParentDir
|
|
3533
|
+
};
|
|
3534
|
+
}
|
|
3535
|
+
return void 0;
|
|
3536
|
+
},
|
|
3520
3537
|
detect: async () => {
|
|
3521
3538
|
const pythonCmd = await findPythonCommand();
|
|
3522
3539
|
if (!pythonCmd) {
|
|
@@ -5189,7 +5206,7 @@ var OutputFormatter = class {
|
|
|
5189
5206
|
/**
|
|
5190
5207
|
* Emit a breakpoint_set event
|
|
5191
5208
|
*/
|
|
5192
|
-
breakpointSet(id, file, line, verified, condition, message) {
|
|
5209
|
+
breakpointSet(id, file, line, verified, condition, message, diagnostics) {
|
|
5193
5210
|
this.emit(
|
|
5194
5211
|
this.createEvent("breakpoint_set", {
|
|
5195
5212
|
id,
|
|
@@ -5197,7 +5214,8 @@ var OutputFormatter = class {
|
|
|
5197
5214
|
line,
|
|
5198
5215
|
verified,
|
|
5199
5216
|
condition,
|
|
5200
|
-
message
|
|
5217
|
+
message,
|
|
5218
|
+
diagnostics
|
|
5201
5219
|
})
|
|
5202
5220
|
);
|
|
5203
5221
|
}
|
|
@@ -5217,7 +5235,169 @@ var OutputFormatter = class {
|
|
|
5217
5235
|
|
|
5218
5236
|
// src/session/breakpoints.ts
|
|
5219
5237
|
var path10 = __toESM(require("node:path"), 1);
|
|
5220
|
-
function
|
|
5238
|
+
function resolveBreakpointPath(file, options = {}) {
|
|
5239
|
+
if (path10.isAbsolute(file)) {
|
|
5240
|
+
return file;
|
|
5241
|
+
}
|
|
5242
|
+
if (options.cwd) {
|
|
5243
|
+
return path10.resolve(options.cwd, file);
|
|
5244
|
+
}
|
|
5245
|
+
return path10.resolve(file);
|
|
5246
|
+
}
|
|
5247
|
+
function validateBreakpointSpec(spec) {
|
|
5248
|
+
const trimmed = spec.trim();
|
|
5249
|
+
if (!trimmed) {
|
|
5250
|
+
return {
|
|
5251
|
+
valid: false,
|
|
5252
|
+
error: "Breakpoint specification cannot be empty",
|
|
5253
|
+
spec
|
|
5254
|
+
};
|
|
5255
|
+
}
|
|
5256
|
+
if (!trimmed.includes(":")) {
|
|
5257
|
+
return {
|
|
5258
|
+
valid: false,
|
|
5259
|
+
error: `Invalid breakpoint format "${spec}". Expected "file:line" (e.g., "Program.cs:42")`,
|
|
5260
|
+
spec
|
|
5261
|
+
};
|
|
5262
|
+
}
|
|
5263
|
+
const match = trimmed.match(/^(.+):(\d+)(?:\?(.+)|#(\d+))?$/);
|
|
5264
|
+
if (!match) {
|
|
5265
|
+
const colonIdx = trimmed.lastIndexOf(":");
|
|
5266
|
+
if (colonIdx !== -1) {
|
|
5267
|
+
const linePartRaw = trimmed.slice(colonIdx + 1);
|
|
5268
|
+
const linePart = linePartRaw.split("?")[0].split("#")[0];
|
|
5269
|
+
if (linePart === "") {
|
|
5270
|
+
return {
|
|
5271
|
+
valid: false,
|
|
5272
|
+
error: `Missing line number in breakpoint "${spec}". Expected "file:line" (e.g., "Program.cs:42")`,
|
|
5273
|
+
spec
|
|
5274
|
+
};
|
|
5275
|
+
}
|
|
5276
|
+
if (!/^\d+$/.test(linePart)) {
|
|
5277
|
+
return {
|
|
5278
|
+
valid: false,
|
|
5279
|
+
error: `Invalid line number "${linePart}" in breakpoint "${spec}". Line must be a positive integer`,
|
|
5280
|
+
spec
|
|
5281
|
+
};
|
|
5282
|
+
}
|
|
5283
|
+
}
|
|
5284
|
+
return {
|
|
5285
|
+
valid: false,
|
|
5286
|
+
error: `Invalid breakpoint format "${spec}". Expected "file:line" (e.g., "Program.cs:42")`,
|
|
5287
|
+
spec
|
|
5288
|
+
};
|
|
5289
|
+
}
|
|
5290
|
+
const [, file, lineStr] = match;
|
|
5291
|
+
const line = parseInt(lineStr, 10);
|
|
5292
|
+
if (!file || !file.trim()) {
|
|
5293
|
+
return {
|
|
5294
|
+
valid: false,
|
|
5295
|
+
error: `Missing file path in breakpoint "${spec}". Expected "file:line" (e.g., "Program.cs:42")`,
|
|
5296
|
+
spec
|
|
5297
|
+
};
|
|
5298
|
+
}
|
|
5299
|
+
if (isNaN(line) || line < 1) {
|
|
5300
|
+
return {
|
|
5301
|
+
valid: false,
|
|
5302
|
+
error: `Invalid line number "${lineStr}" in breakpoint "${spec}". Line must be a positive integer`,
|
|
5303
|
+
spec
|
|
5304
|
+
};
|
|
5305
|
+
}
|
|
5306
|
+
return { valid: true };
|
|
5307
|
+
}
|
|
5308
|
+
function validateLogpointSpec(spec) {
|
|
5309
|
+
const trimmed = spec.trim();
|
|
5310
|
+
if (!trimmed) {
|
|
5311
|
+
return {
|
|
5312
|
+
valid: false,
|
|
5313
|
+
error: "Logpoint specification cannot be empty",
|
|
5314
|
+
spec
|
|
5315
|
+
};
|
|
5316
|
+
}
|
|
5317
|
+
if (!trimmed.includes("|")) {
|
|
5318
|
+
return {
|
|
5319
|
+
valid: false,
|
|
5320
|
+
error: `Invalid logpoint format "${spec}". Expected "file:line|message" (e.g., "Program.cs:42|value is {x}")`,
|
|
5321
|
+
spec
|
|
5322
|
+
};
|
|
5323
|
+
}
|
|
5324
|
+
const pipeIdx = trimmed.indexOf("|");
|
|
5325
|
+
const beforePipe = trimmed.slice(0, pipeIdx);
|
|
5326
|
+
if (!beforePipe.includes(":")) {
|
|
5327
|
+
return {
|
|
5328
|
+
valid: false,
|
|
5329
|
+
error: `Invalid logpoint format "${spec}". Expected "file:line|message" (e.g., "Program.cs:42|value is {x}")`,
|
|
5330
|
+
spec
|
|
5331
|
+
};
|
|
5332
|
+
}
|
|
5333
|
+
const match = trimmed.match(/^(.+):(\d+)\|(.+)$/);
|
|
5334
|
+
if (!match) {
|
|
5335
|
+
const colonIdx = beforePipe.lastIndexOf(":");
|
|
5336
|
+
if (colonIdx !== -1) {
|
|
5337
|
+
const linePart = beforePipe.slice(colonIdx + 1);
|
|
5338
|
+
if (linePart === "") {
|
|
5339
|
+
return {
|
|
5340
|
+
valid: false,
|
|
5341
|
+
error: `Missing line number in logpoint "${spec}". Expected "file:line|message"`,
|
|
5342
|
+
spec
|
|
5343
|
+
};
|
|
5344
|
+
}
|
|
5345
|
+
if (!/^\d+$/.test(linePart)) {
|
|
5346
|
+
return {
|
|
5347
|
+
valid: false,
|
|
5348
|
+
error: `Invalid line number "${linePart}" in logpoint "${spec}". Line must be a positive integer`,
|
|
5349
|
+
spec
|
|
5350
|
+
};
|
|
5351
|
+
}
|
|
5352
|
+
}
|
|
5353
|
+
return {
|
|
5354
|
+
valid: false,
|
|
5355
|
+
error: `Invalid logpoint format "${spec}". Expected "file:line|message" (e.g., "Program.cs:42|value is {x}")`,
|
|
5356
|
+
spec
|
|
5357
|
+
};
|
|
5358
|
+
}
|
|
5359
|
+
const [, file, lineStr, message] = match;
|
|
5360
|
+
const line = parseInt(lineStr, 10);
|
|
5361
|
+
if (!file || !file.trim()) {
|
|
5362
|
+
return {
|
|
5363
|
+
valid: false,
|
|
5364
|
+
error: `Missing file path in logpoint "${spec}". Expected "file:line|message"`,
|
|
5365
|
+
spec
|
|
5366
|
+
};
|
|
5367
|
+
}
|
|
5368
|
+
if (isNaN(line) || line < 1) {
|
|
5369
|
+
return {
|
|
5370
|
+
valid: false,
|
|
5371
|
+
error: `Invalid line number "${lineStr}" in logpoint "${spec}". Line must be a positive integer`,
|
|
5372
|
+
spec
|
|
5373
|
+
};
|
|
5374
|
+
}
|
|
5375
|
+
if (!message || !message.trim()) {
|
|
5376
|
+
return {
|
|
5377
|
+
valid: false,
|
|
5378
|
+
error: `Missing log message in logpoint "${spec}". Expected "file:line|message"`,
|
|
5379
|
+
spec
|
|
5380
|
+
};
|
|
5381
|
+
}
|
|
5382
|
+
return { valid: true };
|
|
5383
|
+
}
|
|
5384
|
+
function validateAllBreakpoints(breakpoints, logpoints = []) {
|
|
5385
|
+
const errors = [];
|
|
5386
|
+
for (const bp of breakpoints) {
|
|
5387
|
+
const result = validateBreakpointSpec(bp);
|
|
5388
|
+
if (!result.valid && result.error) {
|
|
5389
|
+
errors.push(result.error);
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
for (const lp of logpoints) {
|
|
5393
|
+
const result = validateLogpointSpec(lp);
|
|
5394
|
+
if (!result.valid && result.error) {
|
|
5395
|
+
errors.push(result.error);
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5398
|
+
return errors;
|
|
5399
|
+
}
|
|
5400
|
+
function parseBreakpointSpec(spec, pathOptions = {}) {
|
|
5221
5401
|
const match = spec.match(/^(.+):(\d+)(?:\?(.+)|#(\d+))?$/);
|
|
5222
5402
|
if (!match) {
|
|
5223
5403
|
throw new Error(
|
|
@@ -5230,13 +5410,13 @@ function parseBreakpointSpec(spec) {
|
|
|
5230
5410
|
throw new Error(`Invalid line number: ${lineStr}`);
|
|
5231
5411
|
}
|
|
5232
5412
|
return {
|
|
5233
|
-
file:
|
|
5413
|
+
file: resolveBreakpointPath(file, pathOptions),
|
|
5234
5414
|
line,
|
|
5235
5415
|
condition: condition || void 0,
|
|
5236
5416
|
hitCondition: hitCount || void 0
|
|
5237
5417
|
};
|
|
5238
5418
|
}
|
|
5239
|
-
function parseLogpointSpec(spec) {
|
|
5419
|
+
function parseLogpointSpec(spec, pathOptions = {}) {
|
|
5240
5420
|
const match = spec.match(/^(.+):(\d+)\|(.+)$/);
|
|
5241
5421
|
if (!match) {
|
|
5242
5422
|
throw new Error(`Invalid logpoint format: "${spec}". Expected "file:line|log message"`);
|
|
@@ -5247,7 +5427,7 @@ function parseLogpointSpec(spec) {
|
|
|
5247
5427
|
throw new Error(`Invalid line number: ${lineStr}`);
|
|
5248
5428
|
}
|
|
5249
5429
|
return {
|
|
5250
|
-
file:
|
|
5430
|
+
file: resolveBreakpointPath(file, pathOptions),
|
|
5251
5431
|
line,
|
|
5252
5432
|
logMessage: logMessage.trim()
|
|
5253
5433
|
};
|
|
@@ -5257,15 +5437,19 @@ var BreakpointManager = class {
|
|
|
5257
5437
|
formatter;
|
|
5258
5438
|
breakpoints = /* @__PURE__ */ new Map();
|
|
5259
5439
|
nextId = 1;
|
|
5260
|
-
|
|
5440
|
+
pathOptions;
|
|
5441
|
+
adapterType;
|
|
5442
|
+
constructor(client, formatter, options = {}) {
|
|
5261
5443
|
this.client = client;
|
|
5262
5444
|
this.formatter = formatter;
|
|
5445
|
+
this.pathOptions = options;
|
|
5446
|
+
this.adapterType = options.adapterType;
|
|
5263
5447
|
}
|
|
5264
5448
|
/**
|
|
5265
5449
|
* Add a breakpoint from a spec string
|
|
5266
5450
|
*/
|
|
5267
5451
|
addBreakpoint(spec) {
|
|
5268
|
-
const bp = parseBreakpointSpec(spec);
|
|
5452
|
+
const bp = parseBreakpointSpec(spec, this.pathOptions);
|
|
5269
5453
|
this.addBreakpointSpec(bp);
|
|
5270
5454
|
return bp;
|
|
5271
5455
|
}
|
|
@@ -5273,7 +5457,7 @@ var BreakpointManager = class {
|
|
|
5273
5457
|
* Add a logpoint from a spec string
|
|
5274
5458
|
*/
|
|
5275
5459
|
addLogpoint(spec) {
|
|
5276
|
-
const lp = parseLogpointSpec(spec);
|
|
5460
|
+
const lp = parseLogpointSpec(spec, this.pathOptions);
|
|
5277
5461
|
this.addBreakpointSpec(lp);
|
|
5278
5462
|
return lp;
|
|
5279
5463
|
}
|
|
@@ -5306,6 +5490,7 @@ var BreakpointManager = class {
|
|
|
5306
5490
|
hitCondition: spec.hitCondition,
|
|
5307
5491
|
logMessage: spec.logMessage
|
|
5308
5492
|
}));
|
|
5493
|
+
const requestedLines = specs.map((spec) => spec.line);
|
|
5309
5494
|
try {
|
|
5310
5495
|
const response = await this.client.setBreakpoints({
|
|
5311
5496
|
source: { path: file },
|
|
@@ -5318,22 +5503,34 @@ var BreakpointManager = class {
|
|
|
5318
5503
|
specs[i].verified = bp.verified;
|
|
5319
5504
|
specs[i].message = bp.message;
|
|
5320
5505
|
specs[i].line = bp.line ?? specs[i].line;
|
|
5506
|
+
const diagnostics = !bp.verified ? this.generateDiagnostics(file, requestedLines[i], bp.message) : void 0;
|
|
5321
5507
|
this.formatter.breakpointSet(
|
|
5322
5508
|
specs[i].id,
|
|
5323
5509
|
file,
|
|
5324
5510
|
specs[i].line,
|
|
5325
5511
|
specs[i].verified,
|
|
5326
5512
|
specs[i].condition,
|
|
5327
|
-
specs[i].message
|
|
5513
|
+
specs[i].message,
|
|
5514
|
+
diagnostics
|
|
5328
5515
|
);
|
|
5329
5516
|
}
|
|
5330
5517
|
}
|
|
5331
5518
|
} catch (error) {
|
|
5332
|
-
for (
|
|
5519
|
+
for (let i = 0; i < specs.length; i++) {
|
|
5520
|
+
const spec = specs[i];
|
|
5333
5521
|
spec.id = this.nextId++;
|
|
5334
5522
|
spec.verified = false;
|
|
5335
5523
|
spec.message = error instanceof Error ? error.message : "Failed to set breakpoint";
|
|
5336
|
-
this.
|
|
5524
|
+
const diagnostics = this.generateDiagnostics(file, requestedLines[i], spec.message);
|
|
5525
|
+
this.formatter.breakpointSet(
|
|
5526
|
+
spec.id,
|
|
5527
|
+
file,
|
|
5528
|
+
spec.line,
|
|
5529
|
+
false,
|
|
5530
|
+
spec.condition,
|
|
5531
|
+
spec.message,
|
|
5532
|
+
diagnostics
|
|
5533
|
+
);
|
|
5337
5534
|
}
|
|
5338
5535
|
}
|
|
5339
5536
|
}
|
|
@@ -5363,7 +5560,103 @@ var BreakpointManager = class {
|
|
|
5363
5560
|
getHitCount() {
|
|
5364
5561
|
return 0;
|
|
5365
5562
|
}
|
|
5563
|
+
/**
|
|
5564
|
+
* Generate diagnostics for an unverified breakpoint
|
|
5565
|
+
*/
|
|
5566
|
+
generateDiagnostics(requestedFile, requestedLine, adapterMessage) {
|
|
5567
|
+
const ext = path10.extname(requestedFile).toLowerCase();
|
|
5568
|
+
const suggestions = getBreakpointSuggestions(this.adapterType, ext, adapterMessage);
|
|
5569
|
+
return {
|
|
5570
|
+
requestedFile,
|
|
5571
|
+
requestedLine,
|
|
5572
|
+
adapterMessage,
|
|
5573
|
+
suggestions,
|
|
5574
|
+
adapterType: this.adapterType,
|
|
5575
|
+
fileExtension: ext || void 0
|
|
5576
|
+
};
|
|
5577
|
+
}
|
|
5366
5578
|
};
|
|
5579
|
+
function normalizeAdapterType(adapterType) {
|
|
5580
|
+
if (!adapterType) return void 0;
|
|
5581
|
+
const lower = adapterType.toLowerCase();
|
|
5582
|
+
if (["dotnet", "coreclr", "vsdbg", "netcoredbg"].includes(lower)) {
|
|
5583
|
+
return "coreclr";
|
|
5584
|
+
}
|
|
5585
|
+
if (["node", "nodejs", "javascript", "js", "typescript", "ts"].includes(lower)) {
|
|
5586
|
+
return "node";
|
|
5587
|
+
}
|
|
5588
|
+
if (["debugpy", "python", "py"].includes(lower)) {
|
|
5589
|
+
return "python";
|
|
5590
|
+
}
|
|
5591
|
+
if (["lldb", "codelldb", "cpp", "c", "rust"].includes(lower)) {
|
|
5592
|
+
return "lldb";
|
|
5593
|
+
}
|
|
5594
|
+
return lower;
|
|
5595
|
+
}
|
|
5596
|
+
function getBreakpointSuggestions(adapterType, fileExtension, adapterMessage) {
|
|
5597
|
+
const suggestions = [];
|
|
5598
|
+
const normalizedAdapter = normalizeAdapterType(adapterType);
|
|
5599
|
+
const ext = fileExtension.toLowerCase();
|
|
5600
|
+
const msgLower = (adapterMessage || "").toLowerCase();
|
|
5601
|
+
const isSourceMapIssue = msgLower.includes("source map") || msgLower.includes("sourcemap") || msgLower.includes("cannot find");
|
|
5602
|
+
const isPathIssue = msgLower.includes("not found") || msgLower.includes("cannot find file") || msgLower.includes("does not exist");
|
|
5603
|
+
if (normalizedAdapter === "node") {
|
|
5604
|
+
if (ext === ".ts" || ext === ".tsx") {
|
|
5605
|
+
suggestions.push('Ensure "sourceMap": true in tsconfig.json');
|
|
5606
|
+
suggestions.push("Rebuild with source maps: tsc --sourceMap (or your build command)");
|
|
5607
|
+
suggestions.push("Verify .map files exist in your output directory (e.g., dist/**/*.map)");
|
|
5608
|
+
suggestions.push(
|
|
5609
|
+
'Check that "sourceMaps": true is set in your debug config and "outFiles" points to your built JS files'
|
|
5610
|
+
);
|
|
5611
|
+
} else if (ext === ".js" || ext === ".mjs" || ext === ".cjs") {
|
|
5612
|
+
suggestions.push(
|
|
5613
|
+
"Confirm you are setting the breakpoint in the executed file (built output vs source)"
|
|
5614
|
+
);
|
|
5615
|
+
if (isSourceMapIssue) {
|
|
5616
|
+
suggestions.push(
|
|
5617
|
+
"If using bundlers (webpack/esbuild/vite), ensure source maps are generated and accessible"
|
|
5618
|
+
);
|
|
5619
|
+
suggestions.push("Verify source map files (.map) are not excluded from your output");
|
|
5620
|
+
}
|
|
5621
|
+
}
|
|
5622
|
+
} else if (normalizedAdapter === "coreclr") {
|
|
5623
|
+
if (ext === ".cs") {
|
|
5624
|
+
suggestions.push("Build in Debug configuration to ensure PDB files are produced");
|
|
5625
|
+
suggestions.push("Clean and rebuild to refresh symbols: dotnet clean && dotnet build");
|
|
5626
|
+
suggestions.push(
|
|
5627
|
+
"Confirm the running binary matches the source version (stale builds can break mapping)"
|
|
5628
|
+
);
|
|
5629
|
+
suggestions.push("Ensure PDB files are deployed alongside the DLL");
|
|
5630
|
+
}
|
|
5631
|
+
} else if (normalizedAdapter === "python") {
|
|
5632
|
+
if (ext === ".py") {
|
|
5633
|
+
suggestions.push("Confirm the Python interpreter and working directory match your project");
|
|
5634
|
+
suggestions.push(
|
|
5635
|
+
"If debugging remotely or in containers, configure path mappings (localRoot/remoteRoot)"
|
|
5636
|
+
);
|
|
5637
|
+
suggestions.push(
|
|
5638
|
+
"Verify you are setting the breakpoint in code that actually executes (imported module vs different copy)"
|
|
5639
|
+
);
|
|
5640
|
+
}
|
|
5641
|
+
} else if (normalizedAdapter === "lldb") {
|
|
5642
|
+
if ([".c", ".cpp", ".cc", ".cxx", ".h", ".hpp", ".rs", ".m", ".mm"].includes(ext)) {
|
|
5643
|
+
suggestions.push("Compile with debug symbols (-g) and avoid stripping binaries");
|
|
5644
|
+
suggestions.push("Ensure the running binary matches the source used to compile");
|
|
5645
|
+
suggestions.push("For Rust, build with: cargo build (debug mode, not --release)");
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
if (isPathIssue) {
|
|
5649
|
+
suggestions.push("Check the file path is correct and exists relative to the provided cwd");
|
|
5650
|
+
}
|
|
5651
|
+
if (suggestions.length === 0) {
|
|
5652
|
+
suggestions.push("Check the file path is correct and exists relative to the provided cwd");
|
|
5653
|
+
suggestions.push(
|
|
5654
|
+
"Ensure the running program corresponds to this source (no stale build artifacts)"
|
|
5655
|
+
);
|
|
5656
|
+
suggestions.push("Verify the file has been compiled/built with debug information");
|
|
5657
|
+
}
|
|
5658
|
+
return suggestions;
|
|
5659
|
+
}
|
|
5367
5660
|
|
|
5368
5661
|
// src/session/variables.ts
|
|
5369
5662
|
var BLOCKED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
@@ -5437,7 +5730,8 @@ var VariableInspector = class {
|
|
|
5437
5730
|
timeout: options.timeout ?? 5e3,
|
|
5438
5731
|
deduplicateByContent: options.deduplicateByContent ?? true,
|
|
5439
5732
|
compactServices: options.compactServices ?? true,
|
|
5440
|
-
omitNullProperties: options.omitNullProperties ?? true
|
|
5733
|
+
omitNullProperties: options.omitNullProperties ?? true,
|
|
5734
|
+
captureClosures: options.captureClosures ?? false
|
|
5441
5735
|
};
|
|
5442
5736
|
}
|
|
5443
5737
|
/**
|
|
@@ -5449,14 +5743,38 @@ var VariableInspector = class {
|
|
|
5449
5743
|
const contentHashes = /* @__PURE__ */ new Map();
|
|
5450
5744
|
try {
|
|
5451
5745
|
const scopesResponse = await this.client.scopes({ frameId });
|
|
5746
|
+
let foundPrimaryLocals = false;
|
|
5452
5747
|
for (const scope of scopesResponse.scopes) {
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5748
|
+
const scopeLower = scope.name.toLowerCase();
|
|
5749
|
+
const isPrimaryLocals = scopeLower === "locals" || scopeLower === "local" || scopeLower.startsWith("local:") || scopeLower.startsWith("local ");
|
|
5750
|
+
const isArguments = scopeLower === "arguments" || scopeLower.startsWith("arg");
|
|
5751
|
+
const isBlockOrClosure = scopeLower === "block" || scopeLower === "closure";
|
|
5752
|
+
const shouldInclude = isPrimaryLocals || isArguments || isBlockOrClosure && (this.options.captureClosures || !foundPrimaryLocals);
|
|
5753
|
+
if (!shouldInclude) continue;
|
|
5754
|
+
if (isPrimaryLocals) {
|
|
5755
|
+
foundPrimaryLocals = true;
|
|
5756
|
+
}
|
|
5757
|
+
const vars = await this.client.variables({
|
|
5758
|
+
variablesReference: scope.variablesReference,
|
|
5759
|
+
count: this.options.maxCollectionItems
|
|
5760
|
+
});
|
|
5761
|
+
for (const v of vars.variables) {
|
|
5762
|
+
let varName = v.name;
|
|
5763
|
+
if (varName in result) {
|
|
5764
|
+
const existingValue = result[varName];
|
|
5765
|
+
const newValue = await this.expandVariable(
|
|
5766
|
+
v,
|
|
5767
|
+
this.options.maxDepth,
|
|
5768
|
+
visited,
|
|
5769
|
+
contentHashes,
|
|
5770
|
+
v.name
|
|
5771
|
+
);
|
|
5772
|
+
if (!this.valuesEqual(existingValue, newValue)) {
|
|
5773
|
+
varName = `${v.name} (${scope.name})`;
|
|
5774
|
+
result[varName] = newValue;
|
|
5775
|
+
}
|
|
5776
|
+
} else {
|
|
5777
|
+
result[varName] = await this.expandVariable(
|
|
5460
5778
|
v,
|
|
5461
5779
|
this.options.maxDepth,
|
|
5462
5780
|
visited,
|
|
@@ -6131,7 +6449,7 @@ var DebugSession = class {
|
|
|
6131
6449
|
command: this.config.adapter.command,
|
|
6132
6450
|
args: this.config.adapter.args,
|
|
6133
6451
|
cwd: this.config.cwd,
|
|
6134
|
-
env: this.config.env,
|
|
6452
|
+
env: { ...this.config.adapter.env, ...this.config.env },
|
|
6135
6453
|
port: this.config.adapter.socketPort,
|
|
6136
6454
|
timeout: this.config.timeout
|
|
6137
6455
|
});
|
|
@@ -6140,7 +6458,7 @@ var DebugSession = class {
|
|
|
6140
6458
|
command: this.config.adapter.command,
|
|
6141
6459
|
args: this.config.adapter.args,
|
|
6142
6460
|
cwd: this.config.cwd,
|
|
6143
|
-
env: this.config.env,
|
|
6461
|
+
env: { ...this.config.adapter.env, ...this.config.env },
|
|
6144
6462
|
timeout: this.config.timeout
|
|
6145
6463
|
});
|
|
6146
6464
|
}
|
|
@@ -6150,7 +6468,11 @@ var DebugSession = class {
|
|
|
6150
6468
|
await this.client.initialize({
|
|
6151
6469
|
adapterID: this.config.adapter.id
|
|
6152
6470
|
});
|
|
6153
|
-
this.breakpointManager = new BreakpointManager(this.client, this.formatter
|
|
6471
|
+
this.breakpointManager = new BreakpointManager(this.client, this.formatter, {
|
|
6472
|
+
cwd: this.config.cwd,
|
|
6473
|
+
programPath: this.config.program,
|
|
6474
|
+
adapterType: this.config.adapter.name
|
|
6475
|
+
});
|
|
6154
6476
|
this.variableInspector = new VariableInspector(this.client, {
|
|
6155
6477
|
compactServices: !this.config.expandServices,
|
|
6156
6478
|
omitNullProperties: !this.config.showNullProps,
|
|
@@ -6950,6 +7272,16 @@ function createCli() {
|
|
|
6950
7272
|
console.error(`Available adapters: ${getAdapterNames().join(", ")}`);
|
|
6951
7273
|
process.exit(1);
|
|
6952
7274
|
}
|
|
7275
|
+
const breakpointErrors = validateAllBreakpoints(
|
|
7276
|
+
options.breakpoint || [],
|
|
7277
|
+
options.logpoint || []
|
|
7278
|
+
);
|
|
7279
|
+
if (breakpointErrors.length > 0) {
|
|
7280
|
+
for (const error of breakpointErrors) {
|
|
7281
|
+
console.error(`Error: ${error}`);
|
|
7282
|
+
}
|
|
7283
|
+
process.exit(1);
|
|
7284
|
+
}
|
|
6953
7285
|
await runDebugSession({ ...options, program: programPath, adapter: options.adapter });
|
|
6954
7286
|
}
|
|
6955
7287
|
);
|
|
@@ -6984,6 +7316,13 @@ async function runTestDebugSession(options) {
|
|
|
6984
7316
|
console.error('Example: -b "path/to/TestFile.cs:42"');
|
|
6985
7317
|
process.exit(1);
|
|
6986
7318
|
}
|
|
7319
|
+
const breakpointErrors = validateAllBreakpoints(options.breakpoint || [], options.logpoint || []);
|
|
7320
|
+
if (breakpointErrors.length > 0) {
|
|
7321
|
+
for (const error of breakpointErrors) {
|
|
7322
|
+
console.error(`Error: ${error}`);
|
|
7323
|
+
}
|
|
7324
|
+
process.exit(1);
|
|
7325
|
+
}
|
|
6987
7326
|
console.error(`Starting test runner for: ${options.testProject}`);
|
|
6988
7327
|
if (options.testFilter) {
|
|
6989
7328
|
console.error(`Test filter: ${options.testFilter}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "debug-run",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "CLI tool enabling AI agents to programmatically debug code via DAP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"prettier": "^3.8.0",
|
|
38
38
|
"tsx": "^4.21.0",
|
|
39
39
|
"typescript": "^5.3.0",
|
|
40
|
-
"vitest": "^
|
|
40
|
+
"vitest": "^4.0.17"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=18.0.0"
|