agent-dbg 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/main.ts CHANGED
@@ -15,6 +15,7 @@ if (process.argv.includes("--daemon")) {
15
15
  await import("./commands/pause.ts");
16
16
  await import("./commands/run-to.ts");
17
17
  await import("./commands/break.ts");
18
+ await import("./commands/break-fn.ts");
18
19
  await import("./commands/break-rm.ts");
19
20
  await import("./commands/break-ls.ts");
20
21
  await import("./commands/logpoint.ts");
@@ -10,6 +10,7 @@ const LaunchRequest = z.object({
10
10
  command: z.array(z.string()),
11
11
  brk: z.optional(z.boolean()),
12
12
  port: z.optional(z.number()),
13
+ runtime: z.optional(z.string()),
13
14
  }),
14
15
  });
15
16
 
@@ -17,6 +18,7 @@ const AttachRequest = z.object({
17
18
  cmd: z.literal("attach"),
18
19
  args: z.object({
19
20
  target: z.string(),
21
+ runtime: z.optional(z.string()),
20
22
  }),
21
23
  });
22
24
 
@@ -65,6 +67,15 @@ const BreakRequest = z.object({
65
67
  condition: z.optional(z.string()),
66
68
  hitCount: z.optional(z.number()),
67
69
  urlRegex: z.optional(z.string()),
70
+ column: z.optional(z.number()),
71
+ }),
72
+ });
73
+
74
+ const BreakFnRequest = z.object({
75
+ cmd: z.literal("break-fn"),
76
+ args: z.object({
77
+ name: z.string(),
78
+ condition: z.optional(z.string()),
68
79
  }),
69
80
  });
70
81
 
@@ -271,6 +282,7 @@ export const DaemonRequestSchema = z.union([
271
282
  PauseRequest,
272
283
  RunToRequest,
273
284
  BreakRequest,
285
+ BreakFnRequest,
274
286
  BreakRmRequest,
275
287
  BreakLsRequest,
276
288
  LogpointRequest,
Binary file
@@ -0,0 +1,8 @@
1
+ #include <stdio.h>
2
+
3
+ int main() {
4
+ int x = 42;
5
+ int y = x + 1;
6
+ printf("x=%d y=%d\n", x, y);
7
+ return 0;
8
+ }
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>English</string>
7
+ <key>CFBundleIdentifier</key>
8
+ <string>com.apple.xcode.dsym.hello</string>
9
+ <key>CFBundleInfoDictionaryVersion</key>
10
+ <string>6.0</string>
11
+ <key>CFBundlePackageType</key>
12
+ <string>dSYM</string>
13
+ <key>CFBundleSignature</key>
14
+ <string>????</string>
15
+ <key>CFBundleShortVersionString</key>
16
+ <string>1.0</string>
17
+ <key>CFBundleVersion</key>
18
+ <string>1</string>
19
+ </dict>
20
+ </plist>
@@ -0,0 +1,5 @@
1
+ ---
2
+ triple: 'arm64-apple-darwin'
3
+ binary-path: '/Users/waltoss/Code/Theodo/OpenSource/agent-dbg/tests/fixtures/dap/hello'
4
+ relocations: []
5
+ ...
@@ -0,0 +1,7 @@
1
+ // Fixture: hotpatch while function is on the call stack
2
+ function compute(x) {
3
+ debugger;
4
+ return x * 2;
5
+ }
6
+ const result = compute(21);
7
+ console.log("result:", result);
@@ -1,9 +1,9 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import { existsSync, readFileSync, unlinkSync } from "node:fs";
3
- import { join } from "node:path";
4
3
  import { tmpdir } from "node:os";
5
- import { DaemonLogger } from "../../src/daemon/logger.ts";
4
+ import { join } from "node:path";
6
5
  import type { DaemonLogEntry } from "../../src/daemon/logger.ts";
6
+ import { DaemonLogger } from "../../src/daemon/logger.ts";
7
7
  import { getDaemonLogPath } from "../../src/daemon/paths.ts";
8
8
  import { DebugSession } from "../../src/daemon/session.ts";
9
9
 
@@ -104,9 +104,9 @@ describe("DaemonLogger integration", () => {
104
104
  const logPath = getDaemonLogPath(sessionName);
105
105
  try {
106
106
  // Use echo (not node), which won't emit an inspector URL
107
- await expect(
108
- session.launch(["echo", "hello"], { brk: true }),
109
- ).rejects.toThrow("Failed to detect inspector URL");
107
+ await expect(session.launch(["echo", "hello"], { brk: true })).rejects.toThrow(
108
+ "Failed to detect inspector URL",
109
+ );
110
110
 
111
111
  const entries = readEntries(logPath);
112
112
  expect(hasEvent(entries, "child.spawn")).toBe(true);
@@ -128,10 +128,9 @@ describe("DaemonLogger integration", () => {
128
128
  // Use process.exit() to force the child to terminate.
129
129
  // Node.js waits for the debugger to disconnect before exiting,
130
130
  // so we disconnect CDP after a delay to allow the natural exit.
131
- await session.launch(
132
- ["node", "-e", "setTimeout(() => process.exit(0), 200)"],
133
- { brk: false },
134
- );
131
+ await session.launch(["node", "-e", "setTimeout(() => process.exit(0), 200)"], {
132
+ brk: false,
133
+ });
135
134
 
136
135
  // Disconnect CDP so Node.js can actually exit
137
136
  // (Node prints "Waiting for the debugger to disconnect..." otherwise)
@@ -165,6 +165,39 @@ describe("Mutation: hotpatch", () => {
165
165
  }
166
166
  });
167
167
 
168
+ test("hotpatch works when edited function is on the call stack", async () => {
169
+ const session = new DebugSession("test-hotpatch-active-fn");
170
+ try {
171
+ await session.launch(["node", "tests/fixtures/hotpatch-active-fn.js"], {
172
+ brk: true,
173
+ });
174
+ await waitForState(session, "paused");
175
+
176
+ // Continue past --brk to the `debugger;` inside compute()
177
+ await session.continue();
178
+ await waitForState(session, "paused");
179
+
180
+ // We're now paused inside compute() — it's on the call stack
181
+ expect(session.isPaused()).toBe(true);
182
+
183
+ // Get original source and modify compute to multiply by 3 instead of 2
184
+ const source = await session.getSource({ file: "hotpatch-active-fn.js", all: true });
185
+ const originalText = source.lines.map((l) => l.text).join("\n");
186
+ const modifiedSource = originalText.replace("x * 2", "x * 3");
187
+
188
+ // Hotpatch should succeed thanks to allowTopFrameEditing
189
+ const result = await session.hotpatch("hotpatch-active-fn.js", modifiedSource);
190
+ expect(result.status).toBe("Ok");
191
+
192
+ // Verify source was updated
193
+ const newSource = await session.getSource({ file: "hotpatch-active-fn.js", all: true });
194
+ const newText = newSource.lines.map((l) => l.text).join("\n");
195
+ expect(newText).toContain("x * 3");
196
+ } finally {
197
+ await session.stop();
198
+ }
199
+ });
200
+
168
201
  test("hotpatch throws for unknown file", async () => {
169
202
  const session = await launchAndPauseAtDebugger("test-hotpatch-unknown");
170
203
  try {
@@ -1,9 +1,9 @@
1
1
  import { afterEach, describe, expect, test } from "bun:test";
2
2
  import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
3
- import { join } from "node:path";
4
3
  import { tmpdir } from "node:os";
5
- import { DaemonLogger } from "../../src/daemon/logger.ts";
4
+ import { join } from "node:path";
6
5
  import type { DaemonLogEntry } from "../../src/daemon/logger.ts";
6
+ import { DaemonLogger } from "../../src/daemon/logger.ts";
7
7
 
8
8
  const testDir = tmpdir();
9
9
 
package/bun.lock DELETED
@@ -1,60 +0,0 @@
1
- {
2
- "lockfileVersion": 1,
3
- "configVersion": 1,
4
- "workspaces": {
5
- "": {
6
- "name": "ndbg",
7
- "dependencies": {
8
- "@jridgewell/trace-mapping": "^0.3.31",
9
- "zod": "^4.0.0",
10
- },
11
- "devDependencies": {
12
- "@biomejs/biome": "^2.3.14",
13
- "@types/bun": "latest",
14
- "devtools-protocol": "^0.0.1581282",
15
- },
16
- "peerDependencies": {
17
- "typescript": "^5",
18
- },
19
- },
20
- },
21
- "packages": {
22
- "@biomejs/biome": ["@biomejs/biome@2.3.14", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.14", "@biomejs/cli-darwin-x64": "2.3.14", "@biomejs/cli-linux-arm64": "2.3.14", "@biomejs/cli-linux-arm64-musl": "2.3.14", "@biomejs/cli-linux-x64": "2.3.14", "@biomejs/cli-linux-x64-musl": "2.3.14", "@biomejs/cli-win32-arm64": "2.3.14", "@biomejs/cli-win32-x64": "2.3.14" }, "bin": { "biome": "bin/biome" } }, "sha512-QMT6QviX0WqXJCaiqVMiBUCr5WRQ1iFSjvOLoTk6auKukJMvnMzWucXpwZB0e8F00/1/BsS9DzcKgWH+CLqVuA=="],
23
-
24
- "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UJGPpvWJMkLxSRtpCAKfKh41Q4JJXisvxZL8ChN1eNW3m/WlPFJ6EFDCE7YfUb4XS8ZFi3C1dFpxUJ0Ety5n+A=="],
25
-
26
- "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-PNkLNQG6RLo8lG7QoWe/hhnMxJIt1tEimoXpGQjwS/dkdNiKBLPv4RpeQl8o3s1OKI3ZOR5XPiYtmbGGHAOnLA=="],
27
-
28
- "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-KT67FKfzIw6DNnUNdYlBg+eU24Go3n75GWK6NwU4+yJmDYFe9i/MjiI+U/iEzKvo0g7G7MZqoyrhIYuND2w8QQ=="],
29
-
30
- "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-LInRbXhYujtL3sH2TMCH/UBwJZsoGwfQjBrMfl84CD4hL/41C/EU5mldqf1yoFpsI0iPWuU83U+nB2TUUypWeg=="],
31
-
32
- "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.14", "", { "os": "linux", "cpu": "x64" }, "sha512-ZsZzQsl9U+wxFrGGS4f6UxREUlgHwmEfu1IrXlgNFrNnd5Th6lIJr8KmSzu/+meSa9f4rzFrbEW9LBBA6ScoMA=="],
33
-
34
- "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.14", "", { "os": "linux", "cpu": "x64" }, "sha512-KQU7EkbBBuHPW3/rAcoiVmhlPtDSGOGRPv9js7qJVpYTzjQmVR+C9Rfcz+ti8YCH+zT1J52tuBybtP4IodjxZQ=="],
35
-
36
- "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-+IKYkj/pUBbnRf1G1+RlyA3LWiDgra1xpS7H2g4BuOzzRbRB+hmlw0yFsLprHhbbt7jUzbzAbAjK/Pn0FDnh1A=="],
37
-
38
- "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.14", "", { "os": "win32", "cpu": "x64" }, "sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ=="],
39
-
40
- "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
41
-
42
- "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
43
-
44
- "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
45
-
46
- "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
47
-
48
- "@types/node": ["@types/node@25.2.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ=="],
49
-
50
- "bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],
51
-
52
- "devtools-protocol": ["devtools-protocol@0.0.1581282", "", {}, "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ=="],
53
-
54
- "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
55
-
56
- "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
57
-
58
- "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
59
- }
60
- }