agentmomo 0.1.1 → 0.1.2
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/dist/assets/index-BwEFhEay.js +5367 -0
- package/dist/assets/index-CS8oLlw3.css +1 -0
- package/dist/cli.js +2 -0
- package/dist/gemini-cli-hook.cjs +244 -0
- package/dist/index.html +2 -2
- package/dist/server.js +205 -2
- package/package.json +4 -2
- package/dist/assets/index-Cru_j148.js +0 -5346
- package/dist/assets/index-q7eACk3a.css +0 -1
package/dist/server.js
CHANGED
|
@@ -47464,6 +47464,7 @@ var CLAUDE_CONFIG_PATH = process.env.APPDATA ? path3.join(process.env.APPDATA, "
|
|
|
47464
47464
|
var AGENTSMOMO_DIST_DIR = process.env.AGENTSMOMO_DIST_DIR;
|
|
47465
47465
|
var WRAPPER_JS = AGENTSMOMO_DIST_DIR ? path3.join(AGENTSMOMO_DIST_DIR, "stdio-wrapper.js") : path3.join(process.cwd(), "proxy", "dist", "stdio-wrapper.js");
|
|
47466
47466
|
var HOOK_JS = AGENTSMOMO_DIST_DIR ? path3.join(AGENTSMOMO_DIST_DIR, "claude-code-hook.cjs") : path3.join(process.cwd(), "proxy", "dist", "claude-code-hook.cjs");
|
|
47467
|
+
var GEMINI_HOOK_JS = AGENTSMOMO_DIST_DIR ? path3.join(AGENTSMOMO_DIST_DIR, "gemini-cli-hook.cjs") : path3.join(process.cwd(), "proxy", "dist", "gemini-cli-hook.cjs");
|
|
47467
47468
|
function projectSettingsPath(projectPath) {
|
|
47468
47469
|
return path3.join(projectPath, ".claude", "settings.json");
|
|
47469
47470
|
}
|
|
@@ -47622,11 +47623,112 @@ app.post("/api/event", requireAuth, async (req, res) => {
|
|
|
47622
47623
|
};
|
|
47623
47624
|
broadcast(subEvent);
|
|
47624
47625
|
}
|
|
47626
|
+
if (event.event === "call_start" && event.source === "gemini-cli" && event.toolName === "complete_task" && event.metadata?.subAgentId && typeof event.metadata.subAgentId === "string") {
|
|
47627
|
+
const subAgentId = event.metadata.subAgentId;
|
|
47628
|
+
const subAgentName = event.metadata.subAgentName ?? subAgentId;
|
|
47629
|
+
const folderPart = typeof event.metadata.cwd === "string" ? path3.basename(event.metadata.cwd) : "Gemini CLI";
|
|
47630
|
+
const subEvent = {
|
|
47631
|
+
agentId: subAgentId,
|
|
47632
|
+
agentName: `${folderPart} \xB7 ${subAgentName}`,
|
|
47633
|
+
source: "gemini-cli-subagent",
|
|
47634
|
+
event: "agent_register",
|
|
47635
|
+
toolName: "",
|
|
47636
|
+
timestamp: event.timestamp,
|
|
47637
|
+
requestId: `${event.requestId}-sub-register`,
|
|
47638
|
+
parentId: event.agentId,
|
|
47639
|
+
isSubAgent: true,
|
|
47640
|
+
metadata: event.metadata
|
|
47641
|
+
};
|
|
47642
|
+
broadcast(subEvent);
|
|
47643
|
+
}
|
|
47625
47644
|
res.json({ ok: true });
|
|
47626
47645
|
});
|
|
47627
47646
|
app.get("/api/health", (_req, res) => {
|
|
47628
47647
|
res.json({ status: "ok", agents: getAllAgents().length });
|
|
47629
47648
|
});
|
|
47649
|
+
app.get("/.well-known/agent.json", (_req, res) => {
|
|
47650
|
+
res.json({
|
|
47651
|
+
name: "agentmomo",
|
|
47652
|
+
description: "3D visualization dashboard for AI coding agents. Monitor active agents, view real-time activity, and manage the dashboard.",
|
|
47653
|
+
url: `http://localhost:${PORT}`,
|
|
47654
|
+
version: "1.0.0",
|
|
47655
|
+
capabilities: {
|
|
47656
|
+
streaming: false,
|
|
47657
|
+
pushNotifications: false
|
|
47658
|
+
},
|
|
47659
|
+
skills: [
|
|
47660
|
+
{
|
|
47661
|
+
id: "list-agents",
|
|
47662
|
+
name: "List Agents",
|
|
47663
|
+
description: "Get all active agents and their current states (idle, working, break, error, offline)"
|
|
47664
|
+
},
|
|
47665
|
+
{
|
|
47666
|
+
id: "get-activity",
|
|
47667
|
+
name: "Get Activity",
|
|
47668
|
+
description: "Get server health status and agent count"
|
|
47669
|
+
},
|
|
47670
|
+
{
|
|
47671
|
+
id: "reset-dashboard",
|
|
47672
|
+
name: "Reset Dashboard",
|
|
47673
|
+
description: "Clear all agents from the visualization dashboard"
|
|
47674
|
+
}
|
|
47675
|
+
],
|
|
47676
|
+
defaultInputModes: ["text/plain"],
|
|
47677
|
+
defaultOutputModes: ["application/json"]
|
|
47678
|
+
});
|
|
47679
|
+
});
|
|
47680
|
+
app.post("/a2a/tasks/send", import_express2.default.json(), (req, res) => {
|
|
47681
|
+
const { message } = req.body ?? {};
|
|
47682
|
+
if (!message || !message.parts || !Array.isArray(message.parts)) {
|
|
47683
|
+
res.status(400).json({ error: "Invalid A2A task message" });
|
|
47684
|
+
return;
|
|
47685
|
+
}
|
|
47686
|
+
const textParts = message.parts.filter((p) => !p.type || p.type === "text").map((p) => p.text ?? "").join(" ").toLowerCase();
|
|
47687
|
+
let result;
|
|
47688
|
+
if (textParts.includes("reset") || textParts.includes("clear")) {
|
|
47689
|
+
clearAllAgents();
|
|
47690
|
+
broadcast({
|
|
47691
|
+
agentId: "__system__",
|
|
47692
|
+
agentName: "system",
|
|
47693
|
+
source: "manual",
|
|
47694
|
+
event: "agent_register",
|
|
47695
|
+
toolName: "",
|
|
47696
|
+
timestamp: Date.now(),
|
|
47697
|
+
requestId: "a2a-clear"
|
|
47698
|
+
});
|
|
47699
|
+
result = { action: "reset", success: true, message: "Dashboard cleared" };
|
|
47700
|
+
} else if (textParts.includes("list") || textParts.includes("agents") || textParts.includes("status")) {
|
|
47701
|
+
const agents2 = getAllAgents();
|
|
47702
|
+
result = {
|
|
47703
|
+
action: "list-agents",
|
|
47704
|
+
count: agents2.length,
|
|
47705
|
+
agents: agents2.map((a) => ({
|
|
47706
|
+
id: a.id,
|
|
47707
|
+
name: a.name,
|
|
47708
|
+
source: a.source,
|
|
47709
|
+
state: a.state,
|
|
47710
|
+
currentTool: a.currentTool,
|
|
47711
|
+
totalCalls: a.totalCalls,
|
|
47712
|
+
totalErrors: a.totalErrors
|
|
47713
|
+
}))
|
|
47714
|
+
};
|
|
47715
|
+
} else {
|
|
47716
|
+
result = {
|
|
47717
|
+
action: "health",
|
|
47718
|
+
status: "ok",
|
|
47719
|
+
agents: getAllAgents().length
|
|
47720
|
+
};
|
|
47721
|
+
}
|
|
47722
|
+
res.json({
|
|
47723
|
+
id: req.body.id ?? `a2a-${Date.now()}`,
|
|
47724
|
+
status: { state: "completed" },
|
|
47725
|
+
artifacts: [
|
|
47726
|
+
{
|
|
47727
|
+
parts: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
47728
|
+
}
|
|
47729
|
+
]
|
|
47730
|
+
});
|
|
47731
|
+
});
|
|
47630
47732
|
app.post(
|
|
47631
47733
|
"/api/payments/create-checkout-session",
|
|
47632
47734
|
requireAuth,
|
|
@@ -48113,7 +48215,7 @@ app.post("/api/claude-code-config", (req, res) => {
|
|
|
48113
48215
|
if (!cfg.hooks) cfg.hooks = {};
|
|
48114
48216
|
const hookCommandParts = [`node "${HOOK_JS.replace(/\\/g, "/")}"`];
|
|
48115
48217
|
if (apiKey && typeof apiKey === "string" && apiKey.startsWith("amk_")) {
|
|
48116
|
-
hookCommandParts.push(`--api-key
|
|
48218
|
+
hookCommandParts.push(`--api-key ${apiKey}`);
|
|
48117
48219
|
}
|
|
48118
48220
|
const hookEntry = {
|
|
48119
48221
|
type: "command",
|
|
@@ -48161,6 +48263,107 @@ app.post("/api/build-hook", (_req, res) => {
|
|
|
48161
48263
|
}
|
|
48162
48264
|
);
|
|
48163
48265
|
});
|
|
48266
|
+
function geminiSettingsPath(projectPath) {
|
|
48267
|
+
return path3.join(projectPath, ".gemini", "settings.json");
|
|
48268
|
+
}
|
|
48269
|
+
app.get("/api/gemini-cli-config", (req, res) => {
|
|
48270
|
+
const projectPath = req.query.project || process.cwd();
|
|
48271
|
+
const configPath = geminiSettingsPath(projectPath);
|
|
48272
|
+
const hookBuilt = fs2.existsSync(GEMINI_HOOK_JS);
|
|
48273
|
+
const configExists = fs2.existsSync(configPath);
|
|
48274
|
+
let config2 = null;
|
|
48275
|
+
let hooksInstalled = false;
|
|
48276
|
+
if (configExists) {
|
|
48277
|
+
try {
|
|
48278
|
+
config2 = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
48279
|
+
const before = config2?.hooks?.BeforeTool ?? [];
|
|
48280
|
+
hooksInstalled = before.some(
|
|
48281
|
+
(entry) => entry.hooks?.some(
|
|
48282
|
+
(h) => String(h.command ?? "").includes("gemini-cli-hook")
|
|
48283
|
+
)
|
|
48284
|
+
);
|
|
48285
|
+
} catch {
|
|
48286
|
+
config2 = null;
|
|
48287
|
+
}
|
|
48288
|
+
}
|
|
48289
|
+
res.json({
|
|
48290
|
+
configPath,
|
|
48291
|
+
projectPath,
|
|
48292
|
+
exists: configExists,
|
|
48293
|
+
config: config2,
|
|
48294
|
+
hooksInstalled,
|
|
48295
|
+
hookPath: GEMINI_HOOK_JS,
|
|
48296
|
+
hookBuilt
|
|
48297
|
+
});
|
|
48298
|
+
});
|
|
48299
|
+
app.post("/api/gemini-cli-config", (req, res) => {
|
|
48300
|
+
const {
|
|
48301
|
+
action,
|
|
48302
|
+
projectPath: pp,
|
|
48303
|
+
apiKey
|
|
48304
|
+
} = req.body;
|
|
48305
|
+
const projectPath = pp || process.cwd();
|
|
48306
|
+
const configPath = geminiSettingsPath(projectPath);
|
|
48307
|
+
try {
|
|
48308
|
+
const configDir = path3.dirname(configPath);
|
|
48309
|
+
if (!fs2.existsSync(configDir)) fs2.mkdirSync(configDir, { recursive: true });
|
|
48310
|
+
let cfg = {};
|
|
48311
|
+
if (fs2.existsSync(configPath)) {
|
|
48312
|
+
cfg = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
48313
|
+
}
|
|
48314
|
+
if (!cfg.hooks) cfg.hooks = {};
|
|
48315
|
+
const hookCommandParts = [`node "${GEMINI_HOOK_JS.replace(/\\/g, "/")}"`];
|
|
48316
|
+
if (apiKey && typeof apiKey === "string" && apiKey.startsWith("amk_")) {
|
|
48317
|
+
hookCommandParts.push(`--api-key ${apiKey}`);
|
|
48318
|
+
}
|
|
48319
|
+
const hookEntry = {
|
|
48320
|
+
name: "agentmomo",
|
|
48321
|
+
type: "command",
|
|
48322
|
+
command: hookCommandParts.join(" "),
|
|
48323
|
+
timeout: 2e3
|
|
48324
|
+
};
|
|
48325
|
+
const matcher = { matcher: ".*", hooks: [hookEntry] };
|
|
48326
|
+
const sessionMatcher = { matcher: ".*", hooks: [hookEntry] };
|
|
48327
|
+
if (action === "install") {
|
|
48328
|
+
cfg.hooks.BeforeTool = [matcher];
|
|
48329
|
+
cfg.hooks.AfterTool = [matcher];
|
|
48330
|
+
cfg.hooks.SessionStart = [sessionMatcher];
|
|
48331
|
+
if (!cfg.experimental) cfg.experimental = {};
|
|
48332
|
+
cfg.experimental.enableAgents = true;
|
|
48333
|
+
} else {
|
|
48334
|
+
const strip = (arr) => (arr ?? []).filter(
|
|
48335
|
+
(e) => !e.hooks?.some(
|
|
48336
|
+
(h) => String(h.command ?? "").includes("gemini-cli-hook")
|
|
48337
|
+
)
|
|
48338
|
+
);
|
|
48339
|
+
cfg.hooks.BeforeTool = strip(cfg.hooks.BeforeTool ?? []);
|
|
48340
|
+
cfg.hooks.AfterTool = strip(cfg.hooks.AfterTool ?? []);
|
|
48341
|
+
cfg.hooks.SessionStart = strip(cfg.hooks.SessionStart ?? []);
|
|
48342
|
+
if (!cfg.hooks.BeforeTool.length) delete cfg.hooks.BeforeTool;
|
|
48343
|
+
if (!cfg.hooks.AfterTool.length) delete cfg.hooks.AfterTool;
|
|
48344
|
+
if (!cfg.hooks.SessionStart.length) delete cfg.hooks.SessionStart;
|
|
48345
|
+
if (!Object.keys(cfg.hooks).length) delete cfg.hooks;
|
|
48346
|
+
}
|
|
48347
|
+
fs2.writeFileSync(configPath, JSON.stringify(cfg, null, 2), "utf-8");
|
|
48348
|
+
res.json({ ok: true, configPath });
|
|
48349
|
+
} catch (err) {
|
|
48350
|
+
res.status(500).json({ error: err.message });
|
|
48351
|
+
}
|
|
48352
|
+
});
|
|
48353
|
+
app.post("/api/build-gemini-hook", (_req, res) => {
|
|
48354
|
+
if (AGENTSMOMO_DIST_DIR) {
|
|
48355
|
+
res.json({ ok: true });
|
|
48356
|
+
return;
|
|
48357
|
+
}
|
|
48358
|
+
exec(
|
|
48359
|
+
`npx esbuild proxy/gemini-cli-hook.ts --bundle --platform=node --format=cjs --outfile=proxy/dist/gemini-cli-hook.cjs`,
|
|
48360
|
+
{ cwd: process.cwd() },
|
|
48361
|
+
(err, _stdout, stderr) => {
|
|
48362
|
+
if (err) res.status(500).json({ error: stderr || err.message });
|
|
48363
|
+
else res.json({ ok: true });
|
|
48364
|
+
}
|
|
48365
|
+
);
|
|
48366
|
+
});
|
|
48164
48367
|
app.get("/api/subagents", (req, res) => {
|
|
48165
48368
|
const projectPath = req.query.project || process.cwd();
|
|
48166
48369
|
const agentsDir = path3.join(projectPath, ".claude", "agents");
|
|
@@ -48216,7 +48419,7 @@ if (config.httpProxy.targets.length > 0) {
|
|
|
48216
48419
|
if (fs2.existsSync(INDEX_HTML)) {
|
|
48217
48420
|
app.use(import_express2.default.static(DIST_DIR));
|
|
48218
48421
|
app.get("*", (req, res, next) => {
|
|
48219
|
-
if (req.path.startsWith("/api") || req.path.startsWith("/proxy") || req.path.startsWith("/ws")) {
|
|
48422
|
+
if (req.path.startsWith("/api") || req.path.startsWith("/proxy") || req.path.startsWith("/ws") || req.path.startsWith("/.well-known") || req.path.startsWith("/a2a")) {
|
|
48220
48423
|
next();
|
|
48221
48424
|
return;
|
|
48222
48425
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentmomo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "3D visualization of MCP agent activity — watch your AI tools work in a virtual office",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
"start": "tsx proxy/server.ts",
|
|
19
19
|
"build:wrapper": "npx esbuild proxy/stdio-wrapper.ts --bundle --platform=node --format=esm --outfile=proxy/dist/stdio-wrapper.js",
|
|
20
20
|
"build:hook": "npx esbuild proxy/claude-code-hook.ts --bundle --platform=node --format=cjs --outfile=proxy/dist/claude-code-hook.cjs",
|
|
21
|
+
"build:gemini-hook": "npx esbuild proxy/gemini-cli-hook.ts --bundle --platform=node --format=cjs --outfile=proxy/dist/gemini-cli-hook.cjs",
|
|
21
22
|
"build:server": "npx esbuild proxy/server.ts --bundle --platform=node --format=esm --outfile=dist/server.js",
|
|
22
23
|
"build:cli": "npx esbuild bin/cli.ts --bundle --platform=node --format=esm --banner:js=\"#!/usr/bin/env node\" --outfile=dist/cli.js",
|
|
23
|
-
"build:npm": "npm run build && npm run build:server && npm run build:cli && npx esbuild proxy/stdio-wrapper.ts --bundle --platform=node --format=esm --outfile=dist/stdio-wrapper.js && npx esbuild proxy/claude-code-hook.ts --bundle --platform=node --format=cjs --outfile=dist/claude-code-hook.cjs",
|
|
24
|
+
"build:npm": "npm run build && npm run build:server && npm run build:cli && npx esbuild proxy/stdio-wrapper.ts --bundle --platform=node --format=esm --outfile=dist/stdio-wrapper.js && npx esbuild proxy/claude-code-hook.ts --bundle --platform=node --format=cjs --outfile=dist/claude-code-hook.cjs && npx esbuild proxy/gemini-cli-hook.ts --bundle --platform=node --format=cjs --outfile=dist/gemini-cli-hook.cjs",
|
|
24
25
|
"preview": "vite preview"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
33
34
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
34
35
|
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
36
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
35
37
|
"@radix-ui/react-separator": "^1.1.8",
|
|
36
38
|
"@radix-ui/react-slider": "^1.3.6",
|
|
37
39
|
"@radix-ui/react-slot": "^1.2.4",
|