@integrity-labs/agt-cli 0.27.0 → 0.27.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agt.js +305 -83
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-YWXPSVI5.js → chunk-5N3JKXMU.js} +5 -4
- package/dist/chunk-5N3JKXMU.js.map +1 -0
- package/dist/{chunk-LJZK5RL3.js → chunk-CSDKWI5V.js} +92 -11
- package/dist/chunk-CSDKWI5V.js.map +1 -0
- package/dist/{chunk-BKLEFKUZ.js → chunk-JTZZ6YB2.js} +38 -1
- package/dist/chunk-JTZZ6YB2.js.map +1 -0
- package/dist/{claude-pair-runtime-3UQKYKMO.js → claude-pair-runtime-O6ZAT7MQ.js} +2 -2
- package/dist/lib/manager-worker.js +33 -17
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/index.js +40 -1
- package/dist/mcp/slack-channel.js +57 -3
- package/dist/{persistent-session-SE3E72ET.js → persistent-session-3MXZBC5W.js} +3 -3
- package/dist/{responsiveness-probe-MTMEIXEL.js → responsiveness-probe-37336LTO.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-BKLEFKUZ.js.map +0 -1
- package/dist/chunk-LJZK5RL3.js.map +0 -1
- package/dist/chunk-YWXPSVI5.js.map +0 -1
- /package/dist/{claude-pair-runtime-3UQKYKMO.js.map → claude-pair-runtime-O6ZAT7MQ.js.map} +0 -0
- /package/dist/{persistent-session-SE3E72ET.js.map → persistent-session-3MXZBC5W.js.map} +0 -0
- /package/dist/{responsiveness-probe-MTMEIXEL.js.map → responsiveness-probe-37336LTO.js.map} +0 -0
package/dist/bin/agt.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ApiError,
|
|
4
|
+
DEFAULT_AGT_HOST,
|
|
4
5
|
api,
|
|
5
6
|
error,
|
|
6
7
|
exchangeApiKey,
|
|
@@ -26,7 +27,7 @@ import {
|
|
|
26
27
|
success,
|
|
27
28
|
table,
|
|
28
29
|
warn
|
|
29
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-5N3JKXMU.js";
|
|
30
31
|
import {
|
|
31
32
|
CHANNEL_REGISTRY,
|
|
32
33
|
DEPLOYMENT_TEMPLATES,
|
|
@@ -52,10 +53,10 @@ import {
|
|
|
52
53
|
renderTemplate,
|
|
53
54
|
resolveChannels,
|
|
54
55
|
serializeManifestForSlackCli
|
|
55
|
-
} from "../chunk-
|
|
56
|
+
} from "../chunk-JTZZ6YB2.js";
|
|
56
57
|
|
|
57
58
|
// src/bin/agt.ts
|
|
58
|
-
import { join as
|
|
59
|
+
import { join as join14 } from "path";
|
|
59
60
|
import { homedir as homedir5 } from "os";
|
|
60
61
|
import { Command } from "commander";
|
|
61
62
|
|
|
@@ -550,8 +551,8 @@ async function lintCommand(path) {
|
|
|
550
551
|
process.exitCode = 1;
|
|
551
552
|
return;
|
|
552
553
|
}
|
|
553
|
-
const { readdirSync, statSync: statSync2 } = await import("fs");
|
|
554
|
-
const entries =
|
|
554
|
+
const { readdirSync: readdirSync2, statSync: statSync2 } = await import("fs");
|
|
555
|
+
const entries = readdirSync2(augmentedDir);
|
|
555
556
|
for (const entry of entries) {
|
|
556
557
|
const entryPath = join2(augmentedDir, entry);
|
|
557
558
|
if (statSync2(entryPath).isDirectory()) {
|
|
@@ -1556,8 +1557,8 @@ async function provisionCommand(codeName, options) {
|
|
|
1556
1557
|
import chalk10 from "chalk";
|
|
1557
1558
|
import ora10 from "ora";
|
|
1558
1559
|
import { spawn } from "child_process";
|
|
1559
|
-
import { writeFileSync as
|
|
1560
|
-
import { join as
|
|
1560
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
1561
|
+
import { join as join9 } from "path";
|
|
1561
1562
|
|
|
1562
1563
|
// src/lib/impersonate-flag.ts
|
|
1563
1564
|
var ENV_VAR = "AGT_IMPERSONATE_ENABLED";
|
|
@@ -1621,6 +1622,11 @@ function ensureCodeNameDir(codeName) {
|
|
|
1621
1622
|
mkdirSync4(dir, { recursive: true });
|
|
1622
1623
|
return dir;
|
|
1623
1624
|
}
|
|
1625
|
+
function ensureImpersonateWorkdir(codeName) {
|
|
1626
|
+
const dir = join6(ensureCodeNameDir(codeName), "workdir");
|
|
1627
|
+
mkdirSync4(dir, { recursive: true });
|
|
1628
|
+
return dir;
|
|
1629
|
+
}
|
|
1624
1630
|
function readActiveManifest() {
|
|
1625
1631
|
if (!existsSync2(ACTIVE_MANIFEST_PATH)) return null;
|
|
1626
1632
|
try {
|
|
@@ -1668,8 +1674,19 @@ import {
|
|
|
1668
1674
|
unlinkSync
|
|
1669
1675
|
} from "fs";
|
|
1670
1676
|
import { homedir as homedir2 } from "os";
|
|
1671
|
-
import { sep } from "path";
|
|
1677
|
+
import { dirname, join as join7, parse, sep } from "path";
|
|
1672
1678
|
var BACKUP_SUFFIX = ".pre-impersonate-backup";
|
|
1679
|
+
function findGitWorkTreeRoot(startDir) {
|
|
1680
|
+
const { root } = parse(startDir);
|
|
1681
|
+
let dir = startDir;
|
|
1682
|
+
for (; ; ) {
|
|
1683
|
+
if (existsSync3(join7(dir, ".git"))) return dir;
|
|
1684
|
+
if (dir === root) return null;
|
|
1685
|
+
const parent = dirname(dir);
|
|
1686
|
+
if (parent === dir) return null;
|
|
1687
|
+
dir = parent;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1673
1690
|
function swapInPersonaFile(projectPath, personaPath) {
|
|
1674
1691
|
let kind;
|
|
1675
1692
|
if (!lstatSafe(projectPath)) {
|
|
@@ -1734,6 +1751,139 @@ function lstatSafe(path) {
|
|
|
1734
1751
|
}
|
|
1735
1752
|
}
|
|
1736
1753
|
|
|
1754
|
+
// src/lib/impersonate-hook.ts
|
|
1755
|
+
import {
|
|
1756
|
+
copyFileSync,
|
|
1757
|
+
existsSync as existsSync4,
|
|
1758
|
+
mkdirSync as mkdirSync5,
|
|
1759
|
+
readdirSync,
|
|
1760
|
+
readFileSync as readFileSync3,
|
|
1761
|
+
renameSync as renameSync3,
|
|
1762
|
+
rmdirSync,
|
|
1763
|
+
unlinkSync as unlinkSync2,
|
|
1764
|
+
writeFileSync as writeFileSync5
|
|
1765
|
+
} from "fs";
|
|
1766
|
+
import { join as join8 } from "path";
|
|
1767
|
+
var INTRODUCE_HOOK_COMMAND = "agt impersonate introduce";
|
|
1768
|
+
var SESSION_START_MATCHER = "startup";
|
|
1769
|
+
function registerIntroduceHook(projectCwd, command = INTRODUCE_HOOK_COMMAND) {
|
|
1770
|
+
const claudeDir = join8(projectCwd, ".claude");
|
|
1771
|
+
const createdClaudeDir = !existsSync4(claudeDir);
|
|
1772
|
+
mkdirSync5(claudeDir, { recursive: true });
|
|
1773
|
+
const settingsPath = join8(claudeDir, "settings.local.json");
|
|
1774
|
+
const settingsExisted = existsSync4(settingsPath);
|
|
1775
|
+
const backupPath = settingsPath + BACKUP_SUFFIX;
|
|
1776
|
+
let settings = {};
|
|
1777
|
+
if (settingsExisted) {
|
|
1778
|
+
if (!existsSync4(backupPath)) {
|
|
1779
|
+
copyFileSync(settingsPath, backupPath);
|
|
1780
|
+
}
|
|
1781
|
+
settings = asPlainObject(safeParseJson(readFileSync3(settingsPath, "utf-8")));
|
|
1782
|
+
}
|
|
1783
|
+
const hooks = asPlainObject(settings["hooks"]);
|
|
1784
|
+
const existing = Array.isArray(hooks[SESSION_START_KEY]) ? [...hooks[SESSION_START_KEY]] : [];
|
|
1785
|
+
const alreadyRegistered = existing.some(
|
|
1786
|
+
(entry) => entryMatchesCommand(entry, command)
|
|
1787
|
+
);
|
|
1788
|
+
if (!alreadyRegistered) {
|
|
1789
|
+
existing.push({
|
|
1790
|
+
matcher: SESSION_START_MATCHER,
|
|
1791
|
+
hooks: [{ type: "command", command }]
|
|
1792
|
+
});
|
|
1793
|
+
}
|
|
1794
|
+
hooks[SESSION_START_KEY] = existing;
|
|
1795
|
+
settings["hooks"] = hooks;
|
|
1796
|
+
writeFileSync5(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1797
|
+
return {
|
|
1798
|
+
settings_path: settingsPath,
|
|
1799
|
+
settings_backup: settingsExisted ? "had-file" : "didnt-exist",
|
|
1800
|
+
created_claude_dir: createdClaudeDir
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
function unregisterIntroduceHook(backup) {
|
|
1804
|
+
const { settings_path, settings_backup, created_claude_dir } = backup;
|
|
1805
|
+
const backupPath = settings_path + BACKUP_SUFFIX;
|
|
1806
|
+
if (settings_backup === "had-file") {
|
|
1807
|
+
if (existsSync4(backupPath)) {
|
|
1808
|
+
renameSync3(backupPath, settings_path);
|
|
1809
|
+
}
|
|
1810
|
+
} else {
|
|
1811
|
+
if (existsSync4(settings_path)) unlinkSync2(settings_path);
|
|
1812
|
+
if (existsSync4(backupPath)) unlinkSync2(backupPath);
|
|
1813
|
+
}
|
|
1814
|
+
if (created_claude_dir) {
|
|
1815
|
+
const claudeDir = dirOf(settings_path);
|
|
1816
|
+
try {
|
|
1817
|
+
if (existsSync4(claudeDir) && readdirSync(claudeDir).length === 0) {
|
|
1818
|
+
rmdirSync(claudeDir);
|
|
1819
|
+
}
|
|
1820
|
+
} catch {
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
var SESSION_START_KEY = "SessionStart";
|
|
1825
|
+
function entryMatchesCommand(entry, command) {
|
|
1826
|
+
if (entry.matcher !== SESSION_START_MATCHER) return false;
|
|
1827
|
+
const entryHooks = entry.hooks;
|
|
1828
|
+
return Array.isArray(entryHooks) && entryHooks.some(
|
|
1829
|
+
(h) => typeof h === "object" && h !== null && h.type === "command" && h.command === command
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
function dirOf(filePath) {
|
|
1833
|
+
const idx = filePath.lastIndexOf("/");
|
|
1834
|
+
return idx === -1 ? filePath : filePath.slice(0, idx);
|
|
1835
|
+
}
|
|
1836
|
+
function safeParseJson(text) {
|
|
1837
|
+
try {
|
|
1838
|
+
return JSON.parse(text);
|
|
1839
|
+
} catch {
|
|
1840
|
+
return null;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
function asPlainObject(value) {
|
|
1844
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// src/lib/impersonate-introduce.ts
|
|
1848
|
+
function parseIdentityFromClaudeMd(content) {
|
|
1849
|
+
const headingMatch = content.match(/^#\s+(.+?)\s*$/m);
|
|
1850
|
+
const displayName = headingMatch?.[1]?.trim() || null;
|
|
1851
|
+
const roleMatch = content.match(
|
|
1852
|
+
/^You are \*\*[^*]+\*\*,\s*\*\*([^*]+)\*\*/m
|
|
1853
|
+
);
|
|
1854
|
+
const role = roleMatch?.[1]?.trim() || null;
|
|
1855
|
+
return { displayName, role };
|
|
1856
|
+
}
|
|
1857
|
+
function parseIntegrationsFromMcpJson(content) {
|
|
1858
|
+
let parsed;
|
|
1859
|
+
try {
|
|
1860
|
+
parsed = JSON.parse(content);
|
|
1861
|
+
} catch {
|
|
1862
|
+
return [];
|
|
1863
|
+
}
|
|
1864
|
+
const servers = parsed?.mcpServers;
|
|
1865
|
+
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
1866
|
+
return [];
|
|
1867
|
+
}
|
|
1868
|
+
return Object.keys(servers).map(prettifyServerName);
|
|
1869
|
+
}
|
|
1870
|
+
function prettifyServerName(key) {
|
|
1871
|
+
return key.split(/[-_]/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1872
|
+
}
|
|
1873
|
+
function buildIntroduction(input4) {
|
|
1874
|
+
const { displayName, codeName, role, integrations } = input4;
|
|
1875
|
+
const spokenName = displayName || codeName;
|
|
1876
|
+
const codeSuffix = displayName && displayName !== codeName ? ` (${codeName})` : "";
|
|
1877
|
+
const roleClause = role ? `, ${role}` : "";
|
|
1878
|
+
const lines = [`I'm ${spokenName}${codeSuffix}${roleClause}.`, ""];
|
|
1879
|
+
if (integrations.length > 0) {
|
|
1880
|
+
lines.push(`Connected integrations: ${integrations.join(", ")}.`);
|
|
1881
|
+
} else {
|
|
1882
|
+
lines.push("No integrations are connected.");
|
|
1883
|
+
}
|
|
1884
|
+
return lines.join("\n");
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1737
1887
|
// src/commands/impersonate.ts
|
|
1738
1888
|
var SWAP_FILES = ["CLAUDE.md", ".mcp.json"];
|
|
1739
1889
|
var AGENT_IMPERSONATION_HEADER = "X-Agent-Impersonation";
|
|
@@ -1757,13 +1907,23 @@ async function impersonateConnectCommand(token, options = {}) {
|
|
|
1757
1907
|
process.exitCode = 1;
|
|
1758
1908
|
return;
|
|
1759
1909
|
}
|
|
1910
|
+
if (!options.workdir) {
|
|
1911
|
+
const workTreeRoot = findGitWorkTreeRoot(process.cwd());
|
|
1912
|
+
if (workTreeRoot) {
|
|
1913
|
+
const msg = `Refusing to impersonate inside a git working tree (${workTreeRoot}). connect swaps the agent's ${SWAP_FILES.join(" + ")} into the current directory, which would overwrite the repo's own files. Re-run with \`--workdir\` to use an auto-provisioned dedicated directory, or run from a standalone empty directory.`;
|
|
1914
|
+
if (json) jsonOutput({ ok: false, error: msg });
|
|
1915
|
+
else error(msg);
|
|
1916
|
+
process.exitCode = 1;
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1760
1920
|
if (!json) console.log(chalk10.bold("\nAugmented \u2014 Impersonate\n"));
|
|
1761
1921
|
const spinner = ora10({
|
|
1762
1922
|
text: "Redeeming token\u2026",
|
|
1763
1923
|
isSilent: json
|
|
1764
1924
|
});
|
|
1765
1925
|
spinner.start();
|
|
1766
|
-
const host2 =
|
|
1926
|
+
const host2 = (options.apiHost ?? DEFAULT_AGT_HOST).replace(/\/+$/, "");
|
|
1767
1927
|
let bundle;
|
|
1768
1928
|
try {
|
|
1769
1929
|
const res = await fetch(`${host2}/impersonate/agent/redeem`, {
|
|
@@ -1787,25 +1947,27 @@ async function impersonateConnectCommand(token, options = {}) {
|
|
|
1787
1947
|
}
|
|
1788
1948
|
spinner.text = "Writing persona files\u2026";
|
|
1789
1949
|
const personaDir = ensureCodeNameDir(bundle.agent.code_name);
|
|
1790
|
-
|
|
1791
|
-
|
|
1950
|
+
writeFileSync6(
|
|
1951
|
+
join9(personaDir, "CLAUDE.md"),
|
|
1792
1952
|
bundle.artifacts["CLAUDE.md"]
|
|
1793
1953
|
);
|
|
1794
|
-
|
|
1795
|
-
|
|
1954
|
+
writeFileSync6(
|
|
1955
|
+
join9(personaDir, ".mcp.json"),
|
|
1796
1956
|
bundle.artifacts[".mcp.json"]
|
|
1797
1957
|
);
|
|
1798
1958
|
spinner.text = "Swapping persona files\u2026";
|
|
1799
|
-
const projectCwd = process.cwd();
|
|
1959
|
+
const projectCwd = options.workdir ? ensureImpersonateWorkdir(bundle.agent.code_name) : process.cwd();
|
|
1800
1960
|
const backups = {};
|
|
1801
1961
|
const swapped = [];
|
|
1962
|
+
let hookBackup;
|
|
1802
1963
|
try {
|
|
1803
1964
|
for (const file of SWAP_FILES) {
|
|
1804
|
-
const projectPath =
|
|
1805
|
-
const kind = swapInPersonaFile(projectPath,
|
|
1965
|
+
const projectPath = join9(projectCwd, file);
|
|
1966
|
+
const kind = swapInPersonaFile(projectPath, join9(personaDir, file));
|
|
1806
1967
|
backups[file] = kind;
|
|
1807
1968
|
swapped.push({ file, kind });
|
|
1808
1969
|
}
|
|
1970
|
+
hookBackup = registerIntroduceHook(projectCwd);
|
|
1809
1971
|
const manifest = {
|
|
1810
1972
|
code_name: bundle.agent.code_name,
|
|
1811
1973
|
agent_id: bundle.agent.agent_id,
|
|
@@ -1816,13 +1978,20 @@ async function impersonateConnectCommand(token, options = {}) {
|
|
|
1816
1978
|
minted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1817
1979
|
project_cwd: projectCwd,
|
|
1818
1980
|
host: host2,
|
|
1819
|
-
backups
|
|
1981
|
+
backups,
|
|
1982
|
+
hook: hookBackup
|
|
1820
1983
|
};
|
|
1821
1984
|
writeActiveManifest(manifest);
|
|
1822
1985
|
} catch (err) {
|
|
1986
|
+
if (hookBackup) {
|
|
1987
|
+
try {
|
|
1988
|
+
unregisterIntroduceHook(hookBackup);
|
|
1989
|
+
} catch {
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1823
1992
|
for (const { file, kind } of [...swapped].reverse()) {
|
|
1824
1993
|
try {
|
|
1825
|
-
restoreSwapped(
|
|
1994
|
+
restoreSwapped(join9(projectCwd, file), kind);
|
|
1826
1995
|
} catch {
|
|
1827
1996
|
}
|
|
1828
1997
|
}
|
|
@@ -1856,6 +2025,9 @@ async function impersonateConnectCommand(token, options = {}) {
|
|
|
1856
2025
|
console.log(` Swapped: ${chalk10.dim(SWAP_FILES.join(", "))}`);
|
|
1857
2026
|
console.log();
|
|
1858
2027
|
if (!shouldLaunchClaude) {
|
|
2028
|
+
if (options.workdir) {
|
|
2029
|
+
info(`Start Claude Code in the impersonation workdir: \`cd ${projectCwd}\``);
|
|
2030
|
+
}
|
|
1859
2031
|
info(
|
|
1860
2032
|
"Restart Claude Code to pick up the agent's persona + MCP server set. Claude Code 2.1.152 does not honour `tools/list_changed` in-session (spike PoC, ENG-4733)."
|
|
1861
2033
|
);
|
|
@@ -1968,7 +2140,7 @@ async function impersonateExitCommand() {
|
|
|
1968
2140
|
}
|
|
1969
2141
|
const restored = [];
|
|
1970
2142
|
for (const [file, kind] of Object.entries(manifest.backups)) {
|
|
1971
|
-
const projectPath =
|
|
2143
|
+
const projectPath = join9(manifest.project_cwd, file);
|
|
1972
2144
|
try {
|
|
1973
2145
|
restoreSwapped(projectPath, kind);
|
|
1974
2146
|
restored.push(file);
|
|
@@ -1977,6 +2149,14 @@ async function impersonateExitCommand() {
|
|
|
1977
2149
|
if (!json) error(`Failed to restore ${file}: ${msg}`);
|
|
1978
2150
|
}
|
|
1979
2151
|
}
|
|
2152
|
+
if (manifest.hook) {
|
|
2153
|
+
try {
|
|
2154
|
+
unregisterIntroduceHook(manifest.hook);
|
|
2155
|
+
} catch (err) {
|
|
2156
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2157
|
+
if (!json) error(`Failed to remove introduce hook: ${msg}`);
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
1980
2160
|
clearActiveManifest();
|
|
1981
2161
|
if (json) {
|
|
1982
2162
|
jsonOutput({
|
|
@@ -1998,6 +2178,37 @@ async function impersonateExitCommand() {
|
|
|
1998
2178
|
}
|
|
1999
2179
|
info("Restart Claude Code to pick up your original persona.");
|
|
2000
2180
|
}
|
|
2181
|
+
async function impersonateIntroduceCommand() {
|
|
2182
|
+
try {
|
|
2183
|
+
const manifest = readActiveManifest();
|
|
2184
|
+
if (!manifest || isExpired(manifest)) return;
|
|
2185
|
+
const cwd = manifest.project_cwd;
|
|
2186
|
+
const identity = readClaudeMdIdentity(join9(cwd, "CLAUDE.md"));
|
|
2187
|
+
const integrations = readMcpIntegrations(join9(cwd, ".mcp.json"));
|
|
2188
|
+
const intro = buildIntroduction({
|
|
2189
|
+
displayName: identity.displayName,
|
|
2190
|
+
codeName: manifest.code_name,
|
|
2191
|
+
role: identity.role,
|
|
2192
|
+
integrations
|
|
2193
|
+
});
|
|
2194
|
+
process.stdout.write(intro + "\n");
|
|
2195
|
+
} catch {
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
function readClaudeMdIdentity(path) {
|
|
2199
|
+
try {
|
|
2200
|
+
return parseIdentityFromClaudeMd(readFileSync4(path, "utf-8"));
|
|
2201
|
+
} catch {
|
|
2202
|
+
return { displayName: null, role: null };
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
function readMcpIntegrations(path) {
|
|
2206
|
+
try {
|
|
2207
|
+
return parseIntegrationsFromMcpJson(readFileSync4(path, "utf-8"));
|
|
2208
|
+
} catch {
|
|
2209
|
+
return [];
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2001
2212
|
|
|
2002
2213
|
// src/commands/drift.ts
|
|
2003
2214
|
import chalk11 from "chalk";
|
|
@@ -2006,7 +2217,7 @@ import ora11 from "ora";
|
|
|
2006
2217
|
// ../../packages/core/dist/drift/live-state-reader.js
|
|
2007
2218
|
import { readFile } from "fs/promises";
|
|
2008
2219
|
import { createHash } from "crypto";
|
|
2009
|
-
import { join as
|
|
2220
|
+
import { join as join10 } from "path";
|
|
2010
2221
|
import JSON5 from "json5";
|
|
2011
2222
|
async function hashFile(filePath) {
|
|
2012
2223
|
try {
|
|
@@ -2030,8 +2241,8 @@ async function readLiveState(options) {
|
|
|
2030
2241
|
const toolsFile = trackedFiles.find((f) => f.includes("TOOLS")) ?? "TOOLS.md";
|
|
2031
2242
|
const [frameworkConfig, charterHash, toolsHash] = await Promise.all([
|
|
2032
2243
|
readJsonFile(options.configPath),
|
|
2033
|
-
hashFile(
|
|
2034
|
-
hashFile(
|
|
2244
|
+
hashFile(join10(options.teamDir, charterFile)),
|
|
2245
|
+
hashFile(join10(options.teamDir, toolsFile))
|
|
2035
2246
|
]);
|
|
2036
2247
|
return {
|
|
2037
2248
|
frameworkConfig,
|
|
@@ -2640,15 +2851,15 @@ function terminate(child) {
|
|
|
2640
2851
|
// src/commands/manager-watch.tsx
|
|
2641
2852
|
import { useEffect, useState, useMemo } from "react";
|
|
2642
2853
|
import { render, Box, Text, useApp, useInput } from "ink";
|
|
2643
|
-
import { existsSync as
|
|
2854
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, statSync, openSync, readSync, closeSync } from "fs";
|
|
2644
2855
|
import { homedir as homedir3 } from "os";
|
|
2645
|
-
import { join as
|
|
2856
|
+
import { join as join11 } from "path";
|
|
2646
2857
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2647
2858
|
var REFRESH_MS = 1e3;
|
|
2648
2859
|
var LOG_TAIL_LINES = 200;
|
|
2649
2860
|
var DETAIL_RECENT_LINES = 50;
|
|
2650
2861
|
function managerWatchCommand(opts = {}) {
|
|
2651
|
-
const configDir = opts.configDir ??
|
|
2862
|
+
const configDir = opts.configDir ?? join11(homedir3(), ".augmented");
|
|
2652
2863
|
const paths = getManagerPaths(configDir);
|
|
2653
2864
|
const isTty = process.stdout.isTTY === true && process.stdin.isTTY === true;
|
|
2654
2865
|
if (opts.noTui || !isTty) {
|
|
@@ -2672,15 +2883,15 @@ function managerWatchCommand(opts = {}) {
|
|
|
2672
2883
|
}
|
|
2673
2884
|
function readState(stateFile) {
|
|
2674
2885
|
try {
|
|
2675
|
-
if (!
|
|
2676
|
-
const raw =
|
|
2886
|
+
if (!existsSync5(stateFile)) return null;
|
|
2887
|
+
const raw = readFileSync5(stateFile, "utf-8");
|
|
2677
2888
|
return JSON.parse(raw);
|
|
2678
2889
|
} catch {
|
|
2679
2890
|
return null;
|
|
2680
2891
|
}
|
|
2681
2892
|
}
|
|
2682
2893
|
function tailLogFile(logFile, lines) {
|
|
2683
|
-
if (!
|
|
2894
|
+
if (!existsSync5(logFile)) return [];
|
|
2684
2895
|
try {
|
|
2685
2896
|
const fileSize = statSync(logFile).size;
|
|
2686
2897
|
if (fileSize === 0) return [];
|
|
@@ -2921,7 +3132,7 @@ function truncate(s, max) {
|
|
|
2921
3132
|
return s.length > max ? `${s.slice(0, Math.max(0, max - 1))}\u2026` : s;
|
|
2922
3133
|
}
|
|
2923
3134
|
function streamLogFile(logFile) {
|
|
2924
|
-
if (!
|
|
3135
|
+
if (!existsSync5(logFile)) {
|
|
2925
3136
|
process.stderr.write(`No manager log found at ${logFile}.
|
|
2926
3137
|
Start the manager first: agt manager start
|
|
2927
3138
|
`);
|
|
@@ -2930,7 +3141,7 @@ Start the manager first: agt manager start
|
|
|
2930
3141
|
}
|
|
2931
3142
|
let lastSize = 0;
|
|
2932
3143
|
try {
|
|
2933
|
-
const initial =
|
|
3144
|
+
const initial = readFileSync5(logFile, "utf-8");
|
|
2934
3145
|
process.stdout.write(initial);
|
|
2935
3146
|
lastSize = statSync(logFile).size;
|
|
2936
3147
|
} catch (err) {
|
|
@@ -2967,14 +3178,14 @@ Start the manager first: agt manager start
|
|
|
2967
3178
|
// src/commands/agent.ts
|
|
2968
3179
|
import chalk14 from "chalk";
|
|
2969
3180
|
import JSON52 from "json5";
|
|
2970
|
-
import { readFileSync as
|
|
2971
|
-
import { join as
|
|
3181
|
+
import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
|
|
3182
|
+
import { join as join12 } from "path";
|
|
2972
3183
|
async function agentShowCommand(codeName, opts) {
|
|
2973
3184
|
const json = isJsonMode();
|
|
2974
|
-
const unifiedDir =
|
|
2975
|
-
const legacyDir =
|
|
2976
|
-
const agentDir =
|
|
2977
|
-
const hasLocalConfig =
|
|
3185
|
+
const unifiedDir = join12(opts.configDir, codeName, "provision");
|
|
3186
|
+
const legacyDir = join12(opts.configDir, codeName, "claudecode", "provision");
|
|
3187
|
+
const agentDir = existsSync6(unifiedDir) ? unifiedDir : legacyDir;
|
|
3188
|
+
const hasLocalConfig = existsSync6(agentDir);
|
|
2978
3189
|
let apiChannels = null;
|
|
2979
3190
|
let apiAgent = null;
|
|
2980
3191
|
if (getApiKey()) {
|
|
@@ -3007,34 +3218,34 @@ async function agentShowCommand(codeName, opts) {
|
|
|
3007
3218
|
let openclawConfig = null;
|
|
3008
3219
|
let agentState = null;
|
|
3009
3220
|
if (hasLocalConfig) {
|
|
3010
|
-
const charterPath =
|
|
3011
|
-
if (
|
|
3012
|
-
const raw =
|
|
3221
|
+
const charterPath = join12(agentDir, "CHARTER.md");
|
|
3222
|
+
if (existsSync6(charterPath)) {
|
|
3223
|
+
const raw = readFileSync6(charterPath, "utf-8");
|
|
3013
3224
|
const parsed = extractFrontmatter(raw);
|
|
3014
3225
|
if (parsed.frontmatter) {
|
|
3015
3226
|
charter = parsed.frontmatter;
|
|
3016
3227
|
}
|
|
3017
3228
|
}
|
|
3018
|
-
const toolsPath =
|
|
3019
|
-
if (
|
|
3020
|
-
const raw =
|
|
3229
|
+
const toolsPath = join12(agentDir, "TOOLS.md");
|
|
3230
|
+
if (existsSync6(toolsPath)) {
|
|
3231
|
+
const raw = readFileSync6(toolsPath, "utf-8");
|
|
3021
3232
|
const parsed = extractFrontmatter(raw);
|
|
3022
3233
|
if (parsed.frontmatter) {
|
|
3023
3234
|
tools = parsed.frontmatter;
|
|
3024
3235
|
}
|
|
3025
3236
|
}
|
|
3026
|
-
const openclawPath =
|
|
3027
|
-
if (
|
|
3237
|
+
const openclawPath = join12(agentDir, "openclaw.json5");
|
|
3238
|
+
if (existsSync6(openclawPath)) {
|
|
3028
3239
|
try {
|
|
3029
|
-
const raw =
|
|
3240
|
+
const raw = readFileSync6(openclawPath, "utf-8");
|
|
3030
3241
|
openclawConfig = JSON52.parse(raw);
|
|
3031
3242
|
} catch {
|
|
3032
3243
|
}
|
|
3033
3244
|
}
|
|
3034
|
-
const statePath =
|
|
3035
|
-
if (
|
|
3245
|
+
const statePath = join12(opts.configDir, "manager-state.json");
|
|
3246
|
+
if (existsSync6(statePath)) {
|
|
3036
3247
|
try {
|
|
3037
|
-
const raw =
|
|
3248
|
+
const raw = readFileSync6(statePath, "utf-8");
|
|
3038
3249
|
const state = JSON.parse(raw);
|
|
3039
3250
|
agentState = state.agents?.find((a) => a.codeName === codeName) ?? null;
|
|
3040
3251
|
} catch {
|
|
@@ -3371,8 +3582,8 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
3371
3582
|
}
|
|
3372
3583
|
|
|
3373
3584
|
// src/commands/setup.ts
|
|
3374
|
-
import { existsSync as
|
|
3375
|
-
import { join as
|
|
3585
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, accessSync, constants as fsConstants } from "fs";
|
|
3586
|
+
import { join as join13, dirname as dirname2 } from "path";
|
|
3376
3587
|
import { homedir as homedir4 } from "os";
|
|
3377
3588
|
import chalk16 from "chalk";
|
|
3378
3589
|
import ora14 from "ora";
|
|
@@ -3380,15 +3591,15 @@ function detectShellProfile() {
|
|
|
3380
3591
|
const shell = process.env["SHELL"] ?? "";
|
|
3381
3592
|
const home = homedir4();
|
|
3382
3593
|
if (shell.includes("zsh")) {
|
|
3383
|
-
return
|
|
3594
|
+
return join13(home, ".zshrc");
|
|
3384
3595
|
}
|
|
3385
3596
|
if (shell.includes("fish")) {
|
|
3386
|
-
const fishConfig =
|
|
3597
|
+
const fishConfig = join13(home, ".config", "fish", "config.fish");
|
|
3387
3598
|
return fishConfig;
|
|
3388
3599
|
}
|
|
3389
|
-
const bashrc =
|
|
3390
|
-
if (
|
|
3391
|
-
return
|
|
3600
|
+
const bashrc = join13(home, ".bashrc");
|
|
3601
|
+
if (existsSync7(bashrc)) return bashrc;
|
|
3602
|
+
return join13(home, ".bash_profile");
|
|
3392
3603
|
}
|
|
3393
3604
|
function maybeWriteSystemWideEnv(apiUrl, apiKey, consoleUrl) {
|
|
3394
3605
|
const empty = { etcEnvironment: false, profileD: false, bashrc: false };
|
|
@@ -3414,14 +3625,14 @@ function quoteForFishShell(value) {
|
|
|
3414
3625
|
}
|
|
3415
3626
|
function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
3416
3627
|
const envPath = "/etc/environment";
|
|
3417
|
-
if (!
|
|
3628
|
+
if (!existsSync7(envPath)) return false;
|
|
3418
3629
|
try {
|
|
3419
3630
|
accessSync(envPath, fsConstants.W_OK);
|
|
3420
3631
|
} catch {
|
|
3421
3632
|
return false;
|
|
3422
3633
|
}
|
|
3423
3634
|
try {
|
|
3424
|
-
const current =
|
|
3635
|
+
const current = readFileSync7(envPath, "utf-8");
|
|
3425
3636
|
const stripped = current.split(/\r?\n/).filter((line) => !/^\s*(?:export\s+)?AGT_(?:HOST|API_KEY|CONSOLE_URL)=/.test(line)).join("\n");
|
|
3426
3637
|
const base = stripped.endsWith("\n") || stripped.length === 0 ? stripped : `${stripped}
|
|
3427
3638
|
`;
|
|
@@ -3432,7 +3643,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
|
3432
3643
|
if (consoleUrl) lines.push(`AGT_CONSOLE_URL=${quoteForEtcEnvironment(consoleUrl)}`);
|
|
3433
3644
|
const appended = `${base}${lines.join("\n")}
|
|
3434
3645
|
`;
|
|
3435
|
-
|
|
3646
|
+
writeFileSync7(envPath, appended, { mode: 420 });
|
|
3436
3647
|
return true;
|
|
3437
3648
|
} catch {
|
|
3438
3649
|
return false;
|
|
@@ -3440,7 +3651,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
|
3440
3651
|
}
|
|
3441
3652
|
function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
3442
3653
|
const profileD = "/etc/profile.d";
|
|
3443
|
-
if (!
|
|
3654
|
+
if (!existsSync7(profileD)) return false;
|
|
3444
3655
|
try {
|
|
3445
3656
|
accessSync(profileD, fsConstants.W_OK);
|
|
3446
3657
|
} catch {
|
|
@@ -3455,7 +3666,7 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
|
3455
3666
|
];
|
|
3456
3667
|
if (consoleUrl) lines.push(`export AGT_CONSOLE_URL=${quoteForPosixShell(consoleUrl)}`);
|
|
3457
3668
|
lines.push("");
|
|
3458
|
-
|
|
3669
|
+
writeFileSync7(scriptPath, lines.join("\n"), { mode: 420 });
|
|
3459
3670
|
return true;
|
|
3460
3671
|
} catch {
|
|
3461
3672
|
return false;
|
|
@@ -3463,14 +3674,14 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
|
3463
3674
|
}
|
|
3464
3675
|
function ensureBashrcSourcesProfileD() {
|
|
3465
3676
|
const bashrc = "/etc/bashrc";
|
|
3466
|
-
if (!
|
|
3677
|
+
if (!existsSync7(bashrc)) return false;
|
|
3467
3678
|
try {
|
|
3468
3679
|
accessSync(bashrc, fsConstants.W_OK);
|
|
3469
3680
|
} catch {
|
|
3470
3681
|
return false;
|
|
3471
3682
|
}
|
|
3472
3683
|
try {
|
|
3473
|
-
const current =
|
|
3684
|
+
const current = readFileSync7(bashrc, "utf-8");
|
|
3474
3685
|
const marker = "# Augmented (agt) \u2014 source system-wide AGT env";
|
|
3475
3686
|
if (current.includes(marker)) return true;
|
|
3476
3687
|
const snippet = [
|
|
@@ -3481,7 +3692,7 @@ function ensureBashrcSourcesProfileD() {
|
|
|
3481
3692
|
"fi",
|
|
3482
3693
|
""
|
|
3483
3694
|
].join("\n");
|
|
3484
|
-
|
|
3695
|
+
writeFileSync7(bashrc, current + snippet);
|
|
3485
3696
|
return true;
|
|
3486
3697
|
} catch {
|
|
3487
3698
|
return false;
|
|
@@ -3596,12 +3807,12 @@ async function setupCommand(token) {
|
|
|
3596
3807
|
);
|
|
3597
3808
|
}
|
|
3598
3809
|
const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key, consoleUrl);
|
|
3599
|
-
const profileDir =
|
|
3600
|
-
if (!
|
|
3601
|
-
|
|
3810
|
+
const profileDir = dirname2(profilePath);
|
|
3811
|
+
if (!existsSync7(profileDir)) {
|
|
3812
|
+
mkdirSync6(profileDir, { recursive: true });
|
|
3602
3813
|
}
|
|
3603
3814
|
const marker = "# Augmented (agt) host configuration";
|
|
3604
|
-
const current =
|
|
3815
|
+
const current = existsSync7(profilePath) ? readFileSync7(profilePath, "utf-8") : "";
|
|
3605
3816
|
let updated;
|
|
3606
3817
|
if (current.includes(marker)) {
|
|
3607
3818
|
updated = current.replace(
|
|
@@ -3614,7 +3825,7 @@ async function setupCommand(token) {
|
|
|
3614
3825
|
} else {
|
|
3615
3826
|
updated = current + exportLines;
|
|
3616
3827
|
}
|
|
3617
|
-
|
|
3828
|
+
writeFileSync7(profilePath, updated.endsWith("\n") ? updated : `${updated}
|
|
3618
3829
|
`);
|
|
3619
3830
|
if (!json) {
|
|
3620
3831
|
success(`Environment variables written to ${chalk16.bold(profilePath)}`);
|
|
@@ -3632,7 +3843,7 @@ async function setupCommand(token) {
|
|
|
3632
3843
|
const managerSpinner = ora14({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
3633
3844
|
managerSpinner.start();
|
|
3634
3845
|
try {
|
|
3635
|
-
const configDir =
|
|
3846
|
+
const configDir = join13(homedir4(), ".augmented");
|
|
3636
3847
|
const { pid } = startWatchdog({ intervalMs: 1e4, configDir, detached: true });
|
|
3637
3848
|
managerSpinner.succeed(`Manager started (PID ${pid})`);
|
|
3638
3849
|
} catch (err) {
|
|
@@ -4180,10 +4391,10 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
4180
4391
|
|
|
4181
4392
|
// src/commands/update.ts
|
|
4182
4393
|
import { execFileSync, execSync } from "child_process";
|
|
4183
|
-
import { existsSync as
|
|
4394
|
+
import { existsSync as existsSync8, realpathSync as realpathSync2 } from "fs";
|
|
4184
4395
|
import chalk18 from "chalk";
|
|
4185
4396
|
import ora16 from "ora";
|
|
4186
|
-
var cliVersion = true ? "0.27.
|
|
4397
|
+
var cliVersion = true ? "0.27.2" : "dev";
|
|
4187
4398
|
async function fetchLatestVersion() {
|
|
4188
4399
|
const host2 = getHost();
|
|
4189
4400
|
if (!host2) return null;
|
|
@@ -4203,9 +4414,9 @@ async function fetchLatestVersion() {
|
|
|
4203
4414
|
}
|
|
4204
4415
|
function isNewerVersion(local, remote) {
|
|
4205
4416
|
if (local === "dev") return false;
|
|
4206
|
-
const
|
|
4207
|
-
const lParts =
|
|
4208
|
-
const rParts =
|
|
4417
|
+
const parse2 = (v) => v.replace(/^v/, "").split(".").map(Number);
|
|
4418
|
+
const lParts = parse2(local);
|
|
4419
|
+
const rParts = parse2(remote);
|
|
4209
4420
|
const lMaj = lParts[0] ?? 0, lMin = lParts[1] ?? 0, lPat = lParts[2] ?? 0;
|
|
4210
4421
|
const rMaj = rParts[0] ?? 0, rMin = rParts[1] ?? 0, rPat = rParts[2] ?? 0;
|
|
4211
4422
|
if (rMaj !== lMaj) return rMaj > lMaj;
|
|
@@ -4287,7 +4498,7 @@ function performUpdate(version) {
|
|
|
4287
4498
|
function detectBrewOwner() {
|
|
4288
4499
|
for (const prefix of ["/home/linuxbrew/.linuxbrew", "/opt/homebrew", "/usr/local"]) {
|
|
4289
4500
|
const cellar = `${prefix}/Cellar`;
|
|
4290
|
-
if (!
|
|
4501
|
+
if (!existsSync8(cellar)) continue;
|
|
4291
4502
|
try {
|
|
4292
4503
|
return execSync(`stat -c %U "${cellar}" 2>/dev/null || stat -f %Su "${cellar}"`, { encoding: "utf-8" }).trim() || null;
|
|
4293
4504
|
} catch {
|
|
@@ -4715,7 +4926,7 @@ function handleError(err) {
|
|
|
4715
4926
|
}
|
|
4716
4927
|
|
|
4717
4928
|
// src/bin/agt.ts
|
|
4718
|
-
var cliVersion2 = true ? "0.27.
|
|
4929
|
+
var cliVersion2 = true ? "0.27.2" : "dev";
|
|
4719
4930
|
var program = new Command();
|
|
4720
4931
|
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");
|
|
4721
4932
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -4738,16 +4949,27 @@ impersonate.command("connect <token>").description(
|
|
|
4738
4949
|
).option(
|
|
4739
4950
|
"--no-launch",
|
|
4740
4951
|
"Skip launching Claude Code after the swap (operator manages their own session)"
|
|
4952
|
+
).option(
|
|
4953
|
+
"--workdir",
|
|
4954
|
+
"Swap into an auto-provisioned dedicated directory (~/.augmented-impersonate/<agent>/workdir) instead of the current directory \u2014 required when the current directory is inside a git repo"
|
|
4955
|
+
).option(
|
|
4956
|
+
"--api-host <url>",
|
|
4957
|
+
"Override the API host used to redeem the token. Defaults to https://api.augmented.team \u2014 AGT_HOST is intentionally ignored so a dev/Tailscale AGT_HOST doesn't accidentally 502 against a token minted on prod."
|
|
4741
4958
|
).action(
|
|
4742
4959
|
(token, opts) => (
|
|
4743
4960
|
// Commander negates --no-FLAG into opts.flag, so --no-launch arrives
|
|
4744
4961
|
// as opts.launch === false. Translate to the command's noLaunch
|
|
4745
4962
|
// option, defaulting to launching when the flag isn't passed.
|
|
4746
|
-
impersonateConnectCommand(token, {
|
|
4963
|
+
impersonateConnectCommand(token, {
|
|
4964
|
+
noLaunch: opts.launch === false,
|
|
4965
|
+
workdir: opts.workdir === true,
|
|
4966
|
+
apiHost: opts.apiHost
|
|
4967
|
+
})
|
|
4747
4968
|
)
|
|
4748
4969
|
);
|
|
4749
4970
|
impersonate.command("current").description('Print the active impersonation (or "none")').action(impersonateCurrentCommand);
|
|
4750
4971
|
impersonate.command("exit").description("End the active impersonation, restore project files, and notify the server").action(impersonateExitCommand);
|
|
4972
|
+
impersonate.command("introduce", { hidden: true }).description("Print the impersonated agent's self-introduction (SessionStart hook target)").action(impersonateIntroduceCommand);
|
|
4751
4973
|
program.command("init").description("Create a new agent (interactive wizard, or non-interactive with --name)").option("--name <display-name>", "Agent display name (triggers non-interactive mode)").option("--code-name <code-name>", "Agent code name (kebab-case, derived from --name if omitted)").option("--description <text>", "Short agent description").option("--env <environment>", "Environment: dev | stage | prod", "dev").option("--risk-tier <tier>", "Risk tier: Low | Medium | High", "Low").option("--budget-type <type>", "Budget type: tokens | dollars | both", "tokens").option("--budget-tokens <number>", "Token budget limit", "10000").option("--budget-dollars <number>", "Dollar budget limit", "10").option("--budget-window <window>", "Budget window: daily | weekly | monthly", "daily").option("--budget-enforcement <mode>", "Budget enforcement: block | throttle | alert | degrade", "block").option("--channels <list>", "Comma-separated channel IDs").option("--logging <mode>", "Logging mode: redacted | hash-only | full-local", "redacted").action(initCommand);
|
|
4752
4974
|
program.command("lint").argument("[path]", "Path to agent directory (default: all agents in .augmented/)").description("Lint CHARTER.md and TOOLS.md files").action(lintCommand);
|
|
4753
4975
|
var channels = program.command("channels").description("Manage and inspect channel configuration");
|
|
@@ -4780,16 +5002,16 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
|
|
|
4780
5002
|
})
|
|
4781
5003
|
);
|
|
4782
5004
|
var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
|
|
4783
|
-
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",
|
|
4784
|
-
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files",
|
|
4785
|
-
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files",
|
|
4786
|
-
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",
|
|
4787
|
-
manager.command("install").description("Install OS-level supervisor (launchd LaunchAgent on macOS) so the manager auto-restarts after crash, reboot, or self-update (ENG-4593)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files",
|
|
5005
|
+
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", join14(homedir5(), ".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);
|
|
5006
|
+
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join14(homedir5(), ".augmented")).action(managerStopCommand);
|
|
5007
|
+
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join14(homedir5(), ".augmented")).action(managerStatusCommand);
|
|
5008
|
+
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", join14(homedir5(), ".augmented")).option("--no-tui", "Skip the TUI and stream the manager log to stdout instead (CI / scripts)").action(managerWatchCommand);
|
|
5009
|
+
manager.command("install").description("Install OS-level supervisor (launchd LaunchAgent on macOS) so the manager auto-restarts after crash, reboot, or self-update (ENG-4593)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join14(homedir5(), ".augmented")).action(managerInstallCommand);
|
|
4788
5010
|
manager.command("uninstall").description("Remove the OS-level supervisor (launchctl unload + delete plist on macOS). Idempotent.").action(managerUninstallCommand);
|
|
4789
5011
|
manager.command("install-system-unit").description("Install a system-level systemd unit (Linux, root) so the manager auto-starts on every boot. For headless EC2 hosts \u2014 survives reboot without `loginctl enable-linger`. (ENG-4706)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files (defaults to /root/.augmented or /home/<user>/.augmented)").option("--user <name>", "Unix user the manager runs as", "root").action(managerInstallSystemUnitCommand);
|
|
4790
5012
|
manager.command("uninstall-system-unit").description("Remove the system-level systemd unit (Linux, root). Idempotent. (ENG-4706)").action(managerUninstallSystemUnitCommand);
|
|
4791
5013
|
var agent = program.command("agent").description("Inspect and manage agents");
|
|
4792
|
-
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory",
|
|
5014
|
+
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join14(homedir5(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
|
|
4793
5015
|
var kanban = program.command("kanban").description("Manage agent kanban boards");
|
|
4794
5016
|
kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
|
|
4795
5017
|
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);
|