debug-run 0.1.0 → 0.5.1

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.
@@ -0,0 +1,4 @@
1
+ dist/
2
+ node_modules/
3
+ samples/
4
+ *.md
package/dist/index.cjs CHANGED
@@ -961,7 +961,7 @@ var require_command = __commonJS({
961
961
  var EventEmitter5 = require("node:events").EventEmitter;
962
962
  var childProcess = require("node:child_process");
963
963
  var path12 = require("node:path");
964
- var fs2 = require("node:fs");
964
+ var fs3 = require("node:fs");
965
965
  var process2 = require("node:process");
966
966
  var { Argument: Argument2, humanReadableArgName } = require_argument();
967
967
  var { CommanderError: CommanderError2 } = require_error();
@@ -1894,10 +1894,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
1894
1894
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1895
1895
  function findFile(baseDir, baseName) {
1896
1896
  const localBin = path12.resolve(baseDir, baseName);
1897
- if (fs2.existsSync(localBin)) return localBin;
1897
+ if (fs3.existsSync(localBin)) return localBin;
1898
1898
  if (sourceExt.includes(path12.extname(baseName))) return void 0;
1899
1899
  const foundExt = sourceExt.find(
1900
- (ext) => fs2.existsSync(`${localBin}${ext}`)
1900
+ (ext) => fs3.existsSync(`${localBin}${ext}`)
1901
1901
  );
1902
1902
  if (foundExt) return `${localBin}${foundExt}`;
1903
1903
  return void 0;
@@ -1909,7 +1909,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1909
1909
  if (this._scriptPath) {
1910
1910
  let resolvedScriptPath;
1911
1911
  try {
1912
- resolvedScriptPath = fs2.realpathSync(this._scriptPath);
1912
+ resolvedScriptPath = fs3.realpathSync(this._scriptPath);
1913
1913
  } catch (err) {
1914
1914
  resolvedScriptPath = this._scriptPath;
1915
1915
  }
@@ -3021,7 +3021,7 @@ var require_commander = __commonJS({
3021
3021
  });
3022
3022
 
3023
3023
  // src/cli.ts
3024
- var fs = __toESM(require("node:fs"), 1);
3024
+ var fs2 = __toESM(require("node:fs"), 1);
3025
3025
 
3026
3026
  // node_modules/commander/esm.mjs
3027
3027
  var import_index = __toESM(require_commander(), 1);
@@ -3315,9 +3315,7 @@ function findVsdbg() {
3315
3315
  path3.join(csharpExt, ".debugger", vsdbgDir, "vsdbg.exe")
3316
3316
  );
3317
3317
  }
3318
- possiblePaths.push(
3319
- path3.join(csharpExt, "debugAdapters", "vsdbg", "vsdbg")
3320
- );
3318
+ possiblePaths.push(path3.join(csharpExt, "debugAdapters", "vsdbg", "vsdbg"));
3321
3319
  for (const p of possiblePaths) {
3322
3320
  if ((0, import_node_fs2.existsSync)(p)) {
3323
3321
  return p;
@@ -3471,10 +3469,7 @@ Or install the C# Dev Kit extension for additional features.
3471
3469
  // (testhost runs in optimized mode, breakpoints won't hit otherwise)
3472
3470
  justMyCode: false
3473
3471
  }),
3474
- exceptionFilters: [
3475
- "all",
3476
- "user-unhandled"
3477
- ]
3472
+ exceptionFilters: ["all", "user-unhandled"]
3478
3473
  };
3479
3474
 
3480
3475
  // src/adapters/debugpy.ts
@@ -3690,6 +3685,24 @@ Alternative options:
3690
3685
 
3691
3686
  // src/adapters/lldb.ts
3692
3687
  var path7 = __toESM(require("node:path"), 1);
3688
+ var fs = __toESM(require("node:fs"), 1);
3689
+ function findHomebrewLLDB() {
3690
+ if (process.platform !== "darwin") {
3691
+ return null;
3692
+ }
3693
+ const homebrewPaths = [
3694
+ "/opt/homebrew/opt/llvm/bin/lldb-dap",
3695
+ // Apple Silicon
3696
+ "/usr/local/opt/llvm/bin/lldb-dap"
3697
+ // Intel Mac
3698
+ ];
3699
+ for (const p of homebrewPaths) {
3700
+ if (fs.existsSync(p)) {
3701
+ return p;
3702
+ }
3703
+ }
3704
+ return null;
3705
+ }
3693
3706
  var cachedPath4 = null;
3694
3707
  var cachedType2 = null;
3695
3708
  var lldbAdapter = {
@@ -3717,6 +3730,12 @@ var lldbAdapter = {
3717
3730
  cachedType2 = "lldb-dap";
3718
3731
  return lldbVscode;
3719
3732
  }
3733
+ const homebrewLldb = findHomebrewLLDB();
3734
+ if (homebrewLldb) {
3735
+ cachedPath4 = homebrewLldb;
3736
+ cachedType2 = "lldb-dap";
3737
+ return homebrewLldb;
3738
+ }
3720
3739
  const codeLldbPath = findCodeLLDB();
3721
3740
  if (codeLldbPath) {
3722
3741
  cachedPath4 = codeLldbPath;
@@ -3730,18 +3749,21 @@ LLDB debugger not found.
3730
3749
 
3731
3750
  Options:
3732
3751
 
3733
- 1. Install LLVM/LLDB (includes lldb-dap):
3734
- - macOS: xcode-select --install (or brew install llvm)
3735
- - Ubuntu/Debian: apt install lldb
3736
- - Fedora: dnf install lldb
3737
- - The lldb-dap binary should be in your PATH
3752
+ 1. Install LLVM via Homebrew (macOS, recommended):
3753
+ brew install llvm
3754
+ (debug-run auto-detects Homebrew LLVM, no PATH changes needed)
3738
3755
 
3739
3756
  2. Install CodeLLDB VS Code extension:
3740
3757
  - Open VS Code
3741
3758
  - Install "CodeLLDB" extension (vadimcn.vscode-lldb)
3742
3759
  - debug-run will use the bundled adapter
3743
3760
 
3744
- 3. Build from source:
3761
+ 3. Install LLVM system-wide:
3762
+ - Ubuntu/Debian: apt install lldb llvm
3763
+ - Fedora: dnf install lldb llvm
3764
+ - Ensure lldb-dap is in your PATH
3765
+
3766
+ 4. Build from source:
3745
3767
  - Download LLVM from https://releases.llvm.org
3746
3768
  - Build with -DLLDB_ENABLE_DAP=ON
3747
3769
  `.trim(),
@@ -3849,10 +3871,7 @@ var dotnetAdapter = {
3849
3871
  request: "attach",
3850
3872
  processId: options.pid
3851
3873
  }),
3852
- exceptionFilters: [
3853
- "all",
3854
- "user-unhandled"
3855
- ]
3874
+ exceptionFilters: ["all", "user-unhandled"]
3856
3875
  };
3857
3876
  var adapters = /* @__PURE__ */ new Map([
3858
3877
  // Smart .NET adapter (tries vsdbg, then netcoredbg)
@@ -3915,9 +3934,7 @@ var DapTransport = class extends import_node_events.EventEmitter {
3915
3934
  });
3916
3935
  process2.on("exit", (code, signal) => {
3917
3936
  this.closed = true;
3918
- this.rejectAllPending(
3919
- new Error(`Debug adapter exited with code ${code}, signal ${signal}`)
3920
- );
3937
+ this.rejectAllPending(new Error(`Debug adapter exited with code ${code}, signal ${signal}`));
3921
3938
  this.emit("exit", code, signal);
3922
3939
  });
3923
3940
  process2.on("error", (error) => {
@@ -4081,8 +4098,29 @@ var VSDA_PATHS = [
4081
4098
  "/usr/share/code/resources/app/node_modules.asar.unpacked/vsda/build/Release/vsda.node",
4082
4099
  "/usr/share/code-insiders/resources/app/node_modules.asar.unpacked/vsda/build/Release/vsda.node",
4083
4100
  // Windows (common install locations)
4084
- path9.join(process.env.LOCALAPPDATA || "", "Programs", "Microsoft VS Code", "resources", "app", "node_modules.asar.unpacked", "vsda", "build", "Release", "vsda.node"),
4085
- path9.join(process.env.PROGRAMFILES || "", "Microsoft VS Code", "resources", "app", "node_modules.asar.unpacked", "vsda", "build", "Release", "vsda.node")
4101
+ path9.join(
4102
+ process.env.LOCALAPPDATA || "",
4103
+ "Programs",
4104
+ "Microsoft VS Code",
4105
+ "resources",
4106
+ "app",
4107
+ "node_modules.asar.unpacked",
4108
+ "vsda",
4109
+ "build",
4110
+ "Release",
4111
+ "vsda.node"
4112
+ ),
4113
+ path9.join(
4114
+ process.env.PROGRAMFILES || "",
4115
+ "Microsoft VS Code",
4116
+ "resources",
4117
+ "app",
4118
+ "node_modules.asar.unpacked",
4119
+ "vsda",
4120
+ "build",
4121
+ "Release",
4122
+ "vsda.node"
4123
+ )
4086
4124
  ];
4087
4125
  var vsdaModule = null;
4088
4126
  var vsdaLoadAttempted = false;
@@ -4096,7 +4134,17 @@ function loadVsda() {
4096
4134
  // Cursor (VS Code fork) on macOS
4097
4135
  "/Applications/Cursor.app/Contents/Resources/app/node_modules.asar.unpacked/vsda/build/Release/vsda.node",
4098
4136
  // User-installed VS Code on Linux
4099
- path9.join(home, ".vscode-server", "bin", "*", "node_modules.asar.unpacked", "vsda", "build", "Release", "vsda.node")
4137
+ path9.join(
4138
+ home,
4139
+ ".vscode-server",
4140
+ "bin",
4141
+ "*",
4142
+ "node_modules.asar.unpacked",
4143
+ "vsda",
4144
+ "build",
4145
+ "Release",
4146
+ "vsda.node"
4147
+ )
4100
4148
  ];
4101
4149
  const allPaths = [...VSDA_PATHS, ...additionalPaths];
4102
4150
  for (const vsdaPath of allPaths) {
@@ -4485,9 +4533,7 @@ var SocketDapTransport = class extends import_node_events3.EventEmitter {
4485
4533
  return new Promise((resolve10, reject) => {
4486
4534
  const timeout = setTimeout(() => {
4487
4535
  this.pendingRequests.delete(seq);
4488
- reject(
4489
- new Error(`Request '${command}' timed out after ${this.requestTimeout}ms`)
4490
- );
4536
+ reject(new Error(`Request '${command}' timed out after ${this.requestTimeout}ms`));
4491
4537
  }, this.requestTimeout);
4492
4538
  this.pendingRequests.set(seq, {
4493
4539
  resolve: (response) => {
@@ -4604,7 +4650,10 @@ var SocketDapTransport = class extends import_node_events3.EventEmitter {
4604
4650
  break;
4605
4651
  case "request":
4606
4652
  if (process.env.DEBUG_DAP) {
4607
- console.error(`[DAP reverse request] ${message.command}:`, JSON.stringify(message.arguments, null, 2));
4653
+ console.error(
4654
+ `[DAP reverse request] ${message.command}:`,
4655
+ JSON.stringify(message.arguments, null, 2)
4656
+ );
4608
4657
  }
4609
4658
  this.emit("reverseRequest", message);
4610
4659
  this.emit(`reverseRequest:${message.command}`, message);
@@ -4700,25 +4749,34 @@ var SocketDapClient = class extends import_node_events4.EventEmitter {
4700
4749
  this.transport.on("event", (event) => {
4701
4750
  this.emit("event", event);
4702
4751
  });
4703
- this.transport.on("reverseRequest:startDebugging", async (request) => {
4704
- const childConfig = request.arguments?.configuration || {};
4705
- if (process.env.DEBUG_DAP) {
4706
- console.error("[DAP] Creating child session for js-debug");
4707
- console.error("[DAP] Child config:", JSON.stringify(childConfig));
4708
- }
4709
- try {
4710
- await this.createChildSession(childConfig);
4711
- this.transport.sendResponse(request.seq, "startDebugging", true);
4752
+ this.transport.on(
4753
+ "reverseRequest:startDebugging",
4754
+ async (request) => {
4755
+ const childConfig = request.arguments?.configuration || {};
4712
4756
  if (process.env.DEBUG_DAP) {
4713
- console.error("[DAP] Child session created successfully");
4757
+ console.error("[DAP] Creating child session for js-debug");
4758
+ console.error("[DAP] Child config:", JSON.stringify(childConfig));
4714
4759
  }
4715
- } catch (error) {
4716
- if (process.env.DEBUG_DAP) {
4717
- console.error("[DAP] Child session creation failed:", error);
4760
+ try {
4761
+ await this.createChildSession(childConfig);
4762
+ this.transport.sendResponse(request.seq, "startDebugging", true);
4763
+ if (process.env.DEBUG_DAP) {
4764
+ console.error("[DAP] Child session created successfully");
4765
+ }
4766
+ } catch (error) {
4767
+ if (process.env.DEBUG_DAP) {
4768
+ console.error("[DAP] Child session creation failed:", error);
4769
+ }
4770
+ this.transport.sendResponse(
4771
+ request.seq,
4772
+ "startDebugging",
4773
+ false,
4774
+ void 0,
4775
+ String(error)
4776
+ );
4718
4777
  }
4719
- this.transport.sendResponse(request.seq, "startDebugging", false, void 0, String(error));
4720
4778
  }
4721
- });
4779
+ );
4722
4780
  this.on("serverOutput", (data) => {
4723
4781
  if (process.env.DEBUG) {
4724
4782
  console.error("[js-debug server]", data);
@@ -4733,7 +4791,7 @@ var SocketDapClient = class extends import_node_events4.EventEmitter {
4733
4791
  }
4734
4792
  /**
4735
4793
  * Initialize the debug session
4736
- *
4794
+ *
4737
4795
  * Note: Unlike stdio-based adapters, js-debug sends the 'initialized' event
4738
4796
  * after the launch request, not after initialize response. So we don't wait
4739
4797
  * for it here.
@@ -5025,7 +5083,10 @@ var SocketDapClient = class extends import_node_events4.EventEmitter {
5025
5083
  if (process.env.DEBUG_DAP) {
5026
5084
  console.error("[DAP child] Setting breakpoints for:", bp.source?.path);
5027
5085
  }
5028
- const response = await this.childTransport.sendRequest("setBreakpoints", bp);
5086
+ const response = await this.childTransport.sendRequest(
5087
+ "setBreakpoints",
5088
+ bp
5089
+ );
5029
5090
  if (process.env.DEBUG_DAP) {
5030
5091
  console.error("[DAP child] Breakpoint response:", JSON.stringify(response, null, 2));
5031
5092
  }
@@ -5178,9 +5239,7 @@ function parseBreakpointSpec(spec) {
5178
5239
  function parseLogpointSpec(spec) {
5179
5240
  const match = spec.match(/^(.+):(\d+)\|(.+)$/);
5180
5241
  if (!match) {
5181
- throw new Error(
5182
- `Invalid logpoint format: "${spec}". Expected "file:line|log message"`
5183
- );
5242
+ throw new Error(`Invalid logpoint format: "${spec}". Expected "file:line|log message"`);
5184
5243
  }
5185
5244
  const [, file, lineStr, logMessage] = match;
5186
5245
  const line = parseInt(lineStr, 10);
@@ -5274,14 +5333,7 @@ var BreakpointManager = class {
5274
5333
  spec.id = this.nextId++;
5275
5334
  spec.verified = false;
5276
5335
  spec.message = error instanceof Error ? error.message : "Failed to set breakpoint";
5277
- this.formatter.breakpointSet(
5278
- spec.id,
5279
- file,
5280
- spec.line,
5281
- false,
5282
- spec.condition,
5283
- spec.message
5284
- );
5336
+ this.formatter.breakpointSet(spec.id, file, spec.line, false, spec.condition, spec.message);
5285
5337
  }
5286
5338
  }
5287
5339
  }
@@ -5404,7 +5456,13 @@ var VariableInspector = class {
5404
5456
  count: this.options.maxCollectionItems
5405
5457
  });
5406
5458
  for (const v of vars.variables) {
5407
- result[v.name] = await this.expandVariable(v, this.options.maxDepth, visited, contentHashes, v.name);
5459
+ result[v.name] = await this.expandVariable(
5460
+ v,
5461
+ this.options.maxDepth,
5462
+ visited,
5463
+ contentHashes,
5464
+ v.name
5465
+ );
5408
5466
  }
5409
5467
  }
5410
5468
  }
@@ -5455,21 +5513,31 @@ var VariableInspector = class {
5455
5513
  (child) => !this.isBlockedProperty(child.name)
5456
5514
  );
5457
5515
  if (this.options.omitNullProperties) {
5458
- filteredChildren = filteredChildren.filter(
5459
- (child) => !this.isNullValue(child.value)
5460
- );
5516
+ filteredChildren = filteredChildren.filter((child) => !this.isNullValue(child.value));
5461
5517
  }
5462
5518
  if (this.isCollection(v.type, filteredChildren)) {
5463
5519
  variable.value = {
5464
5520
  type: v.type || "collection",
5465
5521
  count: this.getCollectionCount(v, filteredChildren.length),
5466
- items: await this.expandCollection(filteredChildren, depth - 1, visited, contentHashes, currentPath)
5522
+ items: await this.expandCollection(
5523
+ filteredChildren,
5524
+ depth - 1,
5525
+ visited,
5526
+ contentHashes,
5527
+ currentPath
5528
+ )
5467
5529
  };
5468
5530
  } else {
5469
5531
  const obj = {};
5470
5532
  for (const child of filteredChildren) {
5471
5533
  const childPath = currentPath ? `${currentPath}.${child.name}` : child.name;
5472
- obj[child.name] = await this.expandVariable(child, depth - 1, visited, contentHashes, childPath);
5534
+ obj[child.name] = await this.expandVariable(
5535
+ child,
5536
+ depth - 1,
5537
+ visited,
5538
+ contentHashes,
5539
+ childPath
5540
+ );
5473
5541
  }
5474
5542
  if (this.options.deduplicateByContent && Object.keys(obj).length > 0) {
5475
5543
  const contentHash = this.computeContentHash(v.type, obj);
@@ -5734,24 +5802,24 @@ var ACTIONABLE_HINTS = {
5734
5802
  "PostgresException:3D000": "PostgreSQL database does not exist - verify database name",
5735
5803
  "PostgresException:42P01": "PostgreSQL table does not exist - run migrations or check table name",
5736
5804
  // File system
5737
- "FileNotFoundException": "File not found - verify the file path exists and is accessible",
5738
- "DirectoryNotFoundException": "Directory not found - verify the directory path exists",
5739
- "UnauthorizedAccessException": "Access denied - check file/directory permissions or run with elevated privileges",
5740
- "IOException": "I/O error - check disk space, file locks, or permissions",
5805
+ FileNotFoundException: "File not found - verify the file path exists and is accessible",
5806
+ DirectoryNotFoundException: "Directory not found - verify the directory path exists",
5807
+ UnauthorizedAccessException: "Access denied - check file/directory permissions or run with elevated privileges",
5808
+ IOException: "I/O error - check disk space, file locks, or permissions",
5741
5809
  // Null reference
5742
- "NullReferenceException": "Null reference - an object was not initialized before use. Check for null values in the call chain",
5810
+ NullReferenceException: "Null reference - an object was not initialized before use. Check for null values in the call chain",
5743
5811
  // Validation
5744
- "ArgumentNullException": "A required argument was null - check that all required parameters are provided",
5745
- "ArgumentException": "Invalid argument - check the parameter values being passed",
5746
- "ArgumentOutOfRangeException": "Argument out of range - check that values are within expected bounds",
5747
- "ValidationException": "Validation failed - check the input data against validation rules",
5812
+ ArgumentNullException: "A required argument was null - check that all required parameters are provided",
5813
+ ArgumentException: "Invalid argument - check the parameter values being passed",
5814
+ ArgumentOutOfRangeException: "Argument out of range - check that values are within expected bounds",
5815
+ ValidationException: "Validation failed - check the input data against validation rules",
5748
5816
  // Timeout
5749
- "TimeoutException": "Operation timed out - increase timeout or check for performance issues",
5750
- "TaskCanceledException": "Task was cancelled - may indicate timeout or explicit cancellation",
5751
- "OperationCanceledException": "Operation was cancelled - check CancellationToken usage",
5817
+ TimeoutException: "Operation timed out - increase timeout or check for performance issues",
5818
+ TaskCanceledException: "Task was cancelled - may indicate timeout or explicit cancellation",
5819
+ OperationCanceledException: "Operation was cancelled - check CancellationToken usage",
5752
5820
  // Configuration
5753
- "ConfigurationException": "Configuration error - check app settings and configuration files",
5754
- "OptionsValidationException": "Options validation failed - check configuration values match expected schema",
5821
+ ConfigurationException: "Configuration error - check app settings and configuration files",
5822
+ OptionsValidationException: "Options validation failed - check configuration values match expected schema",
5755
5823
  // HTTP
5756
5824
  "HttpRequestException:404": "HTTP 404 Not Found - verify the URL is correct",
5757
5825
  "HttpRequestException:401": "HTTP 401 Unauthorized - check authentication credentials",
@@ -5838,11 +5906,13 @@ function extractExceptionEntryFromVariable(variable, depth) {
5838
5906
  if (val["SocketErrorCode"]) data.socketErrorCode = extractStringValue(val["SocketErrorCode"]);
5839
5907
  if (val["NativeErrorCode"]) data.nativeErrorCode = extractNumberValue(val["NativeErrorCode"]);
5840
5908
  if (val["ErrorCode"]) data.errorCode = extractNumberValue(val["ErrorCode"]);
5841
- if (val["<ErrorCode>k__BackingField"]) data.errorCode = extractNumberValue(val["<ErrorCode>k__BackingField"]);
5909
+ if (val["<ErrorCode>k__BackingField"])
5910
+ data.errorCode = extractNumberValue(val["<ErrorCode>k__BackingField"]);
5842
5911
  }
5843
5912
  if (type.includes("HttpException") || type.includes("HttpRequestException")) {
5844
5913
  if (val["StatusCode"]) data.httpStatusCode = extractNumberValue(val["StatusCode"]);
5845
- if (val["<StatusCode>k__BackingField"]) data.httpStatusCode = extractNumberValue(val["<StatusCode>k__BackingField"]);
5914
+ if (val["<StatusCode>k__BackingField"])
5915
+ data.httpStatusCode = extractNumberValue(val["<StatusCode>k__BackingField"]);
5846
5916
  }
5847
5917
  if (type.includes("ArgumentException") || type.includes("ArgumentNullException")) {
5848
5918
  if (val["ParamName"]) data.paramName = extractStringValue(val["ParamName"]);
@@ -5850,7 +5920,8 @@ function extractExceptionEntryFromVariable(variable, depth) {
5850
5920
  if (type.includes("FileNotFoundException") || type.includes("FileAccessException")) {
5851
5921
  if (val["FileName"]) data.fileName = extractStringValue(val["FileName"]);
5852
5922
  if (val["FilePath"]) data.filePath = extractStringValue(val["FilePath"]);
5853
- if (val["<FilePath>k__BackingField"]) data.filePath = extractStringValue(val["<FilePath>k__BackingField"]);
5923
+ if (val["<FilePath>k__BackingField"])
5924
+ data.filePath = extractStringValue(val["<FilePath>k__BackingField"]);
5854
5925
  }
5855
5926
  }
5856
5927
  return {
@@ -6022,10 +6093,7 @@ var DebugSession = class {
6022
6093
  async run() {
6023
6094
  this.startTime = Date.now();
6024
6095
  if (this.config.attach && this.config.pid) {
6025
- this.formatter.sessionStartAttach(
6026
- this.config.adapter.name,
6027
- this.config.pid
6028
- );
6096
+ this.formatter.sessionStartAttach(this.config.adapter.name, this.config.pid);
6029
6097
  } else {
6030
6098
  this.formatter.sessionStart(
6031
6099
  this.config.adapter.name,
@@ -6147,9 +6215,7 @@ var DebugSession = class {
6147
6215
  await this.client.configurationDone();
6148
6216
  }
6149
6217
  this.state = "running";
6150
- this.formatter.emit(
6151
- this.formatter.createEvent("process_launched", {})
6152
- );
6218
+ this.formatter.emit(this.formatter.createEvent("process_launched", {}));
6153
6219
  }
6154
6220
  }
6155
6221
  /**
@@ -6516,10 +6582,7 @@ var DebugSession = class {
6516
6582
  };
6517
6583
  if (this.config.diffVars && frameId) {
6518
6584
  const currentLocals = await this.variableInspector.getLocals(frameId);
6519
- const changes = this.variableInspector.diffVariables(
6520
- this.previousLocals,
6521
- currentLocals
6522
- );
6585
+ const changes = this.variableInspector.diffVariables(this.previousLocals, currentLocals);
6523
6586
  if (changes.length > 0) {
6524
6587
  stepEvent.changes = changes;
6525
6588
  }
@@ -6543,10 +6606,7 @@ var DebugSession = class {
6543
6606
  return;
6544
6607
  }
6545
6608
  }
6546
- const stopReason = await this.checkTraceStopConditions(
6547
- stackDepth,
6548
- frameId
6549
- );
6609
+ const stopReason = await this.checkTraceStopConditions(stackDepth, frameId);
6550
6610
  if (stopReason) {
6551
6611
  await this.endTrace(threadId, stopReason, stackFrames, frameId);
6552
6612
  return;
@@ -6742,9 +6802,11 @@ async function launchTestRunner(config) {
6742
6802
  testProcess.on("exit", (code, signal) => {
6743
6803
  if (!foundPid) {
6744
6804
  exitedEarly = true;
6745
- reject(new Error(
6746
- `Test process exited before testhost started. Exit code: ${code}, signal: ${signal}. Make sure the test project builds successfully and has tests.`
6747
- ));
6805
+ reject(
6806
+ new Error(
6807
+ `Test process exited before testhost started. Exit code: ${code}, signal: ${signal}. Make sure the test project builds successfully and has tests.`
6808
+ )
6809
+ );
6748
6810
  }
6749
6811
  });
6750
6812
  testProcess.on("error", (err) => {
@@ -6755,9 +6817,11 @@ async function launchTestRunner(config) {
6755
6817
  setTimeout(() => {
6756
6818
  if (!foundPid && !exitedEarly) {
6757
6819
  testProcess.kill();
6758
- reject(new Error(
6759
- "Timeout waiting for testhost to start. The VSTEST_HOST_DEBUG output was not detected within 60 seconds."
6760
- ));
6820
+ reject(
6821
+ new Error(
6822
+ "Timeout waiting for testhost to start. The VSTEST_HOST_DEBUG output was not detected within 60 seconds."
6823
+ )
6824
+ );
6761
6825
  }
6762
6826
  }, 6e4);
6763
6827
  });
@@ -6793,18 +6857,11 @@ function parseTimeout(value) {
6793
6857
  function createCli() {
6794
6858
  const program2 = new Command();
6795
6859
  program2.name("debug-run").description("CLI tool enabling AI agents to programmatically debug code via DAP").version("0.1.0");
6796
- program2.argument("[program]", "Program to debug").option(
6797
- "-a, --adapter <name>",
6798
- `Debug adapter to use (${getAdapterNames().join(", ")})`
6799
- ).option("--args <args...>", "Arguments to pass to the program").option("--cwd <path>", "Working directory for the program").option(
6860
+ program2.argument("[program]", "Program to debug").option("-a, --adapter <name>", `Debug adapter to use (${getAdapterNames().join(", ")})`).option("--args <args...>", "Arguments to pass to the program").option("--cwd <path>", "Working directory for the program").option(
6800
6861
  "-b, --breakpoint <spec...>",
6801
6862
  'Breakpoint specifications (e.g., "file.ts:45" or "file.ts:45?condition")',
6802
6863
  []
6803
- ).option(
6804
- "-e, --eval <expr...>",
6805
- "Expressions to evaluate when breakpoints are hit",
6806
- []
6807
- ).option(
6864
+ ).option("-e, --eval <expr...>", "Expressions to evaluate when breakpoints are hit", []).option(
6808
6865
  "--assert <expr...>",
6809
6866
  "Invariant expressions that must remain truthy; stops on first violation",
6810
6867
  []
@@ -6815,23 +6872,11 @@ function createCli() {
6815
6872
  ).option(
6816
6873
  "--break-on-exception <filter...>",
6817
6874
  'Break on exceptions (e.g., "all", "user-unhandled", "uncaught")'
6818
- ).option(
6819
- "-t, --timeout <duration>",
6820
- "Session timeout (e.g., 30s, 5000ms, 2m)",
6821
- "60s"
6822
- ).option("--capture-locals", "Capture local variables at breakpoints", true).option("--no-capture-locals", "Disable capturing local variables").option("--pretty", "Pretty print JSON output", false).option(
6875
+ ).option("-t, --timeout <duration>", "Session timeout (e.g., 30s, 5000ms, 2m)", "60s").option("--capture-locals", "Capture local variables at breakpoints", true).option("--no-capture-locals", "Disable capturing local variables").option("--pretty", "Pretty print JSON output", false).option(
6823
6876
  "-s, --steps <count>",
6824
6877
  "Number of steps to execute after hitting a breakpoint (step over)",
6825
6878
  (val) => parseInt(val, 10)
6826
- ).option(
6827
- "--capture-each-step",
6828
- "Capture variables and location at each step",
6829
- false
6830
- ).option(
6831
- "--trace",
6832
- "Enable trace mode - step through code after breakpoint hit",
6833
- false
6834
- ).option(
6879
+ ).option("--capture-each-step", "Capture variables and location at each step", false).option("--trace", "Enable trace mode - step through code after breakpoint hit", false).option(
6835
6880
  "--trace-into",
6836
6881
  "Use stepIn instead of stepOver in trace mode (follow into function calls)",
6837
6882
  false
@@ -6840,39 +6885,21 @@ function createCli() {
6840
6885
  "Maximum steps in trace mode before stopping (default: 500)",
6841
6886
  (val) => parseInt(val, 10),
6842
6887
  500
6843
- ).option(
6844
- "--trace-until <expr>",
6845
- "Stop trace when expression evaluates to truthy"
6846
- ).option(
6888
+ ).option("--trace-until <expr>", "Stop trace when expression evaluates to truthy").option(
6847
6889
  "--diff-vars",
6848
6890
  "Show only changed variables in trace steps instead of full dumps",
6849
6891
  false
6850
- ).option(
6851
- "-o, --output <file>",
6852
- "Write events to file instead of stdout"
6853
- ).option(
6854
- "--include <types...>",
6855
- "Only emit these event types (e.g., breakpoint_hit error)"
6856
- ).option(
6892
+ ).option("-o, --output <file>", "Write events to file instead of stdout").option("--include <types...>", "Only emit these event types (e.g., breakpoint_hit error)").option(
6857
6893
  "--exclude <types...>",
6858
6894
  "Suppress these event types (e.g., program_output exception_thrown)"
6859
- ).addOption(
6860
- new Option("--env <key=value...>", "Environment variables for the program")
6861
- ).option(
6862
- "--attach",
6863
- "Attach to a running process instead of launching",
6864
- false
6865
- ).option(
6895
+ ).addOption(new Option("--env <key=value...>", "Environment variables for the program")).option("--attach", "Attach to a running process instead of launching", false).option(
6866
6896
  "--pid <processId>",
6867
6897
  "Process ID to attach to (requires --attach)",
6868
6898
  (val) => parseInt(val, 10)
6869
6899
  ).option(
6870
6900
  "--test-project <path>",
6871
6901
  "Run dotnet test with VSTEST_HOST_DEBUG=1 and auto-attach (for NUnit/xUnit/MSTest)"
6872
- ).option(
6873
- "--test-filter <filter>",
6874
- "Filter which tests to run (passed to dotnet test --filter)"
6875
- ).option(
6902
+ ).option("--test-filter <filter>", "Filter which tests to run (passed to dotnet test --filter)").option(
6876
6903
  "--expand-services",
6877
6904
  "Fully expand service-like types (Logger, Repository, etc.) instead of showing compact form",
6878
6905
  false
@@ -6880,11 +6907,7 @@ function createCli() {
6880
6907
  "--show-null-props",
6881
6908
  "Include null/undefined properties in output (normally omitted for token efficiency)",
6882
6909
  false
6883
- ).option(
6884
- "--no-dedupe",
6885
- "Disable content-based deduplication of repeated objects",
6886
- false
6887
- ).option(
6910
+ ).option("--no-dedupe", "Disable content-based deduplication of repeated objects", false).option(
6888
6911
  "--flatten-exceptions",
6889
6912
  "Enable exception chain flattening and root cause classification (default: true)",
6890
6913
  true
@@ -6896,34 +6919,40 @@ function createCli() {
6896
6919
  "Maximum depth to traverse exception chain (default: 10)",
6897
6920
  (val) => parseInt(val, 10),
6898
6921
  10
6899
- ).action(async (programPath, options) => {
6900
- if (options.testProject) {
6901
- if (!options.adapter) {
6902
- options.adapter = "vsdbg";
6922
+ ).action(
6923
+ async (programPath, options) => {
6924
+ if (options.testProject) {
6925
+ if (!options.adapter) {
6926
+ options.adapter = "vsdbg";
6927
+ }
6928
+ await runTestDebugSession({ ...options, program: programPath, adapter: options.adapter });
6929
+ return;
6903
6930
  }
6904
- await runTestDebugSession({ ...options, program: programPath, adapter: options.adapter });
6905
- return;
6906
- }
6907
- if (options.attach) {
6908
- if (!options.pid) {
6909
- console.error("Error: --pid is required when using --attach");
6910
- console.error("Usage: debug-run --attach --pid <processId> -a <adapter> -b <breakpoint>");
6911
- process.exit(1);
6931
+ if (options.attach) {
6932
+ if (!options.pid) {
6933
+ console.error("Error: --pid is required when using --attach");
6934
+ console.error(
6935
+ "Usage: debug-run --attach --pid <processId> -a <adapter> -b <breakpoint>"
6936
+ );
6937
+ process.exit(1);
6938
+ }
6939
+ } else {
6940
+ if (!programPath) {
6941
+ console.error(
6942
+ "Error: <program> argument is required (or use --attach --pid, or --test-project)"
6943
+ );
6944
+ console.error("Usage: debug-run <program> -a <adapter> -b <breakpoint>");
6945
+ process.exit(1);
6946
+ }
6912
6947
  }
6913
- } else {
6914
- if (!programPath) {
6915
- console.error("Error: <program> argument is required (or use --attach --pid, or --test-project)");
6916
- console.error("Usage: debug-run <program> -a <adapter> -b <breakpoint>");
6948
+ if (!options.adapter) {
6949
+ console.error("Error: --adapter is required");
6950
+ console.error(`Available adapters: ${getAdapterNames().join(", ")}`);
6917
6951
  process.exit(1);
6918
6952
  }
6953
+ await runDebugSession({ ...options, program: programPath, adapter: options.adapter });
6919
6954
  }
6920
- if (!options.adapter) {
6921
- console.error("Error: --adapter is required");
6922
- console.error(`Available adapters: ${getAdapterNames().join(", ")}`);
6923
- process.exit(1);
6924
- }
6925
- await runDebugSession({ ...options, program: programPath, adapter: options.adapter });
6926
- });
6955
+ );
6927
6956
  program2.command("list-adapters").description("List available debug adapters and their installation status").action(async () => {
6928
6957
  await listAdapters();
6929
6958
  });
@@ -6992,13 +7021,17 @@ async function runDebugSession(options) {
6992
7021
  const hasBreakpoints = options.breakpoint.length > 0 || options.logpoint && options.logpoint.length > 0;
6993
7022
  const hasExceptionBreakpoints = options.breakOnException && options.breakOnException.length > 0;
6994
7023
  if (!hasBreakpoints && !hasExceptionBreakpoints && !options.attach) {
6995
- console.error("Error: At least one --breakpoint, --logpoint, or --break-on-exception is required");
7024
+ console.error(
7025
+ "Error: At least one --breakpoint, --logpoint, or --break-on-exception is required"
7026
+ );
6996
7027
  process.exit(1);
6997
7028
  }
6998
7029
  if (hasExceptionBreakpoints && adapter.exceptionFilters) {
6999
7030
  for (const filter of options.breakOnException) {
7000
7031
  if (!adapter.exceptionFilters.includes(filter)) {
7001
- console.error(`Error: Adapter "${adapter.name}" does not support exception filter "${filter}"`);
7032
+ console.error(
7033
+ `Error: Adapter "${adapter.name}" does not support exception filter "${filter}"`
7034
+ );
7002
7035
  console.error(`Supported filters: ${adapter.exceptionFilters.join(", ")}`);
7003
7036
  process.exit(1);
7004
7037
  }
@@ -7017,7 +7050,7 @@ async function runDebugSession(options) {
7017
7050
  let outputStream = process.stdout;
7018
7051
  let fileStream;
7019
7052
  if (options.output) {
7020
- fileStream = fs.createWriteStream(options.output);
7053
+ fileStream = fs2.createWriteStream(options.output);
7021
7054
  outputStream = fileStream;
7022
7055
  }
7023
7056
  const formatter = new OutputFormatter({
@@ -7095,7 +7128,9 @@ async function installAdapter(name) {
7095
7128
  Successfully installed netcoredbg!`);
7096
7129
  console.log(`Path: ${installedPath}`);
7097
7130
  } catch (error) {
7098
- console.error(`Failed to install netcoredbg: ${error instanceof Error ? error.message : error}`);
7131
+ console.error(
7132
+ `Failed to install netcoredbg: ${error instanceof Error ? error.message : error}`
7133
+ );
7099
7134
  process.exit(1);
7100
7135
  }
7101
7136
  } else if (normalizedName === "node" || normalizedName === "nodejs" || normalizedName === "js" || normalizedName === "javascript" || normalizedName === "typescript") {
@@ -7109,7 +7144,9 @@ Successfully installed netcoredbg!`);
7109
7144
  Successfully installed js-debug!`);
7110
7145
  console.log(`Path: ${installedPath}`);
7111
7146
  } catch (error) {
7112
- console.error(`Failed to install js-debug: ${error instanceof Error ? error.message : error}`);
7147
+ console.error(
7148
+ `Failed to install js-debug: ${error instanceof Error ? error.message : error}`
7149
+ );
7113
7150
  process.exit(1);
7114
7151
  }
7115
7152
  } else if (normalizedName === "debugpy" || normalizedName === "python") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "debug-run",
3
- "version": "0.1.0",
3
+ "version": "0.5.1",
4
4
  "description": "CLI tool enabling AI agents to programmatically debug code via DAP",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -8,12 +8,19 @@
8
8
  "debug-run": "dist/index.cjs"
9
9
  },
10
10
  "scripts": {
11
- "prepare": "npm run build",
11
+ "prepare": "husky",
12
12
  "build": "node scripts/build.mjs",
13
13
  "dev": "tsx ./src/index.ts",
14
14
  "test": "vitest",
15
15
  "test:run": "vitest run",
16
- "typecheck": "tsc --noEmit"
16
+ "typecheck": "tsc --noEmit",
17
+ "format": "prettier --write src/",
18
+ "format:check": "prettier --check src/"
19
+ },
20
+ "lint-staged": {
21
+ "src/**/*.{ts,js}": [
22
+ "prettier --write"
23
+ ]
17
24
  },
18
25
  "dependencies": {
19
26
  "@vscode/debugprotocol": "^1.65.0",
@@ -25,6 +32,9 @@
25
32
  "@types/node": "^20.0.0",
26
33
  "bun-types": "^1.0.0",
27
34
  "esbuild": "^0.27.2",
35
+ "husky": "^9.1.7",
36
+ "lint-staged": "^16.2.7",
37
+ "prettier": "^3.8.0",
28
38
  "tsx": "^4.21.0",
29
39
  "typescript": "^5.3.0",
30
40
  "vitest": "^1.0.0"