diff --git a/changelog.d/654.fixed.md b/changelog.d/654.fixed.md new file mode 100644 index 000000000..5c14fdabb --- /dev/null +++ b/changelog.d/654.fixed.md @@ -0,0 +1 @@ +**Attaching says up front that it will pause the target** — `create_debug_session` now advertises `stopOnEntry` for attach mode, and both it and `attach_to_process` state the default in the in-band schema (omitted = pause after attach; `false` = attach without stopping, required for a live service you still need to use), while `start_debugging.dapLaunchArgs.stopOnEntry` documents its opposite `false` default. When the post-attach pause has not landed by the time the tool answers, the `message` now names it (`…; post-attach pause pending — the target stops when it next executes code (pass stopOnEntry: false to attach without pausing)`) alongside the existing `pending: true`, instead of a bare `state: "running"` that reads as "nothing happened" seconds before the target freezes. `set_breakpoint` on an attach session no longer tells a caller who already passed `line` to "use line addressing instead" — it says to drop `expectedContent` and keep `line`. The attach default itself is unchanged (#654) diff --git a/docs/agent-debugging-guide.md b/docs/agent-debugging-guide.md index dd6b2d5fb..99b40f33f 100644 --- a/docs/agent-debugging-guide.md +++ b/docs/agent-debugging-guide.md @@ -13,7 +13,7 @@ This guide explains how to correctly use the MCP Debugger tools when testing deb **How it works:** - The multi-session architecture properly routes evaluate commands to the active debugging context - You can immediately evaluate expressions when stopped at breakpoints -- When `stopOnEntry` is false (the default), the debugger auto-continues past entry breakpoints so execution advances to user code automatically +- When `stopOnEntry` is false (the **launch** default), the debugger auto-continues past entry breakpoints so execution advances to user code automatically. Attach is the opposite: omitting `stopOnEntry` on `attach_to_process`/`create_debug_session` pauses the target (possibly a little after the response, reported as `pending: true`) — pass `stopOnEntry: false` to attach to a live service without freezing it ### Python Variable Inspection diff --git a/docs/cpp/README.md b/docs/cpp/README.md index 142f89368..ac031e35d 100644 --- a/docs/cpp/README.md +++ b/docs/cpp/README.md @@ -49,7 +49,7 @@ Compile with **`-gdwarf-4 -O0`**: full debug info, no optimization (optimized co attach_to_process sessionId=... processId= ``` -- The target is held paused after attach (`stopOnEntry` defaults to `true` for attach; pass `false` to resume immediately). +- The target is held paused after attach (`stopOnEntry` defaults to `true` for attach in every language, not just C/C++; pass `false` to resume immediately). - `detach_from_process` leaves the target running. - **Linux**: `kernel.yama.ptrace_scope=1` (the default on many distros) only allows attaching to child processes. For arbitrary processes: `sudo sysctl kernel.yama.ptrace_scope=0` (temporary) or run the server with `CAP_SYS_PTRACE`. - **Windows**: attach requires same-or-higher privilege than the target. diff --git a/docs/javascript/README.md b/docs/javascript/README.md index dafe740a6..6124d2fc9 100644 --- a/docs/javascript/README.md +++ b/docs/javascript/README.md @@ -223,6 +223,10 @@ If neither `tsx` nor `ts-node` is installed, the factory emits a warning (not an target, including pods via `kubectl port-forward` (see [attach presets](../../examples/kubernetes/attach-presets.md)); the target must be started with the inspector enabled, which mcp-debugger cannot do for you +- Attach pauses the target unless you pass `stopOnEntry: false`. js-debug's pause + lands on the next event-loop dispatch, so an idle server answers + `state: "running", pending: true` (the `message` names the pending pause) and + freezes on its next request — attach to a live server with `stopOnEntry: false` - Some advanced DAP features may not be exposed through MCP tools - Debuggee exit codes are captured via an injected preload (js-debug itself never emits a DAP `exited` event), so `exitCode` is unavailable in two diff --git a/docs/tool-reference.md b/docs/tool-reference.md index 2fe83e9f0..03b0fab08 100644 --- a/docs/tool-reference.md +++ b/docs/tool-reference.md @@ -56,6 +56,7 @@ Creates a new debugging session. - `executablePath` (string, optional): Path to the language interpreter/executable (e.g., Python interpreter path). - `host` (string, optional): Host to attach to for remote debugging. Defaults to `localhost`. - `port` (number, optional): Debug port to attach to. **Passing `port` switches the call into attach mode** — the session is created and immediately attached (see [attach_to_process](#attach_to_process) for the full attach contract). `host` alone does not trigger it. +- `stopOnEntry` (boolean, optional): Attach mode only — same semantics as [attach_to_process](#attach_to_process)'s `stopOnEntry`: **omitting it pauses the target after attach** (the pause may land after the response, reported as `pending: true` and named in `message`); pass `false` to attach to a live service without stopping it. - `timeout` (number, optional): Attach mode only — connection timeout in milliseconds (default: `30000`). - `verifyTimeout` (number, optional): Attach mode only — how long to wait (ms) for the debugger to report at least one thread after attaching before failing the attach (default: `20000`, max: `600000`). - `adapterConfig` (object, optional): Attach mode only — adapter-specific attach configuration merged into the attach config, with the same semantics as [attach_to_process](#attach_to_process)'s `adapterConfig`. @@ -80,7 +81,7 @@ Creates a new debugging session. **Notes:** - Session IDs are UUIDs in the format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` - Sessions start in `"created"` state -- When a `port` parameter is provided in `create_debug_session`, the server performs an inline attach (creating the session and immediately attaching to a running process on that port). The response then mirrors `attach_to_process`: alongside `sessionId` it carries `state`, the attach `data` payload, an optional `warning`, and — when a requested post-attach pause has not landed yet — `pending: true` +- When a `port` parameter is provided in `create_debug_session`, the server performs an inline attach (creating the session and immediately attaching to a running process on that port). The response then mirrors `attach_to_process`: alongside `sessionId` it carries `state`, the attach `data` payload, an optional `warning`, and — when a requested post-attach pause has not landed yet — `pending: true`, with `message` saying so (`…; post-attach pause pending — the target stops when it next executes code (pass stopOnEntry: false to attach without pausing)`) --- @@ -350,7 +351,7 @@ Starts debugging a script. - `scriptPath` (string, required): Path to the script to debug. Must be **absolute** in host mode (a relative path is rejected with `Path must be absolute`); in container mode it is re-rooted under `MCP_WORKSPACE_ROOT`. - `args` (array of strings, optional): Command line arguments for the script. - `dapLaunchArgs` (object, optional): Standard DAP launch arguments: - - `stopOnEntry` (boolean): Stop at first line + - `stopOnEntry` (boolean): Stop at first line (default `false` — the opposite of attach, which pauses unless `stopOnEntry` is `false`) - `justMyCode` (boolean): Debug only user code - Additional DAP launch keys (`program`, `cwd`, `env`, language-specific options) pass through to the adapter. Top-level parameters do **not** belong here: a nested `breakOnExceptions` is honored as an alias (the top-level value wins if both are given) and reported via a `warning` in the response; other misplaced top-level keys (`dryRunSpawn`, `sessionId`, `scriptPath`, `adapterLaunchConfig`) are stripped with a warning instead of silently riding into the launch config. - `adapterLaunchConfig` (object, optional): Adapter-specific launch configuration overrides. Use this for language-specific settings that go beyond standard DAP arguments (e.g., `mainClass` and `classpath` for Java, `buildCommand` for Rust). For Rust, `_adapterSettings` passes through to CodeLLDB (issue #441) — e.g. `{"_adapterSettings": {"scriptConfig": {"lang": {"rust": {"sysroot": "/path"}}}}}` points the Rust formatter lookup at an explicit sysroot; the `CODELLDB_RUST_SYSROOT` env var does the same without per-launch config (a user-supplied `_adapterSettings` value wins over the env var). @@ -1119,7 +1120,7 @@ Attaches the debugger to a running process. Unless you pass `stopOnEntry: false` - `timeout` (number, optional): Connection timeout in milliseconds (default: `30000`). - `verifyTimeout` (number, optional): How long to wait (ms) for the debugger to report at least one thread after attaching before failing the attach (default: `20000`, max: `600000`). Decrease for fast failure-by-design probes; increase for targets that are exceptionally slow to become debuggable. Not used when `stopOnEntry: false` — that path performs no thread verification. - `sourcePaths` (string[], optional): Source paths for code mapping. -- `stopOnEntry` (boolean, optional): Request a pause immediately after attaching. Anything but `false` — including omitting it — takes the verified path described above; `false` skips both the thread verification and the post-attach pause, and the attach returns `state: "running"`. +- `stopOnEntry` (boolean, optional): Request a pause immediately after attaching. Anything but `false` — including omitting it — takes the verified path described above; `false` skips both the thread verification and the post-attach pause, and the attach returns `state: "running"`. **Pass `false` when attaching to a live service you still need to use** — this is the opposite of `start_debugging`, whose `stopOnEntry` defaults to `false`. A pause that lands after the response is reported as `pending: true` and named in `message`. - `justMyCode` (boolean, optional): Only debug user code (skip library code). - `breakOnExceptions` (string, optional): `"uncaught"`, `"all"`, or `"none"` — same mode semantics as on `start_debugging`, but attach never applies a language default: it stays `"none"` unless requested. - `adapterConfig` (object, optional): Adapter-specific attach extras, merged into the attach config before the adapter transforms it, mirroring `start_debugging`'s `adapterLaunchConfig` (C/C++/LLDB example: `{"program": "/proc/1/root/pricer"}` for symbol resolution from a kubectl-debug ephemeral container, or `initCommands`; Python example: `{"pathMappings": [{"localRoot": "/home/user/checkout/src", "remoteRoot": "/app"}]}` so breakpoints at local-checkout paths bind against a remote debugpy, issue #450). Reserved keys `request`/`__attachMode` are ignored with a warning; set `stopOnEntry` via the top-level parameter. @@ -1136,8 +1137,22 @@ Attaches the debugger to a running process. Unless you pass `stopOnEntry: false` } ``` +When the requested pause has not landed by the time the tool answers (an idle Node server, say — js-debug's pause lands on the next event-loop dispatch), the response says so: +```json +{ + "success": true, + "state": "running", + "pending": true, + "message": "Attached to process at 127.0.0.1:9229; post-attach pause pending — the target stops when it next executes code (pass stopOnEntry: false to attach without pausing)", + "data": { + "message": "Attached to process at 127.0.0.1:9229; post-attach pause pending — the target stops when it next executes code (pass stopOnEntry: false to attach without pausing)", + "pending": true + } +} +``` + **Notes:** -- `state` is `"paused"` only once a stopped event has actually been observed; otherwise the attach reports `"running"`. When a requested post-attach pause is accepted but its stopped event has not arrived within the bounded wait, the response is successful with `state: "running"` and `pending: true` (at the top level and in `data`); the late stopped event is the only transition to `paused`, and every paused session has a `lastStop`. +- `state` is `"paused"` only once a stopped event has actually been observed; otherwise the attach reports `"running"`. When a requested post-attach pause is accepted but its stopped event has not arrived within the bounded wait, the response is successful with `state: "running"` and `pending: true` (at the top level and in `data`) and the `message` names the pending pause; the late stopped event is the only transition to `paused`, and every paused session has a `lastStop`. - When `processId` was used, the message reads `Attached to process PID ` instead. - The response `warning` reports two distinct `adapterConfig` key outcomes (issues #450/#466): keys the adapter's attach transform genuinely drops (e.g. Python's ptvsd-era `localRoot`/`remoteRoot` — use `pathMappings`) are named as **ignored**, while keys mcp-debugger doesn't recognize are **forwarded to the adapter as-is** and named with an edit-distance suggestion for near-misses (`pathMapping (did you mean pathMappings?)`) — "ignored" means dropped, "forwarded as-is" means the adapter still sees them. The same field also carries the launch-style warning for function breakpoints still unverified at attach (issue #308). - js-debug attach honors `adapterConfig` too: `localRoot`/`remoteRoot`/`sourceMaps`/`skipFiles`/`continueOnAttach` and other js-debug attach options reach the debugger (issue #466). diff --git a/examples/kubernetes/attach-presets.md b/examples/kubernetes/attach-presets.md index a68846cce..abbf00b2f 100644 --- a/examples/kubernetes/attach-presets.md +++ b/examples/kubernetes/attach-presets.md @@ -149,8 +149,8 @@ through `/proc//root/` — required because mount namespaces are not shared and `/proc/1/maps` paths aren't openable from the sidecar. The target is **PID 1** of the shared namespace when injected with `--target=app`. `--profile=general` is what injects `SYS_PTRACE` (nodes run -`kernel.yama.ptrace_scope=1`). `stopOnEntry` defaults to `true` for C/C++ -attach. Expect `` locals on `-O2` builds and symbol-only +`kernel.yama.ptrace_scope=1`). `stopOnEntry` defaults to `true` for attach in +every language (pass `false` to leave the target running). Expect `` locals on `-O2` builds and symbol-only breakpoints on stripped binaries. ## dotnet — no Kubernetes recipe today diff --git a/skills/debugging/SKILL.md b/skills/debugging/SKILL.md index 8c230638e..8b7bab10e 100644 --- a/skills/debugging/SKILL.md +++ b/skills/debugging/SKILL.md @@ -67,6 +67,7 @@ For an already-running process (including remote machines, containers, and Kuber attach_to_process {sessionId, host: "localhost", port: 5678, sourcePaths: [""], adapterConfig: {...}} ``` +- **Attach pauses the target by default** (omitting `stopOnEntry` means `true` — the opposite of `start_debugging`). Pass `stopOnEntry: false` for a live service you must not freeze. A response with `pending: true` means the pause lands when the target next runs code; `continue_execution` releases it. - **Python**: target ran `python -m debugpy --listen : ...`; to address breakpoints by local-checkout path, map it onto the debuggee tree with `adapterConfig: {pathMappings: [{localRoot: "", remoteRoot: "/app"}]}` - **Ruby**: target ran `rdbg --open --port ...` (works through `kubectl port-forward`); `localfsMap: "/app:"` maps paths - **Java**: target JVM has `-agentlib:jdwp=transport=dt_socket,server=y,address=*:`; breakpoints in not-yet-loaded classes are deferred automatically, and a fully-qualified class name as `file` needs no source files at all diff --git a/skills/debugging/references/cpp.md b/skills/debugging/references/cpp.md index 292840280..083cbfb15 100644 --- a/skills/debugging/references/cpp.md +++ b/skills/debugging/references/cpp.md @@ -31,7 +31,7 @@ close_debug_session {"sessionId": ""} attach_to_process {"sessionId": "", "processId": 4242} ``` -- Target is held **paused** after attach (pass `stopOnEntry: false` to resume immediately). `detach_from_process` leaves it running. +- Target is held **paused** after attach — the attach default for every language, not C/C++-specific (pass `stopOnEntry: false` to resume immediately). `detach_from_process` leaves it running. - Linux: `kernel.yama.ptrace_scope=1` limits attach to child processes — `sudo sysctl kernel.yama.ptrace_scope=0` for arbitrary PIDs. Windows: same-privilege processes. - Adapter extras go in `adapterConfig`: `{"adapterConfig": {"program": "/path/to/binary"}}` helps symbol resolution when LLDB cannot open the module paths from `/proc//maps` (different mount namespace — kubectl-debug sidecar: use `"/proc//root/"`); `initCommands` runs LLDB commands before attach. diff --git a/src/server.ts b/src/server.ts index ce2a1f4be..1fd9b39e8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -370,15 +370,24 @@ export class DebugMcpServer implements ToolContext { const resolved = await this.resolveBreakpointFile(req.sessionId, req.file, { requireExists: true }); const mode = getBpAddressingMode(this.environment); - const readLinesForContentAddressing = async (feature: string): Promise => { + const readLinesForContentAddressing = async ( + feature: 'statement addressing' | 'expectedContent' + ): Promise => { if (!resolved.contentAddressable) { // Two distinct causes, two honest reasons (issue #497): an attach // session's file may be perfectly readable here — the rule is that // the debuggee's loaded source is the authority, not the host's copy. + // The remedy is feature-specific (issue #654): an expectedContent + // caller already passed line, so "use line addressing instead" read + // as a contradiction — tell them what to drop, not what to add. + const remedy = + feature === 'expectedContent' + ? 'drop expectedContent and keep line — the breakpoint is set by plain line addressing.' + : 'use line addressing instead.'; const reason = resolved.nonAddressableReason === 'attach' - ? `${feature} is not supported for attach sessions — the debuggee's loaded source may not match the file on the mcp-debugger host. Use line addressing instead.` - : `${feature} requires a source file readable by the mcp-debugger server; "${req.file}" is a class name or remote path. Use line addressing instead.`; + ? `${feature} is not supported for attach sessions (the debuggee's loaded source may differ from the file on the mcp-debugger host); ${remedy}` + : `${feature} requires a source file readable by the mcp-debugger server; "${req.file}" is a class name or remote path — ${remedy}`; throw new McpError(McpErrorCode.InvalidParams, reason); } const lines = await this.lineReader.getFileLines(resolved.path); diff --git a/src/server/handlers/session-tools.ts b/src/server/handlers/session-tools.ts index 802c2ce7c..82e17353a 100644 --- a/src/server/handlers/session-tools.ts +++ b/src/server/handlers/session-tools.ts @@ -119,7 +119,10 @@ export const createDebugSessionTool: ToolHandler = async (ctx, args) => { sessionId: sessionInfo.id, state: attachResult.state, message: attachResult.success - ? `Created and attached ${sessionInfo.language} debug session: ${sessionInfo.name}` + ? `Created and attached ${sessionInfo.language} debug session: ${sessionInfo.name}` + + // The top-level message is what an agent reads; a pause that has + // not landed yet must be named here too, not only in data (#654). + (attachData?.pending ? `; ${ErrorMessages.attachPausePending}` : '') : `Created session but attach failed: ${attachResult.error || 'Unknown error'}`, ...(attachData?.pending ? { pending: true } : {}), ...(attachData ? { data: attachData } : {}), diff --git a/src/server/tool-schemas.ts b/src/server/tool-schemas.ts index 5c96726f4..81572cf6d 100644 --- a/src/server/tool-schemas.ts +++ b/src/server/tool-schemas.ts @@ -131,7 +131,7 @@ export function buildToolDefinitions(options: BuildToolDefinitionsOptions): Tool const getLocalVariablesRequired = varAccessExplicit ? ['sessionId', 'names'] : ['sessionId']; return [ - { name: 'create_debug_session', description: 'Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode', inputSchema: { type: 'object', properties: { language: { type: 'string', enum: supportedLanguages, description: 'Programming language for debugging' }, name: { type: 'string', description: 'Optional session name' }, executablePath: {type: 'string', description: 'Path to language executable (optional, will auto-detect if not provided)'}, host: { type: 'string', description: 'Host to attach to for remote debugging (optional, triggers attach mode)' }, port: { type: 'number', description: 'Debug port to attach to for remote debugging (optional, triggers attach mode)' }, timeout: { type: 'number', description: 'Connection timeout in milliseconds for attach mode (default: 30000)' }, verifyTimeout: { type: 'number', description: 'Attach mode only: how long to wait (ms) for the debugger to report at least one thread after attaching before failing the attach (default: 20000, max: 600000)' }, adapterConfig: { type: 'object', description: 'Attach mode only: adapter-specific attach configuration merged into the attach config (see attach_to_process)', additionalProperties: true } }, required: ['language'] } }, + { name: 'create_debug_session', description: 'Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false', inputSchema: { type: 'object', properties: { language: { type: 'string', enum: supportedLanguages, description: 'Programming language for debugging' }, name: { type: 'string', description: 'Optional session name' }, executablePath: {type: 'string', description: 'Path to language executable (optional, will auto-detect if not provided)'}, host: { type: 'string', description: 'Host to attach to for remote debugging (optional, triggers attach mode)' }, port: { type: 'number', description: 'Debug port to attach to for remote debugging (optional, triggers attach mode)' }, stopOnEntry: { type: 'boolean', description: 'Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it' }, timeout: { type: 'number', description: 'Connection timeout in milliseconds for attach mode (default: 30000)' }, verifyTimeout: { type: 'number', description: 'Attach mode only: how long to wait (ms) for the debugger to report at least one thread after attaching before failing the attach (default: 20000, max: 600000)' }, adapterConfig: { type: 'object', description: 'Attach mode only: adapter-specific attach configuration merged into the attach config (see attach_to_process)', additionalProperties: true } }, required: ['language'] } }, { name: 'list_supported_languages', description: 'List all supported debugging languages with metadata', inputSchema: { type: 'object', properties: {} } }, { name: 'list_debug_sessions', description: 'List all active debugging sessions. Paused sessions include lastStop with the reason for the most recent stop (e.g. "breakpoint" vs "exception")', inputSchema: { type: 'object', properties: {} } }, { name: 'set_breakpoint', description: 'Set a breakpoint. Setting breakpoints on non-executable lines (structural, declarative) may lead to unexpected behavior', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, file: { type: 'string', description: 'Path to the source file or Java FQCN. For Java, passing a fully-qualified class name (e.g. "com.example.MyClass" or "com.example.Outer$Inner") is preferred — it works reliably with all classloaders including custom classloaders. Alternatively, use absolute file paths.' }, line: { type: 'number', description: 'Line number where to set breakpoint. Executable statements (assignments, function calls, conditionals, returns) work best. Structural lines (function/class definitions), declarative lines (imports), or non-executable lines (comments, blank lines) may cause unexpected stepping behavior' }, ...setBreakpointExtraProps, condition: { type: 'string', description: 'Optional expression: only break (or log) when it evaluates truthy' }, logMessage: { type: 'string', description: 'Create a logpoint: instead of pausing, log this message when the line is hit. Expressions in {curly braces} are interpolated (e.g. "order={orderId} total={total}"). Messages arrive in get_output while the program runs at full speed. Supported by the Python, JavaScript, Go, Rust, C/C++, and mock adapters; not by Java, .NET, or Ruby' }, suspendPolicy: { type: 'string', enum: ['all', 'thread'], description: 'Suspend policy when breakpoint is hit: "all" suspends all threads (default), "thread" only suspends the event thread. Only supported by the Java/JDI adapter.' } }, required: setBreakpointRequired } }, @@ -147,7 +147,7 @@ export function buildToolDefinitions(options: BuildToolDefinitionsOptions): Tool dapLaunchArgs: { type: 'object', properties: { - stopOnEntry: { type: 'boolean' }, + stopOnEntry: { type: 'boolean', description: 'Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false' }, justMyCode: { type: 'boolean' } }, additionalProperties: true @@ -174,7 +174,7 @@ export function buildToolDefinitions(options: BuildToolDefinitionsOptions): Tool timeout: { type: 'number', description: 'Connection timeout in milliseconds (default: 30000)' }, verifyTimeout: { type: 'number', description: 'How long to wait (ms) for the debugger to report at least one thread after attaching before failing the attach (default: 20000, max: 600000). Decrease for fast failure-by-design probes; increase for targets that are exceptionally slow to become debuggable' }, sourcePaths: { type: 'array', items: { type: 'string' }, description: 'Source paths for code mapping' }, - stopOnEntry: { type: 'boolean', description: 'Stop on entry after attaching' }, + stopOnEntry: { type: 'boolean', description: 'Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service' }, justMyCode: { type: 'boolean', description: 'Only debug user code (skip library code)' }, breakOnExceptions: { type: 'string', enum: ['uncaught', 'all', 'none'], description: 'Break when exceptions are thrown: "uncaught" pauses at uncaught exceptions at the crash site; "all" also pauses on caught/raised exceptions (language-dependent). Default "none" — attach sessions never apply a language default (unlike launch)' }, adapterConfig: { type: 'object', description: 'Adapter-specific attach configuration merged into the attach config before the adapter transforms it (e.g. C/C++/LLDB: program — the binary path for symbol resolution when /proc//maps paths are not openable, as in a kubectl-debug ephemeral container — or initCommands like "settings set target.exec-search-paths /proc//root"). Reserved keys request/__attachMode are ignored; set stopOnEntry via the top-level parameter. Keys the adapter does not recognize are still forwarded to the debugger and named in the response warning — a near-miss of a supported key gets a did-you-mean suggestion. js-debug pins its attach orchestration keys (address/port/continueOnAttach/attachExistingChildren) over caller values; its autoAttachChildProcesses defaults to false on attach — child processes the target forks run undebugged (set it true to auto-attach children; only one child can be adopted at a time, further children are resumed undebugged)', additionalProperties: true } diff --git a/src/session/attach/attach-controller.ts b/src/session/attach/attach-controller.ts index cc643b250..d14a02dd3 100644 --- a/src/session/attach/attach-controller.ts +++ b/src/session/attach/attach-controller.ts @@ -299,10 +299,16 @@ export class AttachController { // inside the builder. const attachFnBpWarning = this.breakpoints.functionBreakpointLaunchWarning(session); + const attachedTo = attachConfig.processId + ? `Attached to process PID ${attachConfig.processId}` + : `Attached to process at ${attachConfig.host || 'localhost'}:${attachConfig.port}`; + // A late-landing pause must be named in the message, not only flagged: + // pending:true next to state "running" reads as "nothing happened" to + // an agent, and the target still freezes on its next dispatch (#654). const attachData: AttachResultData = { - message: attachConfig.processId - ? `Attached to process PID ${attachConfig.processId}` - : `Attached to process at ${attachConfig.host || 'localhost'}:${attachConfig.port}`, + message: attachPausePending + ? `${attachedTo}; ${ErrorMessages.attachPausePending}` + : attachedTo, ...(attachPausePending ? { pending: true } : {}) }; // Surface adapterConfig keys the adapter's attach transform dropped diff --git a/src/utils/error-messages.ts b/src/utils/error-messages.ts index ade19ec46..8811d8320 100644 --- a/src/utils/error-messages.ts +++ b/src/utils/error-messages.ts @@ -112,6 +112,18 @@ export const ErrorMessages = { `'paused' once the stop lands. Check the session state to confirm.`, + /** + * Suffix appended to the attach message when the post-attach pause was + * requested (explicitly or by the default) but no 'stopped' event arrived + * within the bounded wait, so the response reports state "running" with + * pending:true while the target will still freeze on its next dispatch + * (issue #654: attaching to a live server without stopOnEntry:false froze + * it seconds later with nothing in the response saying a pause was coming) + * Used in: src/session/attach/attach-controller.ts, src/server/handlers/session-tools.ts + */ + attachPausePending: + 'post-attach pause pending — the target stops when it next executes code (pass stopOnEntry: false to attach without pausing)', + /** * Error message for attach verification failures * Occurs when: After an attach handshake, the debugger does not report any diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-true.json index c8426f46f..206266b36 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -203,7 +207,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -292,7 +297,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-unset.json index 76e63e2f1..9a07d2db4 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-explicit.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -203,7 +207,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -292,7 +297,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-true.json index 335de611b..39b0ff471 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -203,7 +207,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -292,7 +297,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-unset.json index 71891d3b1..2cacb61a4 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-open.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -203,7 +207,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -292,7 +297,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-true.json index 335de611b..39b0ff471 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -203,7 +207,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -292,7 +297,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-unset.json index 71891d3b1..2cacb61a4 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-assert.va-unset.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -203,7 +207,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -292,7 +297,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-true.json index 527471e1b..47a34976e 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-unset.json index a8fb151c5..6e44a2d93 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-explicit.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-true.json index 02def8350..96c722860 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-unset.json index 355dcb810..6428b6c7a 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-open.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-true.json index 02def8350..96c722860 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-unset.json index 355dcb810..6428b6c7a 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-content.va-unset.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-true.json index 7e9cfe825..bf3b16ec7 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -199,7 +203,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -288,7 +293,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-unset.json index 1e1f7b5c4..9a2881231 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-explicit.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -199,7 +203,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -288,7 +293,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-true.json index 821f4b721..aa9b1dfa4 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -199,7 +203,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -288,7 +293,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-unset.json index 4546cad53..32276d0df 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-open.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -199,7 +203,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -288,7 +293,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-true.json index 821f4b721..aa9b1dfa4 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -199,7 +203,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -288,7 +293,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-unset.json index 4546cad53..32276d0df 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-line.va-unset.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -199,7 +203,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -288,7 +293,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-true.json index 527471e1b..47a34976e 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-unset.json index a8fb151c5..6e44a2d93 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-explicit.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-true.json index 02def8350..96c722860 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-unset.json index 355dcb810..6428b6c7a 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-open.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-true.json b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-true.json index 02def8350..96c722860 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-true.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-true.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-unset.json b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-unset.json index 355dcb810..6428b6c7a 100644 --- a/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-unset.json +++ b/tests/core/unit/server/__snapshots__/tool-list/bp-unset.va-unset.container-unset.json @@ -3,7 +3,7 @@ "tools": [ { "name": "create_debug_session", - "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode", + "description": "Create a new debugging session. Provide host and port to attach to a running process; omit them for launch mode. Attaching pauses the target unless stopOnEntry is false", "inputSchema": { "type": "object", "properties": { @@ -31,6 +31,10 @@ "type": "number", "description": "Debug port to attach to for remote debugging (optional, triggers attach mode)" }, + "stopOnEntry": { + "type": "boolean", + "description": "Attach mode only: same as attach_to_process.stopOnEntry — omitted means true, the target is paused after attach (possibly late, reported as pending:true). Pass false to attach to a live service without stopping it" + }, "timeout": { "type": "number", "description": "Connection timeout in milliseconds for attach mode (default: 30000)" @@ -213,7 +217,8 @@ "type": "object", "properties": { "stopOnEntry": { - "type": "boolean" + "type": "boolean", + "description": "Pause at the first line before running. Default false — the opposite of attach, which pauses unless stopOnEntry is false" }, "justMyCode": { "type": "boolean" @@ -302,7 +307,7 @@ }, "stopOnEntry": { "type": "boolean", - "description": "Stop on entry after attaching" + "description": "Pause the target after attaching. Default true when omitted (thread verification, then a pause request; if the stop lands after the response you get pending:true and the target still freezes on its next dispatch). Pass false to attach without stopping — required when attaching to a live service" }, "justMyCode": { "type": "boolean", diff --git a/tests/core/unit/server/server-redefine-and-attach.test.ts b/tests/core/unit/server/server-redefine-and-attach.test.ts index 73a738086..728b51c89 100644 --- a/tests/core/unit/server/server-redefine-and-attach.test.ts +++ b/tests/core/unit/server/server-redefine-and-attach.test.ts @@ -522,6 +522,72 @@ describe('redefine_classes and attach stopOnEntry tests', () => { expect(payload.warning).toContain('remoteRoot'); expect(payload.data.warning).toContain('remoteRoot'); }); + + it('names a pending post-attach pause in the top-level message of a create_debug_session inline attach (issue #654)', async () => { + const sessionInfo: DebugSessionInfo = { + id: 'inline-attach-session', + name: 'inline', + language: 'python' as DebugLanguage, + state: 'created' as SessionState, + createdAt: new Date(), + updatedAt: new Date() + }; + mockSessionManager.createSession.mockResolvedValue(sessionInfo); + mockSessionManager.attachToProcess.mockResolvedValue({ + success: true, + state: 'running', + data: { + message: 'Attached to process at 127.0.0.1:9229; post-attach pause pending — the target stops when it next executes code (pass stopOnEntry: false to attach without pausing)', + pending: true + } + }); + + const result = await callToolHandler({ + method: 'tools/call', + params: { + name: 'create_debug_session', + arguments: { language: 'python', host: '127.0.0.1', port: 5678 } + } + }); + + const payload = JSON.parse(result.content[0].text); + expect(payload.success).toBe(true); + expect(payload.state).toBe('running'); + expect(payload.pending).toBe(true); + expect(payload.message).toMatch(/^Created and attached python debug session: inline; post-attach pause pending/); + expect(payload.message).toMatch(/stopOnEntry: false/); + expect(payload.data.pending).toBe(true); + }); + + it('keeps the plain create_debug_session message when the attach pause was observed', async () => { + const sessionInfo: DebugSessionInfo = { + id: 'inline-attach-session', + name: 'inline', + language: 'python' as DebugLanguage, + state: 'created' as SessionState, + createdAt: new Date(), + updatedAt: new Date() + }; + mockSessionManager.createSession.mockResolvedValue(sessionInfo); + mockSessionManager.attachToProcess.mockResolvedValue({ + success: true, + state: 'paused', + data: { message: 'Attached to process at 127.0.0.1:9229' } + }); + + const result = await callToolHandler({ + method: 'tools/call', + params: { + name: 'create_debug_session', + arguments: { language: 'python', host: '127.0.0.1', port: 5678 } + } + }); + + const payload = JSON.parse(result.content[0].text); + expect(payload.state).toBe('paused'); + expect(payload.pending).toBeUndefined(); + expect(payload.message).toBe('Created and attached python debug session: inline'); + }); }); describe('attach warning join (issue #450)', () => { diff --git a/tests/core/unit/server/server-statement-anchor.test.ts b/tests/core/unit/server/server-statement-anchor.test.ts index d46708d15..06f1a7f86 100644 --- a/tests/core/unit/server/server-statement-anchor.test.ts +++ b/tests/core/unit/server/server-statement-anchor.test.ts @@ -342,6 +342,10 @@ describe('set_breakpoint statement anchors (#271)', () => { expect(err.message).toMatch(/expectedContent/); expect(err.message).toMatch(/not supported for attach sessions/); expect(err.message).not.toMatch(/class name or remote path/); + // The caller already passed line: the remedy must say what to drop, + // not "use line addressing instead" (issue #654) + expect(err.message).toMatch(/drop expectedContent and keep line/); + expect(err.message).not.toMatch(/use line addressing instead/i); }); it('keeps the class-name wording for non-file source identifiers', async () => { diff --git a/tests/unit/session-manager-operations-coverage.test.ts b/tests/unit/session-manager-operations-coverage.test.ts index aa991c588..e67c52554 100644 --- a/tests/unit/session-manager-operations-coverage.test.ts +++ b/tests/unit/session-manager-operations-coverage.test.ts @@ -2437,6 +2437,9 @@ describe('Session Manager Operations Coverage - Error Paths and Edge Cases', () expect(result.success).toBe(true); expect(result.state).toBe(SessionState.RUNNING); expect(result.data?.pending).toBe(true); + // A pending pause is named in the message, not only flagged (issue #654) + expect(result.data?.message).toMatch(/^Attached to process at localhost:5005; post-attach pause pending/); + expect(result.data?.message).toMatch(/stopOnEntry: false/); expect(threadCalls).toBeGreaterThanOrEqual(3); expect(mockProxyManager.setCurrentThreadId).toHaveBeenCalledWith(7); }); @@ -2597,6 +2600,7 @@ describe('Session Manager Operations Coverage - Error Paths and Edge Cases', () expect(mockProxyManager.sendDapRequest).toHaveBeenCalledWith('pause', { threadId: 1 }); expect(result.state).toBe(SessionState.RUNNING); expect(result.data?.pending).toBe(true); + expect(result.data?.message).toMatch(/post-attach pause pending/); expect(mockSession.lastStop).toBeUndefined(); }); @@ -2632,6 +2636,7 @@ describe('Session Manager Operations Coverage - Error Paths and Edge Cases', () expect(result.success).toBe(true); expect(result.state).toBe(SessionState.PAUSED); expect(result.data?.pending).toBeUndefined(); + expect(result.data?.message).toBe('Attached to process at 127.0.0.1:12345'); expect(mockSession.lastStop?.reason).toBe('pause'); });