@integrity-labs/agt-cli 0.28.321 → 0.28.323

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.
@@ -37623,6 +37623,11 @@ var DEFAULT_SCOPES = [
37623
37623
  "reactions:read",
37624
37624
  "reactions:write",
37625
37625
  "users:read",
37626
+ // ENG-7791: needed so users.info returns the sender's email, the join key that
37627
+ // links an inbound Slack sender to their organization_people record (inbound
37628
+ // identity reconcile). Existing installs without it degrade gracefully - the
37629
+ // reconcile no-ops until the bot is re-authorised with the wider scope set.
37630
+ "users:read.email",
37626
37631
  "users.profile:write"
37627
37632
  ];
37628
37633
  var SLACK_SCOPE_PRESETS = {
@@ -18031,8 +18031,76 @@ function createInboundContextClient(args) {
18031
18031
  };
18032
18032
  }
18033
18033
 
18034
- // src/slack-bot-user-id-client.ts
18034
+ // src/reconcile-identity-client.ts
18035
18035
  var REQUEST_TIMEOUT_MS5 = 1e4;
18036
+ function createReconcileIdentityClient(args) {
18037
+ if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
18038
+ const fetchImpl = args.fetchImpl ?? fetch;
18039
+ const log = args.log ?? (() => {
18040
+ });
18041
+ const base = args.agtHost.replace(/\/+$/, "");
18042
+ const agentId = args.agentId;
18043
+ const apiKey = args.agtApiKey;
18044
+ let cachedToken = null;
18045
+ let cachedTokenExpiresAt = 0;
18046
+ async function getToken() {
18047
+ if (cachedToken && Date.now() < cachedTokenExpiresAt) return cachedToken;
18048
+ const resp = await fetchImpl(`${base}/host/exchange`, {
18049
+ method: "POST",
18050
+ headers: { "Content-Type": "application/json" },
18051
+ // Scope the exchange to this agent (per-agent org gate, ADR-0042 P1).
18052
+ body: JSON.stringify({ host_key: apiKey, agent_id: agentId }),
18053
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
18054
+ });
18055
+ if (!resp.ok) {
18056
+ const body = await resp.text().catch(() => "");
18057
+ throw new Error(`/host/exchange failed (${resp.status}): ${body.slice(0, 200)}`);
18058
+ }
18059
+ const data = await resp.json();
18060
+ cachedToken = data.token;
18061
+ cachedTokenExpiresAt = data.expires_at ? new Date(data.expires_at).getTime() - 12e4 : Date.now() + 55 * 6e4;
18062
+ return cachedToken;
18063
+ }
18064
+ async function postOnce(body) {
18065
+ const token = await getToken();
18066
+ return fetchImpl(`${base}/host/reconcile-sender-identity`, {
18067
+ method: "POST",
18068
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
18069
+ body: JSON.stringify(body),
18070
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
18071
+ });
18072
+ }
18073
+ async function emit(args2) {
18074
+ const body = {
18075
+ agent_id: agentId,
18076
+ platform: args2.platform,
18077
+ sender_id: args2.senderId,
18078
+ email: args2.email
18079
+ };
18080
+ try {
18081
+ let resp = await postOnce(body);
18082
+ if (resp.status === 401) {
18083
+ cachedToken = null;
18084
+ cachedTokenExpiresAt = 0;
18085
+ resp = await postOnce(body);
18086
+ }
18087
+ if (!resp.ok) {
18088
+ const text = await resp.text().catch(() => "");
18089
+ log(`reconcile-identity: POST failed (${resp.status}) platform=${args2.platform}: ${text.slice(0, 200)}`);
18090
+ }
18091
+ } catch (err) {
18092
+ log(`reconcile-identity: emit threw platform=${args2.platform}: ${err.message}`);
18093
+ }
18094
+ }
18095
+ return {
18096
+ reconcile(args2) {
18097
+ void emit(args2);
18098
+ }
18099
+ };
18100
+ }
18101
+
18102
+ // src/slack-bot-user-id-client.ts
18103
+ var REQUEST_TIMEOUT_MS6 = 1e4;
18036
18104
  function createSlackBotUserIdClient(args) {
18037
18105
  if (!args.agtHost || !args.agtApiKey || !args.agentId) return null;
18038
18106
  const fetchImpl = args.fetchImpl ?? fetch;
@@ -18051,7 +18119,7 @@ function createSlackBotUserIdClient(args) {
18051
18119
  headers: { "Content-Type": "application/json" },
18052
18120
  // ENG-7438: scope the exchange to this agent (per-agent org gate, ADR-0042 P1).
18053
18121
  body: JSON.stringify({ host_key: apiKey, agent_id: agentId }),
18054
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
18122
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS6)
18055
18123
  });
18056
18124
  if (!resp.ok) {
18057
18125
  const body = await resp.text().catch(() => "");
@@ -18068,7 +18136,7 @@ function createSlackBotUserIdClient(args) {
18068
18136
  method: "POST",
18069
18137
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
18070
18138
  body: JSON.stringify({ agent_id: agentId, bot_user_id: botUserId2 }),
18071
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
18139
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS6)
18072
18140
  });
18073
18141
  }
18074
18142
  async function emitAsync(botUserId2) {
@@ -18100,7 +18168,7 @@ function createSlackBotUserIdClient(args) {
18100
18168
  method: "POST",
18101
18169
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
18102
18170
  body: JSON.stringify({ agent_id: agentId, channel_id: "slack", healthy }),
18103
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS5)
18171
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS6)
18104
18172
  });
18105
18173
  };
18106
18174
  try {
@@ -18454,6 +18522,13 @@ var inboundContextClient = createInboundContextClient({
18454
18522
  log: (line) => process.stderr.write(`slack-channel: ${line}
18455
18523
  `)
18456
18524
  });
18525
+ var reconcileIdentityClient = createReconcileIdentityClient({
18526
+ agtHost: AGT_HOST,
18527
+ agtApiKey: AGT_API_KEY,
18528
+ agentId: AGT_AGENT_ID,
18529
+ log: (line) => process.stderr.write(`slack-channel: ${line}
18530
+ `)
18531
+ });
18457
18532
  var kanbanCardActiveClient = createKanbanCardActiveClient({
18458
18533
  agtHost: AGT_HOST,
18459
18534
  agtApiKey: AGT_API_KEY,
@@ -22249,10 +22324,11 @@ var slackReplayTimer = setInterval(() => {
22249
22324
  });
22250
22325
  }, SLACK_REPLAY_SCAN_INTERVAL_MS);
22251
22326
  slackReplayTimer.unref?.();
22252
- var userNameCache = /* @__PURE__ */ new Map();
22253
- async function resolveUserName(userId) {
22254
- if (!userId || userId === "unknown") return userId ?? "unknown";
22255
- const cached2 = userNameCache.get(userId);
22327
+ var userProfileCache = /* @__PURE__ */ new Map();
22328
+ var reconciledSlackSenders = /* @__PURE__ */ new Set();
22329
+ async function resolveUserProfile(userId) {
22330
+ if (!userId || userId === "unknown") return null;
22331
+ const cached2 = userProfileCache.get(userId);
22256
22332
  if (cached2 !== void 0) return cached2;
22257
22333
  try {
22258
22334
  const res = await fetch(
@@ -22260,14 +22336,30 @@ async function resolveUserName(userId) {
22260
22336
  { headers: { Authorization: `Bearer ${BOT_TOKEN}` } }
22261
22337
  );
22262
22338
  const data = await res.json();
22263
- const name = data.user?.profile?.display_name || data.user?.profile?.real_name || userId;
22264
- userNameCache.set(userId, name);
22265
- return name;
22339
+ if (!data.ok) return null;
22340
+ const profile = {
22341
+ name: data.user?.profile?.display_name || data.user?.profile?.real_name || userId,
22342
+ email: data.user?.profile?.email?.trim() || null,
22343
+ isStranger: data.user?.is_stranger === true
22344
+ };
22345
+ userProfileCache.set(userId, profile);
22346
+ return profile;
22266
22347
  } catch {
22267
- userNameCache.set(userId, userId);
22268
- return userId;
22348
+ return null;
22269
22349
  }
22270
22350
  }
22351
+ async function resolveUserName(userId) {
22352
+ if (!userId || userId === "unknown") return userId ?? "unknown";
22353
+ const profile = await resolveUserProfile(userId);
22354
+ return profile?.name ?? userId;
22355
+ }
22356
+ async function resolveUserEmail(userId) {
22357
+ if (!userId || userId === "unknown") return null;
22358
+ const profile = await resolveUserProfile(userId);
22359
+ if (!profile) return null;
22360
+ if (profile.isStranger) return null;
22361
+ return profile.email;
22362
+ }
22271
22363
  var currentWs = null;
22272
22364
  var isShuttingDown = false;
22273
22365
  var acquiredLockPath = null;
@@ -22703,6 +22795,17 @@ async function connectSocketMode() {
22703
22795
  if (channel && !isFromBot && evt.user !== botUserId) {
22704
22796
  resetThread(channel, threadTs);
22705
22797
  }
22798
+ if (reconcileIdentityClient && !isFromBot && evt.user && !reconciledSlackSenders.has(evt.user)) {
22799
+ const senderId = evt.user;
22800
+ reconciledSlackSenders.add(senderId);
22801
+ void resolveUserEmail(senderId).then((email2) => {
22802
+ if (email2) {
22803
+ reconcileIdentityClient.reconcile({ platform: "slack", senderId, email: email2 });
22804
+ } else {
22805
+ reconciledSlackSenders.delete(senderId);
22806
+ }
22807
+ });
22808
+ }
22706
22809
  const isAutoFollowed = !isDirectMessage && evt.type === "message" && isThreadReply && !!threadKey && trackedThreads.has(threadKey);
22707
22810
  const shouldEngage = decideSlackEngagement({
22708
22811
  type: evt.type ?? "message",
@@ -36,7 +36,7 @@ import {
36
36
  writeDirectChatSessionState,
37
37
  writeEgressAllowlist,
38
38
  writePersistentClaudeWrapper
39
- } from "./chunk-NAS4DZNG.js";
39
+ } from "./chunk-JTQ6RYGM.js";
40
40
  import "./chunk-XWVM4KPK.js";
41
41
  export {
42
42
  EGRESS_BASELINE_DOMAINS,
@@ -77,4 +77,4 @@ export {
77
77
  writeEgressAllowlist,
78
78
  writePersistentClaudeWrapper
79
79
  };
80
- //# sourceMappingURL=persistent-session-ZQSAZIVM.js.map
80
+ //# sourceMappingURL=persistent-session-5FKI4NCL.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-NAS4DZNG.js";
3
+ } from "./chunk-JTQ6RYGM.js";
4
4
  import "./chunk-XWVM4KPK.js";
5
5
 
6
6
  // src/lib/responsiveness-probe.ts
@@ -427,4 +427,4 @@ export {
427
427
  readAndResetSlackReplyBindingClassifications,
428
428
  readAndResetSlackReplyTargetClassifications
429
429
  };
430
- //# sourceMappingURL=responsiveness-probe-NARLJJGH.js.map
430
+ //# sourceMappingURL=responsiveness-probe-R42UJ5ZR.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.321",
3
+ "version": "0.28.323",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {