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/.claude/settings.local.json +27 -1
- package/TODO.md +299 -0
- package/demo/DEMO.md +71 -0
- package/demo/order-processor.js +35 -0
- package/dist/main.js +1250 -187
- package/package.json +3 -1
- package/src/commands/attach.ts +2 -1
- package/src/commands/break-fn.ts +41 -0
- package/src/commands/launch.ts +2 -1
- package/src/daemon/client.ts +1 -1
- package/src/daemon/entry.ts +83 -45
- package/src/daemon/server.ts +67 -34
- package/src/daemon/session-breakpoints.ts +2 -1
- package/src/daemon/session-mutation.ts +1 -0
- package/src/daemon/session.ts +7 -5
- package/src/daemon/spawn.ts +21 -5
- package/src/dap/client.ts +252 -0
- package/src/dap/session.ts +1151 -0
- package/src/main.ts +1 -0
- package/src/protocol/messages.ts +12 -0
- package/tests/fixtures/dap/hello +0 -0
- package/tests/fixtures/dap/hello.c +8 -0
- package/tests/fixtures/dap/hello.dSYM/Contents/Info.plist +20 -0
- package/tests/fixtures/dap/hello.dSYM/Contents/Resources/DWARF/hello +0 -0
- package/tests/fixtures/dap/hello.dSYM/Contents/Resources/Relocations/aarch64/hello.yml +5 -0
- package/tests/fixtures/hotpatch-active-fn.js +7 -0
- package/tests/integration/daemon-logging.test.ts +8 -9
- package/tests/integration/mutation.test.ts +33 -0
- package/tests/unit/daemon-logger.test.ts +2 -2
- package/bun.lock +0 -60
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");
|
package/src/protocol/messages.ts
CHANGED
|
@@ -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,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>
|
|
Binary file
|
|
@@ -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 {
|
|
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
|
-
|
|
109
|
-
)
|
|
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
|
-
|
|
133
|
-
|
|
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 {
|
|
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
|
-
}
|