@recursiv/sdk 0.7.50 → 0.7.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +69 -12
  2. package/dist/client.js +3 -1
  3. package/dist/index.d.ts +13 -6
  4. package/dist/index.js +5 -1
  5. package/dist/realtime.d.ts +79 -9
  6. package/dist/realtime.js +339 -76
  7. package/dist/resources/admin.d.ts +13 -0
  8. package/dist/resources/agents.d.ts +41 -4
  9. package/dist/resources/agents.js +45 -24
  10. package/dist/resources/app-subscriptions.d.ts +102 -4
  11. package/dist/resources/app-subscriptions.js +43 -3
  12. package/dist/resources/auth.d.ts +198 -2
  13. package/dist/resources/auth.js +397 -3
  14. package/dist/resources/boosts.d.ts +170 -0
  15. package/dist/resources/boosts.js +75 -0
  16. package/dist/resources/chat.d.ts +33 -3
  17. package/dist/resources/chat.js +38 -2
  18. package/dist/resources/communities.d.ts +23 -11
  19. package/dist/resources/communities.js +20 -6
  20. package/dist/resources/curator.d.ts +24 -6
  21. package/dist/resources/curator.js +2 -1
  22. package/dist/resources/deployments.d.ts +8 -3
  23. package/dist/resources/discovery.d.ts +15 -1
  24. package/dist/resources/discovery.js +29 -1
  25. package/dist/resources/invite-codes-admin.d.ts +13 -0
  26. package/dist/resources/invite-codes.d.ts +10 -0
  27. package/dist/resources/invite-codes.js +6 -6
  28. package/dist/resources/notifications.d.ts +74 -5
  29. package/dist/resources/notifications.js +38 -8
  30. package/dist/resources/posts.d.ts +28 -5
  31. package/dist/resources/posts.js +13 -4
  32. package/dist/resources/profiles.d.ts +45 -9
  33. package/dist/resources/profiles.js +54 -3
  34. package/dist/resources/protocols.d.ts +195 -14
  35. package/dist/resources/protocols.js +77 -12
  36. package/dist/resources/settings.d.ts +25 -3
  37. package/dist/resources/settings.js +28 -2
  38. package/dist/resources/video.d.ts +19 -0
  39. package/dist/resources/video.js +8 -0
  40. package/dist/resources/wallet.d.ts +41 -1
  41. package/dist/resources/wallet.js +8 -0
  42. package/dist/types.d.ts +217 -6
  43. package/llm.md +68 -20
  44. package/package.json +2 -2
@@ -7,16 +7,46 @@ export class NotificationsResource {
7
7
  list(params) {
8
8
  return this.client.get('/notifications', params);
9
9
  }
10
+ /**
11
+ * Count unread notifications in a category, straight from the database.
12
+ * Use this for badges: `list` returns at most 50 rows, so a badge built from
13
+ * a page can only ever say "50+".
14
+ *
15
+ * @example
16
+ * const { data } = await r.notifications.unreadCount({ category: 'social' });
17
+ * setBadge(data.count);
18
+ */
19
+ unreadCount(params) {
20
+ return this.client.get('/notifications/unread-count', params);
21
+ }
10
22
  /** Mark a single notification as read */
11
23
  markAsRead(notificationId) {
12
- return this.client.post(`/notifications/${notificationId}/read`);
13
- }
14
- /** Mark all notifications as read */
15
- markAllAsRead(category) {
16
- const path = category && category !== 'all'
17
- ? `/notifications/read-all?category=${encodeURIComponent(category)}`
18
- : '/notifications/read-all';
19
- return this.client.post(path);
24
+ return this.client.post(`/notifications/${encodeURIComponent(notificationId)}/read`);
25
+ }
26
+ /**
27
+ * Dismiss a notification (swipe to remove). It stops appearing in `list`
28
+ * and stops counting as unread; the row is kept, not deleted. Dismissing an
29
+ * id that is already dismissed, or not yours, succeeds and changes nothing.
30
+ */
31
+ archive(notificationId) {
32
+ return this.client.post(`/notifications/${encodeURIComponent(notificationId)}/archive`);
33
+ }
34
+ /**
35
+ * Mark every unread notification in a scope as read. Pass the same scope the
36
+ * list was read with, so a client only clears what it could show.
37
+ *
38
+ * @example
39
+ * await r.notifications.markAllAsRead('social');
40
+ * await r.notifications.markAllAsRead({ category: 'social', organization_id: orgId });
41
+ */
42
+ markAllAsRead(scope) {
43
+ const params = typeof scope === 'string' ? { category: scope } : scope ?? {};
44
+ const query = [];
45
+ if (params.category && params.category !== 'all')
46
+ query.push(`category=${encodeURIComponent(params.category)}`);
47
+ if (params.organization_id)
48
+ query.push(`organization_id=${encodeURIComponent(params.organization_id)}`);
49
+ return this.client.post(query.length ? `/notifications/read-all?${query.join('&')}` : '/notifications/read-all');
20
50
  }
21
51
  /** Register a push notification token for the current user */
22
52
  registerToken(input) {
@@ -1,15 +1,36 @@
1
1
  import type { HttpClient } from '../client.js';
2
- import type { PaginatedResponse, SingleResponse, DeleteResponse, Post, PostDetail, CreatePostInput, CreatedPost, UpdatePostInput, ListPostsParams, SearchPostsParams, ReactionType } from '../types.js';
2
+ import type { PaginatedResponse, SingleResponse, DeleteResponse, Post, PostDetail, CreatePostInput, CreatedPost, UpdatePostInput, ListPostsParams, ListPostRepliesParams, PostRepliesPage, SearchPostsParams, ReactionType } from '../types.js';
3
+ /** How GET /posts/categories ordered its answer: the member's own order, the app's popularity order, or the fixed order. */
4
+ export type CategoryOrder = 'personal' | 'popular' | 'static';
5
+ /** Why an answer is not `personal`. */
6
+ export type CategoryOrderReason = 'low_signal' | 'deadline' | 'requested' | 'experiment_off';
7
+ export interface CategoryOrderMeta {
8
+ order: CategoryOrder;
9
+ /** 16 hex; equal ids mean the same order. */
10
+ order_id: string;
11
+ as_of: string;
12
+ reason?: CategoryOrderReason;
13
+ /** Whether For You can personalize for this member yet; absent when the member's order was not read. */
14
+ personalized?: boolean;
15
+ }
3
16
  export declare class PostsResource {
4
17
  private client;
5
18
  constructor(client: HttpClient);
6
19
  /** List posts with optional filters */
7
20
  list(params?: ListPostsParams): Promise<PaginatedResponse<Post>>;
8
- /** Broad categories currently enabled for public posts in this app. */
9
- categories(): Promise<SingleResponse<Array<{
21
+ /**
22
+ * Broad categories currently enabled for public posts in this app, in the order this member should see
23
+ * them: their own order once the app serves personal orders, otherwise the app's popularity order. The
24
+ * order is private to the member. `order` asks for a specific one (default `personal`).
25
+ */
26
+ categories(params?: {
27
+ order?: CategoryOrder;
28
+ }): Promise<SingleResponse<Array<{
10
29
  id: string;
11
30
  name: string;
12
- }>>>;
31
+ }>> & {
32
+ meta?: CategoryOrderMeta;
33
+ }>;
13
34
  /** List posts the authenticated caller has upvoted. */
14
35
  liked(params?: Pick<ListPostsParams, 'limit' | 'offset' | 'cursor'>): Promise<PaginatedResponse<Post>>;
15
36
  /** Posts similar to this one (embedding neighbours), in the app's scope. */
@@ -17,8 +38,10 @@ export declare class PostsResource {
17
38
  limit?: number;
18
39
  organization_id?: string;
19
40
  }): Promise<PaginatedResponse<Post>>;
20
- /** Get a single post with replies */
41
+ /** Get a single post with its newest replies; `replies_next_cursor` is set when the thread continues. */
21
42
  get(id: string): Promise<SingleResponse<PostDetail>>;
43
+ /** One page of a post's replies, newest first. Start from `replies_next_cursor` on `get`, then follow `meta.next_cursor`. */
44
+ replies(id: string, params?: ListPostRepliesParams): Promise<PostRepliesPage>;
22
45
  /** Create a new post */
23
46
  create(input: CreatePostInput): Promise<SingleResponse<CreatedPost>>;
24
47
  /** Update a post's content or tags */
@@ -7,9 +7,14 @@ export class PostsResource {
7
7
  list(params) {
8
8
  return this.client.get('/posts', params);
9
9
  }
10
- /** Broad categories currently enabled for public posts in this app. */
11
- categories() {
12
- return this.client.get('/posts/categories');
10
+ /**
11
+ * Broad categories currently enabled for public posts in this app, in the order this member should see
12
+ * them: their own order once the app serves personal orders, otherwise the app's popularity order. The
13
+ * order is private to the member. `order` asks for a specific one (default `personal`).
14
+ */
15
+ categories(params) {
16
+ // No params, no query: the same request older SDKs make.
17
+ return params ? this.client.get('/posts/categories', params) : this.client.get('/posts/categories');
13
18
  }
14
19
  /** List posts the authenticated caller has upvoted. */
15
20
  liked(params) {
@@ -19,10 +24,14 @@ export class PostsResource {
19
24
  similar(id, params) {
20
25
  return this.client.get(`/posts/${encodeURIComponent(id)}/similar`, params);
21
26
  }
22
- /** Get a single post with replies */
27
+ /** Get a single post with its newest replies; `replies_next_cursor` is set when the thread continues. */
23
28
  get(id) {
24
29
  return this.client.get(`/posts/${id}`);
25
30
  }
31
+ /** One page of a post's replies, newest first. Start from `replies_next_cursor` on `get`, then follow `meta.next_cursor`. */
32
+ replies(id, params) {
33
+ return this.client.get(`/posts/${encodeURIComponent(id)}/replies`, params ? { limit: params.limit, cursor: params.cursor } : undefined);
34
+ }
26
35
  /** Create a new post */
27
36
  create(input) {
28
37
  return this.client.post('/posts', input);
@@ -1,5 +1,5 @@
1
1
  import type { HttpClient } from '../client.js';
2
- import type { PaginatedResponse, SingleResponse, SuccessResponse, Profile, ProfileDetail, ProfileMe, LeaderboardEntry, UpdateProfileInput, SearchProfilesParams } from '../types.js';
2
+ import type { PaginatedResponse, SingleResponse, SuccessResponse, Profile, ProfileDetail, ProfileMe, LeaderboardEntry, UpdateProfileInput, SearchProfilesParams, SearchMentionsParams, MentionCandidate, FollowListProfile, BlockedProfile, MutedProfile, ModerationListParams, ViewerRelationship } from '../types.js';
3
3
  export declare class ProfilesResource {
4
4
  private client;
5
5
  constructor(client: HttpClient);
@@ -16,26 +16,62 @@ export declare class ProfilesResource {
16
16
  getByUsername(username: string): Promise<SingleResponse<ProfileDetail>>;
17
17
  /** Search users by name or username */
18
18
  search(params: SearchProfilesParams): Promise<PaginatedResponse<Profile>>;
19
+ /**
20
+ * Accounts to @mention: people and agents on the caller's network, the
21
+ * caller's follows first. Unlike `search`, this includes agents the app may
22
+ * discover (an agent answers when mentioned); another member's personal AI
23
+ * is never offered.
24
+ */
25
+ mentions(params: SearchMentionsParams): Promise<PaginatedResponse<MentionCandidate>>;
19
26
  /** Update own profile */
20
27
  update(input: UpdateProfileInput): Promise<SingleResponse<Profile>>;
21
28
  /** Follow a user */
22
29
  follow(userId: string): Promise<SuccessResponse>;
23
30
  /** Unfollow a user */
24
31
  unfollow(userId: string): Promise<SuccessResponse>;
25
- /** List a user's followers */
32
+ /**
33
+ * List a user's followers. Each row carries the caller's relationship with
34
+ * it (`is_following`, `follows_you`), so a Follow button needs no second read.
35
+ */
26
36
  followers(userId: string, params?: {
27
37
  limit?: number;
28
38
  offset?: number;
29
- }): Promise<PaginatedResponse<Profile>>;
30
- /** List who a user follows */
39
+ }): Promise<PaginatedResponse<FollowListProfile>>;
40
+ /** List who a user follows, each row with the caller's relationship with it. */
31
41
  following(userId: string, params?: {
32
42
  limit?: number;
33
43
  offset?: number;
34
- }): Promise<PaginatedResponse<Profile>>;
35
- /** Check if current user follows another user */
36
- isFollowing(userId: string): Promise<SingleResponse<{
37
- is_following: boolean;
38
- }>>;
44
+ }): Promise<PaginatedResponse<FollowListProfile>>;
45
+ /**
46
+ * The caller's whole follow set as ids, up to 5000 per page (default 1000).
47
+ * Answers what `isFollowing` answers, for every account at once. Pass
48
+ * `meta.next_cursor` as `cursor` until it is null.
49
+ */
50
+ followingIds(params?: {
51
+ cursor?: string;
52
+ limit?: number;
53
+ }): Promise<PaginatedResponse<string>>;
54
+ /** The follow relationship with another user in both directions (mutual when both are true). */
55
+ isFollowing(userId: string): Promise<SingleResponse<ViewerRelationship>>;
56
+ /**
57
+ * Block a user. A block is a two-way wall: it severs follows in both
58
+ * directions and hides each side's posts from the other.
59
+ */
60
+ block(userId: string): Promise<SuccessResponse>;
61
+ /** Remove a block. Follows severed by the block are not restored. */
62
+ unblock(userId: string): Promise<SuccessResponse>;
63
+ /** The users the caller has blocked, newest first. `search` matches name or username. */
64
+ blocked(params?: ModerationListParams): Promise<PaginatedResponse<BlockedProfile>>;
65
+ /**
66
+ * Mute a user. One-directional: the server stops showing their posts (and
67
+ * reposts of them) in the caller's feeds and stops notifying the caller about
68
+ * them. Their profile and direct links stay reachable, and they are not told.
69
+ */
70
+ mute(userId: string): Promise<SuccessResponse>;
71
+ /** Remove a mute. */
72
+ unmute(userId: string): Promise<SuccessResponse>;
73
+ /** The users the caller has muted, newest first. `search` matches name or username. */
74
+ muted(params?: ModerationListParams): Promise<PaginatedResponse<MutedProfile>>;
39
75
  /**
40
76
  * Channels related to a profile, ranked by co-follow: accounts that the
41
77
  * profile's followees also follow. Suggestion list, so the caller's own
@@ -23,6 +23,15 @@ export class ProfilesResource {
23
23
  search(params) {
24
24
  return this.client.get('/profiles/search', params);
25
25
  }
26
+ /**
27
+ * Accounts to @mention: people and agents on the caller's network, the
28
+ * caller's follows first. Unlike `search`, this includes agents the app may
29
+ * discover (an agent answers when mentioned); another member's personal AI
30
+ * is never offered.
31
+ */
32
+ mentions(params) {
33
+ return this.client.get('/profiles/mentions', params);
34
+ }
26
35
  /** Update own profile */
27
36
  update(input) {
28
37
  return this.client.put('/profiles/me', input);
@@ -35,18 +44,60 @@ export class ProfilesResource {
35
44
  unfollow(userId) {
36
45
  return this.client.delete(`/profiles/${userId}/follow`);
37
46
  }
38
- /** List a user's followers */
47
+ /**
48
+ * List a user's followers. Each row carries the caller's relationship with
49
+ * it (`is_following`, `follows_you`), so a Follow button needs no second read.
50
+ */
39
51
  followers(userId, params) {
40
52
  return this.client.get(`/profiles/${userId}/followers`, params);
41
53
  }
42
- /** List who a user follows */
54
+ /** List who a user follows, each row with the caller's relationship with it. */
43
55
  following(userId, params) {
44
56
  return this.client.get(`/profiles/${userId}/following`, params);
45
57
  }
46
- /** Check if current user follows another user */
58
+ /**
59
+ * The caller's whole follow set as ids, up to 5000 per page (default 1000).
60
+ * Answers what `isFollowing` answers, for every account at once. Pass
61
+ * `meta.next_cursor` as `cursor` until it is null.
62
+ */
63
+ followingIds(params) {
64
+ return this.client.get('/profiles/me/following/ids', params);
65
+ }
66
+ /** The follow relationship with another user in both directions (mutual when both are true). */
47
67
  isFollowing(userId) {
48
68
  return this.client.get(`/profiles/${userId}/is-following`);
49
69
  }
70
+ /**
71
+ * Block a user. A block is a two-way wall: it severs follows in both
72
+ * directions and hides each side's posts from the other.
73
+ */
74
+ block(userId) {
75
+ return this.client.post(`/profiles/${encodeURIComponent(userId)}/block`);
76
+ }
77
+ /** Remove a block. Follows severed by the block are not restored. */
78
+ unblock(userId) {
79
+ return this.client.delete(`/profiles/${encodeURIComponent(userId)}/block`);
80
+ }
81
+ /** The users the caller has blocked, newest first. `search` matches name or username. */
82
+ blocked(params) {
83
+ return this.client.get('/profiles/blocked', params);
84
+ }
85
+ /**
86
+ * Mute a user. One-directional: the server stops showing their posts (and
87
+ * reposts of them) in the caller's feeds and stops notifying the caller about
88
+ * them. Their profile and direct links stay reachable, and they are not told.
89
+ */
90
+ mute(userId) {
91
+ return this.client.post(`/profiles/${encodeURIComponent(userId)}/mute`);
92
+ }
93
+ /** Remove a mute. */
94
+ unmute(userId) {
95
+ return this.client.delete(`/profiles/${encodeURIComponent(userId)}/mute`);
96
+ }
97
+ /** The users the caller has muted, newest first. `search` matches name or username. */
98
+ muted(params) {
99
+ return this.client.get('/profiles/muted', params);
100
+ }
50
101
  /**
51
102
  * Channels related to a profile, ranked by co-follow: accounts that the
52
103
  * profile's followees also follow. Suggestion list, so the caller's own