@integrity-labs/agt-cli 0.28.951 → 0.28.953

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
@@ -40,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-5BEWHNQN.js";
43
+ } from "../chunk-DNJDTNWX.js";
44
44
  import {
45
45
  getProjectDir,
46
46
  isSessionResumeDisabled,
@@ -5471,7 +5471,7 @@ import { execFileSync, execSync } from "child_process";
5471
5471
  import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
5472
5472
  import chalk18 from "chalk";
5473
5473
  import ora16 from "ora";
5474
- var cliVersion = true ? "0.28.951" : "dev";
5474
+ var cliVersion = true ? "0.28.953" : "dev";
5475
5475
  async function fetchLatestVersion() {
5476
5476
  const host2 = getHost();
5477
5477
  if (!host2) return null;
@@ -6731,7 +6731,7 @@ function handleError(err) {
6731
6731
  }
6732
6732
 
6733
6733
  // src/bin/agt.ts
6734
- var cliVersion2 = true ? "0.28.951" : "dev";
6734
+ var cliVersion2 = true ? "0.28.953" : "dev";
6735
6735
  var program = new Command();
6736
6736
  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");
6737
6737
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -6967,7 +6967,7 @@ function exchangeFailureKind(err) {
6967
6967
  }
6968
6968
 
6969
6969
  // src/lib/api-client.ts
6970
- var agtCliVersion = true ? "0.28.951" : "dev";
6970
+ var agtCliVersion = true ? "0.28.953" : "dev";
6971
6971
  var lastConfigHash = null;
6972
6972
  function setConfigHash(hash) {
6973
6973
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -11666,4 +11666,4 @@ export {
11666
11666
  managerInstallSystemUnitCommand,
11667
11667
  managerUninstallSystemUnitCommand
11668
11668
  };
11669
- //# sourceMappingURL=chunk-5BEWHNQN.js.map
11669
+ //# sourceMappingURL=chunk-DNJDTNWX.js.map
@@ -63,7 +63,7 @@ import {
63
63
  safeWriteJsonAtomic,
64
64
  setConfigHash,
65
65
  tripClass
66
- } from "../chunk-5BEWHNQN.js";
66
+ } from "../chunk-DNJDTNWX.js";
67
67
  import {
68
68
  getProjectDir as getProjectDir2,
69
69
  getReadyTasks,
@@ -13943,7 +13943,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13943
13943
  var lastVersionCheckAt = 0;
13944
13944
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13945
13945
  var lastResponsivenessProbeAt = 0;
13946
- var agtCliVersion = true ? "0.28.951" : "dev";
13946
+ var agtCliVersion = true ? "0.28.953" : "dev";
13947
13947
  function resolveBrewPath(execFileSync2) {
13948
13948
  try {
13949
13949
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -21546,8 +21546,8 @@ var checkActionStatusSchema = strictObject({
21546
21546
  });
21547
21547
  var requestSsmRunSchema = strictObject({
21548
21548
  target_agent_id: external_exports.string().min(1).max(64).describe("UUID of the customer agent whose host to run the diagnostic on."),
21549
- command: external_exports.enum(["host_health", "manager_status", "manager_journal", "process_list", "agent_dir"]).describe(
21550
- "The allowlisted, READ-ONLY diagnostic to run (closed set \u2014 no free-form shell). host_health = uptime + df -h + free -m (is the box wedged / out of disk / out of memory?); manager_status = systemctl status agt-manager.service (is the manager daemon up?); manager_journal = journalctl -u agt-manager.service -n 200 (recent systemd-captured manager output); process_list = ps (pid/ppid/user/etime/rss/comm, no argv/env) filtered to claude + agt-manager; agent_dir = ls -la ~/.augmented/<code_name>/ (file NAMES only \u2014 stuck markers, state files; never contents). For file CONTENTS use debug_tail_logs (it covers manager.log/pane.log/channel-stderr/manager-state.json)."
21549
+ command: external_exports.enum(["host_health", "manager_status", "manager_journal", "process_list", "agent_dir", "rpm_verify"]).describe(
21550
+ "The allowlisted, READ-ONLY diagnostic to run (closed set \u2014 no free-form shell). host_health = uptime + df -h + free -m (is the box wedged / out of disk / out of memory?); manager_status = systemctl status agt-manager.service (is the manager daemon up?); manager_journal = journalctl -u agt-manager.service -n 200 (recent systemd-captured manager output); process_list = ps (pid/ppid/user/etime/rss/comm, no argv/env) filtered to claude + agt-manager; agent_dir = ls -la ~/.augmented/<code_name>/ (file NAMES only \u2014 stuck markers, state files; never contents). rpm_verify = rpm -Va --nofiledigest --noscripts filtered to 'missing' (no package %verifyscript is executed; which files rpm OWNS and cannot find, on the HOST filesystem - the ENG-8637 deleted-under-the-package-manager census; lists paths, never contents). For file CONTENTS use debug_tail_logs (it covers manager.log/pane.log/channel-stderr/manager-state.json)."
21551
21551
  ),
21552
21552
  reason: external_exports.string().min(1).max(2e3).describe("Why this diagnostic is needed \u2014 shown verbatim to the human approver. Be specific.")
21553
21553
  });
@@ -13880,6 +13880,39 @@ import { homedir as homedir3 } from "os";
13880
13880
  import { join as join7, resolve as resolvePath2 } from "path";
13881
13881
  import { basename } from "path";
13882
13882
 
13883
+ // ../core/dist/channels/msteams-api.js
13884
+ var MsTeamsApiError = class extends Error {
13885
+ status;
13886
+ aadError;
13887
+ constructor(message, status, aadError) {
13888
+ super(message);
13889
+ this.status = status;
13890
+ this.aadError = aadError;
13891
+ this.name = "MsTeamsApiError";
13892
+ }
13893
+ };
13894
+ var joinUrl = (base, path) => `${base.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
13895
+ var ALLOWED_SERVICE_URL_HOSTS = /* @__PURE__ */ new Set(["smba.trafficmanager.net"]);
13896
+ function isAllowedTeamsServiceUrl(serviceUrl) {
13897
+ try {
13898
+ const url = new URL(serviceUrl);
13899
+ return url.protocol === "https:" && ALLOWED_SERVICE_URL_HOSTS.has(url.hostname) && // Scheme + hostname is not an origin. A non-default port is a different
13900
+ // service on the same host, credentials in the authority are sent as a
13901
+ // Basic header, and a query or fragment on the BASE corrupts the path
13902
+ // joined after it. `URL` normalises an explicit `:443` to '' so the
13903
+ // canonical form of a real serviceUrl still passes. (CodeRabbit, PR #6151.)
13904
+ url.port === "" && url.username === "" && url.password === "" && url.search === "" && url.hash === "";
13905
+ } catch {
13906
+ return false;
13907
+ }
13908
+ }
13909
+ function botFrameworkUrl(serviceUrl, path) {
13910
+ if (!isAllowedTeamsServiceUrl(serviceUrl)) {
13911
+ throw new MsTeamsApiError(`Refusing to call a non-Bot-Framework serviceUrl (ENG-8991). Allowed hosts: ${[...ALLOWED_SERVICE_URL_HOSTS].join(", ")} over https.`);
13912
+ }
13913
+ return joinUrl(serviceUrl, path);
13914
+ }
13915
+
13883
13916
  // src/slack-loop-throttle.ts
13884
13917
  var DEFAULT_THROTTLE = {
13885
13918
  threshold: 3,
@@ -15316,7 +15349,6 @@ async function acquireBotToken(scope = BOT_FRAMEWORK_SCOPE) {
15316
15349
  });
15317
15350
  return data.access_token;
15318
15351
  }
15319
- var joinUrl = (base, path) => `${base.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
15320
15352
  function buildAugmentedTeamsEntity() {
15321
15353
  if (!AGT_TEAM_ID) return null;
15322
15354
  return {
@@ -15334,14 +15366,14 @@ async function sendActivity(serviceUrl, conversationId, activity) {
15334
15366
  augmentedEntity
15335
15367
  ]
15336
15368
  } : activity;
15337
- const token = await acquireBotToken();
15338
- const url = activity.replyToId ? joinUrl(
15369
+ const url = activity.replyToId ? botFrameworkUrl(
15339
15370
  serviceUrl,
15340
15371
  `/v3/conversations/${encodeURIComponent(conversationId)}/activities/${encodeURIComponent(activity.replyToId)}`
15341
- ) : joinUrl(
15372
+ ) : botFrameworkUrl(
15342
15373
  serviceUrl,
15343
15374
  `/v3/conversations/${encodeURIComponent(conversationId)}/activities`
15344
15375
  );
15376
+ const token = await acquireBotToken();
15345
15377
  const response = await fetch(url, {
15346
15378
  method: "POST",
15347
15379
  headers: {
@@ -15349,7 +15381,10 @@ async function sendActivity(serviceUrl, conversationId, activity) {
15349
15381
  "Content-Type": "application/json"
15350
15382
  },
15351
15383
  body: JSON.stringify(activityWithLabel),
15352
- signal: AbortSignal.timeout(1e4)
15384
+ signal: AbortSignal.timeout(1e4),
15385
+ // ENG-8991: botFrameworkUrl validated the FIRST hop only; a 307/308 keeps
15386
+ // method and body. Never follow a redirect off a validated serviceUrl.
15387
+ redirect: "error"
15353
15388
  });
15354
15389
  if (!response.ok) {
15355
15390
  const text = await response.text().catch(() => "");
@@ -15969,15 +16004,17 @@ async function handleReadThread(args) {
15969
16004
  return errResult("conversation_id and service_url are required");
15970
16005
  }
15971
16006
  try {
15972
- const token = await acquireBotToken();
15973
16007
  const qs = continuationToken ? `?continuationToken=${encodeURIComponent(continuationToken)}` : "";
15974
- const url = joinUrl(
16008
+ const url = botFrameworkUrl(
15975
16009
  serviceUrl,
15976
16010
  `/v3/conversations/${encodeURIComponent(conversationId)}/activities${qs}`
15977
16011
  );
16012
+ const token = await acquireBotToken();
15978
16013
  const res = await fetch(url, {
15979
16014
  method: "GET",
15980
- headers: { Authorization: `Bearer ${token}` }
16015
+ headers: { Authorization: `Bearer ${token}` },
16016
+ redirect: "error"
16017
+ // ENG-8991: never follow a redirect off a validated serviceUrl
15981
16018
  });
15982
16019
  if (!res.ok) {
15983
16020
  const body = await res.text().catch(() => "");
@@ -16017,14 +16054,16 @@ async function handleChannelInfo(args) {
16017
16054
  return errResult("conversation_id and service_url are required");
16018
16055
  }
16019
16056
  try {
16020
- const token = await acquireBotToken();
16021
- const url = joinUrl(
16057
+ const url = botFrameworkUrl(
16022
16058
  serviceUrl,
16023
16059
  `/v3/conversations/${encodeURIComponent(conversationId)}/members`
16024
16060
  );
16061
+ const token = await acquireBotToken();
16025
16062
  const res = await fetch(url, {
16026
16063
  method: "GET",
16027
- headers: { Authorization: `Bearer ${token}` }
16064
+ headers: { Authorization: `Bearer ${token}` },
16065
+ redirect: "error"
16066
+ // ENG-8991: never follow a redirect off a validated serviceUrl
16028
16067
  });
16029
16068
  let result;
16030
16069
  if (!res.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.951",
3
+ "version": "0.28.953",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {