agent-dag 1.15.5 → 1.16.0

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.
@@ -1,14 +1,14 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>agent-dag</title>
7
- <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ctext y='84' font-size='84'%3E%E2%97%89%3C/text%3E%3C/svg%3E" />
8
- <script type="module" crossorigin src="/assets/index-DQ6TO5CH.js"></script>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>agent-dag</title>
7
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ctext y='84' font-size='84'%3E%E2%97%89%3C/text%3E%3C/svg%3E" />
8
+ <script type="module" crossorigin src="/assets/index-DNuLi1zC.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-Bwj0xSAo.css">
10
- </head>
11
- <body>
12
- <div id="root"></div>
13
- </body>
14
- </html>
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
package/hook/hook.js CHANGED
@@ -1,96 +1,110 @@
1
- #!/usr/bin/env node
2
- // agent-dag hook forwarder. Claude Code invokes this as a command hook.
3
- // It reads stdin (CC event JSON), finds the matching agent-dag server via
4
- // per-workspace discovery files in ~/.claude/agent-dag/, and forwards the
5
- // payload to it via HTTP POST. Dead instances are cleaned up.
6
- "use strict";
7
-
8
- const fs = require("fs");
9
- const path = require("path");
10
- const http = require("http");
11
- const os = require("os");
12
-
13
- // Hard cap so a stuck server can never wedge Claude Code.
14
- setTimeout(() => process.exit(0), 1500);
15
-
16
- const DIR = path.join(os.homedir(), ".claude", "agent-dag");
17
- const IS_WIN = process.platform === "win32";
18
-
19
- function normPath(p) {
20
- let r = path.resolve(p);
21
- try { r = fs.realpathSync(r); } catch {}
22
- return r;
23
- }
24
-
25
- function isAlive(pid) {
26
- // process.kill(pid, 0) works on Windows in Node 18+:
27
- // ESRCH => no such process, EPERM => exists but not ours (still alive).
28
- try { process.kill(pid, 0); return true; }
29
- catch (e) { return e && e.code === "EPERM"; }
30
- }
31
-
32
- let input = "";
33
- process.stdin.setEncoding("utf8");
34
- process.stdin.on("data", c => { input += c; });
35
- process.stdin.on("end", () => {
36
- let cwd;
37
- try { cwd = JSON.parse(input).cwd; } catch { return process.exit(0); }
38
- if (!cwd) return process.exit(0);
39
-
40
- const resolvedCwd = normPath(cwd);
41
-
42
- let files;
43
- try {
44
- files = fs.readdirSync(DIR).filter(f => f.endsWith(".json"));
45
- } catch { return process.exit(0); }
46
- if (!files.length) return process.exit(0);
47
-
48
- const matches = [];
49
- for (const file of files) {
50
- let d;
51
- try { d = JSON.parse(fs.readFileSync(path.join(DIR, file), "utf8")); } catch { continue; }
52
- if (typeof d.workspace !== "string" || !d.pid || !d.port) continue;
53
-
54
- if (!isAlive(d.pid)) {
55
- try { fs.unlinkSync(path.join(DIR, file)); } catch {}
56
- continue;
57
- }
58
-
59
- // Empty workspace = match-all (used by `agent-dag --all`).
60
- if (d.workspace === "") {
61
- matches.push({ d, wsLen: 0 });
62
- continue;
63
- }
64
- const ws = normPath(d.workspace);
65
- if (resolvedCwd === ws || resolvedCwd.startsWith(ws + path.sep)) {
66
- matches.push({ d, wsLen: ws.length });
67
- }
68
- }
69
-
70
- if (!matches.length) return process.exit(0);
71
-
72
- // Most specific workspace wins.
73
- matches.sort((a, b) => b.wsLen - a.wsLen);
74
- const bestLen = matches[0].wsLen;
75
- const targets = matches.filter(m => m.wsLen === bestLen);
76
-
77
- let pending = targets.length;
78
- const done = () => { if (--pending <= 0) process.exit(0); };
79
-
80
- for (const { d } of targets) {
81
- let settled = false;
82
- const finish = () => { if (settled) return; settled = true; done(); };
83
- const req = http.request({
84
- hostname: "127.0.0.1",
85
- port: d.port,
86
- path: "/api/event",
87
- method: "POST",
88
- headers: { "Content-Type": "application/json" },
89
- timeout: 1000,
90
- }, res => { res.resume(); res.on("end", finish); });
91
- req.on("error", finish);
92
- req.on("timeout", () => req.destroy());
93
- req.write(input);
94
- req.end();
95
- }
96
- });
1
+ #!/usr/bin/env node
2
+ // agent-dag hook forwarder. Invoked by Claude Code or Codex CLI as a command
3
+ // hook. Reads stdin (event JSON), tags it with the provider passed via
4
+ // `--provider <name>`, finds the matching agent-dag server via per-workspace
5
+ // discovery files in ~/.claude/agent-dag/, and POSTs the payload. Dead
6
+ // instances are cleaned up.
7
+ "use strict";
8
+
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+ const http = require("http");
12
+ const os = require("os");
13
+
14
+ // Hard cap so a stuck server can never wedge the host CLI.
15
+ setTimeout(() => process.exit(0), 1500);
16
+
17
+ // Single shared discovery dir — Claude Code and Codex CLI both register here
18
+ // via the installer. Lets one running agent-dag server receive both providers.
19
+ const DIR = path.join(os.homedir(), ".claude", "agent-dag");
20
+
21
+ function parseProvider(argv) {
22
+ for (let i = 0; i < argv.length; i++) {
23
+ if (argv[i] === "--provider" && i + 1 < argv.length) return argv[i + 1];
24
+ }
25
+ return "claude";
26
+ }
27
+ const PROVIDER = parseProvider(process.argv.slice(2));
28
+
29
+ function normPath(p) {
30
+ let r = path.resolve(p);
31
+ try { r = fs.realpathSync(r); } catch {}
32
+ return r;
33
+ }
34
+
35
+ function isAlive(pid) {
36
+ try { process.kill(pid, 0); return true; }
37
+ catch (e) { return e && e.code === "EPERM"; }
38
+ }
39
+
40
+ let input = "";
41
+ process.stdin.setEncoding("utf8");
42
+ process.stdin.on("data", c => { input += c; });
43
+ process.stdin.on("end", () => {
44
+ let parsed;
45
+ try { parsed = JSON.parse(input); } catch { return process.exit(0); }
46
+ const cwd = parsed && parsed.cwd;
47
+ if (!cwd) return process.exit(0);
48
+
49
+ // Stamp provider so the server / reducer can branch on it without
50
+ // re-sniffing payload shape.
51
+ if (parsed && typeof parsed === "object" && !parsed.provider) {
52
+ parsed.provider = PROVIDER;
53
+ }
54
+ const taggedInput = JSON.stringify(parsed);
55
+
56
+ const resolvedCwd = normPath(cwd);
57
+
58
+ let files;
59
+ try {
60
+ files = fs.readdirSync(DIR).filter(f => f.endsWith(".json"));
61
+ } catch { return process.exit(0); }
62
+ if (!files.length) return process.exit(0);
63
+
64
+ const matches = [];
65
+ for (const file of files) {
66
+ let d;
67
+ try { d = JSON.parse(fs.readFileSync(path.join(DIR, file), "utf8")); } catch { continue; }
68
+ if (typeof d.workspace !== "string" || !d.pid || !d.port) continue;
69
+
70
+ if (!isAlive(d.pid)) {
71
+ try { fs.unlinkSync(path.join(DIR, file)); } catch {}
72
+ continue;
73
+ }
74
+
75
+ if (d.workspace === "") {
76
+ matches.push({ d, wsLen: 0 });
77
+ continue;
78
+ }
79
+ const ws = normPath(d.workspace);
80
+ if (resolvedCwd === ws || resolvedCwd.startsWith(ws + path.sep)) {
81
+ matches.push({ d, wsLen: ws.length });
82
+ }
83
+ }
84
+
85
+ if (!matches.length) return process.exit(0);
86
+
87
+ matches.sort((a, b) => b.wsLen - a.wsLen);
88
+ const bestLen = matches[0].wsLen;
89
+ const targets = matches.filter(m => m.wsLen === bestLen);
90
+
91
+ let pending = targets.length;
92
+ const done = () => { if (--pending <= 0) process.exit(0); };
93
+
94
+ for (const { d } of targets) {
95
+ let settled = false;
96
+ const finish = () => { if (settled) return; settled = true; done(); };
97
+ const req = http.request({
98
+ hostname: "127.0.0.1",
99
+ port: d.port,
100
+ path: "/api/event",
101
+ method: "POST",
102
+ headers: { "Content-Type": "application/json" },
103
+ timeout: 1000,
104
+ }, res => { res.resume(); res.on("end", finish); });
105
+ req.on("error", finish);
106
+ req.on("timeout", () => req.destroy());
107
+ req.write(taggedInput);
108
+ req.end();
109
+ }
110
+ });
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "agent-dag",
3
- "version": "1.15.5",
4
- "description": "Live DAG of Claude Code agents — watch parallel subagents fork, call tools, and return on one calm canvas.",
5
- "type": "module",
6
- "bin": {
7
- "agent-dag": "bin/agent-dag.js"
8
- },
9
- "files": [
10
- "bin",
11
- "hook",
12
- "src/server",
13
- "dist/web",
14
- "LICENSE",
15
- "README.md"
16
- ],
17
- "scripts": {
18
- "dev:web": "vite",
19
- "build:web": "vite build",
20
- "dev:server": "node src/server/index.mjs",
21
- "start": "node bin/agent-dag.js",
22
- "build": "vite build",
23
- "test": "vitest run",
24
- "prepublishOnly": "vite build"
25
- },
26
- "engines": {
27
- "node": ">=18"
28
- },
29
- "keywords": [
30
- "claude-code",
31
- "claude",
32
- "anthropic",
33
- "agents",
34
- "subagents",
35
- "visualization",
36
- "dashboard",
37
- "hooks",
38
- "observability",
39
- "dag",
40
- "graph",
41
- "live"
42
- ],
43
- "author": "Bargan Constantin",
44
- "license": "MIT",
45
- "repository": {
46
- "type": "git",
47
- "url": "git+https://github.com/BarganConstantin/agent-dag.git"
48
- },
49
- "bugs": {
50
- "url": "https://github.com/BarganConstantin/agent-dag/issues"
51
- },
52
- "homepage": "https://github.com/BarganConstantin/agent-dag#readme",
53
- "dependencies": {
54
- "open": "^10.1.0"
55
- },
56
- "devDependencies": {
57
- "@types/react": "^18.3.12",
58
- "@types/react-dom": "^18.3.1",
59
- "@vitejs/plugin-react": "^4.3.4",
60
- "dagre": "^0.8.5",
61
- "react": "^18.3.1",
62
- "react-dom": "^18.3.1",
63
- "reactflow": "^11.11.4",
64
- "typescript": "^5.6.3",
65
- "vite": "^6.0.0",
66
- "vitest": "^2.1.9"
67
- }
68
- }
1
+ {
2
+ "name": "agent-dag",
3
+ "version": "1.16.0",
4
+ "description": "Live DAG of Claude Code and Codex agents — watch parallel subagents fork, call tools, and return on one calm canvas.",
5
+ "type": "module",
6
+ "bin": {
7
+ "agent-dag": "bin/agent-dag.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "hook",
12
+ "src/server",
13
+ "dist/web",
14
+ "LICENSE",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "dev:web": "vite",
19
+ "build:web": "vite build",
20
+ "dev:server": "node src/server/index.mjs",
21
+ "start": "node bin/agent-dag.js",
22
+ "build": "vite build",
23
+ "test": "vitest run",
24
+ "prepublishOnly": "vite build"
25
+ },
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "keywords": [
30
+ "claude-code",
31
+ "claude",
32
+ "anthropic",
33
+ "agents",
34
+ "subagents",
35
+ "visualization",
36
+ "dashboard",
37
+ "hooks",
38
+ "observability",
39
+ "dag",
40
+ "graph",
41
+ "live"
42
+ ],
43
+ "author": "Bargan Constantin",
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/BarganConstantin/agent-dag.git"
48
+ },
49
+ "bugs": {
50
+ "url": "https://github.com/BarganConstantin/agent-dag/issues"
51
+ },
52
+ "homepage": "https://github.com/BarganConstantin/agent-dag#readme",
53
+ "dependencies": {
54
+ "open": "^10.1.0"
55
+ },
56
+ "devDependencies": {
57
+ "@types/react": "^18.3.12",
58
+ "@types/react-dom": "^18.3.1",
59
+ "@vitejs/plugin-react": "^4.3.4",
60
+ "dagre": "^0.8.5",
61
+ "react": "^18.3.1",
62
+ "react-dom": "^18.3.1",
63
+ "reactflow": "^11.11.4",
64
+ "typescript": "^5.6.3",
65
+ "vite": "^6.0.0",
66
+ "vitest": "^2.1.9"
67
+ }
68
+ }