@integrity-labs/agt-cli 0.10.10 → 0.10.12
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 +130 -54
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-PZG4XPJV.js → chunk-KZ7Y55HJ.js} +4 -3
- package/dist/{chunk-PZG4XPJV.js.map → chunk-KZ7Y55HJ.js.map} +1 -1
- package/dist/lib/manager-worker.js +5 -3
- package/dist/lib/manager-worker.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/agt.js
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
resolveChannels,
|
|
33
33
|
serializeManifestForSlackCli,
|
|
34
34
|
setActiveTeam
|
|
35
|
-
} from "../chunk-
|
|
35
|
+
} from "../chunk-KZ7Y55HJ.js";
|
|
36
36
|
|
|
37
37
|
// src/bin/agt.ts
|
|
38
38
|
import { join as join11 } from "path";
|
|
@@ -2211,32 +2211,38 @@ import { join as join8 } from "path";
|
|
|
2211
2211
|
import { homedir } from "os";
|
|
2212
2212
|
|
|
2213
2213
|
// src/lib/watchdog.ts
|
|
2214
|
-
import { readFileSync as readFileSync2, writeFileSync as writeFileSync4, unlinkSync, existsSync as existsSync2, mkdirSync as mkdirSync4 } from "fs";
|
|
2214
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync4, unlinkSync, existsSync as existsSync2, mkdirSync as mkdirSync4, openSync, closeSync, chmodSync } from "fs";
|
|
2215
2215
|
import { join as join7 } from "path";
|
|
2216
|
-
|
|
2217
|
-
var
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2216
|
+
import { spawn as spawn2 } from "child_process";
|
|
2217
|
+
var DEFAULT_CONFIG_DIR = join7(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
2218
|
+
function getManagerPaths(configDir) {
|
|
2219
|
+
return {
|
|
2220
|
+
pidFile: join7(configDir, "manager.pid"),
|
|
2221
|
+
stateFile: join7(configDir, "manager-state.json"),
|
|
2222
|
+
logFile: join7(configDir, "manager.log")
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
function ensureDir(configDir) {
|
|
2226
|
+
if (!existsSync2(configDir)) {
|
|
2227
|
+
mkdirSync4(configDir, { recursive: true });
|
|
2222
2228
|
}
|
|
2223
2229
|
}
|
|
2224
|
-
function writePidFile(pid) {
|
|
2225
|
-
ensureDir();
|
|
2226
|
-
writeFileSync4(
|
|
2230
|
+
function writePidFile(configDir, pid) {
|
|
2231
|
+
ensureDir(configDir);
|
|
2232
|
+
writeFileSync4(getManagerPaths(configDir).pidFile, String(pid), { mode: 384 });
|
|
2227
2233
|
}
|
|
2228
|
-
function readPidFile() {
|
|
2234
|
+
function readPidFile(configDir) {
|
|
2229
2235
|
try {
|
|
2230
|
-
const raw = readFileSync2(
|
|
2236
|
+
const raw = readFileSync2(getManagerPaths(configDir).pidFile, "utf-8").trim();
|
|
2231
2237
|
const pid = parseInt(raw, 10);
|
|
2232
2238
|
return isNaN(pid) ? null : pid;
|
|
2233
2239
|
} catch {
|
|
2234
2240
|
return null;
|
|
2235
2241
|
}
|
|
2236
2242
|
}
|
|
2237
|
-
function removePidFile() {
|
|
2243
|
+
function removePidFile(configDir) {
|
|
2238
2244
|
try {
|
|
2239
|
-
unlinkSync(
|
|
2245
|
+
unlinkSync(getManagerPaths(configDir).pidFile);
|
|
2240
2246
|
} catch {
|
|
2241
2247
|
}
|
|
2242
2248
|
}
|
|
@@ -2248,49 +2254,91 @@ function isProcessAlive(pid) {
|
|
|
2248
2254
|
return false;
|
|
2249
2255
|
}
|
|
2250
2256
|
}
|
|
2251
|
-
function readStateFile() {
|
|
2257
|
+
function readStateFile(configDir) {
|
|
2252
2258
|
try {
|
|
2253
|
-
const raw = readFileSync2(
|
|
2259
|
+
const raw = readFileSync2(getManagerPaths(configDir).stateFile, "utf-8");
|
|
2254
2260
|
return JSON.parse(raw);
|
|
2255
2261
|
} catch {
|
|
2256
2262
|
return null;
|
|
2257
2263
|
}
|
|
2258
2264
|
}
|
|
2259
|
-
function removeStateFile() {
|
|
2265
|
+
function removeStateFile(configDir) {
|
|
2260
2266
|
try {
|
|
2261
|
-
unlinkSync(
|
|
2267
|
+
unlinkSync(getManagerPaths(configDir).stateFile);
|
|
2262
2268
|
} catch {
|
|
2263
2269
|
}
|
|
2264
2270
|
}
|
|
2265
2271
|
function startWatchdog(opts) {
|
|
2266
|
-
const
|
|
2272
|
+
const { configDir } = opts;
|
|
2273
|
+
const existingPid = readPidFile(configDir);
|
|
2267
2274
|
if (existingPid !== null) {
|
|
2268
2275
|
if (isProcessAlive(existingPid)) {
|
|
2269
2276
|
throw new Error(`Manager already running (PID ${existingPid}). Use \`agt manager stop\` first.`);
|
|
2270
2277
|
}
|
|
2271
|
-
removePidFile();
|
|
2272
|
-
removeStateFile();
|
|
2278
|
+
removePidFile(configDir);
|
|
2279
|
+
removeStateFile(configDir);
|
|
2280
|
+
}
|
|
2281
|
+
if (opts.detached) {
|
|
2282
|
+
ensureDir(configDir);
|
|
2283
|
+
const { logFile } = getManagerPaths(configDir);
|
|
2284
|
+
const logFd = openSync(logFile, "a", 384);
|
|
2285
|
+
try {
|
|
2286
|
+
chmodSync(logFile, 384);
|
|
2287
|
+
} catch {
|
|
2288
|
+
}
|
|
2289
|
+
const intervalSec = String(Math.max(Math.floor(opts.intervalMs / 1e3), 5));
|
|
2290
|
+
const child = spawn2(
|
|
2291
|
+
process.execPath,
|
|
2292
|
+
[process.argv[1], "manager", "start", "--interval", intervalSec, "--config-dir", configDir],
|
|
2293
|
+
{
|
|
2294
|
+
detached: true,
|
|
2295
|
+
stdio: ["ignore", logFd, logFd],
|
|
2296
|
+
env: process.env
|
|
2297
|
+
}
|
|
2298
|
+
);
|
|
2299
|
+
child.unref();
|
|
2300
|
+
closeSync(logFd);
|
|
2301
|
+
if (!child.pid) {
|
|
2302
|
+
throw new Error("Failed to spawn detached manager process");
|
|
2303
|
+
}
|
|
2304
|
+
const { pidFile } = getManagerPaths(configDir);
|
|
2305
|
+
const deadline = Date.now() + 5e3;
|
|
2306
|
+
const sleepBuf = new Int32Array(new SharedArrayBuffer(4));
|
|
2307
|
+
while (Date.now() < deadline) {
|
|
2308
|
+
if (existsSync2(pidFile)) {
|
|
2309
|
+
return { pid: child.pid };
|
|
2310
|
+
}
|
|
2311
|
+
if (child.exitCode !== null) {
|
|
2312
|
+
throw new Error(
|
|
2313
|
+
`Manager exited during startup (code ${child.exitCode}). See ${logFile} for details.`
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
Atomics.wait(sleepBuf, 0, 0, 100);
|
|
2317
|
+
}
|
|
2318
|
+
throw new Error(
|
|
2319
|
+
`Manager did not become ready within 5s. See ${logFile} for details.`
|
|
2320
|
+
);
|
|
2273
2321
|
}
|
|
2274
|
-
writePidFile(process.pid);
|
|
2322
|
+
writePidFile(configDir, process.pid);
|
|
2275
2323
|
void import("../lib/manager-worker.js").then(({ startManager }) => {
|
|
2276
2324
|
startManager({
|
|
2277
2325
|
intervalMs: opts.intervalMs,
|
|
2278
|
-
configDir
|
|
2326
|
+
configDir
|
|
2279
2327
|
});
|
|
2280
2328
|
});
|
|
2281
2329
|
process.on("exit", () => {
|
|
2282
|
-
removePidFile();
|
|
2330
|
+
removePidFile(configDir);
|
|
2283
2331
|
});
|
|
2284
2332
|
return { pid: process.pid };
|
|
2285
2333
|
}
|
|
2286
|
-
async function stopWatchdog() {
|
|
2287
|
-
const pid = readPidFile();
|
|
2334
|
+
async function stopWatchdog(configDir = DEFAULT_CONFIG_DIR) {
|
|
2335
|
+
const pid = readPidFile(configDir);
|
|
2288
2336
|
if (pid === null) {
|
|
2289
2337
|
return { stopped: false };
|
|
2290
2338
|
}
|
|
2291
2339
|
if (!isProcessAlive(pid)) {
|
|
2292
|
-
removePidFile();
|
|
2293
|
-
removeStateFile();
|
|
2340
|
+
removePidFile(configDir);
|
|
2341
|
+
removeStateFile(configDir);
|
|
2294
2342
|
return { stopped: true, pid };
|
|
2295
2343
|
}
|
|
2296
2344
|
process.kill(pid, "SIGTERM");
|
|
@@ -2298,7 +2346,7 @@ async function stopWatchdog() {
|
|
|
2298
2346
|
while (Date.now() < deadline) {
|
|
2299
2347
|
await new Promise((r) => setTimeout(r, 200));
|
|
2300
2348
|
if (!isProcessAlive(pid)) {
|
|
2301
|
-
removePidFile();
|
|
2349
|
+
removePidFile(configDir);
|
|
2302
2350
|
return { stopped: true, pid };
|
|
2303
2351
|
}
|
|
2304
2352
|
}
|
|
@@ -2306,19 +2354,19 @@ async function stopWatchdog() {
|
|
|
2306
2354
|
process.kill(pid, "SIGKILL");
|
|
2307
2355
|
} catch {
|
|
2308
2356
|
}
|
|
2309
|
-
removePidFile();
|
|
2310
|
-
removeStateFile();
|
|
2357
|
+
removePidFile(configDir);
|
|
2358
|
+
removeStateFile(configDir);
|
|
2311
2359
|
return { stopped: true, pid };
|
|
2312
2360
|
}
|
|
2313
|
-
function getManagerStatus() {
|
|
2314
|
-
const pid = readPidFile();
|
|
2361
|
+
function getManagerStatus(configDir = DEFAULT_CONFIG_DIR) {
|
|
2362
|
+
const pid = readPidFile(configDir);
|
|
2315
2363
|
if (pid === null) return null;
|
|
2316
2364
|
if (!isProcessAlive(pid)) {
|
|
2317
|
-
removePidFile();
|
|
2318
|
-
removeStateFile();
|
|
2365
|
+
removePidFile(configDir);
|
|
2366
|
+
removeStateFile(configDir);
|
|
2319
2367
|
return null;
|
|
2320
2368
|
}
|
|
2321
|
-
return readStateFile();
|
|
2369
|
+
return readStateFile(configDir);
|
|
2322
2370
|
}
|
|
2323
2371
|
|
|
2324
2372
|
// src/commands/manager.ts
|
|
@@ -2367,10 +2415,11 @@ function managerStartCommand(opts) {
|
|
|
2367
2415
|
process.exitCode = 1;
|
|
2368
2416
|
}
|
|
2369
2417
|
}
|
|
2370
|
-
async function managerStopCommand() {
|
|
2418
|
+
async function managerStopCommand(opts = {}) {
|
|
2371
2419
|
const json = isJsonMode();
|
|
2420
|
+
const configDir = opts.configDir ?? join8(homedir(), ".augmented");
|
|
2372
2421
|
try {
|
|
2373
|
-
const result = await stopWatchdog();
|
|
2422
|
+
const result = await stopWatchdog(configDir);
|
|
2374
2423
|
if (!result.stopped && !result.pid) {
|
|
2375
2424
|
if (json) {
|
|
2376
2425
|
jsonOutput({ ok: false, error: "Manager is not running" });
|
|
@@ -2394,9 +2443,10 @@ async function managerStopCommand() {
|
|
|
2394
2443
|
process.exitCode = 1;
|
|
2395
2444
|
}
|
|
2396
2445
|
}
|
|
2397
|
-
function managerStatusCommand() {
|
|
2446
|
+
function managerStatusCommand(opts = {}) {
|
|
2398
2447
|
const json = isJsonMode();
|
|
2399
|
-
const
|
|
2448
|
+
const configDir = opts.configDir ?? join8(homedir(), ".augmented");
|
|
2449
|
+
const status = getManagerStatus(configDir);
|
|
2400
2450
|
if (!status) {
|
|
2401
2451
|
if (json) {
|
|
2402
2452
|
jsonOutput({ ok: true, running: false });
|
|
@@ -2865,7 +2915,7 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
2865
2915
|
}
|
|
2866
2916
|
|
|
2867
2917
|
// src/commands/setup.ts
|
|
2868
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
2918
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, accessSync, constants as fsConstants } from "fs";
|
|
2869
2919
|
import { join as join10, dirname } from "path";
|
|
2870
2920
|
import { homedir as homedir2 } from "os";
|
|
2871
2921
|
import chalk18 from "chalk";
|
|
@@ -2884,6 +2934,30 @@ function detectShellProfile() {
|
|
|
2884
2934
|
if (existsSync4(bashrc)) return bashrc;
|
|
2885
2935
|
return join10(home, ".bash_profile");
|
|
2886
2936
|
}
|
|
2937
|
+
function maybeWriteEtcEnvironment(apiUrl, apiKey) {
|
|
2938
|
+
if (process.platform === "win32") return false;
|
|
2939
|
+
if (typeof process.getuid !== "function" || process.getuid() !== 0) return false;
|
|
2940
|
+
const envPath = "/etc/environment";
|
|
2941
|
+
if (!existsSync4(envPath)) return false;
|
|
2942
|
+
try {
|
|
2943
|
+
accessSync(envPath, fsConstants.W_OK);
|
|
2944
|
+
} catch {
|
|
2945
|
+
return false;
|
|
2946
|
+
}
|
|
2947
|
+
try {
|
|
2948
|
+
const current = readFileSync4(envPath, "utf-8");
|
|
2949
|
+
const stripped = current.split(/\r?\n/).filter((line) => !/^\s*(?:export\s+)?AGT_(?:HOST|API_KEY)=/.test(line)).join("\n");
|
|
2950
|
+
const base = stripped.endsWith("\n") || stripped.length === 0 ? stripped : `${stripped}
|
|
2951
|
+
`;
|
|
2952
|
+
const appended = `${base}AGT_HOST="${apiUrl}"
|
|
2953
|
+
AGT_API_KEY="${apiKey}"
|
|
2954
|
+
`;
|
|
2955
|
+
writeFileSync5(envPath, appended, { mode: 420 });
|
|
2956
|
+
return true;
|
|
2957
|
+
} catch {
|
|
2958
|
+
return false;
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2887
2961
|
function buildExportLines(shell, apiUrl, apiKey) {
|
|
2888
2962
|
if (shell.includes("fish")) {
|
|
2889
2963
|
return [
|
|
@@ -3003,11 +3077,15 @@ async function setupCommand(token) {
|
|
|
3003
3077
|
if (!json) {
|
|
3004
3078
|
success(`Environment variables written to ${chalk18.bold(profilePath)}`);
|
|
3005
3079
|
}
|
|
3080
|
+
const envWritten = maybeWriteEtcEnvironment(finalApiUrl, setupResult.api_key);
|
|
3081
|
+
if (!json && envWritten) {
|
|
3082
|
+
success(`System-wide env written to ${chalk18.bold("/etc/environment")}`);
|
|
3083
|
+
}
|
|
3006
3084
|
const managerSpinner = ora13({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
3007
3085
|
managerSpinner.start();
|
|
3008
3086
|
try {
|
|
3009
3087
|
const configDir = join10(homedir2(), ".augmented");
|
|
3010
|
-
const { pid } = startWatchdog({ intervalMs: 1e4, configDir });
|
|
3088
|
+
const { pid } = startWatchdog({ intervalMs: 1e4, configDir, detached: true });
|
|
3011
3089
|
managerSpinner.succeed(`Manager started (PID ${pid})`);
|
|
3012
3090
|
} catch (err) {
|
|
3013
3091
|
managerSpinner.warn("Could not start manager daemon");
|
|
@@ -3016,6 +3094,7 @@ async function setupCommand(token) {
|
|
|
3016
3094
|
info("Start it manually with: agt manager start");
|
|
3017
3095
|
}
|
|
3018
3096
|
}
|
|
3097
|
+
const includeApiKey = process.env["AGT_SETUP_INCLUDE_API_KEY"] === "1";
|
|
3019
3098
|
if (json) {
|
|
3020
3099
|
jsonOutput({
|
|
3021
3100
|
ok: true,
|
|
@@ -3023,14 +3102,11 @@ async function setupCommand(token) {
|
|
|
3023
3102
|
host_id: setupResult.host_id,
|
|
3024
3103
|
team_slug: setupResult.team_slug,
|
|
3025
3104
|
api_url: finalApiUrl,
|
|
3026
|
-
|
|
3027
|
-
// persist it system-wide. The token the caller just supplied grants
|
|
3028
|
-
// access to this key anyway; re-emitting it here just saves the caller
|
|
3029
|
-
// from having to parse the shell profile we wrote.
|
|
3030
|
-
api_key: setupResult.api_key,
|
|
3105
|
+
...includeApiKey ? { api_key: setupResult.api_key } : {},
|
|
3031
3106
|
agents: setupResult.agents,
|
|
3032
3107
|
profile: profilePath
|
|
3033
3108
|
});
|
|
3109
|
+
process.exit(0);
|
|
3034
3110
|
} else {
|
|
3035
3111
|
console.log();
|
|
3036
3112
|
console.log(chalk18.green.bold(" Setup complete!"));
|
|
@@ -3340,7 +3416,7 @@ function getAcpAgent(name) {
|
|
|
3340
3416
|
}
|
|
3341
3417
|
|
|
3342
3418
|
// ../../packages/core/dist/acp/client.js
|
|
3343
|
-
import { spawn as
|
|
3419
|
+
import { spawn as spawn3 } from "child_process";
|
|
3344
3420
|
function resolveAgentCommand(agentName) {
|
|
3345
3421
|
const adapter = getAcpAgent(agentName);
|
|
3346
3422
|
if (adapter) {
|
|
@@ -3356,7 +3432,7 @@ function resolveAgentCommand(agentName) {
|
|
|
3356
3432
|
}
|
|
3357
3433
|
async function runAcpx(args, options = {}) {
|
|
3358
3434
|
return new Promise((resolve2) => {
|
|
3359
|
-
const child =
|
|
3435
|
+
const child = spawn3("acpx", args, {
|
|
3360
3436
|
cwd: options.cwd,
|
|
3361
3437
|
stdio: ["pipe", "pipe", "pipe"],
|
|
3362
3438
|
env: { ...process.env }
|
|
@@ -3558,7 +3634,7 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
3558
3634
|
import { execSync } from "child_process";
|
|
3559
3635
|
import chalk20 from "chalk";
|
|
3560
3636
|
import ora15 from "ora";
|
|
3561
|
-
var cliVersion = true ? "0.10.
|
|
3637
|
+
var cliVersion = true ? "0.10.12" : "dev";
|
|
3562
3638
|
async function fetchLatestVersion() {
|
|
3563
3639
|
const host2 = getHost();
|
|
3564
3640
|
if (!host2) return null;
|
|
@@ -3957,7 +4033,7 @@ function handleError(err) {
|
|
|
3957
4033
|
}
|
|
3958
4034
|
|
|
3959
4035
|
// src/bin/agt.ts
|
|
3960
|
-
var cliVersion2 = true ? "0.10.
|
|
4036
|
+
var cliVersion2 = true ? "0.10.12" : "dev";
|
|
3961
4037
|
var program = new Command();
|
|
3962
4038
|
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");
|
|
3963
4039
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -4005,8 +4081,8 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
|
|
|
4005
4081
|
);
|
|
4006
4082
|
var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
|
|
4007
4083
|
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", join11(homedir3(), ".augmented")).action(managerStartCommand);
|
|
4008
|
-
manager.command("stop").description("Stop the running manager daemon").action(managerStopCommand);
|
|
4009
|
-
manager.command("status").description("Show the current manager daemon status and discovered agents").action(managerStatusCommand);
|
|
4084
|
+
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join11(homedir3(), ".augmented")).action(managerStopCommand);
|
|
4085
|
+
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join11(homedir3(), ".augmented")).action(managerStatusCommand);
|
|
4010
4086
|
var agent = program.command("agent").description("Inspect and manage agents");
|
|
4011
4087
|
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join11(homedir3(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
|
|
4012
4088
|
var kanban = program.command("kanban").description("Manage agent kanban boards");
|