agmon 0.0.0-stage → 0.1.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.
- package/README.md +81 -2
- package/bin/cli.js +366 -0
- package/jsconfig.json +8 -0
- package/next.config.mjs +6 -0
- package/package.json +50 -4
- package/postcss.config.mjs +5 -0
- package/public/favicon.svg +48 -0
- package/public/icons/icon.svg +48 -0
- package/public/manifest.json +23 -0
- package/public/sw.js +42 -0
- package/src/app/api/traces/stream/route.js +89 -0
- package/src/app/api/version/route.js +23 -0
- package/src/app/globals.css +15 -0
- package/src/app/layout.js +42 -0
- package/src/app/page.js +174 -0
- package/src/components/PwaRegister.js +31 -0
- package/src/components/UpdateNotification.js +79 -0
- package/src/components/factory/AgentPanel.js +92 -0
- package/src/components/factory/office-canvas.js +95 -0
- package/src/components/factory/office-scene.js +519 -0
- package/src/components/factory/scene/characters.js +335 -0
- package/src/components/factory/scene/office-layout.js +188 -0
- package/src/components/factory/scene/token-streams.js +85 -0
- package/src/components/factory/scene/tool-icons.js +233 -0
- package/src/lib/mockTraces.js +171 -0
- package/src/lib/traceContract.js +46 -0
- package/src/lib/useFactoryTraces.js +142 -0
- package/src/lib/watchers/antigravityWatcher.js +180 -0
- package/src/lib/watchers/claudeWatcher.js +190 -0
- package/src/lib/watchers/watcherManager.js +41 -0
package/README.md
CHANGED
|
@@ -1,3 +1,82 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 🤖 AGMon (Agent Monitor)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**AGMon** is a standalone, real-time AI Agent Office & Activity Visualizer. It watches local CLI coding agent logs (Antigravity CLI, Claude Code, Cursor, etc.) and visualizes active agent desks, tool badges, and token packet streams flowing to provider server pods in a rich 2.5D isometric view.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ⚡ Quick Start with `npx`
|
|
8
|
+
|
|
9
|
+
Run AGMon instantly from any terminal without installing:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Start visualizer & open dashboard:
|
|
13
|
+
npx agmon
|
|
14
|
+
|
|
15
|
+
# Or specify a custom port:
|
|
16
|
+
npx agmon --port 4000
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 💻 Global Installation & Background Daemon
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Install globally:
|
|
25
|
+
npm install -g agmon
|
|
26
|
+
|
|
27
|
+
# Start background daemon:
|
|
28
|
+
agmon start
|
|
29
|
+
|
|
30
|
+
# Check status (PID, URL, autostart):
|
|
31
|
+
agmon status
|
|
32
|
+
|
|
33
|
+
# Stop background daemon:
|
|
34
|
+
agmon stop
|
|
35
|
+
|
|
36
|
+
# Enable automatic start on system boot (macOS LaunchAgent / Linux systemd):
|
|
37
|
+
agmon autostart enable
|
|
38
|
+
|
|
39
|
+
# Disable auto-start on boot:
|
|
40
|
+
agmon autostart disable
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 📱 Progressive Web App (PWA)
|
|
46
|
+
|
|
47
|
+
AGMon is fully PWA-compliant with offline shell caching, standalone window frame, and custom high-resolution icons:
|
|
48
|
+
|
|
49
|
+
- **macOS / Chrome / Edge**: Click the **Install** icon in the browser address bar to install AGMon as a native desktop application.
|
|
50
|
+
- **Safari on macOS**: Click **File** > **Add to Dock...** to run as a standalone desktop app.
|
|
51
|
+
- **iPad / iPhone / Android**: Tap **Share** > **Add to Home Screen**.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## ✨ Features
|
|
56
|
+
|
|
57
|
+
- **100% Non-invasive & Safe**: Zero network interception, zero MITM proxy, zero credential touches. Only inspects local read-only CLI session logs.
|
|
58
|
+
- **Dual Live Watchers**:
|
|
59
|
+
- **Antigravity CLI (`agy`)**: Reads `~/.gemini/antigravity-cli/brain/*/transcript.jsonl` with deep tool recognition (GitNexus, Playwright Browser, Git, Docker, Read, Edit, Search, Agent).
|
|
60
|
+
- **Claude Code CLI (`claude`)**: Reads `~/.claude/sessions/*.json` and `~/.claude/projects/*/*.jsonl` with real token usage and active tool calls.
|
|
61
|
+
- **2.5D Isometric Pixi.js Canvas**:
|
|
62
|
+
- Desks with cute robots (specular helmet reflections, rim shading, extruded 3D perspective).
|
|
63
|
+
- Dynamic tool badges cycling over agents in real time.
|
|
64
|
+
- Token streams running from agent desks into provider pods (Gemini, Claude, OpenAI, Minimax, DeepSeek).
|
|
65
|
+
- Fallback courier drones re-routing requests between providers.
|
|
66
|
+
- **Inspector Panel**: Click on any desk to inspect latency, model, tokens (input/output/cached), cost, and currently executing command/file.
|
|
67
|
+
- **Demo Presets**: Includes offline presets (`cases`, `storm`, `busy`, `idle`, `errors`) for demonstrations and development.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 🛠️ Tech Stack
|
|
72
|
+
|
|
73
|
+
- **Framework**: Next.js 16 (App Router) + React 19
|
|
74
|
+
- **Graphics Engine**: Pixi.js v8 (WebGL / Canvas)
|
|
75
|
+
- **Styling**: Tailwind CSS v4
|
|
76
|
+
- **Streaming**: Server-Sent Events (SSE)
|
|
77
|
+
- **PWA**: Web App Manifest + Service Worker + App Shell
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 📄 License
|
|
82
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn, execSync } from "node:child_process";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const PKG_ROOT = path.resolve(__dirname, "..");
|
|
12
|
+
|
|
13
|
+
const HOME = os.homedir();
|
|
14
|
+
const CONFIG_DIR = path.join(HOME, ".agmon");
|
|
15
|
+
const PID_FILE = path.join(CONFIG_DIR, "agmon.pid");
|
|
16
|
+
const LOG_FILE = path.join(CONFIG_DIR, "agmon.log");
|
|
17
|
+
const PLIST_PATH = path.join(HOME, "Library", "LaunchAgents", "com.agmon.daemon.plist");
|
|
18
|
+
const SYSTEMD_DIR = path.join(HOME, ".config", "systemd", "user");
|
|
19
|
+
const SYSTEMD_PATH = path.join(SYSTEMD_DIR, "agmon.service");
|
|
20
|
+
|
|
21
|
+
// Ensure ~/.agmon exists
|
|
22
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
23
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getPort() {
|
|
27
|
+
const argIdx = process.argv.indexOf("--port");
|
|
28
|
+
if (argIdx !== -1 && process.argv[argIdx + 1]) {
|
|
29
|
+
return parseInt(process.argv[argIdx + 1], 10);
|
|
30
|
+
}
|
|
31
|
+
return parseInt(process.env.PORT || "3030", 10);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function openBrowser(url) {
|
|
35
|
+
try {
|
|
36
|
+
const cmd = process.platform === "darwin" ? `open "${url}"` : process.platform === "win32" ? `start "${url}"` : `xdg-open "${url}"`;
|
|
37
|
+
execSync(cmd, { stdio: "ignore" });
|
|
38
|
+
} catch {
|
|
39
|
+
// ignore
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isPidAlive(pid) {
|
|
44
|
+
try {
|
|
45
|
+
process.kill(pid, 0);
|
|
46
|
+
return true;
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getDaemonPid() {
|
|
53
|
+
if (fs.existsSync(PID_FILE)) {
|
|
54
|
+
const raw = fs.readFileSync(PID_FILE, "utf-8").trim();
|
|
55
|
+
const pid = parseInt(raw, 10);
|
|
56
|
+
if (!isNaN(pid) && isPidAlive(pid)) {
|
|
57
|
+
return pid;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// -------------------------------------------------------------
|
|
64
|
+
// Commands
|
|
65
|
+
// -------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
function runForeground(port, open = true, isService = false) {
|
|
68
|
+
if (!isService) {
|
|
69
|
+
const existingPid = getDaemonPid();
|
|
70
|
+
if (existingPid) {
|
|
71
|
+
console.log(`\x1b[33m⚠️ AGMon is already running in background (PID: ${existingPid})\x1b[0m`);
|
|
72
|
+
console.log(`🌐 Dashboard: \x1b[36mhttp://localhost:${port}\x1b[0m\n`);
|
|
73
|
+
if (open) openBrowser(`http://localhost:${port}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(`\n\x1b[32m🤖 Starting AGMon (Agent Monitor) on port ${port}...\x1b[0m`);
|
|
79
|
+
console.log(`📁 Project Root: ${PKG_ROOT}`);
|
|
80
|
+
console.log(`🌐 Dashboard: \x1b[36mhttp://localhost:${port}\x1b[0m\n`);
|
|
81
|
+
|
|
82
|
+
const nextBin = path.join(PKG_ROOT, "node_modules", ".bin", "next");
|
|
83
|
+
const child = spawn(nextBin, ["dev", "--port", String(port)], {
|
|
84
|
+
cwd: PKG_ROOT,
|
|
85
|
+
stdio: "inherit",
|
|
86
|
+
env: { ...process.env, PORT: String(port) },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (open) {
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
openBrowser(`http://localhost:${port}`);
|
|
92
|
+
}, 2000);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
child.on("exit", (code) => {
|
|
96
|
+
process.exit(code || 0);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function startDaemon(port) {
|
|
101
|
+
const existingPid = getDaemonPid();
|
|
102
|
+
if (existingPid) {
|
|
103
|
+
console.log(`\x1b[33m⚠️ AGMon daemon is ALREADY running (PID: ${existingPid})\x1b[0m`);
|
|
104
|
+
console.log(`🌐 URL: \x1b[36mhttp://localhost:${port}\x1b[0m`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log(`\x1b[32m🚀 Starting AGMon in Background Daemon Mode on port ${port}...\x1b[0m`);
|
|
109
|
+
|
|
110
|
+
const out = fs.openSync(LOG_FILE, "a");
|
|
111
|
+
const nextBin = path.join(PKG_ROOT, "node_modules", ".bin", "next");
|
|
112
|
+
|
|
113
|
+
const child = spawn(nextBin, ["dev", "--port", String(port)], {
|
|
114
|
+
cwd: PKG_ROOT,
|
|
115
|
+
detached: true,
|
|
116
|
+
stdio: ["ignore", out, out],
|
|
117
|
+
env: { ...process.env, PORT: String(port) },
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
child.unref();
|
|
121
|
+
|
|
122
|
+
fs.writeFileSync(PID_FILE, String(child.pid), "utf-8");
|
|
123
|
+
|
|
124
|
+
console.log(`\x1b[32m✓ AGMon Daemon launched successfully!\x1b[0m`);
|
|
125
|
+
console.log(` • PID: \x1b[33m${child.pid}\x1b[0m`);
|
|
126
|
+
console.log(` • Log: \x1b[34m${LOG_FILE}\x1b[0m`);
|
|
127
|
+
console.log(` • URL: \x1b[36mhttp://localhost:${port}\x1b[0m\n`);
|
|
128
|
+
console.log(`Type \x1b[35magmon stop\x1b[0m to stop the daemon.\n`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function stopDaemon() {
|
|
132
|
+
const pid = getDaemonPid();
|
|
133
|
+
if (!pid) {
|
|
134
|
+
console.log(`\x1b[33mℹ️ No active AGMon daemon found.\x1b[0m`);
|
|
135
|
+
if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log(`\x1b[33m🛑 Stopping AGMon daemon (PID: ${pid})...\x1b[0m`);
|
|
140
|
+
try {
|
|
141
|
+
process.kill(pid, "SIGTERM");
|
|
142
|
+
setTimeout(() => {
|
|
143
|
+
if (isPidAlive(pid)) {
|
|
144
|
+
try { process.kill(pid, "SIGKILL"); } catch {}
|
|
145
|
+
}
|
|
146
|
+
if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
|
|
147
|
+
console.log(`\x1b[32m✓ AGMon daemon stopped.\x1b[0m`);
|
|
148
|
+
}, 500);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
console.error(`Failed to kill process ${pid}:`, err.message);
|
|
151
|
+
if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function showStatus(port) {
|
|
156
|
+
const pid = getDaemonPid();
|
|
157
|
+
console.log(`\n\x1b[1m🤖 AGMon (Agent Monitor) Status:\x1b[0m`);
|
|
158
|
+
if (pid) {
|
|
159
|
+
console.log(` • Status: \x1b[32m● RUNNING (Daemon)\x1b[0m`);
|
|
160
|
+
console.log(` • PID: \x1b[33m${pid}\x1b[0m`);
|
|
161
|
+
console.log(` • URL: \x1b[36mhttp://localhost:${port}\x1b[0m`);
|
|
162
|
+
console.log(` • Log: ${LOG_FILE}`);
|
|
163
|
+
} else {
|
|
164
|
+
console.log(` • Status: \x1b[31m○ STOPPED\x1b[0m`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const autostart = isAutostartEnabled();
|
|
168
|
+
console.log(` • Auto-start on boot: ${autostart ? "\x1b[32mENABLED\x1b[0m" : "\x1b[33mDISABLED\x1b[0m"}\n`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function isAutostartEnabled() {
|
|
172
|
+
if (process.platform === "darwin") {
|
|
173
|
+
return fs.existsSync(PLIST_PATH);
|
|
174
|
+
}
|
|
175
|
+
if (process.platform === "linux") {
|
|
176
|
+
return fs.existsSync(SYSTEMD_PATH);
|
|
177
|
+
}
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function enableAutostart(port) {
|
|
182
|
+
const nodePath = process.execPath;
|
|
183
|
+
const cliPath = __filename;
|
|
184
|
+
|
|
185
|
+
if (process.platform === "darwin") {
|
|
186
|
+
const launchAgentsDir = path.dirname(PLIST_PATH);
|
|
187
|
+
if (!fs.existsSync(launchAgentsDir)) {
|
|
188
|
+
fs.mkdirSync(launchAgentsDir, { recursive: true });
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
192
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
193
|
+
<plist version="1.0">
|
|
194
|
+
<dict>
|
|
195
|
+
<key>Label</key>
|
|
196
|
+
<string>com.agmon.daemon</string>
|
|
197
|
+
<key>ProgramArguments</key>
|
|
198
|
+
<array>
|
|
199
|
+
<string>${nodePath}</string>
|
|
200
|
+
<string>${cliPath}</string>
|
|
201
|
+
<string>run</string>
|
|
202
|
+
<string>--port</string>
|
|
203
|
+
<string>${port}</string>
|
|
204
|
+
</array>
|
|
205
|
+
<key>RunAtLoad</key>
|
|
206
|
+
<true/>
|
|
207
|
+
<key>KeepAlive</key>
|
|
208
|
+
<true/>
|
|
209
|
+
<key>ThrottleInterval</key>
|
|
210
|
+
<integer>10</integer>
|
|
211
|
+
<key>StandardOutPath</key>
|
|
212
|
+
<string>${LOG_FILE}</string>
|
|
213
|
+
<key>StandardErrorPath</key>
|
|
214
|
+
<string>${LOG_FILE}</string>
|
|
215
|
+
</dict>
|
|
216
|
+
</plist>
|
|
217
|
+
`;
|
|
218
|
+
|
|
219
|
+
fs.writeFileSync(PLIST_PATH, plist, "utf-8");
|
|
220
|
+
try {
|
|
221
|
+
execSync(`launchctl unload "${PLIST_PATH}" 2>/dev/null || true`);
|
|
222
|
+
execSync(`launchctl load "${PLIST_PATH}"`);
|
|
223
|
+
console.log(`\x1b[32m✓ macOS LaunchAgent auto-start enabled!\x1b[0m`);
|
|
224
|
+
console.log(` • Plist: ${PLIST_PATH}`);
|
|
225
|
+
console.log(` • AGMon will now automatically launch on computer login.`);
|
|
226
|
+
} catch (err) {
|
|
227
|
+
console.error("Failed to load launchctl plist:", err.message);
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (process.platform === "linux") {
|
|
233
|
+
if (!fs.existsSync(SYSTEMD_DIR)) {
|
|
234
|
+
fs.mkdirSync(SYSTEMD_DIR, { recursive: true });
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const service = `[Unit]
|
|
238
|
+
Description=AGMon (Agent Monitor) Daemon
|
|
239
|
+
After=network.target
|
|
240
|
+
|
|
241
|
+
[Service]
|
|
242
|
+
Type=simple
|
|
243
|
+
ExecStart=${nodePath} ${cliPath} run --port ${port}
|
|
244
|
+
Restart=always
|
|
245
|
+
RestartSec=5
|
|
246
|
+
StandardOutput=append:${LOG_FILE}
|
|
247
|
+
StandardError=append:${LOG_FILE}
|
|
248
|
+
|
|
249
|
+
[Install]
|
|
250
|
+
WantedBy=default.target
|
|
251
|
+
`;
|
|
252
|
+
fs.writeFileSync(SYSTEMD_PATH, service, "utf-8");
|
|
253
|
+
try {
|
|
254
|
+
execSync("systemctl --user daemon-reload");
|
|
255
|
+
execSync("systemctl --user enable --now agmon");
|
|
256
|
+
console.log(`\x1b[32m✓ Linux systemd auto-start enabled!\x1b[0m`);
|
|
257
|
+
console.log(` • Service: ${SYSTEMD_PATH}`);
|
|
258
|
+
} catch (err) {
|
|
259
|
+
console.error("Failed to enable systemd service:", err.message);
|
|
260
|
+
}
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
console.log(`\x1b[33m⚠️ Auto-start is currently supported on macOS (Launchd) and Linux (systemd).\x1b[0m`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function disableAutostart() {
|
|
268
|
+
if (process.platform === "darwin") {
|
|
269
|
+
if (fs.existsSync(PLIST_PATH)) {
|
|
270
|
+
try {
|
|
271
|
+
execSync(`launchctl unload "${PLIST_PATH}" 2>/dev/null || true`);
|
|
272
|
+
} catch {}
|
|
273
|
+
fs.unlinkSync(PLIST_PATH);
|
|
274
|
+
console.log(`\x1b[32m✓ macOS auto-start disabled (LaunchAgent removed).\x1b[0m`);
|
|
275
|
+
} else {
|
|
276
|
+
console.log(`\x1b[33mℹ️ Auto-start was not enabled.\x1b[0m`);
|
|
277
|
+
}
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (process.platform === "linux") {
|
|
282
|
+
if (fs.existsSync(SYSTEMD_PATH)) {
|
|
283
|
+
try {
|
|
284
|
+
execSync("systemctl --user stop agmon 2>/dev/null || true");
|
|
285
|
+
execSync("systemctl --user disable agmon 2>/dev/null || true");
|
|
286
|
+
} catch {}
|
|
287
|
+
fs.unlinkSync(SYSTEMD_PATH);
|
|
288
|
+
console.log(`\x1b[32m✓ Linux systemd auto-start disabled.\x1b[0m`);
|
|
289
|
+
} else {
|
|
290
|
+
console.log(`\x1b[33mℹ️ Auto-start was not enabled.\x1b[0m`);
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function showHelp() {
|
|
297
|
+
console.log(`
|
|
298
|
+
\x1b[1m🤖 AGMon (Agent Monitor) CLI\x1b[0m
|
|
299
|
+
Universal Live AI Agent Office & Activity Visualizer
|
|
300
|
+
|
|
301
|
+
\x1b[1mUSAGE:\x1b[0m
|
|
302
|
+
npx agmon [command] [options]
|
|
303
|
+
# or when installed globally:
|
|
304
|
+
agmon [command] [options]
|
|
305
|
+
|
|
306
|
+
\x1b[1mCOMMANDS:\x1b[0m
|
|
307
|
+
(default) Start visualizer and open dashboard in browser
|
|
308
|
+
start Start in background (daemon mode)
|
|
309
|
+
stop Stop background daemon
|
|
310
|
+
status Check daemon status & auto-start configuration
|
|
311
|
+
autostart enable Configure to automatically start on computer boot
|
|
312
|
+
autostart disable Disable automatic boot launch
|
|
313
|
+
help Show this help message
|
|
314
|
+
|
|
315
|
+
\x1b[1mOPTIONS:\x1b[0m
|
|
316
|
+
--port <number> Set HTTP port (default: 3030)
|
|
317
|
+
--no-open Do not automatically open browser on start
|
|
318
|
+
`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// -------------------------------------------------------------
|
|
322
|
+
// CLI Routing
|
|
323
|
+
// -------------------------------------------------------------
|
|
324
|
+
|
|
325
|
+
const args = process.argv.slice(2);
|
|
326
|
+
const command = args[0] || "";
|
|
327
|
+
const port = getPort();
|
|
328
|
+
const noOpen = process.argv.includes("--no-open");
|
|
329
|
+
|
|
330
|
+
switch (command) {
|
|
331
|
+
case "start":
|
|
332
|
+
startDaemon(port);
|
|
333
|
+
break;
|
|
334
|
+
|
|
335
|
+
case "stop":
|
|
336
|
+
stopDaemon();
|
|
337
|
+
break;
|
|
338
|
+
|
|
339
|
+
case "status":
|
|
340
|
+
showStatus(port);
|
|
341
|
+
break;
|
|
342
|
+
|
|
343
|
+
case "run":
|
|
344
|
+
runForeground(port, false, true);
|
|
345
|
+
break;
|
|
346
|
+
|
|
347
|
+
case "autostart":
|
|
348
|
+
if (args[1] === "enable") {
|
|
349
|
+
enableAutostart(port);
|
|
350
|
+
} else if (args[1] === "disable") {
|
|
351
|
+
disableAutostart();
|
|
352
|
+
} else {
|
|
353
|
+
console.log(`Usage: agmon autostart [enable|disable]`);
|
|
354
|
+
}
|
|
355
|
+
break;
|
|
356
|
+
|
|
357
|
+
case "help":
|
|
358
|
+
case "--help":
|
|
359
|
+
case "-h":
|
|
360
|
+
showHelp();
|
|
361
|
+
break;
|
|
362
|
+
|
|
363
|
+
default:
|
|
364
|
+
runForeground(port, !noOpen);
|
|
365
|
+
break;
|
|
366
|
+
}
|
package/jsconfig.json
ADDED
package/next.config.mjs
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agmon",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Realtime AI Agent Office & Activity Visualizer for Antigravity, Claude Code & AI CLIs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agmon": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"src",
|
|
12
|
+
"public",
|
|
13
|
+
"jsconfig.json",
|
|
14
|
+
"next.config.mjs",
|
|
15
|
+
"postcss.config.mjs",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "next dev --port 3030",
|
|
20
|
+
"build": "next build",
|
|
21
|
+
"start": "next start --port 3030",
|
|
22
|
+
"lint": "eslint ."
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"next": "^16.1.6",
|
|
26
|
+
"pixi.js": "^8.22.0",
|
|
27
|
+
"react": "19.2.4",
|
|
28
|
+
"react-dom": "19.2.4"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
32
|
+
"postcss": "^8.5.6",
|
|
33
|
+
"tailwindcss": "^4.1.18"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"agmon",
|
|
37
|
+
"agent-monitor",
|
|
38
|
+
"antigravity",
|
|
39
|
+
"claude-code",
|
|
40
|
+
"ai-agent",
|
|
41
|
+
"visualizer",
|
|
42
|
+
"telemetry",
|
|
43
|
+
"office",
|
|
44
|
+
"pixijs"
|
|
45
|
+
],
|
|
46
|
+
"author": "thanhdevapp",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/thanhdevapp/agent-factory.git"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="bgGlow" cx="50%" cy="50%" r="50%">
|
|
4
|
+
<stop offset="0%" stop-color="#0f172a" />
|
|
5
|
+
<stop offset="100%" stop-color="#070b12" />
|
|
6
|
+
</radialGradient>
|
|
7
|
+
<linearGradient id="helmGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
8
|
+
<stop offset="0%" stop-color="#34d399" />
|
|
9
|
+
<stop offset="50%" stop-color="#06b6d4" />
|
|
10
|
+
<stop offset="100%" stop-color="#3b82f6" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
<linearGradient id="visorGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
13
|
+
<stop offset="0%" stop-color="#0b1322" />
|
|
14
|
+
<stop offset="100%" stop-color="#1e293b" />
|
|
15
|
+
</linearGradient>
|
|
16
|
+
</defs>
|
|
17
|
+
<!-- Background -->
|
|
18
|
+
<rect width="512" height="512" rx="112" fill="url(#bgGlow)" />
|
|
19
|
+
<rect width="504" height="504" x="4" y="4" rx="108" fill="none" stroke="#1e293b" stroke-width="8" />
|
|
20
|
+
|
|
21
|
+
<!-- Antenna -->
|
|
22
|
+
<rect x="246" y="70" width="20" height="50" rx="10" fill="#34d399" />
|
|
23
|
+
<circle cx="256" cy="65" r="22" fill="#38bdf8" />
|
|
24
|
+
<circle cx="256" cy="65" r="12" fill="#a7f3d0" />
|
|
25
|
+
|
|
26
|
+
<!-- Robot Head / Helmet -->
|
|
27
|
+
<rect x="116" y="110" width="280" height="230" rx="60" fill="url(#helmGrad)" />
|
|
28
|
+
|
|
29
|
+
<!-- Ear Phones -->
|
|
30
|
+
<rect x="86" y="175" width="30" height="100" rx="12" fill="#38bdf8" />
|
|
31
|
+
<rect x="396" y="175" width="30" height="100" rx="12" fill="#38bdf8" />
|
|
32
|
+
|
|
33
|
+
<!-- Screen Visor -->
|
|
34
|
+
<rect x="146" y="145" width="220" height="160" rx="36" fill="url(#visorGrad)" stroke="#38bdf8" stroke-width="4" />
|
|
35
|
+
|
|
36
|
+
<!-- Eyes (Glowing neon circles) -->
|
|
37
|
+
<circle cx="206" cy="225" r="26" fill="#34d399" />
|
|
38
|
+
<circle cx="206" cy="225" r="14" fill="#ecfdf5" />
|
|
39
|
+
|
|
40
|
+
<!-- Wink / Smile Right Eye -->
|
|
41
|
+
<circle cx="306" cy="225" r="26" fill="#38bdf8" />
|
|
42
|
+
<circle cx="306" cy="225" r="14" fill="#ecfdf5" />
|
|
43
|
+
|
|
44
|
+
<!-- Token Packets Flowing -->
|
|
45
|
+
<circle cx="160" cy="400" r="14" fill="#34d399" />
|
|
46
|
+
<polygon points="256,380 274,400 256,420 238,400" fill="#38bdf8" />
|
|
47
|
+
<rect x="340" y="386" width="26" height="26" rx="4" fill="#a855f7" />
|
|
48
|
+
</svg>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="bgGlow" cx="50%" cy="50%" r="50%">
|
|
4
|
+
<stop offset="0%" stop-color="#0f172a" />
|
|
5
|
+
<stop offset="100%" stop-color="#070b12" />
|
|
6
|
+
</radialGradient>
|
|
7
|
+
<linearGradient id="helmGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
8
|
+
<stop offset="0%" stop-color="#34d399" />
|
|
9
|
+
<stop offset="50%" stop-color="#06b6d4" />
|
|
10
|
+
<stop offset="100%" stop-color="#3b82f6" />
|
|
11
|
+
</linearGradient>
|
|
12
|
+
<linearGradient id="visorGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
13
|
+
<stop offset="0%" stop-color="#0b1322" />
|
|
14
|
+
<stop offset="100%" stop-color="#1e293b" />
|
|
15
|
+
</linearGradient>
|
|
16
|
+
</defs>
|
|
17
|
+
<!-- Background -->
|
|
18
|
+
<rect width="512" height="512" rx="112" fill="url(#bgGlow)" />
|
|
19
|
+
<rect width="504" height="504" x="4" y="4" rx="108" fill="none" stroke="#1e293b" stroke-width="8" />
|
|
20
|
+
|
|
21
|
+
<!-- Antenna -->
|
|
22
|
+
<rect x="246" y="70" width="20" height="50" rx="10" fill="#34d399" />
|
|
23
|
+
<circle cx="256" cy="65" r="22" fill="#38bdf8" />
|
|
24
|
+
<circle cx="256" cy="65" r="12" fill="#a7f3d0" />
|
|
25
|
+
|
|
26
|
+
<!-- Robot Head / Helmet -->
|
|
27
|
+
<rect x="116" y="110" width="280" height="230" rx="60" fill="url(#helmGrad)" />
|
|
28
|
+
|
|
29
|
+
<!-- Ear Phones -->
|
|
30
|
+
<rect x="86" y="175" width="30" height="100" rx="12" fill="#38bdf8" />
|
|
31
|
+
<rect x="396" y="175" width="30" height="100" rx="12" fill="#38bdf8" />
|
|
32
|
+
|
|
33
|
+
<!-- Screen Visor -->
|
|
34
|
+
<rect x="146" y="145" width="220" height="160" rx="36" fill="url(#visorGrad)" stroke="#38bdf8" stroke-width="4" />
|
|
35
|
+
|
|
36
|
+
<!-- Eyes (Glowing neon circles) -->
|
|
37
|
+
<circle cx="206" cy="225" r="26" fill="#34d399" />
|
|
38
|
+
<circle cx="206" cy="225" r="14" fill="#ecfdf5" />
|
|
39
|
+
|
|
40
|
+
<!-- Wink / Smile Right Eye -->
|
|
41
|
+
<circle cx="306" cy="225" r="26" fill="#38bdf8" />
|
|
42
|
+
<circle cx="306" cy="225" r="14" fill="#ecfdf5" />
|
|
43
|
+
|
|
44
|
+
<!-- Token Packets Flowing -->
|
|
45
|
+
<circle cx="160" cy="400" r="14" fill="#34d399" />
|
|
46
|
+
<polygon points="256,380 274,400 256,420 238,400" fill="#38bdf8" />
|
|
47
|
+
<rect x="340" y="386" width="26" height="26" rx="4" fill="#a855f7" />
|
|
48
|
+
</svg>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "AGMon (Agent Monitor)",
|
|
3
|
+
"short_name": "AGMon",
|
|
4
|
+
"description": "Universal Live AI Agent Office & Activity Visualizer",
|
|
5
|
+
"start_url": "/",
|
|
6
|
+
"display": "standalone",
|
|
7
|
+
"background_color": "#070b12",
|
|
8
|
+
"theme_color": "#070b12",
|
|
9
|
+
"orientation": "landscape-primary",
|
|
10
|
+
"icons": [
|
|
11
|
+
{
|
|
12
|
+
"src": "/icons/icon.svg",
|
|
13
|
+
"sizes": "192x192 512x512",
|
|
14
|
+
"type": "image/svg+xml",
|
|
15
|
+
"purpose": "any maskable"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"src": "/favicon.svg",
|
|
19
|
+
"sizes": "any",
|
|
20
|
+
"type": "image/svg+xml"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|