VS Code Extension Development
The VS Code extension source code is located in vscode/extension. It is a separate npm project that must be built before running the Python unit tests that depend on it.
Setup
-
Navigate to the extension directory:
bash cd vscode/extension -
Install dependencies:
bash npm install -
Build the extension:
bash npm run build
For development with auto-rebuild on changes:
bash
npm run watch
- Package and reinstall the VSIX when testing the installed extension:
bash npm run package code --install-extension dist/dapper-debugger-0.9.4.vsix --force
Notes:
- The package script writes the VSIX to vscode/extension/dist/.
- On WSL or remote setups, code may resolve to the VS Code remote CLI.
Use command -v code if you need the exact executable path.
- Reinstalling the VSIX updates the installed extension, but the active
extension host may still be running older code until the window reloads.
- After reinstalling, run Developer: Reload Window before reproducing
extension-host issues.
Running the Extension
- Open the
vscode/extensionfolder in VS Code. - Press
F5to launch the Extension Development Host.
The Extension Development Host opens a new VS Code window with the extension loaded. You can set breakpoints in the extension TypeScript source and debug it like any other Node.js project.
When you are debugging the packaged extension rather than the Extension
Development Host, prefer the package -> code --install-extension --force ->
Developer: Reload Window loop above. A rebuild alone does not update the code
running in the existing extension host.
For Agents
Dapper's LM tools are declared in vscode/extension/package.json and implemented under
vscode/extension/src/agent/tools/. The schema is intentionally compact; the notes below capture
the runtime behavior that is easy to miss.
The public tool surface currently includes dapper_cli, dapper_launch, dapper_state,
dapper_execution, dapper_evaluate, dapper_breakpoints, dapper_variable, and
dapper_session_info, dapper_python_environment, and
dapper_python_autofix, dapper_python_diagnostics, dapper_python_format,
dapper_python_project_model, dapper_python_rename, dapper_python_symbol, and
dapper_python_typecheck.
Command Interface
dapper_cliis a pdb-style command interface over the LM tool set.- The CLI supports semicolon-separated command chaining in a single request.
- Supported commands are
help/h,run,launch,sessions,info,inspect,state,diff,pause,restart,continue/c,next/n,step/s,finish,quit/q,break/b,breaks,clear,disable,enable,print/p,where/bt,locals,globals,list/l,up,down, andframe. helpreturns a pdb-style quick-start plus a full summary of the public Dapper LM tools and their top-level arguments.- Chained command execution stops on the first parse or runtime error and returns partial results for commands that already completed.
- When more than one Dapper session is active,
dapper_clirequires an explicitsessionIdrather than silently picking one. - Frame navigation updates the wrapper-managed
frameIndex, and laterprint,locals, andglobals, andinspectcalls use that selected frame. launchmay start an additional Dapper session even when another session is already active.launchnow returnstrackedSessionsBeforeLaunch,trackedSessions, andwarningsso agents can detect stale sessions before they stack up.- Launch debuggee arguments use
--as the end-of-options marker and pass all remaining tokens through asargs. breakfirst resolves explicit file paths, then unique Python filename stems in the workspace, then function names found in the selected session's current call stack; it also acceptsifconditions andlogmessages for conditional breakpoints and logpoints.breakslists the current VS Code source breakpoints and can filter down to one file or line throughdapper_breakpoints.
Session Resolution
- Most tools accept an optional
sessionId. - When
sessionIdis omitted, the tool resolves to the active Dapper debug session. - Many Python-oriented tools also accept an optional
searchRootPathto anchor the workspace folder used for tool execution in multi-root/nested-workspace scenarios. - Tools do not fall back to arbitrary non-Dapper sessions.
Launch and Session Readiness
dapper_launchnow returnsreadinessandreadyToContinuein addition to launch metadata.dapper_launchalso returnswarningswhen tracked sessions already exist, with a stronger warning when another session already targets the sameprogramormodule.dapper_session_infois the only public session-status surface; it now includes readiness fields, breakpoint counts, grouped breakpoint details, the last transition, and the last recorded error.- If
readyToContinueis false, checkbreakpoints.pending,breakpoints.rejected, andlastErrorbefore issuing execution commands. - For investigative launches, the expected cleanup path is
dapper_executionwithaction: terminateunless the session is being kept alive intentionally.
Snapshot and Journal Semantics
dapper_stateinsnapshotmode reads throughStateJournal.getSnapshot().- On a stop event, the journal first stores a placeholder snapshot with empty
callStack,locals, andglobals. A later custom request fills in the real data. - If that request fails,
StateJournalkeeps the last successful snapshot and records the failure inlastError. dapper_statecan therefore return cached data or_adapterErroreven when the session is still valid.
Execution Tools
dapper_executionwithreport: truecombines a DAP step request, a wait for a new stopped event, and a diff of locals, location, and output since the previous checkpoint.stopped: falsemeans the session did not report a new stop before the timeout or it terminated.dapper_executionwithoutreport: truereturns acknowledgement-oriented status strings (running,pausing,restarting,terminating) rather than waiting for all downstream events to settle.
Evaluation and Inspection
dapper_evaluateanddapper_variableboth execute expressions in the debuggee process.- They should be treated as potentially side-effecting operations.
dapper_evaluatenormalizes single-expression and multi-expression inputs into the same batch request format.dapper_variablerecursively expands dicts, lists, tuples, and public object attributes; it is better suited to structural inspection thandapper_evaluate.
Breakpoint Tools
dapper_breakpointsacceptslist,add,remove,clear,disable, andenable.- On
add, the extension updates the VS Code breakpoint registry and also sends a directsetBreakpointsrequest to the adapter so verification and registration happen immediately. remove,clear,disable, andenablenow also resync the adapter with the enabled source breakpoint set for the affected file.- On
list, it always reports the VS Code breakpoint list. If a Dapper session is active, it also re-queries adapter verification state and merges averifiedfield into the result when the adapter state is definitive. - If the adapter reports
verified: falsewithout a rejection message, the tool now reportsverificationState: pendinginstead of a hardverified: false. - Rejected breakpoints also expose
rejectionReason, which mirrors the adapter verification message when one is available. - If no active Dapper session is available, breakpoint data still returns, but
verifiedmay be missing.
Session Info Caveat
dapper_session_infocan enumerate tracked journals, but only the active VS Code session has a liveDebugSessionobject.- Non-active sessions may therefore carry stale runtime state even though the journal can still report readiness, breakpoint counts, and the last cached snapshot metadata.
Readiness Failures
- Execution requests now fail early when breakpoint verification is still pending or when a breakpoint was rejected.
configurationDonewaits for breakpoint verification and returns a concrete timeout message if the adapter never reaches a terminal readiness state.- When debugging agent issues, prefer inspecting
dapper_session_infobefore treating a session as generically broken.
Fixture Launch Configs
- Keep nested fixture launch examples as
.vscode/launch.template.jsonfiles rather than active.vscode/launch.jsonfiles. - This avoids noisy schema diagnostics in the repo workspace for custom Dapper-only fields such as
moduleSearchPathsor for the unregistered debug type outside the extension host.
Child Auto-Attach Transport
subprocessAutoAttach: trueallocates one shared child IPC listener per parent debug session in the extension rather than one listener per child.- Rewritten child launchers inherit that shared port with
--subprocess-ipc-portand connect back to it after startup. - The first child-side frame on that socket is an internal
dapper/sessionHellomessage carrying the logical childsessionId. ChildSessionManagercorrelates the socket with the pendingdapper/childProcessevent by thatsessionIdbefore constructing the childDapperDebugSession.- The
ipcPortfield exposed indapper/childProcessis therefore the shared listener port for the parent session, not a child-unique port.