@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
package/README.md CHANGED
@@ -74,7 +74,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
74
74
  ### AI Agents
75
75
  | Resource | Key methods |
76
76
  |----------|------------|
77
- | `r.agents` | `create`, `update`, `chat`, `chatStream`, `grantProjectAccess`, `conversations` |
77
+ | `r.agents` | `create`, `update`, `chat`, `chatStream`, `retryChatStream`, `grantProjectAccess`, `conversations` |
78
78
  | `r.e2ee` | `registerDevice`, `devices`, `revokeDevice`, `publishKeyPackages`, `keyPackageStatus`, `claimKeyPackage`, `appendEvent`, `events`, `acknowledge` (flag-gated E2EE v2 transport) |
79
79
  | `r.brain` | `sendMessage` |
80
80
  | `r.commands` | `execute`, `gatePrompt` |
@@ -84,34 +84,37 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
84
84
  ### Identity & Auth
85
85
  | Resource | Key methods |
86
86
  |----------|------------|
87
- | `r.auth` | `signUp`, `signIn`, `getSession`, `signOut`, `createApiKey` (session reads/sign-out use explicit Bearer auth with a native/server Cookie fallback) |
87
+ | `r.auth` | `signUp`, `signIn`, `signInWithUsername`, `getSession`, `signOut`, `createApiKey`, `forgetPassword`, `resetPassword`; two-factor: `enableTwoFactor`, `verifyTwoFactor`, `disableTwoFactor`, `regenerateTwoFactorBackupCodes`, `requestTwoFactorEmailCode`, `completeTwoFactorSignIn`; OAuth consent: `exchangeSessionForCookie`, `getOAuthClientInfo` (session calls use explicit Bearer auth with a native/server Cookie fallback) |
88
88
  | `@recursiv/sdk/next` | `createRecursivAuth` — cookie-session server auth for Next.js App Router (see below) |
89
89
  | `r.users` | `me`, `get` |
90
90
  | `r.organizations` | `create`, `members`, `addMember`, `invite` |
91
- | `r.profiles` | `me`, `get`, `search`, `follow`, `unfollow` |
91
+ | `r.profiles` | `me`, `get`, `search`, `mentions`, `follow`, `unfollow`, `followers`/`following` (rows carry `is_following`, `follows_you`), `followingIds`, `block`, `unblock`, `blocked`, `mute`, `unmute`, `muted` |
92
92
 
93
93
  ### Social
94
94
  | Resource | Key methods |
95
95
  |----------|------------|
96
- | `r.posts` | `create`, `update`, `list`, `liked`, `search`, `react` |
97
- | `r.communities` | `create`, `join`, `members` |
98
- | `r.chat` | `send`, `dm`, `createGroup`, `messages` |
96
+ | `r.posts` | `create`, `update`, `list`, `liked`, `search`, `replies`, `react` |
97
+ | `r.communities` | `create`, `join`, `search`, `members` |
98
+ | `r.chat` | `send`, `dm`, `createGroup`, `messages` (cursor paging), `acceptRequest`, `declineRequest`, `leave`, `deleteConversation` |
99
99
  | `r.tags` | `create`, `list` |
100
100
  | `r.uploads` | `uploadMedia` — upload post/chat bytes end to end |
101
+ | `r.video` | `entitlement` (may the caller publish video, and how much is left), `createUpload`, `getStatus`, `getPlaybackToken` |
101
102
 
102
103
  ### Platform
103
104
  | Resource | Purpose |
104
105
  |----------|---------|
105
- | `r.settings` | User preferences (including app-scoped content choices), sessions, password management |
106
+ | `r.settings` | User preferences (including app-scoped content choices), sessions (`revokeOtherSessions` keeps this device), password management, email change (`requestConfirmationCode` for accounts with no password) |
106
107
  | `r.billing` | Usage tracking, subscriptions, checkout |
107
- | `r.appSubscriptions` | Consumer app plans: `checkout`, `status`, `createPortalSession` |
108
- | `r.notifications` | Push notification tokens |
108
+ | `r.appSubscriptions` | Consumer app plans: `checkout`, `status`, `createPortalSession`, `previewTierChange`, `changeTier` |
109
+ | `r.boosts` | Promoted posts: `create`, `mine`, `balance`, `pause`, `resume`, `cancel`, `recordEvent`, `topup`, `confirmTopup`; admin `listPendingReview`, `review`, `grant` |
110
+ | `r.wallet` | Wallet, MINDS tokens (`getTokenBalance`, `getTokenLedger`), USD payouts (`getPayouts`, `startPayoutOnboarding`, `payoutLoginLink`) |
111
+ | `r.notifications` | Notification stream (`list`, `unreadCount`, `markAsRead`, `archive`, `markAllAsRead`) and push tokens |
109
112
  | `r.github` | GitHub integration |
110
113
  | `r.integrations` | External service connections |
111
114
  | `r.admin` | User management, stats, content reports (`listReports`, `resolveReport`, `dismissReport`) |
112
115
  | `r.dispatcher` | Task queue, claims, signals, outcomes, webhooks |
113
116
  | `r.goals` | Org goals with task rollups (group dispatcher tasks) |
114
- | `r.protocols` | Private Minds safety: `sourceControls` (current enablement and saved choices), `setSourceControl`, `onSourceControlChange`, `reportSource`. Delegated accounts: `nativeSocialAccounts`, `startNativeSocialConnection`, `finishNativeSocialConnection`, `disconnectNativeSocialAccount`. Native follows: `nativeFollowState`, `prepareNativeFollow`, `submitNativeFollow`, `nativeFollowStatus` (native following or pending approval, distinct from a Minds feed subscription; preserve the complete signed Nostr list). Native reposts and undo: `nativeRepostState`, `prepareNativeRepost`, `submitNativeRepost`, `nativeRepostStatus` (public posts, explicit approval, connected account, no uncertain retries). Native likes and unlikes: `nativeLikeState`, `prepareNativeLike`, `submitNativeLike`, `nativeLikeStatus` (connected authority, app enablement and explicit approval; resume pending actions instead of duplicating them). Reviewed replies and optional linked posts: `prepareNativeReply`, `submitNativeReply`, `nativeReplyStatus`, `nativeReplyHistory`, `prepareNativeReplyRemoval`, `removeNativeReply` (require deployed API support and app enablement). Keyless shared post links: `sharedNetworks(projectId)`, `getSharedConversation(projectId, { protocol, post, readRef? })`. Member public reading: `searchPublicPosts` (selected account required for Bluesky/ActivityPub; public Nostr search), `getConnectedSocialConversation` (preserve result readerAccountId/readRef), `publicNetworks`, `searchPublicProfiles`, `getPublicProfile`, `getPublicAuthorFeed`, `getFollowingFeed`, `getPublicConversation`, `getPublicTrends`, `getPublicTrendFeed`; private app subscriptions: `listSubscriptions`, `subscribeToProfile`, `unsubscribeFromProfile`, `onSubscriptionChange`. `list` returns bounded adapter `maturity`, `limitations`, and exhaustive `supported`/`planned`/`unsupported` implementation capabilities (not provider health or enablement); settings, candidate refresh/status, search, and read-only quarantined candidate review via `listCandidates` / `getCandidate` |
117
+ | `r.protocols` | Private Minds safety: `sourceControls` (current enablement and saved choices; filter with `control`, each item may carry a `display` label), `setSourceControl`, `onSourceControlChange`, `reportSource`. Delegated accounts: `nativeSocialAccounts`, `startNativeSocialConnection`, `finishNativeSocialConnection`, `disconnectNativeSocialAccount`. Native follows: `nativeFollowStates` (every connected account's state for one source, one read), `nativeFollowState`, `prepareNativeFollow`, `submitNativeFollow`, `nativeFollowStatus` (native following or pending approval, distinct from a Minds feed subscription; preserve the complete signed Nostr list). Native reposts and undo: `nativeRepostState`, `prepareNativeRepost`, `submitNativeRepost`, `nativeRepostStatus` (public posts, explicit approval, connected account, no uncertain retries). Native likes and unlikes: `nativeLikeState`, `prepareNativeLike`, `submitNativeLike`, `nativeLikeStatus` (connected authority, app enablement and explicit approval; resume pending actions instead of duplicating them). Reviewed replies and optional linked posts: `prepareNativeReply`, `submitNativeReply`, `nativeReplyStatus`, `nativeReplyHistory`, `prepareNativeReplyRemoval`, `removeNativeReply` (require deployed API support and app enablement). Keyless shared post links: `sharedNetworks(projectId)`, `getSharedConversation(projectId, { protocol, post, readRef? })`. Member public reading: `searchPublicPosts` (selected account required for Bluesky/ActivityPub; public Nostr search), `getConnectedSocialConversation` (preserve result readerAccountId/readRef), `publicNetworks`, `searchPublicProfiles`, `getPublicProfile`, `getPublicAuthorFeed`, `getFollowingFeed`, `getPublicConversation`, `getPublicTrends`, `getPublicTrendFeed`; radar stories: `getPublicRadarStory` (one story by id with its posts), keyless `getSharedRadarStory(projectId, { cluster })` and `getSharedRadarPosts(projectId, { cluster })`; private app subscriptions: `listSubscriptions`, `subscribeToProfile`, `unsubscribeFromProfile`, `onSubscriptionChange`. `list` returns bounded adapter `maturity`, `limitations`, and exhaustive `supported`/`planned`/`unsupported` implementation capabilities (not provider health or enablement); settings, candidate refresh/status, search, and read-only quarantined candidate review via `listCandidates` / `getCandidate` |
115
118
 
116
119
  Full reference: see [llm.md](./llm.md) (ships with this package) or the type definitions in `dist/`.
117
120
 
@@ -137,6 +140,7 @@ deployment, throw the normal SDK errors; do not present them as an empty queue.
137
140
  ```typescript
138
141
  const r = new Recursiv({
139
142
  apiKey: 'sk_live_...', // or set RECURSIV_API_KEY env var
143
+ inheritEnvironmentApiKey: true, // default; false guarantees keyless operation
140
144
  baseUrl: 'https://api.recursiv.io/api/v1', // default
141
145
  timeout: 30000, // request timeout in ms
142
146
  maxRetries: 2, // auto-retry on 429/5xx
@@ -145,9 +149,12 @@ const r = new Recursiv({
145
149
  // Zero-arg works when RECURSIV_API_KEY is set
146
150
  const r = new Recursiv()
147
151
 
148
- // Anonymous sandbox (no API key needed)
152
+ // Anonymous sandbox (no API key required; inherits RECURSIV_API_KEY when set)
149
153
  const r = new Recursiv({ anonymous: true })
150
154
 
155
+ // Guaranteed keyless public client, even inside a credentialed server process
156
+ const visitor = new Recursiv({ anonymous: true, inheritEnvironmentApiKey: false })
157
+
151
158
  // Self-hosted
152
159
  const r = new Recursiv({ baseUrl: 'https://my-instance.com/api/v1' })
153
160
  ```
@@ -472,6 +479,25 @@ participant selection is unfinished. `textTruncated` labels an abbreviated sourc
472
479
  preview. Preparation and submission never automatically retry; check the event ID
473
480
  after an uncertain result before choosing a retry of the identical signed event.
474
481
 
482
+ ### A Bluesky account on the app's own PDS
483
+
484
+ `createHostedIdentity` asks the app's own PDS to issue a Bluesky account for the
485
+ signed-in member. Only the label is sent; the app picks the domain.
486
+
487
+ ```ts
488
+ const { data: identity } = await r.protocols.createHostedIdentity({
489
+ protocol: 'atproto', handle: 'alice', email: 'alice@example.com',
490
+ })
491
+ // identity.handle is e.g. 'alice.pds.minds.com'. identity.password exists only in
492
+ // this response: show it to the member once and store it nowhere.
493
+ ```
494
+
495
+ The server either finishes the account or removes it again, so a failure never
496
+ leaves one half made. The call is never retried automatically. `handle_unavailable`
497
+ (409) means choose another label; the 503 codes `handle_dns_unavailable`,
498
+ `handle_unresolvable` and `handle_unverified` are operator setup and succeed
499
+ unchanged once it is done.
500
+
475
501
  ### Delegated Bluesky and ActivityPub accounts
476
502
 
477
503
  These methods require the same signed-in human app key throughout. The API must
@@ -497,6 +523,18 @@ native token is sent through these SDK methods. Start and callback are single-us
497
523
  requests and are never automatically retried. If a callback result is uncertain,
498
524
  refresh the account list before starting again.
499
525
 
526
+ In a native app, use the operator-configured native callback instead of the web
527
+ one when `nativeSocialAccounts()` lists the protocol in `nativeRedirects`:
528
+
529
+ ```ts
530
+ const { data: start } = await r.protocols.startNativeSocialConnection({
531
+ protocol: 'bluesky', identifier: 'alice.bsky.social', redirect: 'native',
532
+ })
533
+ const result = await WebBrowser.openAuthSessionAsync(start.authorizationUrl, start.callbackUrl)
534
+ // In the native callback route, read state, code, iss (or error) from result.url:
535
+ await r.protocols.finishNativeSocialConnection({ protocol: 'bluesky', state, code, iss })
536
+ ```
537
+
500
538
  Connection does not approve publication. The account's `capabilities` lists only
501
539
  implemented actions, currently empty for these adapters. Local disconnect takes
502
540
  effect even when `providerRevocation` is `unconfirmed`; the user can also revoke
@@ -579,7 +617,10 @@ state and obtain a fresh review before a new write.
579
617
  Visitors can read a public conversation in an explicitly configured app without signing in:
580
618
 
581
619
  ```ts
582
- const visitor = new Recursiv({ anonymous: true });
620
+ const visitor = new Recursiv({
621
+ anonymous: true,
622
+ inheritEnvironmentApiKey: false,
623
+ });
583
624
  const { data: networks } = await visitor.protocols.sharedNetworks(projectId);
584
625
  const { data: conversation } = await visitor.protocols.getSharedConversation(projectId, {
585
626
  protocol: 'nostr', post: publicEventId,
@@ -594,6 +635,8 @@ blocks/mutes as well. All reply and account endpoints still require authenticati
594
635
 
595
636
  Standalone public publication uses `protocols.prepareNativePost({ clientMutationId, text, accountIds, media? })`, then explicitly approved `submitNativePost`. Keep the same mutation ID after uncertain preparation; previously attempted deliveries are reconciled without resending. `nativePostStatus` and paginated `nativePostHistory` expose private app/user-owned outcomes. Review current own posts with `prepareNativePostRemoval`, then approve exact removal IDs through `removeNativePost`. Check connected-account `publish_text` capabilities; only explicitly enabled apps may publish. Text is sent unchanged, public only, with each provider’s actual limits. Optional `media` is a `NativeMediaInput[]` of at most four already-uploaded Minds images (`{ url, alt?, width?, height?, mimeType? }`, JPEG/PNG/WebP/GIF, Minds-hosted HTTPS URLs only, a Mastodon GIF must be the only attachment). It additionally requires the account's `publish_media` capability; accounts connected before image permissions existed must reconnect. Pass the member's own `alt` — an omitted one is sent as an empty description, never an invented one — and read `receipt.media` (`{ count, alt_missing }`) after sending. These methods still do not accept a reply parent or caller-supplied authority.
596
637
 
638
+ To delete a post everywhere, link its network copies when you cross-post: pass `crossPostOf: post.id` (the member's own post in this app, from `sdk.posts`) to `prepareNativePost` and to `prepareNativeNostr(id, { action: 'publish', content, crossPostOf })`. Later, `nativePostHistory({ crossPostOf: post.id })` lists exactly that post's copies, each with `crossPostOf` set: delegated items are removed with `prepareNativePostRemoval`/`removeNativePost`, and `type: 'nostr'` items (original notes, which this SDK's history lists; the REST route returns them only with `include=nostr` or `crossPostOf`, so older apps keep the delegated-only shape) with the Nostr signing flow (`prepareNativeNostr(identityId, { action: 'delete', postId: eventId })`). Another member's post, or one from another app, answers `not_found`; copies prepared without `crossPostOf` stay unlinked.
639
+
597
640
  For Bluesky accounts advertising `quote`, prepare the same publication with `quote: { protocol: 'bluesky', nativeId: sourceAtUri }`. The server resolves the exact source CID using each connected account, checks quote permission and Minds safety, and rechecks before writing. Review each delivery’s `quote` alongside the account and comment before submitting. Changed or unavailable sources cannot publish; uncertain deliveries reconcile the original record key. ActivityPub/Nostr quotes are not provided by this method. Public post reads include at most one filtered `quote` with `state: 'available'` and `post`, or `state: 'unavailable'` without source content. Available quotes may include `embeddedReferences`: exact standalone source-reference lines in the unchanged outer `text`. Omit them only when the quoted original is actually visible; retain them for unavailable or locally hidden quotes. Nostr references are decoded and matched by the server, without following relay hints.
598
641
 
599
642
  Topic browsing can request `getPublicTrends({ protocol: "bluesky", includePreviews: true })`. Optional `SocialTrend.preview` is a real image-bearing post from that topic, never a generated illustration. The server samples at most eight posts for each of ten topics, with three concurrent reads and a shared 2.5-second deadline; missing images leave usable text topics. App moderation and user source controls filter previews on every request. Bluesky CDN image attachments, quote-with-media images, and unlabeled link-preview thumbnails are supported; omitted content retains the source link.
@@ -607,6 +650,20 @@ module specs and native or protocol post objects. Preserve their existing source
607
650
  authority and interactive controls. `retryFailed()` explicitly retries unavailable
608
651
  sources; create a new session to refresh exhausted source windows.
609
652
 
653
+ `sdk.discovery.createPersonalFeed({ networks, category?, learning?, recommend? })`
654
+ builds the same kind of session for a member's For you tab: its Minds slot reads
655
+ `sdk.curator.forYou({ surface: 'discover', discovery: true, cursor })`, which ranks
656
+ fresher and past the member's follows, pages a stored ranking by `meta.next_cursor`,
657
+ and says whether the member is personalized yet (`meta.personalized`). With a
658
+ `category` (the member's first), the session also reads open-network posts from it;
659
+ without, it is Minds only. It never carries the radar.
660
+
661
+ `sdk.posts.categories()` answers the app's categories in the order this member
662
+ should see them. `meta.order` is `personal`, `popular` or `static`; `meta.reason`
663
+ says why an answer is not personal (`low_signal`, `deadline`, `requested`,
664
+ `experiment_off`), and `meta.order_id` changes only when the order does. The order
665
+ is private to the member; show it as returned rather than sorting it again.
666
+
610
667
  Optional `DiscoveryLearning` consumes real visible impressions and explicit
611
668
  engagement/hide outcomes. Persist its count-only snapshot per viewer; never share
612
669
  a session or learning state across accounts. It starts conservatively and does
package/dist/client.js CHANGED
@@ -11,7 +11,9 @@ export class HttpClient {
11
11
  clientName;
12
12
  constructor(config) {
13
13
  const apiKey = config?.apiKey ||
14
- (typeof process !== 'undefined' ? process.env?.RECURSIV_API_KEY : undefined);
14
+ (config?.inheritEnvironmentApiKey !== false && typeof process !== 'undefined'
15
+ ? process.env?.RECURSIV_API_KEY
16
+ : undefined);
15
17
  this.anonymous = config?.anonymous ?? false;
16
18
  if (!apiKey && !this.anonymous && !config?.allowNoKey) {
17
19
  throw new RecursivError(0, {
package/dist/index.d.ts CHANGED
@@ -51,6 +51,7 @@ import { SwarmsResource } from './resources/swarms.js';
51
51
  import { TemplatesResource } from './resources/templates.js';
52
52
  import { VideoResource } from './resources/video.js';
53
53
  import { AppSubscriptionsResource } from './resources/app-subscriptions.js';
54
+ import { BoostsResource } from './resources/boosts.js';
54
55
  import { MediaResource } from './resources/media.js';
55
56
  import { WebhooksResource } from './resources/webhooks.js';
56
57
  import { JobsResource } from './resources/jobs.js';
@@ -119,6 +120,7 @@ export declare class Recursiv {
119
120
  readonly discovery: DiscoveryResource;
120
121
  readonly video: VideoResource;
121
122
  readonly appSubscriptions: AppSubscriptionsResource;
123
+ readonly boosts: BoostsResource;
122
124
  readonly reports: ReportsResource;
123
125
  readonly moderation: ModerationResource;
124
126
  readonly linkPreview: LinkPreviewResource;
@@ -137,9 +139,11 @@ export declare class Recursiv {
137
139
  }
138
140
  export { HttpClient } from './client.js';
139
141
  export { RealtimeClient } from './realtime.js';
142
+ export type { RealtimeConnectOptions } from './realtime.js';
140
143
  export { AuthResource } from './resources/auth.js';
141
- export type { AuthSession, SignUpInput, SignInInput, SendOtpInput, VerifyOtpInput, CreateApiKeyInput, ApiKeyResult } from './resources/auth.js';
144
+ export type { AuthSession, SignUpInput, SignInInput, UsernameSignInInput, AppContext, ResetPasswordInput, TwoFactorConfirmation, TwoFactorEnrollment, TwoFactorChallenge, CompleteTwoFactorSignInInput, OAuthClientInfo, SendOtpInput, VerifyOtpInput, CreateApiKeyInput, ApiKeyResult, } from './resources/auth.js';
142
145
  export { PostsResource } from './resources/posts.js';
146
+ export type { CategoryOrder, CategoryOrderMeta, CategoryOrderReason } from './resources/posts.js';
143
147
  export { UsersResource } from './resources/users.js';
144
148
  export { CommunitiesResource } from './resources/communities.js';
145
149
  export { ChatResource } from './resources/chat.js';
@@ -155,7 +159,7 @@ export { SandboxResource } from './resources/sandbox.js';
155
159
  export { ProfilesResource } from './resources/profiles.js';
156
160
  export { OrganizationsResource } from './resources/organizations.js';
157
161
  export { NotificationsResource } from './resources/notifications.js';
158
- export type { Notification, ListNotificationsParams, NotificationListResponse } from './resources/notifications.js';
162
+ export type { Notification, NotificationActor, NotificationCategory, NotificationPostPreview, NotificationScopeParams, NotificationUnreadCount, ListNotificationsParams, NotificationListResponse, } from './resources/notifications.js';
159
163
  export { SettingsResource } from './resources/settings.js';
160
164
  export { BillingResource } from './resources/billing.js';
161
165
  export { FreeTierResource } from './resources/free-tier.js';
@@ -177,10 +181,10 @@ export { WebhooksResource } from './resources/webhooks.js';
177
181
  export { JobsResource } from './resources/jobs.js';
178
182
  export { CuratorResource } from './resources/curator.js';
179
183
  export { VideoResource } from './resources/video.js';
180
- export type { VideoUploadCreds, CreateVideoUploadResult, VideoStatusInfo, VideoPlaybackToken, } from './resources/video.js';
184
+ export type { VideoUploadCreds, CreateVideoUploadResult, VideoStatusInfo, VideoPlaybackToken, VideoEntitlement, } from './resources/video.js';
181
185
  export { AppSubscriptionsResource } from './resources/app-subscriptions.js';
182
- export type { AppSubscriptionCheckoutResult, AppSubscriptionPortalResult, AppSubscriptionStatusResult, } from './resources/app-subscriptions.js';
183
- export type { CuratorSource, CuratorPrompt, CuratorRunInput, CuratorRunResult, CuratorTodayEdition, CuratorTodayExcerpt, CuratorTodayLeadImage, CuratorTodayRadar, CuratorTodayReaction, CuratorTodayResponse, CuratorTodaySource, CuratorTodayStory, } from './resources/curator.js';
186
+ export type { AppSubscriptionBoostCredit, AppSubscriptionCheckoutResult, AppSubscriptionPortalResult, AppSubscriptionStatusResult, AppSubscriptionTierChangePreview, AppSubscriptionTierChangeResult, } from './resources/app-subscriptions.js';
187
+ export type { CuratorSource, CuratorPrompt, CuratorRunInput, CuratorRunResult, CuratorTodayEdition, CuratorTodayExcerpt, CuratorTodayLeadImage, CuratorTodayRadar, CuratorTodayReaction, CuratorTodayResponse, CuratorTodaySource, CuratorTodayStory, ForYouMeta, ForYouParams, ForYouSurface, } from './resources/curator.js';
184
188
  export { ReportsResource } from './resources/reports.js';
185
189
  export type { ReportTargetType, ReportStatus, CreateReportInput, ReportRecord, ResolveReportInput, } from './resources/reports.js';
186
190
  export { ModerationResource } from './resources/moderation.js';
@@ -196,9 +200,12 @@ export { OrganizationSecurityResource } from './resources/organization-security.
196
200
  export { UploadsResource } from './resources/uploads.js';
197
201
  export type { UploadMediaInput, UploadUrlInput, UploadUrlResult } from './resources/uploads.js';
198
202
  export { WalletResource } from './resources/wallet.js';
203
+ export type { LinkedTokenWallet, PayoutState, TokenBalance, TokenLedgerEntry } from './resources/wallet.js';
204
+ export { BoostsResource } from './resources/boosts.js';
205
+ export type { BoostBalance, BoostBalanceResponse, BoostCampaign, BoostCampaignResponse, BoostEventResult, BoostLedgerEntry, BoostLedgerKind, BoostPlanCredit, BoostRejectionReason, BoostReviewStatus, BoostStatus, BoostTopupCheckout, BoostTopupConfirmation, BoostTopupLimits, } from './resources/boosts.js';
199
206
  export { ProtocolsResource } from './resources/protocols.js';
200
207
  export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, } from './resources/protocols.js';
201
- export type { SocialProfile, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendFeed, SocialPopularProfiles, SocialAuthorFeed, SocialFollowingFeed, SocialFollowingSource, SearchPublicProfilesParams, SearchPublicPostsParams, SocialPostSearch, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeSocialCallbackInput, NativeReplyPrepareInput, NativePostPrepareInput, NativeMediaInput, NativeMediaItem, NativePostBatch, NativePostHistory, NativeFollowSourceInput, NativeFollowPrepareInput, NativeFollowTarget, NativeFollowReceipt, NativeFollowState, NativeFollowReview, NativeLikeSourceInput, NativeRepostSourceInput, NativeLikePrepareInput, NativeRepostPrepareInput, NativeLikeTarget, NativeRepostTarget, NativeLikeReceipt, NativeRepostReceipt, NativeLikeState, NativeRepostState, NativeLikeReview, NativeRepostReview, NativeReplyReceipt, NativeReplyBatch, NativeReplyHistory, NativeDelegatedReplyHistoryItem, NativeNostrReplyResult, NativeNostrReplyHistoryItem, NativeReplyRemovalReceipt, NativeReplyRemovalPreview, SocialSourceRef, SocialSourceControl, SocialSourceControlChange, HostedPostPreview, ConnectHostedIdentityInput, PreviewHostedPostInput, PublishHostedPostInput, ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolIngestionReplayResult, ProtocolIngestionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, ReplayProtocolIngestionJobInput, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
208
+ export type { SocialProfile, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialRadar, SocialRadarCluster, SocialRadarMember, SocialRadarParams, SocialRadarPosts, SocialRadarStory, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendSourceIndex, SocialTrendFeed, SocialPopularProfiles, SocialAuthorFeed, SocialFollowingFeed, SocialFollowingSource, SearchPublicProfilesParams, SearchPublicPostsParams, SocialPostSearch, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeSocialCallbackInput, NativeReplyPrepareInput, NativePostPrepareInput, NativeMediaInput, NativeMediaItem, NativePostBatch, NativePostHistory, NativeDelegatedPostHistoryItem, NativeNostrPostHistoryItem, NativeFollowSourceInput, NativeFollowPrepareInput, NativeFollowTarget, NativeFollowReceipt, NativeFollowState, NativeFollowAccount, NativeFollowStates, NativeFollowReview, NativeLikeSourceInput, NativeRepostSourceInput, NativeLikePrepareInput, NativeRepostPrepareInput, NativeLikeTarget, NativeRepostTarget, NativeLikeReceipt, NativeRepostReceipt, NativeLikeState, NativeRepostState, NativeLikeReview, NativeRepostReview, NativeReplyReceipt, NativeReplyBatch, NativeReplyHistory, NativeDelegatedReplyHistoryItem, NativeNostrReplyResult, NativeNostrReplyHistoryItem, NativeReplyRemovalReceipt, NativeReplyRemovalPreview, SocialSourceRef, SocialSourceControl, SocialSourceControlDisplay, SocialSourceControlChange, HostedPostPreview, ConnectHostedIdentityInput, CreateHostedIdentityInput, CreatedHostedProtocolIdentity, PreviewHostedPostInput, PublishHostedPostInput, ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolIngestionReplayResult, ProtocolIngestionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, ReplayProtocolIngestionJobInput, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
202
209
  export { InboxResource } from './resources/inbox.js';
203
210
  export { NetworkResource } from './resources/network.js';
204
211
  export { SimulatorResource } from './resources/simulator.js';
package/dist/index.js CHANGED
@@ -52,6 +52,7 @@ import { SwarmsResource } from './resources/swarms.js';
52
52
  import { TemplatesResource } from './resources/templates.js';
53
53
  import { VideoResource } from './resources/video.js';
54
54
  import { AppSubscriptionsResource } from './resources/app-subscriptions.js';
55
+ import { BoostsResource } from './resources/boosts.js';
55
56
  import { MediaResource } from './resources/media.js';
56
57
  import { WebhooksResource } from './resources/webhooks.js';
57
58
  import { JobsResource } from './resources/jobs.js';
@@ -120,6 +121,7 @@ export class Recursiv {
120
121
  discovery;
121
122
  video;
122
123
  appSubscriptions;
124
+ boosts;
123
125
  reports;
124
126
  moderation;
125
127
  linkPreview;
@@ -179,9 +181,10 @@ export class Recursiv {
179
181
  this.webhooks = new WebhooksResource(client);
180
182
  this.jobs = new JobsResource(client);
181
183
  this.curator = new CuratorResource(client);
182
- this.discovery = new DiscoveryResource(this.posts, this.protocols);
184
+ this.discovery = new DiscoveryResource(this.posts, this.protocols, this.curator);
183
185
  this.video = new VideoResource(client);
184
186
  this.appSubscriptions = new AppSubscriptionsResource(client);
187
+ this.boosts = new BoostsResource(client);
185
188
  this.reports = new ReportsResource(client);
186
189
  this.moderation = new ModerationResource(client);
187
190
  this.linkPreview = new LinkPreviewResource(client);
@@ -246,6 +249,7 @@ export { ProjectSettingsResource } from './resources/project-settings.js';
246
249
  export { OrganizationSecurityResource } from './resources/organization-security.js';
247
250
  export { UploadsResource } from './resources/uploads.js';
248
251
  export { WalletResource } from './resources/wallet.js';
252
+ export { BoostsResource } from './resources/boosts.js';
249
253
  export { ProtocolsResource } from './resources/protocols.js';
250
254
  export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, } from './resources/protocols.js';
251
255
  export { InboxResource } from './resources/inbox.js';
@@ -53,32 +53,102 @@ export interface RealtimeConnectOptions {
53
53
  * Use this when the API key must stay server-side (cookie-auth web apps):
54
54
  * expose a same-origin route that mints the token with the server-held key
55
55
  * and pass its fetcher here. Default: fetch with this client's own key
56
- * (REST `/realtime/ws-token`, tRPC fallback).
56
+ * (REST `/realtime/ws-token`).
57
+ *
58
+ * Throw an error whose `status` is 401 or 403 when the credential itself is
59
+ * refused; the client then stops reconnecting until `connect()` is called
60
+ * again. Returning `undefined` (or throwing anything else) counts as a
61
+ * transient failure and is retried with backoff.
57
62
  */
58
63
  getToken?: () => Promise<string | undefined>;
64
+ /** First reconnect delay in ms. Default 2000. */
65
+ reconnectionDelay?: number;
66
+ /** Longest reconnect delay in ms. Default 30000. */
67
+ reconnectionDelayMax?: number;
68
+ /** Jitter applied to each reconnect delay, as a fraction of it (0 to 1). Default 0.5. */
69
+ randomizationFactor?: number;
59
70
  }
71
+ /**
72
+ * WebSocket client for chat and presence.
73
+ *
74
+ * One socket at a time, and it survives the ways a socket dies:
75
+ * - a transport drop (network blip, sleep, backgrounding, API restart) is
76
+ * retried by socket.io with jittered backoff;
77
+ * - the server ending the connection because its token expired, or refusing
78
+ * a reconnect handshake (spent or expired token, rate limit), is retried
79
+ * here with the same backoff, since socket.io does not retry either;
80
+ * - every attempt authenticates with its own token (the server accepts each
81
+ * token once), and a failed token fetch sends none rather than a spent one;
82
+ * - listeners registered with `on()`/`onMessage()`… and rooms joined with
83
+ * `joinConversation()` are re-applied to every connection, including a
84
+ * socket rebuilt by a later `connect()`.
85
+ *
86
+ * Reconnecting stops only on `disconnect()` or when the token source refuses
87
+ * the credential (401/403).
88
+ */
60
89
  export declare class RealtimeClient {
61
90
  private socket;
62
91
  private client;
63
92
  private connectionPromise;
64
93
  private tokenProvider;
94
+ private backoff;
95
+ /** Every subscription, attached to each socket this client builds. */
96
+ private readonly listeners;
97
+ /** Conversation rooms to join on every connect. */
98
+ private readonly rooms;
99
+ /** connect() callers waiting on a socket that is reconnecting. */
100
+ private waiters;
101
+ private recoveryTimer;
102
+ private recoveryAttempts;
103
+ private credentialRefused;
104
+ /** Bumped by disconnect(), so a connect() still in flight does not revive a socket. */
105
+ private generation;
106
+ /**
107
+ * The socket whose first handshake a connect() is awaiting. Closing a socket
108
+ * that never connected makes socket.io emit nothing, so discardSocket()
109
+ * settles that connect() through this.
110
+ */
111
+ private pendingOpen;
65
112
  constructor(client: HttpClient);
66
113
  private fetchTokenWithClientKey;
114
+ /** A token for one reconnect attempt. Never throws: no token means the attempt is refused and retried. */
115
+ private mintToken;
67
116
  /**
68
117
  * Connects to the WebSocket server using a temporary WebSocket token.
118
+ * Resolves with the connected socket.
69
119
  *
70
- * Reconnect-safe by design:
71
- * - the connection promise is cleared after settling, so a later call
72
- * builds a fresh socket instead of returning a dead one;
73
- * - `connect_error` only tears down the INITIAL attempt — after the first
74
- * successful connect, socket.io's auto-reconnection owns recovery and
75
- * transient errors never disable it;
76
- * - auth uses socket.io's function form, so every (re)connection attempt
77
- * fetches a fresh token via `options.getToken` or the client's key.
120
+ * Safe to call as often as you like: a connected socket is returned as is,
121
+ * a socket that is reconnecting is waited on (the promise rejects if that
122
+ * attempt fails, while the client keeps retrying), and only a socket that
123
+ * has stopped for good is replaced.
78
124
  */
79
125
  connect(options?: RealtimeConnectOptions): Promise<Socket>;
126
+ private applyBackoff;
127
+ private openSocket;
128
+ /** Room rejoin, waiter settlement and recovery from the disconnects socket.io leaves alone. */
129
+ private watchLifecycle;
130
+ private scheduleRecovery;
131
+ /** Exponential backoff with jitter, bounded by reconnectionDelayMax. */
132
+ private recoveryDelay;
133
+ private waitForConnect;
134
+ private discardSocket;
135
+ /**
136
+ * Close the connection and stop reconnecting. Joined rooms are forgotten;
137
+ * listeners stay registered and attach to the next connection.
138
+ */
80
139
  disconnect(): void;
81
140
  getSocket(): Socket | null;
141
+ /**
142
+ * Listen for any server event, including the lifecycle events `connect`
143
+ * (initial and every reconnect: refetch what you may have missed) and
144
+ * `disconnect`. The listener stays attached across reconnects and socket
145
+ * replacement. Returns an unsubscribe function.
146
+ *
147
+ * Server events include `notification`, `feed_update`,
148
+ * `conversation_created`, `chat_message`, `chat_typing` and `agent_thinking`.
149
+ */
150
+ on<T = unknown>(event: string, listener: (payload: T) => void): () => void;
151
+ /** Join a conversation room now, and again after every reconnect, until you leave it. */
82
152
  joinConversation(conversationId: string): void;
83
153
  leaveConversation(conversationId: string): void;
84
154
  sendTyping(conversationId: string): void;