@recursiv/sdk 0.7.152 → 0.7.195
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/README.md +75 -5
- package/dist/index.d.ts +12 -7
- package/dist/index.js +6 -1
- package/dist/resources/alive.d.ts +61 -0
- package/dist/resources/alive.js +16 -0
- package/dist/resources/boosts.d.ts +110 -1
- package/dist/resources/boosts.js +80 -0
- package/dist/resources/deployments.d.ts +5 -1
- package/dist/resources/discovery.d.ts +5 -2
- package/dist/resources/evidence.d.ts +57 -2
- package/dist/resources/evidence.js +19 -0
- package/dist/resources/feeds.d.ts +63 -0
- package/dist/resources/feeds.js +12 -0
- package/dist/resources/protocols.d.ts +336 -12
- package/dist/resources/protocols.js +146 -4
- package/dist/resources/search.d.ts +71 -4
- package/dist/resources/settings.d.ts +3 -2
- package/dist/resources/settings.js +3 -2
- package/dist/types.d.ts +14 -1
- package/llm.md +37 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
68
68
|
| `r.databases` | `ensure`, `create`, `list`, `getCredentials`, `query` |
|
|
69
69
|
| `r.envVars` | `set`, `list`, `delete` (values write-only; secrets masked on read) |
|
|
70
70
|
| `r.projects` | `create`, `deploy`, `executeCode`, `createSandbox`, `stopSandbox`, `deploymentLogs` |
|
|
71
|
-
| `r.deployments` | Operator release coordination: `reserveRelease
|
|
71
|
+
| `r.deployments` | Operator release coordination: `reserveRelease` (optional initial-run `coordinator_identity_token` after compatible API rollout), `getRelease`, `advanceRelease`, `startRelease`, `finishRelease`, `recoverRelease`; follow the [shared release guide](../../docs/deploy/shared-releases.md) |
|
|
72
72
|
| `r.storage` | `ensureBucket`, `getUploadUrl`, `getDownloadUrl`, `listItems`, `deleteObject` |
|
|
73
73
|
| `r.telemetry` | `productCounts` — app-bound first-party aggregate counts; reviewed event names and counts only, retained at most 30 days |
|
|
74
74
|
| `r.sandbox` | `execute` (anonymous, no API key needed) |
|
|
@@ -96,9 +96,10 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
96
96
|
| Resource | Key methods |
|
|
97
97
|
|----------|------------|
|
|
98
98
|
| `r.posts` | `create`, `update`, `list`, `get`, `getMany(ids)` (up to 25 posts by id per request, no thread; a `Map` of each id's post or `NotFoundError`; 0.7.77), `liked`, `bookmarked`, `bookmark`, `unbookmark`, `search`, `replies`, `react` |
|
|
99
|
-
| `r.search` | `query` (blended search in sections; a thin answer steps down the search ladder, each item labelled `via`, the answer's `ladder` says how) |
|
|
99
|
+
| `r.search` | `query` (blended search in sections; a thin answer steps down the search ladder, each item labelled `via`, the answer's `ladder` says how). A visitor's search posts (`publicDiscovery.search`, `PublicSearchPage`) may carry `picture` (`SearchPicture`, 0.7.162): `kind`, `textHeavy`, `tileQuality` (0-3) and an optional `focal` point, layout hints from a background read of pictures the floors cleared, absent until judged and never a safety signal; on the `deep` stage `picture.showsQuery` (0.7.190) says whether the picture itself shows the query, absent unless the operator turned on `SEARCH_PICTURE_SUBJECT`. Both answers may carry `video_lead` (`SearchVideoLeadEntry[]`, 0.7.173): every clip in the order to lead and play it, the most about the words first, then the freshest, a Minds member's clip winning a tie |
|
|
100
100
|
| `r.bookmarks` | `save`, `unsave`, `posts`, `list`, `keys`, `merge` — the member's saved posts, open-network posts and articles, synced across devices; `collections`: `list`, `create`, `update`, `remove`, `add`, `removeItem`, `items`, `posts` — private named collections of saves (0.7.68, where `network.getConfig()` advertises `capabilities.bookmark_collections`) |
|
|
101
|
-
| `r.feeds` | `top` (what the member is most likely to engage with, rotated by what they saw, with open-network lanes and the lead story), `stories` (the story tail), `publicTop` (a visitor's top, keyless and edge-cacheable) |
|
|
101
|
+
| `r.feeds` | `top` (what the member is most likely to engage with, rotated by what they saw, with open-network lanes and the lead story), `stories` (the story tail), `publicTop` (a visitor's top, keyless and edge-cacheable), `firehose` (0.7.195: the member's live stream of the most engaged, viral and breaking posts, never repeated in a session) |
|
|
102
|
+
| `r.alive` | `tick({ followingSince?, posts?, thread? })` (0.7.193; the member's own app key, `users:read`; 404 `alive_disabled` until the operator sets `ALIVE_TICK_ENABLED`): whether anyone the member follows posted since the newest row they hold (`following.fresh`), the current counts of up to 30 posts on screen they may see, the new replies under the open post (their own left out), and `nextAfterMs` (when to tick next). Asked once; at most 4 a minute |
|
|
102
103
|
| `r.communities` | `create`, `join`, `search`, `members` |
|
|
103
104
|
| `r.chat` | `send`, `dm`, `createGroup` (`encrypted: true` for an end-to-end encrypted group, 0.7.59), `messages` (cursor paging), `acceptRequest`, `declineRequest`, `leave`, `deleteConversation`; a private group's admin: `addMembers`, `removeMember`, `updateGroup` (0.7.59); photos and voice notes: `uploadAttachment`, `signAttachments` (private chat storage, 0.7.82) |
|
|
104
105
|
| `r.tags` | `create`, `list` |
|
|
@@ -118,7 +119,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
118
119
|
| `r.settings` | User preferences (including app-scoped content choices; per-kind notification settings in `notifications.channels`, set one kind with `updateNotifications({ channels: { post_reaction: { push: false } } })`, 0.7.72), sessions (`revokeOtherSessions` keeps this device), password management, email change (`requestConfirmationCode` for accounts with no password), deactivation (`disableAccount({ password })`, 0.7.71; 404 on an API that does not serve it) |
|
|
119
120
|
| `r.billing` | Usage tracking, subscriptions, checkout |
|
|
120
121
|
| `r.appSubscriptions` | Consumer app plans: `checkout`, `status`, `createPortalSession`, `previewTierChange`, `changeTier` |
|
|
121
|
-
| `r.boosts` | Promoted posts: `create`, `mine`, `balance`, `pause`, `resume`, `cancel`, `recordEvent`, `topup`, `confirmTopup`; admin `listPendingReview`, `review`, `grant` |
|
|
122
|
+
| `r.boosts` | Promoted posts: `create`, `mine`, `balance`, `pause`, `resume`, `cancel`, `recordEvent`, `stats`, `topup`, `confirmTopup`, `topupWithTokens`; a feed page's boosts `slots` / `publicSlots` (splice with `spliceBoostSlots`); admin `listPendingReview`, `review`, `grant` |
|
|
122
123
|
| `r.wallet` | Wallet, MINDS tokens (`getTokenBalance`, `getTokenLedger`), a wallet the member holds linked by signature (`createLinkNonce`, `linkWallet`, `listLinkedWallets`, `unlinkWallet`), USD payouts (`getPayouts`, `startPayoutOnboarding`, `payoutLoginLink`) |
|
|
123
124
|
| `r.notifications` | Notification stream (`list`, `unreadCount`, `markAsRead`, `archive`, `markAllAsRead`; `category: 'mentions'` for mentions and replies only, 0.7.72) and push tokens |
|
|
124
125
|
| `r.github` | GitHub integration |
|
|
@@ -130,7 +131,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
130
131
|
| `r.goals` | Org goals with task rollups (group dispatcher tasks) |
|
|
131
132
|
| `r.media` | `sourceApprovals({ projectId, sources })` — cached public host/purpose judgments and exact owned hosts; no caller-triggered provider fetch or inference. Image/icon requests stay relayed; direct players use approved, unexpired decisions once enforcement is active |
|
|
132
133
|
| `r.linkPreview` | `get(url, source?, { projectId })` opts into expiring relayed image/icon capabilities; refresh before `media_expires_at`, and preserve source authorization. `get(url)` — a public link's Open Graph card (`data: null` when it has none). For a chat link pass `{ messageId }` or `{ conversationId }` on a signed-in key with `chat:read`: the link is fetched only when it is in the named message and a person wrote that message, or the caller wrote it in that conversation, else `refused: 'ai_link'`. A source with no id rejects (`ValidationError`). Not in encrypted chats: the server cannot read them, so leave `source` out there and apply the app's own rule |
|
|
133
|
-
| `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?, replies?: 'none' })` (`replies: 'none'`, 0.7.78: the post alone for a card, with `repliesStatus: 'not_requested'`; `getPublicConversation` and `getConnectedSocialConversation` take it too). 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`; a Fediverse community's newest threads, read-only (0.7.109): `getOpenGroupThreads({ group, limit?, cursor?, compass? })`, `group` being the `actor` of a groups read's `open_network` entry; radar stories: `getPublicRadarStory` (one story by id with its posts; one that left the radar within its minimum lifetime, or within the last half hour, still answers live with `liveUntil` and the story that continues it; one that has left for longer comes with its archived copy and the live story it continues as; the id may be a World Today edition story's, and the answer then names it in `editionStory` under the story's radar id; a story a World Today story seeded carries `volume`, the first page of the posts that story counts across Minds and the open networks, whose `cursor` goes on with `curator.storyPosts` or `curator.memberStoryPosts`), keyless `getSharedRadarStory(projectId, { cluster })` and `getSharedRadarPosts(projectId, { cluster })` (keyless reads carry images and videos only from outlets and members marked `visitorMedia`; signed-in reads keep all media, so a share card uses only those); the Viral read (fastest-moving posts across Bluesky, the Fediverse, Nostr and Minds, each against its own network's pace; 0.7.59): `getPublicViral({ network?, category?, media?: 'video', limit?: 5 | 10 | 20 | 40, cursor?, compass? })` under the member's key and keyless `getSharedViral(projectId, params)` (visitors: `compass` `all` or `hide` only; a visitor's `media: 'video'` read can carry items whose video the server withheld, so filter with the exported `viralItemHasVideo` before a video player; `item.post` narrows on `item.protocol`). `status: 'off'` resolves with no items until the app enables the read, and `getSharedViral` also resolves an older API's 401 `missing_api_key` as off; `getPublicViral` throws every 401 and 403, so a session failure is never read as off; 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` |
|
|
134
|
+
| `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?, replies?: 'none' })` (`replies: 'none'`, 0.7.78: the post alone for a card, with `repliesStatus: 'not_requested'`; `getPublicConversation` and `getConnectedSocialConversation` take it too). 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`; a Fediverse community's newest threads, read-only (0.7.109): `getOpenGroupThreads({ group, limit?, cursor?, compass? })`, `group` being the `actor` of a groups read's `open_network` entry; radar stories: `getPublicRadarStory` (one story by id with its posts; one that left the radar within its minimum lifetime, or within the last half hour, still answers live with `liveUntil` and the story that continues it; one that has left for longer comes with its archived copy and the live story it continues as; the id may be a World Today edition story's, and the answer then names it in `editionStory` under the story's radar id; a story a World Today story seeded carries `volume`, the first page of the posts that story counts across Minds and the open networks, whose `cursor` goes on with `curator.storyPosts` or `curator.memberStoryPosts`), keyless `getSharedRadarStory(projectId, { cluster })` and `getSharedRadarPosts(projectId, { cluster })` (keyless reads carry images and videos only from outlets and members marked `visitorMedia`; signed-in reads keep all media, so a share card uses only those); keyless category surface (0.7.165): `getSharedCategorySurface(projectId, { category, compass? })`, a category's `stories`, `network` and `clips` for a signed-out page in one read under every visitor floor (`compass` `all` or `hide`, or a side or Mix where the visitor catalog lists `compass_sides`, answered `unavailable`; never people or groups); the Viral read (fastest-moving posts across Bluesky, the Fediverse, Nostr and Minds, each against its own network's pace; 0.7.59): `getPublicViral({ network?, category?, media?: 'video', limit?: 5 | 10 | 20 | 40, cursor?, compass? })` under the member's key and keyless `getSharedViral(projectId, params)` (visitors: `compass` `all` or `hide` only; a visitor's `media: 'video'` read can carry items whose video the server withheld, so filter with the exported `viralItemHasVideo` before a video player; `item.post` narrows on `item.protocol`). `status: 'off'` resolves with no items until the app enables the read, and `getSharedViral` also resolves an older API's 401 `missing_api_key` as off; `getPublicViral` throws every 401 and 403, so a session failure is never read as off; 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` |
|
|
134
135
|
|
|
135
136
|
Full reference: see [llm.md](./llm.md) (ships with this package) or the type definitions in `dist/`.
|
|
136
137
|
|
|
@@ -657,8 +658,67 @@ for (const network of data.networks) {
|
|
|
657
658
|
await r.protocols.setNetwork('nostr', { enabled: false, removePast: true });
|
|
658
659
|
```
|
|
659
660
|
|
|
661
|
+
One-tap actions act as the member's own identity on that network by default (0.7.191). `engageLike`,
|
|
662
|
+
`engageRepost`, `engageFollow`, `engageReply` and `engageQuote` take `identity?: 'native' | 'linked'`. A
|
|
663
|
+
native answer is sent (`queued: false`, with the network's `delivery`) or, while the identity is still
|
|
664
|
+
being set up, queued (202, `queued: true`, sent in order once it is on; `pendingInteractions()` lists
|
|
665
|
+
them). A linked answer is the review to submit, as `prepareNativeLike` always returned. Every answer
|
|
666
|
+
says who acted (`actedAs`). A member who linked an account before the cutover keeps acting as it until they
|
|
667
|
+
choose otherwise with `setEngageDefault(network, 'native')`; the first such answer carries
|
|
668
|
+
`notice: 'engage_default_linked'`. An account linked later is a choice: `setEngageDefault(network, 'linked')`.
|
|
669
|
+
Keep the same `clientMutationId` across retries: a retry is answered from the first tap, never sent twice
|
|
670
|
+
(once that tap expired unsent, with `delivery.code` `interaction_expired`; a new tap takes a new id). A native
|
|
671
|
+
reply's or quote's `media` takes only the member's own Minds uploads, as the linked flows do.
|
|
672
|
+
|
|
673
|
+
```ts
|
|
674
|
+
const { data } = await r.protocols.engageLike({ protocol: 'bluesky', nativeId: post.nativeId, clientMutationId, action: 'like' });
|
|
675
|
+
if (data.identity === 'native') showActedAs(data.actedAs, data.queued ? 'Sending when your account is ready' : null);
|
|
676
|
+
else await r.protocols.submitNativeLike(data.id, { approve: true });
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
A member's AT Protocol account is created on the PDS Minds runs, with their verified email (0.7.191); Minds keeps only a
|
|
680
|
+
revocable app password named "Minds". `claimAtprotoPassword({ password })` (or `{ emailCode }` from
|
|
681
|
+
`POST /settings/confirmation-code` with purpose `atproto_password`, for an account with no password) has the PDS
|
|
682
|
+
email a reset code to that address, so the member can sign in from any AT Protocol app and revoke Minds there.
|
|
683
|
+
A member without a verified email reads `needs_action` with reason `needs_verified_email` on AT Protocol.
|
|
684
|
+
|
|
685
|
+
```ts
|
|
686
|
+
const { data } = await r.protocols.claimAtprotoPassword({ password });
|
|
687
|
+
show(`We sent a reset code for ${data.handle} to ${data.sentTo}`);
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
AT Protocol reads `needs_action` with reason `needs_atproto_grant` for an account made before Minds ran it natively,
|
|
691
|
+
and `error` with `app_password_revoked` after the member revoked Minds' app password. `grantAtproto({ password })`
|
|
692
|
+
(0.7.191), with that account's password (or a non-privileged app password the member made), lets Minds act as it again:
|
|
693
|
+
Minds keeps only a new revocable app password, and answers the handle and the presence after the grant.
|
|
694
|
+
|
|
695
|
+
```ts
|
|
696
|
+
const { data } = await r.protocols.grantAtproto({ password: atPassword });
|
|
697
|
+
if (data.presence.state === 'on') show(`Minds acts as ${data.handle} again`);
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
A member can take their Minds-held Nostr key home, in three steps of their own:
|
|
701
|
+
`protocols.exportNostrKey({ password })` returns it as an `nsec` (an account with no password
|
|
702
|
+
sends `{ emailCode }` from `settings.requestConfirmationCode('nostr_key')`); after they
|
|
703
|
+
import it into their signer, `nostrRebindChallenge()` and `rebindNostrKey(signedEvent)`
|
|
704
|
+
prove the device holds the same key; then `deleteManagedNostrCopy({ password })` deletes
|
|
705
|
+
Minds' copy, and every later Nostr action is signed on their device. What Minds published
|
|
706
|
+
with the key still comes down when they delete a post or their account (Minds signs those
|
|
707
|
+
takedowns before the copy goes; 409 `too_many_published` keeps the copy when there is too
|
|
708
|
+
much). Show the `nsec` to the member alone and never log it. None of these is retried
|
|
709
|
+
automatically.
|
|
710
|
+
|
|
660
711
|
### Native Nostr signing
|
|
661
712
|
|
|
713
|
+
A member's Nostr key is either their own, signed on their device, or one Minds holds for them (0.7.192).
|
|
714
|
+
`nativeNostrAccount()` says which: `signing: 'client'` is the flow below; `signing: 'server'` (with
|
|
715
|
+
`mode: 'managed'`) means Minds signs. Then `prepareNativeNostr` is the preview to show (nothing is signed
|
|
716
|
+
or sent), and `prepareNativeNostr(id, { ...input, send: true })` once the member approves signs and sends
|
|
717
|
+
in that call and answers with the `receipt` (nothing to submit). A like, repost or follow review is submitted with
|
|
718
|
+
`{ approve: true }` and no `event`, and `engageLike`, `engageReply`, `engageFollow` and the rest with
|
|
719
|
+
`identity: 'native'` act as that key in one tap. For a key Minds holds, a like or repost Minds is still sending (the
|
|
720
|
+
relay has not taken it yet) reads as liked or reposted with `acknowledged: false`, and an unlike or unrepost removes it.
|
|
721
|
+
|
|
662
722
|
Use `protocols.nativeNostrAccount()` to check the app's explicit native-write
|
|
663
723
|
capability. For an enabled connected key, prepare a text post with
|
|
664
724
|
`prepareNativeNostr(identityId, { action: 'publish', content })`, show its
|
|
@@ -959,6 +1019,16 @@ is a visitor's top (safe items only, the same for every visitor in one 15-minute
|
|
|
959
1019
|
read with no credential so the edge can hold it. Each answers 404 while the app's operator
|
|
960
1020
|
has it off. Send `block: 'top'` and the item's position with a visible view of a top item.
|
|
961
1021
|
|
|
1022
|
+
`sdk.feeds.firehose({ session, limit?, compass?, network? })` (0.7.195) is the member's live
|
|
1023
|
+
stream: the next items of the most engaged, viral and breaking posts of Minds and the open
|
|
1024
|
+
networks, re-checked for the member on the server and never sent twice in one `session`. Each
|
|
1025
|
+
item carries `network`, `state` (`breaking`, `viral` or null), `publishedAt`, `chosenAt`, an
|
|
1026
|
+
in-app `target` and, for an open-network post, a `card`. Reveal them one at a time and read
|
|
1027
|
+
again no sooner than `meta.refillAfterMs`; remove the refs in `retract` wherever you hold them.
|
|
1028
|
+
404 while the app's operator has it off; 429 and 503 carry Retry-After. A Mix or Choose sides `compass`
|
|
1029
|
+
spends one of the member's hourly sided Politics reads at most once per `session` and choice in ten
|
|
1030
|
+
minutes, and answers 429 `compass_rate_limited` once those are spent.
|
|
1031
|
+
|
|
962
1032
|
A feed session opens with it when asked: `createFeed({ networks, top: { ref, session? }, seen,
|
|
963
1033
|
seenClusters?, bucket? })` (or `new DiscoveryFeedSession(..., { top: { ref, read, post? }, seen })`
|
|
964
1034
|
with your own readers). The top's read starts with the first page's reads, and the top holds
|
package/dist/index.d.ts
CHANGED
|
@@ -68,6 +68,7 @@ import { LinkPreviewResource } from './resources/link-preview.js';
|
|
|
68
68
|
import { SearchResource } from './resources/search.js';
|
|
69
69
|
import { BookmarksResource } from './resources/bookmarks.js';
|
|
70
70
|
import { FeedsResource } from './resources/feeds.js';
|
|
71
|
+
import { AliveResource } from './resources/alive.js';
|
|
71
72
|
import { AccountsResource } from './resources/accounts.js';
|
|
72
73
|
import { SignalsResource } from './resources/signals.js';
|
|
73
74
|
import { SealedResource } from './resources/sealed.js';
|
|
@@ -133,6 +134,8 @@ export declare class Recursiv {
|
|
|
133
134
|
readonly discovery: DiscoveryResource;
|
|
134
135
|
/** The top of a feed: what the member (or a visitor) is most likely to engage with, rotated by what they have seen. */
|
|
135
136
|
readonly feeds: FeedsResource;
|
|
137
|
+
/** The alive tick: whether people the member follows posted, current counts on screen, new replies (0.7.193). */
|
|
138
|
+
readonly alive: AliveResource;
|
|
136
139
|
readonly video: VideoResource;
|
|
137
140
|
readonly appSubscriptions: AppSubscriptionsResource;
|
|
138
141
|
readonly boosts: BoostsResource;
|
|
@@ -182,7 +185,7 @@ export type { E2eeAccountReset, E2eeDevice, E2eeDevicesRealtimeEvent, E2eeEnvelo
|
|
|
182
185
|
export { ProjectsResource } from './resources/projects.js';
|
|
183
186
|
export { AgentsResource, SUPPORTED_MODELS, AGENT_DIRECTORY_SORTS, AGENT_DIRECTORY_MAX_LIMIT } from './resources/agents.js';
|
|
184
187
|
export { EvidenceResource } from './resources/evidence.js';
|
|
185
|
-
export type { EvidenceTarget, EvalType, CreateEvalInput, SimulateInput, SimulateResult, EvalRunRow, EvalResultRow, EvalRunDetail, EvidenceSummary, EvidenceEvent, EvidenceRecordDetail } from './resources/evidence.js';
|
|
188
|
+
export type { EvidenceTarget, EvalType, CreateEvalInput, SimulateInput, SimulateResult, EvalRunRow, EvalResultRow, EvalRunDetail, EvidenceSummary, EvidenceEvent, EvidenceRecordDetail, CreateEvalSetInput, EvalSetRow, EvalRunExport } from './resources/evidence.js';
|
|
186
189
|
export type { AgentMessage, AgentMessageInput, AgentInboxParams, AgentAskInput, AgentAskResult, SupportedModel, SalesLead, SalesLeadListParams, SalesLeadStatus, AgentDirectorySort, AgentDirectoryParams, AgentDirectoryEntry, AgentDirectoryMeta, AgentDirectoryPage } from './resources/agents.js';
|
|
187
190
|
export { TagsResource } from './resources/tags.js';
|
|
188
191
|
export { SandboxResource } from './resources/sandbox.js';
|
|
@@ -205,7 +208,7 @@ export { EnvVarsResource } from './resources/env-vars.js';
|
|
|
205
208
|
export type { QueryDatabaseInput, QueryResult } from './resources/databases.js';
|
|
206
209
|
export { GitHubResource } from './resources/github.js';
|
|
207
210
|
export { DeploymentsResource } from './resources/deployments.js';
|
|
208
|
-
export type { DeploymentReleaseInput, DeploymentRelease, DeploymentReleaseOperation, DeploymentReleaseRecoveryInput } from './resources/deployments.js';
|
|
211
|
+
export type { DeploymentReleaseInput, DeploymentReleaseReservationInput, DeploymentRelease, DeploymentReleaseOperation, DeploymentReleaseRecoveryInput } from './resources/deployments.js';
|
|
209
212
|
export type { PrepareProtocolServersInput, PreparedProtocolServers, ProtocolServerPreparation, ProtocolServerUpgradePreview, ProtocolServerUpgradeInput, ProtocolServerUpgradeStatus } from './resources/deployments.js';
|
|
210
213
|
export { IntegrationsResource } from './resources/integrations.js';
|
|
211
214
|
export type { ExecuteToolInput, ExecuteToolResult } from './resources/integrations.js';
|
|
@@ -229,10 +232,12 @@ export { TrustResource } from './resources/trust.js';
|
|
|
229
232
|
export type { TrustEnvelope, OwnTrustEvent, TrustPublicKey, OwnTrustEvents } from './resources/trust.js';
|
|
230
233
|
export { LinkPreviewResource } from './resources/link-preview.js';
|
|
231
234
|
export { SEARCH_MEDIA_KINDS, SEARCH_SECTIONS, SearchResource } from './resources/search.js';
|
|
232
|
-
export type { PublicSearchPage, PublicSearchTab, SearchAnswer, SearchGroup, SearchLadder, SearchOmitReason, SearchParams, SearchPerson, SearchPost, SearchRelated, SearchResponse, SearchSection, SearchStage, SearchStory, SearchTopic, SearchVia, SearchMedia, SearchMediaEmbed, SearchMediaItem, SearchMediaKind, SearchMediaProvider, SearchMediaProviderStatus, SearchMediaSource, } from './resources/search.js';
|
|
235
|
+
export type { PublicSearchPage, PublicSearchTab, SearchAnswer, SearchGroup, SearchLadder, SearchOmitReason, SearchParams, SearchPerson, SearchPicture, SearchPost, SearchRelated, SearchResponse, SearchSection, SearchStage, SearchStory, SearchTopic, SearchVia, SearchVideoLeadEntry, SearchVideoLeadSource, SearchMedia, SearchMediaEmbed, SearchMediaItem, SearchMediaKind, SearchMediaProvider, SearchMediaProviderStatus, SearchMediaSource, } from './resources/search.js';
|
|
233
236
|
export { BOOKMARK_MERGE_MAX_ITEMS, BookmarkCollectionsResource, BookmarksResource } from './resources/bookmarks.js';
|
|
234
237
|
export { FEED_TOP_NETWORKS, FeedsResource } from './resources/feeds.js';
|
|
235
|
-
export
|
|
238
|
+
export { AliveResource } from './resources/alive.js';
|
|
239
|
+
export type { AliveTick, AliveTickCounts, AliveTickParams } from './resources/alive.js';
|
|
240
|
+
export type { FeedFirehoseItem, FeedFirehoseMeta, FeedFirehoseNetwork, FeedFirehoseParams, FeedFirehoseResponse, FeedStoriesParams, FeedStoriesResponse, FeedStory, FeedTopExplain, FeedTopItem, FeedTopMeta, FeedTopNetwork, FeedTopNetworkCard, FeedTopNetworkEntry, FeedTopNetworkMap, FeedTopParams, FeedTopResponse, FeedTopTarget, PublicFeedTopMeta, PublicFeedTopParams, PublicFeedTopResponse, } from './resources/feeds.js';
|
|
236
241
|
export type { BookmarkCollection, BookmarkCollectionInput, BookmarkCollectionKind, BookmarkCollectionPatch, BookmarkCollectionsList, BookmarkCollectionTarget, BookmarkCollectionVisibility, BookmarkedPost, BookmarkInput, BookmarkItem, BookmarkKey, BookmarkKeyRow, BookmarkKeysPage, BookmarkKind, BookmarkMergeItem, BookmarkMergeResult, BookmarkProtocol, BookmarkRequestOptions, BookmarksPage, FiledBookmark, RemovedBookmarkCollection, SavedBookmark, UnfiledBookmark, UnsavedBookmark, } from './resources/bookmarks.js';
|
|
237
242
|
export { AccountsResource } from './resources/accounts.js';
|
|
238
243
|
export { SIGNAL_BATCH_MAX, SignalsResource, newClientEventId } from './resources/signals.js';
|
|
@@ -249,11 +254,11 @@ export { UploadsResource } from './resources/uploads.js';
|
|
|
249
254
|
export type { UploadMediaInput, UploadUrlInput, UploadUrlResult } from './resources/uploads.js';
|
|
250
255
|
export { WalletResource } from './resources/wallet.js';
|
|
251
256
|
export type { LinkedTokenWallet, PayoutState, TokenBalance, TokenLedgerEntry, WalletLink, WalletLinkNonce } from './resources/wallet.js';
|
|
252
|
-
export { BoostsResource } from './resources/boosts.js';
|
|
253
|
-
export type { BoostBalance, BoostBalanceResponse, BoostCampaign, BoostCampaignResponse, BoostEventResult, BoostLedgerEntry, BoostLedgerKind, BoostPlanCredit, BoostRejectionReason, BoostReviewStatus, BoostStatus, BoostTopupCheckout, BoostTopupConfirmation, BoostTopupLimits, } from './resources/boosts.js';
|
|
257
|
+
export { BoostsResource, spliceBoostSlots } from './resources/boosts.js';
|
|
258
|
+
export type { BoostBalance, BoostBalanceResponse, BoostCampaign, BoostCampaignResponse, BoostCampaignStats, BoostDailyStats, BoostEventResult, BoostLedgerEntry, BoostLedgerKind, BoostPlanCredit, BoostRejectionReason, BoostReviewStatus, BoostSlotItem, BoostSlotSurface, BoostSlotsParams, BoostSlotsResponse, BoostStatus, BoostTopupCheckout, BoostTopupConfirmation, BoostTopupLimits, BoostTokenTopupInfo, BoostTokenTopupResult, PublicBoostSlotsParams, } from './resources/boosts.js';
|
|
254
259
|
export { ProtocolsResource } from './resources/protocols.js';
|
|
255
260
|
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, SOCIAL_FOLLOWING_SOURCE_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
|
|
256
|
-
export type { SocialProfile, SocialBridge, SocialMention, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialRadar, SocialRadarCluster, SocialRadarMember, SocialRadarParams, SocialRadarSourceKind, SocialRadarPosts, SocialRadarStory, SocialRadarStoryArchive, ViralBaseline, ViralItem, ViralItemFields, ViralItemSpread, ViralItemVelocity, ViralLabel, ViralMindsCard, ViralMindsItem, ViralNetwork, ViralOpenProtocol, ViralProtocol, ViralProvider, ViralReadMeta, ViralReadParams, ViralReadResponse, ViralReadStatus, ViralRef, ViralSocialItem, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendSourceIndex, SocialTrendFeed, SocialPopularProfiles, SocialPopularProfile, SocialPopularProfilesParams, SocialPopularProfilesProtocol, SocialPopularProfilesSource, SocialAuthorFeed, OpenGroupThreads, OpenGroupThreadsGroup, OpenGroupThreadsParams, SocialFollowingFeed, SocialFollowingSource, SocialFollowingSourceStatus, SearchPublicProfilesParams, SearchPublicPostsParams, SocialPostSearch, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeNetwork, NativeNetworkState, NativeNetworkPresence, NativeNetworkActivation, NativeNetworkOff, SetNativeNetworkInput, NativeSocialCallbackInput, NativeReplyPrepareInput, NativePostPrepareInput, NativeMediaInput, NativeMediaItem, NativePostBatch, NativePostQuote, 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, ProtocolIngestionActivityReason, ProtocolIngestionCircuitHealth, ProtocolIngestionDeadLetterGroup, ProtocolIngestionHealthPosition, ProtocolIngestionHealthReport, ProtocolIngestionHealthRuntime, ProtocolIngestionHealthSection, ProtocolIngestionLaneActivity, ProtocolIngestionLaneCurrentJob, ProtocolIngestionLaneDeadLetters, ProtocolIngestionLaneHealth, ProtocolIngestionLaneJobs, ProtocolIngestionReplayResult, ProtocolIngestionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, ReplayProtocolIngestionJobInput, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
|
|
261
|
+
export type { SocialProfile, SocialBridge, SocialMention, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialRadar, SocialRadarCluster, SocialRadarMember, SocialRadarParams, SocialRadarSourceKind, SocialRadarPosts, SocialRadarStory, SharedCategorySurface, SharedCategorySurfaceParams, SocialRadarStoryArchive, ViralBaseline, ViralItem, ViralItemFields, ViralItemSpread, ViralItemVelocity, ViralLabel, ViralMindsCard, ViralMindsItem, ViralNetwork, ViralOpenProtocol, ViralProtocol, ViralProvider, ViralReadMeta, ViralReadParams, ViralReadResponse, ViralReadStatus, ViralRef, ViralSocialItem, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendSourceIndex, SocialTrendFeed, SocialPopularProfiles, SocialPopularProfile, SocialPopularProfilesParams, SocialPopularProfilesProtocol, SocialPopularProfilesSource, SocialAuthorFeed, OpenGroupThreads, OpenGroupThreadsGroup, OpenGroupThreadsParams, SocialFollowingFeed, SocialFollowingSource, SocialFollowingSourceStatus, SearchPublicProfilesParams, SearchPublicPostsParams, SocialPostSearch, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeNetwork, NativeNetworkState, NativeNetworkPresence, NativeNetworkActivation, NativeNetworkOff, SetNativeNetworkInput, AtprotoPasswordClaimProof, AtprotoPasswordClaim, AtprotoGrant, EngageIdentity, EngageActedAs, EngageLinkedFields, NativeEngageSent, NativeEngageQueued, EngageAnswer, PendingNativeInteraction, EngageOneInput, NostrKeyStepUp, ManagedNostrKeyExport, NostrRebindChallenge, NostrRebindResult, ManagedNostrCopyDeleted, NativeSocialCallbackInput, NativeReplyPrepareInput, NativePostPrepareInput, NativeMediaInput, NativeMediaItem, NativePostBatch, NativePostQuote, 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, ProtocolIngestionActivityReason, ProtocolIngestionCircuitHealth, ProtocolIngestionDeadLetterGroup, ProtocolIngestionHealthPosition, ProtocolIngestionHealthReport, ProtocolIngestionHealthRuntime, ProtocolIngestionHealthSection, ProtocolIngestionLaneActivity, ProtocolIngestionLaneCurrentJob, ProtocolIngestionLaneDeadLetters, ProtocolIngestionLaneHealth, ProtocolIngestionLaneJobs, ProtocolIngestionReplayResult, ProtocolIngestionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, ReplayProtocolIngestionJobInput, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
|
|
257
262
|
export { InboxResource } from './resources/inbox.js';
|
|
258
263
|
export { NetworkResource } from './resources/network.js';
|
|
259
264
|
export { SimulatorResource } from './resources/simulator.js';
|
package/dist/index.js
CHANGED
|
@@ -69,6 +69,7 @@ import { LinkPreviewResource } from './resources/link-preview.js';
|
|
|
69
69
|
import { SearchResource } from './resources/search.js';
|
|
70
70
|
import { BookmarksResource } from './resources/bookmarks.js';
|
|
71
71
|
import { FeedsResource } from './resources/feeds.js';
|
|
72
|
+
import { AliveResource } from './resources/alive.js';
|
|
72
73
|
import { AccountsResource } from './resources/accounts.js';
|
|
73
74
|
import { SignalsResource } from './resources/signals.js';
|
|
74
75
|
import { SealedResource } from './resources/sealed.js';
|
|
@@ -134,6 +135,8 @@ export class Recursiv {
|
|
|
134
135
|
discovery;
|
|
135
136
|
/** The top of a feed: what the member (or a visitor) is most likely to engage with, rotated by what they have seen. */
|
|
136
137
|
feeds;
|
|
138
|
+
/** The alive tick: whether people the member follows posted, current counts on screen, new replies (0.7.193). */
|
|
139
|
+
alive;
|
|
137
140
|
video;
|
|
138
141
|
appSubscriptions;
|
|
139
142
|
boosts;
|
|
@@ -212,6 +215,7 @@ export class Recursiv {
|
|
|
212
215
|
this.jobs = new JobsResource(client);
|
|
213
216
|
this.curator = new CuratorResource(client);
|
|
214
217
|
this.feeds = new FeedsResource(client);
|
|
218
|
+
this.alive = new AliveResource(client);
|
|
215
219
|
this.discovery = new DiscoveryResource(this.posts, this.protocols, this.curator, client, this.feeds);
|
|
216
220
|
this.video = new VideoResource(client);
|
|
217
221
|
this.appSubscriptions = new AppSubscriptionsResource(client);
|
|
@@ -287,6 +291,7 @@ export { LinkPreviewResource } from './resources/link-preview.js';
|
|
|
287
291
|
export { SEARCH_MEDIA_KINDS, SEARCH_SECTIONS, SearchResource } from './resources/search.js';
|
|
288
292
|
export { BOOKMARK_MERGE_MAX_ITEMS, BookmarkCollectionsResource, BookmarksResource } from './resources/bookmarks.js';
|
|
289
293
|
export { FEED_TOP_NETWORKS, FeedsResource } from './resources/feeds.js';
|
|
294
|
+
export { AliveResource } from './resources/alive.js';
|
|
290
295
|
export { AccountsResource } from './resources/accounts.js';
|
|
291
296
|
export { SIGNAL_BATCH_MAX, SignalsResource, newClientEventId } from './resources/signals.js';
|
|
292
297
|
export { SEALED_ALLOWANCE_REMAINING_HEADER, SEALED_REFUSAL_HEADER, SealedResource, SealedTransportError, SEALED_WEB_OFF, isSealedWebOff, } from './resources/sealed.js';
|
|
@@ -295,7 +300,7 @@ export { ProjectSettingsResource } from './resources/project-settings.js';
|
|
|
295
300
|
export { OrganizationSecurityResource } from './resources/organization-security.js';
|
|
296
301
|
export { UploadsResource } from './resources/uploads.js';
|
|
297
302
|
export { WalletResource } from './resources/wallet.js';
|
|
298
|
-
export { BoostsResource } from './resources/boosts.js';
|
|
303
|
+
export { BoostsResource, spliceBoostSlots } from './resources/boosts.js';
|
|
299
304
|
export { ProtocolsResource } from './resources/protocols.js';
|
|
300
305
|
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, SOCIAL_FOLLOWING_SOURCE_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
|
|
301
306
|
export { InboxResource } from './resources/inbox.js';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { HttpClient } from '../client.js';
|
|
2
|
+
/**
|
|
3
|
+
* The alive tick (0.7.193): one calm read for the member, with their own key of the app, that says whether anyone they
|
|
4
|
+
* follow has posted since the newest row they hold, keeps the counts of the posts on their screen current, and counts
|
|
5
|
+
* the new replies under the post they have open. Off until the operator turns on `ALIVE_TICK_ENABLED`: the read then
|
|
6
|
+
* throws `NotFoundError` (code `alive_disabled`), and the app stops ticking.
|
|
7
|
+
*
|
|
8
|
+
* Tick again after `nextAfterMs` (the server slows every client this way), only while the page is visible. One tick
|
|
9
|
+
* carries every open screen's interests. A tick is asked once (`retry: false`): the next tick is its retry. More than
|
|
10
|
+
* 4 a minute for one member throws `RateLimitError`.
|
|
11
|
+
*/
|
|
12
|
+
/** What one tick asks about. Each part is answered only when asked for. */
|
|
13
|
+
export interface AliveTickParams {
|
|
14
|
+
/** The newest row the member holds on Following (a Date or an ISO 8601 instant). */
|
|
15
|
+
followingSince?: Date | string;
|
|
16
|
+
/** Ids of the Minds posts on screen, at most 30 (more is refused). */
|
|
17
|
+
posts?: readonly string[];
|
|
18
|
+
/** The open post's id and the newest reply the member holds under it (or when the thread was loaded). */
|
|
19
|
+
thread?: {
|
|
20
|
+
id: string;
|
|
21
|
+
since: Date | string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** A post's numbers, as its card shows them. */
|
|
25
|
+
export interface AliveTickCounts {
|
|
26
|
+
score: number;
|
|
27
|
+
upvote_count: number;
|
|
28
|
+
reply_count: number;
|
|
29
|
+
reposts_count: number;
|
|
30
|
+
}
|
|
31
|
+
export interface AliveTick {
|
|
32
|
+
/**
|
|
33
|
+
* Whether anyone the member follows posted a top-level Minds post after `followingSince` that they may be served
|
|
34
|
+
* (their blocks, mutes and safety setting applied), and when the newest of them was written. Load the new rows behind
|
|
35
|
+
* the new-posts pill; never move what the member is reading.
|
|
36
|
+
*/
|
|
37
|
+
following?: {
|
|
38
|
+
fresh: boolean;
|
|
39
|
+
newestAt: string | null;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The current numbers of the posts asked for that the member may be served, by post id. A post left out (a repost,
|
|
43
|
+
* a reply, one the member may not be served) keeps the number the app has.
|
|
44
|
+
*/
|
|
45
|
+
counts?: Record<string, AliveTickCounts>;
|
|
46
|
+
/** How many replies under the open post the member may see were written after `thread.since`, their own left out. */
|
|
47
|
+
thread?: {
|
|
48
|
+
newReplies: number;
|
|
49
|
+
newestAt: string | null;
|
|
50
|
+
};
|
|
51
|
+
/** When to tick next, in milliseconds. */
|
|
52
|
+
nextAfterMs: number;
|
|
53
|
+
/** When the server read it. */
|
|
54
|
+
asOf: string;
|
|
55
|
+
}
|
|
56
|
+
export declare class AliveResource {
|
|
57
|
+
private client;
|
|
58
|
+
constructor(client: HttpClient);
|
|
59
|
+
/** One tick for the member (GET /alive/tick, `users:read`, their own key of the app). */
|
|
60
|
+
tick(params?: AliveTickParams): Promise<AliveTick>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const iso = (value) => (value instanceof Date ? value.toISOString() : value);
|
|
2
|
+
export class AliveResource {
|
|
3
|
+
client;
|
|
4
|
+
constructor(client) {
|
|
5
|
+
this.client = client;
|
|
6
|
+
}
|
|
7
|
+
/** One tick for the member (GET /alive/tick, `users:read`, their own key of the app). */
|
|
8
|
+
tick(params = {}) {
|
|
9
|
+
return this.client.get('/alive/tick', {
|
|
10
|
+
following_since: params.followingSince === undefined ? undefined : iso(params.followingSince),
|
|
11
|
+
posts: params.posts?.length ? params.posts.join(',') : undefined,
|
|
12
|
+
thread: params.thread?.id,
|
|
13
|
+
thread_since: params.thread ? iso(params.thread.since) : undefined,
|
|
14
|
+
}, { retry: false });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { HttpClient } from '../client.js';
|
|
2
|
-
import type { PaginatedResponse, SingleResponse } from '../types.js';
|
|
2
|
+
import type { PaginatedResponse, Post, SingleResponse } from '../types.js';
|
|
3
3
|
/** Campaign lifecycle axis. */
|
|
4
4
|
export type BoostStatus = 'active' | 'paused' | 'completed' | 'refunded';
|
|
5
5
|
/** Campaign moderation axis. A campaign delivers only when `active` AND `approved`. */
|
|
@@ -59,12 +59,30 @@ export interface BoostPlanCredit {
|
|
|
59
59
|
*/
|
|
60
60
|
owed_micros?: number;
|
|
61
61
|
}
|
|
62
|
+
/** Paying for Boost with tokens. */
|
|
63
|
+
export interface BoostTokenTopupInfo {
|
|
64
|
+
/** False until the platform sets the price of a token. */
|
|
65
|
+
available: boolean;
|
|
66
|
+
/** Micro-USD of Boost balance one token buys; null when unavailable. */
|
|
67
|
+
usd_micros_per_token: number | null;
|
|
68
|
+
/** Most whole tokens one conversion takes. */
|
|
69
|
+
max_tokens: number;
|
|
70
|
+
}
|
|
71
|
+
export interface BoostTokenTopupResult {
|
|
72
|
+
/** False when this request_id was already credited: nothing new was written. */
|
|
73
|
+
applied: boolean;
|
|
74
|
+
tokens: number;
|
|
75
|
+
credited_micros: number;
|
|
76
|
+
balance_micros: number;
|
|
77
|
+
}
|
|
62
78
|
export interface BoostBalanceResponse extends SingleResponse<BoostBalance> {
|
|
63
79
|
/** `plan_credit` is null when the app's plans include no boost credit (absent from older servers). */
|
|
64
80
|
meta: {
|
|
65
81
|
min_cpm_micros: number;
|
|
66
82
|
topup?: BoostTopupLimits;
|
|
67
83
|
plan_credit?: BoostPlanCredit | null;
|
|
84
|
+
/** Absent from older servers. */
|
|
85
|
+
token_topup?: BoostTokenTopupInfo;
|
|
68
86
|
};
|
|
69
87
|
}
|
|
70
88
|
export interface BoostCampaignResponse extends SingleResponse<BoostCampaign> {
|
|
@@ -80,6 +98,27 @@ export interface BoostEventResult {
|
|
|
80
98
|
spent_micros: number;
|
|
81
99
|
impressions_served: number;
|
|
82
100
|
}
|
|
101
|
+
/** One UTC day of a campaign's results. */
|
|
102
|
+
export interface BoostDailyStats {
|
|
103
|
+
/** `YYYY-MM-DD`, UTC. */
|
|
104
|
+
date: string;
|
|
105
|
+
impressions: number;
|
|
106
|
+
clicks: number;
|
|
107
|
+
}
|
|
108
|
+
/** What a campaign delivered: totals and a per-day series (days with no events are absent). */
|
|
109
|
+
export interface BoostCampaignStats {
|
|
110
|
+
campaign: BoostCampaign;
|
|
111
|
+
totals: {
|
|
112
|
+
impressions: number;
|
|
113
|
+
clicks: number;
|
|
114
|
+
/** clicks / impressions, or null before the first view. */
|
|
115
|
+
click_rate: number | null;
|
|
116
|
+
spent_micros: number;
|
|
117
|
+
/** Spend per 1,000 views in micro-USD, or null before the first view. */
|
|
118
|
+
cost_per_1000_micros: number | null;
|
|
119
|
+
};
|
|
120
|
+
daily: BoostDailyStats[];
|
|
121
|
+
}
|
|
83
122
|
export interface BoostTopupCheckout {
|
|
84
123
|
/** Stripe Checkout URL to open. */
|
|
85
124
|
url: string;
|
|
@@ -92,6 +131,47 @@ export interface BoostTopupConfirmation {
|
|
|
92
131
|
credited_micros: number;
|
|
93
132
|
balance_micros: number | null;
|
|
94
133
|
}
|
|
134
|
+
/** A feed whose boosts the app splices into its pages itself: All, a category, or the big-screen grid of either. */
|
|
135
|
+
export type BoostSlotSurface = 'all' | 'category' | 'grid';
|
|
136
|
+
export interface BoostSlotsParams {
|
|
137
|
+
surface: BoostSlotSurface;
|
|
138
|
+
/** A browse category id: required for `category`, allowed for `grid`, refused for `all`. */
|
|
139
|
+
category?: string;
|
|
140
|
+
/** How many posts the page has before its boosts (1..50, default 20). */
|
|
141
|
+
limit?: number;
|
|
142
|
+
/** Up to 50 post ids already on the page (and the originals they carry): never served as a boost. */
|
|
143
|
+
exclude?: readonly string[];
|
|
144
|
+
/** The Politics choice the page is served under: under one that leaves posts out, only boosts judged not political. */
|
|
145
|
+
compass?: string;
|
|
146
|
+
}
|
|
147
|
+
export interface PublicBoostSlotsParams extends BoostSlotsParams {
|
|
148
|
+
/** The public app whose feed it is. */
|
|
149
|
+
projectId: string;
|
|
150
|
+
}
|
|
151
|
+
/** One boost of a page: where it stands in the page as served, and the boosted post (labelled `boosted: true`). */
|
|
152
|
+
export interface BoostSlotItem {
|
|
153
|
+
place: number;
|
|
154
|
+
post: Post;
|
|
155
|
+
}
|
|
156
|
+
export interface BoostSlotsResponse {
|
|
157
|
+
data: BoostSlotItem[];
|
|
158
|
+
meta: {
|
|
159
|
+
surface: BoostSlotSurface;
|
|
160
|
+
category: string | null;
|
|
161
|
+
limit: number;
|
|
162
|
+
/** One boost per `every` posts. */
|
|
163
|
+
every: number;
|
|
164
|
+
/** No boost before this place (0-based): the first two places are never a boost. */
|
|
165
|
+
first: number;
|
|
166
|
+
/** Why there are none: the key is bound to no app, or (a visitor's read) the app is not public. */
|
|
167
|
+
reason?: 'no_app' | 'not_public';
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A page with its boosts in their places: each slot's post goes in at its `place`, in order, and one whose place the
|
|
172
|
+
* page does not reach is left out, so a short page never pulls a boost forward. The page's own posts keep their order.
|
|
173
|
+
*/
|
|
174
|
+
export declare function spliceBoostSlots<T>(page: readonly T[], slots: readonly BoostSlotItem[]): Array<T | Post>;
|
|
95
175
|
/**
|
|
96
176
|
* Boost: pay to promote your own post into the For You feed. CPM campaigns
|
|
97
177
|
* funded from a prepaid balance with an append-only ledger. Top-ups run on the
|
|
@@ -126,6 +206,35 @@ export declare class BoostsResource {
|
|
|
126
206
|
resume(campaignId: string): Promise<BoostCampaignResponse>;
|
|
127
207
|
/** Cancel a campaign and refund its unspent budget to your balance (`meta.refunded_micros`). */
|
|
128
208
|
cancel(campaignId: string): Promise<BoostCampaignResponse>;
|
|
209
|
+
/**
|
|
210
|
+
* One page's boosts for a feed the app splices them into itself (All, a category, or the big-screen grid), read beside
|
|
211
|
+
* the page: pass the page's own post count as `limit` and its post ids as `exclude`, then put each item's post in at
|
|
212
|
+
* its `place` (`spliceBoostSlots`). Each post is labelled `boosted: true` with `boost_campaign_id` and
|
|
213
|
+
* `boost_disclosure`; report what was seen with `recordEvent`. Never the member's own campaign, one they hid or one
|
|
214
|
+
* walled from them. Watch's boosts come on its own pages.
|
|
215
|
+
*/
|
|
216
|
+
slots(params: BoostSlotsParams, options?: {
|
|
217
|
+
retry?: boolean;
|
|
218
|
+
}): Promise<BoostSlotsResponse>;
|
|
219
|
+
/**
|
|
220
|
+
* A visitor's boosts for one page of a public app's feed (tRPC `publicDiscovery.boostSlots`), as `slots` answers a
|
|
221
|
+
* member: read with no credential at all (no key, no cookie: `credentials: 'omit'`). An app that is not public answers
|
|
222
|
+
* none (`meta.reason` `not_public`).
|
|
223
|
+
*/
|
|
224
|
+
publicSlots(params: PublicBoostSlotsParams, options?: {
|
|
225
|
+
timeoutMs?: number;
|
|
226
|
+
}): Promise<BoostSlotsResponse>;
|
|
227
|
+
/** Results for one of your campaigns: views, clicks, click rate, spend and a daily series. */
|
|
228
|
+
stats(campaignId: string): Promise<SingleResponse<BoostCampaignStats>>;
|
|
229
|
+
/**
|
|
230
|
+
* Turn whole tokens into Boost balance at the platform's price (`balance().meta.token_topup`).
|
|
231
|
+
* `request_id` (8 to 100 of A-Z a-z 0-9 - _) makes a retry safe: the same id debits once.
|
|
232
|
+
* Not retried automatically.
|
|
233
|
+
*/
|
|
234
|
+
topupWithTokens(input: {
|
|
235
|
+
tokens: number;
|
|
236
|
+
request_id: string;
|
|
237
|
+
}): Promise<SingleResponse<BoostTokenTopupResult>>;
|
|
129
238
|
/** Report an impression or click on a boosted feed entry. Idempotent per viewer per UTC day. */
|
|
130
239
|
recordEvent(campaignId: string, kind: 'impression' | 'click'): Promise<SingleResponse<BoostEventResult>>;
|
|
131
240
|
/**
|
package/dist/resources/boosts.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import { NotFoundError, RecursivError } from '../errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* A page with its boosts in their places: each slot's post goes in at its `place`, in order, and one whose place the
|
|
4
|
+
* page does not reach is left out, so a short page never pulls a boost forward. The page's own posts keep their order.
|
|
5
|
+
*/
|
|
6
|
+
export function spliceBoostSlots(page, slots) {
|
|
7
|
+
const out = [...page];
|
|
8
|
+
for (const slot of [...slots].sort((a, b) => a.place - b.place)) {
|
|
9
|
+
if (!Number.isInteger(slot.place) || slot.place < 0 || slot.place > out.length)
|
|
10
|
+
continue;
|
|
11
|
+
out.splice(slot.place, 0, slot.post);
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
1
15
|
/**
|
|
2
16
|
* Boost: pay to promote your own post into the For You feed. CPM campaigns
|
|
3
17
|
* funded from a prepaid balance with an append-only ledger. Top-ups run on the
|
|
@@ -39,6 +53,72 @@ export class BoostsResource {
|
|
|
39
53
|
cancel(campaignId) {
|
|
40
54
|
return this.client.post(`/boosts/${encodeURIComponent(campaignId)}/cancel`, {});
|
|
41
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* One page's boosts for a feed the app splices them into itself (All, a category, or the big-screen grid), read beside
|
|
58
|
+
* the page: pass the page's own post count as `limit` and its post ids as `exclude`, then put each item's post in at
|
|
59
|
+
* its `place` (`spliceBoostSlots`). Each post is labelled `boosted: true` with `boost_campaign_id` and
|
|
60
|
+
* `boost_disclosure`; report what was seen with `recordEvent`. Never the member's own campaign, one they hid or one
|
|
61
|
+
* walled from them. Watch's boosts come on its own pages.
|
|
62
|
+
*/
|
|
63
|
+
slots(params, options) {
|
|
64
|
+
return this.client.get('/boosts/slots', {
|
|
65
|
+
surface: params.surface, category: params.category, limit: params.limit,
|
|
66
|
+
exclude: params.exclude?.length ? params.exclude.join(',') : undefined, compass: params.compass,
|
|
67
|
+
}, options);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A visitor's boosts for one page of a public app's feed (tRPC `publicDiscovery.boostSlots`), as `slots` answers a
|
|
71
|
+
* member: read with no credential at all (no key, no cookie: `credentials: 'omit'`). An app that is not public answers
|
|
72
|
+
* none (`meta.reason` `not_public`).
|
|
73
|
+
*/
|
|
74
|
+
async publicSlots(params, options) {
|
|
75
|
+
const input = { projectId: params.projectId, surface: params.surface, ...(params.category ? { category: params.category } : {}),
|
|
76
|
+
...(params.limit !== undefined ? { limit: params.limit } : {}), ...(params.exclude?.length ? { exclude: [...params.exclude] } : {}),
|
|
77
|
+
...(params.compass ? { compass: params.compass } : {}) };
|
|
78
|
+
const url = `${this.client.baseOrigin}/api/trpc/publicDiscovery.boostSlots?input=${encodeURIComponent(JSON.stringify(input))}`;
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
const timer = setTimeout(() => controller.abort(), options?.timeoutMs ?? this.client.requestTimeoutMs);
|
|
81
|
+
try {
|
|
82
|
+
let response;
|
|
83
|
+
try {
|
|
84
|
+
response = await fetch(url, { method: 'GET', headers: { Accept: 'application/json' }, credentials: 'omit', signal: controller.signal });
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw new RecursivError(0, { type: 'api_error', code: controller.signal.aborted ? 'timeout' : 'network_error',
|
|
88
|
+
message: controller.signal.aborted ? 'The visitor boost slots did not answer in time.' : `The visitor boost slots could not be reached (${error instanceof Error ? error.message : String(error)}).` });
|
|
89
|
+
}
|
|
90
|
+
let body = null;
|
|
91
|
+
try {
|
|
92
|
+
body = await response.json();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
body = null;
|
|
96
|
+
}
|
|
97
|
+
const data = body?.result?.data;
|
|
98
|
+
if (response.ok && data && typeof data === 'object')
|
|
99
|
+
return data;
|
|
100
|
+
const error = body?.error && typeof body.error === 'object' ? body.error : undefined;
|
|
101
|
+
const said = [error?.json?.message, error?.message].find((value) => typeof value === 'string' && value.length > 0);
|
|
102
|
+
const code = typeof error?.data?.code === 'string' ? error.data.code.toLowerCase() : 'unknown_error';
|
|
103
|
+
const failure = { type: response.status === 404 ? 'not_found_error' : 'api_error', code, message: said ?? `HTTP ${response.status}` };
|
|
104
|
+
throw response.status === 404 ? new NotFoundError(failure) : new RecursivError(response.ok ? 502 : response.status, failure);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
clearTimeout(timer);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Results for one of your campaigns: views, clicks, click rate, spend and a daily series. */
|
|
111
|
+
stats(campaignId) {
|
|
112
|
+
return this.client.get(`/boosts/${encodeURIComponent(campaignId)}/stats`);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Turn whole tokens into Boost balance at the platform's price (`balance().meta.token_topup`).
|
|
116
|
+
* `request_id` (8 to 100 of A-Z a-z 0-9 - _) makes a retry safe: the same id debits once.
|
|
117
|
+
* Not retried automatically.
|
|
118
|
+
*/
|
|
119
|
+
topupWithTokens(input) {
|
|
120
|
+
return this.client.post('/boosts/topup/tokens', input, { retry: false });
|
|
121
|
+
}
|
|
42
122
|
/** Report an impression or click on a boosted feed entry. Idempotent per viewer per UTC day. */
|
|
43
123
|
recordEvent(campaignId, kind) {
|
|
44
124
|
return this.client.post(`/boosts/${encodeURIComponent(campaignId)}/events`, { kind });
|
|
@@ -43,6 +43,10 @@ export interface DeploymentReleaseInput {
|
|
|
43
43
|
run_id: number;
|
|
44
44
|
attempt: number;
|
|
45
45
|
}
|
|
46
|
+
export interface DeploymentReleaseReservationInput extends DeploymentReleaseInput {
|
|
47
|
+
/** Optional initial-run GitHub OIDC proof. Requires compatible server support; never log it or retry a refused proof. */
|
|
48
|
+
coordinator_identity_token?: string;
|
|
49
|
+
}
|
|
46
50
|
export interface DeploymentRelease {
|
|
47
51
|
deployment_id: string;
|
|
48
52
|
status: string;
|
|
@@ -183,7 +187,7 @@ export declare class DeploymentsResource {
|
|
|
183
187
|
private client;
|
|
184
188
|
constructor(client: HttpClient);
|
|
185
189
|
/** Atomically block competing production deployments before promoting the API. Retry explicitly with the SAME capability. */
|
|
186
|
-
reserveRelease(input:
|
|
190
|
+
reserveRelease(input: DeploymentReleaseReservationInput): Promise<SingleResponse<DeploymentRelease>>;
|
|
187
191
|
getRelease(deploymentId: string, projectId: string): Promise<SingleResponse<DeploymentRelease>>;
|
|
188
192
|
/** Mark immediately before API mutation, then only after the existing API health gates pass. */
|
|
189
193
|
advanceRelease(deploymentId: string, input: DeploymentReleaseOperation & {
|
|
@@ -175,8 +175,11 @@ export interface CategorySurfaceSection<T> {
|
|
|
175
175
|
ms: number;
|
|
176
176
|
reason?: string;
|
|
177
177
|
}
|
|
178
|
-
/**
|
|
179
|
-
|
|
178
|
+
/**
|
|
179
|
+
* A radar cluster themed into the category, with up to six members (headline or excerpt and link only). `political`
|
|
180
|
+
* (0.7.165) is the radar's own mark, what Hide politics reads; absent from an older server or a copy cached before it.
|
|
181
|
+
*/
|
|
182
|
+
export type CategoryStory = Pick<SocialRadar['clusters'][number], 'id' | 'label' | 'kind' | 'theme' | 'political' | 'sources' | 'corroboration' | 'laneMix' | 'outlets' | 'velocity' | 'media' | 'freshness' | 'score' | 'members'>;
|
|
180
183
|
export interface CategoryClip {
|
|
181
184
|
id: string;
|
|
182
185
|
title: string | null;
|