commonswarm 0.1.51 → 0.1.52

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.
Files changed (2) hide show
  1. package/cswarm.cjs +192 -123
  2. package/package.json +1 -1
package/cswarm.cjs CHANGED
@@ -26624,6 +26624,138 @@ function parseAgentCredentialInput(value, source) {
26624
26624
 
26625
26625
  // src/cloud/renewal.ts
26626
26626
  var import_node_crypto9 = require("node:crypto");
26627
+
26628
+ // src/cloud/renewal-grants.ts
26629
+ var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
26630
+ function nullableString(value, field) {
26631
+ if (value === null) return null;
26632
+ if (typeof value !== "string") {
26633
+ throw new Error(`renewal grant read returned malformed ${field}`);
26634
+ }
26635
+ return value;
26636
+ }
26637
+ function nullableTimestamp(value, field) {
26638
+ const text = nullableString(value, field);
26639
+ if (text !== null && !Number.isFinite(Date.parse(text))) {
26640
+ throw new Error(`renewal grant read returned malformed ${field}`);
26641
+ }
26642
+ return text;
26643
+ }
26644
+ function uuid2(value, field) {
26645
+ if (typeof value !== "string" || !UUID_RE5.test(value)) {
26646
+ throw new Error(`renewal grant read returned malformed ${field}`);
26647
+ }
26648
+ return value.toLowerCase();
26649
+ }
26650
+ function nullableUuid(value, field) {
26651
+ return value === null ? null : uuid2(value, field);
26652
+ }
26653
+ function parseGrant(value) {
26654
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
26655
+ throw new Error("renewal grant read returned a malformed row");
26656
+ }
26657
+ const row = value;
26658
+ if (row.kind !== "timeboxed" && row.kind !== "standing") {
26659
+ throw new Error("renewal grant read returned malformed kind");
26660
+ }
26661
+ const horizon = nullableTimestamp(
26662
+ row.horizon_expires_at,
26663
+ "horizon_expires_at"
26664
+ );
26665
+ if (row.kind === "standing" && horizon !== null || row.kind === "timeboxed" && horizon === null) {
26666
+ throw new Error("renewal grant read returned an invalid kind/horizon pair");
26667
+ }
26668
+ return {
26669
+ renewal_grant_id: uuid2(row.renewal_grant_id, "renewal_grant_id"),
26670
+ principal_id: uuid2(row.principal_id, "principal_id"),
26671
+ kind: row.kind,
26672
+ horizon_expires_at: horizon,
26673
+ bound_device_id: nullableUuid(row.bound_device_id, "bound_device_id"),
26674
+ last_used_at: nullableTimestamp(row.last_used_at, "last_used_at"),
26675
+ last_used_device_id: nullableUuid(
26676
+ row.last_used_device_id,
26677
+ "last_used_device_id"
26678
+ ),
26679
+ last_used_from: nullableString(row.last_used_from, "last_used_from"),
26680
+ new_host_at: nullableTimestamp(row.new_host_at, "new_host_at"),
26681
+ suspended_at: nullableTimestamp(row.suspended_at, "suspended_at"),
26682
+ revoked_at: nullableTimestamp(row.revoked_at, "revoked_at"),
26683
+ token_id: nullableUuid(row.token_id, "token_id"),
26684
+ issued_at: nullableTimestamp(row.issued_at, "issued_at"),
26685
+ token_expires_at: nullableTimestamp(
26686
+ row.token_expires_at,
26687
+ "token_expires_at"
26688
+ ),
26689
+ token_revoked_at: nullableTimestamp(
26690
+ row.token_revoked_at,
26691
+ "token_revoked_at"
26692
+ )
26693
+ };
26694
+ }
26695
+ async function readRenewalGrants(target2, credential, workspaceId2, fetcher = fetch) {
26696
+ const response = await fetcher(readEndpoint(target2), {
26697
+ method: "POST",
26698
+ headers: {
26699
+ authorization: `Bearer ${credential}`,
26700
+ apikey: target2.anonKey,
26701
+ "content-type": "application/json"
26702
+ },
26703
+ body: JSON.stringify({
26704
+ resource: "renewal_grants",
26705
+ workspace_id: workspaceId2
26706
+ }),
26707
+ signal: AbortSignal.timeout(15e3)
26708
+ });
26709
+ if (!response.ok) {
26710
+ throw new Error(`renewal grant read failed (HTTP ${response.status})`);
26711
+ }
26712
+ const body = await response.json().catch(() => null);
26713
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
26714
+ throw new Error("renewal grant read returned malformed JSON");
26715
+ }
26716
+ const grants = body.grants;
26717
+ if (!Array.isArray(grants)) {
26718
+ throw new Error("renewal grant read returned no grants array");
26719
+ }
26720
+ return grants.map(parseGrant);
26721
+ }
26722
+ var STANDING_IDLE_PAUSE_DAYS = 14;
26723
+ var STANDING_RESUME_ACTORS = [
26724
+ "a workspace owner",
26725
+ "an admin",
26726
+ "the member who added the agent"
26727
+ ];
26728
+ function orList(items) {
26729
+ if (items.length === 0) return "";
26730
+ if (items.length === 1) return items[0];
26731
+ return `${items.slice(0, -1).join(", ")}, or ${items[items.length - 1]}`;
26732
+ }
26733
+ var STANDING_RESUME_ACTORS_SENTENCE = orList(STANDING_RESUME_ACTORS);
26734
+ var STANDING_GRANT_RULES = [
26735
+ "Access does not expire.",
26736
+ `${STANDING_IDLE_PAUSE_DAYS} days with no use pauses it; ${STANDING_RESUME_ACTORS_SENTENCE} can resume it.`,
26737
+ "Revoking it is the only permanent stop."
26738
+ ];
26739
+ function standingPausedRenewalMessage(idle) {
26740
+ const cause = idle ? `This standing grant went ${STANDING_IDLE_PAUSE_DAYS} days with no use, so CommonSwarm paused it and refused renewal.` : "This renewal grant is paused, so CommonSwarm refused renewal.";
26741
+ return `${cause} It is not revoked and this agent is not gone. Next step: ${STANDING_RESUME_ACTORS_SENTENCE} runs cswarm grant resume, then this agent continues.`;
26742
+ }
26743
+ function describeRenewalGrant(grant) {
26744
+ const lines = grant.kind === "standing" ? [`Grant: standing \u2014 ${STANDING_GRANT_RULES.join(" ")}`] : [`Grant: timeboxed \u2014 renewal horizon ${grant.horizon_expires_at}.`];
26745
+ if (grant.suspended_at !== null) {
26746
+ lines.push(
26747
+ `PAUSED since ${grant.suspended_at} after ${STANDING_IDLE_PAUSE_DAYS} days with no use. This is not revoked and the agent is not gone. Next step: ${orList(STANDING_RESUME_ACTORS)} runs cswarm grant resume --renewal-grant-id ${grant.renewal_grant_id}`
26748
+ );
26749
+ }
26750
+ if (grant.revoked_at !== null) {
26751
+ lines.push(
26752
+ `REVOKED since ${grant.revoked_at}. This is permanent and cannot be resumed. Next step: mint a new grant if this agent should continue.`
26753
+ );
26754
+ }
26755
+ return lines;
26756
+ }
26757
+
26758
+ // src/cloud/renewal.ts
26627
26759
  var AGENT_TOKEN_DEFAULT_TTL_MS2 = 60 * 60 * 1e3;
26628
26760
  var AGENT_TOKEN_MAX_TTL_MS2 = 8 * 60 * 60 * 1e3;
26629
26761
  var RENEWAL_HORIZON_DEFAULT_MS2 = 30 * 24 * 60 * 60 * 1e3;
@@ -26633,7 +26765,8 @@ function describeMintRenewal(hasExpiry, horizonDays, kind = "timeboxed") {
26633
26765
  return "This credential does not renew itself; re-issue one by hand when it expires.\n";
26634
26766
  }
26635
26767
  if (kind === "standing") {
26636
- return "Standing grant created. This does not expire. Revoke is the only kill switch. The bearer credential still rotates before expiry while a cswarm process remains running and secure local state is available.\n";
26768
+ return `Standing grant created. ${STANDING_GRANT_RULES.join(" ")} The bearer credential still rotates before expiry while a cswarm process remains running and secure local state is available.
26769
+ `;
26637
26770
  }
26638
26771
  const days = Number.isFinite(horizonDays) && horizonDays > 0 ? Math.round(horizonDays) : Math.round(RENEWAL_HORIZON_DEFAULT_MS2 / 864e5);
26639
26772
  return `While a cswarm process remains running and secure local state is available, this credential rotates before expiry. A person is asked to authorise it again in ${days} days. A stopped or idle CLI cannot renew it.
@@ -26644,7 +26777,7 @@ var RENEWAL_LEAD_FLOOR_MS = 5 * 6e4;
26644
26777
  var RENEWAL_LEAD_CEILING_MS = 15 * 6e4;
26645
26778
  var RENEWAL_PENDING_RECOVERY_MS = 60 * 6e4;
26646
26779
  var RENEW_TIMEOUT_MS = 3e4;
26647
- var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
26780
+ var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
26648
26781
  var AGENT_TOKEN_RE4 = /^swm_agt_[A-Za-z0-9_-]{43}$/;
26649
26782
  function renewalDueAt(issuedAt, expiresAt) {
26650
26783
  const lifetime = Math.max(0, expiresAt - issuedAt);
@@ -26803,7 +26936,7 @@ async function requestSuccessor(options) {
26803
26936
  } catch {
26804
26937
  body = {};
26805
26938
  }
26806
- const principalId = typeof body.principal_id === "string" && UUID_RE5.test(body.principal_id) ? body.principal_id.toLowerCase() : null;
26939
+ const principalId = typeof body.principal_id === "string" && UUID_RE6.test(body.principal_id) ? body.principal_id.toLowerCase() : null;
26807
26940
  if (response.status === 400 || response.status === 404) {
26808
26941
  throw new RenewalUnsupported(
26809
26942
  "this deployment does not offer credential renewal yet, so a credential here still has to be re-issued by hand when it expires"
@@ -26838,7 +26971,7 @@ async function requestSuccessor(options) {
26838
26971
  if (reason === "renewal_idle_suspended" || reason === "renewal_grant_suspended") {
26839
26972
  throw new RenewalSuspended(
26840
26973
  reason,
26841
- reason === "renewal_idle_suspended" ? "This standing grant was idle for more than 14 days, so CommonSwarm suspended it and refused renewal. Ask a workspace owner to revoke this grant and mint a new credential before this agent continues." : "This renewal grant is suspended, so CommonSwarm refused renewal. Ask a workspace owner to revoke this grant and mint a new credential before this agent continues."
26974
+ standingPausedRenewalMessage(reason === "renewal_idle_suspended")
26842
26975
  );
26843
26976
  }
26844
26977
  if (reason === "renewal_horizon_reached") {
@@ -26900,7 +27033,7 @@ async function requestSuccessor(options) {
26900
27033
  }
26901
27034
  const tokenId = typeof body.token_id === "string" ? body.token_id : "";
26902
27035
  const runId = typeof body.run_id === "string" ? body.run_id : "";
26903
- if (!UUID_RE5.test(tokenId) || !UUID_RE5.test(runId) || principalId === null) {
27036
+ if (!UUID_RE6.test(tokenId) || !UUID_RE6.test(runId) || principalId === null) {
26904
27037
  throw new RenewalRefused(
26905
27038
  response.status,
26906
27039
  "incomplete_successor",
@@ -27409,7 +27542,7 @@ var MAX_LINK_PAYLOAD_BYTES = 8 * 1024;
27409
27542
  var MAX_LABEL_INPUT_LENGTH = 1024;
27410
27543
  var CONTROL_GLOBAL_RE = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g;
27411
27544
  var ANSI_ESCAPE_GLOBAL_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
27412
- var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
27545
+ var UUID_RE7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
27413
27546
  var STRICT_BASE64URL_RE = /^[A-Za-z0-9_-]+$/;
27414
27547
  var RAW_BASE64_PAYLOAD_CANDIDATE_RE = /^[A-Za-z0-9+/_=-]+$/;
27415
27548
  var CURRENT_INVITE_SCHEME = "cswarm://accept/";
@@ -27460,7 +27593,7 @@ function validatedPayload(value) {
27460
27593
  throw new Error("invite link target is malformed");
27461
27594
  }
27462
27595
  cloudTarget(value.url, value.anon_key);
27463
- if (typeof value.workspace_id !== "string" || !UUID_RE6.test(value.workspace_id)) {
27596
+ if (typeof value.workspace_id !== "string" || !UUID_RE7.test(value.workspace_id)) {
27464
27597
  throw new Error("invite link workspace_id must be a UUID");
27465
27598
  }
27466
27599
  if (typeof value.invitation_token !== "string") {
@@ -27470,7 +27603,7 @@ function validatedPayload(value) {
27470
27603
  if (typeof value.workspace_name !== "string" || typeof value.inviter_display_name !== "string" || value.workspace_name.length > MAX_LABEL_INPUT_LENGTH || value.inviter_display_name.length > MAX_LABEL_INPUT_LENGTH) {
27471
27604
  throw new Error("invite link display labels are malformed");
27472
27605
  }
27473
- if (value.inviter_user_id !== void 0 && (typeof value.inviter_user_id !== "string" || !UUID_RE6.test(value.inviter_user_id))) {
27606
+ if (value.inviter_user_id !== void 0 && (typeof value.inviter_user_id !== "string" || !UUID_RE7.test(value.inviter_user_id))) {
27474
27607
  throw new Error("invite link inviter_user_id must be a UUID");
27475
27608
  }
27476
27609
  return value;
@@ -27670,7 +27803,7 @@ function acceptedResponse(result) {
27670
27803
  }
27671
27804
  return result.response;
27672
27805
  }
27673
- function uuid2(value, field) {
27806
+ function uuid3(value, field) {
27674
27807
  if (typeof value !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
27675
27808
  throw new Error(`server returned a malformed ${field}`);
27676
27809
  }
@@ -28014,7 +28147,7 @@ function cloudAcceptOperations(target2, store2, fetcher = fetch) {
28014
28147
  );
28015
28148
  return {
28016
28149
  status: "accepted",
28017
- workspaceId: uuid2(response.workspace_id, "workspace_id")
28150
+ workspaceId: uuid3(response.workspace_id, "workspace_id")
28018
28151
  };
28019
28152
  } catch (error) {
28020
28153
  if (error instanceof CommandHttpError && error.status === 403) {
@@ -28033,7 +28166,7 @@ function cloudAcceptOperations(target2, store2, fetcher = fetch) {
28033
28166
  if (result.response.status === "accepted") {
28034
28167
  return {
28035
28168
  status: "accepted",
28036
- principalId: uuid2(result.response.principal_id, "principal_id")
28169
+ principalId: uuid3(result.response.principal_id, "principal_id")
28037
28170
  };
28038
28171
  }
28039
28172
  if (String(result.response.reason) === "principal_name_taken") {
@@ -28127,113 +28260,6 @@ function renderCapabilityRevoke(capabilityId, revokedAt) {
28127
28260
  return `Capability link ${capabilityId} was revoked at ${revokedAt}. Anyone who still holds it now gets the same answer as someone holding a link that never existed. Links you have not revoked are unaffected.`;
28128
28261
  }
28129
28262
 
28130
- // src/cloud/renewal-grants.ts
28131
- var UUID_RE7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
28132
- function nullableString(value, field) {
28133
- if (value === null) return null;
28134
- if (typeof value !== "string") {
28135
- throw new Error(`renewal grant read returned malformed ${field}`);
28136
- }
28137
- return value;
28138
- }
28139
- function nullableTimestamp(value, field) {
28140
- const text = nullableString(value, field);
28141
- if (text !== null && !Number.isFinite(Date.parse(text))) {
28142
- throw new Error(`renewal grant read returned malformed ${field}`);
28143
- }
28144
- return text;
28145
- }
28146
- function uuid3(value, field) {
28147
- if (typeof value !== "string" || !UUID_RE7.test(value)) {
28148
- throw new Error(`renewal grant read returned malformed ${field}`);
28149
- }
28150
- return value.toLowerCase();
28151
- }
28152
- function nullableUuid(value, field) {
28153
- return value === null ? null : uuid3(value, field);
28154
- }
28155
- function parseGrant(value) {
28156
- if (!value || typeof value !== "object" || Array.isArray(value)) {
28157
- throw new Error("renewal grant read returned a malformed row");
28158
- }
28159
- const row = value;
28160
- if (row.kind !== "timeboxed" && row.kind !== "standing") {
28161
- throw new Error("renewal grant read returned malformed kind");
28162
- }
28163
- const horizon = nullableTimestamp(
28164
- row.horizon_expires_at,
28165
- "horizon_expires_at"
28166
- );
28167
- if (row.kind === "standing" && horizon !== null || row.kind === "timeboxed" && horizon === null) {
28168
- throw new Error("renewal grant read returned an invalid kind/horizon pair");
28169
- }
28170
- return {
28171
- renewal_grant_id: uuid3(row.renewal_grant_id, "renewal_grant_id"),
28172
- principal_id: uuid3(row.principal_id, "principal_id"),
28173
- kind: row.kind,
28174
- horizon_expires_at: horizon,
28175
- bound_device_id: nullableUuid(row.bound_device_id, "bound_device_id"),
28176
- last_used_at: nullableTimestamp(row.last_used_at, "last_used_at"),
28177
- last_used_device_id: nullableUuid(
28178
- row.last_used_device_id,
28179
- "last_used_device_id"
28180
- ),
28181
- last_used_from: nullableString(row.last_used_from, "last_used_from"),
28182
- new_host_at: nullableTimestamp(row.new_host_at, "new_host_at"),
28183
- suspended_at: nullableTimestamp(row.suspended_at, "suspended_at"),
28184
- revoked_at: nullableTimestamp(row.revoked_at, "revoked_at"),
28185
- token_id: nullableUuid(row.token_id, "token_id"),
28186
- issued_at: nullableTimestamp(row.issued_at, "issued_at"),
28187
- token_expires_at: nullableTimestamp(
28188
- row.token_expires_at,
28189
- "token_expires_at"
28190
- ),
28191
- token_revoked_at: nullableTimestamp(
28192
- row.token_revoked_at,
28193
- "token_revoked_at"
28194
- )
28195
- };
28196
- }
28197
- async function readRenewalGrants(target2, credential, workspaceId2, fetcher = fetch) {
28198
- const response = await fetcher(readEndpoint(target2), {
28199
- method: "POST",
28200
- headers: {
28201
- authorization: `Bearer ${credential}`,
28202
- apikey: target2.anonKey,
28203
- "content-type": "application/json"
28204
- },
28205
- body: JSON.stringify({
28206
- resource: "renewal_grants",
28207
- workspace_id: workspaceId2
28208
- }),
28209
- signal: AbortSignal.timeout(15e3)
28210
- });
28211
- if (!response.ok) {
28212
- throw new Error(`renewal grant read failed (HTTP ${response.status})`);
28213
- }
28214
- const body = await response.json().catch(() => null);
28215
- if (!body || typeof body !== "object" || Array.isArray(body)) {
28216
- throw new Error("renewal grant read returned malformed JSON");
28217
- }
28218
- const grants = body.grants;
28219
- if (!Array.isArray(grants)) {
28220
- throw new Error("renewal grant read returned no grants array");
28221
- }
28222
- return grants.map(parseGrant);
28223
- }
28224
- function describeRenewalGrant(grant) {
28225
- const lines = grant.kind === "standing" ? ["Grant: standing \u2014 does not expire; revoke is the only kill switch."] : [`Grant: timeboxed \u2014 renewal horizon ${grant.horizon_expires_at}.`];
28226
- if (grant.suspended_at !== null) {
28227
- lines.push(
28228
- `SUSPENDED since ${grant.suspended_at}. Next step: ask a workspace owner to revoke this grant and mint a new credential.`
28229
- );
28230
- }
28231
- if (grant.revoked_at !== null) {
28232
- lines.push(`REVOKED since ${grant.revoked_at}. Next step: mint a new grant if this agent should continue.`);
28233
- }
28234
- return lines;
28235
- }
28236
-
28237
28263
  // src/cloud/workspaces.ts
28238
28264
  var UUID_RE8 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
28239
28265
  var ROLES = /* @__PURE__ */ new Set(["owner", "admin", "member"]);
@@ -31102,7 +31128,7 @@ var DELIVERY_HANDLED_OUTCOMES = new Set(
31102
31128
  var DELIVERY_PROVIDER_PROVEN_OUTCOMES = new Set(
31103
31129
  [...DELIVERY_ACK_OUTCOMES].filter((outcome) => outcome === "replied")
31104
31130
  );
31105
- function orList(values2) {
31131
+ function orList2(values2) {
31106
31132
  return values2.length <= 1 ? values2.join("") : `${values2.slice(0, -1).join(", ")}, or ${values2[values2.length - 1]}`;
31107
31133
  }
31108
31134
  var DELIVERY_REQUEST_TIMEOUT_MS = 3e4;
@@ -31448,13 +31474,13 @@ function assertAckRequest(request) {
31448
31474
  checkedUuidRequest(request.listenerInstanceId, "listenerInstanceId");
31449
31475
  if (!DELIVERY_ACK_OUTCOMES.has(request.outcome)) {
31450
31476
  throw new Error(
31451
- `a delivery outcome must be ${orList([...DELIVERY_ACK_OUTCOMES])}`
31477
+ `a delivery outcome must be ${orList2([...DELIVERY_ACK_OUTCOMES])}`
31452
31478
  );
31453
31479
  }
31454
31480
  if (request.outcome === "failed_terminal") {
31455
31481
  if (typeof request.lastErrorCode !== "string" || !FAILED_TERMINAL_CODES_SET.has(request.lastErrorCode)) {
31456
31482
  throw new Error(
31457
- `a failed_terminal acknowledgement requires one of ${orList([...FAILED_TERMINAL_CODES_SET])}`
31483
+ `a failed_terminal acknowledgement requires one of ${orList2([...FAILED_TERMINAL_CODES_SET])}`
31458
31484
  );
31459
31485
  }
31460
31486
  } else if (request.lastErrorCode !== null) {
@@ -41978,6 +42004,7 @@ var KNOWN_FLAGS = /* @__PURE__ */ new Set([
41978
42004
  "permissions",
41979
42005
  "principal-id",
41980
42006
  "provider",
42007
+ "renewal-grant-id",
41981
42008
  "repo",
41982
42009
  "reveal-anon-key",
41983
42010
  "route",
@@ -42029,8 +42056,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
42029
42056
  ]);
42030
42057
  var UUID_RE23 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
42031
42058
  function packageVersion() {
42032
- if ("0.1.51".length > 0) {
42033
- return "0.1.51";
42059
+ if ("0.1.52".length > 0) {
42060
+ return "0.1.52";
42034
42061
  }
42035
42062
  try {
42036
42063
  const value = JSON.parse(
@@ -42191,6 +42218,7 @@ Usage:
42191
42218
  cswarm token mint [--url <url> --anon-key <key>] [--workspace-id <uuid>] --principal-id <uuid> --run-id <uuid> --task-id <uuid> --epoch <n> [--ttl-ms <ms>] [--renewal-horizon-days <1..90> | --standing --confirm-standing]
42192
42219
  cswarm token revoke [--url <url> --anon-key <key>] [--workspace-id <uuid>] --token-id <uuid>
42193
42220
  cswarm token revoke ${requiredAgentCredential} [--url <url> --anon-key <key>] --workspace-id <uuid> [--token-id <uuid>]
42221
+ cswarm grant resume [--url <url> --anon-key <key>] [--workspace-id <uuid>] --renewal-grant-id <uuid> [--json] # lifts an idle pause; a REVOKED grant is refused
42194
42222
  cswarm link new [--url <url> --anon-key <key>] [--workspace-id <uuid>] --task-id <uuid> [--ttl-ms <ms>] [--site <origin>] [--json]
42195
42223
  cswarm link revoke [--url <url> --anon-key <key>] [--workspace-id <uuid>] --capability-id <uuid> [--json]
42196
42224
  cswarm command <kind> [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [command fields]
@@ -43333,6 +43361,43 @@ async function runToken(args) {
43333
43361
  expiresAt
43334
43362
  }));
43335
43363
  }
43364
+ async function runGrant(args) {
43365
+ const action = args.positionals[1];
43366
+ args.assertShape(
43367
+ [
43368
+ ...TARGET_FLAGS,
43369
+ "workspace-id",
43370
+ "renewal-grant-id",
43371
+ /* `--json` accepted, no effect — see the note on `runInvite`. D-064. */
43372
+ "json"
43373
+ ],
43374
+ 2
43375
+ );
43376
+ if (action !== "resume") {
43377
+ throw new UsageError(`unknown grant command: ${action ?? "(missing)"}`);
43378
+ }
43379
+ const renewalGrantId = args.required("renewal-grant-id");
43380
+ const cloud = await target(args);
43381
+ const human = await humanCredential(args, cloud);
43382
+ const workspace = await workspaceId(args, cloud, human);
43383
+ const response = acceptedConnect(
43384
+ "grant resume",
43385
+ await sendConnectWithPending(
43386
+ new ThinCommandClient(cloud),
43387
+ human,
43388
+ workspace,
43389
+ { kind: "resume_renewal_grant", renewal_grant_id: renewalGrantId }
43390
+ )
43391
+ );
43392
+ const resumedAt = response.resumed_at ?? null;
43393
+ process.stdout.write(
43394
+ `Grant resumed${resumedAt === null ? "" : ` at ${resumedAt}`}.
43395
+ Renewal is allowed again. Nothing has reached the agent yet: it starts renewing when its own cswarm process next tries, so start that process if it is not running.
43396
+ The idle clock restarts now \u2014 another ${STANDING_IDLE_PAUSE_DAYS} days with no use pauses it again.
43397
+ Confirm with: cswarm whoami --agent-token-file <path>
43398
+ `
43399
+ );
43400
+ }
43336
43401
  async function runTokenRevoke(args) {
43337
43402
  if (hasAgentCredential(args)) {
43338
43403
  args.assertShape(
@@ -47463,6 +47528,10 @@ async function main() {
47463
47528
  await runToken(args);
47464
47529
  return;
47465
47530
  }
47531
+ if (verb === "grant") {
47532
+ await runGrant(args);
47533
+ return;
47534
+ }
47466
47535
  if (verb === "link") {
47467
47536
  await runLink(args);
47468
47537
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commonswarm",
3
- "version": "0.1.51",
3
+ "version": "0.1.52",
4
4
  "description": "CommonSwarm CLI — coordination for teams where people and AI agents work side by side.",
5
5
  "bin": {
6
6
  "cswarm": "cswarm.cjs"