@debugmcp/mcp-debugger
Version:
Step-through debugging MCP server for LLMs
1,340 lines (1,329 loc) • 785 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// ../../node_modules/.pnpm/tsup@8.5.0_postcss@8.5.6_typescript@5.9.2/node_modules/tsup/assets/cjs_shims.js
var getImportMetaUrl, importMetaUrl;
var init_cjs_shims = __esm({
"../../node_modules/.pnpm/tsup@8.5.0_postcss@8.5.6_typescript@5.9.2/node_modules/tsup/assets/cjs_shims.js"() {
"use strict";
getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
}
});
// ../shared/dist/interfaces/debug-adapter.js
var AdapterState, DebugFeature, AdapterErrorCode;
var init_debug_adapter = __esm({
"../shared/dist/interfaces/debug-adapter.js"() {
"use strict";
init_cjs_shims();
(function(AdapterState2) {
AdapterState2["UNINITIALIZED"] = "uninitialized";
AdapterState2["INITIALIZING"] = "initializing";
AdapterState2["READY"] = "ready";
AdapterState2["CONNECTED"] = "connected";
AdapterState2["DEBUGGING"] = "debugging";
AdapterState2["DISCONNECTED"] = "disconnected";
AdapterState2["ERROR"] = "error";
})(AdapterState || (AdapterState = {}));
(function(DebugFeature2) {
DebugFeature2["CONDITIONAL_BREAKPOINTS"] = "conditionalBreakpoints";
DebugFeature2["FUNCTION_BREAKPOINTS"] = "functionBreakpoints";
DebugFeature2["EXCEPTION_BREAKPOINTS"] = "exceptionBreakpoints";
DebugFeature2["VARIABLE_PAGING"] = "variablePaging";
DebugFeature2["EVALUATE_FOR_HOVERS"] = "evaluateForHovers";
DebugFeature2["SET_VARIABLE"] = "setVariable";
DebugFeature2["SET_EXPRESSION"] = "setExpression";
DebugFeature2["DATA_BREAKPOINTS"] = "dataBreakpoints";
DebugFeature2["DISASSEMBLE_REQUEST"] = "disassembleRequest";
DebugFeature2["TERMINATE_THREADS_REQUEST"] = "terminateThreadsRequest";
DebugFeature2["DELAYED_STACK_TRACE_LOADING"] = "delayedStackTraceLoading";
DebugFeature2["LOADED_SOURCES_REQUEST"] = "loadedSourcesRequest";
DebugFeature2["LOG_POINTS"] = "logPoints";
DebugFeature2["TERMINATE_REQUEST"] = "terminateRequest";
DebugFeature2["RESTART_REQUEST"] = "restartRequest";
DebugFeature2["EXCEPTION_OPTIONS"] = "exceptionOptions";
DebugFeature2["EXCEPTION_INFO_REQUEST"] = "exceptionInfoRequest";
DebugFeature2["STEP_BACK"] = "stepBack";
DebugFeature2["REVERSE_DEBUGGING"] = "reverseDebugging";
DebugFeature2["STEP_IN_TARGETS_REQUEST"] = "stepInTargetsRequest";
})(DebugFeature || (DebugFeature = {}));
(function(AdapterErrorCode2) {
AdapterErrorCode2["ENVIRONMENT_INVALID"] = "ENVIRONMENT_INVALID";
AdapterErrorCode2["EXECUTABLE_NOT_FOUND"] = "EXECUTABLE_NOT_FOUND";
AdapterErrorCode2["ADAPTER_NOT_INSTALLED"] = "ADAPTER_NOT_INSTALLED";
AdapterErrorCode2["INCOMPATIBLE_VERSION"] = "INCOMPATIBLE_VERSION";
AdapterErrorCode2["CONNECTION_FAILED"] = "CONNECTION_FAILED";
AdapterErrorCode2["CONNECTION_TIMEOUT"] = "CONNECTION_TIMEOUT";
AdapterErrorCode2["CONNECTION_LOST"] = "CONNECTION_LOST";
AdapterErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
AdapterErrorCode2["UNSUPPORTED_OPERATION"] = "UNSUPPORTED_OPERATION";
AdapterErrorCode2["DEBUGGER_ERROR"] = "DEBUGGER_ERROR";
AdapterErrorCode2["SCRIPT_NOT_FOUND"] = "SCRIPT_NOT_FOUND";
AdapterErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
AdapterErrorCode2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
})(AdapterErrorCode || (AdapterErrorCode = {}));
}
});
// ../shared/dist/interfaces/adapter-registry.js
var init_adapter_registry = __esm({
"../shared/dist/interfaces/adapter-registry.js"() {
"use strict";
init_cjs_shims();
}
});
// ../shared/dist/models/index.js
var DebugLanguage, SessionLifecycleState, ExecutionState, SessionState;
var init_models = __esm({
"../shared/dist/models/index.js"() {
"use strict";
init_cjs_shims();
(function(DebugLanguage2) {
DebugLanguage2["PYTHON"] = "python";
DebugLanguage2["JAVASCRIPT"] = "javascript";
DebugLanguage2["RUST"] = "rust";
DebugLanguage2["MOCK"] = "mock";
})(DebugLanguage || (DebugLanguage = {}));
(function(SessionLifecycleState2) {
SessionLifecycleState2["CREATED"] = "created";
SessionLifecycleState2["ACTIVE"] = "active";
SessionLifecycleState2["TERMINATED"] = "terminated";
})(SessionLifecycleState || (SessionLifecycleState = {}));
(function(ExecutionState2) {
ExecutionState2["INITIALIZING"] = "initializing";
ExecutionState2["RUNNING"] = "running";
ExecutionState2["PAUSED"] = "paused";
ExecutionState2["TERMINATED"] = "terminated";
ExecutionState2["ERROR"] = "error";
})(ExecutionState || (ExecutionState = {}));
(function(SessionState2) {
SessionState2["CREATED"] = "created";
SessionState2["INITIALIZING"] = "initializing";
SessionState2["READY"] = "ready";
SessionState2["RUNNING"] = "running";
SessionState2["PAUSED"] = "paused";
SessionState2["STOPPED"] = "stopped";
SessionState2["ERROR"] = "error";
})(SessionState || (SessionState = {}));
}
});
// ../shared/dist/factories/adapter-factory.js
var init_adapter_factory = __esm({
"../shared/dist/factories/adapter-factory.js"() {
"use strict";
init_cjs_shims();
}
});
// ../shared/dist/interfaces/adapter-policy.js
var DefaultAdapterPolicy;
var init_adapter_policy = __esm({
"../shared/dist/interfaces/adapter-policy.js"() {
"use strict";
init_cjs_shims();
DefaultAdapterPolicy = {
name: "default",
supportsReverseStartDebugging: false,
childSessionStrategy: "none",
shouldDeferParentConfigDone: () => false,
buildChildStartArgs: (pendingId) => {
throw new Error(`DefaultAdapterPolicy is a placeholder and cannot start child sessions (pendingId=${pendingId}).`);
},
isChildReadyEvent: () => false,
getDapAdapterConfiguration: () => ({
type: "default"
}),
resolveExecutablePath: (providedPath) => providedPath,
getDebuggerConfiguration: () => ({}),
requiresCommandQueueing: () => false,
shouldQueueCommand: () => ({
shouldQueue: false,
shouldDefer: false,
reason: "DefaultAdapterPolicy is inactive until a real adapter is selected"
}),
createInitialState: () => ({
initialized: false,
configurationDone: false
}),
isInitialized: () => false,
isConnected: () => false,
matchesAdapter: () => false,
getInitializationBehavior: () => ({}),
getDapClientBehavior: () => ({})
};
}
});
// ../shared/dist/interfaces/adapter-policy-js.js
var JsDebugAdapterPolicy;
var init_adapter_policy_js = __esm({
"../shared/dist/interfaces/adapter-policy-js.js"() {
"use strict";
init_cjs_shims();
init_dist();
JsDebugAdapterPolicy = {
name: "js-debug",
supportsReverseStartDebugging: true,
childSessionStrategy: "launchWithPendingTarget",
shouldDeferParentConfigDone: () => true,
buildChildStartArgs: (pendingId, parentConfig) => {
const type = typeof parentConfig?.type === "string" ? parentConfig.type : "pwa-node";
return {
command: "attach",
args: {
type,
request: "attach",
__pendingTargetId: pendingId,
continueOnAttach: true
// js-debug requires true to work properly
}
};
},
isChildReadyEvent: (evt) => {
return evt?.event === "thread" || evt?.event === "stopped";
},
/**
* Check if a stack frame is a Node.js internal frame
*/
isInternalFrame: (frame) => {
const filePath = frame.file || "";
return filePath.includes("<node_internals>");
},
/**
* Filter stack frames to optionally remove Node.js internals
*/
filterStackFrames: (frames, includeInternals) => {
if (includeInternals) {
return frames;
}
const filtered = frames.filter((frame) => !JsDebugAdapterPolicy.isInternalFrame(frame));
if (filtered.length === 0 && frames.length > 0) {
return [frames[0]];
}
return filtered;
},
/**
* Extract local variables for JavaScript, filtering out internals by default
*/
extractLocalVariables: (stackFrames, scopes, variables, includeSpecial = false) => {
if (!stackFrames || stackFrames.length === 0) {
return [];
}
const topFrame = stackFrames[0];
const frameScopes = scopes[topFrame.id];
if (!frameScopes || frameScopes.length === 0) {
return [];
}
let localScope = frameScopes.find((scope) => scope.name === "Local" || scope.name === "Locals" || scope.name.startsWith("Local:") || scope.name.startsWith("Block:"));
if (!localScope) {
localScope = frameScopes.find((scope) => scope.name === "Script" || scope.name === "Module" || scope.name === "module" || scope.name.toLowerCase().includes("global"));
}
if (!localScope) {
return [];
}
let localVars = variables[localScope.variablesReference] || [];
if (!includeSpecial) {
localVars = localVars.filter((v) => {
const name = v.name;
if (name === "this") {
return false;
}
if (name === "__proto__" || name === "prototype") {
return false;
}
if (name.startsWith("[[") && name.endsWith("]]")) {
return false;
}
if (name.startsWith("$") || name.startsWith("_$")) {
return false;
}
return true;
});
}
return localVars;
},
/**
* JavaScript uses various local scope names
*/
getLocalScopeName: () => {
return ["Local", "Local:", "Block:", "Script", "Global"];
},
getDapAdapterConfiguration: () => {
return {
type: "pwa-node"
// VS Code JavaScript/TypeScript debugger type
};
},
resolveExecutablePath: (providedPath) => {
if (providedPath) {
return providedPath;
}
return "node";
},
getDebuggerConfiguration: () => {
return {
// JavaScript debugger configuration for js-debug/pwa-node
requiresStrictHandshake: true,
// js-debug requires strict initialization sequence
skipConfigurationDone: false,
supportsVariableType: true
// JavaScript debugger supports variable type information
};
},
isSessionReady: (state, options) => state === SessionState.PAUSED || !options.stopOnEntry && state === SessionState.RUNNING,
/**
* Perform JavaScript-specific handshake sequence for js-debug/pwa-node.
* This includes the strict initialization sequence required by js-debug.
*/
performHandshake: async (context) => {
const { proxyManager, sessionId, dapLaunchArgs, scriptPath, scriptArgs, breakpoints, launchConfig } = context;
const pm = proxyManager;
if (!pm || !pm.isRunning()) {
console.warn(`[JsDebugAdapterPolicy] performHandshake skipped: proxy manager not running for session ${sessionId}`);
return;
}
try {
console.info(`[JsDebugAdapterPolicy] [JS] Sending 'initialize' request`);
await pm.sendDapRequest("initialize", {
clientID: "mcp",
adapterID: "javascript",
linesStartAt1: true,
columnsStartAt1: true,
pathFormat: "path",
// CRITICAL: Tell js-debug we support multi-session for proper breakpoint handling
supportsStartDebuggingRequest: true
});
} catch (e) {
console.warn(`[JsDebugAdapterPolicy] [JS] 'initialize' failed or deferred: ${e instanceof Error ? e.message : String(e)}`);
}
await new Promise((resolve2) => {
let done = false;
const timer = setTimeout(() => {
if (done)
return;
done = true;
console.warn(`[JsDebugAdapterPolicy] [JS] Timeout waiting for DAP 'initialized' event`);
resolve2();
}, 1e4);
const onHandler = (event) => {
if (done)
return;
const eventName = typeof event === "string" ? event : event?.event;
if (eventName === "initialized") {
done = true;
clearTimeout(timer);
pm.removeListener("dap-event", onHandler);
resolve2();
}
};
pm.on("dap-event", onHandler);
});
try {
console.info(`[JsDebugAdapterPolicy] [JS] Sending 'setExceptionBreakpoints' []`);
await pm.sendDapRequest("setExceptionBreakpoints", { filters: [] });
} catch (e) {
console.warn(`[JsDebugAdapterPolicy] [JS] 'setExceptionBreakpoints' failed or unsupported: ${e instanceof Error ? e.message : String(e)}`);
}
try {
const grouped = /* @__PURE__ */ new Map();
for (const bp of breakpoints.values()) {
const breakpoint = bp;
const arr = grouped.get(breakpoint.file) || [];
arr.push({ line: breakpoint.line, condition: breakpoint.condition });
grouped.set(breakpoint.file, arr);
}
for (const [file, bps] of grouped) {
console.info(`[JsDebugAdapterPolicy] [JS] Sending 'setBreakpoints' for ${file} (${bps.length})`);
await pm.sendDapRequest("setBreakpoints", {
source: { path: file },
breakpoints: bps
});
}
} catch (e) {
console.warn(`[JsDebugAdapterPolicy] [JS] 'setBreakpoints' failed: ${e instanceof Error ? e.message : String(e)}`);
}
try {
console.info(`[JsDebugAdapterPolicy] [JS] Sending 'configurationDone'`);
await pm.sendDapRequest("configurationDone", {});
} catch (e) {
console.warn(`[JsDebugAdapterPolicy] [JS] 'configurationDone' failed or deferred: ${e instanceof Error ? e.message : String(e)}`);
}
const a = dapLaunchArgs || {};
const baseLaunchConfig = launchConfig ? { ...launchConfig } : {};
const baseRecord = baseLaunchConfig;
const getPortValue = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
const type = typeof baseLaunchConfig.type === "string" ? baseLaunchConfig.type : typeof a.type === "string" ? a.type : "pwa-node";
const req = typeof baseLaunchConfig.request === "string" ? baseLaunchConfig.request : typeof a.request === "string" ? a.request : "launch";
const attachPort = getPortValue(baseRecord.attachSimplePort) ?? getPortValue(baseRecord.port) ?? getPortValue(a.attachSimplePort) ?? getPortValue(a.port);
if (req === "attach" && typeof attachPort === "number" && attachPort > 0) {
try {
console.info(`[JsDebugAdapterPolicy] [JS] Sending 'attach' to ${attachPort} (address=127.0.0.1)`);
await pm.sendDapRequest("attach", {
type,
request: "attach",
address: "127.0.0.1",
port: attachPort,
continueOnAttach: true,
attachExistingChildren: true,
attachSimplePort: attachPort
});
} catch (e) {
console.warn(`[JsDebugAdapterPolicy] [JS] 'attach' failed: ${e instanceof Error ? e.message : String(e)}`);
}
} else {
try {
const path7 = await import("path");
if (typeof baseLaunchConfig.program !== "string" || !baseLaunchConfig.program.length) {
baseLaunchConfig.program = scriptPath;
}
if ((!Array.isArray(baseLaunchConfig.args) || baseLaunchConfig.args.length === 0) && Array.isArray(scriptArgs) && scriptArgs.length > 0) {
baseLaunchConfig.args = scriptArgs;
}
if (typeof baseLaunchConfig.cwd !== "string" || !baseLaunchConfig.cwd.length) {
baseLaunchConfig.cwd = scriptPath ? path7.dirname(scriptPath) : process.cwd();
}
if (typeof baseLaunchConfig.stopOnEntry !== "boolean" && typeof a?.stopOnEntry === "boolean") {
baseLaunchConfig.stopOnEntry = a.stopOnEntry;
}
if (typeof baseLaunchConfig.justMyCode !== "boolean" && typeof a?.justMyCode === "boolean") {
baseLaunchConfig.justMyCode = a.justMyCode;
}
if (typeof baseLaunchConfig.console !== "string") {
baseLaunchConfig.console = "internalConsole";
}
if (typeof baseLaunchConfig.outputCapture !== "string") {
baseLaunchConfig.outputCapture = "std";
}
if (typeof baseLaunchConfig.smartStep !== "boolean") {
baseLaunchConfig.smartStep = true;
}
if (typeof baseLaunchConfig.pauseForSourceMap !== "boolean") {
baseLaunchConfig.pauseForSourceMap = true;
}
if (typeof baseLaunchConfig.runtimeExecutable !== "string") {
baseLaunchConfig.runtimeExecutable = process.execPath;
}
const finalLaunchArgs = {
...baseLaunchConfig,
type,
request: req
};
if (typeof baseLaunchConfig.sourceMaps === "boolean") {
finalLaunchArgs.sourceMaps = baseLaunchConfig.sourceMaps;
} else if (typeof a.sourceMaps === "boolean") {
finalLaunchArgs.sourceMaps = a.sourceMaps;
}
const resolvedOutFiles = Array.isArray(baseLaunchConfig.outFiles) && baseLaunchConfig.outFiles.length > 0 ? baseLaunchConfig.outFiles : Array.isArray(a.outFiles) && a.outFiles.length > 0 ? a.outFiles : void 0;
if (resolvedOutFiles) {
finalLaunchArgs.outFiles = resolvedOutFiles;
}
const resolvedSourcemapLocations = Array.isArray(baseLaunchConfig.resolveSourceMapLocations) ? baseLaunchConfig.resolveSourceMapLocations : Array.isArray(a.resolveSourceMapLocations) ? a.resolveSourceMapLocations : void 0;
if (resolvedSourcemapLocations) {
finalLaunchArgs.resolveSourceMapLocations = resolvedSourcemapLocations;
}
console.info(`[JsDebugAdapterPolicy] [JS] Sending 'launch' for program='${finalLaunchArgs.program}' cwd='${finalLaunchArgs.cwd}'`);
await pm.sendDapRequest("launch", finalLaunchArgs);
} catch (e) {
console.warn(`[JsDebugAdapterPolicy] [JS] 'launch' failed: ${e instanceof Error ? e.message : String(e)}`);
}
}
console.info(`[JsDebugAdapterPolicy] [JS] Handshake complete. Multi-session architecture now handling debugging.`);
},
/**
* JavaScript adapter requires command queueing for proper initialization
*/
requiresCommandQueueing: () => true,
/**
* Determine if a command should be queued based on JavaScript-specific state
*/
shouldQueueCommand: (command, state) => {
const jsState = state;
if (command === "initialize") {
return { shouldQueue: false, shouldDefer: false };
}
if (!jsState.initializeResponded) {
return {
shouldQueue: true,
shouldDefer: false,
reason: `Queuing '${command}' until 'initialize' response (JS adapter)`
};
}
const configCommands = /* @__PURE__ */ new Set([
"setBreakpoints",
"setFunctionBreakpoints",
"setExceptionBreakpoints",
"setDataBreakpoints",
"setInstructionBreakpoints",
"configurationDone"
]);
if (!jsState.initialized && configCommands.has(command)) {
return {
shouldQueue: true,
shouldDefer: false,
reason: `Queuing '${command}' until 'initialized' event (JS adapter)`
};
}
if ((command === "launch" || command === "attach") && !jsState.configurationDone) {
return {
shouldQueue: true,
shouldDefer: true,
// Signal that we need to inject configurationDone first
reason: `JS: deferring '${command}' until configurationDone (strict order)`
};
}
return { shouldQueue: false, shouldDefer: false };
},
/**
* Process queued commands in JavaScript-specific order
*/
processQueuedCommands: (commands) => {
const typedCommands = commands;
const isConfig = (cmd) => [
"setBreakpoints",
"setFunctionBreakpoints",
"setExceptionBreakpoints",
"setDataBreakpoints",
"setInstructionBreakpoints"
].includes(cmd);
const configs = typedCommands.filter((p) => isConfig(p.dapCommand));
const configDone = typedCommands.filter((p) => p.dapCommand === "configurationDone");
const launches = typedCommands.filter((p) => p.dapCommand === "launch" || p.dapCommand === "attach");
const others = typedCommands.filter((p) => !isConfig(p.dapCommand) && p.dapCommand !== "configurationDone" && p.dapCommand !== "launch" && p.dapCommand !== "attach");
return [...configs, ...configDone, ...launches, ...others];
},
/**
* Create initial state for JavaScript adapter
*/
createInitialState: () => {
return {
initialized: false,
configurationDone: false,
initializeResponded: false,
startSent: false,
pendingCommands: []
};
},
/**
* Update state when a command is sent
*/
updateStateOnCommand: (command, _args, state) => {
const jsState = state;
if (command === "initialize") {
} else if (command === "configurationDone") {
jsState.configurationDone = true;
} else if (command === "launch" || command === "attach") {
jsState.startSent = true;
}
},
/**
* Update state when a command response is received
*/
updateStateOnResponse: (command, _response, state) => {
const jsState = state;
if (command === "initialize") {
jsState.initializeResponded = true;
}
},
/**
* Update state when an event is received
*/
updateStateOnEvent: (event, _body, state) => {
const jsState = state;
if (event === "initialized") {
jsState.initialized = true;
}
},
/**
* Check if JavaScript adapter is initialized
*/
isInitialized: (state) => {
const jsState = state;
return jsState.initialized && jsState.initializeResponded;
},
/**
* Check if JavaScript adapter is connected
*/
isConnected: (state) => {
const jsState = state;
return jsState.initializeResponded;
},
/**
* Check if this policy applies to the given adapter command
*/
matchesAdapter: (adapterCommand) => {
const commandStr = adapterCommand.command.toLowerCase();
const argsStr = adapterCommand.args.join(" ").toLowerCase();
return commandStr.includes("js-debug") || commandStr.includes("pwa-node") || commandStr.includes("vsDebugServer") || argsStr.includes("js-debug") || argsStr.includes("pwa-node") || argsStr.includes("vsDebugServer");
},
/**
* JavaScript adapter has special initialization requirements
*/
getInitializationBehavior: () => {
return {
deferConfigDone: true,
// Must defer configurationDone until after launch/attach
addRuntimeExecutable: true,
// Needs to add runtimeExecutable to launch args
trackInitializeResponse: true,
// Must track initialize response separately
requiresInitialStop: true
// Must ensure initial stop after launch/attach
};
},
/**
* JavaScript-specific DAP client behaviors
*/
getDapClientBehavior: () => {
return {
// Handle reverse startDebugging requests
handleReverseRequest: async (request, context) => {
if (request.command === "startDebugging") {
const args = request?.arguments ?? {};
const cfg = args?.configuration ?? {};
const pendingId = cfg?.__pendingTargetId;
context.sendResponse(request, {});
if (pendingId && typeof pendingId === "string") {
if (!context.adoptedTargets.has(pendingId)) {
context.adoptedTargets.add(pendingId);
return {
handled: true,
createChildSession: true,
childConfig: {
host: cfg.host || "localhost",
port: cfg.port || 9229,
pendingId,
parentConfig: cfg
}
};
}
}
return { handled: true };
} else if (request.command === "runInTerminal") {
context.sendResponse(request, {});
return { handled: true };
}
return { handled: false };
},
// Commands that should be routed to child sessions
childRoutedCommands: /* @__PURE__ */ new Set([
"threads",
"pause",
"continue",
"next",
"stepIn",
"stepOut",
"stackTrace",
"scopes",
"variables",
"evaluate",
"loadedSources",
"source",
"setVariable",
"setExpression",
"restart",
"disconnect",
"terminate",
"goto",
"restartFrame",
"stepBack",
"reverseContinue"
]),
// JavaScript-specific child session behaviors
mirrorBreakpointsToChild: true,
deferParentConfigDone: true,
pauseAfterChildAttach: true,
stackTraceRequiresChild: true,
// Normalize adapter ID for initialize
normalizeAdapterId: (requestedId) => {
if (requestedId.toLowerCase() === "javascript") {
return "pwa-node";
}
return requestedId;
},
// Timeouts
childInitTimeout: 12e3,
suppressPostAttachConfigDone: false
// Child session needs configurationDone
};
},
/**
* Get the configuration for spawning the JavaScript debug adapter (js-debug/pwa-node)
*/
getAdapterSpawnConfig: (payload) => {
if (payload.adapterCommand) {
return {
command: payload.adapterCommand.command,
args: payload.adapterCommand.args,
host: payload.adapterHost,
port: payload.adapterPort,
logDir: payload.logDir,
env: payload.adapterCommand.env
};
}
console.warn("[JsDebugAdapterPolicy] No adapter command provided - JavaScript debugging may not work correctly");
return void 0;
}
};
}
});
// ../shared/dist/interfaces/adapter-policy-python.js
var PythonAdapterPolicy;
var init_adapter_policy_python = __esm({
"../shared/dist/interfaces/adapter-policy-python.js"() {
"use strict";
init_cjs_shims();
init_dist();
PythonAdapterPolicy = {
name: "python",
supportsReverseStartDebugging: false,
childSessionStrategy: "none",
shouldDeferParentConfigDone: () => false,
buildChildStartArgs: () => {
throw new Error("PythonAdapterPolicy does not support child sessions");
},
isChildReadyEvent: (evt) => {
return evt?.event === "initialized";
},
/**
* Extract local variables for Python, filtering out special variables by default
*/
extractLocalVariables: (stackFrames, scopes, variables, includeSpecial = false) => {
if (!stackFrames || stackFrames.length === 0) {
return [];
}
const topFrame = stackFrames[0];
const frameScopes = scopes[topFrame.id];
if (!frameScopes || frameScopes.length === 0) {
return [];
}
const localScope = frameScopes.find((scope) => scope.name === "Locals" || scope.name === "Local");
if (!localScope) {
return [];
}
let localVars = variables[localScope.variablesReference] || [];
if (!includeSpecial) {
localVars = localVars.filter((v) => {
const name = v.name;
if (name === "special variables" || name === "function variables") {
return false;
}
if (name.startsWith("__") && name.endsWith("__")) {
const keepDunders = ["__name__", "__file__", "__doc__"];
return keepDunders.includes(name);
}
if (name.startsWith("_pydev") || name === "_") {
return false;
}
return true;
});
}
return localVars;
},
/**
* Python uses "Locals" for local variables scope
*/
getLocalScopeName: () => {
return ["Locals"];
},
getDapAdapterConfiguration: () => {
return {
type: "debugpy"
// Python Debug Adapter Protocol type
};
},
resolveExecutablePath: (providedPath) => {
if (providedPath) {
return providedPath;
}
if (process.env.PYTHON_PATH) {
return process.env.PYTHON_PATH;
}
return process.platform === "win32" ? "python" : "python3";
},
getDebuggerConfiguration: () => {
return {
// Python debugger configuration
requiresStrictHandshake: false,
skipConfigurationDone: false,
supportsVariableType: true
// Python debugpy supports variable type information
};
},
isSessionReady: (state) => state === SessionState.PAUSED,
/**
* Validate that a Python command is a real Python executable, not a Windows Store alias.
* This validation is critical on Windows to avoid false positives.
*/
validateExecutable: async (pythonCmd) => {
const { spawn: spawn2 } = await import("child_process");
return new Promise((resolve2) => {
const child = spawn2(pythonCmd, ["-c", "import sys; sys.exit(0)"], {
stdio: ["ignore", "ignore", "pipe"]
});
let stderrData = "";
child.stderr?.on("data", (data) => {
stderrData += data.toString();
});
child.on("error", () => resolve2(false));
child.on("exit", (code) => {
const storeAlias = code === 9009 || stderrData.includes("Microsoft Store") || stderrData.includes("Windows Store") || stderrData.includes("AppData\\Local\\Microsoft\\WindowsApps");
if (storeAlias) {
resolve2(false);
} else {
resolve2(code === 0);
}
});
});
},
/**
* Python adapter doesn't require command queueing
*/
requiresCommandQueueing: () => false,
/**
* Python doesn't need to queue commands
*/
shouldQueueCommand: () => {
return {
shouldQueue: false,
shouldDefer: false,
reason: "Python adapter does not queue commands"
};
},
/**
* Create initial state for Python adapter
*/
createInitialState: () => {
return {
initialized: false,
configurationDone: false
};
},
/**
* Update state when a command is sent
*/
updateStateOnCommand: (command, _args, state) => {
if (command === "configurationDone") {
state.configurationDone = true;
}
},
/**
* Update state when an event is received
*/
updateStateOnEvent: (event, _body, state) => {
if (event === "initialized") {
state.initialized = true;
}
},
/**
* Check if Python adapter is initialized
*/
isInitialized: (state) => {
return state.initialized;
},
/**
* Check if Python adapter is connected
*/
isConnected: (state) => {
return state.initialized;
},
/**
* Check if this policy applies to the given adapter command
*/
matchesAdapter: (adapterCommand) => {
const commandStr = adapterCommand.command.toLowerCase();
const argsStr = adapterCommand.args.join(" ").toLowerCase();
return commandStr.includes("debugpy") || commandStr.includes("python") || argsStr.includes("debugpy") || argsStr.includes("-m debugpy");
},
/**
* Python adapter has no special initialization requirements
*/
getInitializationBehavior: () => {
return {};
},
/**
* Python DAP client behaviors - minimal since Python doesn't use child sessions
*/
getDapClientBehavior: () => {
return {
// Python doesn't handle reverse requests
handleReverseRequest: async (request, context) => {
if (request.command === "runInTerminal") {
context.sendResponse(request, {});
return { handled: true };
}
return { handled: false };
},
// No child session routing needed
childRoutedCommands: void 0,
// Python-specific behaviors
mirrorBreakpointsToChild: false,
deferParentConfigDone: false,
pauseAfterChildAttach: false,
// No adapter ID normalization needed
normalizeAdapterId: void 0,
// Standard timeouts
childInitTimeout: 5e3,
suppressPostAttachConfigDone: false
};
},
/**
* Get the configuration for spawning the Python debug adapter (debugpy)
*/
getAdapterSpawnConfig: (payload) => {
if (payload.adapterCommand) {
return {
command: payload.adapterCommand.command,
args: payload.adapterCommand.args,
host: payload.adapterHost,
port: payload.adapterPort,
logDir: payload.logDir,
env: payload.adapterCommand.env
};
}
const pythonPath = payload.executablePath || "python";
return {
command: pythonPath,
args: [
"-m",
"debugpy.adapter",
"--host",
payload.adapterHost,
"--port",
String(payload.adapterPort),
"--log-dir",
payload.logDir
],
host: payload.adapterHost,
port: payload.adapterPort,
logDir: payload.logDir
};
}
};
}
});
// ../shared/dist/interfaces/adapter-policy-rust.js
var path, RustAdapterPolicy;
var init_adapter_policy_rust = __esm({
"../shared/dist/interfaces/adapter-policy-rust.js"() {
"use strict";
init_cjs_shims();
path = __toESM(require("path"), 1);
init_dist();
RustAdapterPolicy = {
name: "rust",
supportsReverseStartDebugging: false,
childSessionStrategy: "none",
shouldDeferParentConfigDone: () => false,
buildChildStartArgs: () => {
throw new Error("RustAdapterPolicy does not support child sessions");
},
isChildReadyEvent: (evt) => {
return evt?.event === "initialized";
},
/**
* Extract local variables for Rust, filtering out special variables by default
*/
extractLocalVariables: (stackFrames, scopes, variables, includeSpecial = false) => {
if (!stackFrames || stackFrames.length === 0) {
return [];
}
const topFrame = stackFrames[0];
const frameScopes = scopes[topFrame.id];
if (!frameScopes || frameScopes.length === 0) {
return [];
}
const localScope = frameScopes.find((scope) => scope.name === "Local" || scope.name === "Locals");
if (!localScope) {
return [];
}
let localVars = variables[localScope.variablesReference] || [];
if (!includeSpecial) {
localVars = localVars.filter((v) => {
const name = v.name;
if (name.startsWith("$") || name.startsWith("__")) {
return false;
}
if (name.startsWith("_lldb") || name.startsWith("_debug")) {
return false;
}
return true;
});
}
return localVars;
},
/**
* Rust/CodeLLDB uses "Local" or "Locals" for local variables scope
*/
getLocalScopeName: () => {
return ["Local", "Locals"];
},
getDapAdapterConfiguration: () => {
return {
type: "lldb"
// CodeLLDB adapter type
};
},
resolveExecutablePath: (providedPath) => {
if (providedPath) {
return providedPath;
}
if (process.env.CARGO_PATH) {
return process.env.CARGO_PATH;
}
return void 0;
},
getDebuggerConfiguration: () => {
return {
// CodeLLDB debugger configuration
requiresStrictHandshake: false,
skipConfigurationDone: false,
supportsVariableType: true,
// CodeLLDB supports variable type information
supportsValueFormat: true,
// CodeLLDB supports value formatting
supportsMemoryReferences: true
// CodeLLDB supports memory references
};
},
isSessionReady: (state) => state === SessionState.PAUSED,
/**
* Validate that the CodeLLDB adapter is available and executable
*/
validateExecutable: async (codelldbPath) => {
const fs4 = await import("fs/promises");
const { spawn: spawn2 } = await import("child_process");
try {
await fs4.access(codelldbPath, fs4.constants.F_OK);
return new Promise((resolve2) => {
const child = spawn2(codelldbPath, ["--version"], {
stdio: ["ignore", "pipe", "pipe"]
});
let output = "";
child.stdout?.on("data", (data) => {
output += data.toString();
});
child.on("error", () => resolve2(false));
child.on("exit", (code) => {
resolve2(code === 0 && output.includes("codelldb"));
});
});
} catch {
return false;
}
},
/**
* Rust adapter doesn't require command queueing
*/
requiresCommandQueueing: () => false,
/**
* Rust doesn't need to queue commands
*/
shouldQueueCommand: () => {
return {
shouldQueue: false,
shouldDefer: false,
reason: "Rust/CodeLLDB adapter does not queue commands"
};
},
/**
* Create initial state for Rust adapter
*/
createInitialState: () => {
return {
initialized: false,
configurationDone: false
};
},
/**
* Update state when a command is sent
*/
updateStateOnCommand: (command, _args, state) => {
if (command === "configurationDone") {
state.configurationDone = true;
}
},
/**
* Update state when an event is received
*/
updateStateOnEvent: (event, _body, state) => {
if (event === "initialized") {
state.initialized = true;
}
},
/**
* Check if Rust adapter is initialized
*/
isInitialized: (state) => {
return state.initialized;
},
/**
* Check if Rust adapter is connected
*/
isConnected: (state) => {
return state.initialized;
},
/**
* Check if this policy applies to the given adapter command
*/
matchesAdapter: (adapterCommand) => {
const commandStr = adapterCommand.command.toLowerCase();
const argsStr = adapterCommand.args.join(" ").toLowerCase();
return commandStr.includes("codelldb") || commandStr.includes("lldb-server") || argsStr.includes("codelldb") || argsStr.includes("lldb");
},
/**
* Rust adapter has no special initialization requirements
*/
getInitializationBehavior: () => {
return {};
},
/**
* Rust DAP client behaviors - minimal since Rust doesn't use child sessions
*/
getDapClientBehavior: () => {
return {
// Rust doesn't handle reverse requests
handleReverseRequest: async (request, context) => {
if (request.command === "runInTerminal") {
context.sendResponse(request, {});
return { handled: true };
}
return { handled: false };
},
// No child session routing needed
childRoutedCommands: void 0,
// Rust-specific behaviors
mirrorBreakpointsToChild: false,
deferParentConfigDone: false,
pauseAfterChildAttach: false,
// No adapter ID normalization needed
normalizeAdapterId: void 0,
// Standard timeouts
childInitTimeout: 5e3,
suppressPostAttachConfigDone: false
};
},
/**
* Get the configuration for spawning the Rust debug adapter (CodeLLDB)
*/
getAdapterSpawnConfig: (payload) => {
if (payload.adapterCommand) {
return {
command: payload.adapterCommand.command,
args: payload.adapterCommand.args,
host: payload.adapterHost,
port: payload.adapterPort,
logDir: payload.logDir,
env: payload.adapterCommand.env
};
}
const platform = process.platform;
const arch = process.arch;
let platformDir = "";
if (platform === "win32") {
platformDir = "win32-x64";
} else if (platform === "darwin") {
platformDir = arch === "arm64" ? "darwin-arm64" : "darwin-x64";
} else if (platform === "linux") {
platformDir = arch === "arm64" ? "linux-arm64" : "linux-x64";
}
const codelldbPath = payload.executablePath || path.resolve(process.cwd(), "packages", "adapter-rust", "vendor", "codelldb", platformDir, "adapter", `codelldb${platform === "win32" ? ".exe" : ""}`);
return {
command: codelldbPath,
args: [
"--port",
String(payload.adapterPort)
],
host: payload.adapterHost,
port: payload.adapterPort,
logDir: payload.logDir,
env: {
...process.env,
// Windows specific: enable native PDB reader
...platform === "win32" ? { LLDB_USE_NATIVE_PDB_READER: "1" } : {}
}
};
}
};
}
});
// ../shared/dist/interfaces/adapter-policy-mock.js
var MockAdapterPolicy;
var init_adapter_policy_mock = __esm({
"../shared/dist/interfaces/adapter-policy-mock.js"() {
"use strict";
init_cjs_shims();
MockAdapterPolicy = {
name: "mock",
supportsReverseStartDebugging: false,
childSessionStrategy: "none",
shouldDeferParentConfigDone: () => false,
buildChildStartArgs: () => {
throw new Error("MockAdapterPolicy does not support child sessions");
},
isChildReadyEvent: (evt) => {
return evt?.event === "initialized";
},
/**
* Mock adapter doesn't need stack frame filtering
*/
filterStackFrames: (frames) => {
return frames;
},
/**
* Extract local variables for mock adapter (simple implementation)
*/
extractLocalVariables: (stackFrames, scopes, variables) => {
if (!stackFrames || stackFrames.length === 0) {
return [];
}
const topFrame = stackFrames[0];
const frameScopes = scopes[topFrame.id];
if (!frameScopes || frameScopes.length === 0) {
return [];
}
const localScope = frameScopes[0];
if (!localScope) {
return [];
}
return variables[localScope.variablesReference] || [];
},
/**
* Mock adapter uses simple scope names
*/
getLocalScopeName: () => {
return ["Local", "Locals"];
},
getDapAdapterConfiguration: () => {
return {
type: "mock"
// Mock adapter type for testing
};
},
resolveExecutablePath: (providedPath) => {
return providedPath || "mock";
},
getDebuggerConfiguration: () => {
return {
// Mock adapter configuration for testing
requiresStrictHandshake: false,
skipConfigurationDone: false,
supportsVariableType: false
// Mock adapter has simple variable support
};
},
/**
* Mock adapter doesn't require command queueing
*/
requiresCommandQueueing: () => false,
/**
* Mock adapter doesn't queue commands
*/
shouldQueueCommand: () => {
return {
shouldQueue: false,
shouldDefer: false,
reason: "Mock adapter does not queue commands"
};
},
/**
* Create initial state for mock adapter
*/
createInitialState: () => {
return {
initialized: false,
configurationDone: false
};
},
/**
* Update state when a command is sent
*/
updateStateOnCommand: (command, _args, state) => {
if (command === "configurationDone") {
state.configurationDone = true;
}
},
/**
* Update state when an event is received
*/
updateStateOnEvent: (event, _body, state) => {
if (event === "initialized") {
state.initialized = true;
}
},
/**
* Check if mock adapter is initialized
*/
isInitialized: (state) => {
return state.initialized;
},
/**
* Check if mock adapter is connected
*/
isConnected: (state) => {
return state.initialized;
},
/**
* Check if this policy applies to the given adapter command
*/
matchesAdapter: (adapterCommand) => {
const commandStr = adapterCommand.command.toLowerCase();
const argsStr = adapterCommand.args.join(" ").toLowerCase();
return commandStr.includes("mock-adapter") || argsStr.includes("mock-adapter");
},
/**
* Mock adapter has no special initialization requirements
*/
getInitializationBehavior: () => {
return {};
},
/**
* Mock DAP client behaviors - minimal for testing
*/
getDapClientBehavior: () => {
return {
// Mock doesn't handle reverse requests
handleReverseRequest: void 0,
// No child session routing needed for mock
childRoutedCommands: void 0,
// Mock-specific behaviors (all disabled)
mirrorBreakpointsToChild: false,
deferParentConfigDone: false,
pauseAfterChildAttach: false,
// No adapter ID normalization needed
normalizeAdapterId: void 0,
// Standard timeouts
childInitTimeout: 1e3,
// Shorter for testing
suppressPostAttachConfigDone: false
};
},
/**
* Get the configuration for spawning the mock debug adapter (for testing)