@samva/cli 0.9.0 → 0.10.0

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 (3) hide show
  1. package/AGENTS.md +27 -3
  2. package/dist/bin.mjs +1289 -312
  3. package/package.json +7 -7
package/dist/bin.mjs CHANGED
@@ -13982,7 +13982,7 @@ var layer12 = /* @__PURE__ */ layer.pipe(/* @__PURE__ */ provideMerge(/* @__PURE
13982
13982
  // package.json
13983
13983
  var package_default = {
13984
13984
  name: "@samva/cli",
13985
- version: "0.9.0",
13985
+ version: "0.10.0",
13986
13986
  description: "Samva CLI \u2014 email and platform operations from your terminal",
13987
13987
  keywords: [
13988
13988
  "cli",
@@ -14037,16 +14037,16 @@ var package_default = {
14037
14037
  "@types/node": "catalog:",
14038
14038
  "better-auth": "catalog:",
14039
14039
  effect: "catalog:effect",
14040
- samva: "workspace:0.12.0",
14040
+ samva: "workspace:0.13.0",
14041
14041
  typescript: "catalog:",
14042
14042
  vite: "~8.3.0",
14043
14043
  vitest: "catalog:"
14044
14044
  },
14045
14045
  optionalDependencies: {
14046
- "@samva/cli-darwin-arm64": "workspace:0.9.0",
14047
- "@samva/cli-darwin-x64": "workspace:0.9.0",
14048
- "@samva/cli-linux-arm64": "workspace:0.9.0",
14049
- "@samva/cli-linux-x64": "workspace:0.9.0"
14046
+ "@samva/cli-darwin-arm64": "workspace:0.10.0",
14047
+ "@samva/cli-darwin-x64": "workspace:0.10.0",
14048
+ "@samva/cli-linux-arm64": "workspace:0.10.0",
14049
+ "@samva/cli-linux-x64": "workspace:0.10.0"
14050
14050
  },
14051
14051
  engines: {
14052
14052
  node: ">=18"
@@ -43621,6 +43621,121 @@ var DIAGNOSTIC_CODES = codes2({
43621
43621
  channelOnly: true
43622
43622
  }
43623
43623
  });
43624
+ // ../sdk/dist/inline-attachments-B56eS0MF.js
43625
+ var SDK_VERSION = "0.13.0";
43626
+ var CLIENT_ATTRIBUTION_HEADER = "x-samva-client";
43627
+ var clientAttribution = (surface) => `${surface}/${SDK_VERSION}`;
43628
+ var MediaUploadError = class extends Error {
43629
+ _tag = "MediaUploadError";
43630
+ filename;
43631
+ mediaId;
43632
+ status;
43633
+ cause;
43634
+ constructor(input) {
43635
+ super(input.status === undefined ? `Uploading attachment "${input.filename}" (${input.mediaId}) failed before storage answered` : `Uploading attachment "${input.filename}" (${input.mediaId}) failed with storage status ${input.status}`, { cause: input.cause });
43636
+ this.name = "MediaUploadError";
43637
+ this.filename = input.filename;
43638
+ this.mediaId = input.mediaId;
43639
+ this.status = input.status;
43640
+ this.cause = input.cause;
43641
+ }
43642
+ };
43643
+ var isRecord = (value) => typeof value === "object" && value !== null;
43644
+ var attachmentsOf = (payload) => {
43645
+ const email = payload.email;
43646
+ if (!isRecord(email))
43647
+ return [];
43648
+ const attachments = email.attachments;
43649
+ return Array.isArray(attachments) ? attachments : [];
43650
+ };
43651
+ var decodedBase64Bytes = (content) => {
43652
+ const length = content.length;
43653
+ if (length === 0)
43654
+ return 0;
43655
+ let padding = 0;
43656
+ if (content.endsWith("=="))
43657
+ padding = 2;
43658
+ else if (content.endsWith("="))
43659
+ padding = 1;
43660
+ return Math.floor(length * 3 / 4) - padding;
43661
+ };
43662
+ var base64ToBytes = (content) => {
43663
+ let binary;
43664
+ try {
43665
+ binary = atob(content);
43666
+ } catch {
43667
+ return;
43668
+ }
43669
+ const bytes = new Uint8Array(binary.length);
43670
+ for (let index = 0;index < binary.length; index += 1)
43671
+ bytes[index] = binary.charCodeAt(index);
43672
+ return bytes;
43673
+ };
43674
+ var planInlineUploads = (payload) => {
43675
+ const inline = [];
43676
+ for (const [index, entry] of attachmentsOf(payload).entries()) {
43677
+ if (!isRecord(entry))
43678
+ continue;
43679
+ const attachment = entry;
43680
+ if (typeof attachment.content !== "string")
43681
+ continue;
43682
+ if (attachment.mediaId !== undefined)
43683
+ return [];
43684
+ inline.push({
43685
+ index,
43686
+ filename: typeof attachment.filename === "string" ? attachment.filename : "attachment",
43687
+ contentType: typeof attachment.contentType === "string" ? attachment.contentType : "application/octet-stream",
43688
+ content: attachment.content,
43689
+ sizeBytes: typeof attachment.size === "number" ? attachment.size : decodedBase64Bytes(attachment.content)
43690
+ });
43691
+ }
43692
+ let remaining = inline.reduce((total, upload) => total + upload.sizeBytes, 0);
43693
+ if (remaining <= 4194304)
43694
+ return [];
43695
+ const chosen = [];
43696
+ const largestFirst = [...inline].sort((left, right) => right.sizeBytes - left.sizeBytes || left.index - right.index);
43697
+ for (const { content, ...upload } of largestFirst) {
43698
+ if (remaining <= 4194304)
43699
+ break;
43700
+ const bytes = base64ToBytes(content);
43701
+ if (bytes === undefined)
43702
+ return [];
43703
+ chosen.push({
43704
+ ...upload,
43705
+ bytes
43706
+ });
43707
+ remaining -= upload.sizeBytes;
43708
+ }
43709
+ return chosen;
43710
+ };
43711
+ var mediaCreateBody = (upload) => ({
43712
+ filename: upload.filename,
43713
+ contentType: upload.contentType,
43714
+ sizeBytes: upload.sizeBytes,
43715
+ purpose: "attachment"
43716
+ });
43717
+ var uploadContentType = (headers) => Object.entries(headers).find(([name]) => name.toLowerCase() === "content-type")?.[1];
43718
+ var withUploadedAttachments = (payload, uploaded) => {
43719
+ const email = payload.email;
43720
+ const attachments = email.attachments.map((entry, index) => {
43721
+ const replacement = uploaded.get(index);
43722
+ if (replacement === undefined)
43723
+ return entry;
43724
+ const { content: _content, ...rest } = entry;
43725
+ return {
43726
+ ...rest,
43727
+ mediaId: replacement.mediaId
43728
+ };
43729
+ });
43730
+ return {
43731
+ ...payload,
43732
+ email: {
43733
+ ...email,
43734
+ attachments
43735
+ }
43736
+ };
43737
+ };
43738
+
43624
43739
  // ../sdk/dist/normalize-B79uJIeb.js
43625
43740
  function toRecipientArray(recipient) {
43626
43741
  return Array.isArray(recipient) ? recipient : [recipient];
@@ -43690,11 +43805,6 @@ function buildMessagesSendPayload(input) {
43690
43805
  };
43691
43806
  }
43692
43807
 
43693
- // ../sdk/dist/client-attribution-BTWYSXxo.js
43694
- var SDK_VERSION = "0.12.0";
43695
- var CLIENT_ATTRIBUTION_HEADER = "x-samva-client";
43696
- var clientAttribution = (surface) => `${surface}/${SDK_VERSION}`;
43697
-
43698
43808
  // ../../node_modules/.bun/effect@4.0.0/node_modules/effect/dist/Random.js
43699
43809
  var Random2 = Random;
43700
43810
  var randomWith = (f) => withFiber2((fiber) => succeed6(f(fiber.getRef(Random2))));
@@ -43946,6 +44056,7 @@ var baseUrl = () => {
43946
44056
 
43947
44057
  // ../../node_modules/.bun/effect@4.0.0/node_modules/effect/dist/http/HttpClientRequest.js
43948
44058
  var TypeId40 = "~effect/http/HttpClientRequest";
44059
+ var isHttpClientRequest = (u) => hasProperty(u, TypeId40);
43949
44060
  var Proto13 = {
43950
44061
  [TypeId40]: TypeId40,
43951
44062
  ...BaseProto,
@@ -44044,6 +44155,7 @@ var setHash = /* @__PURE__ */ dual(2, (self, hash) => makeWith(self.method, self
44044
44155
  var setBody = /* @__PURE__ */ dual(2, (self, body) => {
44045
44156
  return makeWith(self.method, self.url, self.urlParams, self.hash, updateHeaders(self.headers, body), body);
44046
44157
  });
44158
+ var bodyUint8Array = /* @__PURE__ */ dual((args) => isHttpClientRequest(args[0]), (self, body, contentType) => setBody(self, uint8Array(body, contentType)));
44047
44159
  var bodyFormData = /* @__PURE__ */ dual(2, (self, body) => setBody(self, formData(body)));
44048
44160
  function toUrl(self) {
44049
44161
  const r = make32(self.url, self.urlParams, getOrUndefined(self.hash));
@@ -46053,7 +46165,7 @@ var fetch2 = /* @__PURE__ */ make34((request, url, signal, fiber) => {
46053
46165
  });
46054
46166
  var layer15 = /* @__PURE__ */ layerMergedContext(/* @__PURE__ */ succeed6(fetch2));
46055
46167
 
46056
- // ../sdk/dist/client-Cj1bqIEe.js
46168
+ // ../sdk/dist/client-DYPNDvVU.js
46057
46169
  var Sensitive = (schema) => RedactedFromValue(schema);
46058
46170
  var SensitiveString = Sensitive(String4);
46059
46171
  var ABSOLUTE_ISO_INSTANT_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?(Z|([+-])(\d{2}):(\d{2}))$/;
@@ -46290,6 +46402,12 @@ var CampaignFooterRequiredError = class extends TaggedError3()("CampaignFooterRe
46290
46402
  };
46291
46403
  var ExternalServiceError = class extends TaggedError3()("ExternalServiceError", Struct({ message: String4 })) {
46292
46404
  };
46405
+ var SenderNotReadyError = class extends TaggedError3()("SenderNotReadyError", Struct({
46406
+ message: String4,
46407
+ sender: String4,
46408
+ retryAfterSeconds: optionalKey2(Union2([Finite.check(isFinite4().annotate({ expected: "a finite number" })), Null2]))
46409
+ })) {
46410
+ };
46293
46411
  var CampaignRecipientId = String4.check(isPattern2(/* @__PURE__ */ new RegExp("^crcpt_[0-9a-hjkmnp-tv-z]{16,24}$", "u")).annotate({
46294
46412
  expected: "a string matching the RegExp ^crcpt_[0-9a-hjkmnp-tv-z]{16,24}$",
46295
46413
  identifier: "CampaignRecipientId"
@@ -46327,11 +46445,11 @@ var ContactPreferences = Struct({
46327
46445
  }), Null2]))
46328
46446
  }), Null2]))
46329
46447
  }).annotate({ identifier: "ContactPreferences" });
46330
- var UnknownRecord = Record(String4, JsonValue).annotate({ identifier: "UnknownRecord" });
46331
46448
  var BulkUpdateResult = Struct({
46332
46449
  updated: Finite.check(isInt().annotate({ expected: "an integer" })).check(isGreaterThanOrEqualTo2(0).annotate({ expected: "a value greater than or equal to 0" })),
46333
46450
  failed: Finite.check(isInt().annotate({ expected: "an integer" })).check(isGreaterThanOrEqualTo2(0).annotate({ expected: "a value greater than or equal to 0" }))
46334
46451
  }).annotate({ identifier: "BulkUpdateResult" });
46452
+ var UnknownRecord = Record(String4, JsonValue).annotate({ identifier: "UnknownRecord" });
46335
46453
  var CustomFieldDefinitionId = String4.check(isPattern2(/* @__PURE__ */ new RegExp("^cfield_[0-9a-hjkmnp-tv-z]{16,24}$", "u")).annotate({
46336
46454
  expected: "a string matching the RegExp ^cfield_[0-9a-hjkmnp-tv-z]{16,24}$",
46337
46455
  identifier: "CustomFieldDefinitionId"
@@ -46586,6 +46704,36 @@ var ExtensionRun = Struct({
46586
46704
  error: Union2([String4, Null2]),
46587
46705
  logs: ArraySchema(String4)
46588
46706
  }).annotate({ identifier: "ExtensionRun" });
46707
+ var ExtensionPermissionDiff = Struct({
46708
+ added: ArraySchema(Union2([
46709
+ Literal2("permission:read"),
46710
+ Literal2("permission:update"),
46711
+ Literal2("permission:send"),
46712
+ Literal2("permission:quarantine.read"),
46713
+ Literal2("event:mailbox.message.received"),
46714
+ Literal2("event:mailbox.message.sent"),
46715
+ Literal2("event:mailbox.action.pending_approval"),
46716
+ Literal2("event:mailbox.message.quarantined"),
46717
+ Literal2("event:mailbox.message.released"),
46718
+ Literal2("event:mailbox.message.discarded")
46719
+ ])),
46720
+ removed: ArraySchema(Union2([
46721
+ Literal2("permission:read"),
46722
+ Literal2("permission:update"),
46723
+ Literal2("permission:send"),
46724
+ Literal2("permission:quarantine.read"),
46725
+ Literal2("event:mailbox.message.received"),
46726
+ Literal2("event:mailbox.message.sent"),
46727
+ Literal2("event:mailbox.action.pending_approval"),
46728
+ Literal2("event:mailbox.message.quarantined"),
46729
+ Literal2("event:mailbox.message.released"),
46730
+ Literal2("event:mailbox.message.discarded")
46731
+ ]))
46732
+ }).annotate({ identifier: "ExtensionPermissionDiff" });
46733
+ var UserId = String4.check(isPattern2(/* @__PURE__ */ new RegExp("^user_[0-9a-hjkmnp-tv-z]{16,24}$", "u")).annotate({
46734
+ expected: "a string matching the RegExp ^user_[0-9a-hjkmnp-tv-z]{16,24}$",
46735
+ identifier: "UserId"
46736
+ })).pipe(brand("UserId"));
46589
46737
  var ExtensionBundle = Struct({
46590
46738
  sha256: String4,
46591
46739
  sizeBytes: Finite.check(isInt().annotate({ expected: "an integer" }))
@@ -46636,6 +46784,39 @@ var MailboxPolicyId = String4.check(isPattern2(/* @__PURE__ */ new RegExp("^mbxp
46636
46784
  expected: "a string matching the RegExp ^mbxpol_[0-9a-hjkmnp-tv-z]{16,24}$",
46637
46785
  identifier: "MailboxPolicyId"
46638
46786
  })).pipe(brand("MailboxPolicyId"));
46787
+ var OnboardingReviewRequiredError = class extends TaggedError3()("OnboardingReviewRequiredError", Struct({
46788
+ message: String4,
46789
+ code: Union2([
46790
+ Literal2("review_required"),
46791
+ Literal2("review_in_progress"),
46792
+ Literal2("information_required"),
46793
+ Literal2("review_rejected"),
46794
+ Literal2("identity_review_required"),
46795
+ Literal2("identity_review_rejected"),
46796
+ Literal2("identity_changed")
46797
+ ]),
46798
+ decision: Union2([
46799
+ Literal2("undecided"),
46800
+ Literal2("approved"),
46801
+ Literal2("rejected")
46802
+ ]),
46803
+ stage: Union2([
46804
+ Literal2("collecting"),
46805
+ Literal2("automated_review"),
46806
+ Literal2("manual_review"),
46807
+ Literal2("information_requested"),
46808
+ Literal2("complete")
46809
+ ]),
46810
+ nextAction: Union2([
46811
+ Literal2("wait_for_review"),
46812
+ Literal2("provide_information"),
46813
+ Literal2("verify_sending_identity"),
46814
+ Literal2("reapply"),
46815
+ Literal2("contact_support")
46816
+ ]),
46817
+ identityId: optionalKey2(Union2([String4, Null2]))
46818
+ })) {
46819
+ };
46639
46820
  var MailboxAgentActivity = Struct({
46640
46821
  actions: Struct({
46641
46822
  byType: ArraySchema(Struct({
@@ -46709,10 +46890,6 @@ var MailboxGrantId = String4.check(isPattern2(/* @__PURE__ */ new RegExp("^mbxac
46709
46890
  expected: "a string matching the RegExp ^mbxacl_[0-9a-hjkmnp-tv-z]{16,24}$",
46710
46891
  identifier: "MailboxGrantId"
46711
46892
  })).pipe(brand("MailboxGrantId"));
46712
- var UserId = String4.check(isPattern2(/* @__PURE__ */ new RegExp("^user_[0-9a-hjkmnp-tv-z]{16,24}$", "u")).annotate({
46713
- expected: "a string matching the RegExp ^user_[0-9a-hjkmnp-tv-z]{16,24}$",
46714
- identifier: "UserId"
46715
- })).pipe(brand("UserId"));
46716
46893
  var MailboxGrantRole = Union2([
46717
46894
  Literal2("admin"),
46718
46895
  Literal2("collaborator"),
@@ -46819,39 +46996,6 @@ var EmailSender = Union2([Struct({
46819
46996
  email: String4.check(isMinLength(1).annotate({ expected: "a value with a length of at least 1" })),
46820
46997
  name: optionalKey2(Union2([String4, Null2]))
46821
46998
  }), Null2]).annotate({ identifier: "EmailSender" });
46822
- var OnboardingReviewRequiredError = class extends TaggedError3()("OnboardingReviewRequiredError", Struct({
46823
- message: String4,
46824
- code: Union2([
46825
- Literal2("review_required"),
46826
- Literal2("review_in_progress"),
46827
- Literal2("information_required"),
46828
- Literal2("review_rejected"),
46829
- Literal2("identity_review_required"),
46830
- Literal2("identity_review_rejected"),
46831
- Literal2("identity_changed")
46832
- ]),
46833
- decision: Union2([
46834
- Literal2("undecided"),
46835
- Literal2("approved"),
46836
- Literal2("rejected")
46837
- ]),
46838
- stage: Union2([
46839
- Literal2("collecting"),
46840
- Literal2("automated_review"),
46841
- Literal2("manual_review"),
46842
- Literal2("information_requested"),
46843
- Literal2("complete")
46844
- ]),
46845
- nextAction: Union2([
46846
- Literal2("wait_for_review"),
46847
- Literal2("provide_information"),
46848
- Literal2("verify_sending_identity"),
46849
- Literal2("reapply"),
46850
- Literal2("contact_support")
46851
- ]),
46852
- identityId: optionalKey2(Union2([String4, Null2]))
46853
- })) {
46854
- };
46855
46999
  var DeliveryUnavailableError = class extends TaggedError3()("DeliveryUnavailableError", Struct({
46856
47000
  message: String4,
46857
47001
  retryAfterSeconds: Finite.check(isFinite4().annotate({ expected: "a finite number" }))
@@ -47319,7 +47463,7 @@ var BrandFooter = Struct({
47319
47463
  }).annotate({ identifier: "BrandFooter" });
47320
47464
  var EmailAttachment = Struct({
47321
47465
  filename: String4,
47322
- content: optionalKey2(Union2([String4.check(isPattern2(/* @__PURE__ */ new RegExp("^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$", "u")).annotate({ expected: "a string matching the RegExp ^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$" })), Null2])),
47466
+ content: optionalKey2(Union2([String4, Null2])),
47323
47467
  mediaId: optionalKey2(Union2([MediaId, Null2])),
47324
47468
  contentType: String4,
47325
47469
  size: Finite.check(isInt().annotate({ expected: "an integer" })).check(isLessThanOrEqualTo3(26214400).annotate({ expected: "a value less than or equal to 26214400" })).check(isGreaterThan2(0).annotate({ expected: "a value greater than 0" }))
@@ -48135,6 +48279,22 @@ var ExtensionVersionRef = Struct({
48135
48279
  id: ExtensionVersionId,
48136
48280
  version: String4
48137
48281
  }).annotate({ identifier: "ExtensionVersionRef" });
48282
+ Struct({
48283
+ version: optionalKey2(Union2([Union2([String4.check(isPattern2(/* @__PURE__ */ new RegExp("^\\d{1,6}\\.\\d{1,6}\\.\\d{1,6}(?:-[0-9A-Za-z.-]{1,64})?$", "u")).annotate({ expected: "a string matching the RegExp ^\\d{1,6}\\.\\d{1,6}\\.\\d{1,6}(?:-[0-9A-Za-z.-]{1,64})?$" })), ExtensionVersionId]), Null2])),
48284
+ acceptPermissions: optionalKey2(Union2([ArraySchema(Union2([
48285
+ Literal2("permission:read"),
48286
+ Literal2("permission:update"),
48287
+ Literal2("permission:send"),
48288
+ Literal2("permission:quarantine.read"),
48289
+ Literal2("event:mailbox.message.received"),
48290
+ Literal2("event:mailbox.message.sent"),
48291
+ Literal2("event:mailbox.action.pending_approval"),
48292
+ Literal2("event:mailbox.message.quarantined"),
48293
+ Literal2("event:mailbox.message.released"),
48294
+ Literal2("event:mailbox.message.discarded")
48295
+ ])), Null2])),
48296
+ dryRun: optionalKey2(Union2([Boolean3, Null2]))
48297
+ }).annotate({ identifier: "UpgradeExtensionPayload" });
48138
48298
  var ExtensionRunList = Struct({ items: ArraySchema(ExtensionRunSummary) }).annotate({ identifier: "ExtensionRunList" });
48139
48299
  var ExtensionVersion = Struct({
48140
48300
  id: ExtensionVersionId,
@@ -49398,6 +49558,17 @@ var ExtensionInstallation = Struct({
49398
49558
  updatedAt: String4,
49399
49559
  disabledAt: Union2([String4, Null2])
49400
49560
  }).annotate({ identifier: "ExtensionInstallation" });
49561
+ var ExtensionVersionChange = Struct({
49562
+ id: String4,
49563
+ organizationId: OrganizationId,
49564
+ installationId: ExtensionInstallationId,
49565
+ extensionId: ExtensionId,
49566
+ fromVersion: ExtensionVersionRef,
49567
+ toVersion: ExtensionVersionRef,
49568
+ permissionDiff: ExtensionPermissionDiff,
49569
+ changedBy: UserId,
49570
+ changedAt: String4
49571
+ }).annotate({ identifier: "ExtensionVersionChange" });
49401
49572
  var Extension = Struct({
49402
49573
  id: ExtensionId,
49403
49574
  name: String4,
@@ -49663,6 +49834,14 @@ var InstallExtensionResponse = Struct({
49663
49834
  webhookSecret: SensitiveString
49664
49835
  }), Null2])
49665
49836
  }).annotate({ identifier: "InstallExtensionResponse" });
49837
+ var UpgradeExtensionResponse = Struct({
49838
+ installation: ExtensionInstallation,
49839
+ fromVersion: ExtensionVersionRef,
49840
+ toVersion: ExtensionVersionRef,
49841
+ permissionDiff: ExtensionPermissionDiff,
49842
+ dryRun: Boolean3,
49843
+ versionChange: Union2([ExtensionVersionChange, Null2])
49844
+ }).annotate({ identifier: "UpgradeExtensionResponse" });
49666
49845
  var ExtensionPage = Struct({
49667
49846
  items: ArraySchema(Extension),
49668
49847
  nextCursor: Union2([String4, Null2])
@@ -50254,6 +50433,7 @@ var CampaignsScheduleRun422 = Union2([
50254
50433
  ]);
50255
50434
  var CampaignsScheduleRun500 = InternalError;
50256
50435
  var CampaignsScheduleRun502 = ExternalServiceError;
50436
+ var CampaignsScheduleRun503 = SenderNotReadyError;
50257
50437
  var CampaignsScheduleRun504 = GatewayTimeoutError;
50258
50438
  var CampaignsGetRunPathParams = Struct({
50259
50439
  id: CampaignId,
@@ -50550,8 +50730,6 @@ var ContactGroupsRemoveMembers422 = ValidationError;
50550
50730
  var ContactGroupsRemoveMembers500 = InternalError;
50551
50731
  var ContactGroupsRemoveMembers504 = GatewayTimeoutError;
50552
50732
  var ContactGroupsPreviewRequestJson = Struct({ criteria: Struct({
50553
- contactTypes: optionalKey2(Union2([ArraySchema(String4), Null2])),
50554
- capabilities: optionalKey2(Union2([ArraySchema(String4), Null2])),
50555
50733
  tags: optionalKey2(Union2([ArraySchema(String4), Null2])),
50556
50734
  channels: optionalKey2(Union2([ArraySchema(String4), Null2])),
50557
50735
  match: optionalKey2(Union2([Union2([Literal2("all"), Literal2("any")]), Null2])),
@@ -50566,7 +50744,6 @@ var ContactGroupsPreview200 = Struct({
50566
50744
  sample: ArraySchema(Struct({
50567
50745
  id: ContactId,
50568
50746
  name: String4,
50569
- type: String4,
50570
50747
  status: String4
50571
50748
  }))
50572
50749
  });
@@ -50761,16 +50938,23 @@ var ContactsBulkDelete504 = GatewayTimeoutError;
50761
50938
  var ContactsBulkImportRequestJson = Struct({
50762
50939
  contacts: ArraySchema(Struct({
50763
50940
  name: String4,
50764
- email: optionalKey2(Union2([String4, Null2])),
50765
- phone: optionalKey2(Union2([String4, Null2])),
50941
+ displayName: optionalKey2(Union2([Union2([String4, Null2]), Null2])),
50942
+ avatar: optionalKey2(Union2([Union2([String4, Null2]), Null2])),
50943
+ identities: optionalKey2(Union2([ArraySchema(ContactIdentityInput), Null2])),
50944
+ profile: optionalKey2(Union2([Union2([ContactProfile, Null2]), Null2])),
50945
+ preferences: optionalKey2(Union2([Union2([ContactPreferences, Null2]), Null2])),
50766
50946
  tags: optionalKey2(Union2([ArraySchema(String4), Null2])),
50767
- firstName: optionalKey2(Union2([String4, Null2])),
50768
- lastName: optionalKey2(Union2([String4, Null2])),
50769
- company: optionalKey2(Union2([String4, Null2])),
50770
- jobTitle: optionalKey2(Union2([String4, Null2])),
50771
- customFields: optionalKey2(Union2([UnknownRecord, Null2]))
50947
+ status: optionalKey2(Union2([Union2([
50948
+ Literal2("active"),
50949
+ Literal2("paused"),
50950
+ Literal2("blocked"),
50951
+ Literal2("archived")
50952
+ ]), Null2])),
50953
+ statusReason: optionalKey2(Union2([Union2([String4, Null2]), Null2])),
50954
+ externalId: optionalKey2(Union2([Union2([String4, Null2]), Null2])),
50955
+ metadata: optionalKey2(Union2([Union2([JsonObject, Null2]), Null2]))
50772
50956
  })),
50773
- upsertByEmail: optionalKey2(Union2([Boolean3, Null2]))
50957
+ onConflict: optionalKey2(Union2([Union2([Literal2("skip"), Literal2("update")]), Null2]))
50774
50958
  });
50775
50959
  var ContactsBulkImport200 = Struct({
50776
50960
  total: Finite.check(isInt().annotate({ expected: "an integer" })).check(isGreaterThanOrEqualTo2(0).annotate({ expected: "a value greater than or equal to 0" })),
@@ -52080,6 +52264,31 @@ var ExtensionInstallationsGetRun404 = ResourceNotFoundError;
52080
52264
  var ExtensionInstallationsGetRun422 = ValidationError;
52081
52265
  var ExtensionInstallationsGetRun500 = InternalError;
52082
52266
  var ExtensionInstallationsGetRun504 = GatewayTimeoutError;
52267
+ var ExtensionInstallationsUpgradePathParams = Struct({ id: ExtensionInstallationId });
52268
+ var ExtensionInstallationsUpgradeRequestJson = Struct({
52269
+ version: optionalKey2(Union2([Union2([String4.check(isPattern2(/* @__PURE__ */ new RegExp("^\\d{1,6}\\.\\d{1,6}\\.\\d{1,6}(?:-[0-9A-Za-z.-]{1,64})?$", "u")).annotate({ expected: "a string matching the RegExp ^\\d{1,6}\\.\\d{1,6}\\.\\d{1,6}(?:-[0-9A-Za-z.-]{1,64})?$" })), ExtensionVersionId]), Null2])),
52270
+ acceptPermissions: optionalKey2(Union2([ArraySchema(Union2([
52271
+ Literal2("permission:read"),
52272
+ Literal2("permission:update"),
52273
+ Literal2("permission:send"),
52274
+ Literal2("permission:quarantine.read"),
52275
+ Literal2("event:mailbox.message.received"),
52276
+ Literal2("event:mailbox.message.sent"),
52277
+ Literal2("event:mailbox.action.pending_approval"),
52278
+ Literal2("event:mailbox.message.quarantined"),
52279
+ Literal2("event:mailbox.message.released"),
52280
+ Literal2("event:mailbox.message.discarded")
52281
+ ])), Null2])),
52282
+ dryRun: optionalKey2(Union2([Boolean3, Null2]))
52283
+ });
52284
+ var ExtensionInstallationsUpgrade200 = UpgradeExtensionResponse;
52285
+ var ExtensionInstallationsUpgrade401 = UnauthorizedError;
52286
+ var ExtensionInstallationsUpgrade403 = ForbiddenError;
52287
+ var ExtensionInstallationsUpgrade404 = ResourceNotFoundError;
52288
+ var ExtensionInstallationsUpgrade409 = ConflictError;
52289
+ var ExtensionInstallationsUpgrade422 = ValidationError;
52290
+ var ExtensionInstallationsUpgrade500 = InternalError;
52291
+ var ExtensionInstallationsUpgrade504 = GatewayTimeoutError;
52083
52292
  var ExtensionsListQuery = Struct({
52084
52293
  limit: optionalKey2(Union2([String4, Null2])),
52085
52294
  cursor: optionalKey2(Union2([Cursor, Null2])),
@@ -52270,12 +52479,14 @@ var MailboxesApproveActionPathParams = Struct({
52270
52479
  var MailboxesApproveAction200 = MailboxAction;
52271
52480
  var MailboxesApproveAction401 = UnauthorizedError;
52272
52481
  var MailboxesApproveAction402 = PaymentRequiredError;
52273
- var MailboxesApproveAction403 = ForbiddenError;
52482
+ var MailboxesApproveAction403 = Union2([ForbiddenError, OnboardingReviewRequiredError]);
52274
52483
  var MailboxesApproveAction404 = ResourceNotFoundError;
52275
52484
  var MailboxesApproveAction409 = ConflictError;
52276
52485
  var MailboxesApproveAction422 = ValidationError;
52486
+ var MailboxesApproveAction429 = RateLimitedError;
52277
52487
  var MailboxesApproveAction500 = InternalError;
52278
52488
  var MailboxesApproveAction502 = BillingProviderError;
52489
+ var MailboxesApproveAction503 = SenderNotReadyError;
52279
52490
  var MailboxesApproveAction504 = GatewayTimeoutError;
52280
52491
  var MailboxesDenyActionPathParams = Struct({
52281
52492
  id: MailboxId,
@@ -52386,12 +52597,14 @@ var MailboxesSendDraftHeaders = Struct({ "idempotency-key": optionalKey2(Union2(
52386
52597
  var MailboxesSendDraft200 = MailboxSendReceipt;
52387
52598
  var MailboxesSendDraft401 = UnauthorizedError;
52388
52599
  var MailboxesSendDraft402 = PaymentRequiredError;
52389
- var MailboxesSendDraft403 = ForbiddenError;
52600
+ var MailboxesSendDraft403 = Union2([ForbiddenError, OnboardingReviewRequiredError]);
52390
52601
  var MailboxesSendDraft404 = ResourceNotFoundError;
52391
52602
  var MailboxesSendDraft409 = ConflictError;
52392
52603
  var MailboxesSendDraft422 = ValidationError;
52604
+ var MailboxesSendDraft429 = RateLimitedError;
52393
52605
  var MailboxesSendDraft500 = InternalError;
52394
52606
  var MailboxesSendDraft502 = BillingProviderError;
52607
+ var MailboxesSendDraft503 = SenderNotReadyError;
52395
52608
  var MailboxesSendDraft504 = GatewayTimeoutError;
52396
52609
  var MailboxesListEventsPathParams = Struct({ id: MailboxId });
52397
52610
  var MailboxesListEventsQuery = Struct({
@@ -52546,12 +52759,14 @@ var MailboxesSendMessageRequestJson = Struct({
52546
52759
  var MailboxesSendMessage200 = MailboxSendReceipt;
52547
52760
  var MailboxesSendMessage401 = UnauthorizedError;
52548
52761
  var MailboxesSendMessage402 = PaymentRequiredError;
52549
- var MailboxesSendMessage403 = ForbiddenError;
52762
+ var MailboxesSendMessage403 = Union2([ForbiddenError, OnboardingReviewRequiredError]);
52550
52763
  var MailboxesSendMessage404 = ResourceNotFoundError;
52551
52764
  var MailboxesSendMessage409 = ConflictError;
52552
52765
  var MailboxesSendMessage422 = ValidationError;
52766
+ var MailboxesSendMessage429 = RateLimitedError;
52553
52767
  var MailboxesSendMessage500 = InternalError;
52554
52768
  var MailboxesSendMessage502 = BillingProviderError;
52769
+ var MailboxesSendMessage503 = SenderNotReadyError;
52555
52770
  var MailboxesSendMessage504 = GatewayTimeoutError;
52556
52771
  var MailboxesGetMessagePathParams = Struct({
52557
52772
  id: MailboxId,
@@ -52605,12 +52820,14 @@ var MailboxesForwardRequestJson = Struct({
52605
52820
  var MailboxesForward200 = MailboxSendReceipt;
52606
52821
  var MailboxesForward401 = UnauthorizedError;
52607
52822
  var MailboxesForward402 = PaymentRequiredError;
52608
- var MailboxesForward403 = ForbiddenError;
52823
+ var MailboxesForward403 = Union2([ForbiddenError, OnboardingReviewRequiredError]);
52609
52824
  var MailboxesForward404 = ResourceNotFoundError;
52610
52825
  var MailboxesForward409 = ConflictError;
52611
52826
  var MailboxesForward422 = ValidationError;
52827
+ var MailboxesForward429 = RateLimitedError;
52612
52828
  var MailboxesForward500 = InternalError;
52613
52829
  var MailboxesForward502 = BillingProviderError;
52830
+ var MailboxesForward503 = SenderNotReadyError;
52614
52831
  var MailboxesForward504 = GatewayTimeoutError;
52615
52832
  var MailboxesGetMessageRawPathParams = Struct({
52616
52833
  id: MailboxId,
@@ -52650,12 +52867,14 @@ var MailboxesReplyRequestJson = Struct({
52650
52867
  var MailboxesReply200 = MailboxSendReceipt;
52651
52868
  var MailboxesReply401 = UnauthorizedError;
52652
52869
  var MailboxesReply402 = PaymentRequiredError;
52653
- var MailboxesReply403 = ForbiddenError;
52870
+ var MailboxesReply403 = Union2([ForbiddenError, OnboardingReviewRequiredError]);
52654
52871
  var MailboxesReply404 = ResourceNotFoundError;
52655
52872
  var MailboxesReply409 = ConflictError;
52656
52873
  var MailboxesReply422 = ValidationError;
52874
+ var MailboxesReply429 = RateLimitedError;
52657
52875
  var MailboxesReply500 = InternalError;
52658
52876
  var MailboxesReply502 = BillingProviderError;
52877
+ var MailboxesReply503 = SenderNotReadyError;
52659
52878
  var MailboxesReply504 = GatewayTimeoutError;
52660
52879
  var MailboxesReplyAllPathParams = Struct({
52661
52880
  id: MailboxId,
@@ -52672,12 +52891,14 @@ var MailboxesReplyAllRequestJson = Struct({
52672
52891
  var MailboxesReplyAll200 = MailboxSendReceipt;
52673
52892
  var MailboxesReplyAll401 = UnauthorizedError;
52674
52893
  var MailboxesReplyAll402 = PaymentRequiredError;
52675
- var MailboxesReplyAll403 = ForbiddenError;
52894
+ var MailboxesReplyAll403 = Union2([ForbiddenError, OnboardingReviewRequiredError]);
52676
52895
  var MailboxesReplyAll404 = ResourceNotFoundError;
52677
52896
  var MailboxesReplyAll409 = ConflictError;
52678
52897
  var MailboxesReplyAll422 = ValidationError;
52898
+ var MailboxesReplyAll429 = RateLimitedError;
52679
52899
  var MailboxesReplyAll500 = InternalError;
52680
52900
  var MailboxesReplyAll502 = BillingProviderError;
52901
+ var MailboxesReplyAll503 = SenderNotReadyError;
52681
52902
  var MailboxesReplyAll504 = GatewayTimeoutError;
52682
52903
  var MailboxesPausePathParams = Struct({ id: MailboxId });
52683
52904
  var MailboxesPause200 = Mailbox;
@@ -53028,7 +53249,7 @@ var MessagesSend422 = ValidationError;
53028
53249
  var MessagesSend429 = RateLimitedError;
53029
53250
  var MessagesSend500 = InternalError;
53030
53251
  var MessagesSend502 = Union2([BillingProviderError, ExternalServiceError]);
53031
- var MessagesSend503 = DeliveryUnavailableError;
53252
+ var MessagesSend503 = Union2([SenderNotReadyError, DeliveryUnavailableError]);
53032
53253
  var MessagesSend504 = GatewayTimeoutError;
53033
53254
  var MessagesGetPathParams = Struct({ id: MessageId });
53034
53255
  var MessagesGet200 = Message;
@@ -53330,6 +53551,7 @@ var ScheduledMessagesResume409 = ConflictError;
53330
53551
  var ScheduledMessagesResume422 = ValidationError;
53331
53552
  var ScheduledMessagesResume500 = InternalError;
53332
53553
  var ScheduledMessagesResume502 = ExternalServiceError;
53554
+ var ScheduledMessagesResume503 = SenderNotReadyError;
53333
53555
  var ScheduledMessagesResume504 = GatewayTimeoutError;
53334
53556
  var MessagesValidateEmailRequestJson = Struct({
53335
53557
  conversationId: optionalKey2(Union2([Union2([ConversationId, Null2]), Null2])),
@@ -53347,6 +53569,7 @@ var MessagesValidateEmail403 = ForbiddenError;
53347
53569
  var MessagesValidateEmail404 = ResourceNotFoundError;
53348
53570
  var MessagesValidateEmail422 = ValidationError;
53349
53571
  var MessagesValidateEmail500 = InternalError;
53572
+ var MessagesValidateEmail503 = SenderNotReadyError;
53350
53573
  var MessagesValidateEmail504 = GatewayTimeoutError;
53351
53574
  var NamespacesListQuery = Struct({
53352
53575
  limit: optionalKey2(Union2([String4, Null2])),
@@ -55846,6 +56069,7 @@ var CampaignsGroup = class extends make38("Campaigns").add(get5("campaignsList",
55846
56069
  CampaignsScheduleRun422.pipe(status(422)),
55847
56070
  CampaignsScheduleRun500,
55848
56071
  CampaignsScheduleRun502.pipe(status(502)),
56072
+ CampaignsScheduleRun503.pipe(status(503)),
55849
56073
  CampaignsScheduleRun504.pipe(status(504))
55850
56074
  ]
55851
56075
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "campaigns.scheduleRun").annotate(Summary, "Schedule a campaign run").annotate(Description, "Schedules an email campaign run at the absolute ISO-8601 instant in scheduledFor, or immediately when omitted. The optional idempotencyKey is scoped to the organization and replays return the original run. An email campaign must carry the brand footer: it is refused with CampaignFooterRequiredError when its footer is off and its template renders no BrandFooter, and with BrandAddressRequiredError when a brand that signs it off has no postal address."), get5("campaignsGetRun", "/v1/campaigns/:id/runs/:runId", {
@@ -56191,7 +56415,7 @@ var ContactsGroup = class extends make38("Contacts").add(get5("contactsList", "/
56191
56415
  ContactsBulkImport502.pipe(status(502)),
56192
56416
  ContactsBulkImport504.pipe(status(504))
56193
56417
  ]
56194
- }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "contacts.bulkImport").annotate(Summary, "Bulk import contacts").annotate(Description, "Creates or updates contacts in bulk from a list, returning per-entry results with created, updated, skipped, and error counts."), post("contactsBulkUpdateStatus", "/v1/contacts/bulk-update-status", {
56418
+ }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "contacts.bulkImport").annotate(Summary, "Bulk import contacts").annotate(Description, 'Creates contacts in bulk from a list of entries shaped like a create request, returning per-entry results with created, updated, skipped, and error counts. An entry whose identities match an existing contact is skipped, or updates it with `onConflict: "update"`.'), post("contactsBulkUpdateStatus", "/v1/contacts/bulk-update-status", {
56195
56419
  payload: ContactsBulkUpdateStatusRequestJson,
56196
56420
  success: ContactsBulkUpdateStatus200,
56197
56421
  error: [
@@ -57273,7 +57497,20 @@ var ExtensionInstallationsGroup = class extends make38("Extension installations"
57273
57497
  ExtensionInstallationsGetRun500,
57274
57498
  ExtensionInstallationsGetRun504.pipe(status(504))
57275
57499
  ]
57276
- }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "extensionInstallations.getRun").annotate(Summary, "Get a hosted run").annotate(Description, "Returns one retained run with the lines its handler logged: at most 50 lines of 500 characters.")).annotate(Description, "Extension versions installed into the organization, each acting as its own principal") {
57500
+ }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "extensionInstallations.getRun").annotate(Summary, "Get a hosted run").annotate(Description, "Returns one retained run with the lines its handler logged: at most 50 lines of 500 characters."), post("extensionInstallationsUpgrade", "/v1/extension-installations/:id/upgrade", {
57501
+ params: ExtensionInstallationsUpgradePathParams,
57502
+ payload: ExtensionInstallationsUpgradeRequestJson,
57503
+ success: ExtensionInstallationsUpgrade200,
57504
+ error: [
57505
+ ExtensionInstallationsUpgrade401.pipe(status(401)),
57506
+ ExtensionInstallationsUpgrade403.pipe(status(403)),
57507
+ ExtensionInstallationsUpgrade404.pipe(status(404)),
57508
+ ExtensionInstallationsUpgrade409.pipe(status(409)),
57509
+ ExtensionInstallationsUpgrade422.pipe(status(422)),
57510
+ ExtensionInstallationsUpgrade500,
57511
+ ExtensionInstallationsUpgrade504.pipe(status(504))
57512
+ ]
57513
+ }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "extensionInstallations.upgrade").annotate(Summary, "Upgrade or roll back an installation").annotate(Description, "Changes the pinned version in place. Omit version for the latest publication, or name a version string or id, including an older version to roll back. Preview with dryRun; changing requires acceptPermissions to list exactly the added permission: and event: grants. Only a person can upgrade. Credentials, owner, scope, send mode, and status stay attached to the installation.")).annotate(Description, "Extension versions installed into the organization, each acting as its own principal") {
57277
57514
  };
57278
57515
  var ExtensionsGroup = class extends make38("Extensions").add(get5("extensionsList", "/v1/extensions", {
57279
57516
  query: ExtensionsListQuery,
@@ -57427,8 +57664,10 @@ var MailboxesGroup = class extends make38("Mailboxes").add(get5("mailboxesList",
57427
57664
  MailboxesApproveAction404.pipe(status(404)),
57428
57665
  MailboxesApproveAction409.pipe(status(409)),
57429
57666
  MailboxesApproveAction422.pipe(status(422)),
57667
+ MailboxesApproveAction429.pipe(status(429)),
57430
57668
  MailboxesApproveAction500,
57431
57669
  MailboxesApproveAction502.pipe(status(502)),
57670
+ MailboxesApproveAction503.pipe(status(503)),
57432
57671
  MailboxesApproveAction504.pipe(status(504))
57433
57672
  ]
57434
57673
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "mailboxes.approveAction").annotate(Summary, "Approve a mailbox action").annotate(Description, "Approves an action waiting for approval, executes it, and returns the executed action. Only a person signed in or through OAuth may approve, and never the one who proposed it."), post("mailboxesDenyAction", "/v1/mailboxes/:id/actions/:actionId/deny", {
@@ -57526,8 +57765,10 @@ var MailboxesGroup = class extends make38("Mailboxes").add(get5("mailboxesList",
57526
57765
  MailboxesSendDraft404.pipe(status(404)),
57527
57766
  MailboxesSendDraft409.pipe(status(409)),
57528
57767
  MailboxesSendDraft422.pipe(status(422)),
57768
+ MailboxesSendDraft429.pipe(status(429)),
57529
57769
  MailboxesSendDraft500,
57530
57770
  MailboxesSendDraft502.pipe(status(502)),
57771
+ MailboxesSendDraft503.pipe(status(503)),
57531
57772
  MailboxesSendDraft504.pipe(status(504))
57532
57773
  ]
57533
57774
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "mailboxes.sendDraft").annotate(Summary, "Send a draft").annotate(Description, "Sends one of the caller's drafts: a reply draft in its thread, any other draft as a new conversation. A draft needs recipients, a subject, and a body."), get5("mailboxesListEvents", "/v1/mailboxes/:id/events", {
@@ -57662,8 +57903,10 @@ var MailboxesGroup = class extends make38("Mailboxes").add(get5("mailboxesList",
57662
57903
  MailboxesSendMessage404.pipe(status(404)),
57663
57904
  MailboxesSendMessage409.pipe(status(409)),
57664
57905
  MailboxesSendMessage422.pipe(status(422)),
57906
+ MailboxesSendMessage429.pipe(status(429)),
57665
57907
  MailboxesSendMessage500,
57666
57908
  MailboxesSendMessage502.pipe(status(502)),
57909
+ MailboxesSendMessage503.pipe(status(503)),
57667
57910
  MailboxesSendMessage504.pipe(status(504))
57668
57911
  ]
57669
57912
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "mailboxes.sendMessage").annotate(Summary, "Send a new message").annotate(Description, "Starts a new conversation from the mailbox's default From address. `status` is `sent`, or `pending_approval` when the caller's grant or a mailbox policy holds sends for a person's approval; a policy that denies sends refuses it with 403."), get5("mailboxesGetMessage", "/v1/mailboxes/:id/messages/:messageId", {
@@ -57713,8 +57956,10 @@ var MailboxesGroup = class extends make38("Mailboxes").add(get5("mailboxesList",
57713
57956
  MailboxesForward404.pipe(status(404)),
57714
57957
  MailboxesForward409.pipe(status(409)),
57715
57958
  MailboxesForward422.pipe(status(422)),
57959
+ MailboxesForward429.pipe(status(429)),
57716
57960
  MailboxesForward500,
57717
57961
  MailboxesForward502.pipe(status(502)),
57962
+ MailboxesForward503.pipe(status(503)),
57718
57963
  MailboxesForward504.pipe(status(504))
57719
57964
  ]
57720
57965
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "mailboxes.forward").annotate(Summary, "Forward a message").annotate(Description, "Forwards the message to new recipients as a new conversation, with the original quoted below the caller's text and its attachments attached ahead of any the caller adds. The combined attachments must fit the email attachment limits."), get5("mailboxesGetMessageRaw", "/v1/mailboxes/:id/messages/:messageId/raw", {
@@ -57752,8 +57997,10 @@ var MailboxesGroup = class extends make38("Mailboxes").add(get5("mailboxesList",
57752
57997
  MailboxesReply404.pipe(status(404)),
57753
57998
  MailboxesReply409.pipe(status(409)),
57754
57999
  MailboxesReply422.pipe(status(422)),
58000
+ MailboxesReply429.pipe(status(429)),
57755
58001
  MailboxesReply500,
57756
58002
  MailboxesReply502.pipe(status(502)),
58003
+ MailboxesReply503.pipe(status(503)),
57757
58004
  MailboxesReply504.pipe(status(504))
57758
58005
  ]
57759
58006
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "mailboxes.reply").annotate(Summary, "Reply to a message").annotate(Description, "Replies to the message's Reply-To address, or its sender, in the same thread. The server sets the recipients, subject, and threading headers."), post("mailboxesReplyAll", "/v1/mailboxes/:id/messages/:messageId/reply-all", {
@@ -57768,8 +58015,10 @@ var MailboxesGroup = class extends make38("Mailboxes").add(get5("mailboxesList",
57768
58015
  MailboxesReplyAll404.pipe(status(404)),
57769
58016
  MailboxesReplyAll409.pipe(status(409)),
57770
58017
  MailboxesReplyAll422.pipe(status(422)),
58018
+ MailboxesReplyAll429.pipe(status(429)),
57771
58019
  MailboxesReplyAll500,
57772
58020
  MailboxesReplyAll502.pipe(status(502)),
58021
+ MailboxesReplyAll503.pipe(status(503)),
57773
58022
  MailboxesReplyAll504.pipe(status(504))
57774
58023
  ]
57775
58024
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "mailboxes.replyAll").annotate(Summary, "Reply to all recipients of a message").annotate(Description, "Replies to the sender and every other recipient of the message except the mailbox itself, in the same thread."), post("mailboxesPause", "/v1/mailboxes/:id/pause", {
@@ -58006,7 +58255,7 @@ var MediaGroup = class extends make38("Media").add(post("mediaCreate", "/v1/medi
58006
58255
  MediaCreate500,
58007
58256
  MediaCreate504.pipe(status(504))
58008
58257
  ]
58009
- }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "media.create").annotate(Summary, "Create a media object").annotate(Description, "Creates the media object in the pending state and returns it with the upload instruction \u2014 URL, method, and headers \u2014 for putting its bytes into storage."), get5("mediaGetById", "/v1/media/:id", {
58258
+ }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "media.create").annotate(Summary, "Create a media object").annotate(Description, "Creates the media object in the pending state and returns it with the upload instruction \u2014 URL, method, and headers \u2014 for putting its bytes into storage. Requires `messages:create`, or `email:send` for `attachment` media."), get5("mediaGetById", "/v1/media/:id", {
58010
58259
  params: MediaGetByIdPathParams,
58011
58260
  success: MediaGetById200,
58012
58261
  error: [
@@ -58039,7 +58288,7 @@ var MediaGroup = class extends make38("Media").add(post("mediaCreate", "/v1/medi
58039
58288
  MediaComplete500,
58040
58289
  MediaComplete504.pipe(status(504))
58041
58290
  ]
58042
- }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "media.complete").annotate(Summary, "Complete a media upload").annotate(Description, "Verifies the uploaded object exists in storage, marks the media object ready, and returns it with a download URL."), get5("mediaDownloadUrl", "/v1/media/:id/url", {
58291
+ }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "media.complete").annotate(Summary, "Complete a media upload").annotate(Description, "Verifies the uploaded object exists in storage, marks the media object ready, and returns it with a download URL. Requires the permission that creating the media object did."), get5("mediaDownloadUrl", "/v1/media/:id/url", {
58043
58292
  params: MediaDownloadUrlPathParams,
58044
58293
  success: MediaDownloadUrl200,
58045
58294
  error: [
@@ -58168,6 +58417,7 @@ var MessagesGroup = class extends make38("Messages").add(get5("messagesList", "/
58168
58417
  MessagesValidateEmail404.pipe(status(404)),
58169
58418
  MessagesValidateEmail422.pipe(status(422)),
58170
58419
  MessagesValidateEmail500,
58420
+ MessagesValidateEmail503.pipe(status(503)),
58171
58421
  MessagesValidateEmail504.pipe(status(504))
58172
58422
  ]
58173
58423
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "messages.validateEmail").annotate(Summary, "Validate an email message").annotate(Description, "Resolves recipients, sender, and inline or published-template content without sending anything, creating contacts or messages, or counting toward your quota.")).annotate(Description, "Send messages and read their delivery state and timeline.") {
@@ -58229,6 +58479,7 @@ var ScheduledMessagesGroup = class extends make38("Scheduled Messages").add(get5
58229
58479
  ScheduledMessagesResume422.pipe(status(422)),
58230
58480
  ScheduledMessagesResume500,
58231
58481
  ScheduledMessagesResume502.pipe(status(502)),
58482
+ ScheduledMessagesResume503.pipe(status(503)),
58232
58483
  ScheduledMessagesResume504.pipe(status(504))
58233
58484
  ]
58234
58485
  }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "scheduledMessages.resume").annotate(Summary, "Resume a review-paused scheduled message").annotate(Description, "Explicitly resumes a scheduled message after onboarding review clearance. An overdue message requires either send_now or a new future scheduledFor value.")).annotate(Description, "One-off scheduled message timers") {
@@ -58277,7 +58528,7 @@ var NamespacesGroup = class extends make38("Namespaces").add(get5("namespacesLis
58277
58528
  NamespacesRemove500,
58278
58529
  NamespacesRemove504.pipe(status(504))
58279
58530
  ]
58280
- }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "namespaces.remove").annotate(Summary, "Delete a namespace").annotate(Description, "Deletes an empty namespace. A namespace that still holds mailboxes or API keys conflicts: remove or move them first."), patch("namespacesUpdate", "/v1/namespaces/:id", {
58531
+ }).middleware(ApiKeySecurityMiddleware).annotate(Identifier, "namespaces.remove").annotate(Summary, "Delete a namespace").annotate(Description, "Deletes an empty namespace. A namespace that still holds mailboxes, API keys, or webhook endpoints conflicts: remove them first."), patch("namespacesUpdate", "/v1/namespaces/:id", {
58281
58532
  params: NamespacesUpdatePathParams,
58282
58533
  payload: NamespacesUpdateRequestJson,
58283
58534
  success: NamespacesUpdate200,
@@ -59039,7 +59290,18 @@ var make39 = (config) => gen2(function* () {
59039
59290
  for (const [name, value] of Object.entries(config.headers ?? {}))
59040
59291
  if (value !== undefined)
59041
59292
  headers[name] = value;
59293
+ const storage = yield* HttpClient;
59294
+ const putUpload = (input) => storage.execute(make33(input.method)(input.url).pipe(bodyUint8Array(input.bytes, uploadContentType(input.headers)), setHeaders(input.headers))).pipe(mapError2((cause) => new MediaUploadError({
59295
+ filename: input.filename,
59296
+ mediaId: input.mediaId,
59297
+ cause
59298
+ })), flatMap3((response) => response.status >= 200 && response.status < 300 ? void_3 : fail6(new MediaUploadError({
59299
+ filename: input.filename,
59300
+ mediaId: input.mediaId,
59301
+ status: response.status
59302
+ }))));
59042
59303
  return Service3.of({
59304
+ putUpload,
59043
59305
  raw,
59044
59306
  operation: (name) => flat[name],
59045
59307
  connection: {
@@ -59055,7 +59317,7 @@ var layer16 = (config) => effect(Service3, make39(config));
59055
59317
  var layerFetch = (config) => layer16(config).pipe(provide2(layer15));
59056
59318
  var raw2 = map7(Service3, (client) => client.raw);
59057
59319
 
59058
- // ../sdk/dist/categories-DvsHUJtX.js
59320
+ // ../sdk/dist/categories-Bcwq5jPV.js
59059
59321
  var SamvaErrorMetadata = {
59060
59322
  AnalyticsQueryError: {
59061
59323
  categories: [],
@@ -59121,6 +59383,10 @@ var SamvaErrorMetadata = {
59121
59383
  categories: ["notFound"],
59122
59384
  retryable: false
59123
59385
  },
59386
+ SenderNotReadyError: {
59387
+ categories: ["transient"],
59388
+ retryable: true
59389
+ },
59124
59390
  UnauthorizedError: {
59125
59391
  categories: ["auth"],
59126
59392
  retryable: false
@@ -59216,7 +59482,7 @@ var generateIdempotencyKey = gen2(function* () {
59216
59482
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
59217
59483
  });
59218
59484
 
59219
- // ../sdk/dist/operation-BEghYyLu.js
59485
+ // ../sdk/dist/operation-B_Ty1LG-.js
59220
59486
  var SDK_OPERATION_CALLS = {
59221
59487
  brandsList: { kind: "none" },
59222
59488
  brandsCreate: { kind: "payload" },
@@ -60146,6 +60412,10 @@ var SDK_OPERATION_CALLS = {
60146
60412
  },
60147
60413
  extensionInstallationsList: { kind: "params" },
60148
60414
  extensionInstallationsInstall: { kind: "payload" },
60415
+ extensionInstallationsUpgrade: {
60416
+ kind: "pathPayload",
60417
+ paths: ["id"]
60418
+ },
60149
60419
  extensionInstallationsGet: {
60150
60420
  kind: "path",
60151
60421
  paths: ["id"]
@@ -60322,11 +60592,35 @@ var make40 = (operationName) => {
60322
60592
  }
60323
60593
  return operation;
60324
60594
  };
60595
+ var uploadOversizedAttachments = (client, payload) => gen2(function* () {
60596
+ const plan = planInlineUploads(payload);
60597
+ if (plan.length === 0)
60598
+ return payload;
60599
+ const uploaded = /* @__PURE__ */ new Map;
60600
+ for (const upload of plan) {
60601
+ const created = yield* rawOperation(client, "mediaCreate")({ payload: mediaCreateBody(upload) });
60602
+ yield* client.putUpload({
60603
+ filename: upload.filename,
60604
+ mediaId: created.id,
60605
+ url: created.upload.url,
60606
+ method: created.upload.method,
60607
+ headers: created.upload.headers,
60608
+ bytes: upload.bytes
60609
+ });
60610
+ yield* rawOperation(client, "mediaComplete")({ params: { id: created.id } });
60611
+ uploaded.set(upload.index, {
60612
+ mediaId: created.id,
60613
+ upload
60614
+ });
60615
+ }
60616
+ return withUploadedAttachments(payload, uploaded);
60617
+ });
60325
60618
  var sendPayload = (payload, options) => gen2(function* () {
60326
60619
  const client = yield* Service3;
60327
60620
  const idempotencyKey = options?.idempotencyKey ?? (yield* generateIdempotencyKey);
60621
+ const prepared = yield* uploadOversizedAttachments(client, payload);
60328
60622
  return yield* withRetry(rawOperation(client, "messagesSend")({
60329
- payload: stripUndefined(payload),
60623
+ payload: stripUndefined(prepared),
60330
60624
  headers: { "idempotency-key": idempotencyKey }
60331
60625
  }));
60332
60626
  });
@@ -60519,6 +60813,7 @@ var getForwardingLog = make40("emailGetForwardingLog");
60519
60813
  // ../sdk/dist/effect/extension-installations.js
60520
60814
  var list9 = make40("extensionInstallationsList");
60521
60815
  var install = make40("extensionInstallationsInstall");
60816
+ var upgrade = make40("extensionInstallationsUpgrade");
60522
60817
  var get11 = make40("extensionInstallationsGet");
60523
60818
  var uninstall = make40("extensionInstallationsUninstall");
60524
60819
  var disable = make40("extensionInstallationsDisable");
@@ -60589,7 +60884,7 @@ var DIAGNOSE_TIMEOUT_MILLIS = 1e4;
60589
60884
  var MAILBOX_EVENT_STREAM_PING_FRAME = '{"kind":"ping"}';
60590
60885
  var MAILBOX_EVENT_STREAM_PING_MILLIS = 30000;
60591
60886
  var MAILBOX_EVENT_STREAM_IDLE_MILLIS = 3 * MAILBOX_EVENT_STREAM_PING_MILLIS;
60592
- var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
60887
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
60593
60888
  var frameText = (raw) => {
60594
60889
  if (typeof raw === "string")
60595
60890
  return raw;
@@ -60606,16 +60901,16 @@ var decodeFrame = (raw) => {
60606
60901
  } catch {
60607
60902
  return;
60608
60903
  }
60609
- if (isRecord(parsed) && parsed.kind === "pong")
60904
+ if (isRecord2(parsed) && parsed.kind === "pong")
60610
60905
  return { kind: "pong" };
60611
- if (!isRecord(parsed) || typeof parsed.cursor !== "string")
60906
+ if (!isRecord2(parsed) || typeof parsed.cursor !== "string")
60612
60907
  return;
60613
60908
  if (parsed.kind === "live" || parsed.kind === "progress")
60614
60909
  return {
60615
60910
  kind: parsed.kind,
60616
60911
  cursor: parsed.cursor
60617
60912
  };
60618
- if (parsed.kind !== "event" || typeof parsed.id !== "string" || !isRecord(parsed.event))
60913
+ if (parsed.kind !== "event" || typeof parsed.id !== "string" || !isRecord2(parsed.event))
60619
60914
  return;
60620
60915
  const { type, timestamp, data } = parsed.event;
60621
60916
  if (typeof type !== "string" || typeof timestamp !== "string")
@@ -60713,7 +61008,7 @@ var closeOutcome = (closeCode) => {
60713
61008
  }
60714
61009
  };
60715
61010
  var fieldsOf = (value) => {
60716
- if (!isRecord(value))
61011
+ if (!isRecord2(value))
60717
61012
  return;
60718
61013
  const fields = {};
60719
61014
  for (const [path, messages] of Object.entries(value))
@@ -60722,7 +61017,7 @@ var fieldsOf = (value) => {
60722
61017
  return fields;
60723
61018
  };
60724
61019
  var refusalOutcome = (refusal) => {
60725
- const body = isRecord(refusal.body) ? refusal.body : {};
61020
+ const body = isRecord2(refusal.body) ? refusal.body : {};
60726
61021
  const serverTag = typeof body._tag === "string" ? body._tag : undefined;
60727
61022
  const known = serverTag !== undefined && REFUSAL_TAGS.has(serverTag);
60728
61023
  const _tag = known ? serverTag : REFUSAL_TAG_BY_STATUS[refusal.status] ?? "StreamRefusedError";
@@ -61018,7 +61313,7 @@ var MailboxEventStream = class {
61018
61313
  id: frame.id,
61019
61314
  type: frame.event.type,
61020
61315
  timestamp: frame.event.timestamp,
61021
- data: isRecord(frame.event.data) ? frame.event.data : {}
61316
+ data: isRecord2(frame.event.data) ? frame.event.data : {}
61022
61317
  });
61023
61318
  this.#wake();
61024
61319
  return;
@@ -61122,7 +61417,7 @@ var readRefusalBody = async (response) => {
61122
61417
  }
61123
61418
  };
61124
61419
 
61125
- // ../sdk/dist/mailboxes-BtcktcNB.js
61420
+ // ../sdk/dist/mailboxes-D3Kx7elM.js
61126
61421
  var toStreamError = (cause) => cause instanceof MailboxEventStreamError ? cause : new MailboxEventStreamError({
61127
61422
  _tag: "StreamDisconnectedError",
61128
61423
  message: String(cause)
@@ -61407,6 +61702,7 @@ var apiStatuses = {
61407
61702
  BillingProviderError: 502,
61408
61703
  DeliveryUnavailableError: 503,
61409
61704
  ServiceUnavailableError: 503,
61705
+ SenderNotReadyError: 503,
61410
61706
  EmailChannelError: 502,
61411
61707
  SmsChannelError: 502,
61412
61708
  WhatsAppChannelError: 502,
@@ -61444,6 +61740,9 @@ var apiErrorGuidance = (error) => {
61444
61740
  case "ServiceUnavailableError":
61445
61741
  next = typeof details.retryAfterSeconds === "number" ? `Wait ${details.retryAfterSeconds} seconds before retrying.` : "Wait a moment before retrying.";
61446
61742
  break;
61743
+ case "SenderNotReadyError":
61744
+ next = typeof details.retryAfterSeconds === "number" ? `Wait ${details.retryAfterSeconds} seconds before retrying.` : "Wait for the sending identity to be ready before retrying.";
61745
+ break;
61447
61746
  case "CursorExpiredError":
61448
61747
  next = "Read current state from the API, then retry without the cursor.";
61449
61748
  break;
@@ -61590,10 +61889,16 @@ var commandTree = {
61590
61889
  events: {},
61591
61890
  list: {},
61592
61891
  create: {},
61892
+ get: {},
61893
+ update: {},
61894
+ pause: {},
61895
+ resume: {},
61896
+ remove: {},
61593
61897
  threads: {},
61594
61898
  read: {},
61595
61899
  send: {},
61596
61900
  reply: {},
61901
+ actions: { list: {}, approve: {}, deny: {} },
61597
61902
  quarantine: { list: {}, release: {}, discard: {} }
61598
61903
  },
61599
61904
  extensions: {
@@ -63643,8 +63948,117 @@ var reapply = make29("reapply", { json: jsonFlag }).pipe(withDescription3("Resub
63643
63948
  }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
63644
63949
  var reviewCommand = make29("review").pipe(withDescription3("Inspect or resubmit email onboarding review"), withSubcommands([status3, reapply]));
63645
63950
 
63951
+ // src/lib/attachments.ts
63952
+ import { readFile as readFile3, stat as stat3 } from "fs/promises";
63953
+ import { basename, extname } from "path";
63954
+
63955
+ // ../core/src/messages/attachment-budget.ts
63956
+ var EMAIL_ATTACHMENT_BUDGET = {
63957
+ maxCount: 10,
63958
+ maxItemBytes: 25 * 1024 * 1024,
63959
+ maxAggregateBytes: 25 * 1024 * 1024,
63960
+ maxInlineBytes: 4 * 1024 * 1024
63961
+ };
63962
+ var emailAttachmentBudgetViolation = (attachments) => {
63963
+ if (attachments.length > EMAIL_ATTACHMENT_BUDGET.maxCount)
63964
+ return "count";
63965
+ let aggregateBytes = 0;
63966
+ for (const attachment of attachments) {
63967
+ if (!Number.isSafeInteger(attachment.size) || attachment.size <= 0 || attachment.size > EMAIL_ATTACHMENT_BUDGET.maxItemBytes) {
63968
+ return "itemBytes";
63969
+ }
63970
+ aggregateBytes += attachment.size;
63971
+ if (aggregateBytes > EMAIL_ATTACHMENT_BUDGET.maxAggregateBytes)
63972
+ return "aggregateBytes";
63973
+ }
63974
+ return null;
63975
+ };
63976
+ var emailAttachmentBudgetMessage = (violation) => {
63977
+ switch (violation) {
63978
+ case "count":
63979
+ return `Email supports at most ${EMAIL_ATTACHMENT_BUDGET.maxCount} attachments`;
63980
+ case "itemBytes":
63981
+ return `Each email attachment must be between 1 byte and ${EMAIL_ATTACHMENT_BUDGET.maxItemBytes} bytes`;
63982
+ case "aggregateBytes":
63983
+ return `Email attachments must total at most ${EMAIL_ATTACHMENT_BUDGET.maxAggregateBytes} bytes`;
63984
+ }
63985
+ };
63986
+ var emailInlineAttachmentBytes = (attachments) => attachments.reduce((total, attachment) => attachment.content === undefined ? total : total + attachment.size, 0);
63987
+ var EMAIL_INLINE_ATTACHMENT_MESSAGE = `Inline attachment content must total at most ${EMAIL_ATTACHMENT_BUDGET.maxInlineBytes} bytes. Upload larger files with POST /v1/media and send their mediaId instead of content.`;
63988
+
63989
+ // src/lib/attachments.ts
63990
+ var CONTENT_TYPE_BY_EXTENSION = {
63991
+ ".csv": "text/csv",
63992
+ ".doc": "application/msword",
63993
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
63994
+ ".gif": "image/gif",
63995
+ ".htm": "text/html",
63996
+ ".html": "text/html",
63997
+ ".ics": "text/calendar",
63998
+ ".jpeg": "image/jpeg",
63999
+ ".jpg": "image/jpeg",
64000
+ ".json": "application/json",
64001
+ ".md": "text/markdown",
64002
+ ".mp3": "audio/mpeg",
64003
+ ".mp4": "video/mp4",
64004
+ ".pdf": "application/pdf",
64005
+ ".png": "image/png",
64006
+ ".ppt": "application/vnd.ms-powerpoint",
64007
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
64008
+ ".svg": "image/svg+xml",
64009
+ ".txt": "text/plain",
64010
+ ".webp": "image/webp",
64011
+ ".xls": "application/vnd.ms-excel",
64012
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
64013
+ ".xml": "application/xml",
64014
+ ".zip": "application/zip"
64015
+ };
64016
+ var contentTypeForPath = (path) => CONTENT_TYPE_BY_EXTENSION[extname(path).toLowerCase()] ?? "application/octet-stream";
64017
+ var attachmentError = (code, message) => new CliUsageError({ code, message });
64018
+ var describeCause = (cause) => cause instanceof Error ? cause.message : String(cause);
64019
+ var unreadable = (path) => (cause) => attachmentError("attachment_unreadable", `Cannot read --attach ${path}: ${describeCause(cause)}`);
64020
+ var checkAttachmentBudget = (files) => gen2(function* () {
64021
+ for (const file of files) {
64022
+ if (file.size === 0) {
64023
+ return yield* attachmentError("attachment_empty", `--attach ${file.path} is empty; an attachment must be at least 1 byte.`);
64024
+ }
64025
+ if (file.size > EMAIL_ATTACHMENT_BUDGET.maxItemBytes) {
64026
+ return yield* attachmentError("attachment_too_large", `--attach ${file.path} is ${file.size} bytes; each attachment must be at most ${EMAIL_ATTACHMENT_BUDGET.maxItemBytes} bytes.`);
64027
+ }
64028
+ }
64029
+ const violation = emailAttachmentBudgetViolation(files);
64030
+ if (violation !== null) {
64031
+ const total = files.reduce((sum, file) => sum + file.size, 0);
64032
+ return yield* attachmentError(`attachment_budget_${violation}`, `${emailAttachmentBudgetMessage(violation)} (got ${files.length} files, ${total} bytes).`);
64033
+ }
64034
+ });
64035
+ var readAttachments = (paths) => gen2(function* () {
64036
+ const sizes = yield* forEach2(paths, (path) => tryPromise2({
64037
+ try: async () => ({ path, size: (await stat3(path)).size }),
64038
+ catch: unreadable(path)
64039
+ }));
64040
+ yield* checkAttachmentBudget(sizes);
64041
+ const files = yield* forEach2(paths, (path) => tryPromise2({
64042
+ try: async () => ({
64043
+ path,
64044
+ filename: basename(path),
64045
+ contentType: contentTypeForPath(path),
64046
+ bytes: await readFile3(path)
64047
+ }),
64048
+ catch: unreadable(path)
64049
+ }));
64050
+ yield* checkAttachmentBudget(files.map((file) => ({ path: file.path, size: file.bytes.length })));
64051
+ return files;
64052
+ });
64053
+ var toSendAttachments = (files) => files.map((file) => ({
64054
+ filename: file.filename,
64055
+ contentType: file.contentType,
64056
+ size: file.bytes.length,
64057
+ content: Buffer.from(file.bytes).toString("base64")
64058
+ }));
64059
+
63646
64060
  // src/lib/stdin.ts
63647
- import { readFile as readFile3 } from "fs";
64061
+ import { readFile as readFile4 } from "fs";
63648
64062
  import { isatty as isatty2 } from "tty";
63649
64063
  import { promisify } from "util";
63650
64064
  var readStdinUtf8 = gen2(function* () {
@@ -63654,7 +64068,7 @@ var readStdinUtf8 = gen2(function* () {
63654
64068
  });
63655
64069
  }
63656
64070
  return yield* tryPromise2({
63657
- try: () => promisify(readFile3)(0, "utf8"),
64071
+ try: () => promisify(readFile4)(0, "utf8"),
63658
64072
  catch: () => new SamvaCliError({ message: "Could not read stdin." })
63659
64073
  });
63660
64074
  });
@@ -63965,6 +64379,7 @@ var replyToAddressFlag = String9("reply-to").pipe(withDescription2("Reply-To hea
63965
64379
  var idempotencyKeyFlag2 = String9("idempotency-key").pipe(withDescription2("Key (1-255 characters) so identical retries return the original email"), optional4);
63966
64380
  var trackOpensFlag2 = Literals3("track-opens", ["on", "off"]).pipe(withDescription2("Override open tracking for this send; recipient opt-out still wins"), optional4);
63967
64381
  var trackClicksFlag2 = Literals3("track-clicks", ["on", "off"]).pipe(withDescription2("Override click tracking for this send; recipient opt-out still wins"), optional4);
64382
+ var attachFlag = String9("attach").pipe(withDescription2("File to attach (repeatable); small files travel inline, larger ones upload through media first"), atLeast2(0));
63968
64383
  var dryRunFlag2 = Boolean6("dry-run").pipe(withDescription2("Validate inputs and print the request payload without calling the API"), withDefault5(false));
63969
64384
  var bodySourceName = (input) => {
63970
64385
  if (input.templateRefValue)
@@ -64001,6 +64416,7 @@ var send3 = make29("send", {
64001
64416
  idempotencyKey: idempotencyKeyFlag2,
64002
64417
  trackOpens: trackOpensFlag2,
64003
64418
  trackClicks: trackClicksFlag2,
64419
+ attach: attachFlag,
64004
64420
  dryRun: dryRunFlag2,
64005
64421
  wait: Boolean6("wait").pipe(withDescription2("Wait for delivered/read or a terminal delivery failure"), withDefault5(false)),
64006
64422
  timeout: timeoutFlag,
@@ -64029,6 +64445,10 @@ var send3 = make29("send", {
64029
64445
  {
64030
64446
  command: "samva email send --to you@example.com --subject Hi --text Hello --idempotency-key welcome-email-ada",
64031
64447
  description: "Retry a send safely with an idempotency key"
64448
+ },
64449
+ {
64450
+ command: "samva email send --to you@example.com --subject Report --text Attached --attach ./report.pdf --attach ./data.csv",
64451
+ description: "Attach files; those past the 4 MiB inline limit upload through media automatically"
64032
64452
  }
64033
64453
  ]), withHandler(({
64034
64454
  to,
@@ -64049,6 +64469,7 @@ var send3 = make29("send", {
64049
64469
  idempotencyKey,
64050
64470
  trackOpens,
64051
64471
  trackClicks,
64472
+ attach,
64052
64473
  dryRun,
64053
64474
  wait,
64054
64475
  timeout,
@@ -64120,6 +64541,7 @@ var send3 = make29("send", {
64120
64541
  message: "Choose exactly one body source: --html, --text, or a template (--template-id/--template-slug)."
64121
64542
  });
64122
64543
  }
64544
+ const attachmentFiles = yield* readAttachments(attach);
64123
64545
  const request = {
64124
64546
  to: [...to],
64125
64547
  ...ccValue ? { cc: [{ email: ccValue }] } : {},
@@ -64166,7 +64588,16 @@ var send3 = make29("send", {
64166
64588
  return yield* printJson({
64167
64589
  dryRun: true,
64168
64590
  bodySource: source,
64169
- request,
64591
+ request: {
64592
+ ...request,
64593
+ ...attachmentFiles.length === 0 ? {} : {
64594
+ attachments: attachmentFiles.map((file) => ({
64595
+ filename: file.filename,
64596
+ contentType: file.contentType,
64597
+ size: file.bytes.length
64598
+ }))
64599
+ }
64600
+ },
64170
64601
  idempotencyKey: idempotencyKeyValue
64171
64602
  });
64172
64603
  }
@@ -64182,6 +64613,10 @@ var send3 = make29("send", {
64182
64613
  ...request.inReplyToMessageId ? [["Reply to", request.inReplyToMessageId]] : [],
64183
64614
  ...request.replyTo ? [["Reply-To", request.replyTo]] : [],
64184
64615
  ...idempotencyKeyValue ? [["Idempotency key", idempotencyKeyValue]] : [],
64616
+ ...attachmentFiles.map((file) => [
64617
+ "Attachment",
64618
+ `${file.filename} (${file.contentType}, ${file.bytes.length} bytes)`
64619
+ ]),
64185
64620
  ...request.tracking ? [
64186
64621
  ["Track opens", request.tracking.opens],
64187
64622
  ["Track clicks", request.tracking.clicks]
@@ -64205,7 +64640,8 @@ ${truncateForDisplay(JSON.stringify(request.templateData, null, 2))}`);
64205
64640
  return;
64206
64641
  }
64207
64642
  const client = yield* getClientProvider;
64208
- const data = yield* send(request, sendOptions).pipe(client.provide, mapError2((error) => toCliApiError("Failed to send email", error)));
64643
+ const attachments = toSendAttachments(attachmentFiles);
64644
+ const data = yield* send({ ...request, ...attachments.length === 0 ? {} : { attachments } }, sendOptions).pipe(client.provide, mapError2((error) => toCliApiError("Failed to send email", error)));
64209
64645
  const finalMessage = waitDuration === undefined ? data : yield* waitForMessage(data, waitDuration);
64210
64646
  const projection = projectMessage(finalMessage);
64211
64647
  const outcome = wait ? lifecycleOf(finalMessage) : undefined;
@@ -64980,8 +65416,6 @@ var CONTACT_STATUS_VALUES = ["active", "paused", "blocked", "archived"];
64980
65416
  var contactStatusSchema = Literals(CONTACT_STATUS_VALUES);
64981
65417
  var ACTOR_STATUS_VALUES = ["active", "disabled", "archived"];
64982
65418
  var actorStatusSchema = Literals(ACTOR_STATUS_VALUES);
64983
- var ACCESS_LEVEL_VALUES = ["public", "authenticated", "vip", "internal"];
64984
- var accessLevelSchema = Literals(ACCESS_LEVEL_VALUES);
64985
65419
  var CONTACT_GROUP_TYPE_VALUES = ["static", "dynamic", "smart"];
64986
65420
  var contactGroupTypeSchema = Literals(CONTACT_GROUP_TYPE_VALUES);
64987
65421
  var CUSTOM_FIELD_TYPE_VALUES = ["text", "number", "boolean", "date", "select"];
@@ -65437,6 +65871,33 @@ var IanaTimezone2 = String4.check(makeFilter2(isIanaTimezone, {
65437
65871
  })).annotate({ identifier: "IanaTimezone" });
65438
65872
 
65439
65873
  // ../core/src/mailboxes/mailbox.ts
65874
+ var mailboxEventTypes = [
65875
+ "mailbox.created",
65876
+ "address.attached",
65877
+ "email.received",
65878
+ "email.released",
65879
+ "email.sent",
65880
+ "thread.created",
65881
+ "thread.updated",
65882
+ "draft.created",
65883
+ "draft.updated",
65884
+ "action.proposed",
65885
+ "action.policy_decided",
65886
+ "action.approval_requested",
65887
+ "action.approval_resolved",
65888
+ "action.executed",
65889
+ "action.failed"
65890
+ ];
65891
+ var mailboxActionScopes = [
65892
+ "sendMessage",
65893
+ "reply",
65894
+ "updateDraft",
65895
+ "createNote",
65896
+ "assignThread",
65897
+ "changeThreadState",
65898
+ "call",
65899
+ "extensionRequest"
65900
+ ];
65440
65901
  var mailboxActorKinds = [
65441
65902
  "user",
65442
65903
  "apiKey",
@@ -65445,6 +65906,27 @@ var mailboxActorKinds = [
65445
65906
  "samvaAgent",
65446
65907
  "system"
65447
65908
  ];
65909
+ var mailboxActionSources = [
65910
+ "humanUi",
65911
+ "externalApi",
65912
+ "aiSdkTool",
65913
+ "extension",
65914
+ "externalAgent",
65915
+ "samvaManagedAgent",
65916
+ "system"
65917
+ ];
65918
+ var mailboxActionStates = [
65919
+ "proposed",
65920
+ "allowed",
65921
+ "approvalRequired",
65922
+ "policyDenied",
65923
+ "approved",
65924
+ "approvalDenied",
65925
+ "executing",
65926
+ "executed",
65927
+ "failed"
65928
+ ];
65929
+ var mailboxApproverKinds = ["user", "samvaAgent", "system"];
65448
65930
  var mailboxPermissions = [
65449
65931
  "mailbox:read",
65450
65932
  "mailbox:configure",
@@ -65474,7 +65956,6 @@ var extensionRuntimes = ["hosted", "webhook"];
65474
65956
  var ExtensionRuntime = Literals(extensionRuntimes);
65475
65957
  var ExtensionPermission = Literals(mailboxKeyActions);
65476
65958
  var EXTENSION_BUNDLE_MAX_BYTES = 1024 * 1024;
65477
- var EXTENSION_TOOL_REQUEST_MAX_BYTES = 6 * 1024 * 1024;
65478
65959
  var uniqueValues = (values) => new Set(values).size === values.length;
65479
65960
  var ExtensionName = String4.check(isPattern2(/^[a-z][a-z0-9-]{1,62}[a-z0-9]$/u, {
65480
65961
  message: "An extension name is 3-64 lowercase letters, digits, and hyphens"
@@ -65577,6 +66058,38 @@ var InstallExtensionResponse2 = Struct({
65577
66058
  webhookSecret: SensitiveString2
65578
66059
  }))
65579
66060
  }).annotate({ identifier: "InstallExtensionResponse" });
66061
+ var ExtensionUpgradeGrant = Literals([
66062
+ ...mailboxKeyActions.map((permission) => `permission:${permission}`),
66063
+ ...MAILBOX_WEBHOOK_EVENT_TYPE_VALUES.map((event) => `event:${event}`)
66064
+ ]);
66065
+ var ExtensionPermissionDiff2 = Struct({
66066
+ added: ArraySchema(ExtensionUpgradeGrant),
66067
+ removed: ArraySchema(ExtensionUpgradeGrant)
66068
+ }).annotate({ identifier: "ExtensionPermissionDiff" });
66069
+ var ExtensionVersionChange2 = Struct({
66070
+ id: String4,
66071
+ organizationId: OrganizationId2,
66072
+ installationId: ExtensionInstallationId2,
66073
+ extensionId: ExtensionId2,
66074
+ fromVersion: ExtensionVersionRef2,
66075
+ toVersion: ExtensionVersionRef2,
66076
+ permissionDiff: ExtensionPermissionDiff2,
66077
+ changedBy: UserId2,
66078
+ changedAt: DateFromString
66079
+ }).annotate({ identifier: "ExtensionVersionChange" });
66080
+ var UpgradeExtensionPayload = Struct({
66081
+ version: optional2(Union2([ExtensionVersionString, ExtensionVersionId2])),
66082
+ acceptPermissions: optional2(ArraySchema(ExtensionUpgradeGrant).check(makeFilter2(uniqueValues, { message: "Each accepted grant is listed once" }))),
66083
+ dryRun: optional2(Boolean3)
66084
+ }).annotate({ identifier: "UpgradeExtensionPayload" });
66085
+ var UpgradeExtensionResponse2 = Struct({
66086
+ installation: ExtensionInstallation2,
66087
+ fromVersion: ExtensionVersionRef2,
66088
+ toVersion: ExtensionVersionRef2,
66089
+ permissionDiff: ExtensionPermissionDiff2,
66090
+ dryRun: Boolean3,
66091
+ versionChange: NullOr(ExtensionVersionChange2)
66092
+ }).annotate({ identifier: "UpgradeExtensionResponse" });
65580
66093
  var ExtensionRunOutcome = Literals([
65581
66094
  "succeeded",
65582
66095
  "failed",
@@ -65837,10 +66350,14 @@ var initExtension = (dir, manifest) => gen2(function* () {
65837
66350
  "src/extension.ts": `import { defineExtension } from "@samva/mailbox";
65838
66351
 
65839
66352
  export default defineExtension({
65840
- manifest: ${JSON.stringify(manifest, null, 2)},
66353
+ manifest: ${JSON.stringify(manifest, null, 2).replaceAll(`
66354
+ `, `
66355
+ `)},
65841
66356
  on: {
65842
66357
  "mailbox.message.received": async (event, { samva, log }) => {
65843
- await samva.messages.reply(event.data.mailboxId, event.data.message.id, { text: "Thanks for your message. We received it." });
66358
+ await samva.messages.reply(event.data.mailboxId, event.data.message.id, {
66359
+ text: "Thanks for your message. We received it.",
66360
+ });
65844
66361
  log("Acknowledged", event.data.message.id);
65845
66362
  },
65846
66363
  },
@@ -65869,6 +66386,10 @@ var undecodedStatus = (error) => isHttpClientError(error) ? error.response?.stat
65869
66386
  var GATED_NEXT = "Mailboxes are not enabled for this organization (the `mailbox` launch flag is off). Mailbox commands work once it is enabled.";
65870
66387
  var personOnlyNext = (action) => {
65871
66388
  switch (action) {
66389
+ case "approve":
66390
+ return "Approving an action needs a person signed in with `samva login`, different from its proposer; an API key cannot approve.";
66391
+ case "deny":
66392
+ return "Denying an action needs a person signed in with `samva login`, different from its proposer; an API key cannot deny.";
65872
66393
  case "release":
65873
66394
  return "Releasing a held message needs a person signed in with `samva login`; an API key cannot release.";
65874
66395
  case "discard":
@@ -65888,7 +66409,7 @@ var mailboxApiError = (prefix, error, options = {}) => {
65888
66409
  api: { reason: "FlagDisabledError", status: 404, details: {}, next: GATED_NEXT }
65889
66410
  });
65890
66411
  const failure = toCliApiError(prefix, error);
65891
- if (options.personOnly !== undefined && failure.api?.status === 403)
66412
+ if (options.personOnly !== undefined && failure.api?.reason === "ForbiddenError")
65892
66413
  return new SamvaCliError({
65893
66414
  message: failure.message,
65894
66415
  api: { ...failure.api, next: personOnlyNext(options.personOnly) }
@@ -65936,26 +66457,98 @@ var ActivityRangeQuery = {
65936
66457
  }))
65937
66458
  };
65938
66459
 
65939
- // src/commands/extensions-api.ts
65940
- var printInstallationSummary = (item) => printFields([
65941
- ["Installation", item.id],
65942
- ["Extension", item.name],
65943
- ["Version", item.version.version],
66460
+ // src/commands/extensions-output.ts
66461
+ var printManifest = (item) => printFields([
66462
+ ["Extension", `${item.name}@${item.version}`],
66463
+ ["Display name", item.displayName],
66464
+ ["Description", item.description === null ? "None" : item.description],
65944
66465
  ["Runtime", item.runtime],
65945
- ["Status", item.status]
66466
+ ["Events", item.events.join(", ")],
66467
+ ["Permissions", item.permissions.join(", ")]
65946
66468
  ]);
65947
- var printInstallation = (item) => printFields([
65948
- ["Installation", item.id],
65949
- ["Extension", item.name],
65950
- ["Version", item.version.version],
66469
+ var printExtension = (item) => gen2(function* () {
66470
+ yield* log(`${item.displayName} (${item.name})`);
66471
+ yield* printFields([
66472
+ ["Extension ID", item.id],
66473
+ ["Description", item.description ?? "None"],
66474
+ ["Runtime", item.runtime],
66475
+ ["Latest version", `${item.latestVersion.version} (${item.latestVersion.id})`],
66476
+ ["Created", item.createdAt],
66477
+ ["Updated", item.updatedAt]
66478
+ ]);
66479
+ });
66480
+ var printVersionSummary = (item) => printFields([
66481
+ ["Version", `${item.version} (${item.id})`],
65951
66482
  ["Runtime", item.runtime],
65952
- ["Status", item.status],
65953
- ["Permissions", item.permissions.join(", ")],
65954
- ["Send mode", item.sendMode],
65955
- ["Mailboxes", item.scope.mailboxIds?.join(", ") ?? "All accessible mailboxes"],
65956
- ["Namespace", item.scope.namespaceId],
65957
- ["Webhook", item.webhook?.url]
66483
+ ["Published", item.publishedAt],
66484
+ ["Bundle", item.bundle === null ? "None" : `${item.bundle.sizeBytes} bytes`],
66485
+ ["SHA256", item.bundle?.sha256]
65958
66486
  ]);
66487
+ var printVersion = (item) => gen2(function* () {
66488
+ yield* printVersionSummary(item);
66489
+ yield* log("Manifest");
66490
+ yield* printManifest(item.manifest);
66491
+ });
66492
+ var printInstallationSummary = (item) => gen2(function* () {
66493
+ yield* log(`${item.displayName} (${item.name}) \u2014 ${item.status}`);
66494
+ yield* printFields([
66495
+ ["Installation", item.id],
66496
+ ["Extension ID", item.extensionId],
66497
+ ["Version", `${item.version.version} (${item.version.id})`],
66498
+ ["Runtime", item.runtime],
66499
+ ["Created", item.createdAt]
66500
+ ]);
66501
+ });
66502
+ var printInstallation = (item) => gen2(function* () {
66503
+ yield* printInstallationSummary(item);
66504
+ yield* log("Access and delivery");
66505
+ yield* printFields([
66506
+ ["Events", item.events.join(", ") || "None"],
66507
+ ["Permissions", item.permissions.join(", ") || "None"],
66508
+ ["Send mode", item.sendMode],
66509
+ [
66510
+ "Mailboxes",
66511
+ item.scope.mailboxIds === null ? "All accessible mailboxes" : item.scope.mailboxIds.join(", ") || "None"
66512
+ ],
66513
+ ["Namespace", item.scope.namespaceId ?? "All namespaces"],
66514
+ ["Webhook", item.webhook?.url ?? "None"],
66515
+ ["Webhook endpoint", item.webhook?.endpointId],
66516
+ ["Updated", item.updatedAt],
66517
+ ["Disabled", item.disabledAt ?? "No"]
66518
+ ]);
66519
+ });
66520
+ var printRunSummary = (item) => gen2(function* () {
66521
+ yield* log(`${item.id}: ${item.outcome}`);
66522
+ yield* printFields([
66523
+ ["Event", item.eventId],
66524
+ ["Type", item.eventType],
66525
+ ["Attempt", item.attempt],
66526
+ ["Started", item.startedAt],
66527
+ ["Duration (ms)", item.durationMs],
66528
+ ["Error", item.error ?? "None"]
66529
+ ]);
66530
+ });
66531
+ var printUpgrade = (result) => gen2(function* () {
66532
+ yield* log(result.dryRun ? "Upgrade preview; no changes made. Installation details below show its current state." : result.versionChange === null ? "Installation already uses the selected version; no changes made." : "Installation upgraded.");
66533
+ yield* printFields([
66534
+ ["From version", `${result.fromVersion.version} (${result.fromVersion.id})`],
66535
+ ["To version", `${result.toVersion.version} (${result.toVersion.id})`],
66536
+ ["Added grants", result.permissionDiff.added.join(", ") || "None"],
66537
+ ["Removed grants", result.permissionDiff.removed.join(", ") || "None"]
66538
+ ]);
66539
+ yield* printInstallation(result.installation);
66540
+ if (result.versionChange !== null) {
66541
+ yield* log("Version change");
66542
+ yield* printFields([
66543
+ ["Change ID", result.versionChange.id],
66544
+ ["Organization", result.versionChange.organizationId],
66545
+ ["Changed by", result.versionChange.changedBy],
66546
+ ["Changed at", result.versionChange.changedAt]
66547
+ ]);
66548
+ }
66549
+ });
66550
+
66551
+ // src/commands/extensions-api.ts
65959
66552
  var pageFlags = {
65960
66553
  limit: Int5("limit").pipe(withDescription2("Items per page"), optional4),
65961
66554
  cursor: String9("cursor").pipe(withDescription2("Resume after this nextCursor from a previous page"), optional4),
@@ -66015,13 +66608,7 @@ var list24 = make29("list", { ...pageFlags, json: jsonFlag }).pipe(withDescripti
66015
66608
  flags,
66016
66609
  empty: "No extensions found.",
66017
66610
  fetch: (query) => list10(query).pipe(client.provide, mapError2((e) => mailboxApiError("Could not list extensions", e))),
66018
- print: (item) => printFields([
66019
- ["ID", item.id],
66020
- ["Name", item.name],
66021
- ["Display name", item.displayName],
66022
- ["Runtime", item.runtime],
66023
- ["Version", item.latestVersion.version]
66024
- ])
66611
+ print: printExtension
66025
66612
  });
66026
66613
  })));
66027
66614
  var versions = make29("versions", {
@@ -66034,35 +66621,19 @@ var versions = make29("versions", {
66034
66621
  flags,
66035
66622
  empty: "No versions found.",
66036
66623
  fetch: (query) => listVersions({ id: extension, ...query }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not list versions", e))),
66037
- print: (item) => printFields([
66038
- ["ID", item.id],
66039
- ["Version", item.version],
66040
- ["Runtime", item.runtime],
66041
- ["Published", item.publishedAt],
66042
- ["Size", item.bundle?.sizeBytes],
66043
- ["SHA256", item.bundle?.sha256]
66044
- ])
66624
+ print: printVersionSummary
66045
66625
  });
66046
66626
  })));
66047
66627
  var version2 = make29("version", {
66048
66628
  extension: extensionArgument,
66049
66629
  version: String10("version"),
66050
66630
  json: jsonFlag
66051
- }).pipe(withDescription3("Show one published version with its manifest, by version or id"), withExamples([{ command: "samva extensions version auto-reply 1.0.0 --json" }]), withHandler(({ extension, version, json }) => gen2(function* () {
66631
+ }).pipe(withDescription3("Show one published version with its manifest, by version or id"), withExamples([{ command: "samva extensions version auto-reply 1.0.0 --json" }]), withHandler(({ extension, version: selectedVersion, json }) => gen2(function* () {
66052
66632
  const client = yield* getClientProvider;
66053
- const data = yield* getVersion({ id: extension, versionId: version }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not read version", e)));
66633
+ const data = yield* getVersion({ id: extension, versionId: selectedVersion }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not read version", e)));
66054
66634
  if (json)
66055
66635
  return yield* printJson(data);
66056
- yield* printFields([
66057
- ["ID", data.id],
66058
- ["Version", data.version],
66059
- ["Runtime", data.runtime],
66060
- ["Published", data.publishedAt],
66061
- ["Events", data.manifest.events.join(", ")],
66062
- ["Permissions", data.manifest.permissions.join(", ")],
66063
- ["Size", data.bundle?.sizeBytes],
66064
- ["SHA256", data.bundle?.sha256]
66065
- ]);
66636
+ yield* printVersion(data);
66066
66637
  })));
66067
66638
  var install2 = make29("install", {
66068
66639
  extension: extensionArgument,
@@ -66077,11 +66648,20 @@ var install2 = make29("install", {
66077
66648
  {
66078
66649
  command: "samva extensions install auto-reply --mailbox mbx_1234567890123456 --permission read --permission send --send-mode approval"
66079
66650
  }
66080
- ]), withHandler(({ extension, version, mailbox, namespace, permission, sendMode, webhookUrl, json }) => gen2(function* () {
66651
+ ]), withHandler(({
66652
+ extension,
66653
+ version: selectedVersion,
66654
+ mailbox,
66655
+ namespace,
66656
+ permission,
66657
+ sendMode,
66658
+ webhookUrl,
66659
+ json
66660
+ }) => gen2(function* () {
66081
66661
  const client = yield* getClientProvider;
66082
66662
  const data = yield* install({
66083
66663
  extension,
66084
- ...isSome2(version) ? { version: version.value } : {},
66664
+ ...isSome2(selectedVersion) ? { version: selectedVersion.value } : {},
66085
66665
  ...mailbox.length ? { mailboxIds: mailbox } : {},
66086
66666
  ...isSome2(namespace) ? { namespaceId: namespace.value } : {},
66087
66667
  ...permission.length ? { permissions: permission } : {},
@@ -66122,6 +66702,37 @@ var installation = make29("installation", {
66122
66702
  return yield* printJson(data);
66123
66703
  yield* printInstallation(data);
66124
66704
  })));
66705
+ var upgrade2 = make29("upgrade", {
66706
+ id: installationArgument,
66707
+ version: String9("version").pipe(withSchema2(Union2([ExtensionVersionString, ExtensionVersionId2])), withDescription2("Published version or version ID; defaults to the latest published version"), optional4),
66708
+ acceptPermissions: Literals3("accept-permissions", ExtensionUpgradeGrant.literals).pipe(withDescription2("Acknowledge one added permission:<name> or event:<type> grant; repeat for each"), atLeast2(0)),
66709
+ dryRun: Boolean6("dry-run").pipe(withDescription2("Ask the API for a preview without changing the installation"), withDefault5(false)),
66710
+ yes: Boolean6("yes").pipe(withDescription2("Skip confirmation"), withDefault5(false)),
66711
+ json: jsonFlag
66712
+ }).pipe(withDescription3("Upgrade an installation using a person signed in with samva login"), withExamples([
66713
+ { command: "samva extensions upgrade exti_1234567890123456 --dry-run --json" },
66714
+ {
66715
+ command: "samva extensions upgrade exti_1234567890123456 --version 2.0.0 --accept-permissions permission:send --accept-permissions event:mailbox.message.sent --yes"
66716
+ }
66717
+ ]), withHandler(({ id, version: selectedVersion, acceptPermissions, dryRun, yes, json }) => gen2(function* () {
66718
+ if (!dryRun)
66719
+ yield* confirmDestructive({
66720
+ yes,
66721
+ json,
66722
+ message: `Upgrade ${id} to ${getOrElse(selectedVersion, () => "the latest published version")}?`,
66723
+ nonInteractiveMessage: "Upgrade changes the installation's version and grants. Preview with --dry-run, then pass --yes to confirm and --accept-permissions for every added grant."
66724
+ });
66725
+ const client = yield* getClientProvider;
66726
+ const data = yield* upgrade({
66727
+ id,
66728
+ ...isSome2(selectedVersion) ? { version: selectedVersion.value } : {},
66729
+ ...acceptPermissions.length ? { acceptPermissions } : {},
66730
+ ...dryRun ? { dryRun: true } : {}
66731
+ }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not upgrade extension", e, { personOnly: "manage" })));
66732
+ if (json)
66733
+ return yield* printJson(data);
66734
+ yield* printUpgrade(data);
66735
+ })));
66125
66736
  var uninstall2 = make29("uninstall", {
66126
66737
  id: installationArgument,
66127
66738
  yes: Boolean6("yes").pipe(withDefault5(false)),
@@ -66157,15 +66768,7 @@ var runs = make29("runs", { id: installationArgument, json: jsonFlag }).pipe(wit
66157
66768
  if (!data.items.length)
66158
66769
  return yield* log("No runs found.");
66159
66770
  for (const item of data.items)
66160
- yield* printFields([
66161
- ["Run", item.id],
66162
- ["Event", item.eventId],
66163
- ["Type", item.eventType],
66164
- ["Attempt", item.attempt],
66165
- ["Outcome", item.outcome],
66166
- ["Duration (ms)", item.durationMs],
66167
- ["Error", item.error]
66168
- ]);
66771
+ yield* printRunSummary(item);
66169
66772
  })));
66170
66773
  var run6 = make29("run", {
66171
66774
  id: installationArgument,
@@ -66173,23 +66776,15 @@ var run6 = make29("run", {
66173
66776
  json: jsonFlag
66174
66777
  }).pipe(withDescription3("Show one hosted run with the lines its handler logged"), withExamples([
66175
66778
  { command: "samva extensions run exti_1234567890123456 0b6c1e1a-run-id --json" }
66176
- ]), withHandler(({ id, run, json }) => gen2(function* () {
66779
+ ]), withHandler(({ id, run: runId, json }) => gen2(function* () {
66177
66780
  const client = yield* getClientProvider;
66178
- const data = yield* getRun2({ id, runId: run }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not read run", e)));
66781
+ const data = yield* getRun2({ id, runId }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not read run", e)));
66179
66782
  if (json)
66180
66783
  return yield* printJson(data);
66181
- yield* printFields([
66182
- ["Run", data.id],
66183
- ["Event", data.eventId],
66184
- ["Type", data.eventType],
66185
- ["Attempt", data.attempt],
66186
- ["Outcome", data.outcome],
66187
- ["Duration (ms)", data.durationMs],
66188
- ["Error", data.error]
66189
- ]);
66190
- if (data.logs.length)
66191
- yield* log(truncateForDisplay(data.logs.join(`
66192
- `)));
66784
+ yield* printRunSummary(data);
66785
+ yield* log("Logs");
66786
+ yield* log(data.logs.length ? data.logs.join(`
66787
+ `) : "None");
66193
66788
  })));
66194
66789
  var extensionApiCommands = [
66195
66790
  list24,
@@ -66198,6 +66793,7 @@ var extensionApiCommands = [
66198
66793
  install2,
66199
66794
  installations,
66200
66795
  installation,
66796
+ upgrade2,
66201
66797
  uninstall2,
66202
66798
  setStatus("disable"),
66203
66799
  setStatus("enable"),
@@ -66205,6 +66801,66 @@ var extensionApiCommands = [
66205
66801
  run6
66206
66802
  ];
66207
66803
 
66804
+ // ../sdk/dist/effect/mailboxes.js
66805
+ var exports_mailboxes = {};
66806
+ __export(exports_mailboxes, {
66807
+ MailboxEventStreamError: () => MailboxEventStreamError,
66808
+ addThreadLabels: () => addThreadLabels,
66809
+ approveAction: () => approveAction,
66810
+ create: () => create8,
66811
+ createDraft: () => createDraft,
66812
+ createGrant: () => createGrant,
66813
+ createLabel: () => createLabel,
66814
+ createNote: () => createNote,
66815
+ createPolicy: () => createPolicy,
66816
+ deleteDraft: () => deleteDraft,
66817
+ deleteLabel: () => deleteLabel,
66818
+ deleteNote: () => deleteNote,
66819
+ deletePolicy: () => deletePolicy,
66820
+ denyAction: () => denyAction,
66821
+ discardMessage: () => discardMessage,
66822
+ events: () => events,
66823
+ forward: () => forward,
66824
+ get: () => get13,
66825
+ getAgentActivity: () => getAgentActivity,
66826
+ getDraft: () => getDraft,
66827
+ getMessage: () => getMessage,
66828
+ getMessageAttachment: () => getMessageAttachment,
66829
+ getMessageRaw: () => getMessageRaw,
66830
+ getPolicy: () => getPolicy,
66831
+ getThread: () => getThread,
66832
+ getThreadContent: () => getThreadContent,
66833
+ list: () => list11,
66834
+ listActions: () => listActions,
66835
+ listDrafts: () => listDrafts,
66836
+ listEvents: () => listEvents,
66837
+ listFolders: () => listFolders,
66838
+ listGrants: () => listGrants,
66839
+ listLabels: () => listLabels,
66840
+ listPolicies: () => listPolicies,
66841
+ listQuarantine: () => listQuarantine,
66842
+ listThreadMessages: () => listThreadMessages,
66843
+ listThreadNotes: () => listThreadNotes,
66844
+ listThreads: () => listThreads,
66845
+ pause: () => pause,
66846
+ releaseMessage: () => releaseMessage,
66847
+ remove: () => remove9,
66848
+ removeThreadLabels: () => removeThreadLabels,
66849
+ reply: () => reply,
66850
+ replyAll: () => replyAll,
66851
+ resume: () => resume,
66852
+ revokeGrant: () => revokeGrant,
66853
+ sendDraft: () => sendDraft,
66854
+ sendMessage: () => sendMessage2,
66855
+ update: () => update9,
66856
+ updateDraft: () => updateDraft,
66857
+ updateGrant: () => updateGrant,
66858
+ updateLabel: () => updateLabel,
66859
+ updateNote: () => updateNote,
66860
+ updatePolicy: () => updatePolicy,
66861
+ updateThread: () => updateThread
66862
+ });
66863
+
66208
66864
  // src/commands/mailboxes-events.ts
66209
66865
  var NORMAL_CLOSE = 1000;
66210
66866
  var refusalNext = (failure) => {
@@ -66360,8 +67016,12 @@ var init = make29("init", {
66360
67016
  const data = yield* initExtension(dir, manifest);
66361
67017
  if (json)
66362
67018
  yield* printJson(data);
66363
- else
66364
- yield* log(`Created ${name} in ${data.directory}. Run bun install, then samva extensions dev.`);
67019
+ else {
67020
+ yield* log(`Created ${name} in ${data.directory}.`);
67021
+ yield* printManifest(data.manifest);
67022
+ yield* printFields([["Files", data.files.join(", ")]]);
67023
+ yield* log("Run bun install in that directory, then samva extensions dev.");
67024
+ }
66365
67025
  })));
66366
67026
  var build2 = make29("build", {
66367
67027
  ...projectFlags,
@@ -66370,14 +67030,14 @@ var build2 = make29("build", {
66370
67030
  const { bundle: _bundle, ...data } = yield* buildExtension(dir, entry, out);
66371
67031
  if (json)
66372
67032
  yield* printJson(data);
66373
- else
67033
+ else {
67034
+ yield* printManifest(data.manifest);
66374
67035
  yield* printFields([
66375
- ["Extension", `${data.manifest.name}@${data.manifest.version}`],
66376
- ["Runtime", data.manifest.runtime],
66377
67036
  ["Size", `${data.sizeBytes} bytes`],
66378
67037
  ["SHA256", data.sha256],
66379
67038
  ["Output", data.output]
66380
67039
  ]);
67040
+ }
66381
67041
  })));
66382
67042
  var publish3 = make29("publish", projectFlags).pipe(withDescription3("Build and publish an immutable extension version as a person signed in with samva login"), withExamples([{ command: "samva extensions publish . --json" }]), withHandler(({ dir, entry, json }) => gen2(function* () {
66383
67043
  const built = yield* buildExtension(dir, entry);
@@ -66388,8 +67048,11 @@ var publish3 = make29("publish", projectFlags).pipe(withDescription3("Build and
66388
67048
  }).pipe(client.provide, mapError2((error) => mailboxApiError("Could not publish extension", error, { personOnly: "publish" })));
66389
67049
  if (json)
66390
67050
  yield* printJson(data);
66391
- else
66392
- yield* log(`Published ${data.extension.name}@${data.version.version} (${data.version.id}).`);
67051
+ else {
67052
+ yield* log(`Published ${data.extension.name}@${data.version.version}.`);
67053
+ yield* printExtension(data.extension);
67054
+ yield* printVersion(data.version);
67055
+ }
66393
67056
  })));
66394
67057
  var dev = make29("dev", {
66395
67058
  ...projectFlags,
@@ -66414,9 +67077,9 @@ var dev = make29("dev", {
66414
67077
  };
66415
67078
  const stopped = new AbortController;
66416
67079
  const client = createSamvaClient({
66417
- fetch: (input, init) => globalThis.fetch(input, {
66418
- ...init,
66419
- signal: init?.signal === undefined || init.signal === null ? stopped.signal : AbortSignal.any([init.signal, stopped.signal])
67080
+ fetch: (input, requestInit) => globalThis.fetch(input, {
67081
+ ...requestInit,
67082
+ signal: requestInit?.signal === undefined || requestInit.signal === null ? stopped.signal : AbortSignal.any([requestInit.signal, stopped.signal])
66420
67083
  }),
66421
67084
  baseUrl: config.baseUrl,
66422
67085
  headers
@@ -66441,7 +67104,8 @@ var dev = make29("dev", {
66441
67104
  const data = { eventId: event.id, cursor: event.cursor, ...result };
66442
67105
  const text = mode === "jsonl" ? JSON.stringify(resultEnvelope("extensions.dev", data)) : [
66443
67106
  ...result.logs,
66444
- `${event.id}: ${result.ok ? "succeeded" : `failed: ${result.error}`}`
67107
+ `${event.id}: ${result.ok ? "succeeded" : `failed: ${result.error}`}`,
67108
+ `Cursor ${event.cursor}`
66445
67109
  ].join(`
66446
67110
  `);
66447
67111
  yield* writeOutput(process.stdout, `${text}
@@ -69149,67 +69813,6 @@ var logoutCommand = make29("logout").pipe(withDescription3("Sign out and remove
69149
69813
  yield* clearCredentials;
69150
69814
  yield* printResult({ action: "logout" }, "Logged out.");
69151
69815
  })));
69152
- // ../core/src/shared/excess-properties.ts
69153
- var rejectExcessProperties = (schema) => {
69154
- const declared = new Set(Object.keys(schema.fields));
69155
- return flip3(flip3(schema).check(makeFilter2((input, ast) => {
69156
- if (!isObject(input))
69157
- return;
69158
- const issues = [];
69159
- for (const key of Reflect.ownKeys(input)) {
69160
- if (declared.has(key))
69161
- continue;
69162
- issues.push({ path: [key], issue: new UnexpectedKey(ast, input[key]) });
69163
- }
69164
- return issues;
69165
- })));
69166
- };
69167
-
69168
- // ../core/src/messages/attachment-budget.ts
69169
- var EMAIL_ATTACHMENT_BUDGET = {
69170
- maxCount: 10,
69171
- maxItemBytes: 25 * 1024 * 1024,
69172
- maxAggregateBytes: 25 * 1024 * 1024
69173
- };
69174
- var emailAttachmentBudgetViolation = (attachments) => {
69175
- if (attachments.length > EMAIL_ATTACHMENT_BUDGET.maxCount)
69176
- return "count";
69177
- let aggregateBytes = 0;
69178
- for (const attachment of attachments) {
69179
- if (!Number.isSafeInteger(attachment.size) || attachment.size <= 0 || attachment.size > EMAIL_ATTACHMENT_BUDGET.maxItemBytes) {
69180
- return "itemBytes";
69181
- }
69182
- aggregateBytes += attachment.size;
69183
- if (aggregateBytes > EMAIL_ATTACHMENT_BUDGET.maxAggregateBytes)
69184
- return "aggregateBytes";
69185
- }
69186
- return null;
69187
- };
69188
-
69189
- // ../core/src/messages/email-attachment.ts
69190
- var EmailAttachment2 = Struct({
69191
- filename: String4,
69192
- content: optional2(String4.check(isBase64())),
69193
- mediaId: optional2(MediaId2),
69194
- contentType: String4,
69195
- size: Finite.check(isInt(), isGreaterThan2(0), isLessThanOrEqualTo3(EMAIL_ATTACHMENT_BUDGET.maxItemBytes))
69196
- }).check(makeFilter2((attachment) => {
69197
- const hasInlineContent = attachment.content !== undefined;
69198
- const hasOwnedMedia = attachment.mediaId !== undefined;
69199
- if (hasInlineContent === hasOwnedMedia)
69200
- return false;
69201
- if (!hasInlineContent)
69202
- return true;
69203
- const decoded = decode(attachment.content);
69204
- return isSuccess2(decoded) && decoded.success.byteLength === attachment.size;
69205
- }, {
69206
- message: "Email attachment requires exactly one of content or mediaId, and inline content must match its declared size"
69207
- })).annotate({
69208
- identifier: "EmailAttachment"
69209
- }).pipe(rejectExcessProperties);
69210
- var EmailAttachments2 = ArraySchema(EmailAttachment2).check(isMaxLength(EMAIL_ATTACHMENT_BUDGET.maxCount), makeFilter2((attachments) => emailAttachmentBudgetViolation(attachments) === null, {
69211
- message: `Email attachments must total at most ${EMAIL_ATTACHMENT_BUDGET.maxAggregateBytes} bytes`
69212
- }));
69213
69816
 
69214
69817
  // ../core/src/mailboxes/resource.ts
69215
69818
  var MailboxActorKind = Literals(mailboxActorKinds);
@@ -69330,6 +69933,116 @@ var UpdateMailboxPayload = Struct({
69330
69933
  }))
69331
69934
  }).annotate({ identifier: "UpdateMailboxPayload" });
69332
69935
 
69936
+ // ../core/src/mailboxes/action-event-policy.ts
69937
+ var MailboxActionType = Literals(mailboxActionScopes);
69938
+ var MailboxActionSource = Literals(mailboxActionSources);
69939
+ var MailboxActionState = Literals(mailboxActionStates);
69940
+ var MailboxPolicyOutcome = Union2([
69941
+ Struct({ outcome: Literal2("allow") }),
69942
+ Struct({
69943
+ outcome: Literal2("requireApproval"),
69944
+ approverKinds: ArraySchema(Literals(mailboxApproverKinds)),
69945
+ reason: String4
69946
+ }),
69947
+ Struct({ outcome: Literal2("deny"), reason: String4 })
69948
+ ]);
69949
+ var MailboxPolicyDecisionSchema = Struct({
69950
+ policyId: NullOr(MailboxPolicyId2),
69951
+ actionId: MailboxActionId2,
69952
+ outcome: MailboxPolicyOutcome,
69953
+ decidedAt: DateFromString
69954
+ });
69955
+ var MailboxActionRecord = Struct({
69956
+ id: MailboxActionId2,
69957
+ mailboxId: MailboxId2,
69958
+ threadId: optional2(MailboxThreadId2),
69959
+ conversationId: optional2(ConversationId2),
69960
+ draftId: optional2(MailboxDraftId2),
69961
+ type: MailboxActionType,
69962
+ source: MailboxActionSource,
69963
+ state: MailboxActionState,
69964
+ proposedBy: MailboxActorRef,
69965
+ policyDecision: optional2(MailboxPolicyDecisionSchema),
69966
+ payload: Record(String4, Unknown2),
69967
+ createdAt: DateFromString,
69968
+ updatedAt: DateFromString
69969
+ });
69970
+ var MailboxEventType = Literals(mailboxEventTypes);
69971
+ var MailboxActionProposalResponse = Union2([
69972
+ Struct({ status: Literal2("accepted"), action: MailboxActionRecord }),
69973
+ Struct({
69974
+ status: Literal2("approvalRequired"),
69975
+ action: MailboxActionRecord,
69976
+ reason: String4
69977
+ }),
69978
+ Struct({
69979
+ status: Literal2("denied"),
69980
+ action: MailboxActionRecord,
69981
+ reason: String4
69982
+ })
69983
+ ]);
69984
+ var MailboxActionDecision2 = Struct({
69985
+ outcome: Literals(["allow", "requireApproval", "deny"]),
69986
+ reason: NullOr(String4),
69987
+ policyId: NullOr(MailboxPolicyId2),
69988
+ decidedAt: DateFromString
69989
+ }).annotate({ identifier: "MailboxActionDecision" });
69990
+ var MailboxAction2 = Struct({
69991
+ id: MailboxActionId2,
69992
+ type: MailboxActionType,
69993
+ state: MailboxActionState,
69994
+ source: MailboxActionSource,
69995
+ proposedBy: MailboxActorRef,
69996
+ threadId: NullOr(MailboxThreadId2),
69997
+ draftId: NullOr(MailboxDraftId2),
69998
+ decision: NullOr(MailboxActionDecision2),
69999
+ createdAt: DateFromString,
70000
+ updatedAt: DateFromString
70001
+ }).annotate({ identifier: "MailboxAction" });
70002
+ var MailboxEvent2 = Struct({
70003
+ id: MailboxEventId2,
70004
+ type: MailboxEventType,
70005
+ threadId: NullOr(MailboxThreadId2),
70006
+ actionId: NullOr(MailboxActionId2),
70007
+ actor: MailboxActorRef,
70008
+ payload: Record(String4, Unknown2),
70009
+ occurredAt: DateFromString
70010
+ }).annotate({ identifier: "MailboxEvent" });
70011
+ // ../core/src/shared/excess-properties.ts
70012
+ var rejectExcessProperties = (schema) => {
70013
+ const declared = new Set(Object.keys(schema.fields));
70014
+ return flip3(flip3(schema).check(makeFilter2((input, ast) => {
70015
+ if (!isObject(input))
70016
+ return;
70017
+ const issues = [];
70018
+ for (const key of Reflect.ownKeys(input)) {
70019
+ if (declared.has(key))
70020
+ continue;
70021
+ issues.push({ path: [key], issue: new UnexpectedKey(ast, input[key]) });
70022
+ }
70023
+ return issues;
70024
+ })));
70025
+ };
70026
+
70027
+ // ../core/src/messages/email-attachment.ts
70028
+ var EmailAttachment2 = Struct({
70029
+ filename: String4,
70030
+ content: optional2(String4),
70031
+ mediaId: optional2(MediaId2),
70032
+ contentType: String4,
70033
+ size: Finite.check(isInt(), isGreaterThan2(0), isLessThanOrEqualTo3(EMAIL_ATTACHMENT_BUDGET.maxItemBytes))
70034
+ }).check(makeFilter2((attachment) => attachment.content === undefined !== (attachment.mediaId === undefined), { message: "Email attachment requires exactly one of content or mediaId" }), makeFilter2((attachment) => {
70035
+ if (attachment.content === undefined)
70036
+ return true;
70037
+ const decoded = decode(attachment.content);
70038
+ return isSuccess2(decoded) && decoded.success.byteLength === attachment.size;
70039
+ }, { message: "Inline content must be Base64 that decodes to exactly its declared size" })).annotate({
70040
+ identifier: "EmailAttachment"
70041
+ }).pipe(rejectExcessProperties);
70042
+ var EmailAttachments2 = ArraySchema(EmailAttachment2).check(isMaxLength(EMAIL_ATTACHMENT_BUDGET.maxCount), makeFilter2((attachments) => emailAttachmentBudgetViolation(attachments) === null, {
70043
+ message: `Email attachments must total at most ${EMAIL_ATTACHMENT_BUDGET.maxAggregateBytes} bytes`
70044
+ }), makeFilter2((attachments) => emailInlineAttachmentBytes(attachments) <= EMAIL_ATTACHMENT_BUDGET.maxInlineBytes, { message: EMAIL_INLINE_ATTACHMENT_MESSAGE }));
70045
+
69333
70046
  // ../core/src/mailboxes/thread.ts
69334
70047
  var CssTrustedEmailBody = String4.pipe(brand("CssTrustedEmailBody"));
69335
70048
  var MailboxMessageAttachmentSchema = Struct({
@@ -69521,6 +70234,143 @@ var MailboxThreadLabels = Struct({
69521
70234
  labels: NonEmptyArray(MailboxLabelId2)
69522
70235
  }).annotate({ identifier: "MailboxThreadLabels" });
69523
70236
 
70237
+ // src/lib/mailbox-output.ts
70238
+ var present = (value) => value === null ? "none" : value === "" ? '""' : value;
70239
+ var actor = (value) => `${value.displayName == null ? "" : `${value.displayName} \u2014 `}${value.kind} ${value.id}`;
70240
+ var identity2 = (address, name, attributed) => `${name === undefined || name === null ? "" : `${name} <`}${address}${name === undefined || name === null ? "" : ">"}${attributed === undefined ? "" : attributed === null ? "; actor: none" : `; actor: ${actor(attributed)}`}`;
70241
+ var printMailboxSummary = (data) => gen2(function* () {
70242
+ yield* log(`${data.displayName} (${data.slug}) \u2014 ${data.status}`);
70243
+ yield* printFields([
70244
+ ["ID", data.id],
70245
+ ["Primary address", present(data.primaryAddress)],
70246
+ ["Namespace", present(data.namespaceId)],
70247
+ ["Created", data.createdAt]
70248
+ ]);
70249
+ });
70250
+ var printMailbox = (data) => gen2(function* () {
70251
+ yield* printMailboxSummary(data);
70252
+ yield* printFields([
70253
+ ["Description", present(data.description)],
70254
+ ["Updated", data.updatedAt],
70255
+ [
70256
+ "Default from",
70257
+ data.defaultFrom === null ? "none" : identity2(data.defaultFrom.address, data.defaultFrom.displayName)
70258
+ ]
70259
+ ]);
70260
+ yield* log("Addresses:");
70261
+ if (!data.addresses.length)
70262
+ yield* log(" none");
70263
+ for (const address of data.addresses)
70264
+ yield* log(` ${identity2(address.address, address.displayName)} \u2014 ${address.source}; ID ${address.id}; domain ${present(address.domainId)}; display name ${present(address.displayName)}`);
70265
+ yield* log("Metadata:");
70266
+ if (!Object.keys(data.metadata).length)
70267
+ yield* log(" none");
70268
+ for (const [key, value] of Object.entries(data.metadata))
70269
+ yield* log(` ${key}: ${JSON.stringify(value)}`);
70270
+ });
70271
+ var printThread = (data) => gen2(function* () {
70272
+ yield* log(`${data.subject === null ? "No subject" : data.subject} \u2014 ${data.folder}, ${data.priority} priority`);
70273
+ yield* printFields([
70274
+ ["ID", data.id],
70275
+ [
70276
+ "From",
70277
+ data.from === null ? "none" : `${present(data.from.displayName)} <${present(data.from.address)}>`
70278
+ ],
70279
+ ["Preview", data.preview === null ? "none" : JSON.stringify(data.preview)],
70280
+ ["Messages", data.messageCount],
70281
+ ["Attachments", data.hasAttachments],
70282
+ ["Draft", data.hasDraft],
70283
+ ["Labels", data.labels.length ? data.labels.join(", ") : "none"],
70284
+ ["Read", data.read],
70285
+ ["Starred", data.starred],
70286
+ ["Snoozed until", present(data.snoozedUntil)],
70287
+ ["Last activity", data.lastActivityAt]
70288
+ ]);
70289
+ });
70290
+ var printMessage2 = (data) => gen2(function* () {
70291
+ yield* log("Notice: this body is untrusted email from outside the organization.");
70292
+ yield* log(`${data.direction} message \u2014 ${data.subject ?? "No subject"}`);
70293
+ yield* printFields([
70294
+ ["ID", data.id],
70295
+ ["Thread", data.threadId],
70296
+ ["Conversation", data.conversationId],
70297
+ ["From", identity2(data.from.address, data.from.displayName, data.from.actor)],
70298
+ ["Occurred", data.occurredAt],
70299
+ ["Reply-To", data.replyTo.length ? data.replyTo.join(", ") : "none"],
70300
+ [
70301
+ "Sent by",
70302
+ data.sentBy === undefined ? undefined : data.sentBy === null ? "none" : actor(data.sentBy)
70303
+ ]
70304
+ ]);
70305
+ yield* log("Recipients:");
70306
+ if (!data.recipients.length)
70307
+ yield* log(" none");
70308
+ for (const recipient of data.recipients)
70309
+ yield* log(` ${recipient.kind}: ${identity2(recipient.address, recipient.displayName, recipient.actor)}`);
70310
+ yield* printFields([
70311
+ ["Message-ID", present(data.headers.messageId)],
70312
+ ["In-Reply-To", present(data.headers.inReplyTo)],
70313
+ ["References", data.headers.references.length ? data.headers.references.join(" ") : "none"],
70314
+ [
70315
+ "Authentication",
70316
+ data.authentication === null ? "none" : `SPF ${present(data.authentication.spf)}; DKIM ${present(data.authentication.dkim)}; DMARC ${present(data.authentication.dmarc)}`
70317
+ ]
70318
+ ]);
70319
+ yield* log("Attachments:");
70320
+ if (!data.attachments.length)
70321
+ yield* log(" none");
70322
+ for (const attachment of data.attachments)
70323
+ yield* log(` ${attachment.filename} \u2014 ${attachment.contentType}, ${attachment.size} bytes; inline ${attachment.isInline}; ID ${attachment.id}`);
70324
+ for (const [label, content] of [
70325
+ ["Reply text", data.replyText],
70326
+ ["Text", data.text],
70327
+ ["HTML", data.html]
70328
+ ]) {
70329
+ if (content !== undefined) {
70330
+ yield* log(`${label}:`);
70331
+ yield* log(content);
70332
+ }
70333
+ }
70334
+ });
70335
+ var printReceipt = (data) => gen2(function* () {
70336
+ yield* log(`Send ${data.status}${data.waitReason === null ? "" : ` \u2014 waiting: ${data.waitReason}`}`);
70337
+ yield* printFields([
70338
+ ["Message", present(data.messageId)],
70339
+ ["Thread", data.threadId],
70340
+ ["Action", data.actionId],
70341
+ ["Wait reason", present(data.waitReason)],
70342
+ ["Review expected at", present(data.reviewExpectedAt)],
70343
+ ["Skipped", skippedRecipientsLine(data) ?? "none"],
70344
+ ["Created", data.createdAt]
70345
+ ]);
70346
+ });
70347
+ var printAction = (data) => gen2(function* () {
70348
+ yield* log(`${data.type} \u2014 ${data.state}`);
70349
+ yield* printFields([
70350
+ ["Action", data.id],
70351
+ ["Source", data.source],
70352
+ ["Proposed by", actor(data.proposedBy)],
70353
+ ["Thread", present(data.threadId)],
70354
+ ["Draft", present(data.draftId)],
70355
+ ["Created", data.createdAt],
70356
+ ["Updated", data.updatedAt]
70357
+ ]);
70358
+ yield* log(data.decision === null ? "Decision: none" : `Decision: ${data.decision.outcome}; reason ${present(data.decision.reason)}; policy ${present(data.decision.policyId)}; decided ${data.decision.decidedAt}`);
70359
+ });
70360
+ var printHeldMessage = (data) => gen2(function* () {
70361
+ yield* log(`${data.subject === null ? "No subject" : data.subject} \u2014 ${data.disposition}, ${data.reason} (${data.source})`);
70362
+ yield* printFields([
70363
+ ["Message", data.id],
70364
+ ["From", identity2(data.from.address, data.from.name)],
70365
+ ["Sender name", present(data.from.name)],
70366
+ ["Received at", data.receivedAt],
70367
+ ["Held at", data.heldAt],
70368
+ ["Released at", present(data.releasedAt)],
70369
+ ["Thread", present(data.threadId)],
70370
+ ["Discarded at", present(data.discardedAt)]
70371
+ ]);
70372
+ });
70373
+
69524
70374
  // src/commands/mailboxes.ts
69525
70375
  var mailboxFlag = String9("mailbox").pipe(withDescription2("Mailbox ID"), withSchema2(MailboxId2));
69526
70376
  var messageIdArgument = String10("message-id").pipe(withSchema3(MessageId2));
@@ -69607,11 +70457,7 @@ var list25 = make29("list", {
69607
70457
  before: getOrUndefined(before)
69608
70458
  }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not list mailboxes", e))),
69609
70459
  empty: "No mailboxes found.",
69610
- human: (item) => printFields([
69611
- ["ID", item.id],
69612
- ["Slug", item.slug],
69613
- ["Name", item.displayName]
69614
- ])
70460
+ human: printMailboxSummary
69615
70461
  });
69616
70462
  })));
69617
70463
  var create17 = make29("create", {
@@ -69643,13 +70489,164 @@ var create17 = make29("create", {
69643
70489
  }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not create mailbox", e)));
69644
70490
  if (json)
69645
70491
  return yield* printJson(data);
69646
- yield* printFields([
69647
- ["ID", data.id],
69648
- ["Name", data.displayName],
69649
- ["Address", data.primaryAddress],
69650
- ["Status", data.status]
69651
- ]);
70492
+ yield* printMailbox(data);
70493
+ })));
70494
+ var mailboxIdArgument = String10("mailbox-id").pipe(withSchema3(MailboxId2));
70495
+ var get23 = make29("get", { id: mailboxIdArgument, json: jsonFlag }).pipe(withDescription3("Inspect a mailbox's addresses, sending identity, and settings"), withHandler(({ id, json }) => gen2(function* () {
70496
+ const client = yield* getClientProvider;
70497
+ const result = yield* get13({ id }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not read mailbox", e)));
70498
+ yield* json ? printJson(result) : printMailbox(result);
70499
+ })));
70500
+ var update16 = make29("update", {
70501
+ id: mailboxIdArgument,
70502
+ data: String9("data").pipe(withDescription2("JSON patch or @file: displayName, defaultFrom, metadata (null deletes a metadata key)")),
70503
+ dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
70504
+ json: jsonFlag
70505
+ }).pipe(withDescription3("Update mailbox settings from JSON"), withExamples([
70506
+ {
70507
+ command: `samva mailboxes update mbx_1234567890123456 --data '{"displayName":"Support","defaultFrom":{"address":"support@example.com"}}'`
70508
+ }
70509
+ ]), withHandler(({ id, data, dryRun, json }) => gen2(function* () {
70510
+ let source = data;
70511
+ if (data.startsWith("@")) {
70512
+ const path = data.slice(1);
70513
+ if (!path)
70514
+ return yield* new CliUsageError({
70515
+ code: "missing_data_file",
70516
+ message: "--data @ requires a file path."
70517
+ });
70518
+ const fs = yield* FileSystem;
70519
+ source = yield* fs.readFileString(path).pipe(mapError2(() => new CliUsageError({
70520
+ code: "data_file_unreadable",
70521
+ message: `Could not read mailbox update data from ${path}.`
70522
+ })));
70523
+ }
70524
+ const raw = yield* try_3({
70525
+ try: () => JSON.parse(source),
70526
+ catch: () => new CliUsageError({
70527
+ code: "mailbox_update_invalid",
70528
+ message: "--data must be valid JSON."
70529
+ })
70530
+ });
70531
+ const payload = yield* decodeUnknownEffect2(UpdateMailboxPayload)(raw, {
70532
+ onExcessProperty: "error"
70533
+ }).pipe(mapError2((e) => new CliUsageError({
70534
+ code: "mailbox_update_invalid",
70535
+ message: `--data must match the mailbox update schema: ${String(e)}`
70536
+ })));
70537
+ if (!Object.keys(payload).length)
70538
+ return yield* new CliUsageError({
70539
+ code: "mailbox_update_empty",
70540
+ message: "--data must name at least one of displayName, defaultFrom, or metadata."
70541
+ });
70542
+ if (dryRun)
70543
+ return yield* json ? printJson({ dryRun: true, action: "mailboxes.update", id, request: payload }) : printFields([
70544
+ ["Dry run", true],
70545
+ ["Mailbox", id],
70546
+ ["Patch", JSON.stringify(payload)]
70547
+ ]);
70548
+ const client = yield* getClientProvider;
70549
+ const result = yield* update9({ id, ...payload }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not update mailbox", e)));
70550
+ yield* json ? printJson(result) : printMailbox(result);
70551
+ })));
70552
+ var lifecycle = (verb) => make29(verb, {
70553
+ id: mailboxIdArgument,
70554
+ dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
70555
+ json: jsonFlag
70556
+ }).pipe(withDescription3(verb === "pause" ? "Pause sending and inbound delivery; mail arriving while paused is not backfilled" : "Resume mailbox delivery"), withHandler(({ id, dryRun, json }) => gen2(function* () {
70557
+ if (dryRun)
70558
+ return yield* json ? printJson({ dryRun: true, action: `mailboxes.${verb}`, id }) : log(`[dry-run] Would ${verb} mailbox ${id}.`);
70559
+ const client = yield* getClientProvider;
70560
+ const result = yield* exports_mailboxes[verb]({ id }).pipe(client.provide, mapError2((e) => mailboxApiError(`Could not ${verb} mailbox`, e)));
70561
+ yield* json ? printJson(result) : printMailbox(result);
70562
+ })));
70563
+ var actionsList = make29("list", {
70564
+ mailbox: mailboxFlag,
70565
+ ...pageFlags2,
70566
+ state: Literals3("state", MailboxActionState.literals).pipe(optional4),
70567
+ after: instantFlag("after", "Only actions created after this ISO 8601 instant"),
70568
+ before: instantFlag("before", "Only actions created before this ISO 8601 instant"),
70569
+ json: jsonFlag
70570
+ }).pipe(withDescription3("List mailbox actions and their policy decisions"), withHandler(({ mailbox, limit, cursor, all, state, after, before, json }) => gen2(function* () {
70571
+ const client = yield* getClientProvider;
70572
+ yield* followPages({
70573
+ all,
70574
+ json,
70575
+ cursor,
70576
+ page: (pageCursor) => listActions({
70577
+ id: mailbox,
70578
+ limit: pageLimit(limit),
70579
+ cursor: pageCursor,
70580
+ state: getOrUndefined(state),
70581
+ after: getOrUndefined(after),
70582
+ before: getOrUndefined(before)
70583
+ }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not list actions", e))),
70584
+ empty: "No mailbox actions found.",
70585
+ human: printAction
70586
+ });
70587
+ })));
70588
+ var actionDecision = (verb) => make29(verb, {
70589
+ actionId: String10("action-id").pipe(withSchema3(MailboxActionId2)),
70590
+ mailbox: mailboxFlag,
70591
+ ...verb === "deny" ? {
70592
+ reason: optional6("reason").pipe(withDescription2("Denial reason; defaults to Denied by reviewer."))
70593
+ } : {},
70594
+ dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
70595
+ yes: Boolean6("yes").pipe(withDefault5(false)),
70596
+ json: jsonFlag
70597
+ }).pipe(withDescription3(`${verb === "approve" ? "Approve and execute" : "Deny"} an action as a signed-in person other than its proposer`), withHandler(({ actionId, mailbox, reason, dryRun, yes, json }) => gen2(function* () {
70598
+ const denialReason = reason === undefined ? undefined : getOrElse(reason, () => "Denied by reviewer.");
70599
+ if (dryRun)
70600
+ return yield* json ? printJson({
70601
+ dryRun: true,
70602
+ action: `mailboxes.actions.${verb}`,
70603
+ id: mailbox,
70604
+ actionId,
70605
+ ...verb === "deny" ? { reason: denialReason } : {}
70606
+ }) : printJson({
70607
+ dryRun: true,
70608
+ action: verb,
70609
+ mailbox,
70610
+ actionId,
70611
+ ...verb === "deny" ? { reason: denialReason } : {}
70612
+ });
70613
+ yield* confirmDestructive({
70614
+ yes,
70615
+ json,
70616
+ message: `${verb === "approve" ? "Approve and execute" : "Deny"} mailbox action ${actionId}?`,
70617
+ nonInteractiveMessage: `Action ${verb} requires --yes in non-interactive mode. Preview with --dry-run.`
70618
+ });
70619
+ const client = yield* getClientProvider;
70620
+ const result = yield* (verb === "approve" ? approveAction({ id: mailbox, actionId }) : denyAction({
70621
+ id: mailbox,
70622
+ actionId,
70623
+ reason: denialReason ?? "Denied by reviewer."
70624
+ })).pipe(client.provide, mapError2((e) => mailboxApiError(`Could not ${verb} action`, e, { personOnly: verb })));
70625
+ yield* json ? printJson(result) : printAction(result);
69652
70626
  })));
70627
+ var remove18 = make29("remove", {
70628
+ id: String10("mailbox-id").pipe(withSchema3(MailboxId2)),
70629
+ dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
70630
+ yes: Boolean6("yes").pipe(withDefault5(false)),
70631
+ json: jsonFlag
70632
+ }).pipe(withDescription3("Permanently delete a mailbox with its addresses, threads, drafts, and history"), withExamples([
70633
+ { command: "samva mailboxes remove mbx_1234567890123456 --dry-run" },
70634
+ { command: "samva mailboxes remove mbx_1234567890123456 --yes" }
70635
+ ]), withHandler(({ id, dryRun, yes, json }) => gen2(function* () {
70636
+ if (dryRun)
70637
+ return yield* json ? printJson({ dryRun: true, action: "mailboxes.remove", id }) : log(`[dry-run] Would permanently remove mailbox ${id}.`);
70638
+ yield* confirmDestructive({
70639
+ yes,
70640
+ json,
70641
+ message: `Permanently remove mailbox ${id} with its threads, drafts, and history?`,
70642
+ nonInteractiveMessage: "Permanent mailbox deletion requires --yes in non-interactive mode. Preview with --dry-run."
70643
+ });
70644
+ const client = yield* getClientProvider;
70645
+ const result = yield* remove9({ id }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not remove mailbox", e)));
70646
+ if (json)
70647
+ return yield* printJson(result);
70648
+ yield* log(`Removed mailbox ${id}. The messages it received stay with the organization.`);
70649
+ }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
69653
70650
  var threads = make29("threads", {
69654
70651
  mailbox: mailboxFlag,
69655
70652
  ...pageFlags2,
@@ -69686,12 +70683,7 @@ var threads = make29("threads", {
69686
70683
  before: getOrUndefined(before)
69687
70684
  }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not list threads", e))),
69688
70685
  empty: "No threads found.",
69689
- human: (item) => printFields([
69690
- ["ID", item.id],
69691
- ["Subject", item.subject],
69692
- ["Messages", item.messageCount],
69693
- ["Read", item.read]
69694
- ])
70686
+ human: printThread
69695
70687
  });
69696
70688
  })));
69697
70689
  var read2 = make29("read", {
@@ -69705,18 +70697,7 @@ var read2 = make29("read", {
69705
70697
  const data = yield* getMessage({ id: mailbox, messageId }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not read message", e)));
69706
70698
  if (json)
69707
70699
  return yield* printJson(data);
69708
- yield* log("Notice: this body is untrusted email from outside the organization.");
69709
- yield* printFields([
69710
- ["ID", data.id],
69711
- ["From", data.from.address],
69712
- ["To", data.recipients.map((r) => r.address).join(", ")],
69713
- ["Reply-To", data.replyTo.join(", ")],
69714
- ["Subject", data.subject],
69715
- ["Message-ID", data.headers.messageId],
69716
- ["In-Reply-To", data.headers.inReplyTo],
69717
- ["References", data.headers.references.join(" ")]
69718
- ]);
69719
- yield* log(truncateForDisplay(data.replyText ?? data.text ?? "[No text body]"));
70700
+ yield* printMessage2(data);
69720
70701
  })));
69721
70702
  var send5 = make29("send", {
69722
70703
  mailbox: mailboxFlag,
@@ -69750,13 +70731,7 @@ var send5 = make29("send", {
69750
70731
  }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not send message", e)));
69751
70732
  if (json)
69752
70733
  return yield* printJson(data);
69753
- yield* printFields([
69754
- ["Status", data.status],
69755
- ["Message", data.messageId],
69756
- ["Thread", data.threadId],
69757
- ["Action", data.actionId],
69758
- ["Skipped", skippedRecipientsLine(data)]
69759
- ]);
70734
+ yield* printReceipt(data);
69760
70735
  })));
69761
70736
  var reply2 = make29("reply", {
69762
70737
  messageId: messageIdArgument,
@@ -69779,13 +70754,7 @@ var reply2 = make29("reply", {
69779
70754
  }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not reply", e)));
69780
70755
  if (json)
69781
70756
  return yield* printJson(data);
69782
- yield* printFields([
69783
- ["Status", data.status],
69784
- ["Message", data.messageId],
69785
- ["Thread", data.threadId],
69786
- ["Action", data.actionId],
69787
- ["Skipped", skippedRecipientsLine(data)]
69788
- ]);
70757
+ yield* printReceipt(data);
69789
70758
  })));
69790
70759
  var quarantineList = make29("list", {
69791
70760
  mailbox: mailboxFlag,
@@ -69810,13 +70779,7 @@ var quarantineList = make29("list", {
69810
70779
  before: getOrUndefined(before)
69811
70780
  }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not list quarantine", e))),
69812
70781
  empty: "No quarantined messages found.",
69813
- human: (item) => printFields([
69814
- ["Message", item.id],
69815
- ["From", item.from.address],
69816
- ["Subject", item.subject],
69817
- ["Disposition", item.disposition],
69818
- ["Reason", item.reason]
69819
- ])
70782
+ human: printHeldMessage
69820
70783
  });
69821
70784
  })));
69822
70785
  var release2 = make29("release", {
@@ -69832,13 +70795,11 @@ var release2 = make29("release", {
69832
70795
  const data = yield* releaseMessage({ id: mailbox, messageId }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not release message", e, { personOnly: "release" })));
69833
70796
  if (json)
69834
70797
  return yield* printJson(data);
69835
- yield* printFields([
69836
- ["Message", data.id],
69837
- ["Released", data.releasedAt],
69838
- ["Thread", data.threadId]
69839
- ]);
70798
+ yield* printHeldMessage(data);
69840
70799
  })));
69841
70800
  var discard = make29("discard", {
70801
+ dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
70802
+ yes: Boolean6("yes").pipe(withDefault5(false)),
69842
70803
  messageId: messageIdArgument,
69843
70804
  mailbox: mailboxFlag,
69844
70805
  json: jsonFlag
@@ -69846,20 +70807,36 @@ var discard = make29("discard", {
69846
70807
  {
69847
70808
  command: "samva mailboxes quarantine discard msg_1234567890123456 --mailbox mbx_1234567890123456"
69848
70809
  }
69849
- ]), withHandler(({ messageId, mailbox, json }) => gen2(function* () {
70810
+ ]), withHandler(({ messageId, mailbox, dryRun, yes, json }) => gen2(function* () {
70811
+ if (dryRun)
70812
+ return yield* json ? printJson({
70813
+ dryRun: true,
70814
+ action: "mailboxes.quarantine.discard",
70815
+ id: mailbox,
70816
+ messageId
70817
+ }) : log(`[dry-run] Would permanently discard held message ${messageId}.`);
70818
+ yield* confirmDestructive({
70819
+ yes,
70820
+ json,
70821
+ message: `Permanently discard held message ${messageId}?`,
70822
+ nonInteractiveMessage: "Discarding held mail requires --yes in non-interactive mode. Preview with --dry-run."
70823
+ });
69850
70824
  const client = yield* getClientProvider;
69851
70825
  const data = yield* discardMessage({ id: mailbox, messageId }).pipe(client.provide, mapError2((e) => mailboxApiError("Could not discard message", e, { personOnly: "discard" })));
69852
70826
  if (json)
69853
70827
  return yield* printJson(data);
69854
- yield* printFields([
69855
- ["Message", data.id],
69856
- ["Discarded", data.discardedAt]
69857
- ]);
70828
+ yield* printHeldMessage(data);
69858
70829
  })));
69859
70830
  var mailboxesCommand = make29("mailboxes").pipe(withDescription3("Mailbox reading and governed sending"), withSubcommands([
69860
70831
  mailboxesEventsCommand,
69861
70832
  list25,
69862
70833
  create17,
70834
+ get23,
70835
+ update16,
70836
+ lifecycle("pause"),
70837
+ lifecycle("resume"),
70838
+ make29("actions").pipe(withSubcommands([actionsList, actionDecision("approve"), actionDecision("deny")])),
70839
+ remove18,
69863
70840
  threads,
69864
70841
  read2,
69865
70842
  send5,
@@ -70054,7 +71031,7 @@ var use2 = make29("use", { name: String10("name") }).pipe(withDescription3("Sele
70054
71031
  yield* writeConfig({ ...config, activeProfile: name });
70055
71032
  yield* printResult({ action: "profile.use", name }, `Active profile set to ${name}.`);
70056
71033
  })));
70057
- var remove18 = make29("delete", {
71034
+ var remove19 = make29("delete", {
70058
71035
  name: String10("name"),
70059
71036
  yes: Boolean6("yes").pipe(withDefault5(false))
70060
71037
  }).pipe(withDescription3("Delete a profile and its OS-keyring credential"), withHandler(fnUntraced2(function* ({ name, yes }) {
@@ -70079,7 +71056,7 @@ var remove18 = make29("delete", {
70079
71056
  yield* (yield* Service5).clear(name);
70080
71057
  yield* printResult({ action: "profile.delete", name }, `Deleted profile ${name}.`);
70081
71058
  })));
70082
- var profileCommand = make29("profile").pipe(withDescription3("Manage user-level credential identity and organization contexts"), withSubcommands([list27, show, create18, use2, remove18]));
71059
+ var profileCommand = make29("profile").pipe(withDescription3("Manage user-level credential identity and organization contexts"), withSubcommands([list27, show, create18, use2, remove19]));
70083
71060
 
70084
71061
  // src/commands/scheduled.ts
70085
71062
  var SCHEDULED_STATUSES = [
@@ -70359,7 +71336,7 @@ var list28 = make29("list", {
70359
71336
  if (data.nextCursor !== null)
70360
71337
  yield* printFields([["Next cursor", data.nextCursor]]);
70361
71338
  }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
70362
- var get23 = make29("get", { id: String10("id"), json: jsonFlag }).pipe(withDescription3("Show a scheduled message by id"), withExamples([{ command: "samva scheduled-messages get sched_abc123" }]), withHandler(({ id, json }) => gen2(function* () {
71339
+ var get24 = make29("get", { id: String10("id"), json: jsonFlag }).pipe(withDescription3("Show a scheduled message by id"), withExamples([{ command: "samva scheduled-messages get sched_abc123" }]), withHandler(({ id, json }) => gen2(function* () {
70363
71340
  const client = yield* getClientProvider;
70364
71341
  const data = yield* get18({ id }).pipe(client.provide, mapError2((error) => toCliApiError("Could not fetch scheduled message", error)));
70365
71342
  if (json)
@@ -70442,11 +71419,11 @@ var scheduledMessagesCommand = make29("scheduled-messages").pipe(withDescription
70442
71419
  description: "Schedule an email"
70443
71420
  },
70444
71421
  { command: "samva scheduled-messages list", description: "List scheduled messages" }
70445
- ]), withSubcommands([create19, list28, get23, cancel2, resume3]));
71422
+ ]), withSubcommands([create19, list28, get24, cancel2, resume3]));
70446
71423
 
70447
71424
  // src/commands/templates.ts
70448
71425
  import { constants as constants2 } from "fs";
70449
- import { access as access3, stat as stat4 } from "fs/promises";
71426
+ import { access as access3, stat as stat5 } from "fs/promises";
70450
71427
  import { dirname as dirname5, resolve as resolve16 } from "path";
70451
71428
  import { pathToFileURL as pathToFileURL5 } from "url";
70452
71429
 
@@ -71736,7 +72713,7 @@ import { resolve as resolve13 } from "path";
71736
72713
 
71737
72714
  // src/commands/templates/snapshot-browser.ts
71738
72715
  import { existsSync } from "fs";
71739
- import { copyFile as copyFile3, mkdir as mkdir4, mkdtemp as mkdtemp2, readFile as readFile4, rm as rm2, stat as stat3, writeFile as writeFile5 } from "fs/promises";
72716
+ import { copyFile as copyFile3, mkdir as mkdir4, mkdtemp as mkdtemp2, readFile as readFile5, rm as rm2, stat as stat4, writeFile as writeFile5 } from "fs/promises";
71740
72717
  import { tmpdir as tmpdir2 } from "os";
71741
72718
  import { join as join4 } from "path";
71742
72719
  import { pathToFileURL as pathToFileURL4 } from "url";
@@ -71850,7 +72827,7 @@ var runProcess = async (command, args, until) => {
71850
72827
  stderr += text;
71851
72828
  });
71852
72829
  const deadline = Date.now() + RUN_TIMEOUT_MS;
71853
- const produced = async () => until.stdoutIncludes !== undefined && stdout.includes(until.stdoutIncludes) || until.file !== undefined && existsSync(until.file) && (await stat3(until.file)).size > 0;
72830
+ const produced = async () => until.stdoutIncludes !== undefined && stdout.includes(until.stdoutIncludes) || until.file !== undefined && existsSync(until.file) && (await stat4(until.file)).size > 0;
71854
72831
  const state = { exited: false };
71855
72832
  child.exited.then(() => {
71856
72833
  state.exited = true;
@@ -71876,7 +72853,7 @@ var chromeLauncher = (binary, run = runProcess) => ({
71876
72853
  const profile = await mkdtemp2(join4(tmpdir2(), "samva-chrome-"));
71877
72854
  try {
71878
72855
  for (const request of requests) {
71879
- const source = await readFile4(request.htmlPath, "utf8");
72856
+ const source = await readFile5(request.htmlPath, "utf8");
71880
72857
  const measured = request.htmlPath.replace(/\.html$/, `.${request.viewport}.${request.scheme}.html`);
71881
72858
  await writeFile5(measured, withMeasurement(source));
71882
72859
  const measure = await run(binary, chromeMeasureArgs({
@@ -72594,7 +73571,7 @@ var typesCommand = make29("types", {
72594
73571
  })));
72595
73572
 
72596
73573
  // src/commands/templates/workspace.ts
72597
- import { basename, resolve as resolve15 } from "path";
73574
+ import { basename as basename2, resolve as resolve15 } from "path";
72598
73575
  var templateIdArgument = String10("template-id").pipe(withDescription4("Template whose project workspace to act on"));
72599
73576
  var revisionFlag = String9("revision").pipe(withDescription2("Workspace revision this call is fenced to; a workspace that moved refuses the call"));
72600
73577
  var idempotencyKeyFlag4 = String9("idempotency-key").pipe(withDescription2("Key so an identical retry returns the original result rather than repeating it"));
@@ -72687,7 +73664,7 @@ var addAsset = make29("add-asset", {
72687
73664
  const view = yield* putWorkspaceAsset({
72688
73665
  id,
72689
73666
  expectedRevision: revision,
72690
- path: getOrElse(path, () => `assets/${basename(source)}`),
73667
+ path: getOrElse(path, () => `assets/${basename2(source)}`),
72691
73668
  contentBase64: Buffer.from(bytes).toString("base64"),
72692
73669
  replace,
72693
73670
  idempotencyKey
@@ -72860,7 +73837,7 @@ var typecheckProject = (tsconfig) => tryPromise2({
72860
73837
  });
72861
73838
  var validateTemplatesDir = (dir) => tryPromise2({
72862
73839
  try: async () => {
72863
- const info = await stat4(dir);
73840
+ const info = await stat5(dir);
72864
73841
  if (!info.isDirectory()) {
72865
73842
  return Promise.reject(new SamvaCliError({ message: `${dir} is not a directory.` }));
72866
73843
  }
@@ -73448,7 +74425,7 @@ var list29 = make29("list", {
73448
74425
  if (data.nextCursor !== null)
73449
74426
  yield* printFields([["Next cursor", data.nextCursor]]);
73450
74427
  }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
73451
- var get24 = make29("get", { id: idArgument, json: jsonFlag }).pipe(withDescription3("Get a customer webhook"), withExamples([{ command: "samva webhooks get wep_abc123 --json" }]), withHandler(({ id, json }) => gen2(function* () {
74428
+ var get25 = make29("get", { id: idArgument, json: jsonFlag }).pipe(withDescription3("Get a customer webhook"), withExamples([{ command: "samva webhooks get wep_abc123 --json" }]), withHandler(({ id, json }) => gen2(function* () {
73452
74429
  const client = yield* getClientProvider;
73453
74430
  const data = yield* get19({ id }).pipe(client.provide, mapError2((error) => toCliApiError("Could not get webhook", error)));
73454
74431
  if (json)
@@ -73572,12 +74549,12 @@ var rotate2 = make29("rotate-secret", {
73572
74549
  yield* log(secret);
73573
74550
  }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
73574
74551
  var create20 = make29("create", {
73575
- data: String9("data").pipe(withDescription2("Webhook JSON: name, url, events, and optional retry settings")),
74552
+ data: String9("data").pipe(withDescription2("Webhook JSON: name, url, eventTypes, and optional retry settings")),
73576
74553
  dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
73577
74554
  json: jsonFlag
73578
74555
  }).pipe(withDescription3("Create a customer webhook from JSON"), withExamples([
73579
74556
  {
73580
- command: `samva webhooks create --data '{"name":"delivery","url":"https://example.com/hook","events":["message.delivered"]}' --dry-run`
74557
+ command: `samva webhooks create --data '{"name":"delivery","url":"https://example.com/hook","eventTypes":["message.delivered"]}' --dry-run`
73581
74558
  }
73582
74559
  ]), withHandler(({ data, dryRun, json }) => gen2(function* () {
73583
74560
  const payload = yield* decodePayload2(data, "--data", CreateWebhookPayload);
@@ -73589,7 +74566,7 @@ var create20 = make29("create", {
73589
74566
  return yield* printJson(result);
73590
74567
  yield* printJson(result);
73591
74568
  }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
73592
- var update16 = make29("update", {
74569
+ var update17 = make29("update", {
73593
74570
  id: idArgument,
73594
74571
  data: String9("data").pipe(withDescription2("JSON object of webhook fields to update")),
73595
74572
  dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
@@ -73608,7 +74585,7 @@ var update16 = make29("update", {
73608
74585
  return yield* printJson(result);
73609
74586
  yield* printJson(result);
73610
74587
  }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
73611
- var remove19 = make29("remove", {
74588
+ var remove20 = make29("remove", {
73612
74589
  id: idArgument,
73613
74590
  dryRun: Boolean6("dry-run").pipe(withDefault5(false)),
73614
74591
  yes: Boolean6("yes").pipe(withDefault5(false)),
@@ -73631,7 +74608,7 @@ var remove19 = make29("remove", {
73631
74608
  return yield* printJson(result);
73632
74609
  yield* log(`Removed webhook ${id}.`);
73633
74610
  }).pipe(json ? provideService2(MinimumLogLevel2, "None") : identity)));
73634
- var webhooksCommand = make29("webhooks").pipe(withDescription3("Inspect, test, and recover customer webhooks"), withExamples([{ command: "samva webhooks list --json" }]), withSubcommands([list29, get24, create20, update16, test2, logs, stats, retry5, rotate2, remove19]));
74611
+ var webhooksCommand = make29("webhooks").pipe(withDescription3("Inspect, test, and recover customer webhooks"), withExamples([{ command: "samva webhooks list --json" }]), withSubcommands([list29, get25, create20, update17, test2, logs, stats, retry5, rotate2, remove20]));
73635
74612
 
73636
74613
  // src/lib/root-commands.ts
73637
74614
  var rootCommands = [