@integrity-labs/agt-cli 0.15.1 → 0.15.2

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/mcp/index.js CHANGED
@@ -20985,6 +20985,36 @@ var StdioServerTransport = class {
20985
20985
  }
20986
20986
  };
20987
20987
 
20988
+ // src/token-refresh-selection.ts
20989
+ var REFRESH_WINDOW_MS = 10 * 6e4;
20990
+ function selectIntegrationsToRefresh(input) {
20991
+ const now = input.now ?? Date.now();
20992
+ const windowMs = input.windowMs ?? REFRESH_WINDOW_MS;
20993
+ const oauth = input.integrations.filter((i) => i.auth_type === "oauth2");
20994
+ if (input.integration_id) {
20995
+ const target = oauth.find((i) => i.id === input.integration_id);
20996
+ if (!target) return [];
20997
+ return [{ kind: "force_refresh", integration: target }];
20998
+ }
20999
+ return oauth.map((integration) => {
21000
+ if (!integration.credentials.access_token) {
21001
+ return { kind: "force_refresh", integration };
21002
+ }
21003
+ const expiresAtRaw = integration.credentials.token_expires_at;
21004
+ if (!expiresAtRaw) {
21005
+ return { kind: "force_refresh", integration };
21006
+ }
21007
+ const expiresAt = Date.parse(expiresAtRaw);
21008
+ if (Number.isNaN(expiresAt)) {
21009
+ return { kind: "force_refresh", integration };
21010
+ }
21011
+ if (expiresAt - now < windowMs) {
21012
+ return { kind: "force_refresh", integration };
21013
+ }
21014
+ return { kind: "return_cached", integration };
21015
+ });
21016
+ }
21017
+
20988
21018
  // src/index.ts
20989
21019
  import { spawn } from "child_process";
20990
21020
  var DeliveryTargetSchema = external_exports.union([
@@ -21371,40 +21401,48 @@ server.tool(
21371
21401
  );
21372
21402
  server.tool(
21373
21403
  "token.refresh",
21374
- "Request fresh OAuth tokens for an integration. Returns the new access token directly \u2014 no file-based handoff needed.",
21404
+ "Get a working OAuth access token for an integration. Returns the current cached token when it is still valid (the server-side cron rotates tokens every ~15 minutes) and forces a refresh only when the cached token is expiring or missing. Pass `integration_id` to force-refresh a specific integration after a 401/TokenExpired from the provider.",
21375
21405
  {
21376
- integration_id: external_exports.string().optional().describe("Specific integration UUID to refresh. If omitted, refreshes all expiring tokens.")
21406
+ integration_id: external_exports.string().optional().describe("Specific integration UUID to force-refresh (use after a 401 from the provider). If omitted, returns current tokens for all OAuth integrations, refreshing any that are within ~10 minutes of expiry.")
21377
21407
  },
21378
21408
  async (params) => {
21379
21409
  const integrations = await apiPost("/host/agent-integrations", {
21380
21410
  agent_id: AGT_AGENT_ID
21381
21411
  });
21382
- const TEN_MINUTES_MS = 10 * 6e4;
21383
- const oauthIntegrations = integrations.integrations.filter((i) => {
21384
- if (i.auth_type !== "oauth2") return false;
21385
- if (params.integration_id) return i.id === params.integration_id;
21386
- if (!i.credentials.token_expires_at) return true;
21387
- return new Date(i.credentials.token_expires_at).getTime() - Date.now() < TEN_MINUTES_MS;
21412
+ const decisions = selectIntegrationsToRefresh({
21413
+ integrations: integrations.integrations,
21414
+ integration_id: params.integration_id
21388
21415
  });
21389
- if (oauthIntegrations.length === 0) {
21416
+ if (decisions.length === 0) {
21390
21417
  return {
21391
21418
  content: [
21392
21419
  {
21393
21420
  type: "text",
21394
- text: params.integration_id ? `No OAuth integration found with ID ${params.integration_id}.` : "No expiring OAuth tokens found for this agent."
21421
+ text: params.integration_id ? `No OAuth integration found with ID ${params.integration_id}.` : "No OAuth integrations found for this agent."
21395
21422
  }
21396
21423
  ]
21397
21424
  };
21398
21425
  }
21399
21426
  const results = [];
21400
- for (const integration of oauthIntegrations) {
21427
+ for (const decision of decisions) {
21428
+ const { integration } = decision;
21429
+ if (decision.kind === "return_cached") {
21430
+ results.push({
21431
+ definition_id: integration.definition_id,
21432
+ access_token: integration.credentials.access_token,
21433
+ expires_at: integration.credentials.token_expires_at,
21434
+ source: "cached"
21435
+ });
21436
+ continue;
21437
+ }
21401
21438
  try {
21402
21439
  const refreshed = await apiPost(`/integrations/oauth/${integration.id}/refresh`, {});
21403
21440
  if (refreshed.ok && refreshed.access_token) {
21404
21441
  results.push({
21405
21442
  definition_id: integration.definition_id,
21406
21443
  access_token: refreshed.access_token,
21407
- expires_at: refreshed.expires_at
21444
+ expires_at: refreshed.expires_at,
21445
+ source: "refreshed"
21408
21446
  });
21409
21447
  } else {
21410
21448
  results.push({ definition_id: integration.definition_id, error: true });
@@ -21414,17 +21452,20 @@ server.tool(
21414
21452
  }
21415
21453
  }
21416
21454
  const summary = results.map(
21417
- (r) => r.access_token ? `${r.definition_id}: refreshed (expires ${r.expires_at ?? "unknown"})` : `${r.definition_id}: refresh failed`
21455
+ (r) => r.access_token ? `${r.definition_id}: ${r.source} (expires ${r.expires_at ?? "unknown"})` : `${r.definition_id}: refresh failed`
21418
21456
  );
21419
21457
  return {
21420
21458
  content: [
21421
21459
  {
21422
21460
  type: "text",
21423
21461
  text: JSON.stringify({
21462
+ // Key is `refreshed` for backwards compatibility — entries can now
21463
+ // be either cached or freshly-rotated, distinguished by `source`.
21424
21464
  refreshed: results.filter((r) => r.access_token).map((r) => ({
21425
21465
  definition_id: r.definition_id,
21426
21466
  access_token: r.access_token,
21427
- expires_at: r.expires_at
21467
+ expires_at: r.expires_at,
21468
+ source: r.source
21428
21469
  })),
21429
21470
  failed: results.filter((r) => r.error).map((r) => r.definition_id),
21430
21471
  summary: summary.join("; ")
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {