@integrity-labs/agt-cli 0.15.4 → 0.15.7
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 +381 -52
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-IEVDKEIT.js → chunk-S3SFU5IM.js} +1 -1
- package/dist/{chunk-IEVDKEIT.js.map → chunk-S3SFU5IM.js.map} +1 -1
- package/dist/{chunk-WDF7NJ2F.js → chunk-WIW5FIRY.js} +2 -1
- package/dist/{chunk-WDF7NJ2F.js.map → chunk-WIW5FIRY.js.map} +1 -1
- package/dist/lib/manager-worker.js +100 -34
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-ALP5DGFI.js → persistent-session-Q4X2KRS6.js} +2 -2
- package/package.json +4 -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-WIW5FIRY.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,344 @@ 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
|
+
process.stdout.write("\x1B[?1049h\x1B[H\x1B[?25l");
|
|
2206
|
+
const restore = () => {
|
|
2207
|
+
process.stdout.write("\x1B[?25h\x1B[?1049l");
|
|
2208
|
+
};
|
|
2209
|
+
const onSignal = () => {
|
|
2210
|
+
restore();
|
|
2211
|
+
process.exit(0);
|
|
2212
|
+
};
|
|
2213
|
+
process.once("SIGINT", onSignal);
|
|
2214
|
+
process.once("SIGTERM", onSignal);
|
|
2215
|
+
process.once("exit", restore);
|
|
2216
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx(Dashboard, { stateFile: paths.stateFile, logFile: paths.logFile }));
|
|
2217
|
+
waitUntilExit().catch(() => {
|
|
2218
|
+
}).finally(restore);
|
|
2219
|
+
}
|
|
2220
|
+
function readState(stateFile) {
|
|
2221
|
+
try {
|
|
2222
|
+
if (!existsSync2(stateFile)) return null;
|
|
2223
|
+
const raw = readFileSync2(stateFile, "utf-8");
|
|
2224
|
+
return JSON.parse(raw);
|
|
2225
|
+
} catch {
|
|
2226
|
+
return null;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
function tailLogFile(logFile, lines) {
|
|
2230
|
+
if (!existsSync2(logFile)) return [];
|
|
2231
|
+
try {
|
|
2232
|
+
const fileSize = statSync(logFile).size;
|
|
2233
|
+
if (fileSize === 0) return [];
|
|
2234
|
+
const readSize = Math.min(fileSize, lines * 800);
|
|
2235
|
+
const fd = openSync(logFile, "r");
|
|
2236
|
+
try {
|
|
2237
|
+
const buf = Buffer.alloc(readSize);
|
|
2238
|
+
readSync(fd, buf, 0, readSize, fileSize - readSize);
|
|
2239
|
+
const text = buf.toString("utf-8");
|
|
2240
|
+
const all = text.split("\n").filter((l) => l.length > 0);
|
|
2241
|
+
return all.slice(-lines);
|
|
2242
|
+
} finally {
|
|
2243
|
+
closeSync(fd);
|
|
2244
|
+
}
|
|
2245
|
+
} catch {
|
|
2246
|
+
return [];
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
var Dashboard = ({ stateFile, logFile }) => {
|
|
2250
|
+
const { exit } = useApp();
|
|
2251
|
+
const [status, setStatus] = useState(() => readState(stateFile));
|
|
2252
|
+
const [logLines, setLogLines] = useState(() => tailLogFile(logFile, LOG_TAIL_LINES));
|
|
2253
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
2254
|
+
const [view, setView] = useState("grid");
|
|
2255
|
+
const [tick, setTick] = useState(0);
|
|
2256
|
+
useEffect(() => {
|
|
2257
|
+
const id = setInterval(() => {
|
|
2258
|
+
setStatus(readState(stateFile));
|
|
2259
|
+
setLogLines(tailLogFile(logFile, LOG_TAIL_LINES));
|
|
2260
|
+
setTick((t) => t + 1);
|
|
2261
|
+
}, REFRESH_MS);
|
|
2262
|
+
return () => clearInterval(id);
|
|
2263
|
+
}, [stateFile, logFile]);
|
|
2264
|
+
const agents = status?.agents ?? [];
|
|
2265
|
+
const selected = agents[selectedIndex];
|
|
2266
|
+
useInput((input4, key) => {
|
|
2267
|
+
if (view === "detail") {
|
|
2268
|
+
if (key.escape || input4 === "q") setView("grid");
|
|
2269
|
+
else if (key.ctrl && input4 === "c") exit();
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2272
|
+
if (input4 === "q" || key.ctrl && input4 === "c") {
|
|
2273
|
+
exit();
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
if (agents.length === 0) return;
|
|
2277
|
+
if (key.upArrow || key.leftArrow) {
|
|
2278
|
+
setSelectedIndex((i) => (i - 1 + agents.length) % agents.length);
|
|
2279
|
+
} else if (key.downArrow || key.rightArrow) {
|
|
2280
|
+
setSelectedIndex((i) => (i + 1) % agents.length);
|
|
2281
|
+
} else if (key.return) {
|
|
2282
|
+
setView("detail");
|
|
2283
|
+
}
|
|
2284
|
+
});
|
|
2285
|
+
if (!status) {
|
|
2286
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
|
|
2287
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "\u26A0 Manager state not found" }),
|
|
2288
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2289
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2290
|
+
"Looked for: ",
|
|
2291
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: stateFile })
|
|
2292
|
+
] }),
|
|
2293
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2294
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2295
|
+
"Start the manager first: ",
|
|
2296
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "agt manager start" })
|
|
2297
|
+
] }),
|
|
2298
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2299
|
+
"Press ",
|
|
2300
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: "q" }),
|
|
2301
|
+
" to quit."
|
|
2302
|
+
] })
|
|
2303
|
+
] });
|
|
2304
|
+
}
|
|
2305
|
+
if (view === "detail" && selected) {
|
|
2306
|
+
return /* @__PURE__ */ jsx(DetailView, { agent: selected, logLines });
|
|
2307
|
+
}
|
|
2308
|
+
return /* @__PURE__ */ jsx(GridView, { status, agents, selectedIndex, logLines, tick });
|
|
2309
|
+
};
|
|
2310
|
+
var GridView = ({ status, agents, selectedIndex, logLines, tick }) => {
|
|
2311
|
+
const lastLogLine = logLines[logLines.length - 1] ?? "";
|
|
2312
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2313
|
+
/* @__PURE__ */ jsx(HeaderBar, { status, tick }),
|
|
2314
|
+
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(
|
|
2315
|
+
AgentBox,
|
|
2316
|
+
{
|
|
2317
|
+
agent: agent2,
|
|
2318
|
+
selected: i === selectedIndex,
|
|
2319
|
+
recentLogLine: mostRecentLineForAgent(logLines, agent2.codeName)
|
|
2320
|
+
},
|
|
2321
|
+
agent2.agentId
|
|
2322
|
+
)) }),
|
|
2323
|
+
/* @__PURE__ */ jsx(Footer, { tail: lastLogLine })
|
|
2324
|
+
] });
|
|
2325
|
+
};
|
|
2326
|
+
var HeaderBar = ({ status, tick }) => {
|
|
2327
|
+
void tick;
|
|
2328
|
+
return /* @__PURE__ */ jsx(Box, { paddingX: 1, paddingY: 0, borderStyle: "single", borderColor: "cyan", children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
|
|
2329
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
2330
|
+
"agt manager \xB7 ",
|
|
2331
|
+
status.agents.length,
|
|
2332
|
+
" agent",
|
|
2333
|
+
status.agents.length === 1 ? "" : "s"
|
|
2334
|
+
] }),
|
|
2335
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2336
|
+
"PID ",
|
|
2337
|
+
status.pid,
|
|
2338
|
+
" \xB7 polls ",
|
|
2339
|
+
status.pollCount,
|
|
2340
|
+
" \xB7 errors ",
|
|
2341
|
+
status.errorCount,
|
|
2342
|
+
" \xB7 last poll ",
|
|
2343
|
+
relativeTime(status.lastPollAt)
|
|
2344
|
+
] })
|
|
2345
|
+
] }) });
|
|
2346
|
+
};
|
|
2347
|
+
var Footer = ({ tail }) => /* @__PURE__ */ jsxs(Box, { paddingX: 1, flexDirection: "column", children: [
|
|
2348
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2349
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2191\u2193 select \xB7 " }),
|
|
2350
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Enter detail \xB7 " }),
|
|
2351
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "q quit" })
|
|
2352
|
+
] }),
|
|
2353
|
+
tail && /* @__PURE__ */ jsxs(Box, { children: [
|
|
2354
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "last log: " }),
|
|
2355
|
+
/* @__PURE__ */ jsx(Text, { children: truncate(tail, process.stdout.columns ? process.stdout.columns - 12 : 100) })
|
|
2356
|
+
] })
|
|
2357
|
+
] });
|
|
2358
|
+
var AgentBox = ({ agent: agent2, selected, recentLogLine }) => {
|
|
2359
|
+
const isError = agent2.status !== "active" && agent2.status !== "paused" && agent2.status !== "";
|
|
2360
|
+
const borderColor = selected ? "yellow" : isError ? "red" : "gray";
|
|
2361
|
+
const statusColor = agent2.status === "active" ? "green" : agent2.status === "paused" ? "yellow" : isError ? "red" : "gray";
|
|
2362
|
+
const gateway = agent2.gatewayRunning ? `:${agent2.gatewayPort} (PID ${agent2.gatewayPid})` : agent2.gatewayPort ? `:${agent2.gatewayPort} down` : "\u2014";
|
|
2363
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor, paddingX: 1, marginRight: 1, marginBottom: 0, width: 42, children: [
|
|
2364
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
2365
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: agent2.codeName }),
|
|
2366
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2367
|
+
/* @__PURE__ */ jsx(Text, { color: statusColor, children: agent2.status || "unknown" })
|
|
2368
|
+
] }),
|
|
2369
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2370
|
+
"charter ",
|
|
2371
|
+
agent2.charterVersion || "\u2014",
|
|
2372
|
+
" \xB7 tools ",
|
|
2373
|
+
agent2.toolsVersion || "\u2014"
|
|
2374
|
+
] }),
|
|
2375
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2376
|
+
"gateway ",
|
|
2377
|
+
gateway
|
|
2378
|
+
] }),
|
|
2379
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2380
|
+
"acp sessions ",
|
|
2381
|
+
agent2.acpSessions?.length ?? 0
|
|
2382
|
+
] }),
|
|
2383
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2384
|
+
"last provision ",
|
|
2385
|
+
relativeTime(agent2.lastProvisionAt)
|
|
2386
|
+
] }),
|
|
2387
|
+
recentLogLine && /* @__PURE__ */ jsxs(Text, { children: [
|
|
2388
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u25B8" }),
|
|
2389
|
+
" ",
|
|
2390
|
+
truncate(recentLogLine, 36)
|
|
2391
|
+
] })
|
|
2392
|
+
] });
|
|
2393
|
+
};
|
|
2394
|
+
var DetailView = ({ agent: agent2, logLines }) => {
|
|
2395
|
+
const recent = useMemo(
|
|
2396
|
+
() => logLines.filter((l) => l.toLowerCase().includes(agent2.codeName.toLowerCase())).slice(-DETAIL_RECENT_LINES),
|
|
2397
|
+
[logLines, agent2.codeName]
|
|
2398
|
+
);
|
|
2399
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2400
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, borderStyle: "double", borderColor: "cyan", children: [
|
|
2401
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: agent2.codeName }),
|
|
2402
|
+
/* @__PURE__ */ jsx(Text, { children: " \xB7 " }),
|
|
2403
|
+
/* @__PURE__ */ jsx(Text, { children: agent2.status || "unknown" }),
|
|
2404
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2405
|
+
" \xB7 charter ",
|
|
2406
|
+
agent2.charterVersion || "\u2014",
|
|
2407
|
+
" \xB7 tools ",
|
|
2408
|
+
agent2.toolsVersion || "\u2014"
|
|
2409
|
+
] })
|
|
2410
|
+
] }),
|
|
2411
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, marginTop: 1, flexDirection: "column", children: [
|
|
2412
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "Gateway" }),
|
|
2413
|
+
/* @__PURE__ */ jsx(Text, { children: agent2.gatewayRunning ? `running on :${agent2.gatewayPort} (PID ${agent2.gatewayPid})` : agent2.gatewayPort ? `configured :${agent2.gatewayPort} but not running` : "no gateway configured" })
|
|
2414
|
+
] }),
|
|
2415
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, marginTop: 1, flexDirection: "column", children: [
|
|
2416
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
2417
|
+
"ACP sessions (",
|
|
2418
|
+
agent2.acpSessions?.length ?? 0,
|
|
2419
|
+
")"
|
|
2420
|
+
] }),
|
|
2421
|
+
(agent2.acpSessions ?? []).length === 0 ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: "none" }) : (agent2.acpSessions ?? []).map((s) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
2422
|
+
"\xB7 ",
|
|
2423
|
+
s.agentCommand,
|
|
2424
|
+
" ",
|
|
2425
|
+
s.sessionName ?? "",
|
|
2426
|
+
" \xB7 ",
|
|
2427
|
+
s.queueState,
|
|
2428
|
+
" \xB7 turns ",
|
|
2429
|
+
s.turnCount,
|
|
2430
|
+
" \xB7 started ",
|
|
2431
|
+
relativeTime(s.startedAt)
|
|
2432
|
+
] }, s.sessionId))
|
|
2433
|
+
] }),
|
|
2434
|
+
/* @__PURE__ */ jsxs(Box, { paddingX: 1, marginTop: 1, flexDirection: "column", children: [
|
|
2435
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
2436
|
+
"Recent activity (",
|
|
2437
|
+
recent.length,
|
|
2438
|
+
' lines, filtered to "',
|
|
2439
|
+
agent2.codeName,
|
|
2440
|
+
'")'
|
|
2441
|
+
] }),
|
|
2442
|
+
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))
|
|
2443
|
+
] }),
|
|
2444
|
+
/* @__PURE__ */ jsx(Box, { paddingX: 1, marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "esc / q \xB7 back to grid" }) })
|
|
2445
|
+
] });
|
|
2446
|
+
};
|
|
2447
|
+
function mostRecentLineForAgent(lines, codeName) {
|
|
2448
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2449
|
+
const line = lines[i];
|
|
2450
|
+
if (line && line.toLowerCase().includes(codeName.toLowerCase())) return line;
|
|
2451
|
+
}
|
|
2452
|
+
return null;
|
|
2453
|
+
}
|
|
2454
|
+
function relativeTime(iso) {
|
|
2455
|
+
if (!iso) return "never";
|
|
2456
|
+
const t = new Date(iso).getTime();
|
|
2457
|
+
if (isNaN(t)) return "never";
|
|
2458
|
+
const diff = Math.max(0, Date.now() - t);
|
|
2459
|
+
const sec = Math.floor(diff / 1e3);
|
|
2460
|
+
if (sec < 60) return `${sec}s ago`;
|
|
2461
|
+
const min = Math.floor(sec / 60);
|
|
2462
|
+
if (min < 60) return `${min}m ago`;
|
|
2463
|
+
const hr = Math.floor(min / 60);
|
|
2464
|
+
if (hr < 24) return `${hr}h ago`;
|
|
2465
|
+
return `${Math.floor(hr / 24)}d ago`;
|
|
2466
|
+
}
|
|
2467
|
+
function truncate(s, max) {
|
|
2468
|
+
return s.length > max ? `${s.slice(0, Math.max(0, max - 1))}\u2026` : s;
|
|
2469
|
+
}
|
|
2470
|
+
function streamLogFile(logFile) {
|
|
2471
|
+
if (!existsSync2(logFile)) {
|
|
2472
|
+
process.stderr.write(`No manager log found at ${logFile}.
|
|
2473
|
+
Start the manager first: agt manager start
|
|
2474
|
+
`);
|
|
2475
|
+
process.exitCode = 1;
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
let lastSize = 0;
|
|
2479
|
+
try {
|
|
2480
|
+
const initial = readFileSync2(logFile, "utf-8");
|
|
2481
|
+
process.stdout.write(initial);
|
|
2482
|
+
lastSize = statSync(logFile).size;
|
|
2483
|
+
} catch (err) {
|
|
2484
|
+
process.stderr.write(`Failed to read log: ${err.message}
|
|
2485
|
+
`);
|
|
2486
|
+
process.exitCode = 1;
|
|
2487
|
+
return;
|
|
2488
|
+
}
|
|
2489
|
+
const id = setInterval(() => {
|
|
2490
|
+
try {
|
|
2491
|
+
const size = statSync(logFile).size;
|
|
2492
|
+
if (size < lastSize) lastSize = 0;
|
|
2493
|
+
if (size === lastSize) return;
|
|
2494
|
+
const fd = openSync(logFile, "r");
|
|
2495
|
+
try {
|
|
2496
|
+
const buf = Buffer.alloc(size - lastSize);
|
|
2497
|
+
readSync(fd, buf, 0, buf.length, lastSize);
|
|
2498
|
+
process.stdout.write(buf.toString("utf-8"));
|
|
2499
|
+
lastSize = size;
|
|
2500
|
+
} finally {
|
|
2501
|
+
closeSync(fd);
|
|
2502
|
+
}
|
|
2503
|
+
} catch {
|
|
2504
|
+
}
|
|
2505
|
+
}, 500);
|
|
2506
|
+
const stop = () => {
|
|
2507
|
+
clearInterval(id);
|
|
2508
|
+
process.exit(0);
|
|
2509
|
+
};
|
|
2510
|
+
process.on("SIGINT", stop);
|
|
2511
|
+
process.on("SIGTERM", stop);
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2186
2514
|
// src/commands/agent.ts
|
|
2187
2515
|
import chalk13 from "chalk";
|
|
2188
2516
|
import JSON52 from "json5";
|
|
2189
|
-
import { readFileSync as
|
|
2190
|
-
import { join as
|
|
2517
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
|
|
2518
|
+
import { join as join8 } from "path";
|
|
2191
2519
|
async function agentShowCommand(codeName, opts) {
|
|
2192
2520
|
const json = isJsonMode();
|
|
2193
|
-
const unifiedDir =
|
|
2194
|
-
const legacyDir =
|
|
2195
|
-
const agentDir =
|
|
2196
|
-
const hasLocalConfig =
|
|
2521
|
+
const unifiedDir = join8(opts.configDir, codeName, "provision");
|
|
2522
|
+
const legacyDir = join8(opts.configDir, codeName, "claudecode", "provision");
|
|
2523
|
+
const agentDir = existsSync3(unifiedDir) ? unifiedDir : legacyDir;
|
|
2524
|
+
const hasLocalConfig = existsSync3(agentDir);
|
|
2197
2525
|
let apiChannels = null;
|
|
2198
2526
|
let apiAgent = null;
|
|
2199
2527
|
if (getApiKey()) {
|
|
@@ -2226,34 +2554,34 @@ async function agentShowCommand(codeName, opts) {
|
|
|
2226
2554
|
let openclawConfig = null;
|
|
2227
2555
|
let agentState = null;
|
|
2228
2556
|
if (hasLocalConfig) {
|
|
2229
|
-
const charterPath =
|
|
2230
|
-
if (
|
|
2231
|
-
const raw =
|
|
2557
|
+
const charterPath = join8(agentDir, "CHARTER.md");
|
|
2558
|
+
if (existsSync3(charterPath)) {
|
|
2559
|
+
const raw = readFileSync3(charterPath, "utf-8");
|
|
2232
2560
|
const parsed = extractFrontmatter(raw);
|
|
2233
2561
|
if (parsed.frontmatter) {
|
|
2234
2562
|
charter = parsed.frontmatter;
|
|
2235
2563
|
}
|
|
2236
2564
|
}
|
|
2237
|
-
const toolsPath =
|
|
2238
|
-
if (
|
|
2239
|
-
const raw =
|
|
2565
|
+
const toolsPath = join8(agentDir, "TOOLS.md");
|
|
2566
|
+
if (existsSync3(toolsPath)) {
|
|
2567
|
+
const raw = readFileSync3(toolsPath, "utf-8");
|
|
2240
2568
|
const parsed = extractFrontmatter(raw);
|
|
2241
2569
|
if (parsed.frontmatter) {
|
|
2242
2570
|
tools = parsed.frontmatter;
|
|
2243
2571
|
}
|
|
2244
2572
|
}
|
|
2245
|
-
const openclawPath =
|
|
2246
|
-
if (
|
|
2573
|
+
const openclawPath = join8(agentDir, "openclaw.json5");
|
|
2574
|
+
if (existsSync3(openclawPath)) {
|
|
2247
2575
|
try {
|
|
2248
|
-
const raw =
|
|
2576
|
+
const raw = readFileSync3(openclawPath, "utf-8");
|
|
2249
2577
|
openclawConfig = JSON52.parse(raw);
|
|
2250
2578
|
} catch {
|
|
2251
2579
|
}
|
|
2252
2580
|
}
|
|
2253
|
-
const statePath =
|
|
2254
|
-
if (
|
|
2581
|
+
const statePath = join8(opts.configDir, "manager-state.json");
|
|
2582
|
+
if (existsSync3(statePath)) {
|
|
2255
2583
|
try {
|
|
2256
|
-
const raw =
|
|
2584
|
+
const raw = readFileSync3(statePath, "utf-8");
|
|
2257
2585
|
const state = JSON.parse(raw);
|
|
2258
2586
|
agentState = state.agents?.find((a) => a.codeName === codeName) ?? null;
|
|
2259
2587
|
} catch {
|
|
@@ -2590,24 +2918,24 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
2590
2918
|
}
|
|
2591
2919
|
|
|
2592
2920
|
// src/commands/setup.ts
|
|
2593
|
-
import { existsSync as
|
|
2594
|
-
import { join as
|
|
2595
|
-
import { homedir } from "os";
|
|
2921
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, accessSync, constants as fsConstants } from "fs";
|
|
2922
|
+
import { join as join9, dirname } from "path";
|
|
2923
|
+
import { homedir as homedir2 } from "os";
|
|
2596
2924
|
import chalk15 from "chalk";
|
|
2597
2925
|
import ora13 from "ora";
|
|
2598
2926
|
function detectShellProfile() {
|
|
2599
2927
|
const shell = process.env["SHELL"] ?? "";
|
|
2600
|
-
const home =
|
|
2928
|
+
const home = homedir2();
|
|
2601
2929
|
if (shell.includes("zsh")) {
|
|
2602
|
-
return
|
|
2930
|
+
return join9(home, ".zshrc");
|
|
2603
2931
|
}
|
|
2604
2932
|
if (shell.includes("fish")) {
|
|
2605
|
-
const fishConfig =
|
|
2933
|
+
const fishConfig = join9(home, ".config", "fish", "config.fish");
|
|
2606
2934
|
return fishConfig;
|
|
2607
2935
|
}
|
|
2608
|
-
const bashrc =
|
|
2609
|
-
if (
|
|
2610
|
-
return
|
|
2936
|
+
const bashrc = join9(home, ".bashrc");
|
|
2937
|
+
if (existsSync4(bashrc)) return bashrc;
|
|
2938
|
+
return join9(home, ".bash_profile");
|
|
2611
2939
|
}
|
|
2612
2940
|
function maybeWriteSystemWideEnv(apiUrl, apiKey, consoleUrl) {
|
|
2613
2941
|
const empty = { etcEnvironment: false, profileD: false, bashrc: false };
|
|
@@ -2633,14 +2961,14 @@ function quoteForFishShell(value) {
|
|
|
2633
2961
|
}
|
|
2634
2962
|
function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
2635
2963
|
const envPath = "/etc/environment";
|
|
2636
|
-
if (!
|
|
2964
|
+
if (!existsSync4(envPath)) return false;
|
|
2637
2965
|
try {
|
|
2638
2966
|
accessSync(envPath, fsConstants.W_OK);
|
|
2639
2967
|
} catch {
|
|
2640
2968
|
return false;
|
|
2641
2969
|
}
|
|
2642
2970
|
try {
|
|
2643
|
-
const current =
|
|
2971
|
+
const current = readFileSync4(envPath, "utf-8");
|
|
2644
2972
|
const stripped = current.split(/\r?\n/).filter((line) => !/^\s*(?:export\s+)?AGT_(?:HOST|API_KEY|CONSOLE_URL)=/.test(line)).join("\n");
|
|
2645
2973
|
const base = stripped.endsWith("\n") || stripped.length === 0 ? stripped : `${stripped}
|
|
2646
2974
|
`;
|
|
@@ -2659,7 +2987,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
|
2659
2987
|
}
|
|
2660
2988
|
function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
2661
2989
|
const profileD = "/etc/profile.d";
|
|
2662
|
-
if (!
|
|
2990
|
+
if (!existsSync4(profileD)) return false;
|
|
2663
2991
|
try {
|
|
2664
2992
|
accessSync(profileD, fsConstants.W_OK);
|
|
2665
2993
|
} catch {
|
|
@@ -2682,14 +3010,14 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
|
2682
3010
|
}
|
|
2683
3011
|
function ensureBashrcSourcesProfileD() {
|
|
2684
3012
|
const bashrc = "/etc/bashrc";
|
|
2685
|
-
if (!
|
|
3013
|
+
if (!existsSync4(bashrc)) return false;
|
|
2686
3014
|
try {
|
|
2687
3015
|
accessSync(bashrc, fsConstants.W_OK);
|
|
2688
3016
|
} catch {
|
|
2689
3017
|
return false;
|
|
2690
3018
|
}
|
|
2691
3019
|
try {
|
|
2692
|
-
const current =
|
|
3020
|
+
const current = readFileSync4(bashrc, "utf-8");
|
|
2693
3021
|
const marker = "# Augmented (agt) \u2014 source system-wide AGT env";
|
|
2694
3022
|
if (current.includes(marker)) return true;
|
|
2695
3023
|
const snippet = [
|
|
@@ -2816,11 +3144,11 @@ async function setupCommand(token) {
|
|
|
2816
3144
|
}
|
|
2817
3145
|
const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key, consoleUrl);
|
|
2818
3146
|
const profileDir = dirname(profilePath);
|
|
2819
|
-
if (!
|
|
3147
|
+
if (!existsSync4(profileDir)) {
|
|
2820
3148
|
mkdirSync4(profileDir, { recursive: true });
|
|
2821
3149
|
}
|
|
2822
3150
|
const marker = "# Augmented (agt) host configuration";
|
|
2823
|
-
const current =
|
|
3151
|
+
const current = existsSync4(profilePath) ? readFileSync4(profilePath, "utf-8") : "";
|
|
2824
3152
|
let updated;
|
|
2825
3153
|
if (current.includes(marker)) {
|
|
2826
3154
|
updated = current.replace(
|
|
@@ -2851,7 +3179,7 @@ async function setupCommand(token) {
|
|
|
2851
3179
|
const managerSpinner = ora13({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
2852
3180
|
managerSpinner.start();
|
|
2853
3181
|
try {
|
|
2854
|
-
const configDir =
|
|
3182
|
+
const configDir = join9(homedir2(), ".augmented");
|
|
2855
3183
|
const { pid } = startWatchdog({ intervalMs: 1e4, configDir, detached: true });
|
|
2856
3184
|
managerSpinner.succeed(`Manager started (PID ${pid})`);
|
|
2857
3185
|
} catch (err) {
|
|
@@ -2905,7 +3233,7 @@ function priorityLabel2(p) {
|
|
|
2905
3233
|
function statusLabel(s) {
|
|
2906
3234
|
const map = {
|
|
2907
3235
|
in_progress: chalk16.blue("In Progress"),
|
|
2908
|
-
|
|
3236
|
+
todo: chalk16.green("To Do"),
|
|
2909
3237
|
backlog: chalk16.dim("Backlog"),
|
|
2910
3238
|
done: chalk16.gray("Done")
|
|
2911
3239
|
};
|
|
@@ -2975,7 +3303,7 @@ async function kanbanAddCommand(title, opts) {
|
|
|
2975
3303
|
title,
|
|
2976
3304
|
description: opts.description,
|
|
2977
3305
|
priority: opts.priority ? Number(opts.priority) : 2,
|
|
2978
|
-
status: opts.status ?? "
|
|
3306
|
+
status: opts.status ?? "todo",
|
|
2979
3307
|
estimated_minutes: opts.estimate ? Number(opts.estimate) : void 0,
|
|
2980
3308
|
deliverable: opts.deliverable,
|
|
2981
3309
|
source: "manual"
|
|
@@ -3000,7 +3328,7 @@ async function kanbanMoveCommand(titleOrId, status, opts) {
|
|
|
3000
3328
|
const teamSlug = requireTeam();
|
|
3001
3329
|
if (!teamSlug) return;
|
|
3002
3330
|
const json = isJsonMode();
|
|
3003
|
-
const validStatuses = ["backlog", "
|
|
3331
|
+
const validStatuses = ["backlog", "todo", "in_progress", "done"];
|
|
3004
3332
|
if (!validStatuses.includes(status)) {
|
|
3005
3333
|
error(`Invalid status "${status}". Must be one of: ${validStatuses.join(", ")}`);
|
|
3006
3334
|
process.exitCode = 1;
|
|
@@ -3399,10 +3727,10 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
3399
3727
|
|
|
3400
3728
|
// src/commands/update.ts
|
|
3401
3729
|
import { execFileSync, execSync } from "child_process";
|
|
3402
|
-
import { existsSync as
|
|
3730
|
+
import { existsSync as existsSync5, realpathSync } from "fs";
|
|
3403
3731
|
import chalk17 from "chalk";
|
|
3404
3732
|
import ora15 from "ora";
|
|
3405
|
-
var cliVersion = true ? "0.15.
|
|
3733
|
+
var cliVersion = true ? "0.15.7" : "dev";
|
|
3406
3734
|
async function fetchLatestVersion() {
|
|
3407
3735
|
const host2 = getHost();
|
|
3408
3736
|
if (!host2) return null;
|
|
@@ -3497,7 +3825,7 @@ function performUpdate(version) {
|
|
|
3497
3825
|
function detectBrewOwner() {
|
|
3498
3826
|
for (const prefix of ["/home/linuxbrew/.linuxbrew", "/opt/homebrew", "/usr/local"]) {
|
|
3499
3827
|
const cellar = `${prefix}/Cellar`;
|
|
3500
|
-
if (!
|
|
3828
|
+
if (!existsSync5(cellar)) continue;
|
|
3501
3829
|
try {
|
|
3502
3830
|
return execSync(`stat -c %U "${cellar}" 2>/dev/null || stat -f %Su "${cellar}"`, { encoding: "utf-8" }).trim() || null;
|
|
3503
3831
|
} catch {
|
|
@@ -3851,7 +4179,7 @@ function handleError(err) {
|
|
|
3851
4179
|
}
|
|
3852
4180
|
|
|
3853
4181
|
// src/bin/agt.ts
|
|
3854
|
-
var cliVersion2 = true ? "0.15.
|
|
4182
|
+
var cliVersion2 = true ? "0.15.7" : "dev";
|
|
3855
4183
|
var program = new Command();
|
|
3856
4184
|
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
4185
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -3898,14 +4226,15 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
|
|
|
3898
4226
|
})
|
|
3899
4227
|
);
|
|
3900
4228
|
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",
|
|
4229
|
+
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);
|
|
4230
|
+
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join10(homedir3(), ".augmented")).action(managerStopCommand);
|
|
4231
|
+
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);
|
|
4232
|
+
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
4233
|
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",
|
|
4234
|
+
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
4235
|
var kanban = program.command("kanban").description("Manage agent kanban boards");
|
|
3907
4236
|
kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
|
|
3908
|
-
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 |
|
|
4237
|
+
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 | todo | in_progress", "todo").option("--description <text>", "Item description").option("--estimate <minutes>", "Estimated time in minutes").option("--deliverable <text>", "Expected output/deliverable").action(kanbanAddCommand);
|
|
3909
4238
|
kanban.command("move <title-or-id> <status>").description("Move a kanban item to a different status").requiredOption("--agent <code-name>", "Agent code name").option("--notes <text>", "Progress notes").action(kanbanMoveCommand);
|
|
3910
4239
|
kanban.command("update <title-or-id>").description("Update notes or result on a kanban item").requiredOption("--agent <code-name>", "Agent code name").option("--notes <text>", "Progress notes").option("--result <text>", "Result/output produced").action(kanbanUpdateCommand);
|
|
3911
4240
|
kanban.command("done <title-or-id>").description("Mark a kanban item as done").requiredOption("--agent <code-name>", "Agent code name").option("--result <text>", "What was produced/delivered").option("--notes <text>", "Completion notes").action(kanbanDoneCommand);
|