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.
@@ -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
@@ -0,0 +1,3 @@
1
+
2
+ # Use bd merge for beads JSONL files
3
+ .beads/issues.jsonl merge=beads
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 parseBreakpointSpec(spec) {
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: path10.resolve(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: path10.resolve(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
- constructor(client, formatter) {
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 (const spec of specs) {
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.formatter.breakpointSet(spec.id, file, spec.line, false, spec.condition, spec.message);
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
- if (scope.name === "Locals" || scope.name === "Arguments" || scope.name === "Local") {
5454
- const vars = await this.client.variables({
5455
- variablesReference: scope.variablesReference,
5456
- count: this.options.maxCollectionItems
5457
- });
5458
- for (const v of vars.variables) {
5459
- result[v.name] = await this.expandVariable(
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.6",
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": "^1.0.0"
40
+ "vitest": "^4.0.17"
41
41
  },
42
42
  "engines": {
43
43
  "node": ">=18.0.0"