@integrity-labs/agt-cli 0.27.7-test.6 → 0.27.8-test.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ApiError,
4
- DEFAULT_AGT_HOST,
4
+ PROD_AGT_HOST,
5
5
  api,
6
6
  error,
7
7
  exchangeApiKey,
@@ -27,7 +27,7 @@ import {
27
27
  success,
28
28
  table,
29
29
  warn
30
- } from "../chunk-AACMX6LE.js";
30
+ } from "../chunk-2E5OABKX.js";
31
31
  import {
32
32
  CHANNEL_REGISTRY,
33
33
  DEPLOYMENT_TEMPLATES,
@@ -53,7 +53,7 @@ import {
53
53
  renderTemplate,
54
54
  resolveChannels,
55
55
  serializeManifestForSlackCli
56
- } from "../chunk-YSBGIXJG.js";
56
+ } from "../chunk-6HFXSNNY.js";
57
57
 
58
58
  // src/bin/agt.ts
59
59
  import { join as join15 } from "path";
@@ -1557,8 +1557,9 @@ async function provisionCommand(codeName, options) {
1557
1557
  import chalk10 from "chalk";
1558
1558
  import ora10 from "ora";
1559
1559
  import { spawn } from "child_process";
1560
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync7 } from "fs";
1561
- import { join as join10 } from "path";
1560
+ import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync7 } from "fs";
1561
+ import { delimiter, dirname as dirname3, join as join10 } from "path";
1562
+ import { fileURLToPath as fileURLToPath2 } from "url";
1562
1563
 
1563
1564
  // src/lib/impersonate-flag.ts
1564
1565
  var ENV_VAR = "AGT_IMPERSONATE_ENABLED";
@@ -1996,12 +1997,73 @@ function buildIntroduction(input4) {
1996
1997
  const lines = [`I'm ${spokenName}${codeSuffix}${roleClause}.`, ""];
1997
1998
  if (integrations.length > 0) {
1998
1999
  lines.push(`Connected integrations: ${integrations.join(", ")}.`);
2000
+ lines.push("");
2001
+ lines.push(
2002
+ "If the operator asks what you can do, call each MCP server's `tools/list` and report the actual tool inventory. Do not narrate capabilities from CHARTER.md \u2014 it describes intent, not runtime state. Tools that fail to enumerate (server failed to spawn, env missing, etc.) should be reported as such, not silently omitted."
2003
+ );
1999
2004
  } else {
2000
2005
  lines.push("No integrations are connected.");
2001
2006
  }
2002
2007
  return lines.join("\n");
2003
2008
  }
2004
2009
 
2010
+ // src/lib/impersonate-mcp-rewrite.ts
2011
+ var SERVER_HOME_MCP_PATH_RE = /^\/home\/[^/]+\/\.augmented\/_mcp\/([^/]+)$/;
2012
+ function rewriteMcpJsonForImpersonation(mcpJson, ctx) {
2013
+ const parsed = JSON.parse(mcpJson);
2014
+ if (!isPlainObject(parsed)) {
2015
+ throw new Error(
2016
+ `rewriteMcpJsonForImpersonation: expected an object at the JSON root, got ${typeof parsed}`
2017
+ );
2018
+ }
2019
+ const servers = parsed["mcpServers"];
2020
+ if (!isPlainObject(servers)) {
2021
+ throw new Error(
2022
+ "rewriteMcpJsonForImpersonation: expected an object-typed `mcpServers` field"
2023
+ );
2024
+ }
2025
+ const rewrittenServers = {};
2026
+ for (const [serverName, raw] of Object.entries(servers)) {
2027
+ rewrittenServers[serverName] = rewriteServerEntry(raw, ctx);
2028
+ }
2029
+ const out = { ...parsed, mcpServers: rewrittenServers };
2030
+ return JSON.stringify(out, null, 2);
2031
+ }
2032
+ function rewriteServerEntry(raw, ctx) {
2033
+ if (!isPlainObject(raw)) return raw;
2034
+ let args = raw["args"];
2035
+ if (Array.isArray(args)) {
2036
+ args = args.map((arg) => {
2037
+ if (typeof arg !== "string") return arg;
2038
+ const m = SERVER_HOME_MCP_PATH_RE.exec(arg);
2039
+ if (!m) return arg;
2040
+ return `${ctx.cliMcpBundleDir}/${m[1]}`;
2041
+ });
2042
+ }
2043
+ const env = isPlainObject(raw["env"]) ? { ...raw["env"] } : {};
2044
+ fillIfEmpty(env, "AGT_HOST", ctx.apiHost);
2045
+ fillIfEmpty(env, "AGT_API_KEY", ctx.impersonationToken);
2046
+ fillIfEmpty(env, "HOME", ctx.operatorHome);
2047
+ fillIfEmpty(env, "AGT_AGENT_ID", ctx.agentId);
2048
+ fillIfEmpty(env, "AGT_AGENT_CODE_NAME", ctx.agentCodeName);
2049
+ if ("PATH" in env) {
2050
+ env["PATH"] = ctx.operatorPath;
2051
+ }
2052
+ if (env["AGT_RUN_ID"] === "${AGT_RUN_ID}") {
2053
+ delete env["AGT_RUN_ID"];
2054
+ }
2055
+ return { ...raw, args, env };
2056
+ }
2057
+ function fillIfEmpty(env, key, value) {
2058
+ const current = env[key];
2059
+ if (typeof current !== "string" || current.length === 0) {
2060
+ env[key] = value;
2061
+ }
2062
+ }
2063
+ function isPlainObject(v) {
2064
+ return typeof v === "object" && v !== null && !Array.isArray(v);
2065
+ }
2066
+
2005
2067
  // src/commands/impersonate.ts
2006
2068
  var SWAP_FILES = ["CLAUDE.md", ".mcp.json"];
2007
2069
  var AGENT_IMPERSONATION_HEADER = "X-Agent-Impersonation";
@@ -2041,7 +2103,7 @@ async function impersonateConnectCommand(token, options = {}) {
2041
2103
  isSilent: json
2042
2104
  });
2043
2105
  spinner.start();
2044
- const host2 = (options.apiHost ?? DEFAULT_AGT_HOST).replace(/\/+$/, "");
2106
+ const host2 = (options.apiHost ?? PROD_AGT_HOST).replace(/\/+$/, "");
2045
2107
  let bundle;
2046
2108
  try {
2047
2109
  const res = await fetch(`${host2}/impersonate/agent/redeem`, {
@@ -2071,7 +2133,15 @@ async function impersonateConnectCommand(token, options = {}) {
2071
2133
  );
2072
2134
  writeFileSync7(
2073
2135
  join10(personaDir, ".mcp.json"),
2074
- bundle.artifacts[".mcp.json"]
2136
+ rewriteMcpJsonForImpersonation(bundle.artifacts[".mcp.json"], {
2137
+ operatorHome: process.env.HOME ?? "",
2138
+ operatorPath: resolveOperatorPath(),
2139
+ cliMcpBundleDir: resolveCliMcpBundleDir(),
2140
+ impersonationToken: bundle.token,
2141
+ apiHost: host2,
2142
+ agentId: bundle.agent.agent_id,
2143
+ agentCodeName: bundle.agent.code_name
2144
+ })
2075
2145
  );
2076
2146
  spinner.text = "Swapping persona files\u2026";
2077
2147
  const projectCwd = options.workdir ? ensureImpersonateWorkdir(bundle.agent.code_name) : process.cwd();
@@ -2353,6 +2423,26 @@ function readMcpIntegrations(path) {
2353
2423
  return [];
2354
2424
  }
2355
2425
  }
2426
+ function resolveCliMcpBundleDir() {
2427
+ const moduleDir = dirname3(fileURLToPath2(import.meta.url));
2428
+ const candidates = [
2429
+ join10(moduleDir, "mcp"),
2430
+ join10(moduleDir, "..", "mcp"),
2431
+ join10(moduleDir, "..", "..", "mcp")
2432
+ ];
2433
+ for (const candidate of candidates) {
2434
+ if (existsSync6(join10(candidate, "index.js"))) return candidate;
2435
+ }
2436
+ return candidates[candidates.length - 1];
2437
+ }
2438
+ function resolveOperatorPath(execPath = process.execPath, inheritedPath = process.env.PATH ?? "") {
2439
+ const nodeBinDir = dirname3(execPath);
2440
+ const segments = inheritedPath.split(delimiter).filter((s) => s.length > 0);
2441
+ if (!segments.includes(nodeBinDir)) {
2442
+ segments.unshift(nodeBinDir);
2443
+ }
2444
+ return segments.join(delimiter);
2445
+ }
2356
2446
  function buildImpersonateClaudeLaunch(projectCwd, inheritEnv = process.env, agentId = null) {
2357
2447
  const env = {
2358
2448
  ...inheritEnv,
@@ -3012,7 +3102,7 @@ function terminate(child) {
3012
3102
  // src/commands/manager-watch.tsx
3013
3103
  import { useEffect, useState, useMemo } from "react";
3014
3104
  import { render, Box, Text, useApp, useInput } from "ink";
3015
- import { existsSync as existsSync6, readFileSync as readFileSync6, statSync, openSync, readSync, closeSync } from "fs";
3105
+ import { existsSync as existsSync7, readFileSync as readFileSync6, statSync, openSync, readSync, closeSync } from "fs";
3016
3106
  import { homedir as homedir4 } from "os";
3017
3107
  import { join as join12 } from "path";
3018
3108
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -3044,7 +3134,7 @@ function managerWatchCommand(opts = {}) {
3044
3134
  }
3045
3135
  function readState(stateFile) {
3046
3136
  try {
3047
- if (!existsSync6(stateFile)) return null;
3137
+ if (!existsSync7(stateFile)) return null;
3048
3138
  const raw = readFileSync6(stateFile, "utf-8");
3049
3139
  return JSON.parse(raw);
3050
3140
  } catch {
@@ -3052,7 +3142,7 @@ function readState(stateFile) {
3052
3142
  }
3053
3143
  }
3054
3144
  function tailLogFile(logFile, lines) {
3055
- if (!existsSync6(logFile)) return [];
3145
+ if (!existsSync7(logFile)) return [];
3056
3146
  try {
3057
3147
  const fileSize = statSync(logFile).size;
3058
3148
  if (fileSize === 0) return [];
@@ -3293,7 +3383,7 @@ function truncate(s, max) {
3293
3383
  return s.length > max ? `${s.slice(0, Math.max(0, max - 1))}\u2026` : s;
3294
3384
  }
3295
3385
  function streamLogFile(logFile) {
3296
- if (!existsSync6(logFile)) {
3386
+ if (!existsSync7(logFile)) {
3297
3387
  process.stderr.write(`No manager log found at ${logFile}.
3298
3388
  Start the manager first: agt manager start
3299
3389
  `);
@@ -3339,14 +3429,14 @@ Start the manager first: agt manager start
3339
3429
  // src/commands/agent.ts
3340
3430
  import chalk14 from "chalk";
3341
3431
  import JSON52 from "json5";
3342
- import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
3432
+ import { readFileSync as readFileSync7, existsSync as existsSync8 } from "fs";
3343
3433
  import { join as join13 } from "path";
3344
3434
  async function agentShowCommand(codeName, opts) {
3345
3435
  const json = isJsonMode();
3346
3436
  const unifiedDir = join13(opts.configDir, codeName, "provision");
3347
3437
  const legacyDir = join13(opts.configDir, codeName, "claudecode", "provision");
3348
- const agentDir = existsSync7(unifiedDir) ? unifiedDir : legacyDir;
3349
- const hasLocalConfig = existsSync7(agentDir);
3438
+ const agentDir = existsSync8(unifiedDir) ? unifiedDir : legacyDir;
3439
+ const hasLocalConfig = existsSync8(agentDir);
3350
3440
  let apiChannels = null;
3351
3441
  let apiAgent = null;
3352
3442
  if (getApiKey()) {
@@ -3380,7 +3470,7 @@ async function agentShowCommand(codeName, opts) {
3380
3470
  let agentState = null;
3381
3471
  if (hasLocalConfig) {
3382
3472
  const charterPath = join13(agentDir, "CHARTER.md");
3383
- if (existsSync7(charterPath)) {
3473
+ if (existsSync8(charterPath)) {
3384
3474
  const raw = readFileSync7(charterPath, "utf-8");
3385
3475
  const parsed = extractFrontmatter(raw);
3386
3476
  if (parsed.frontmatter) {
@@ -3388,7 +3478,7 @@ async function agentShowCommand(codeName, opts) {
3388
3478
  }
3389
3479
  }
3390
3480
  const toolsPath = join13(agentDir, "TOOLS.md");
3391
- if (existsSync7(toolsPath)) {
3481
+ if (existsSync8(toolsPath)) {
3392
3482
  const raw = readFileSync7(toolsPath, "utf-8");
3393
3483
  const parsed = extractFrontmatter(raw);
3394
3484
  if (parsed.frontmatter) {
@@ -3396,7 +3486,7 @@ async function agentShowCommand(codeName, opts) {
3396
3486
  }
3397
3487
  }
3398
3488
  const openclawPath = join13(agentDir, "openclaw.json5");
3399
- if (existsSync7(openclawPath)) {
3489
+ if (existsSync8(openclawPath)) {
3400
3490
  try {
3401
3491
  const raw = readFileSync7(openclawPath, "utf-8");
3402
3492
  openclawConfig = JSON52.parse(raw);
@@ -3404,7 +3494,7 @@ async function agentShowCommand(codeName, opts) {
3404
3494
  }
3405
3495
  }
3406
3496
  const statePath = join13(opts.configDir, "manager-state.json");
3407
- if (existsSync7(statePath)) {
3497
+ if (existsSync8(statePath)) {
3408
3498
  try {
3409
3499
  const raw = readFileSync7(statePath, "utf-8");
3410
3500
  const state = JSON.parse(raw);
@@ -3743,8 +3833,8 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
3743
3833
  }
3744
3834
 
3745
3835
  // src/commands/setup.ts
3746
- import { existsSync as existsSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, accessSync, constants as fsConstants } from "fs";
3747
- import { join as join14, dirname as dirname3 } from "path";
3836
+ import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, accessSync, constants as fsConstants } from "fs";
3837
+ import { join as join14, dirname as dirname4 } from "path";
3748
3838
  import { homedir as homedir5 } from "os";
3749
3839
  import chalk16 from "chalk";
3750
3840
  import ora14 from "ora";
@@ -3759,7 +3849,7 @@ function detectShellProfile() {
3759
3849
  return fishConfig;
3760
3850
  }
3761
3851
  const bashrc = join14(home, ".bashrc");
3762
- if (existsSync8(bashrc)) return bashrc;
3852
+ if (existsSync9(bashrc)) return bashrc;
3763
3853
  return join14(home, ".bash_profile");
3764
3854
  }
3765
3855
  function maybeWriteSystemWideEnv(apiUrl, apiKey, consoleUrl) {
@@ -3786,7 +3876,7 @@ function quoteForFishShell(value) {
3786
3876
  }
3787
3877
  function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
3788
3878
  const envPath = "/etc/environment";
3789
- if (!existsSync8(envPath)) return false;
3879
+ if (!existsSync9(envPath)) return false;
3790
3880
  try {
3791
3881
  accessSync(envPath, fsConstants.W_OK);
3792
3882
  } catch {
@@ -3812,7 +3902,7 @@ function writeEtcEnvironment(apiUrl, apiKey, consoleUrl) {
3812
3902
  }
3813
3903
  function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
3814
3904
  const profileD = "/etc/profile.d";
3815
- if (!existsSync8(profileD)) return false;
3905
+ if (!existsSync9(profileD)) return false;
3816
3906
  try {
3817
3907
  accessSync(profileD, fsConstants.W_OK);
3818
3908
  } catch {
@@ -3835,7 +3925,7 @@ function writeProfileDScript(apiUrl, apiKey, consoleUrl) {
3835
3925
  }
3836
3926
  function ensureBashrcSourcesProfileD() {
3837
3927
  const bashrc = "/etc/bashrc";
3838
- if (!existsSync8(bashrc)) return false;
3928
+ if (!existsSync9(bashrc)) return false;
3839
3929
  try {
3840
3930
  accessSync(bashrc, fsConstants.W_OK);
3841
3931
  } catch {
@@ -3881,7 +3971,7 @@ function buildExportLines(shell, apiUrl, apiKey, consoleUrl) {
3881
3971
  lines.push("");
3882
3972
  return lines.join("\n");
3883
3973
  }
3884
- async function setupCommand(token) {
3974
+ async function setupCommand(token, options = {}) {
3885
3975
  const json = isJsonMode();
3886
3976
  const shortTokenPattern = /^[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4}$/i;
3887
3977
  const legacyTokenPattern = /^prov_[a-f0-9]{64}$/i;
@@ -3896,11 +3986,24 @@ async function setupCommand(token) {
3896
3986
  return;
3897
3987
  }
3898
3988
  const normalizedToken = shortTokenPattern.test(token) ? token.toUpperCase() : token.toLowerCase();
3899
- let apiUrl = process.env["AGT_HOST"];
3989
+ const apiHostFlag = options.apiHost?.trim();
3990
+ const envHost = process.env["AGT_HOST"]?.trim();
3991
+ const apiUrl = apiHostFlag || envHost;
3900
3992
  if (!apiUrl) {
3901
- apiUrl = "https://api.augmented.team";
3902
- if (!json) {
3903
- info(`No AGT_HOST set \u2014 using default: ${chalk16.bold(apiUrl)}`);
3993
+ const msg = "Cannot determine API host for token exchange. Pass --api-host <url> or set AGT_HOST before running `agt setup`.\n Production: --api-host https://api.augmented.team\n Non-prod stage: --api-host https://<stage>.api.staging.augmented.team\n Local development: --api-host http://api.agt.localhost:1355";
3994
+ if (json) {
3995
+ jsonOutput({ ok: false, error: msg });
3996
+ } else {
3997
+ error(msg);
3998
+ }
3999
+ process.exitCode = 1;
4000
+ return;
4001
+ }
4002
+ if (!json) {
4003
+ if (apiHostFlag) {
4004
+ info(`Exchanging token against ${chalk16.bold(apiUrl)} (from --api-host)`);
4005
+ } else {
4006
+ info(`Exchanging token against ${chalk16.bold(apiUrl)} (from AGT_HOST)`);
3904
4007
  }
3905
4008
  }
3906
4009
  const spinner = ora14({ text: "Exchanging provisioning token\u2026", isSilent: json });
@@ -3968,12 +4071,12 @@ async function setupCommand(token) {
3968
4071
  );
3969
4072
  }
3970
4073
  const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key, consoleUrl);
3971
- const profileDir = dirname3(profilePath);
3972
- if (!existsSync8(profileDir)) {
4074
+ const profileDir = dirname4(profilePath);
4075
+ if (!existsSync9(profileDir)) {
3973
4076
  mkdirSync7(profileDir, { recursive: true });
3974
4077
  }
3975
4078
  const marker = "# Augmented (agt) host configuration";
3976
- const current = existsSync8(profilePath) ? readFileSync8(profilePath, "utf-8") : "";
4079
+ const current = existsSync9(profilePath) ? readFileSync8(profilePath, "utf-8") : "";
3977
4080
  let updated;
3978
4081
  if (current.includes(marker)) {
3979
4082
  updated = current.replace(
@@ -4552,10 +4655,10 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
4552
4655
 
4553
4656
  // src/commands/update.ts
4554
4657
  import { execFileSync, execSync } from "child_process";
4555
- import { existsSync as existsSync9, realpathSync as realpathSync2 } from "fs";
4658
+ import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4556
4659
  import chalk18 from "chalk";
4557
4660
  import ora16 from "ora";
4558
- var cliVersion = true ? "0.27.7-test.6" : "dev";
4661
+ var cliVersion = true ? "0.27.8-test.10" : "dev";
4559
4662
  async function fetchLatestVersion() {
4560
4663
  const host2 = getHost();
4561
4664
  if (!host2) return null;
@@ -4659,7 +4762,7 @@ function performUpdate(version) {
4659
4762
  function detectBrewOwner() {
4660
4763
  for (const prefix of ["/home/linuxbrew/.linuxbrew", "/opt/homebrew", "/usr/local"]) {
4661
4764
  const cellar = `${prefix}/Cellar`;
4662
- if (!existsSync9(cellar)) continue;
4765
+ if (!existsSync10(cellar)) continue;
4663
4766
  try {
4664
4767
  return execSync(`stat -c %U "${cellar}" 2>/dev/null || stat -f %Su "${cellar}"`, { encoding: "utf-8" }).trim() || null;
4665
4768
  } catch {
@@ -5087,7 +5190,7 @@ function handleError(err) {
5087
5190
  }
5088
5191
 
5089
5192
  // src/bin/agt.ts
5090
- var cliVersion2 = true ? "0.27.7-test.6" : "dev";
5193
+ var cliVersion2 = true ? "0.27.8-test.10" : "dev";
5091
5194
  var program = new Command();
5092
5195
  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");
5093
5196
  program.hook("preAction", (thisCommand) => {
@@ -5097,7 +5200,13 @@ program.hook("preAction", (thisCommand) => {
5097
5200
  }
5098
5201
  });
5099
5202
  program.command("whoami").description("Show the authenticated host, team, and user from AGT_API_KEY").action(whoamiCommand);
5100
- program.command("setup <token>").description("One-command host setup: exchange provisioning token, configure env vars, verify, and start manager").action(setupCommand);
5203
+ program.command("setup <token>").description("One-command host setup: exchange provisioning token, configure env vars, verify, and start manager").option(
5204
+ "--api-host <url>",
5205
+ // ENG-5831: required when AGT_HOST is not set in the shell — the setup
5206
+ // command no longer silently defaults to prod. Mirrors `agt impersonate
5207
+ // connect --api-host` (ENG-5773).
5208
+ "API host to exchange the provisioning token against. Takes precedence over AGT_HOST. Required when AGT_HOST is unset (e.g. https://test.api.staging.augmented.team for the test stage; https://api.augmented.team for prod)."
5209
+ ).action(setupCommand);
5101
5210
  var team = program.command("team").description("Manage teams");
5102
5211
  team.command("list").description("List teams you belong to").action(teamListCommand);
5103
5212
  team.command("create <name>").description("Create a new team and set it as active").action(teamCreateCommand);