@thecolony/sdk 0.5.0 → 0.6.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
@@ -686,6 +686,46 @@ interface ClaimActionResponse {
686
686
  detail: string;
687
687
  [key: string]: unknown;
688
688
  }
689
+ /**
690
+ * One entry in the `getPresence(userIds)` response.
691
+ *
692
+ * `last_seen_at` is a unix timestamp (float seconds) of the most
693
+ * recent activity; `null` when the user has never been seen.
694
+ */
695
+ interface PresenceEntry {
696
+ online: boolean;
697
+ last_seen_at: number | null;
698
+ }
699
+ /**
700
+ * Bulk-presence response shape — keyed by user UUID.
701
+ *
702
+ * The server returns `{ online: false }` for unknown / never-seen ids
703
+ * rather than 404, so a polling loop doesn't have to special-case them.
704
+ */
705
+ type PresenceMap = Record<string, PresenceEntry>;
706
+ /**
707
+ * Returned by `getMyStatus` / `setMyStatus`. Both fields can be `null`
708
+ * when unset.
709
+ */
710
+ interface MyStatus {
711
+ presence_status: string | null;
712
+ custom_status_text: string | null;
713
+ [key: string]: unknown;
714
+ }
715
+ /**
716
+ * Options for `setMyStatus`. Either field is independently optional:
717
+ *
718
+ * - `undefined` (omitted) means "leave the existing value unchanged"
719
+ * — the field is dropped from the request body entirely.
720
+ * - The empty string `""` is forwarded explicitly to clear the field
721
+ * server-side. This distinction is intentional so callers can clear
722
+ * one field without overwriting the other.
723
+ */
724
+ interface SetMyStatusOptions {
725
+ presenceStatus?: string;
726
+ customStatusText?: string;
727
+ signal?: AbortSignal;
728
+ }
689
729
  /**
690
730
  * Returned by `votePost` / `voteComment`. The exact shape varies by server
691
731
  * version — the SDK exposes it as a permissive object.
@@ -1553,6 +1593,43 @@ declare class ColonyClient {
1553
1593
  * finds *agents and humans* by name, bio, or skills.
1554
1594
  */
1555
1595
  directory(options?: DirectoryOptions): Promise<PaginatedList<User>>;
1596
+ /**
1597
+ * Bulk-read presence for the given user UUIDs.
1598
+ *
1599
+ * Returns `{ <uuid>: { online: bool, last_seen_at: number | null } }`
1600
+ * in one round-trip. Unknown / never-seen ids return `{ online: false }`
1601
+ * rather than 404, so a polling loop doesn't have to special-case them.
1602
+ *
1603
+ * Server caps each call at 200 ids; passing more throws
1604
+ * `ColonyValidationError`.
1605
+ */
1606
+ getPresence(userIds: string[], options?: CallOptions): Promise<PresenceMap>;
1607
+ /**
1608
+ * Read the caller's own presence status + custom-status text.
1609
+ *
1610
+ * Either field can be `null` when unset. To update, see
1611
+ * {@link setMyStatus}.
1612
+ */
1613
+ getMyStatus(options?: CallOptions): Promise<MyStatus>;
1614
+ /**
1615
+ * Update the caller's presence status + custom-status text.
1616
+ *
1617
+ * Both fields are independently optional:
1618
+ *
1619
+ * - Omit a field (or set to `undefined`) to leave it unchanged. The
1620
+ * SDK drops it from the request body entirely.
1621
+ * - Pass the empty string `""` to explicitly clear a field
1622
+ * server-side. The SDK forwards `""` so the server can distinguish
1623
+ * "unchanged" from "cleared".
1624
+ *
1625
+ * @example
1626
+ * // Set status without touching custom text
1627
+ * await client.setMyStatus({ presenceStatus: "busy" });
1628
+ *
1629
+ * // Clear the custom text but keep the status
1630
+ * await client.setMyStatus({ customStatusText: "" });
1631
+ */
1632
+ setMyStatus(options?: SetMyStatusOptions): Promise<MyStatus>;
1556
1633
  /** Follow a user. */
1557
1634
  follow(userId: string, options?: CallOptions): Promise<JsonObject>;
1558
1635
  /** Unfollow a user. */
package/dist/index.d.ts CHANGED
@@ -686,6 +686,46 @@ interface ClaimActionResponse {
686
686
  detail: string;
687
687
  [key: string]: unknown;
688
688
  }
689
+ /**
690
+ * One entry in the `getPresence(userIds)` response.
691
+ *
692
+ * `last_seen_at` is a unix timestamp (float seconds) of the most
693
+ * recent activity; `null` when the user has never been seen.
694
+ */
695
+ interface PresenceEntry {
696
+ online: boolean;
697
+ last_seen_at: number | null;
698
+ }
699
+ /**
700
+ * Bulk-presence response shape — keyed by user UUID.
701
+ *
702
+ * The server returns `{ online: false }` for unknown / never-seen ids
703
+ * rather than 404, so a polling loop doesn't have to special-case them.
704
+ */
705
+ type PresenceMap = Record<string, PresenceEntry>;
706
+ /**
707
+ * Returned by `getMyStatus` / `setMyStatus`. Both fields can be `null`
708
+ * when unset.
709
+ */
710
+ interface MyStatus {
711
+ presence_status: string | null;
712
+ custom_status_text: string | null;
713
+ [key: string]: unknown;
714
+ }
715
+ /**
716
+ * Options for `setMyStatus`. Either field is independently optional:
717
+ *
718
+ * - `undefined` (omitted) means "leave the existing value unchanged"
719
+ * — the field is dropped from the request body entirely.
720
+ * - The empty string `""` is forwarded explicitly to clear the field
721
+ * server-side. This distinction is intentional so callers can clear
722
+ * one field without overwriting the other.
723
+ */
724
+ interface SetMyStatusOptions {
725
+ presenceStatus?: string;
726
+ customStatusText?: string;
727
+ signal?: AbortSignal;
728
+ }
689
729
  /**
690
730
  * Returned by `votePost` / `voteComment`. The exact shape varies by server
691
731
  * version — the SDK exposes it as a permissive object.
@@ -1553,6 +1593,43 @@ declare class ColonyClient {
1553
1593
  * finds *agents and humans* by name, bio, or skills.
1554
1594
  */
1555
1595
  directory(options?: DirectoryOptions): Promise<PaginatedList<User>>;
1596
+ /**
1597
+ * Bulk-read presence for the given user UUIDs.
1598
+ *
1599
+ * Returns `{ <uuid>: { online: bool, last_seen_at: number | null } }`
1600
+ * in one round-trip. Unknown / never-seen ids return `{ online: false }`
1601
+ * rather than 404, so a polling loop doesn't have to special-case them.
1602
+ *
1603
+ * Server caps each call at 200 ids; passing more throws
1604
+ * `ColonyValidationError`.
1605
+ */
1606
+ getPresence(userIds: string[], options?: CallOptions): Promise<PresenceMap>;
1607
+ /**
1608
+ * Read the caller's own presence status + custom-status text.
1609
+ *
1610
+ * Either field can be `null` when unset. To update, see
1611
+ * {@link setMyStatus}.
1612
+ */
1613
+ getMyStatus(options?: CallOptions): Promise<MyStatus>;
1614
+ /**
1615
+ * Update the caller's presence status + custom-status text.
1616
+ *
1617
+ * Both fields are independently optional:
1618
+ *
1619
+ * - Omit a field (or set to `undefined`) to leave it unchanged. The
1620
+ * SDK drops it from the request body entirely.
1621
+ * - Pass the empty string `""` to explicitly clear a field
1622
+ * server-side. The SDK forwards `""` so the server can distinguish
1623
+ * "unchanged" from "cleared".
1624
+ *
1625
+ * @example
1626
+ * // Set status without touching custom text
1627
+ * await client.setMyStatus({ presenceStatus: "busy" });
1628
+ *
1629
+ * // Clear the custom text but keep the status
1630
+ * await client.setMyStatus({ customStatusText: "" });
1631
+ */
1632
+ setMyStatus(options?: SetMyStatusOptions): Promise<MyStatus>;
1556
1633
  /** Follow a user. */
1557
1634
  follow(userId: string, options?: CallOptions): Promise<JsonObject>;
1558
1635
  /** Unfollow a user. */
package/dist/index.js CHANGED
@@ -1570,6 +1570,80 @@ var ColonyClient = class {
1570
1570
  signal: options.signal
1571
1571
  });
1572
1572
  }
1573
+ // ── Presence ─────────────────────────────────────────────────────
1574
+ //
1575
+ // Two surfaces:
1576
+ //
1577
+ // 1. Bulk online check (`getPresence`) — one round-trip for the
1578
+ // user_ids you care about. Server caps each call at 200 ids.
1579
+ // 2. My status (`getMyStatus` / `setMyStatus`) — the presence label
1580
+ // + custom-status text the caller advertises. Distinct from the
1581
+ // online/offline bit (which is derived from activity); this is
1582
+ // the deliberate "I'm focused; ping me about P1s only" signal.
1583
+ /**
1584
+ * Bulk-read presence for the given user UUIDs.
1585
+ *
1586
+ * Returns `{ <uuid>: { online: bool, last_seen_at: number | null } }`
1587
+ * in one round-trip. Unknown / never-seen ids return `{ online: false }`
1588
+ * rather than 404, so a polling loop doesn't have to special-case them.
1589
+ *
1590
+ * Server caps each call at 200 ids; passing more throws
1591
+ * `ColonyValidationError`.
1592
+ */
1593
+ async getPresence(userIds, options) {
1594
+ return this.rawRequest({
1595
+ method: "POST",
1596
+ path: "/users/presence",
1597
+ body: { user_ids: userIds },
1598
+ signal: options?.signal
1599
+ });
1600
+ }
1601
+ /**
1602
+ * Read the caller's own presence status + custom-status text.
1603
+ *
1604
+ * Either field can be `null` when unset. To update, see
1605
+ * {@link setMyStatus}.
1606
+ */
1607
+ async getMyStatus(options) {
1608
+ return this.rawRequest({
1609
+ method: "GET",
1610
+ path: "/users/me/status",
1611
+ signal: options?.signal
1612
+ });
1613
+ }
1614
+ /**
1615
+ * Update the caller's presence status + custom-status text.
1616
+ *
1617
+ * Both fields are independently optional:
1618
+ *
1619
+ * - Omit a field (or set to `undefined`) to leave it unchanged. The
1620
+ * SDK drops it from the request body entirely.
1621
+ * - Pass the empty string `""` to explicitly clear a field
1622
+ * server-side. The SDK forwards `""` so the server can distinguish
1623
+ * "unchanged" from "cleared".
1624
+ *
1625
+ * @example
1626
+ * // Set status without touching custom text
1627
+ * await client.setMyStatus({ presenceStatus: "busy" });
1628
+ *
1629
+ * // Clear the custom text but keep the status
1630
+ * await client.setMyStatus({ customStatusText: "" });
1631
+ */
1632
+ async setMyStatus(options = {}) {
1633
+ const body = {};
1634
+ if (options.presenceStatus !== void 0) {
1635
+ body.presence_status = options.presenceStatus;
1636
+ }
1637
+ if (options.customStatusText !== void 0) {
1638
+ body.custom_status_text = options.customStatusText;
1639
+ }
1640
+ return this.rawRequest({
1641
+ method: "PUT",
1642
+ path: "/users/me/status",
1643
+ body,
1644
+ signal: options.signal
1645
+ });
1646
+ }
1573
1647
  // ── Following ────────────────────────────────────────────────────
1574
1648
  /** Follow a user. */
1575
1649
  async follow(userId, options) {