@integrity-labs/agt-cli 0.26.2 → 0.27.0-test.4
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 +352 -93
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-4CESBZPM.js → chunk-CPZIFISH.js} +2 -2
- package/dist/{chunk-U3HCB23E.js → chunk-CTWY2X4S.js} +41 -8
- package/dist/chunk-CTWY2X4S.js.map +1 -0
- package/dist/{chunk-QSDDP7JN.js → chunk-WDCSMDQ4.js} +52 -8
- package/dist/chunk-WDCSMDQ4.js.map +1 -0
- package/dist/{claude-pair-runtime-2NNAUBP3.js → claude-pair-runtime-YRPKT45R.js} +2 -2
- package/dist/lib/manager-worker.js +7 -7
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +76 -0
- package/dist/mcp/slack-channel.js +143 -7
- package/dist/mcp/telegram-channel.js +82 -0
- package/dist/{persistent-session-K4X76LLB.js → persistent-session-QJT7JE5P.js} +3 -3
- package/dist/{responsiveness-probe-QBV43SJ7.js → responsiveness-probe-ZERSZOZ2.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-QSDDP7JN.js.map +0 -1
- package/dist/chunk-U3HCB23E.js.map +0 -1
- /package/dist/{chunk-4CESBZPM.js.map → chunk-CPZIFISH.js.map} +0 -0
- /package/dist/{claude-pair-runtime-2NNAUBP3.js.map → claude-pair-runtime-YRPKT45R.js.map} +0 -0
- /package/dist/{persistent-session-K4X76LLB.js.map → persistent-session-QJT7JE5P.js.map} +0 -0
- /package/dist/{responsiveness-probe-QBV43SJ7.js.map → responsiveness-probe-ZERSZOZ2.js.map} +0 -0
package/dist/bin/agt.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
success,
|
|
27
27
|
table,
|
|
28
28
|
warn
|
|
29
|
-
} from "../chunk-
|
|
29
|
+
} from "../chunk-CPZIFISH.js";
|
|
30
30
|
import {
|
|
31
31
|
CHANNEL_REGISTRY,
|
|
32
32
|
DEPLOYMENT_TEMPLATES,
|
|
@@ -52,10 +52,10 @@ import {
|
|
|
52
52
|
renderTemplate,
|
|
53
53
|
resolveChannels,
|
|
54
54
|
serializeManifestForSlackCli
|
|
55
|
-
} from "../chunk-
|
|
55
|
+
} from "../chunk-CTWY2X4S.js";
|
|
56
56
|
|
|
57
57
|
// src/bin/agt.ts
|
|
58
|
-
import { join as
|
|
58
|
+
import { join as join14 } from "path";
|
|
59
59
|
import { homedir as homedir5 } from "os";
|
|
60
60
|
import { Command } from "commander";
|
|
61
61
|
|
|
@@ -550,8 +550,8 @@ async function lintCommand(path) {
|
|
|
550
550
|
process.exitCode = 1;
|
|
551
551
|
return;
|
|
552
552
|
}
|
|
553
|
-
const { readdirSync, statSync: statSync2 } = await import("fs");
|
|
554
|
-
const entries =
|
|
553
|
+
const { readdirSync: readdirSync2, statSync: statSync2 } = await import("fs");
|
|
554
|
+
const entries = readdirSync2(augmentedDir);
|
|
555
555
|
for (const entry of entries) {
|
|
556
556
|
const entryPath = join2(augmentedDir, entry);
|
|
557
557
|
if (statSync2(entryPath).isDirectory()) {
|
|
@@ -1555,8 +1555,9 @@ async function provisionCommand(codeName, options) {
|
|
|
1555
1555
|
// src/commands/impersonate.ts
|
|
1556
1556
|
import chalk10 from "chalk";
|
|
1557
1557
|
import ora10 from "ora";
|
|
1558
|
-
import {
|
|
1559
|
-
import {
|
|
1558
|
+
import { spawn } from "child_process";
|
|
1559
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
1560
|
+
import { join as join9 } from "path";
|
|
1560
1561
|
|
|
1561
1562
|
// src/lib/impersonate-flag.ts
|
|
1562
1563
|
var ENV_VAR = "AGT_IMPERSONATE_ENABLED";
|
|
@@ -1620,6 +1621,11 @@ function ensureCodeNameDir(codeName) {
|
|
|
1620
1621
|
mkdirSync4(dir, { recursive: true });
|
|
1621
1622
|
return dir;
|
|
1622
1623
|
}
|
|
1624
|
+
function ensureImpersonateWorkdir(codeName) {
|
|
1625
|
+
const dir = join6(ensureCodeNameDir(codeName), "workdir");
|
|
1626
|
+
mkdirSync4(dir, { recursive: true });
|
|
1627
|
+
return dir;
|
|
1628
|
+
}
|
|
1623
1629
|
function readActiveManifest() {
|
|
1624
1630
|
if (!existsSync2(ACTIVE_MANIFEST_PATH)) return null;
|
|
1625
1631
|
try {
|
|
@@ -1667,8 +1673,19 @@ import {
|
|
|
1667
1673
|
unlinkSync
|
|
1668
1674
|
} from "fs";
|
|
1669
1675
|
import { homedir as homedir2 } from "os";
|
|
1670
|
-
import { sep } from "path";
|
|
1676
|
+
import { dirname, join as join7, parse, sep } from "path";
|
|
1671
1677
|
var BACKUP_SUFFIX = ".pre-impersonate-backup";
|
|
1678
|
+
function findGitWorkTreeRoot(startDir) {
|
|
1679
|
+
const { root } = parse(startDir);
|
|
1680
|
+
let dir = startDir;
|
|
1681
|
+
for (; ; ) {
|
|
1682
|
+
if (existsSync3(join7(dir, ".git"))) return dir;
|
|
1683
|
+
if (dir === root) return null;
|
|
1684
|
+
const parent = dirname(dir);
|
|
1685
|
+
if (parent === dir) return null;
|
|
1686
|
+
dir = parent;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1672
1689
|
function swapInPersonaFile(projectPath, personaPath) {
|
|
1673
1690
|
let kind;
|
|
1674
1691
|
if (!lstatSafe(projectPath)) {
|
|
@@ -1733,13 +1750,147 @@ function lstatSafe(path) {
|
|
|
1733
1750
|
}
|
|
1734
1751
|
}
|
|
1735
1752
|
|
|
1753
|
+
// src/lib/impersonate-hook.ts
|
|
1754
|
+
import {
|
|
1755
|
+
copyFileSync,
|
|
1756
|
+
existsSync as existsSync4,
|
|
1757
|
+
mkdirSync as mkdirSync5,
|
|
1758
|
+
readdirSync,
|
|
1759
|
+
readFileSync as readFileSync3,
|
|
1760
|
+
renameSync as renameSync3,
|
|
1761
|
+
rmdirSync,
|
|
1762
|
+
unlinkSync as unlinkSync2,
|
|
1763
|
+
writeFileSync as writeFileSync5
|
|
1764
|
+
} from "fs";
|
|
1765
|
+
import { join as join8 } from "path";
|
|
1766
|
+
var INTRODUCE_HOOK_COMMAND = "agt impersonate introduce";
|
|
1767
|
+
var SESSION_START_MATCHER = "startup";
|
|
1768
|
+
function registerIntroduceHook(projectCwd, command = INTRODUCE_HOOK_COMMAND) {
|
|
1769
|
+
const claudeDir = join8(projectCwd, ".claude");
|
|
1770
|
+
const createdClaudeDir = !existsSync4(claudeDir);
|
|
1771
|
+
mkdirSync5(claudeDir, { recursive: true });
|
|
1772
|
+
const settingsPath = join8(claudeDir, "settings.local.json");
|
|
1773
|
+
const settingsExisted = existsSync4(settingsPath);
|
|
1774
|
+
const backupPath = settingsPath + BACKUP_SUFFIX;
|
|
1775
|
+
let settings = {};
|
|
1776
|
+
if (settingsExisted) {
|
|
1777
|
+
if (!existsSync4(backupPath)) {
|
|
1778
|
+
copyFileSync(settingsPath, backupPath);
|
|
1779
|
+
}
|
|
1780
|
+
settings = asPlainObject(safeParseJson(readFileSync3(settingsPath, "utf-8")));
|
|
1781
|
+
}
|
|
1782
|
+
const hooks = asPlainObject(settings["hooks"]);
|
|
1783
|
+
const existing = Array.isArray(hooks[SESSION_START_KEY]) ? [...hooks[SESSION_START_KEY]] : [];
|
|
1784
|
+
const alreadyRegistered = existing.some(
|
|
1785
|
+
(entry) => entryMatchesCommand(entry, command)
|
|
1786
|
+
);
|
|
1787
|
+
if (!alreadyRegistered) {
|
|
1788
|
+
existing.push({
|
|
1789
|
+
matcher: SESSION_START_MATCHER,
|
|
1790
|
+
hooks: [{ type: "command", command }]
|
|
1791
|
+
});
|
|
1792
|
+
}
|
|
1793
|
+
hooks[SESSION_START_KEY] = existing;
|
|
1794
|
+
settings["hooks"] = hooks;
|
|
1795
|
+
writeFileSync5(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1796
|
+
return {
|
|
1797
|
+
settings_path: settingsPath,
|
|
1798
|
+
settings_backup: settingsExisted ? "had-file" : "didnt-exist",
|
|
1799
|
+
created_claude_dir: createdClaudeDir
|
|
1800
|
+
};
|
|
1801
|
+
}
|
|
1802
|
+
function unregisterIntroduceHook(backup) {
|
|
1803
|
+
const { settings_path, settings_backup, created_claude_dir } = backup;
|
|
1804
|
+
const backupPath = settings_path + BACKUP_SUFFIX;
|
|
1805
|
+
if (settings_backup === "had-file") {
|
|
1806
|
+
if (existsSync4(backupPath)) {
|
|
1807
|
+
renameSync3(backupPath, settings_path);
|
|
1808
|
+
}
|
|
1809
|
+
} else {
|
|
1810
|
+
if (existsSync4(settings_path)) unlinkSync2(settings_path);
|
|
1811
|
+
if (existsSync4(backupPath)) unlinkSync2(backupPath);
|
|
1812
|
+
}
|
|
1813
|
+
if (created_claude_dir) {
|
|
1814
|
+
const claudeDir = dirOf(settings_path);
|
|
1815
|
+
try {
|
|
1816
|
+
if (existsSync4(claudeDir) && readdirSync(claudeDir).length === 0) {
|
|
1817
|
+
rmdirSync(claudeDir);
|
|
1818
|
+
}
|
|
1819
|
+
} catch {
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
var SESSION_START_KEY = "SessionStart";
|
|
1824
|
+
function entryMatchesCommand(entry, command) {
|
|
1825
|
+
if (entry.matcher !== SESSION_START_MATCHER) return false;
|
|
1826
|
+
const entryHooks = entry.hooks;
|
|
1827
|
+
return Array.isArray(entryHooks) && entryHooks.some(
|
|
1828
|
+
(h) => typeof h === "object" && h !== null && h.type === "command" && h.command === command
|
|
1829
|
+
);
|
|
1830
|
+
}
|
|
1831
|
+
function dirOf(filePath) {
|
|
1832
|
+
const idx = filePath.lastIndexOf("/");
|
|
1833
|
+
return idx === -1 ? filePath : filePath.slice(0, idx);
|
|
1834
|
+
}
|
|
1835
|
+
function safeParseJson(text) {
|
|
1836
|
+
try {
|
|
1837
|
+
return JSON.parse(text);
|
|
1838
|
+
} catch {
|
|
1839
|
+
return null;
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
function asPlainObject(value) {
|
|
1843
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
// src/lib/impersonate-introduce.ts
|
|
1847
|
+
function parseIdentityFromClaudeMd(content) {
|
|
1848
|
+
const headingMatch = content.match(/^#\s+(.+?)\s*$/m);
|
|
1849
|
+
const displayName = headingMatch?.[1]?.trim() || null;
|
|
1850
|
+
const roleMatch = content.match(
|
|
1851
|
+
/^You are \*\*[^*]+\*\*,\s*\*\*([^*]+)\*\*/m
|
|
1852
|
+
);
|
|
1853
|
+
const role = roleMatch?.[1]?.trim() || null;
|
|
1854
|
+
return { displayName, role };
|
|
1855
|
+
}
|
|
1856
|
+
function parseIntegrationsFromMcpJson(content) {
|
|
1857
|
+
let parsed;
|
|
1858
|
+
try {
|
|
1859
|
+
parsed = JSON.parse(content);
|
|
1860
|
+
} catch {
|
|
1861
|
+
return [];
|
|
1862
|
+
}
|
|
1863
|
+
const servers = parsed?.mcpServers;
|
|
1864
|
+
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
1865
|
+
return [];
|
|
1866
|
+
}
|
|
1867
|
+
return Object.keys(servers).map(prettifyServerName);
|
|
1868
|
+
}
|
|
1869
|
+
function prettifyServerName(key) {
|
|
1870
|
+
return key.split(/[-_]/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1871
|
+
}
|
|
1872
|
+
function buildIntroduction(input4) {
|
|
1873
|
+
const { displayName, codeName, role, integrations } = input4;
|
|
1874
|
+
const spokenName = displayName || codeName;
|
|
1875
|
+
const codeSuffix = displayName && displayName !== codeName ? ` (${codeName})` : "";
|
|
1876
|
+
const roleClause = role ? `, ${role}` : "";
|
|
1877
|
+
const lines = [`I'm ${spokenName}${codeSuffix}${roleClause}.`, ""];
|
|
1878
|
+
if (integrations.length > 0) {
|
|
1879
|
+
lines.push(`Connected integrations: ${integrations.join(", ")}.`);
|
|
1880
|
+
} else {
|
|
1881
|
+
lines.push("No integrations are connected.");
|
|
1882
|
+
}
|
|
1883
|
+
return lines.join("\n");
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1736
1886
|
// src/commands/impersonate.ts
|
|
1737
1887
|
var SWAP_FILES = ["CLAUDE.md", ".mcp.json"];
|
|
1738
1888
|
var AGENT_IMPERSONATION_HEADER = "X-Agent-Impersonation";
|
|
1739
1889
|
var REDEEM_TOKEN_RE = /^[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4}$/i;
|
|
1740
|
-
async function impersonateConnectCommand(token) {
|
|
1890
|
+
async function impersonateConnectCommand(token, options = {}) {
|
|
1741
1891
|
requireImpersonateEnabled();
|
|
1742
1892
|
const json = isJsonMode();
|
|
1893
|
+
const shouldLaunchClaude = !options.noLaunch && !json;
|
|
1743
1894
|
if (!REDEEM_TOKEN_RE.test(token)) {
|
|
1744
1895
|
const msg = "Token is not in the expected XXXX-XXXX format. Copy the full `agt impersonate connect <token>` command from the webapp.";
|
|
1745
1896
|
if (json) jsonOutput({ ok: false, error: msg });
|
|
@@ -1755,6 +1906,16 @@ async function impersonateConnectCommand(token) {
|
|
|
1755
1906
|
process.exitCode = 1;
|
|
1756
1907
|
return;
|
|
1757
1908
|
}
|
|
1909
|
+
if (!options.workdir) {
|
|
1910
|
+
const workTreeRoot = findGitWorkTreeRoot(process.cwd());
|
|
1911
|
+
if (workTreeRoot) {
|
|
1912
|
+
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.`;
|
|
1913
|
+
if (json) jsonOutput({ ok: false, error: msg });
|
|
1914
|
+
else error(msg);
|
|
1915
|
+
process.exitCode = 1;
|
|
1916
|
+
return;
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1758
1919
|
if (!json) console.log(chalk10.bold("\nAugmented \u2014 Impersonate\n"));
|
|
1759
1920
|
const spinner = ora10({
|
|
1760
1921
|
text: "Redeeming token\u2026",
|
|
@@ -1785,25 +1946,27 @@ async function impersonateConnectCommand(token) {
|
|
|
1785
1946
|
}
|
|
1786
1947
|
spinner.text = "Writing persona files\u2026";
|
|
1787
1948
|
const personaDir = ensureCodeNameDir(bundle.agent.code_name);
|
|
1788
|
-
|
|
1789
|
-
|
|
1949
|
+
writeFileSync6(
|
|
1950
|
+
join9(personaDir, "CLAUDE.md"),
|
|
1790
1951
|
bundle.artifacts["CLAUDE.md"]
|
|
1791
1952
|
);
|
|
1792
|
-
|
|
1793
|
-
|
|
1953
|
+
writeFileSync6(
|
|
1954
|
+
join9(personaDir, ".mcp.json"),
|
|
1794
1955
|
bundle.artifacts[".mcp.json"]
|
|
1795
1956
|
);
|
|
1796
1957
|
spinner.text = "Swapping persona files\u2026";
|
|
1797
|
-
const projectCwd = process.cwd();
|
|
1958
|
+
const projectCwd = options.workdir ? ensureImpersonateWorkdir(bundle.agent.code_name) : process.cwd();
|
|
1798
1959
|
const backups = {};
|
|
1799
1960
|
const swapped = [];
|
|
1961
|
+
let hookBackup;
|
|
1800
1962
|
try {
|
|
1801
1963
|
for (const file of SWAP_FILES) {
|
|
1802
|
-
const projectPath =
|
|
1803
|
-
const kind = swapInPersonaFile(projectPath,
|
|
1964
|
+
const projectPath = join9(projectCwd, file);
|
|
1965
|
+
const kind = swapInPersonaFile(projectPath, join9(personaDir, file));
|
|
1804
1966
|
backups[file] = kind;
|
|
1805
1967
|
swapped.push({ file, kind });
|
|
1806
1968
|
}
|
|
1969
|
+
hookBackup = registerIntroduceHook(projectCwd);
|
|
1807
1970
|
const manifest = {
|
|
1808
1971
|
code_name: bundle.agent.code_name,
|
|
1809
1972
|
agent_id: bundle.agent.agent_id,
|
|
@@ -1814,13 +1977,20 @@ async function impersonateConnectCommand(token) {
|
|
|
1814
1977
|
minted_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1815
1978
|
project_cwd: projectCwd,
|
|
1816
1979
|
host: host2,
|
|
1817
|
-
backups
|
|
1980
|
+
backups,
|
|
1981
|
+
hook: hookBackup
|
|
1818
1982
|
};
|
|
1819
1983
|
writeActiveManifest(manifest);
|
|
1820
1984
|
} catch (err) {
|
|
1985
|
+
if (hookBackup) {
|
|
1986
|
+
try {
|
|
1987
|
+
unregisterIntroduceHook(hookBackup);
|
|
1988
|
+
} catch {
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1821
1991
|
for (const { file, kind } of [...swapped].reverse()) {
|
|
1822
1992
|
try {
|
|
1823
|
-
restoreSwapped(
|
|
1993
|
+
restoreSwapped(join9(projectCwd, file), kind);
|
|
1824
1994
|
} catch {
|
|
1825
1995
|
}
|
|
1826
1996
|
}
|
|
@@ -1853,11 +2023,44 @@ async function impersonateConnectCommand(token) {
|
|
|
1853
2023
|
console.log(` Host: ${chalk10.dim(host2)}`);
|
|
1854
2024
|
console.log(` Swapped: ${chalk10.dim(SWAP_FILES.join(", "))}`);
|
|
1855
2025
|
console.log();
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
2026
|
+
if (!shouldLaunchClaude) {
|
|
2027
|
+
if (options.workdir) {
|
|
2028
|
+
info(`Start Claude Code in the impersonation workdir: \`cd ${projectCwd}\``);
|
|
2029
|
+
}
|
|
2030
|
+
info(
|
|
2031
|
+
"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)."
|
|
2032
|
+
);
|
|
2033
|
+
console.log();
|
|
2034
|
+
info("When done: `agt impersonate exit`");
|
|
2035
|
+
return;
|
|
2036
|
+
}
|
|
2037
|
+
info("Launching Claude Code\u2026 (use `--no-launch` next time to skip)");
|
|
2038
|
+
console.log();
|
|
2039
|
+
await new Promise((resolve2) => {
|
|
2040
|
+
const child = spawn("claude", {
|
|
2041
|
+
stdio: "inherit",
|
|
2042
|
+
cwd: projectCwd
|
|
2043
|
+
});
|
|
2044
|
+
child.on("error", (err) => {
|
|
2045
|
+
if (err.code === "ENOENT") {
|
|
2046
|
+
error(
|
|
2047
|
+
`\`claude\` binary not found on PATH. Start Claude Code yourself from ${projectCwd}, or install the CLI from claude.ai/code.`
|
|
2048
|
+
);
|
|
2049
|
+
process.exitCode = 1;
|
|
2050
|
+
} else {
|
|
2051
|
+
error(`Failed to launch Claude Code: ${err.message}`);
|
|
2052
|
+
process.exitCode = 1;
|
|
2053
|
+
}
|
|
2054
|
+
resolve2();
|
|
2055
|
+
});
|
|
2056
|
+
child.on("exit", (code, signal) => {
|
|
2057
|
+
if (code !== null && code !== 0) process.exitCode = code;
|
|
2058
|
+
if (signal) process.exitCode = 130;
|
|
2059
|
+
resolve2();
|
|
2060
|
+
});
|
|
2061
|
+
});
|
|
1859
2062
|
console.log();
|
|
1860
|
-
info("When done: `agt impersonate exit`");
|
|
2063
|
+
info("When done: `agt impersonate exit` (still active).");
|
|
1861
2064
|
}
|
|
1862
2065
|
async function impersonateCurrentCommand() {
|
|
1863
2066
|
requireImpersonateEnabled();
|
|
@@ -1936,7 +2139,7 @@ async function impersonateExitCommand() {
|
|
|
1936
2139
|
}
|
|
1937
2140
|
const restored = [];
|
|
1938
2141
|
for (const [file, kind] of Object.entries(manifest.backups)) {
|
|
1939
|
-
const projectPath =
|
|
2142
|
+
const projectPath = join9(manifest.project_cwd, file);
|
|
1940
2143
|
try {
|
|
1941
2144
|
restoreSwapped(projectPath, kind);
|
|
1942
2145
|
restored.push(file);
|
|
@@ -1945,6 +2148,14 @@ async function impersonateExitCommand() {
|
|
|
1945
2148
|
if (!json) error(`Failed to restore ${file}: ${msg}`);
|
|
1946
2149
|
}
|
|
1947
2150
|
}
|
|
2151
|
+
if (manifest.hook) {
|
|
2152
|
+
try {
|
|
2153
|
+
unregisterIntroduceHook(manifest.hook);
|
|
2154
|
+
} catch (err) {
|
|
2155
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2156
|
+
if (!json) error(`Failed to remove introduce hook: ${msg}`);
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
1948
2159
|
clearActiveManifest();
|
|
1949
2160
|
if (json) {
|
|
1950
2161
|
jsonOutput({
|
|
@@ -1966,6 +2177,37 @@ async function impersonateExitCommand() {
|
|
|
1966
2177
|
}
|
|
1967
2178
|
info("Restart Claude Code to pick up your original persona.");
|
|
1968
2179
|
}
|
|
2180
|
+
async function impersonateIntroduceCommand() {
|
|
2181
|
+
try {
|
|
2182
|
+
const manifest = readActiveManifest();
|
|
2183
|
+
if (!manifest || isExpired(manifest)) return;
|
|
2184
|
+
const cwd = manifest.project_cwd;
|
|
2185
|
+
const identity = readClaudeMdIdentity(join9(cwd, "CLAUDE.md"));
|
|
2186
|
+
const integrations = readMcpIntegrations(join9(cwd, ".mcp.json"));
|
|
2187
|
+
const intro = buildIntroduction({
|
|
2188
|
+
displayName: identity.displayName,
|
|
2189
|
+
codeName: manifest.code_name,
|
|
2190
|
+
role: identity.role,
|
|
2191
|
+
integrations
|
|
2192
|
+
});
|
|
2193
|
+
process.stdout.write(intro + "\n");
|
|
2194
|
+
} catch {
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
function readClaudeMdIdentity(path) {
|
|
2198
|
+
try {
|
|
2199
|
+
return parseIdentityFromClaudeMd(readFileSync4(path, "utf-8"));
|
|
2200
|
+
} catch {
|
|
2201
|
+
return { displayName: null, role: null };
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
function readMcpIntegrations(path) {
|
|
2205
|
+
try {
|
|
2206
|
+
return parseIntegrationsFromMcpJson(readFileSync4(path, "utf-8"));
|
|
2207
|
+
} catch {
|
|
2208
|
+
return [];
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
1969
2211
|
|
|
1970
2212
|
// src/commands/drift.ts
|
|
1971
2213
|
import chalk11 from "chalk";
|
|
@@ -1974,7 +2216,7 @@ import ora11 from "ora";
|
|
|
1974
2216
|
// ../../packages/core/dist/drift/live-state-reader.js
|
|
1975
2217
|
import { readFile } from "fs/promises";
|
|
1976
2218
|
import { createHash } from "crypto";
|
|
1977
|
-
import { join as
|
|
2219
|
+
import { join as join10 } from "path";
|
|
1978
2220
|
import JSON5 from "json5";
|
|
1979
2221
|
async function hashFile(filePath) {
|
|
1980
2222
|
try {
|
|
@@ -1998,8 +2240,8 @@ async function readLiveState(options) {
|
|
|
1998
2240
|
const toolsFile = trackedFiles.find((f) => f.includes("TOOLS")) ?? "TOOLS.md";
|
|
1999
2241
|
const [frameworkConfig, charterHash, toolsHash] = await Promise.all([
|
|
2000
2242
|
readJsonFile(options.configPath),
|
|
2001
|
-
hashFile(
|
|
2002
|
-
hashFile(
|
|
2243
|
+
hashFile(join10(options.teamDir, charterFile)),
|
|
2244
|
+
hashFile(join10(options.teamDir, toolsFile))
|
|
2003
2245
|
]);
|
|
2004
2246
|
return {
|
|
2005
2247
|
frameworkConfig,
|
|
@@ -2454,7 +2696,7 @@ async function hostDecommissionCommand(hostName) {
|
|
|
2454
2696
|
}
|
|
2455
2697
|
|
|
2456
2698
|
// src/commands/host-pair.ts
|
|
2457
|
-
import { spawn, spawnSync } from "child_process";
|
|
2699
|
+
import { spawn as spawn2, spawnSync } from "child_process";
|
|
2458
2700
|
import chalk13 from "chalk";
|
|
2459
2701
|
async function hostPairCommand(name, opts) {
|
|
2460
2702
|
const teamSlug = requireTeam();
|
|
@@ -2535,7 +2777,7 @@ async function hostPairCommand(name, opts) {
|
|
|
2535
2777
|
console.log();
|
|
2536
2778
|
console.log(chalk13.dim("Exit the shell (Ctrl+D) when Claude Code reports successful login."));
|
|
2537
2779
|
console.log();
|
|
2538
|
-
const tunnel =
|
|
2780
|
+
const tunnel = spawn2(
|
|
2539
2781
|
"aws",
|
|
2540
2782
|
[
|
|
2541
2783
|
"ssm",
|
|
@@ -2592,7 +2834,7 @@ function preflightAws() {
|
|
|
2592
2834
|
}
|
|
2593
2835
|
function runInteractive(cmd, args) {
|
|
2594
2836
|
return new Promise((resolve2) => {
|
|
2595
|
-
const child =
|
|
2837
|
+
const child = spawn2(cmd, args, { stdio: "inherit" });
|
|
2596
2838
|
child.on("exit", (code) => resolve2(code ?? 0));
|
|
2597
2839
|
child.on("error", () => resolve2(1));
|
|
2598
2840
|
});
|
|
@@ -2608,15 +2850,15 @@ function terminate(child) {
|
|
|
2608
2850
|
// src/commands/manager-watch.tsx
|
|
2609
2851
|
import { useEffect, useState, useMemo } from "react";
|
|
2610
2852
|
import { render, Box, Text, useApp, useInput } from "ink";
|
|
2611
|
-
import { existsSync as
|
|
2853
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, statSync, openSync, readSync, closeSync } from "fs";
|
|
2612
2854
|
import { homedir as homedir3 } from "os";
|
|
2613
|
-
import { join as
|
|
2855
|
+
import { join as join11 } from "path";
|
|
2614
2856
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2615
2857
|
var REFRESH_MS = 1e3;
|
|
2616
2858
|
var LOG_TAIL_LINES = 200;
|
|
2617
2859
|
var DETAIL_RECENT_LINES = 50;
|
|
2618
2860
|
function managerWatchCommand(opts = {}) {
|
|
2619
|
-
const configDir = opts.configDir ??
|
|
2861
|
+
const configDir = opts.configDir ?? join11(homedir3(), ".augmented");
|
|
2620
2862
|
const paths = getManagerPaths(configDir);
|
|
2621
2863
|
const isTty = process.stdout.isTTY === true && process.stdin.isTTY === true;
|
|
2622
2864
|
if (opts.noTui || !isTty) {
|
|
@@ -2640,15 +2882,15 @@ function managerWatchCommand(opts = {}) {
|
|
|
2640
2882
|
}
|
|
2641
2883
|
function readState(stateFile) {
|
|
2642
2884
|
try {
|
|
2643
|
-
if (!
|
|
2644
|
-
const raw =
|
|
2885
|
+
if (!existsSync5(stateFile)) return null;
|
|
2886
|
+
const raw = readFileSync5(stateFile, "utf-8");
|
|
2645
2887
|
return JSON.parse(raw);
|
|
2646
2888
|
} catch {
|
|
2647
2889
|
return null;
|
|
2648
2890
|
}
|
|
2649
2891
|
}
|
|
2650
2892
|
function tailLogFile(logFile, lines) {
|
|
2651
|
-
if (!
|
|
2893
|
+
if (!existsSync5(logFile)) return [];
|
|
2652
2894
|
try {
|
|
2653
2895
|
const fileSize = statSync(logFile).size;
|
|
2654
2896
|
if (fileSize === 0) return [];
|
|
@@ -2889,7 +3131,7 @@ function truncate(s, max) {
|
|
|
2889
3131
|
return s.length > max ? `${s.slice(0, Math.max(0, max - 1))}\u2026` : s;
|
|
2890
3132
|
}
|
|
2891
3133
|
function streamLogFile(logFile) {
|
|
2892
|
-
if (!
|
|
3134
|
+
if (!existsSync5(logFile)) {
|
|
2893
3135
|
process.stderr.write(`No manager log found at ${logFile}.
|
|
2894
3136
|
Start the manager first: agt manager start
|
|
2895
3137
|
`);
|
|
@@ -2898,7 +3140,7 @@ Start the manager first: agt manager start
|
|
|
2898
3140
|
}
|
|
2899
3141
|
let lastSize = 0;
|
|
2900
3142
|
try {
|
|
2901
|
-
const initial =
|
|
3143
|
+
const initial = readFileSync5(logFile, "utf-8");
|
|
2902
3144
|
process.stdout.write(initial);
|
|
2903
3145
|
lastSize = statSync(logFile).size;
|
|
2904
3146
|
} catch (err) {
|
|
@@ -2935,14 +3177,14 @@ Start the manager first: agt manager start
|
|
|
2935
3177
|
// src/commands/agent.ts
|
|
2936
3178
|
import chalk14 from "chalk";
|
|
2937
3179
|
import JSON52 from "json5";
|
|
2938
|
-
import { readFileSync as
|
|
2939
|
-
import { join as
|
|
3180
|
+
import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
|
|
3181
|
+
import { join as join12 } from "path";
|
|
2940
3182
|
async function agentShowCommand(codeName, opts) {
|
|
2941
3183
|
const json = isJsonMode();
|
|
2942
|
-
const unifiedDir =
|
|
2943
|
-
const legacyDir =
|
|
2944
|
-
const agentDir =
|
|
2945
|
-
const hasLocalConfig =
|
|
3184
|
+
const unifiedDir = join12(opts.configDir, codeName, "provision");
|
|
3185
|
+
const legacyDir = join12(opts.configDir, codeName, "claudecode", "provision");
|
|
3186
|
+
const agentDir = existsSync6(unifiedDir) ? unifiedDir : legacyDir;
|
|
3187
|
+
const hasLocalConfig = existsSync6(agentDir);
|
|
2946
3188
|
let apiChannels = null;
|
|
2947
3189
|
let apiAgent = null;
|
|
2948
3190
|
if (getApiKey()) {
|
|
@@ -2975,34 +3217,34 @@ async function agentShowCommand(codeName, opts) {
|
|
|
2975
3217
|
let openclawConfig = null;
|
|
2976
3218
|
let agentState = null;
|
|
2977
3219
|
if (hasLocalConfig) {
|
|
2978
|
-
const charterPath =
|
|
2979
|
-
if (
|
|
2980
|
-
const raw =
|
|
3220
|
+
const charterPath = join12(agentDir, "CHARTER.md");
|
|
3221
|
+
if (existsSync6(charterPath)) {
|
|
3222
|
+
const raw = readFileSync6(charterPath, "utf-8");
|
|
2981
3223
|
const parsed = extractFrontmatter(raw);
|
|
2982
3224
|
if (parsed.frontmatter) {
|
|
2983
3225
|
charter = parsed.frontmatter;
|
|
2984
3226
|
}
|
|
2985
3227
|
}
|
|
2986
|
-
const toolsPath =
|
|
2987
|
-
if (
|
|
2988
|
-
const raw =
|
|
3228
|
+
const toolsPath = join12(agentDir, "TOOLS.md");
|
|
3229
|
+
if (existsSync6(toolsPath)) {
|
|
3230
|
+
const raw = readFileSync6(toolsPath, "utf-8");
|
|
2989
3231
|
const parsed = extractFrontmatter(raw);
|
|
2990
3232
|
if (parsed.frontmatter) {
|
|
2991
3233
|
tools = parsed.frontmatter;
|
|
2992
3234
|
}
|
|
2993
3235
|
}
|
|
2994
|
-
const openclawPath =
|
|
2995
|
-
if (
|
|
3236
|
+
const openclawPath = join12(agentDir, "openclaw.json5");
|
|
3237
|
+
if (existsSync6(openclawPath)) {
|
|
2996
3238
|
try {
|
|
2997
|
-
const raw =
|
|
3239
|
+
const raw = readFileSync6(openclawPath, "utf-8");
|
|
2998
3240
|
openclawConfig = JSON52.parse(raw);
|
|
2999
3241
|
} catch {
|
|
3000
3242
|
}
|
|
3001
3243
|
}
|
|
3002
|
-
const statePath =
|
|
3003
|
-
if (
|
|
3244
|
+
const statePath = join12(opts.configDir, "manager-state.json");
|
|
3245
|
+
if (existsSync6(statePath)) {
|
|
3004
3246
|
try {
|
|
3005
|
-
const raw =
|
|
3247
|
+
const raw = readFileSync6(statePath, "utf-8");
|
|
3006
3248
|
const state = JSON.parse(raw);
|
|
3007
3249
|
agentState = state.agents?.find((a) => a.codeName === codeName) ?? null;
|
|
3008
3250
|
} catch {
|
|
@@ -3339,8 +3581,8 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
3339
3581
|
}
|
|
3340
3582
|
|
|
3341
3583
|
// src/commands/setup.ts
|
|
3342
|
-
import { existsSync as
|
|
3343
|
-
import { join as
|
|
3584
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, accessSync, constants as fsConstants } from "fs";
|
|
3585
|
+
import { join as join13, dirname as dirname2 } from "path";
|
|
3344
3586
|
import { homedir as homedir4 } from "os";
|
|
3345
3587
|
import chalk16 from "chalk";
|
|
3346
3588
|
import ora14 from "ora";
|
|
@@ -3348,15 +3590,15 @@ function detectShellProfile() {
|
|
|
3348
3590
|
const shell = process.env["SHELL"] ?? "";
|
|
3349
3591
|
const home = homedir4();
|
|
3350
3592
|
if (shell.includes("zsh")) {
|
|
3351
|
-
return
|
|
3593
|
+
return join13(home, ".zshrc");
|
|
3352
3594
|
}
|
|
3353
3595
|
if (shell.includes("fish")) {
|
|
3354
|
-
const fishConfig =
|
|
3596
|
+
const fishConfig = join13(home, ".config", "fish", "config.fish");
|
|
3355
3597
|
return fishConfig;
|
|
3356
3598
|
}
|
|
3357
|
-
const bashrc =
|
|
3358
|
-
if (
|
|
3359
|
-
return
|
|
3599
|
+
const bashrc = join13(home, ".bashrc");
|
|
3600
|
+
if (existsSync7(bashrc)) return bashrc;
|
|
3601
|
+
return join13(home, ".bash_profile");
|
|
3360
3602
|
}
|
|
3361
3603
|
function maybeWriteSystemWideEnv(apiUrl, apiKey, consoleUrl) {
|
|
3362
3604
|
const empty = { etcEnvironment: false, profileD: false, bashrc: false };
|
|
@@ -3382,14 +3624,14 @@ function quoteForFishShell(value) {
|
|
|
3382
3624
|
}
|
|
3383
3625
|
function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
3384
3626
|
const envPath = "/etc/environment";
|
|
3385
|
-
if (!
|
|
3627
|
+
if (!existsSync7(envPath)) return false;
|
|
3386
3628
|
try {
|
|
3387
3629
|
accessSync(envPath, fsConstants.W_OK);
|
|
3388
3630
|
} catch {
|
|
3389
3631
|
return false;
|
|
3390
3632
|
}
|
|
3391
3633
|
try {
|
|
3392
|
-
const current =
|
|
3634
|
+
const current = readFileSync7(envPath, "utf-8");
|
|
3393
3635
|
const stripped = current.split(/\r?\n/).filter((line) => !/^\s*(?:export\s+)?AGT_(?:HOST|API_KEY|CONSOLE_URL)=/.test(line)).join("\n");
|
|
3394
3636
|
const base = stripped.endsWith("\n") || stripped.length === 0 ? stripped : `${stripped}
|
|
3395
3637
|
`;
|
|
@@ -3400,7 +3642,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
|
3400
3642
|
if (consoleUrl) lines.push(`AGT_CONSOLE_URL=${quoteForEtcEnvironment(consoleUrl)}`);
|
|
3401
3643
|
const appended = `${base}${lines.join("\n")}
|
|
3402
3644
|
`;
|
|
3403
|
-
|
|
3645
|
+
writeFileSync7(envPath, appended, { mode: 420 });
|
|
3404
3646
|
return true;
|
|
3405
3647
|
} catch {
|
|
3406
3648
|
return false;
|
|
@@ -3408,7 +3650,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
|
|
|
3408
3650
|
}
|
|
3409
3651
|
function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
3410
3652
|
const profileD = "/etc/profile.d";
|
|
3411
|
-
if (!
|
|
3653
|
+
if (!existsSync7(profileD)) return false;
|
|
3412
3654
|
try {
|
|
3413
3655
|
accessSync(profileD, fsConstants.W_OK);
|
|
3414
3656
|
} catch {
|
|
@@ -3423,7 +3665,7 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
|
3423
3665
|
];
|
|
3424
3666
|
if (consoleUrl) lines.push(`export AGT_CONSOLE_URL=${quoteForPosixShell(consoleUrl)}`);
|
|
3425
3667
|
lines.push("");
|
|
3426
|
-
|
|
3668
|
+
writeFileSync7(scriptPath, lines.join("\n"), { mode: 420 });
|
|
3427
3669
|
return true;
|
|
3428
3670
|
} catch {
|
|
3429
3671
|
return false;
|
|
@@ -3431,14 +3673,14 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
|
|
|
3431
3673
|
}
|
|
3432
3674
|
function ensureBashrcSourcesProfileD() {
|
|
3433
3675
|
const bashrc = "/etc/bashrc";
|
|
3434
|
-
if (!
|
|
3676
|
+
if (!existsSync7(bashrc)) return false;
|
|
3435
3677
|
try {
|
|
3436
3678
|
accessSync(bashrc, fsConstants.W_OK);
|
|
3437
3679
|
} catch {
|
|
3438
3680
|
return false;
|
|
3439
3681
|
}
|
|
3440
3682
|
try {
|
|
3441
|
-
const current =
|
|
3683
|
+
const current = readFileSync7(bashrc, "utf-8");
|
|
3442
3684
|
const marker = "# Augmented (agt) \u2014 source system-wide AGT env";
|
|
3443
3685
|
if (current.includes(marker)) return true;
|
|
3444
3686
|
const snippet = [
|
|
@@ -3449,7 +3691,7 @@ function ensureBashrcSourcesProfileD() {
|
|
|
3449
3691
|
"fi",
|
|
3450
3692
|
""
|
|
3451
3693
|
].join("\n");
|
|
3452
|
-
|
|
3694
|
+
writeFileSync7(bashrc, current + snippet);
|
|
3453
3695
|
return true;
|
|
3454
3696
|
} catch {
|
|
3455
3697
|
return false;
|
|
@@ -3564,12 +3806,12 @@ async function setupCommand(token) {
|
|
|
3564
3806
|
);
|
|
3565
3807
|
}
|
|
3566
3808
|
const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key, consoleUrl);
|
|
3567
|
-
const profileDir =
|
|
3568
|
-
if (!
|
|
3569
|
-
|
|
3809
|
+
const profileDir = dirname2(profilePath);
|
|
3810
|
+
if (!existsSync7(profileDir)) {
|
|
3811
|
+
mkdirSync6(profileDir, { recursive: true });
|
|
3570
3812
|
}
|
|
3571
3813
|
const marker = "# Augmented (agt) host configuration";
|
|
3572
|
-
const current =
|
|
3814
|
+
const current = existsSync7(profilePath) ? readFileSync7(profilePath, "utf-8") : "";
|
|
3573
3815
|
let updated;
|
|
3574
3816
|
if (current.includes(marker)) {
|
|
3575
3817
|
updated = current.replace(
|
|
@@ -3582,7 +3824,7 @@ async function setupCommand(token) {
|
|
|
3582
3824
|
} else {
|
|
3583
3825
|
updated = current + exportLines;
|
|
3584
3826
|
}
|
|
3585
|
-
|
|
3827
|
+
writeFileSync7(profilePath, updated.endsWith("\n") ? updated : `${updated}
|
|
3586
3828
|
`);
|
|
3587
3829
|
if (!json) {
|
|
3588
3830
|
success(`Environment variables written to ${chalk16.bold(profilePath)}`);
|
|
@@ -3600,7 +3842,7 @@ async function setupCommand(token) {
|
|
|
3600
3842
|
const managerSpinner = ora14({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
3601
3843
|
managerSpinner.start();
|
|
3602
3844
|
try {
|
|
3603
|
-
const configDir =
|
|
3845
|
+
const configDir = join13(homedir4(), ".augmented");
|
|
3604
3846
|
const { pid } = startWatchdog({ intervalMs: 1e4, configDir, detached: true });
|
|
3605
3847
|
managerSpinner.succeed(`Manager started (PID ${pid})`);
|
|
3606
3848
|
} catch (err) {
|
|
@@ -3932,7 +4174,7 @@ function getAcpAgent(name) {
|
|
|
3932
4174
|
}
|
|
3933
4175
|
|
|
3934
4176
|
// ../../packages/core/dist/acp/client.js
|
|
3935
|
-
import { spawn as
|
|
4177
|
+
import { spawn as spawn3 } from "child_process";
|
|
3936
4178
|
function resolveAgentCommand(agentName) {
|
|
3937
4179
|
const adapter = getAcpAgent(agentName);
|
|
3938
4180
|
if (adapter) {
|
|
@@ -3948,7 +4190,7 @@ function resolveAgentCommand(agentName) {
|
|
|
3948
4190
|
}
|
|
3949
4191
|
async function runAcpx(args, options = {}) {
|
|
3950
4192
|
return new Promise((resolve2) => {
|
|
3951
|
-
const child =
|
|
4193
|
+
const child = spawn3("acpx", args, {
|
|
3952
4194
|
cwd: options.cwd,
|
|
3953
4195
|
stdio: ["pipe", "pipe", "pipe"],
|
|
3954
4196
|
env: { ...process.env }
|
|
@@ -4148,10 +4390,10 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
4148
4390
|
|
|
4149
4391
|
// src/commands/update.ts
|
|
4150
4392
|
import { execFileSync, execSync } from "child_process";
|
|
4151
|
-
import { existsSync as
|
|
4393
|
+
import { existsSync as existsSync8, realpathSync as realpathSync2 } from "fs";
|
|
4152
4394
|
import chalk18 from "chalk";
|
|
4153
4395
|
import ora16 from "ora";
|
|
4154
|
-
var cliVersion = true ? "0.
|
|
4396
|
+
var cliVersion = true ? "0.27.0-test.4" : "dev";
|
|
4155
4397
|
async function fetchLatestVersion() {
|
|
4156
4398
|
const host2 = getHost();
|
|
4157
4399
|
if (!host2) return null;
|
|
@@ -4171,9 +4413,9 @@ async function fetchLatestVersion() {
|
|
|
4171
4413
|
}
|
|
4172
4414
|
function isNewerVersion(local, remote) {
|
|
4173
4415
|
if (local === "dev") return false;
|
|
4174
|
-
const
|
|
4175
|
-
const lParts =
|
|
4176
|
-
const rParts =
|
|
4416
|
+
const parse2 = (v) => v.replace(/^v/, "").split(".").map(Number);
|
|
4417
|
+
const lParts = parse2(local);
|
|
4418
|
+
const rParts = parse2(remote);
|
|
4177
4419
|
const lMaj = lParts[0] ?? 0, lMin = lParts[1] ?? 0, lPat = lParts[2] ?? 0;
|
|
4178
4420
|
const rMaj = rParts[0] ?? 0, rMin = rParts[1] ?? 0, rPat = rParts[2] ?? 0;
|
|
4179
4421
|
if (rMaj !== lMaj) return rMaj > lMaj;
|
|
@@ -4255,7 +4497,7 @@ function performUpdate(version) {
|
|
|
4255
4497
|
function detectBrewOwner() {
|
|
4256
4498
|
for (const prefix of ["/home/linuxbrew/.linuxbrew", "/opt/homebrew", "/usr/local"]) {
|
|
4257
4499
|
const cellar = `${prefix}/Cellar`;
|
|
4258
|
-
if (!
|
|
4500
|
+
if (!existsSync8(cellar)) continue;
|
|
4259
4501
|
try {
|
|
4260
4502
|
return execSync(`stat -c %U "${cellar}" 2>/dev/null || stat -f %Su "${cellar}"`, { encoding: "utf-8" }).trim() || null;
|
|
4261
4503
|
} catch {
|
|
@@ -4683,7 +4925,7 @@ function handleError(err) {
|
|
|
4683
4925
|
}
|
|
4684
4926
|
|
|
4685
4927
|
// src/bin/agt.ts
|
|
4686
|
-
var cliVersion2 = true ? "0.
|
|
4928
|
+
var cliVersion2 = true ? "0.27.0-test.4" : "dev";
|
|
4687
4929
|
var program = new Command();
|
|
4688
4930
|
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");
|
|
4689
4931
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -4702,10 +4944,27 @@ var impersonate = program.command("impersonate").description(
|
|
|
4702
4944
|
"Operate as a managed agent locally (experimental, gated by AGT_IMPERSONATE_ENABLED)"
|
|
4703
4945
|
);
|
|
4704
4946
|
impersonate.command("connect <token>").description(
|
|
4705
|
-
"Redeem a XXXX-XXXX token from the webapp, render the agent's CLAUDE.md + .mcp.json,
|
|
4706
|
-
).
|
|
4947
|
+
"Redeem a XXXX-XXXX token from the webapp, render the agent's CLAUDE.md + .mcp.json, swap them into the current project, and launch Claude Code (use --no-launch to skip the launch)"
|
|
4948
|
+
).option(
|
|
4949
|
+
"--no-launch",
|
|
4950
|
+
"Skip launching Claude Code after the swap (operator manages their own session)"
|
|
4951
|
+
).option(
|
|
4952
|
+
"--workdir",
|
|
4953
|
+
"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"
|
|
4954
|
+
).action(
|
|
4955
|
+
(token, opts) => (
|
|
4956
|
+
// Commander negates --no-FLAG into opts.flag, so --no-launch arrives
|
|
4957
|
+
// as opts.launch === false. Translate to the command's noLaunch
|
|
4958
|
+
// option, defaulting to launching when the flag isn't passed.
|
|
4959
|
+
impersonateConnectCommand(token, {
|
|
4960
|
+
noLaunch: opts.launch === false,
|
|
4961
|
+
workdir: opts.workdir === true
|
|
4962
|
+
})
|
|
4963
|
+
)
|
|
4964
|
+
);
|
|
4707
4965
|
impersonate.command("current").description('Print the active impersonation (or "none")').action(impersonateCurrentCommand);
|
|
4708
4966
|
impersonate.command("exit").description("End the active impersonation, restore project files, and notify the server").action(impersonateExitCommand);
|
|
4967
|
+
impersonate.command("introduce", { hidden: true }).description("Print the impersonated agent's self-introduction (SessionStart hook target)").action(impersonateIntroduceCommand);
|
|
4709
4968
|
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);
|
|
4710
4969
|
program.command("lint").argument("[path]", "Path to agent directory (default: all agents in .augmented/)").description("Lint CHARTER.md and TOOLS.md files").action(lintCommand);
|
|
4711
4970
|
var channels = program.command("channels").description("Manage and inspect channel configuration");
|
|
@@ -4738,16 +4997,16 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
|
|
|
4738
4997
|
})
|
|
4739
4998
|
);
|
|
4740
4999
|
var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
|
|
4741
|
-
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",
|
|
4742
|
-
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files",
|
|
4743
|
-
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files",
|
|
4744
|
-
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",
|
|
4745
|
-
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",
|
|
5000
|
+
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);
|
|
5001
|
+
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join14(homedir5(), ".augmented")).action(managerStopCommand);
|
|
5002
|
+
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);
|
|
5003
|
+
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);
|
|
5004
|
+
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);
|
|
4746
5005
|
manager.command("uninstall").description("Remove the OS-level supervisor (launchctl unload + delete plist on macOS). Idempotent.").action(managerUninstallCommand);
|
|
4747
5006
|
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);
|
|
4748
5007
|
manager.command("uninstall-system-unit").description("Remove the system-level systemd unit (Linux, root). Idempotent. (ENG-4706)").action(managerUninstallSystemUnitCommand);
|
|
4749
5008
|
var agent = program.command("agent").description("Inspect and manage agents");
|
|
4750
|
-
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory",
|
|
5009
|
+
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);
|
|
4751
5010
|
var kanban = program.command("kanban").description("Manage agent kanban boards");
|
|
4752
5011
|
kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
|
|
4753
5012
|
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);
|