agmon 0.0.0-stage → 0.1.1

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 CHANGED
@@ -1,3 +1,82 @@
1
- # Temporary Holding Version
1
+ # 🤖 AGMon (Agent Monitor)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "paths": {
5
+ "@/*": ["./src/*"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,6 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: false,
4
+ };
5
+
6
+ export default nextConfig;
package/package.json CHANGED
@@ -1,6 +1,52 @@
1
1
  {
2
2
  "name": "agmon",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
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,5 @@
1
+ export default {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
@@ -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
+ }