@integrity-labs/agt-cli 0.15.3 → 0.15.6
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/bin/agt.js +366 -48
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-IQI7XAQ6.js → chunk-IGKAMH32.js} +43 -11
- package/dist/chunk-IGKAMH32.js.map +1 -0
- package/dist/{chunk-IEVDKEIT.js → chunk-S3SFU5IM.js} +1 -1
- package/dist/{chunk-IEVDKEIT.js.map → chunk-S3SFU5IM.js.map} +1 -1
- package/dist/lib/manager-worker.js +73 -15
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-ALP5DGFI.js → persistent-session-Q4X2KRS6.js} +2 -2
- package/mcp/index.js +0 -0
- package/mcp/slack-channel.js +17 -6
- package/mcp/telegram-channel.js +2 -2
- package/package.json +4 -1
- package/dist/chunk-IQI7XAQ6.js.map +0 -1
- /package/dist/{persistent-session-ALP5DGFI.js.map → persistent-session-Q4X2KRS6.js.map} +0 -0
package/dist/bin/agt.js
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
getFramework,
|
|
25
25
|
getHost,
|
|
26
26
|
getHostId,
|
|
27
|
+
getManagerPaths,
|
|
27
28
|
getScopesByCategory,
|
|
28
29
|
getTemplate,
|
|
29
30
|
info,
|
|
@@ -45,11 +46,11 @@ import {
|
|
|
45
46
|
success,
|
|
46
47
|
table,
|
|
47
48
|
warn
|
|
48
|
-
} from "../chunk-
|
|
49
|
+
} from "../chunk-IGKAMH32.js";
|
|
49
50
|
|
|
50
51
|
// src/bin/agt.ts
|
|
51
|
-
import { join as
|
|
52
|
-
import { homedir as
|
|
52
|
+
import { join as join10 } from "path";
|
|
53
|
+
import { homedir as homedir3 } from "os";
|
|
53
54
|
import { Command } from "commander";
|
|
54
55
|
|
|
55
56
|
// src/commands/whoami.ts
|
|
@@ -543,11 +544,11 @@ async function lintCommand(path) {
|
|
|
543
544
|
process.exitCode = 1;
|
|
544
545
|
return;
|
|
545
546
|
}
|
|
546
|
-
const { readdirSync, statSync } = await import("fs");
|
|
547
|
+
const { readdirSync, statSync: statSync2 } = await import("fs");
|
|
547
548
|
const entries = readdirSync(augmentedDir);
|
|
548
549
|
for (const entry of entries) {
|
|
549
550
|
const entryPath = join2(augmentedDir, entry);
|
|
550
|
-
if (
|
|
551
|
+
if (statSync2(entryPath).isDirectory()) {
|
|
551
552
|
dirs.push({ name: entry, dir: entryPath });
|
|
552
553
|
}
|
|
553
554
|
}
|
|
@@ -2183,17 +2184,333 @@ function terminate(child) {
|
|
|
2183
2184
|
}
|
|
2184
2185
|
}
|
|
2185
2186
|
|
|
2187
|
+
// src/commands/manager-watch.tsx
|
|
2188
|
+
import { useEffect, useState, useMemo } from "react";
|
|
2189
|
+
import { render, Box, Text, useApp, useInput } from "ink";
|
|
2190
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, statSync, openSync, readSync, closeSync } from "fs";
|
|
2191
|
+
import { homedir } from "os";
|
|
2192
|
+
import { join as join7 } from "path";
|
|
2193
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2194
|
+
var REFRESH_MS = 1e3;
|
|
2195
|
+
var LOG_TAIL_LINES = 200;
|
|
2196
|
+
var DETAIL_RECENT_LINES = 50;
|
|
2197
|
+
function managerWatchCommand(opts = {}) {
|
|
2198
|
+
const configDir = opts.configDir ?? join7(homedir(), ".augmented");
|
|
2199
|
+
const paths = getManagerPaths(configDir);
|
|
2200
|
+
const isTty = process.stdout.isTTY === true && process.stdin.isTTY === true;
|
|
2201
|
+
if (opts.noTui || !isTty) {
|
|
2202
|
+
streamLogFile(paths.logFile);
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx(Dashboard, { stateFile: paths.stateFile, logFile: paths.logFile }));
|
|
2206
|
+
waitUntilExit().catch(() => {
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2209
|
+
function readState(stateFile) {
|
|
2210
|
+
try {
|
|
2211
|
+
if (!existsSync2(stateFile)) return null;
|
|
2212
|
+
const raw = readFileSync2(stateFile, "utf-8");
|
|
2213
|
+
return JSON.parse(raw);
|
|
2214
|
+
} catch {
|
|
2215
|
+
return null;
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
function tailLogFile(logFile, lines) {
|
|
2219
|
+
if (!existsSync2(logFile)) return [];
|
|
2220
|
+
try {
|
|
2221
|
+
const fileSize = statSync(logFile).size;
|
|
2222
|
+
if (fileSize === 0) return [];
|
|
2223
|
+
const readSize = Math.min(fileSize, lines * 800);
|
|
2224
|
+
const fd = openSync(logFile, "r");
|
|
2225
|
+
try {
|
|
2226
|
+
const buf = Buffer.alloc(readSize);
|
|
2227
|
+
readSync(fd, buf, 0, readSize, fileSize - readSize);
|
|
2228
|
+
const text = buf.toString("utf-8");
|
|
2229
|
+
const all = text.split("\n").filter((l) => l.length > 0);
|
|
2230
|
+
return all.slice(-lines);
|
|
2231
|
+
} finally {
|
|
2232
|
+
closeSync(fd);
|
|
2233
|
+
}
|
|
2234
|
+
} catch {
|
|
2235
|
+
return [];
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
var Dashboard = ({ stateFile, logFile }) => {
|
|
2239
|
+
const { exit } = useApp();
|
|
2240
|
+
const [status, setStatus] = useState(() => readState(stateFile));
|
|
2241
|
+
const [logLines, setLogLines] = useState(() => tailLogFile(logFile, LOG_TAIL_LINES));
|
|
2242
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
2243
|
+
const [view, setView] = useState("grid");
|
|
2244
|
+
const [tick, setTick] = useState(0);
|
|
2245
|
+
useEffect(() => {
|
|
2246
|
+
const id = setInterval(() => {
|
|
2247
|
+
setStatus(readState(stateFile));
|
|
2248
|
+
setLogLines(tailLogFile(logFile, LOG_TAIL_LINES));
|
|
2249
|
+
setTick((t) => t + 1);
|
|
2250
|
+
}, REFRESH_MS);
|
|
2251
|
+
return () => clearInterval(id);
|
|
2252
|
+
}, [stateFile, logFile]);
|
|
2253
|
+
const agents = status?.agents ?? [];
|
|
2254
|
+
const selected = agents[selectedIndex];
|
|
2255
|
+
useInput((input4, key) => {
|
|
2256
|
+
if (view === "detail") {
|
|
2257
|
+
if (key.escape || input4 === "q") setView("grid");
|
|
2258
|
+
else if (key.ctrl && input4 === "c") exit();
|
|
2259
|
+
return;
|
|
2260
|
+
}
|
|
2261
|
+
if (input4 === "q" || key.ctrl && input4 === "c") {
|
|
2262
|
+
exit();
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
if (agents.length === 0) return;
|
|
2266
|
+
if (key.upArrow || key.leftArrow) {
|
|
2267
|
+
setSelectedIndex((i) => (i - 1 + agents.length) % agents.length);
|
|
2268
|
+
} else if (key.downArrow || key.rightArrow) {
|
|
2269
|
+
setSelectedIndex((i) => (i + 1) % agents.length);
|
|
2270
|
+
} else if (key.return) {
|
|
2271
|
+
setView("detail");
|
|
2272
|
+
}
|
|
2273
|
+
});
|
|
2274
|
+
if (!status) {
|
|
2275
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
|
|
2276
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "\u26A0 Manager state not found" }),
|
|
2277
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2278
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2279
|
+
"Looked for: ",
|
|
2280
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: stateFile })
|
|
2281
|
+
] }),
|
|
2282
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2283
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2284
|
+
"Start the manager first: ",
|
|
2285
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "agt manager start" })
|
|
2286
|
+
] }),
|
|
2287
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2288
|
+
"Press ",
|
|
2289
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: "q" }),
|
|
2290
|
+
" to quit."
|
|
2291
|
+
] })
|
|
2292
|
+
] });
|
|
2293
|
+
}
|
|
2294
|
+
if (view === "detail" && selected) {
|
|
2295
|
+
return /* @__PURE__ */ jsx(DetailView, { agent: selected, logLines });
|
|
2296
|
+
}
|
|
2297
|
+
return /* @__PURE__ */ jsx(GridView, { status, agents, selectedIndex, logLines, tick });
|
|
2298
|
+
};
|
|
2299
|
+
var GridView = ({ status, agents, selectedIndex, logLines, tick }) => {
|
|
2300
|
+
const lastLogLine = logLines[logLines.length - 1] ?? "";
|
|
2301
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2302
|
+
/* @__PURE__ */ jsx(HeaderBar, { status, tick }),
|
|
2303
|
+
agents.length === 0 ? /* @__PURE__ */ jsx(Box, { padding: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No agents discovered yet. Manager is polling\u2026" }) }) : /* @__PURE__ */ jsx(Box, { flexDirection: "row", flexWrap: "wrap", paddingX: 1, children: agents.map((agent2, i) => /* @__PURE__ */ jsx(
|
|
2304
|
+
AgentBox,
|
|
2305
|
+
{
|
|
2306
|
+
agent: agent2,
|
|
2307
|
+
selected: i === selectedIndex,
|
|
2308
|
+
recentLogLine: mostRecentLineForAgent(logLines, agent2.codeName)
|
|
2309
|
+
},
|
|
2310
|
+
agent2.agentId
|
|
2311
|
+
)) }),
|
|
2312
|
+
/* @__PURE__ */ jsx(Footer, { tail: lastLogLine })
|
|
2313
|
+
] });
|
|
2314
|
+
};
|
|
2315
|
+
var HeaderBar = ({ status, tick }) => {
|
|
2316
|
+
void tick;
|
|
2317
|
+
return /* @__PURE__ */ jsx(Box, { paddingX: 1, paddingY: 0, borderStyle: "single", borderColor: "cyan", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
|
|
2318
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
2319
|
+
"agt manager \xB7 ",
|
|
2320
|
+
status.agents.length,
|
|
2321
|
+
" agent",
|
|
2322
|
+
status.agents.length === 1 ? "" : "s"
|
|
2323
|
+
] }),
|
|
2324
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2325
|
+
"PID ",
|
|
2326
|
+
status.pid,
|
|
2327
|
+
" \xB7 polls ",
|
|
2328
|
+
status.pollCount,
|
|
2329
|
+
" \xB7 errors ",
|
|
2330
|
+
status.errorCount,
|
|
2331
|
+
" \xB7 last poll ",
|
|
2332
|
+
relativeTime(status.lastPollAt)
|
|
2333
|
+
] })
|
|
2334
|
+
] }) });
|
|
2335
|
+
};
|
|
2336
|
+
var Footer = ({ tail }) => /* @__PURE__ */ jsxs(Box, { paddingX: 1, flexDirection: "column", children: [
|
|
2337
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2338
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 select \xB7 " }),
|
|
2339
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Enter detail \xB7 " }),
|
|
2340
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "q quit" })
|
|
2341
|
+
] }),
|
|
2342
|
+
tail && /* @__PURE__ */ jsxs(Box, { children: [
|
|
2343
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "last log: " }),
|
|
2344
|
+
/* @__PURE__ */ jsx(Text, { children: truncate(tail, process.stdout.columns ? process.stdout.columns - 12 : 100) })
|
|
2345
|
+
] })
|
|
2346
|
+
] });
|
|
2347
|
+
var AgentBox = ({ agent: agent2, selected, recentLogLine }) => {
|
|
2348
|
+
const isError = agent2.status !== "active" && agent2.status !== "paused" && agent2.status !== "";
|
|
2349
|
+
const borderColor = selected ? "yellow" : isError ? "red" : "gray";
|
|
2350
|
+
const statusColor = agent2.status === "active" ? "green" : agent2.status === "paused" ? "yellow" : isError ? "red" : "gray";
|
|
2351
|
+
const gateway = agent2.gatewayRunning ? `:${agent2.gatewayPort} (PID ${agent2.gatewayPid})` : agent2.gatewayPort ? `:${agent2.gatewayPort} down` : "\u2014";
|
|
2352
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor, paddingX: 1, marginRight: 1, marginBottom: 0, width: 42, children: [
|
|
2353
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2354
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: agent2.codeName }),
|
|
2355
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2356
|
+
/* @__PURE__ */ jsx(Text, { color: statusColor, children: agent2.status || "unknown" })
|
|
2357
|
+
] }),
|
|
2358
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2359
|
+
"charter ",
|
|
2360
|
+
agent2.charterVersion || "\u2014",
|
|
2361
|
+
" \xB7 tools ",
|
|
2362
|
+
agent2.toolsVersion || "\u2014"
|
|
2363
|
+
] }),
|
|
2364
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2365
|
+
"gateway ",
|
|
2366
|
+
gateway
|
|
2367
|
+
] }),
|
|
2368
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2369
|
+
"acp sessions ",
|
|
2370
|
+
agent2.acpSessions?.length ?? 0
|
|
2371
|
+
] }),
|
|
2372
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2373
|
+
"last provision ",
|
|
2374
|
+
relativeTime(agent2.lastProvisionAt)
|
|
2375
|
+
] }),
|
|
2376
|
+
recentLogLine && /* @__PURE__ */ jsxs(Text, { children: [
|
|
2377
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u25B8" }),
|
|
2378
|
+
" ",
|
|
2379
|
+
truncate(recentLogLine, 36)
|
|
2380
|
+
] })
|
|
2381
|
+
] });
|
|
2382
|
+
};
|
|
2383
|
+
var DetailView = ({ agent: agent2, logLines }) => {
|
|
2384
|
+
const recent = useMemo(
|
|
2385
|
+
() => logLines.filter((l) => l.toLowerCase().includes(agent2.codeName.toLowerCase())).slice(-DETAIL_RECENT_LINES),
|
|
2386
|
+
[logLines, agent2.codeName]
|
|
2387
|
+
);
|
|
2388
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2389
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, borderStyle: "double", borderColor: "cyan", children: [
|
|
2390
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: agent2.codeName }),
|
|
2391
|
+
/* @__PURE__ */ jsx(Text, { children: " \xB7 " }),
|
|
2392
|
+
/* @__PURE__ */ jsx(Text, { children: agent2.status || "unknown" }),
|
|
2393
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2394
|
+
" \xB7 charter ",
|
|
2395
|
+
agent2.charterVersion || "\u2014",
|
|
2396
|
+
" \xB7 tools ",
|
|
2397
|
+
agent2.toolsVersion || "\u2014"
|
|
2398
|
+
] })
|
|
2399
|
+
] }),
|
|
2400
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, marginTop: 1, flexDirection: "column", children: [
|
|
2401
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Gateway" }),
|
|
2402
|
+
/* @__PURE__ */ jsx(Text, { children: agent2.gatewayRunning ? `running on :${agent2.gatewayPort} (PID ${agent2.gatewayPid})` : agent2.gatewayPort ? `configured :${agent2.gatewayPort} but not running` : "no gateway configured" })
|
|
2403
|
+
] }),
|
|
2404
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, marginTop: 1, flexDirection: "column", children: [
|
|
2405
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
2406
|
+
"ACP sessions (",
|
|
2407
|
+
agent2.acpSessions?.length ?? 0,
|
|
2408
|
+
")"
|
|
2409
|
+
] }),
|
|
2410
|
+
(agent2.acpSessions ?? []).length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "none" }) : (agent2.acpSessions ?? []).map((s) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
2411
|
+
"\xB7 ",
|
|
2412
|
+
s.agentCommand,
|
|
2413
|
+
" ",
|
|
2414
|
+
s.sessionName ?? "",
|
|
2415
|
+
" \xB7 ",
|
|
2416
|
+
s.queueState,
|
|
2417
|
+
" \xB7 turns ",
|
|
2418
|
+
s.turnCount,
|
|
2419
|
+
" \xB7 started ",
|
|
2420
|
+
relativeTime(s.startedAt)
|
|
2421
|
+
] }, s.sessionId))
|
|
2422
|
+
] }),
|
|
2423
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, marginTop: 1, flexDirection: "column", children: [
|
|
2424
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
2425
|
+
"Recent activity (",
|
|
2426
|
+
recent.length,
|
|
2427
|
+
' lines, filtered to "',
|
|
2428
|
+
agent2.codeName,
|
|
2429
|
+
'")'
|
|
2430
|
+
] }),
|
|
2431
|
+
recent.length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "nothing in the log mentions this agent yet" }) : recent.map((line, i) => /* @__PURE__ */ jsx(Text, { children: truncate(line, process.stdout.columns ? process.stdout.columns - 4 : 120) }, i))
|
|
2432
|
+
] }),
|
|
2433
|
+
/* @__PURE__ */ jsx(Box, { paddingX: 1, marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "esc / q \xB7 back to grid" }) })
|
|
2434
|
+
] });
|
|
2435
|
+
};
|
|
2436
|
+
function mostRecentLineForAgent(lines, codeName) {
|
|
2437
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2438
|
+
const line = lines[i];
|
|
2439
|
+
if (line && line.toLowerCase().includes(codeName.toLowerCase())) return line;
|
|
2440
|
+
}
|
|
2441
|
+
return null;
|
|
2442
|
+
}
|
|
2443
|
+
function relativeTime(iso) {
|
|
2444
|
+
if (!iso) return "never";
|
|
2445
|
+
const t = new Date(iso).getTime();
|
|
2446
|
+
if (isNaN(t)) return "never";
|
|
2447
|
+
const diff = Math.max(0, Date.now() - t);
|
|
2448
|
+
const sec = Math.floor(diff / 1e3);
|
|
2449
|
+
if (sec < 60) return `${sec}s ago`;
|
|
2450
|
+
const min = Math.floor(sec / 60);
|
|
2451
|
+
if (min < 60) return `${min}m ago`;
|
|
2452
|
+
const hr = Math.floor(min / 60);
|
|
2453
|
+
if (hr < 24) return `${hr}h ago`;
|
|
2454
|
+
return `${Math.floor(hr / 24)}d ago`;
|
|
2455
|
+
}
|
|
2456
|
+
function truncate(s, max) {
|
|
2457
|
+
return s.length > max ? `${s.slice(0, Math.max(0, max - 1))}\u2026` : s;
|
|
2458
|
+
}
|
|
2459
|
+
function streamLogFile(logFile) {
|
|
2460
|
+
if (!existsSync2(logFile)) {
|
|
2461
|
+
process.stderr.write(`No manager log found at ${logFile}.
|
|
2462
|
+
Start the manager first: agt manager start
|
|
2463
|
+
`);
|
|
2464
|
+
process.exitCode = 1;
|
|
2465
|
+
return;
|
|
2466
|
+
}
|
|
2467
|
+
let lastSize = 0;
|
|
2468
|
+
try {
|
|
2469
|
+
const initial = readFileSync2(logFile, "utf-8");
|
|
2470
|
+
process.stdout.write(initial);
|
|
2471
|
+
lastSize = statSync(logFile).size;
|
|
2472
|
+
} catch (err) {
|
|
2473
|
+
process.stderr.write(`Failed to read log: ${err.message}
|
|
2474
|
+
`);
|
|
2475
|
+
process.exitCode = 1;
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
const id = setInterval(() => {
|
|
2479
|
+
try {
|
|
2480
|
+
const size = statSync(logFile).size;
|
|
2481
|
+
if (size < lastSize) lastSize = 0;
|
|
2482
|
+
if (size === lastSize) return;
|
|
2483
|
+
const fd = openSync(logFile, "r");
|
|
2484
|
+
try {
|
|
2485
|
+
const buf = Buffer.alloc(size - lastSize);
|
|
2486
|
+
readSync(fd, buf, 0, buf.length, lastSize);
|
|
2487
|
+
process.stdout.write(buf.toString("utf-8"));
|
|
2488
|
+
lastSize = size;
|
|
2489
|
+
} finally {
|
|
2490
|
+
closeSync(fd);
|
|
2491
|
+
}
|
|
2492
|
+
} catch {
|
|
2493
|
+
}
|
|
2494
|
+
}, 500);
|
|
2495
|
+
const stop = () => {
|
|
2496
|
+
clearInterval(id);
|
|
2497
|
+
process.exit(0);
|
|
2498
|
+
};
|
|
2499
|
+
process.on("SIGINT", stop);
|
|
2500
|
+
process.on("SIGTERM", stop);
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2186
2503
|
// src/commands/agent.ts
|
|
2187
2504
|
import chalk13 from "chalk";
|
|
2188
2505
|
import JSON52 from "json5";
|
|
2189
|
-
import { readFileSync as
|
|
2190
|
-
import { join as
|
|
2506
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
|
|
2507
|
+
import { join as join8 } from "path";
|
|
2191
2508
|
async function agentShowCommand(codeName, opts) {
|
|
2192
2509
|
const json = isJsonMode();
|
|
2193
|
-
const unifiedDir =
|
|
2194
|
-
const legacyDir =
|
|
2195
|
-
const agentDir =
|
|
2196
|
-
const hasLocalConfig =
|
|
2510
|
+
const unifiedDir = join8(opts.configDir, codeName, "provision");
|
|
2511
|
+
const legacyDir = join8(opts.configDir, codeName, "claudecode", "provision");
|
|
2512
|
+
const agentDir = existsSync3(unifiedDir) ? unifiedDir : legacyDir;
|
|
2513
|
+
const hasLocalConfig = existsSync3(agentDir);
|
|
2197
2514
|
let apiChannels = null;
|
|
2198
2515
|
let apiAgent = null;
|
|
2199
2516
|
if (getApiKey()) {
|
|
@@ -2226,34 +2543,34 @@ async function agentShowCommand(codeName, opts) {
|
|
|
2226
2543
|
let openclawConfig = null;
|
|
2227
2544
|
let agentState = null;
|
|
2228
2545
|
if (hasLocalConfig) {
|
|
2229
|
-
const charterPath =
|
|
2230
|
-
if (
|
|
2231
|
-
const raw =
|
|
2546
|
+
const charterPath = join8(agentDir, "CHARTER.md");
|
|
2547
|
+
if (existsSync3(charterPath)) {
|
|
2548
|
+
const raw = readFileSync3(charterPath, "utf-8");
|
|
2232
2549
|
const parsed = extractFrontmatter(raw);
|
|
2233
2550
|
if (parsed.frontmatter) {
|
|
2234
2551
|
charter = parsed.frontmatter;
|
|
2235
2552
|
}
|
|
2236
2553
|
}
|
|
2237
|
-
const toolsPath =
|
|
2238
|
-
if (
|
|
2239
|
-
const raw =
|
|
2554
|
+
const toolsPath = join8(agentDir, "TOOLS.md");
|
|
2555
|
+
if (existsSync3(toolsPath)) {
|
|
2556
|
+
const raw = readFileSync3(toolsPath, "utf-8");
|
|
2240
2557
|
const parsed = extractFrontmatter(raw);
|
|
2241
2558
|
if (parsed.frontmatter) {
|
|
2242
2559
|
tools = parsed.frontmatter;
|
|
2243
2560
|
}
|
|
2244
2561
|
}
|
|
2245
|
-
const openclawPath =
|
|
2246
|
-
if (
|
|
2562
|
+
const openclawPath = join8(agentDir, "openclaw.json5");
|
|
2563
|
+
if (existsSync3(openclawPath)) {
|
|
2247
2564
|
try {
|
|
2248
|
-
const raw =
|
|
2565
|
+
const raw = readFileSync3(openclawPath, "utf-8");
|
|
2249
2566
|
openclawConfig = JSON52.parse(raw);
|
|
2250
2567
|
} catch {
|
|
2251
2568
|
}
|
|
2252
2569
|
}
|
|
2253
|
-
const statePath =
|
|
2254
|
-
if (
|
|
2570
|
+
const statePath = join8(opts.configDir, "manager-state.json");
|
|
2571
|
+
if (existsSync3(statePath)) {
|
|
2255
2572
|
try {
|
|
2256
|
-
const raw =
|
|
2573
|
+
const raw = readFileSync3(statePath, "utf-8");
|
|
2257
2574
|
const state = JSON.parse(raw);
|
|
2258
2575
|
agentState = state.agents?.find((a) => a.codeName === codeName) ?? null;
|
|
2259
2576
|
} catch {
|
|
@@ -2590,24 +2907,24 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
2590
2907
|
}
|
|
2591
2908
|
|
|
2592
2909
|
// src/commands/setup.ts
|
|
2593
|
-
import { existsSync as
|
|
2594
|
-
import { join as
|
|
2595
|
-
import { homedir } from "os";
|
|
2910
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, accessSync, constants as fsConstants } from "fs";
|
|
2911
|
+
import { join as join9, dirname } from "path";
|
|
2912
|
+
import { homedir as homedir2 } from "os";
|
|
2596
2913
|
import chalk15 from "chalk";
|
|
2597
2914
|
import ora13 from "ora";
|
|
2598
2915
|
function detectShellProfile() {
|
|
2599
2916
|
const shell = process.env["SHELL"] ?? "";
|
|
2600
|
-
const home =
|
|
2917
|
+
const home = homedir2();
|
|
2601
2918
|
if (shell.includes("zsh")) {
|
|
2602
|
-
return
|
|
2919
|
+
return join9(home, ".zshrc");
|
|
2603
2920
|
}
|
|
2604
2921
|
if (shell.includes("fish")) {
|
|
2605
|
-
const fishConfig =
|
|
2922
|
+
const fishConfig = join9(home, ".config", "fish", "config.fish");
|
|
2606
2923
|
return fishConfig;
|
|
2607
2924
|
}
|
|
2608
|
-
const bashrc =
|
|
2609
|
-
if (
|
|
2610
|
-
return
|
|
2925
|
+
const bashrc = join9(home, ".bashrc");
|
|
2926
|
+
if (existsSync4(bashrc)) return bashrc;
|
|
2927
|
+
return join9(home, ".bash_profile");
|
|
2611
2928
|
}
|
|
2612
2929
|
function maybeWriteSystemWideEnv(apiUrl, apiKey, consoleUrl) {
|
|
2613
2930
|
const empty = { etcEnvironment: false, profileD: false, bashrc: false };
|
|
@@ -2633,14 +2950,14 @@ function quoteForFishShell(value) {
|
|
|
2633
2950
|
}
|
|
2634
2951
|
function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
2635
2952
|
const envPath = "/etc/environment";
|
|
2636
|
-
if (!
|
|
2953
|
+
if (!existsSync4(envPath)) return false;
|
|
2637
2954
|
try {
|
|
2638
2955
|
accessSync(envPath, fsConstants.W_OK);
|
|
2639
2956
|
} catch {
|
|
2640
2957
|
return false;
|
|
2641
2958
|
}
|
|
2642
2959
|
try {
|
|
2643
|
-
const current =
|
|
2960
|
+
const current = readFileSync4(envPath, "utf-8");
|
|
2644
2961
|
const stripped = current.split(/\r?\n/).filter((line) => !/^\s*(?:export\s+)?AGT_(?:HOST|API_KEY|CONSOLE_URL)=/.test(line)).join("\n");
|
|
2645
2962
|
const base = stripped.endsWith("\n") || stripped.length === 0 ? stripped : `${stripped}
|
|
2646
2963
|
`;
|
|
@@ -2659,7 +2976,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
|
2659
2976
|
}
|
|
2660
2977
|
function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
2661
2978
|
const profileD = "/etc/profile.d";
|
|
2662
|
-
if (!
|
|
2979
|
+
if (!existsSync4(profileD)) return false;
|
|
2663
2980
|
try {
|
|
2664
2981
|
accessSync(profileD, fsConstants.W_OK);
|
|
2665
2982
|
} catch {
|
|
@@ -2682,14 +2999,14 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
|
2682
2999
|
}
|
|
2683
3000
|
function ensureBashrcSourcesProfileD() {
|
|
2684
3001
|
const bashrc = "/etc/bashrc";
|
|
2685
|
-
if (!
|
|
3002
|
+
if (!existsSync4(bashrc)) return false;
|
|
2686
3003
|
try {
|
|
2687
3004
|
accessSync(bashrc, fsConstants.W_OK);
|
|
2688
3005
|
} catch {
|
|
2689
3006
|
return false;
|
|
2690
3007
|
}
|
|
2691
3008
|
try {
|
|
2692
|
-
const current =
|
|
3009
|
+
const current = readFileSync4(bashrc, "utf-8");
|
|
2693
3010
|
const marker = "# Augmented (agt) \u2014 source system-wide AGT env";
|
|
2694
3011
|
if (current.includes(marker)) return true;
|
|
2695
3012
|
const snippet = [
|
|
@@ -2816,11 +3133,11 @@ async function setupCommand(token) {
|
|
|
2816
3133
|
}
|
|
2817
3134
|
const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key, consoleUrl);
|
|
2818
3135
|
const profileDir = dirname(profilePath);
|
|
2819
|
-
if (!
|
|
3136
|
+
if (!existsSync4(profileDir)) {
|
|
2820
3137
|
mkdirSync4(profileDir, { recursive: true });
|
|
2821
3138
|
}
|
|
2822
3139
|
const marker = "# Augmented (agt) host configuration";
|
|
2823
|
-
const current =
|
|
3140
|
+
const current = existsSync4(profilePath) ? readFileSync4(profilePath, "utf-8") : "";
|
|
2824
3141
|
let updated;
|
|
2825
3142
|
if (current.includes(marker)) {
|
|
2826
3143
|
updated = current.replace(
|
|
@@ -2851,7 +3168,7 @@ async function setupCommand(token) {
|
|
|
2851
3168
|
const managerSpinner = ora13({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
2852
3169
|
managerSpinner.start();
|
|
2853
3170
|
try {
|
|
2854
|
-
const configDir =
|
|
3171
|
+
const configDir = join9(homedir2(), ".augmented");
|
|
2855
3172
|
const { pid } = startWatchdog({ intervalMs: 1e4, configDir, detached: true });
|
|
2856
3173
|
managerSpinner.succeed(`Manager started (PID ${pid})`);
|
|
2857
3174
|
} catch (err) {
|
|
@@ -3399,10 +3716,10 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
3399
3716
|
|
|
3400
3717
|
// src/commands/update.ts
|
|
3401
3718
|
import { execFileSync, execSync } from "child_process";
|
|
3402
|
-
import { existsSync as
|
|
3719
|
+
import { existsSync as existsSync5, realpathSync } from "fs";
|
|
3403
3720
|
import chalk17 from "chalk";
|
|
3404
3721
|
import ora15 from "ora";
|
|
3405
|
-
var cliVersion = true ? "0.15.
|
|
3722
|
+
var cliVersion = true ? "0.15.6" : "dev";
|
|
3406
3723
|
async function fetchLatestVersion() {
|
|
3407
3724
|
const host2 = getHost();
|
|
3408
3725
|
if (!host2) return null;
|
|
@@ -3497,7 +3814,7 @@ function performUpdate(version) {
|
|
|
3497
3814
|
function detectBrewOwner() {
|
|
3498
3815
|
for (const prefix of ["/home/linuxbrew/.linuxbrew", "/opt/homebrew", "/usr/local"]) {
|
|
3499
3816
|
const cellar = `${prefix}/Cellar`;
|
|
3500
|
-
if (!
|
|
3817
|
+
if (!existsSync5(cellar)) continue;
|
|
3501
3818
|
try {
|
|
3502
3819
|
return execSync(`stat -c %U "${cellar}" 2>/dev/null || stat -f %Su "${cellar}"`, { encoding: "utf-8" }).trim() || null;
|
|
3503
3820
|
} catch {
|
|
@@ -3851,7 +4168,7 @@ function handleError(err) {
|
|
|
3851
4168
|
}
|
|
3852
4169
|
|
|
3853
4170
|
// src/bin/agt.ts
|
|
3854
|
-
var cliVersion2 = true ? "0.15.
|
|
4171
|
+
var cliVersion2 = true ? "0.15.6" : "dev";
|
|
3855
4172
|
var program = new Command();
|
|
3856
4173
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
3857
4174
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -3898,11 +4215,12 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
|
|
|
3898
4215
|
})
|
|
3899
4216
|
);
|
|
3900
4217
|
var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
|
|
3901
|
-
manager.command("start").description("Start the manager daemon (polls API for config changes and detects local drift)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files",
|
|
3902
|
-
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files",
|
|
3903
|
-
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files",
|
|
4218
|
+
manager.command("start").description("Start the manager daemon (polls API for config changes and detects local drift)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join10(homedir3(), ".augmented")).option("--supervise", "Wrap the manager in a respawn-on-clean-exit loop so auto-upgrades can restart it transparently (ENG-4488)", false).action(managerStartCommand);
|
|
4219
|
+
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join10(homedir3(), ".augmented")).action(managerStopCommand);
|
|
4220
|
+
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join10(homedir3(), ".augmented")).action(managerStatusCommand);
|
|
4221
|
+
manager.command("watch").description("Live TUI dashboard \u2014 per-agent boxes, drill-in, log tail. Read-only (ENG-4555).").option("--config-dir <dir>", "Config directory for agent files", join10(homedir3(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
|
|
3904
4222
|
var agent = program.command("agent").description("Inspect and manage agents");
|
|
3905
|
-
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory",
|
|
4223
|
+
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join10(homedir3(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
|
|
3906
4224
|
var kanban = program.command("kanban").description("Manage agent kanban boards");
|
|
3907
4225
|
kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
|
|
3908
4226
|
kanban.command("add <title>").description("Add a new item to an agent kanban board").requiredOption("--agent <code-name>", "Agent code name").option("--priority <1|2|3>", "Priority: 1=high, 2=medium, 3=low", "2").option("--status <status>", "Initial status: backlog | today | in_progress", "today").option("--description <text>", "Item description").option("--estimate <minutes>", "Estimated time in minutes").option("--deliverable <text>", "Expected output/deliverable").action(kanbanAddCommand);
|