agentmomo 0.1.2 → 0.2.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 +18 -8
- package/dist/assets/index-BQyAbSge.js +5574 -0
- package/dist/assets/index-BjOLTppo.css +1 -0
- package/dist/claude-code-hook.cjs +66 -0
- package/dist/cli.js +42 -11
- package/dist/codex-cli-hook.cjs +415 -0
- package/dist/gemini-cli-hook.cjs +68 -0
- package/dist/index.html +3 -3
- package/dist/server.js +8064 -26
- package/package.json +29 -2
- package/dist/assets/index-BwEFhEay.js +0 -5367
- package/dist/assets/index-CS8oLlw3.css +0 -1
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// proxy/codex-cli-hook.ts
|
|
26
|
+
var import_http = __toESM(require("http"), 1);
|
|
27
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
28
|
+
var import_path = __toESM(require("path"), 1);
|
|
29
|
+
var AGENTMOMO_PORT = 9001;
|
|
30
|
+
var TIMEOUT_MS = 1500;
|
|
31
|
+
var LOG_FILE = import_path.default.join(
|
|
32
|
+
process.env.USERPROFILE ?? process.env.HOME ?? ".",
|
|
33
|
+
".agentmomo-hook.log"
|
|
34
|
+
);
|
|
35
|
+
var ROLE_LABELS = {
|
|
36
|
+
reader: "Reader",
|
|
37
|
+
writer: "Writer",
|
|
38
|
+
runner: "Runner",
|
|
39
|
+
searcher: "Searcher"
|
|
40
|
+
};
|
|
41
|
+
var pendingItems = /* @__PURE__ */ new Map();
|
|
42
|
+
var threadCwd = /* @__PURE__ */ new Map();
|
|
43
|
+
var registeredThreads = /* @__PURE__ */ new Set();
|
|
44
|
+
function readArg(name) {
|
|
45
|
+
const idx = process.argv.indexOf(name);
|
|
46
|
+
if (idx !== -1 && process.argv[idx + 1]) {
|
|
47
|
+
return process.argv[idx + 1].replace(/^['\"]+|['\"]+$/g, "");
|
|
48
|
+
}
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
var AGENTMOMO_API_KEY = readArg("--api-key") ?? process.env.AGENTMOMO_API_KEY ?? "";
|
|
52
|
+
function log(msg) {
|
|
53
|
+
try {
|
|
54
|
+
import_fs.default.appendFileSync(
|
|
55
|
+
LOG_FILE,
|
|
56
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] [codex] ${msg}
|
|
57
|
+
`
|
|
58
|
+
);
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function postEvent(body) {
|
|
63
|
+
const headers = {
|
|
64
|
+
"Content-Type": "application/json",
|
|
65
|
+
"Content-Length": Buffer.byteLength(body)
|
|
66
|
+
};
|
|
67
|
+
if (AGENTMOMO_API_KEY) {
|
|
68
|
+
headers.Authorization = `Bearer ${AGENTMOMO_API_KEY}`;
|
|
69
|
+
}
|
|
70
|
+
const req = import_http.default.request(
|
|
71
|
+
{
|
|
72
|
+
hostname: "localhost",
|
|
73
|
+
port: AGENTMOMO_PORT,
|
|
74
|
+
path: "/api/event",
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers,
|
|
77
|
+
timeout: TIMEOUT_MS
|
|
78
|
+
},
|
|
79
|
+
(res) => {
|
|
80
|
+
if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {
|
|
81
|
+
let responseBody = "";
|
|
82
|
+
res.on("data", (chunk) => {
|
|
83
|
+
responseBody += chunk.toString();
|
|
84
|
+
});
|
|
85
|
+
res.on("end", () => {
|
|
86
|
+
log(`POST /api/event failed ${res.statusCode}: ${responseBody}`);
|
|
87
|
+
});
|
|
88
|
+
} else {
|
|
89
|
+
res.resume();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
req.on("error", (err) => {
|
|
94
|
+
log(`POST error: ${err.message}`);
|
|
95
|
+
});
|
|
96
|
+
req.on("timeout", () => {
|
|
97
|
+
req.destroy();
|
|
98
|
+
});
|
|
99
|
+
req.write(body);
|
|
100
|
+
req.end();
|
|
101
|
+
}
|
|
102
|
+
function isEventType(actual, expected) {
|
|
103
|
+
if (typeof actual !== "string") return false;
|
|
104
|
+
return actual === expected || actual === expected.replace(".", "/");
|
|
105
|
+
}
|
|
106
|
+
function normalizeItemType(raw) {
|
|
107
|
+
if (typeof raw !== "string") return "unknown";
|
|
108
|
+
return raw.replace(/[\s_-]+/g, "").toLowerCase();
|
|
109
|
+
}
|
|
110
|
+
function getTimestamp(value) {
|
|
111
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
if (typeof value === "string") {
|
|
115
|
+
const parsed = Date.parse(value);
|
|
116
|
+
if (!Number.isNaN(parsed)) return parsed;
|
|
117
|
+
}
|
|
118
|
+
return Date.now();
|
|
119
|
+
}
|
|
120
|
+
function asRecord(value) {
|
|
121
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
function pickThreadId(payload) {
|
|
127
|
+
const params = asRecord(payload.params);
|
|
128
|
+
const item = asRecord(payload.item) ?? asRecord(params?.item);
|
|
129
|
+
const threadValue = payload.thread_id ?? payload.threadId ?? params?.threadId ?? item?.thread_id ?? item?.threadId;
|
|
130
|
+
return typeof threadValue === "string" && threadValue.trim() ? threadValue : "codex-thread";
|
|
131
|
+
}
|
|
132
|
+
function pickTurnId(payload) {
|
|
133
|
+
const params = asRecord(payload.params);
|
|
134
|
+
const item = asRecord(payload.item) ?? asRecord(params?.item);
|
|
135
|
+
const turnValue = payload.turn_id ?? payload.turnId ?? params?.turnId ?? item?.turn_id ?? item?.turnId;
|
|
136
|
+
return typeof turnValue === "string" && turnValue.trim() ? turnValue : void 0;
|
|
137
|
+
}
|
|
138
|
+
function pickCwd(payload) {
|
|
139
|
+
const params = asRecord(payload.params);
|
|
140
|
+
const item = asRecord(payload.item) ?? asRecord(params?.item);
|
|
141
|
+
const cwdValue = payload.cwd ?? params?.cwd ?? item?.cwd;
|
|
142
|
+
return typeof cwdValue === "string" && cwdValue.trim() ? cwdValue : void 0;
|
|
143
|
+
}
|
|
144
|
+
function getAgentIdentity(threadId, cwd, role) {
|
|
145
|
+
const folderName = cwd ? import_path.default.basename(cwd) : "Codex CLI";
|
|
146
|
+
const cwdSlug = folderName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 16) || "project";
|
|
147
|
+
return {
|
|
148
|
+
agentId: `cx-${cwdSlug}-${role}`,
|
|
149
|
+
agentName: `${folderName} \xB7 ${ROLE_LABELS[role]}`
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function truncate(value, max = 120) {
|
|
153
|
+
if (value.length <= max) return value;
|
|
154
|
+
return `${value.slice(0, max - 1)}\u2026`;
|
|
155
|
+
}
|
|
156
|
+
function extractCommandLabel(command) {
|
|
157
|
+
if (typeof command === "string" && command.trim()) {
|
|
158
|
+
return truncate(command.trim());
|
|
159
|
+
}
|
|
160
|
+
if (Array.isArray(command)) {
|
|
161
|
+
const tokens = command.filter((v) => typeof v === "string");
|
|
162
|
+
if (tokens.length > 0) return truncate(tokens.join(" "));
|
|
163
|
+
}
|
|
164
|
+
const commandObj = asRecord(command);
|
|
165
|
+
if (commandObj) {
|
|
166
|
+
if (Array.isArray(commandObj.argv)) {
|
|
167
|
+
const tokens = commandObj.argv.filter(
|
|
168
|
+
(v) => typeof v === "string"
|
|
169
|
+
);
|
|
170
|
+
if (tokens.length > 0) return truncate(tokens.join(" "));
|
|
171
|
+
}
|
|
172
|
+
if (typeof commandObj.command === "string" && commandObj.command.trim()) {
|
|
173
|
+
return truncate(commandObj.command.trim());
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return "shell";
|
|
177
|
+
}
|
|
178
|
+
function deriveItemInfo(item) {
|
|
179
|
+
const rawType = item.type ?? item.item_type;
|
|
180
|
+
const itemType = normalizeItemType(rawType);
|
|
181
|
+
if (itemType === "commandexecution") {
|
|
182
|
+
return {
|
|
183
|
+
role: "runner",
|
|
184
|
+
toolName: extractCommandLabel(item.command),
|
|
185
|
+
itemType: "command_execution",
|
|
186
|
+
threadId: "codex-thread"
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (itemType === "filechange") {
|
|
190
|
+
return {
|
|
191
|
+
role: "writer",
|
|
192
|
+
toolName: "file_change",
|
|
193
|
+
itemType: "file_change",
|
|
194
|
+
threadId: "codex-thread"
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
if (itemType === "mcptoolcall") {
|
|
198
|
+
const server = typeof item.server === "string" ? item.server : "mcp";
|
|
199
|
+
const tool = typeof item.tool === "string" ? item.tool : "tool";
|
|
200
|
+
return {
|
|
201
|
+
role: "runner",
|
|
202
|
+
toolName: `${server}.${tool}`,
|
|
203
|
+
itemType: "mcp_tool_call",
|
|
204
|
+
threadId: "codex-thread"
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (itemType === "websearch") {
|
|
208
|
+
return {
|
|
209
|
+
role: "searcher",
|
|
210
|
+
toolName: "web_search",
|
|
211
|
+
itemType: "web_search",
|
|
212
|
+
threadId: "codex-thread"
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if (itemType === "dynamictoolcall") {
|
|
216
|
+
const tool = typeof item.tool === "string" && item.tool.trim() ? item.tool : "dynamic_tool";
|
|
217
|
+
return {
|
|
218
|
+
role: "runner",
|
|
219
|
+
toolName: tool,
|
|
220
|
+
itemType: "dynamic_tool_call",
|
|
221
|
+
threadId: "codex-thread"
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
function emitEvent(event) {
|
|
227
|
+
postEvent(JSON.stringify(event));
|
|
228
|
+
}
|
|
229
|
+
function ensureThreadRegistered(threadId, cwd, timestamp) {
|
|
230
|
+
if (registeredThreads.has(threadId)) return;
|
|
231
|
+
registeredThreads.add(threadId);
|
|
232
|
+
const identity = getAgentIdentity(threadId, cwd, "runner");
|
|
233
|
+
emitEvent({
|
|
234
|
+
agentId: identity.agentId,
|
|
235
|
+
agentName: identity.agentName,
|
|
236
|
+
source: "codex-cli",
|
|
237
|
+
event: "agent_register",
|
|
238
|
+
toolName: "",
|
|
239
|
+
timestamp,
|
|
240
|
+
requestId: `${threadId}-register-${timestamp}`,
|
|
241
|
+
metadata: {
|
|
242
|
+
threadId,
|
|
243
|
+
cwd: cwd ?? "unknown",
|
|
244
|
+
provider: "codex-cli"
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
function handlePayload(payload) {
|
|
249
|
+
const type = payload.type;
|
|
250
|
+
const timestamp = getTimestamp(payload.timestamp);
|
|
251
|
+
const threadId = pickThreadId(payload);
|
|
252
|
+
const turnId = pickTurnId(payload);
|
|
253
|
+
const cwd = pickCwd(payload) ?? threadCwd.get(threadId);
|
|
254
|
+
if (cwd) threadCwd.set(threadId, cwd);
|
|
255
|
+
if (isEventType(type, "thread.started") || isEventType(type, "turn.started")) {
|
|
256
|
+
ensureThreadRegistered(threadId, cwd, timestamp);
|
|
257
|
+
const identity = getAgentIdentity(threadId, cwd, "runner");
|
|
258
|
+
emitEvent({
|
|
259
|
+
agentId: identity.agentId,
|
|
260
|
+
agentName: identity.agentName,
|
|
261
|
+
source: "codex-cli",
|
|
262
|
+
event: "agent_heartbeat",
|
|
263
|
+
toolName: "",
|
|
264
|
+
timestamp,
|
|
265
|
+
requestId: `${threadId}-heartbeat-${timestamp}`,
|
|
266
|
+
metadata: {
|
|
267
|
+
threadId,
|
|
268
|
+
turnId,
|
|
269
|
+
cwd: cwd ?? "unknown",
|
|
270
|
+
codexEventType: type
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (isEventType(type, "turn.failed") || isEventType(type, "error")) {
|
|
276
|
+
ensureThreadRegistered(threadId, cwd, timestamp);
|
|
277
|
+
const identity = getAgentIdentity(threadId, cwd, "runner");
|
|
278
|
+
const errObj = asRecord(payload.error);
|
|
279
|
+
const errMsg = typeof errObj?.message === "string" && errObj.message || typeof payload.message === "string" && payload.message || "Codex turn failed";
|
|
280
|
+
emitEvent({
|
|
281
|
+
agentId: identity.agentId,
|
|
282
|
+
agentName: identity.agentName,
|
|
283
|
+
source: "codex-cli",
|
|
284
|
+
event: "call_error",
|
|
285
|
+
toolName: "turn",
|
|
286
|
+
timestamp,
|
|
287
|
+
requestId: `${threadId}-turn-failed-${timestamp}`,
|
|
288
|
+
error: errMsg,
|
|
289
|
+
metadata: {
|
|
290
|
+
threadId,
|
|
291
|
+
turnId,
|
|
292
|
+
cwd: cwd ?? "unknown",
|
|
293
|
+
codexEventType: type
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (isEventType(type, "item.started") || isEventType(type, "item.completed")) {
|
|
299
|
+
const params = asRecord(payload.params);
|
|
300
|
+
const item = asRecord(payload.item) ?? asRecord(params?.item);
|
|
301
|
+
if (!item) return;
|
|
302
|
+
if (isEventType(type, "item.completed")) {
|
|
303
|
+
const rawItemType = normalizeItemType(item.type ?? item.item_type);
|
|
304
|
+
const isLlmText = rawItemType === "agentmessage" || rawItemType === "message" || rawItemType === "reasoning";
|
|
305
|
+
const textContent = typeof item.text === "string" ? item.text.trim() : typeof item.content === "string" ? item.content.trim() : void 0;
|
|
306
|
+
if (isLlmText && textContent) {
|
|
307
|
+
ensureThreadRegistered(threadId, cwd, timestamp);
|
|
308
|
+
const identity2 = getAgentIdentity(threadId, cwd, "runner");
|
|
309
|
+
emitEvent({
|
|
310
|
+
agentId: identity2.agentId,
|
|
311
|
+
agentName: identity2.agentName,
|
|
312
|
+
source: "codex-cli",
|
|
313
|
+
event: "agent_message",
|
|
314
|
+
toolName: "",
|
|
315
|
+
message: textContent,
|
|
316
|
+
timestamp,
|
|
317
|
+
requestId: `${threadId}-msg-${timestamp}`,
|
|
318
|
+
metadata: {
|
|
319
|
+
threadId,
|
|
320
|
+
turnId,
|
|
321
|
+
cwd: cwd ?? "unknown",
|
|
322
|
+
codexEventType: type
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const itemIdValue = item.id ?? payload.item_id ?? params?.itemId;
|
|
329
|
+
const itemId = typeof itemIdValue === "string" && itemIdValue.trim() ? itemIdValue : void 0;
|
|
330
|
+
const derived = deriveItemInfo(item);
|
|
331
|
+
if (!derived || !itemId) return;
|
|
332
|
+
const itemInfo = {
|
|
333
|
+
...derived,
|
|
334
|
+
threadId,
|
|
335
|
+
turnId,
|
|
336
|
+
cwd
|
|
337
|
+
};
|
|
338
|
+
ensureThreadRegistered(threadId, cwd, timestamp);
|
|
339
|
+
const identity = getAgentIdentity(threadId, cwd, itemInfo.role);
|
|
340
|
+
if (isEventType(type, "item.started")) {
|
|
341
|
+
pendingItems.set(itemId, itemInfo);
|
|
342
|
+
emitEvent({
|
|
343
|
+
agentId: identity.agentId,
|
|
344
|
+
agentName: identity.agentName,
|
|
345
|
+
source: "codex-cli",
|
|
346
|
+
event: "call_start",
|
|
347
|
+
toolName: itemInfo.toolName,
|
|
348
|
+
arguments: asRecord(item.arguments) ?? {},
|
|
349
|
+
timestamp,
|
|
350
|
+
requestId: `${threadId}-${itemId}-start-${timestamp}`,
|
|
351
|
+
metadata: {
|
|
352
|
+
threadId,
|
|
353
|
+
turnId,
|
|
354
|
+
itemId,
|
|
355
|
+
itemType: itemInfo.itemType,
|
|
356
|
+
cwd: cwd ?? "unknown"
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const existing = pendingItems.get(itemId) ?? itemInfo;
|
|
362
|
+
pendingItems.delete(itemId);
|
|
363
|
+
const status = typeof item.status === "string" ? item.status.toLowerCase() : "completed";
|
|
364
|
+
const itemError = asRecord(item.error)?.message ?? (typeof item.error === "string" ? item.error : void 0);
|
|
365
|
+
const failed = status.includes("fail") || status.includes("error") || status.includes("declin") || !!itemError;
|
|
366
|
+
emitEvent({
|
|
367
|
+
agentId: identity.agentId,
|
|
368
|
+
agentName: identity.agentName,
|
|
369
|
+
source: "codex-cli",
|
|
370
|
+
event: failed ? "call_error" : "call_end",
|
|
371
|
+
toolName: existing.toolName,
|
|
372
|
+
timestamp,
|
|
373
|
+
requestId: `${threadId}-${itemId}-end-${timestamp}`,
|
|
374
|
+
...failed ? { error: itemError ?? `Item failed (${status})` } : {},
|
|
375
|
+
metadata: {
|
|
376
|
+
threadId,
|
|
377
|
+
turnId,
|
|
378
|
+
itemId,
|
|
379
|
+
itemType: existing.itemType,
|
|
380
|
+
cwd: cwd ?? "unknown",
|
|
381
|
+
codexStatus: status
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
process.stdin.setEncoding("utf-8");
|
|
387
|
+
var buffer = "";
|
|
388
|
+
process.stdin.on("data", (chunk) => {
|
|
389
|
+
buffer += chunk;
|
|
390
|
+
let newlineIndex = buffer.indexOf("\n");
|
|
391
|
+
while (newlineIndex !== -1) {
|
|
392
|
+
const line = buffer.slice(0, newlineIndex).trim();
|
|
393
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
394
|
+
if (line) {
|
|
395
|
+
try {
|
|
396
|
+
const payload = JSON.parse(line);
|
|
397
|
+
handlePayload(payload);
|
|
398
|
+
} catch (err) {
|
|
399
|
+
log(`Invalid JSONL line: ${err?.message ?? String(err)}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
newlineIndex = buffer.indexOf("\n");
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
process.stdin.on("end", () => {
|
|
406
|
+
const tail = buffer.trim();
|
|
407
|
+
if (tail) {
|
|
408
|
+
try {
|
|
409
|
+
const payload = JSON.parse(tail);
|
|
410
|
+
handlePayload(payload);
|
|
411
|
+
} catch (err) {
|
|
412
|
+
log(`Invalid tail JSON: ${err?.message ?? String(err)}`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
});
|
package/dist/gemini-cli-hook.cjs
CHANGED
|
@@ -123,6 +123,70 @@ var ROLE_LABELS = {
|
|
|
123
123
|
runner: "Runner",
|
|
124
124
|
searcher: "Searcher"
|
|
125
125
|
};
|
|
126
|
+
function extractToolMessage(toolName, toolInput) {
|
|
127
|
+
const str = (v, max = 80) => typeof v === "string" && v.trim() ? v.trim().slice(0, max) : void 0;
|
|
128
|
+
switch (toolName) {
|
|
129
|
+
case "read_file":
|
|
130
|
+
case "read_many_files":
|
|
131
|
+
return str(toolInput["path"] ?? toolInput["paths"]) ? `Reading ${str(toolInput["path"] ?? toolInput["paths"])}` : void 0;
|
|
132
|
+
case "list_directory":
|
|
133
|
+
return str(toolInput["path"]) ? `Listing ${str(toolInput["path"])}` : void 0;
|
|
134
|
+
case "write_file":
|
|
135
|
+
return str(toolInput["path"]) ? `Writing ${str(toolInput["path"])}` : void 0;
|
|
136
|
+
case "replace":
|
|
137
|
+
return str(toolInput["path"]) ? `Editing ${str(toolInput["path"])}` : void 0;
|
|
138
|
+
case "run_shell_command": {
|
|
139
|
+
const cmd = str(toolInput["command"], 100);
|
|
140
|
+
return cmd ? `Running: ${cmd}` : void 0;
|
|
141
|
+
}
|
|
142
|
+
case "grep_search": {
|
|
143
|
+
const pat = str(toolInput["pattern"]);
|
|
144
|
+
const dir = str(toolInput["directory"] ?? toolInput["path"], 40);
|
|
145
|
+
return pat ? `Searching "${pat}"${dir ? ` in ${dir}` : ""}` : void 0;
|
|
146
|
+
}
|
|
147
|
+
case "google_web_search":
|
|
148
|
+
return str(toolInput["query"]) ? `Web search: ${str(toolInput["query"])}` : void 0;
|
|
149
|
+
case "web_fetch":
|
|
150
|
+
return str(toolInput["url"]) ? `Fetching ${str(toolInput["url"])}` : void 0;
|
|
151
|
+
case "save_memory":
|
|
152
|
+
return "Saving to memory";
|
|
153
|
+
case "write_todos":
|
|
154
|
+
return "Updating task list";
|
|
155
|
+
case "ask_user": {
|
|
156
|
+
const q = str(toolInput["question"], 80);
|
|
157
|
+
return q ? `Asking: ${q}` : void 0;
|
|
158
|
+
}
|
|
159
|
+
case "complete_task": {
|
|
160
|
+
const result = str(toolInput["result"], 80);
|
|
161
|
+
return result ? `Completing task: ${result}` : void 0;
|
|
162
|
+
}
|
|
163
|
+
default:
|
|
164
|
+
if (toolName.startsWith("mcp_")) {
|
|
165
|
+
return `Using ${toolName.replace(/^mcp_[^_]+_/, "").replace(/_/g, " ")}`;
|
|
166
|
+
}
|
|
167
|
+
return void 0;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function extractResultText(response) {
|
|
171
|
+
if (!response || typeof response !== "object") return void 0;
|
|
172
|
+
const obj = response;
|
|
173
|
+
for (const key of ["text", "content", "output", "result", "stdout"]) {
|
|
174
|
+
if (typeof obj[key] === "string" && obj[key].trim())
|
|
175
|
+
return obj[key].trim();
|
|
176
|
+
}
|
|
177
|
+
const llm = obj.llmContent;
|
|
178
|
+
if (typeof llm === "string" && llm.trim()) return llm.trim();
|
|
179
|
+
if (llm && typeof llm === "object") {
|
|
180
|
+
const llmObj = llm;
|
|
181
|
+
if (typeof llmObj.text === "string" && llmObj.text.trim())
|
|
182
|
+
return llmObj.text.trim();
|
|
183
|
+
if (Array.isArray(llmObj.parts)) {
|
|
184
|
+
const parts = llmObj.parts.map((p) => typeof p === "string" ? p : p?.text).filter((t) => typeof t === "string" && t.trim());
|
|
185
|
+
if (parts.length > 0) return parts.join("\n").trim() || void 0;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return void 0;
|
|
189
|
+
}
|
|
126
190
|
function getRole(toolName) {
|
|
127
191
|
if (TOOL_ROLES[toolName]) return TOOL_ROLES[toolName];
|
|
128
192
|
if (toolName.startsWith("mcp_")) {
|
|
@@ -220,6 +284,7 @@ process.stdin.on("end", () => {
|
|
|
220
284
|
} else {
|
|
221
285
|
eventType = "call_start";
|
|
222
286
|
}
|
|
287
|
+
const resultText = isAfter ? extractResultText(tool_response) : void 0;
|
|
223
288
|
const event = {
|
|
224
289
|
agentId,
|
|
225
290
|
agentName,
|
|
@@ -230,6 +295,9 @@ process.stdin.on("end", () => {
|
|
|
230
295
|
timestamp: timestamp ? new Date(timestamp).getTime() : Date.now(),
|
|
231
296
|
requestId: `${session_id}-${tool_name}-${Date.now()}`,
|
|
232
297
|
...hasError ? { error: String(tool_response.error) } : {},
|
|
298
|
+
// On BeforeTool: attach context hint; on AfterTool: attach tool result
|
|
299
|
+
...!isAfter && tool_input ? { message: extractToolMessage(tool_name, tool_input) } : {},
|
|
300
|
+
...isAfter && resultText ? { message: resultText } : {},
|
|
233
301
|
metadata: {
|
|
234
302
|
cwd: cwd ?? "unknown",
|
|
235
303
|
role,
|
package/dist/index.html
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>
|
|
7
|
+
<title>AgentMOMO— MCP Activity Visualizer</title>
|
|
8
8
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
9
9
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
10
10
|
<link
|
|
11
11
|
href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&display=swap"
|
|
12
12
|
rel="stylesheet"
|
|
13
13
|
/>
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-BQyAbSge.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BjOLTppo.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="root"></div>
|