@integrity-labs/agt-cli 0.28.474 → 0.28.476

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.
@@ -18867,7 +18867,7 @@ var require_filters = __commonJS({
18867
18867
  return r.copySafeness(str, res);
18868
18868
  }
18869
18869
  _exports.indent = indent;
18870
- function join15(arr, del, attr) {
18870
+ function join14(arr, del, attr) {
18871
18871
  del = del || "";
18872
18872
  if (attr) {
18873
18873
  arr = lib.map(arr, function(v) {
@@ -18876,7 +18876,7 @@ var require_filters = __commonJS({
18876
18876
  }
18877
18877
  return arr.join(del);
18878
18878
  }
18879
- _exports.join = join15;
18879
+ _exports.join = join14;
18880
18880
  function last(arr) {
18881
18881
  return arr[arr.length - 1];
18882
18882
  }
@@ -30087,40 +30087,6 @@ function resolveHostBooleanFlag(opts) {
30087
30087
  if (cached2 !== void 0) return cached2;
30088
30088
  return opts.defaultValue;
30089
30089
  }
30090
- var USAGE_LIMIT_REACTIVE_FLAG_KEY = "usage-limit-reactive-notice";
30091
- function parseUsageLimitReactiveMode(raw) {
30092
- if (raw === void 0) return void 0;
30093
- const v = raw.trim().toLowerCase();
30094
- if (v === "") return void 0;
30095
- if (v === "off" || v === "shadow" || v === "enforce") return v;
30096
- const b = envBoolean(raw);
30097
- if (b === true) return "enforce";
30098
- if (b === false) return "off";
30099
- return void 0;
30100
- }
30101
- function cachedUsageLimitReactiveMode(path) {
30102
- try {
30103
- if (!existsSync4(path)) return void 0;
30104
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
30105
- if (!parsed || typeof parsed !== "object") return void 0;
30106
- const flags = parsed.flags;
30107
- if (!flags || typeof flags !== "object") return void 0;
30108
- const value = flags[USAGE_LIMIT_REACTIVE_FLAG_KEY];
30109
- if (typeof value === "string") return parseUsageLimitReactiveMode(value);
30110
- if (typeof value === "boolean") return value ? "enforce" : "off";
30111
- return void 0;
30112
- } catch {
30113
- return void 0;
30114
- }
30115
- }
30116
- function resolveUsageLimitReactiveMode(opts) {
30117
- const env2 = opts?.env ?? process.env;
30118
- const modeOverride = parseUsageLimitReactiveMode(env2["AGT_USAGE_LIMIT_REACTIVE_MODE"]);
30119
- if (modeOverride !== void 0) return modeOverride;
30120
- const cached2 = cachedUsageLimitReactiveMode(opts?.cachePath ?? defaultFlagsCachePath());
30121
- if (cached2 !== void 0) return cached2;
30122
- return "off";
30123
- }
30124
30090
 
30125
30091
  // src/ack-reaction.ts
30126
30092
  var REPLY_WEDGED_THRESHOLD_MS = 5 * 60 * 1e3;
@@ -32968,6 +32934,34 @@ var INTEGRATION_REGISTRY = [
32968
32934
  docs_url: "https://higgsfield.ai/mcp",
32969
32935
  beta: true
32970
32936
  },
32937
+ {
32938
+ id: "vercel",
32939
+ name: "Vercel",
32940
+ category: "infrastructure",
32941
+ description: "Check on Vercel app deployments \u2014 status, build/runtime logs \u2014 and search Vercel documentation. Remote streamable-HTTP MCP at https://mcp.vercel.com.",
32942
+ // Same OAuth pattern as Granola/Higgsfield: Claude Code brokers the
32943
+ // browser sign-in at runtime; nothing for the manager API to provision.
32944
+ supported_auth_types: ["none"],
32945
+ capabilities: [
32946
+ { id: "vercel:read-deployments", name: "Read Deployments", description: "List teams/projects, check deployment status, and read build/runtime logs.", access: "read" },
32947
+ { id: "vercel:search-docs", name: "Search Documentation", description: "Search Vercel platform documentation.", access: "read" }
32948
+ ],
32949
+ docs_url: "https://vercel.com/docs/agent-resources/vercel-mcp",
32950
+ // Beta until the headless OAuth flow (and Vercel's OAuth-client allowlist,
32951
+ // which is vendor-side and outside our control) is verified end-to-end.
32952
+ beta: true,
32953
+ // No `auth`/`headers` — host-brokered OAuth (Claude Code authenticates
32954
+ // directly with Vercel; nothing for us to inject). Declaring this here
32955
+ // (rather than a hardcoded buildMcpJson/writeIntegrations branch, the
32956
+ // pre-ENG-8035 Higgsfield-era pattern) lets the generic remote-MCP loop
32957
+ // render the `.mcp.json` entry AND enrolls 'vercel' in the
32958
+ // `registryRemoteMcpKeys` prune universe automatically, so an uninstall
32959
+ // actually removes the entry instead of leaving it stale.
32960
+ remoteMcp: {
32961
+ type: "http",
32962
+ url: "https://mcp.vercel.com"
32963
+ }
32964
+ },
32971
32965
  {
32972
32966
  id: "qmd",
32973
32967
  name: "QMD Memory Search",
@@ -33691,30 +33685,11 @@ function parseResetDateTime(humanDate, now) {
33691
33685
  return resolved;
33692
33686
  }
33693
33687
 
33694
- // ../core/dist/claude-code-usage/usage-limit-marker.js
33695
- var USAGE_LIMIT_MARKER_FILENAME = "claude-usage-limit.json";
33696
- var USAGE_LIMIT_MARKER_VERSION = 1;
33697
- function parseUsageLimitMarker(raw) {
33698
- let parsed;
33699
- try {
33700
- parsed = JSON.parse(raw);
33701
- } catch {
33702
- return null;
33703
- }
33704
- if (typeof parsed !== "object" || parsed === null || parsed.version !== USAGE_LIMIT_MARKER_VERSION) {
33705
- return null;
33706
- }
33707
- const until = parsed.limited_until;
33708
- if (typeof until !== "string" || !Number.isFinite(Date.parse(until)))
33709
- return null;
33710
- return { version: USAGE_LIMIT_MARKER_VERSION, limited_until: until };
33711
- }
33712
- function resolveUsageLimitUntil(marker, now) {
33713
- if (!marker)
33714
- return null;
33715
- const until = new Date(marker.limited_until);
33716
- return until.getTime() > now.getTime() ? until : null;
33717
- }
33688
+ // ../core/dist/claude-code-usage/run-marker.js
33689
+ var RUN_MARKER_RE = /<!--\s*agt-run:([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\s*-->/;
33690
+ var RUN_MARKER_RE_GLOBAL = new RegExp(RUN_MARKER_RE.source, "g");
33691
+
33692
+ // ../core/dist/claude-code-usage/usage-limit-notice-text.js
33718
33693
  function formatUtcClock(date3) {
33719
33694
  const hours = date3.getUTCHours();
33720
33695
  const minutes = date3.getUTCMinutes();
@@ -34646,42 +34621,6 @@ var FLAG_REGISTRY = [
34646
34621
  // projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
34647
34622
  since: "0.28.421"
34648
34623
  },
34649
- {
34650
- key: "usage-limit-reactive-notice",
34651
- description: "Report a Claude Code usage cap REACTIVELY instead of predicting it (ENG-8201). Today the manager guesses from the agent transcript that the next turn will be refused, writes a marker, and every channel MCP refuses to dispatch on the strength of that guess - so a wrong guess is a swallowed message, and because the notice is throttled per (channel, sender) while the DROP is not, the usual symptom is total silence rather than a wrong reply. A refused turn actually costs nothing (rejected in under a second, zero tokens) and Claude Code records it with the reset time in it, so there is no need to guess: dispatch, and report the refusal if one comes back. off = today behaviour (pre-dispatch marker gate, no watcher). shadow = still gate on the marker, but ALSO watch dispatched messages and log the refusal that would have been reported - measures the true-positive rate with no user-visible change. enforce = stop reading the marker before dispatch; every admitted human message reaches the agent and a refusal is answered in-thread with the reset time from the error itself. Read live from the heartbeat flags-cache (or the env override).",
34652
- flagType: "enum",
34653
- allowedValues: ["off", "shadow", "enforce"],
34654
- // Ships dark: off preserves today's gate byte-for-byte. shadow is a free
34655
- // local log line (the watch is a transcript read, no model spend), so it is a
34656
- // cheap soak; enforce changes what reaches the agent, so it is the audited
34657
- // per-org flip.
34658
- defaultValue: "off",
34659
- // Enum override AGT_USAGE_LIMIT_REACTIVE_MODE (off|shadow|enforce), resolved
34660
- // by resolveUsageLimitReactiveMode in the channel-server bundle.
34661
- envVar: "AGT_USAGE_LIMIT_REACTIVE_MODE",
34662
- // enforce sends a message to an agent the host currently believes is capped -
34663
- // a deliberate availability trade (the refusal is free, but it is still a
34664
- // dispatch the operator previously suppressed), so flipping toward it is an
34665
- // audited change (ADR-0022 sensitive-flag confirm).
34666
- sensitive: true,
34667
- // ENG-8149 / ENG-8229: the agt-cli that first carries
34668
- // resolveUsageLimitReactiveMode in ALL THREE channel servers - published from
34669
- // the ENG-8207 merge 0294fa1a8. Without this the flip-reach modal reports FULL
34670
- // reach, because an undefined `since` means "every host can honour it" - true
34671
- // for flags that predate the reach work, wrong for a NEW host-read flag whose
34672
- // reader older hosts simply do not have. Excluded from projectDefinition, so
34673
- // setting it does not roll FLAGS_SCHEMA_VERSION.
34674
- //
34675
- // Deliberately the LATER of the two versions this flag's reader shipped in.
34676
- // Unlike its siblings, this reader landed in two stages: direct-chat at the
34677
- // ENG-8201 Slice 2 publish, slack + telegram only at 0.28.450 (ENG-8207) - and
34678
- // `since` is one version per flag, so it cannot express "partially honoured".
34679
- // A host in between genuinely honours the flag for direct-chat and is still
34680
- // classified `stale`. That understates reach rather than overstating it, which
34681
- // is the safe direction, and it is the useful one while the flag sits at
34682
- // enforce and slack/telegram adoption is what an operator needs to track.
34683
- since: "0.28.450"
34684
- },
34685
34624
  {
34686
34625
  key: "slack-hot-thread-guard",
34687
34626
  description: "Server-side hot-thread guard on the slack.reply surface (ENG-7462). Prevents an agent posting a NEW top-level Slack message when it meant to reply inside the thread it is already working in - a prompt/memory rule proved insufficient (the agent had the rule and still slipped). When a reply would otherwise post to channel ROOT (no thread_ts / message_ts / inbound_id, no active kanban card) and the agent has a recent active thread in that channel (its last bot-posted thread, from the persisted trackedThreads cache, within a freshness window), the reply is redirected into that thread. proactive:true no longer implies channel root; posting at root becomes a deliberate action (the to_channel_root flag, or the thread_ts:null sentinel). off = guard never runs, replies with no coords root exactly as today (ships dark). shadow = compute + log the would-redirect but STILL post to root (measure the fire rate before acting). enforce = apply the redirect (a soft-block: redirect + inform, never a hard rejection). Read live from the heartbeat flags-cache (or the env override); enforce is a deliberate per-org flip after a shadow soak.",
@@ -35783,14 +35722,14 @@ function readLockHolder(path) {
35783
35722
  }
35784
35723
 
35785
35724
  // src/direct-chat-channel.ts
35786
- import { homedir as homedir5 } from "os";
35787
- import { join as join14 } from "path";
35725
+ import { homedir as homedir4 } from "os";
35726
+ import { join as join13 } from "path";
35788
35727
  import { randomUUID } from "crypto";
35789
35728
  import {
35790
35729
  watch,
35791
35730
  mkdirSync as mkdirSync5,
35792
35731
  writeFileSync as writeFileSync6,
35793
- readFileSync as readFileSync13,
35732
+ readFileSync as readFileSync12,
35794
35733
  readdirSync as readdirSync6,
35795
35734
  existsSync as existsSync6,
35796
35735
  renameSync as renameSync5,
@@ -36222,30 +36161,10 @@ function isMaintenanceModeActive(opts) {
36222
36161
  });
36223
36162
  }
36224
36163
 
36225
- // src/usage-limit-notice.ts
36164
+ // src/account-enforcement-notice.ts
36226
36165
  import { readFileSync as readFileSync11 } from "fs";
36227
36166
  import { homedir as homedir3 } from "os";
36228
36167
  import { join as join12 } from "path";
36229
- function usageLimitMarkerPath(codeName) {
36230
- if (!codeName) return null;
36231
- return join12(homedir3(), ".augmented", codeName, USAGE_LIMIT_MARKER_FILENAME);
36232
- }
36233
- function readUsageLimitUntil(opts) {
36234
- const path = opts.filePath ?? usageLimitMarkerPath(opts.codeName);
36235
- if (!path) return null;
36236
- let raw;
36237
- try {
36238
- raw = readFileSync11(path, "utf-8");
36239
- } catch {
36240
- return null;
36241
- }
36242
- return resolveUsageLimitUntil(parseUsageLimitMarker(raw), opts.now ?? /* @__PURE__ */ new Date());
36243
- }
36244
-
36245
- // src/account-enforcement-notice.ts
36246
- import { readFileSync as readFileSync12 } from "fs";
36247
- import { homedir as homedir4 } from "os";
36248
- import { join as join13 } from "path";
36249
36168
 
36250
36169
  // ../core/dist/channels/governance/sender-policy-decline.js
36251
36170
  function decideDeclineReply(input) {
@@ -36263,14 +36182,14 @@ function decideDeclineReply(input) {
36263
36182
  // src/account-enforcement-notice.ts
36264
36183
  function accountEnforcementMarkerPath(codeName) {
36265
36184
  if (!codeName) return null;
36266
- return join13(homedir4(), ".augmented", codeName, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
36185
+ return join12(homedir3(), ".augmented", codeName, ACCOUNT_ENFORCEMENT_MARKER_FILENAME);
36267
36186
  }
36268
36187
  function readAccountEnforcementLevel(opts) {
36269
36188
  const path = opts.filePath ?? accountEnforcementMarkerPath(opts.codeName);
36270
36189
  if (!path) return null;
36271
36190
  let raw;
36272
36191
  try {
36273
- raw = readFileSync12(path, "utf-8");
36192
+ raw = readFileSync11(path, "utf-8");
36274
36193
  } catch {
36275
36194
  return null;
36276
36195
  }
@@ -36288,6 +36207,17 @@ function shouldSendAccountWarn(opts) {
36288
36207
  }).reply;
36289
36208
  }
36290
36209
 
36210
+ // src/usage-limit-reactive-decision.ts
36211
+ import { createHash } from "crypto";
36212
+ function shouldArmWatch(opts) {
36213
+ return !opts.isBot && opts.replyOwed;
36214
+ }
36215
+ function describeUnparsedRefusal(text) {
36216
+ if (!text) return "refusal=absent";
36217
+ const hash = createHash("sha256").update(text).digest("hex").slice(0, 12);
36218
+ return `refusal_hash=${hash} refusal_len=${text.length}`;
36219
+ }
36220
+
36291
36221
  // src/direct-chat-channel.ts
36292
36222
  var DIRECT_CHAT_MAINTENANCE_CACHE = /* @__PURE__ */ new Map();
36293
36223
  var DIRECT_CHAT_MAINTENANCE_COOLDOWN_MS = (() => {
@@ -36306,21 +36236,21 @@ var DIRECT_CHAT_ACCOUNT_WARN_COOLDOWN_MS = (() => {
36306
36236
  var AGT_HOST = process.env.AGT_HOST;
36307
36237
  var AGT_API_KEY = process.env.AGT_API_KEY;
36308
36238
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
36309
- var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join14(homedir5(), ".augmented", AGT_AGENT_ID) : null;
36239
+ var DIRECT_CHAT_AGENT_DIR = AGT_AGENT_ID ? join13(homedir4(), ".augmented", AGT_AGENT_ID) : null;
36310
36240
  var INBOUND_ATTACHMENTS_DIR = resolveInboundAttachmentsDir({
36311
36241
  codeName: process.env.AGT_AGENT_CODE_NAME,
36312
36242
  turnInitiatorFile: process.env.AGT_TURN_INITIATOR_FILE,
36313
36243
  agentId: AGT_AGENT_ID,
36314
- homeDir: homedir5()
36244
+ homeDir: homedir4()
36315
36245
  });
36316
36246
  var AGT_AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME;
36317
36247
  var directChatStderrLogStream = null;
36318
36248
  if (AGT_AGENT_CODE_NAME) {
36319
36249
  try {
36320
- const logDir = join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME);
36250
+ const logDir = join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME);
36321
36251
  mkdirSync5(logDir, { recursive: true });
36322
36252
  directChatStderrLogStream = createWriteStream(
36323
- join14(logDir, "direct-chat-channel-stderr.log"),
36253
+ join13(logDir, "direct-chat-channel-stderr.log"),
36324
36254
  { flags: "a", mode: 384 }
36325
36255
  );
36326
36256
  directChatStderrLogStream.on("error", () => {
@@ -36339,10 +36269,10 @@ if (AGT_AGENT_CODE_NAME) {
36339
36269
  } catch {
36340
36270
  }
36341
36271
  }
36342
- var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
36343
- var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-pending-inbound") : null;
36344
- var DIRECT_CHAT_DELIVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-inbound-delivery-ledger") : null;
36345
- var DIRECT_CHAT_CODE_NAME_AGENT_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME) : null;
36272
+ var PROGRESS_HEARTBEAT_PATH = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, "channel-progress-heartbeat.json") : null;
36273
+ var DIRECT_CHAT_PENDING_INBOUND_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-pending-inbound") : null;
36274
+ var DIRECT_CHAT_DELIVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-inbound-delivery-ledger") : null;
36275
+ var DIRECT_CHAT_CODE_NAME_AGENT_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME) : null;
36346
36276
  var DIRECT_CHAT_STALE_MARKER_MS = 24 * 60 * 60 * 1e3;
36347
36277
  function recordDirectChatDelivery(sessionId, messageIds) {
36348
36278
  if (!sessionId) return;
@@ -36353,8 +36283,8 @@ function recordDirectChatDelivery(sessionId, messageIds) {
36353
36283
  delivered_at: (/* @__PURE__ */ new Date()).toISOString()
36354
36284
  });
36355
36285
  }
36356
- var DIRECT_CHAT_RECOVERY_OUTBOX_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-recovery-outbox") : null;
36357
- var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-direct-chat-recovery-ledger") : null;
36286
+ var DIRECT_CHAT_RECOVERY_OUTBOX_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, "direct-chat-recovery-outbox") : null;
36287
+ var DIRECT_CHAT_RECOVERY_LEDGER_DIR = AGT_AGENT_CODE_NAME ? join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME, ".agt-direct-chat-recovery-ledger") : null;
36358
36288
  var progressReceivedAt = /* @__PURE__ */ new Map();
36359
36289
  var directChatProgressState = { tracked: null };
36360
36290
  var directChatProgressTickRunning = false;
@@ -36373,7 +36303,7 @@ var directChatKanbanCardClient = createKanbanCardActiveClient({
36373
36303
  function readProgressHeartbeat() {
36374
36304
  if (!PROGRESS_HEARTBEAT_PATH || !existsSync6(PROGRESS_HEARTBEAT_PATH)) return null;
36375
36305
  try {
36376
- return parseProgressHeartbeat(readFileSync13(PROGRESS_HEARTBEAT_PATH, "utf-8"));
36306
+ return parseProgressHeartbeat(readFileSync12(PROGRESS_HEARTBEAT_PATH, "utf-8"));
36377
36307
  } catch {
36378
36308
  return null;
36379
36309
  }
@@ -36382,7 +36312,7 @@ function seedProgressHeartbeat() {
36382
36312
  if (!PROGRESS_HEARTBEAT_PATH) return;
36383
36313
  const tmp = `${PROGRESS_HEARTBEAT_PATH}.${process.pid}.tmp`;
36384
36314
  try {
36385
- mkdirSync5(join14(homedir5(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
36315
+ mkdirSync5(join13(homedir4(), ".augmented", AGT_AGENT_CODE_NAME), { recursive: true });
36386
36316
  writeFileSync6(tmp, serializeProgressHeartbeat(SEED_PROGRESS_STEP, Date.now()), { mode: 384 });
36387
36317
  renameSync5(tmp, PROGRESS_HEARTBEAT_PATH);
36388
36318
  } catch {
@@ -36577,7 +36507,7 @@ var inboundAttachmentDeps = {
36577
36507
  },
36578
36508
  ensureDir: (dir) => mkdirSync5(dir, { recursive: true }),
36579
36509
  writeFile: (path, bytes) => writeFileSync6(path, bytes, { mode: 384 }),
36580
- joinPath: (...parts) => join14(...parts),
36510
+ joinPath: (...parts) => join13(...parts),
36581
36511
  warn: (msg) => process.stderr.write(`${msg}
36582
36512
  `)
36583
36513
  };
@@ -36911,7 +36841,7 @@ function scheduleDirectChatBusyAck(sessionId, messageId, arrivedWhileBusy) {
36911
36841
  let paneLogFreshAgeMs = null;
36912
36842
  if (DIRECT_CHAT_CODE_NAME_AGENT_DIR) {
36913
36843
  try {
36914
- const paneMtimeMs = statSync4(join14(DIRECT_CHAT_CODE_NAME_AGENT_DIR, "pane.log")).mtimeMs;
36844
+ const paneMtimeMs = statSync4(join13(DIRECT_CHAT_CODE_NAME_AGENT_DIR, "pane.log")).mtimeMs;
36915
36845
  paneLogFreshAgeMs = Math.max(0, Date.now() - paneMtimeMs);
36916
36846
  } catch {
36917
36847
  }
@@ -37004,14 +36934,7 @@ function armUsageLimitWatch(args) {
37004
36934
  if (!refusal) return;
37005
36935
  if (!refusal.resetsAt) {
37006
36936
  process.stderr.write(
37007
- `direct-chat-channel: [usage-limit-reactive] mode=${args.mode} refusal detected for session=${args.sessionId} but no reset time in it (${refusal.text ?? "no text"}) - no notice
37008
- `
37009
- );
37010
- return;
37011
- }
37012
- if (args.mode === "shadow") {
37013
- process.stderr.write(
37014
- `direct-chat-channel: [usage-limit-reactive] mode=shadow WOULD notify session=${args.sessionId} message=${args.messageId} resets=${refusal.resetsAt.toISOString()}
36937
+ `direct-chat-channel: [usage-limit-reactive] refusal detected for session=${args.sessionId} but no reset time in it (${describeUnparsedRefusal(refusal.text)}) - no notice
37015
36938
  `
37016
36939
  );
37017
36940
  return;
@@ -37084,9 +37007,7 @@ async function pollForMessages(sinceMs) {
37084
37007
  const isNotice = msg.kind === "notice";
37085
37008
  const maintenanceActive = !isNotice && isMaintenanceModeActive();
37086
37009
  const accountMuted = !isNotice && !maintenanceActive ? readAccountEnforcementLevel({ codeName: AGT_AGENT_CODE_NAME ?? null }) === "mute" : false;
37087
- const reactiveMode = resolveUsageLimitReactiveMode();
37088
- const usageLimitUntil = !isNotice && !maintenanceActive && !accountMuted && reactiveMode !== "enforce" ? readUsageLimitUntil({ codeName: AGT_AGENT_CODE_NAME ?? null }) : null;
37089
- if (!isNotice && !maintenanceActive && !accountMuted && !usageLimitUntil) {
37010
+ if (!isNotice && !maintenanceActive && !accountMuted) {
37090
37011
  markProcessed(msg.id);
37091
37012
  claimTracker.track(msg.session_id, msg.id);
37092
37013
  if (!progressReceivedAt.has(msg.session_id)) {
@@ -37151,37 +37072,6 @@ async function pollForMessages(sinceMs) {
37151
37072
  if (throttle.reply) DIRECT_CHAT_ACCOUNT_MUTE_CACHE.delete(throttleKey);
37152
37073
  process.stderr.write(
37153
37074
  `direct-chat-channel: account-mute reply failed: ${err.message}
37154
- `
37155
- );
37156
- }
37157
- continue;
37158
- }
37159
- if (usageLimitUntil) {
37160
- const throttleKey = `${msg.session_id}|usage_limit`;
37161
- const throttle = decideDeclineReply({
37162
- cache: DIRECT_CHAT_USAGE_LIMIT_CACHE,
37163
- key: throttleKey,
37164
- cooldownMs: DIRECT_CHAT_MAINTENANCE_COOLDOWN_MS,
37165
- now: Date.now()
37166
- });
37167
- const route = throttle.reply ? "/host/direct-chat/reply" : "/host/direct-chat/consume";
37168
- const body = throttle.reply ? { agent_id: AGT_AGENT_ID, session_id: msg.session_id, content: buildUsageLimitReplyText(usageLimitUntil), message_ids: [msg.id], kind: "notice" } : { agent_id: AGT_AGENT_ID, session_id: msg.session_id, message_ids: [msg.id] };
37169
- try {
37170
- const res2 = await apiPost(route, body);
37171
- const data2 = await res2.json().catch(() => ({}));
37172
- if (res2.ok && data2.error == null) {
37173
- markProcessed(msg.id);
37174
- } else {
37175
- if (throttle.reply) DIRECT_CHAT_USAGE_LIMIT_CACHE.delete(throttleKey);
37176
- process.stderr.write(
37177
- `direct-chat-channel: usage-limit ${throttle.reply ? "reply" : "consume"} failed: ${data2.error ?? `HTTP ${res2.status}`}
37178
- `
37179
- );
37180
- }
37181
- } catch (err) {
37182
- if (throttle.reply) DIRECT_CHAT_USAGE_LIMIT_CACHE.delete(throttleKey);
37183
- process.stderr.write(
37184
- `direct-chat-channel: usage-limit reply failed: ${err.message}
37185
37075
  `
37186
37076
  );
37187
37077
  }
@@ -37264,9 +37154,8 @@ async function pollForMessages(sinceMs) {
37264
37154
  `direct-chat-channel: Injected message ${msg.id} (session=${msg.session_id})
37265
37155
  `
37266
37156
  );
37267
- if (!isNotice && reactiveMode !== "off") {
37157
+ if (shouldArmWatch({ isBot: false, replyOwed: !isNotice })) {
37268
37158
  armUsageLimitWatch({
37269
- mode: reactiveMode,
37270
37159
  sessionId: msg.session_id,
37271
37160
  messageId: msg.id,
37272
37161
  sinceMs: dispatchedAtMs
@@ -37385,7 +37274,7 @@ function sweepAgedDirectChatMarkersNow(thresholdMs) {
37385
37274
  const now = Date.now();
37386
37275
  const res = sweepAgedDirectChatMarkers(DIRECT_CHAT_PENDING_INBOUND_DIR, {
37387
37276
  readdir: (dir) => readdirSync6(dir),
37388
- readFile: (p2) => readFileSync13(p2, "utf8"),
37277
+ readFile: (p2) => readFileSync12(p2, "utf8"),
37389
37278
  unlink: (p2) => {
37390
37279
  if (existsSync6(p2)) unlinkSync4(p2);
37391
37280
  },
@@ -37421,7 +37310,7 @@ function sanitizeRecoveryText(text) {
37421
37310
  }
37422
37311
  function directChatRecoveryDeps() {
37423
37312
  return {
37424
- readFile: (p2) => readFileSync13(p2, "utf-8"),
37313
+ readFile: (p2) => readFileSync12(p2, "utf-8"),
37425
37314
  renameFile: (from, to) => renameSync5(from, to),
37426
37315
  unlinkFile: (p2) => {
37427
37316
  if (existsSync6(p2)) unlinkSync4(p2);
@@ -37434,7 +37323,7 @@ function directChatRecoveryDeps() {
37434
37323
  if (!DIRECT_CHAT_RECOVERY_LEDGER_DIR) return;
37435
37324
  if (markerName.includes("/") || markerName.includes("\\") || markerName.includes("..")) return;
37436
37325
  try {
37437
- const p2 = join14(DIRECT_CHAT_RECOVERY_LEDGER_DIR, markerName);
37326
+ const p2 = join13(DIRECT_CHAT_RECOVERY_LEDGER_DIR, markerName);
37438
37327
  if (existsSync6(p2)) unlinkSync4(p2);
37439
37328
  } catch {
37440
37329
  }
@@ -37470,7 +37359,7 @@ async function processDirectChatRecoveryOutboxFile(filename) {
37470
37359
  if (!enabled) return;
37471
37360
  directChatRecoveryInFlight.add(filename);
37472
37361
  try {
37473
- const fullPath = join14(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, filename);
37362
+ const fullPath = join13(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, filename);
37474
37363
  await consumeDirectChatRecoveryFile(fullPath, filename, directChatRecoveryDeps());
37475
37364
  } catch (err) {
37476
37365
  process.stderr.write(
@@ -37498,7 +37387,7 @@ if (DIRECT_CHAT_RECOVERY_OUTBOX_DIR) {
37498
37387
  if (!filename) return;
37499
37388
  const name = filename.toString();
37500
37389
  if (!name.endsWith(".json")) return;
37501
- if (existsSync6(join14(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
37390
+ if (existsSync6(join13(DIRECT_CHAT_RECOVERY_OUTBOX_DIR, name))) {
37502
37391
  void processDirectChatRecoveryOutboxFile(name);
37503
37392
  }
37504
37393
  });
@@ -39261,6 +39261,34 @@ var INTEGRATION_REGISTRY = [
39261
39261
  docs_url: "https://higgsfield.ai/mcp",
39262
39262
  beta: true
39263
39263
  },
39264
+ {
39265
+ id: "vercel",
39266
+ name: "Vercel",
39267
+ category: "infrastructure",
39268
+ description: "Check on Vercel app deployments \u2014 status, build/runtime logs \u2014 and search Vercel documentation. Remote streamable-HTTP MCP at https://mcp.vercel.com.",
39269
+ // Same OAuth pattern as Granola/Higgsfield: Claude Code brokers the
39270
+ // browser sign-in at runtime; nothing for the manager API to provision.
39271
+ supported_auth_types: ["none"],
39272
+ capabilities: [
39273
+ { id: "vercel:read-deployments", name: "Read Deployments", description: "List teams/projects, check deployment status, and read build/runtime logs.", access: "read" },
39274
+ { id: "vercel:search-docs", name: "Search Documentation", description: "Search Vercel platform documentation.", access: "read" }
39275
+ ],
39276
+ docs_url: "https://vercel.com/docs/agent-resources/vercel-mcp",
39277
+ // Beta until the headless OAuth flow (and Vercel's OAuth-client allowlist,
39278
+ // which is vendor-side and outside our control) is verified end-to-end.
39279
+ beta: true,
39280
+ // No `auth`/`headers` — host-brokered OAuth (Claude Code authenticates
39281
+ // directly with Vercel; nothing for us to inject). Declaring this here
39282
+ // (rather than a hardcoded buildMcpJson/writeIntegrations branch, the
39283
+ // pre-ENG-8035 Higgsfield-era pattern) lets the generic remote-MCP loop
39284
+ // render the `.mcp.json` entry AND enrolls 'vercel' in the
39285
+ // `registryRemoteMcpKeys` prune universe automatically, so an uninstall
39286
+ // actually removes the entry instead of leaving it stale.
39287
+ remoteMcp: {
39288
+ type: "http",
39289
+ url: "https://mcp.vercel.com"
39290
+ }
39291
+ },
39264
39292
  {
39265
39293
  id: "qmd",
39266
39294
  name: "QMD Memory Search",
@@ -39878,6 +39906,10 @@ var BANNER_PATTERNS = [
39878
39906
  ];
39879
39907
  var MS_PER_DAY = 24 * 60 * 60 * 1e3;
39880
39908
 
39909
+ // ../core/dist/claude-code-usage/run-marker.js
39910
+ var RUN_MARKER_RE = /<!--\s*agt-run:([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\s*-->/;
39911
+ var RUN_MARKER_RE_GLOBAL = new RegExp(RUN_MARKER_RE.source, "g");
39912
+
39881
39913
  // ../core/dist/claude-code-usage/rate-limit-classifier.js
39882
39914
  var UNKNOWN_RATE_LIMIT = Object.freeze({
39883
39915
  verdict: "unknown",
@@ -40536,42 +40568,6 @@ var FLAG_REGISTRY = [
40536
40568
  // projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
40537
40569
  since: "0.28.421"
40538
40570
  },
40539
- {
40540
- key: "usage-limit-reactive-notice",
40541
- description: "Report a Claude Code usage cap REACTIVELY instead of predicting it (ENG-8201). Today the manager guesses from the agent transcript that the next turn will be refused, writes a marker, and every channel MCP refuses to dispatch on the strength of that guess - so a wrong guess is a swallowed message, and because the notice is throttled per (channel, sender) while the DROP is not, the usual symptom is total silence rather than a wrong reply. A refused turn actually costs nothing (rejected in under a second, zero tokens) and Claude Code records it with the reset time in it, so there is no need to guess: dispatch, and report the refusal if one comes back. off = today behaviour (pre-dispatch marker gate, no watcher). shadow = still gate on the marker, but ALSO watch dispatched messages and log the refusal that would have been reported - measures the true-positive rate with no user-visible change. enforce = stop reading the marker before dispatch; every admitted human message reaches the agent and a refusal is answered in-thread with the reset time from the error itself. Read live from the heartbeat flags-cache (or the env override).",
40542
- flagType: "enum",
40543
- allowedValues: ["off", "shadow", "enforce"],
40544
- // Ships dark: off preserves today's gate byte-for-byte. shadow is a free
40545
- // local log line (the watch is a transcript read, no model spend), so it is a
40546
- // cheap soak; enforce changes what reaches the agent, so it is the audited
40547
- // per-org flip.
40548
- defaultValue: "off",
40549
- // Enum override AGT_USAGE_LIMIT_REACTIVE_MODE (off|shadow|enforce), resolved
40550
- // by resolveUsageLimitReactiveMode in the channel-server bundle.
40551
- envVar: "AGT_USAGE_LIMIT_REACTIVE_MODE",
40552
- // enforce sends a message to an agent the host currently believes is capped -
40553
- // a deliberate availability trade (the refusal is free, but it is still a
40554
- // dispatch the operator previously suppressed), so flipping toward it is an
40555
- // audited change (ADR-0022 sensitive-flag confirm).
40556
- sensitive: true,
40557
- // ENG-8149 / ENG-8229: the agt-cli that first carries
40558
- // resolveUsageLimitReactiveMode in ALL THREE channel servers - published from
40559
- // the ENG-8207 merge 0294fa1a8. Without this the flip-reach modal reports FULL
40560
- // reach, because an undefined `since` means "every host can honour it" - true
40561
- // for flags that predate the reach work, wrong for a NEW host-read flag whose
40562
- // reader older hosts simply do not have. Excluded from projectDefinition, so
40563
- // setting it does not roll FLAGS_SCHEMA_VERSION.
40564
- //
40565
- // Deliberately the LATER of the two versions this flag's reader shipped in.
40566
- // Unlike its siblings, this reader landed in two stages: direct-chat at the
40567
- // ENG-8201 Slice 2 publish, slack + telegram only at 0.28.450 (ENG-8207) - and
40568
- // `since` is one version per flag, so it cannot express "partially honoured".
40569
- // A host in between genuinely honours the flag for direct-chat and is still
40570
- // classified `stale`. That understates reach rather than overstating it, which
40571
- // is the safe direction, and it is the useful one while the flag sits at
40572
- // enforce and slack/telegram adoption is what an operator needs to track.
40573
- since: "0.28.450"
40574
- },
40575
40571
  {
40576
40572
  key: "slack-hot-thread-guard",
40577
40573
  description: "Server-side hot-thread guard on the slack.reply surface (ENG-7462). Prevents an agent posting a NEW top-level Slack message when it meant to reply inside the thread it is already working in - a prompt/memory rule proved insufficient (the agent had the rule and still slipped). When a reply would otherwise post to channel ROOT (no thread_ts / message_ts / inbound_id, no active kanban card) and the agent has a recent active thread in that channel (its last bot-posted thread, from the persisted trackedThreads cache, within a freshness window), the reply is redirected into that thread. proactive:true no longer implies channel root; posting at root becomes a deliberate action (the to_channel_root flag, or the thread_ts:null sentinel). off = guard never runs, replies with no coords root exactly as today (ships dark). shadow = compute + log the would-redirect but STILL post to root (measure the fire rate before acting). enforce = apply the redirect (a soft-block: redirect + inform, never a hard rejection). Read live from the heartbeat flags-cache (or the env override); enforce is a deliberate per-org flip after a shadow soak.",