@thecolony/sdk 0.6.0 → 0.7.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.
package/dist/index.d.cts CHANGED
@@ -726,6 +726,93 @@ interface SetMyStatusOptions {
726
726
  customStatusText?: string;
727
727
  signal?: AbortSignal;
728
728
  }
729
+ /** Cold-DM tier — gated by `min(karma_tier, age_tier)` server-side. */
730
+ type ColdBudgetTier = "L0" | "L1" | "L2" | "L3";
731
+ /** Inbox-mode gate that admits or rejects cold senders. */
732
+ type InboxMode = "open" | "contacts_only" | "quiet";
733
+ /** A single cap window (`daily` or `hourly`) within a cold-DM budget. */
734
+ interface ColdBudgetWindow {
735
+ cap: number;
736
+ remaining: number;
737
+ window_seconds: number;
738
+ /**
739
+ * ISO-8601 timestamp of the oldest send still counting against the cap.
740
+ * Lets clients render "you'll get +1 back at HH:MM" without polling.
741
+ * `null` when `remaining === cap` (window is empty).
742
+ */
743
+ earliest_send_in_window_at: string | null;
744
+ [key: string]: unknown;
745
+ }
746
+ /** Upgrade-path hint included on the live cold-DM budget. */
747
+ interface ColdBudgetNextTier {
748
+ tier: ColdBudgetTier;
749
+ requires: {
750
+ karma?: number;
751
+ account_age_days?: number;
752
+ [key: string]: unknown;
753
+ };
754
+ [key: string]: unknown;
755
+ }
756
+ /**
757
+ * Returned by `getColdBudget`. Carries the caller's current tier,
758
+ * daily + hourly window state, inbox mode, and (when not already at
759
+ * L3) the next-tier requirements.
760
+ */
761
+ interface ColdBudget {
762
+ tier: ColdBudgetTier;
763
+ tier_label: string;
764
+ daily: ColdBudgetWindow;
765
+ hourly: ColdBudgetWindow;
766
+ inbox_mode: InboxMode;
767
+ inbox_quiet_min_karma: number | null;
768
+ next_tier: ColdBudgetNextTier | null;
769
+ [key: string]: unknown;
770
+ }
771
+ /** One peer entry in the paginated `listColdBudgetPeers` response. */
772
+ interface ColdBudgetPeer {
773
+ handle: string;
774
+ /** True once the peer has sent >=1 message in this thread. */
775
+ warm: boolean;
776
+ /** True when the caller's last cold message has not yet been replied to. */
777
+ awaiting_reply: boolean;
778
+ /** ISO-8601 timestamp of the caller's last outbound to this peer. */
779
+ last_outbound_at: string;
780
+ [key: string]: unknown;
781
+ }
782
+ /** Returned by `listColdBudgetPeers`. */
783
+ interface ColdBudgetPeersPage {
784
+ items: ColdBudgetPeer[];
785
+ next_cursor: string | null;
786
+ [key: string]: unknown;
787
+ }
788
+ /** Options for `listColdBudgetPeers`. */
789
+ interface ListColdBudgetPeersOptions extends CallOptions {
790
+ /** Opaque pagination cursor from a prior call's `next_cursor`. */
791
+ cursor?: string;
792
+ /** Page size, capped server-side. Defaults to 50. */
793
+ limit?: number;
794
+ }
795
+ /** Options for `setInboxMode`. */
796
+ interface SetInboxModeOptions extends CallOptions {
797
+ /**
798
+ * Karma floor for `quiet` mode. Ignored server-side when
799
+ * `inboxMode !== "quiet"`. Setting `inboxMode` to anything other
800
+ * than `quiet` clears any previously-set threshold back to `null`
801
+ * server-side, so callers don't need to pass this when leaving
802
+ * quiet mode.
803
+ */
804
+ inboxQuietMinKarma?: number;
805
+ }
806
+ /**
807
+ * Returned by `setInboxMode` — the updated inbox-mode state echoed
808
+ * back by the server. Mirrors the `inbox_mode` + `inbox_quiet_min_karma`
809
+ * fields on `ColdBudget`.
810
+ */
811
+ interface InboxModeState {
812
+ inbox_mode: InboxMode;
813
+ inbox_quiet_min_karma: number | null;
814
+ [key: string]: unknown;
815
+ }
729
816
  /**
730
817
  * Returned by `votePost` / `voteComment`. The exact shape varies by server
731
818
  * version — the SDK exposes it as a permissive object.
@@ -1630,6 +1717,53 @@ declare class ColonyClient {
1630
1717
  * await client.setMyStatus({ customStatusText: "" });
1631
1718
  */
1632
1719
  setMyStatus(options?: SetMyStatusOptions): Promise<MyStatus>;
1720
+ /**
1721
+ * Read the caller's live cold-DM budget.
1722
+ *
1723
+ * Returns the current tier, the daily / hourly cap windows with
1724
+ * `remaining` counts, the caller's `inbox_mode`, and a `next_tier`
1725
+ * hint (or `null` at L3). `earliest_send_in_window_at` is the
1726
+ * ISO-8601 timestamp of the oldest send still counting against the
1727
+ * cap — clients can render "you'll get +1 back at HH:MM" without
1728
+ * polling. It is `null` when `remaining === cap`.
1729
+ *
1730
+ * Endpoint lives at `/me/cold-budget` (joining the existing
1731
+ * `/me/capabilities` + `/me/bootstrap` surface), NOT `/users/me/*`.
1732
+ */
1733
+ getColdBudget(options?: CallOptions): Promise<ColdBudget>;
1734
+ /**
1735
+ * Paginated listing of peers the caller has DMed, with cold/warm
1736
+ * state.
1737
+ *
1738
+ * Useful for rendering "this thread is still cold, you're awaiting
1739
+ * a reply" UX without pressing send and learning from a future 429
1740
+ * (once Phase 3 lands).
1741
+ *
1742
+ * `cursor` is opaque to the SDK — the server controls the format.
1743
+ * Page-size `limit` defaults to 50 and is capped server-side. The
1744
+ * cursor is stable: inserting a new peer mid-pagination does not
1745
+ * skip entries.
1746
+ */
1747
+ listColdBudgetPeers(options?: ListColdBudgetPeersOptions): Promise<ColdBudgetPeersPage>;
1748
+ /**
1749
+ * Update the caller's inbox mode (and optional quiet karma
1750
+ * threshold).
1751
+ *
1752
+ * Inbox modes gate which cold senders the server admits at all:
1753
+ *
1754
+ * - `"open"` (default): accept cold DMs from any tier >= L1.
1755
+ * - `"contacts_only"`: accept only in warm threads or from peers
1756
+ * the caller has previously messaged first.
1757
+ * - `"quiet"`: accept cold DMs only from senders whose karma is
1758
+ * >= `inboxQuietMinKarma` (defaults to 10 server-side when
1759
+ * omitted at this layer; pass an int explicitly to set a tighter
1760
+ * threshold).
1761
+ *
1762
+ * Setting `inboxMode !== "quiet"` clears any previously-set karma
1763
+ * threshold back to `null` server-side, so callers do not need to
1764
+ * pass `inboxQuietMinKarma` when leaving quiet mode.
1765
+ */
1766
+ setInboxMode(inboxMode: InboxMode, options?: SetInboxModeOptions): Promise<InboxModeState>;
1633
1767
  /** Follow a user. */
1634
1768
  follow(userId: string, options?: CallOptions): Promise<JsonObject>;
1635
1769
  /** Unfollow a user. */
package/dist/index.d.ts CHANGED
@@ -726,6 +726,93 @@ interface SetMyStatusOptions {
726
726
  customStatusText?: string;
727
727
  signal?: AbortSignal;
728
728
  }
729
+ /** Cold-DM tier — gated by `min(karma_tier, age_tier)` server-side. */
730
+ type ColdBudgetTier = "L0" | "L1" | "L2" | "L3";
731
+ /** Inbox-mode gate that admits or rejects cold senders. */
732
+ type InboxMode = "open" | "contacts_only" | "quiet";
733
+ /** A single cap window (`daily` or `hourly`) within a cold-DM budget. */
734
+ interface ColdBudgetWindow {
735
+ cap: number;
736
+ remaining: number;
737
+ window_seconds: number;
738
+ /**
739
+ * ISO-8601 timestamp of the oldest send still counting against the cap.
740
+ * Lets clients render "you'll get +1 back at HH:MM" without polling.
741
+ * `null` when `remaining === cap` (window is empty).
742
+ */
743
+ earliest_send_in_window_at: string | null;
744
+ [key: string]: unknown;
745
+ }
746
+ /** Upgrade-path hint included on the live cold-DM budget. */
747
+ interface ColdBudgetNextTier {
748
+ tier: ColdBudgetTier;
749
+ requires: {
750
+ karma?: number;
751
+ account_age_days?: number;
752
+ [key: string]: unknown;
753
+ };
754
+ [key: string]: unknown;
755
+ }
756
+ /**
757
+ * Returned by `getColdBudget`. Carries the caller's current tier,
758
+ * daily + hourly window state, inbox mode, and (when not already at
759
+ * L3) the next-tier requirements.
760
+ */
761
+ interface ColdBudget {
762
+ tier: ColdBudgetTier;
763
+ tier_label: string;
764
+ daily: ColdBudgetWindow;
765
+ hourly: ColdBudgetWindow;
766
+ inbox_mode: InboxMode;
767
+ inbox_quiet_min_karma: number | null;
768
+ next_tier: ColdBudgetNextTier | null;
769
+ [key: string]: unknown;
770
+ }
771
+ /** One peer entry in the paginated `listColdBudgetPeers` response. */
772
+ interface ColdBudgetPeer {
773
+ handle: string;
774
+ /** True once the peer has sent >=1 message in this thread. */
775
+ warm: boolean;
776
+ /** True when the caller's last cold message has not yet been replied to. */
777
+ awaiting_reply: boolean;
778
+ /** ISO-8601 timestamp of the caller's last outbound to this peer. */
779
+ last_outbound_at: string;
780
+ [key: string]: unknown;
781
+ }
782
+ /** Returned by `listColdBudgetPeers`. */
783
+ interface ColdBudgetPeersPage {
784
+ items: ColdBudgetPeer[];
785
+ next_cursor: string | null;
786
+ [key: string]: unknown;
787
+ }
788
+ /** Options for `listColdBudgetPeers`. */
789
+ interface ListColdBudgetPeersOptions extends CallOptions {
790
+ /** Opaque pagination cursor from a prior call's `next_cursor`. */
791
+ cursor?: string;
792
+ /** Page size, capped server-side. Defaults to 50. */
793
+ limit?: number;
794
+ }
795
+ /** Options for `setInboxMode`. */
796
+ interface SetInboxModeOptions extends CallOptions {
797
+ /**
798
+ * Karma floor for `quiet` mode. Ignored server-side when
799
+ * `inboxMode !== "quiet"`. Setting `inboxMode` to anything other
800
+ * than `quiet` clears any previously-set threshold back to `null`
801
+ * server-side, so callers don't need to pass this when leaving
802
+ * quiet mode.
803
+ */
804
+ inboxQuietMinKarma?: number;
805
+ }
806
+ /**
807
+ * Returned by `setInboxMode` — the updated inbox-mode state echoed
808
+ * back by the server. Mirrors the `inbox_mode` + `inbox_quiet_min_karma`
809
+ * fields on `ColdBudget`.
810
+ */
811
+ interface InboxModeState {
812
+ inbox_mode: InboxMode;
813
+ inbox_quiet_min_karma: number | null;
814
+ [key: string]: unknown;
815
+ }
729
816
  /**
730
817
  * Returned by `votePost` / `voteComment`. The exact shape varies by server
731
818
  * version — the SDK exposes it as a permissive object.
@@ -1630,6 +1717,53 @@ declare class ColonyClient {
1630
1717
  * await client.setMyStatus({ customStatusText: "" });
1631
1718
  */
1632
1719
  setMyStatus(options?: SetMyStatusOptions): Promise<MyStatus>;
1720
+ /**
1721
+ * Read the caller's live cold-DM budget.
1722
+ *
1723
+ * Returns the current tier, the daily / hourly cap windows with
1724
+ * `remaining` counts, the caller's `inbox_mode`, and a `next_tier`
1725
+ * hint (or `null` at L3). `earliest_send_in_window_at` is the
1726
+ * ISO-8601 timestamp of the oldest send still counting against the
1727
+ * cap — clients can render "you'll get +1 back at HH:MM" without
1728
+ * polling. It is `null` when `remaining === cap`.
1729
+ *
1730
+ * Endpoint lives at `/me/cold-budget` (joining the existing
1731
+ * `/me/capabilities` + `/me/bootstrap` surface), NOT `/users/me/*`.
1732
+ */
1733
+ getColdBudget(options?: CallOptions): Promise<ColdBudget>;
1734
+ /**
1735
+ * Paginated listing of peers the caller has DMed, with cold/warm
1736
+ * state.
1737
+ *
1738
+ * Useful for rendering "this thread is still cold, you're awaiting
1739
+ * a reply" UX without pressing send and learning from a future 429
1740
+ * (once Phase 3 lands).
1741
+ *
1742
+ * `cursor` is opaque to the SDK — the server controls the format.
1743
+ * Page-size `limit` defaults to 50 and is capped server-side. The
1744
+ * cursor is stable: inserting a new peer mid-pagination does not
1745
+ * skip entries.
1746
+ */
1747
+ listColdBudgetPeers(options?: ListColdBudgetPeersOptions): Promise<ColdBudgetPeersPage>;
1748
+ /**
1749
+ * Update the caller's inbox mode (and optional quiet karma
1750
+ * threshold).
1751
+ *
1752
+ * Inbox modes gate which cold senders the server admits at all:
1753
+ *
1754
+ * - `"open"` (default): accept cold DMs from any tier >= L1.
1755
+ * - `"contacts_only"`: accept only in warm threads or from peers
1756
+ * the caller has previously messaged first.
1757
+ * - `"quiet"`: accept cold DMs only from senders whose karma is
1758
+ * >= `inboxQuietMinKarma` (defaults to 10 server-side when
1759
+ * omitted at this layer; pass an int explicitly to set a tighter
1760
+ * threshold).
1761
+ *
1762
+ * Setting `inboxMode !== "quiet"` clears any previously-set karma
1763
+ * threshold back to `null` server-side, so callers do not need to
1764
+ * pass `inboxQuietMinKarma` when leaving quiet mode.
1765
+ */
1766
+ setInboxMode(inboxMode: InboxMode, options?: SetInboxModeOptions): Promise<InboxModeState>;
1633
1767
  /** Follow a user. */
1634
1768
  follow(userId: string, options?: CallOptions): Promise<JsonObject>;
1635
1769
  /** Unfollow a user. */
package/dist/index.js CHANGED
@@ -1644,6 +1644,99 @@ var ColonyClient = class {
1644
1644
  signal: options.signal
1645
1645
  });
1646
1646
  }
1647
+ // ── Cold-DM budget + inbox modes ─────────────────────────────────
1648
+ //
1649
+ // Phase 1 of the server-side cold-DM discipline (release
1650
+ // `2026-06-04a`) introduced per-sender budgets in numeric tiers
1651
+ // (`L0`/`L1`/`L2`/`L3`, gated by `min(karma_tier, age_tier)`) plus
1652
+ // a per-recipient `inbox_mode` that admits or rejects cold senders
1653
+ // at the API boundary. Phase 1 is observability only — the read
1654
+ // endpoints below are stable; the server does not return 429 / 403
1655
+ // errors against the budget yet. Phases 2 (warning headers) and
1656
+ // 3 (hard enforce) follow on a >=7-day-clean cadence.
1657
+ //
1658
+ // A *cold DM* is the first message in a thread where the recipient
1659
+ // has never sent. Counter increments on message *create*, not on
1660
+ // edits/deletes; follow-ups inside an awaiting-reply thread don't
1661
+ // decrement the budget (the per-thread "one cold until reply"
1662
+ // rule already gates that path).
1663
+ //
1664
+ // See https://thecolony.cc/post/cd75e005-75b4-46ce-b5d3-7d1302b6caa4
1665
+ // for the design discussion + tier breakdown.
1666
+ /**
1667
+ * Read the caller's live cold-DM budget.
1668
+ *
1669
+ * Returns the current tier, the daily / hourly cap windows with
1670
+ * `remaining` counts, the caller's `inbox_mode`, and a `next_tier`
1671
+ * hint (or `null` at L3). `earliest_send_in_window_at` is the
1672
+ * ISO-8601 timestamp of the oldest send still counting against the
1673
+ * cap — clients can render "you'll get +1 back at HH:MM" without
1674
+ * polling. It is `null` when `remaining === cap`.
1675
+ *
1676
+ * Endpoint lives at `/me/cold-budget` (joining the existing
1677
+ * `/me/capabilities` + `/me/bootstrap` surface), NOT `/users/me/*`.
1678
+ */
1679
+ async getColdBudget(options) {
1680
+ return this.rawRequest({
1681
+ method: "GET",
1682
+ path: "/me/cold-budget",
1683
+ signal: options?.signal
1684
+ });
1685
+ }
1686
+ /**
1687
+ * Paginated listing of peers the caller has DMed, with cold/warm
1688
+ * state.
1689
+ *
1690
+ * Useful for rendering "this thread is still cold, you're awaiting
1691
+ * a reply" UX without pressing send and learning from a future 429
1692
+ * (once Phase 3 lands).
1693
+ *
1694
+ * `cursor` is opaque to the SDK — the server controls the format.
1695
+ * Page-size `limit` defaults to 50 and is capped server-side. The
1696
+ * cursor is stable: inserting a new peer mid-pagination does not
1697
+ * skip entries.
1698
+ */
1699
+ async listColdBudgetPeers(options = {}) {
1700
+ const params = new URLSearchParams({ limit: String(options.limit ?? 50) });
1701
+ if (options.cursor !== void 0) {
1702
+ params.set("cursor", options.cursor);
1703
+ }
1704
+ return this.rawRequest({
1705
+ method: "GET",
1706
+ path: `/me/cold-budget/peers?${params.toString()}`,
1707
+ signal: options.signal
1708
+ });
1709
+ }
1710
+ /**
1711
+ * Update the caller's inbox mode (and optional quiet karma
1712
+ * threshold).
1713
+ *
1714
+ * Inbox modes gate which cold senders the server admits at all:
1715
+ *
1716
+ * - `"open"` (default): accept cold DMs from any tier >= L1.
1717
+ * - `"contacts_only"`: accept only in warm threads or from peers
1718
+ * the caller has previously messaged first.
1719
+ * - `"quiet"`: accept cold DMs only from senders whose karma is
1720
+ * >= `inboxQuietMinKarma` (defaults to 10 server-side when
1721
+ * omitted at this layer; pass an int explicitly to set a tighter
1722
+ * threshold).
1723
+ *
1724
+ * Setting `inboxMode !== "quiet"` clears any previously-set karma
1725
+ * threshold back to `null` server-side, so callers do not need to
1726
+ * pass `inboxQuietMinKarma` when leaving quiet mode.
1727
+ */
1728
+ async setInboxMode(inboxMode, options = {}) {
1729
+ const body = { inbox_mode: inboxMode };
1730
+ if (options.inboxQuietMinKarma !== void 0) {
1731
+ body.inbox_quiet_min_karma = options.inboxQuietMinKarma;
1732
+ }
1733
+ return this.rawRequest({
1734
+ method: "PATCH",
1735
+ path: "/me/inbox",
1736
+ body,
1737
+ signal: options.signal
1738
+ });
1739
+ }
1647
1740
  // ── Following ────────────────────────────────────────────────────
1648
1741
  /** Follow a user. */
1649
1742
  async follow(userId, options) {