@recursiv/sdk 0.7.123 → 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 +78 -6
- package/dist/index.d.ts +13 -7
- package/dist/index.js +6 -1
- package/dist/privacy/facts.generated.d.ts +52 -3
- package/dist/privacy/facts.generated.js +59 -3
- package/dist/resources/agents.d.ts +10 -1
- package/dist/resources/agents.js +11 -0
- 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/member-experience.d.ts +24 -0
- package/dist/resources/member-experience.js +1 -0
- package/dist/resources/protocols.d.ts +409 -20
- package/dist/resources/protocols.js +153 -6
- package/dist/resources/reports.d.ts +11 -2
- package/dist/resources/reports.js +5 -1
- package/dist/resources/search.d.ts +94 -4
- package/dist/resources/settings.d.ts +12 -2
- package/dist/resources/settings.js +15 -2
- package/dist/types.d.ts +26 -1
- package/llm.md +49 -6
- 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) |
|
|
@@ -76,7 +76,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
76
76
|
### AI Agents
|
|
77
77
|
| Resource | Key methods |
|
|
78
78
|
|----------|------------|
|
|
79
|
-
| `r.agents` | `create`, `update`, `chat`, `chatStream`, `retryChatStream`, `grantProjectAccess`, `conversations
|
|
79
|
+
| `r.agents` | `create`, `update`, `chat`, `chatStream`, `retryChatStream`, `grantProjectAccess`, `conversations` (each with a `name`), `createConversation` ("New chat" with your own personal agent; send its first message with `chatStream` and its `conversation_id`), `discover` (the app's agent directory: server search and sort, keyless-readable) |
|
|
80
80
|
| `r.e2ee` | `status`, `registerDevice`, `devices`, `revokeDevice` (`{ cascade }` to also revoke devices approved through it; 409 `has_dependents` otherwise), `requestResetCode` and `resetAccount` (reset encrypted chat with an emailed code where `status().accountReset`), `peerChanges` (contacts whose main device a reset replaced since a time), `publishKeyPackages`, `keyPackageStatus`, `claimKeyPackage`, `appendEvent` (`trust_change: true`: after a contact's reset, 409 `peer_not_joined` until this account added their new device), `events`, `acknowledge`, `conversations`, `requestStart` and `cancelStartRequest` (ask the other person to encrypt a chat when they have no device yet: a message with `metadata.kind` `e2ee_start_request`; the live ones are `ConversationDetail.encryption_requests`); device linking by scan: `createLink`, `link`, `scannedLink`, `approveLink`, `completeLink`, `linkProgress`, `cancelLink` (flag-gated E2EE v2 transport; its doorbell is `r.realtime.onE2eeEvent`, which carries a small message's stored ciphertext to the owner's own sockets; link and device changes arrive on `r.realtime.onE2eeLink` and `onE2eeDevices`, a contact's reset on `onE2eePeer`) |
|
|
81
81
|
| `r.brain` | `sendMessage` |
|
|
82
82
|
| `r.commands` | `execute`, `gatePrompt` |
|
|
@@ -96,14 +96,16 @@ 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` |
|
|
105
106
|
| `r.signals` | `batch` (up to 100 engagement signals, such as views, dwell and hides, for the member's own ranking; `keepalive` for a page-leave flush), `record` (one signal) (0.7.71); `clearViewingHistory` ("Clear my viewing history"); typed `SignalMetadata`, an id per event so a retry is stored once, and `duplicates`/`limited`/`rejected` in the answer (0.7.93) |
|
|
106
107
|
| `r.privacy` | `capabilities` (the platform privacy facts the deployed API's build enforces, and its commit); pair with `@recursiv/sdk/privacy` (`PRIVACY_FACTS`, `isFactLive`, `liveFacts`) (unreleased) |
|
|
108
|
+
| `r.reports` | `create`, `list`, `resolve`, `dismiss`, `signAttachments`; 0.7.152 `sealed_answer` reports target the key's exact project id and need `posts:write` on a human-owned, non-agent project key. This intake does not recheck live app membership; the Sealed gateway additionally does. Review applies no account enforcement. Every answer request, including a join, spends report budget. `create` returns the report `id`, optional `existing`, and `details_kept` for an answer: false means its reason was kept but its text did not fit in full. Deploy supporting API before client adoption. |
|
|
107
109
|
| `r.sealed` | Sealed mode: `config`, `attestation`, `send`; for web Sealed's frame (unreleased): `frameToken` (a short-lived `sft_` credential for the frame), `me` (the member's own age view and Sealed adult setting), `report`; pair with `@recursiv/sdk/sealed` (the resource alone) and `@recursiv/sdk/sealed-frame` (below) |
|
|
108
110
|
| `r.curator` | `today` (World Today; a world story can carry `story_key` and `discussion`, its count across networks), `storyPosts` / `memberStoryPosts` (one page of a story's posts, keyless or under the member's key), `storyPostPages` (walk every page), `forYou`, `run`, `refreshIfStale`, `seedDeck` |
|
|
109
111
|
| `r.uploads` | `uploadMedia` — upload post/chat bytes end to end |
|
|
@@ -113,10 +115,11 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
113
115
|
### Platform
|
|
114
116
|
| Resource | Purpose |
|
|
115
117
|
|----------|---------|
|
|
118
|
+
| `r.settings` experience | `getExperience`, `updateExperience({ version, goals?, interests?, avoid_categories? })`, `undoExperience({ version })` — explicit per-app starting choices with a real category Discover link; requires the member's own project-bound key (unreleased). Does not change whole-feed ranking or privacy settings. |
|
|
116
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) |
|
|
117
120
|
| `r.billing` | Usage tracking, subscriptions, checkout |
|
|
118
121
|
| `r.appSubscriptions` | Consumer app plans: `checkout`, `status`, `createPortalSession`, `previewTierChange`, `changeTier` |
|
|
119
|
-
| `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` |
|
|
120
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`) |
|
|
121
124
|
| `r.notifications` | Notification stream (`list`, `unreadCount`, `markAsRead`, `archive`, `markAllAsRead`; `category: 'mentions'` for mentions and replies only, 0.7.72) and push tokens |
|
|
122
125
|
| `r.github` | GitHub integration |
|
|
@@ -128,7 +131,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
128
131
|
| `r.goals` | Org goals with task rollups (group dispatcher tasks) |
|
|
129
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 |
|
|
130
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 |
|
|
131
|
-
| `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` |
|
|
132
135
|
|
|
133
136
|
Full reference: see [llm.md](./llm.md) (ships with this package) or the type definitions in `dist/`.
|
|
134
137
|
|
|
@@ -655,8 +658,67 @@ for (const network of data.networks) {
|
|
|
655
658
|
await r.protocols.setNetwork('nostr', { enabled: false, removePast: true });
|
|
656
659
|
```
|
|
657
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
|
+
|
|
658
711
|
### Native Nostr signing
|
|
659
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
|
+
|
|
660
722
|
Use `protocols.nativeNostrAccount()` to check the app's explicit native-write
|
|
661
723
|
capability. For an enabled connected key, prepare a text post with
|
|
662
724
|
`prepareNativeNostr(identityId, { action: 'publish', content })`, show its
|
|
@@ -957,6 +1019,16 @@ is a visitor's top (safe items only, the same for every visitor in one 15-minute
|
|
|
957
1019
|
read with no credential so the edge can hold it. Each answers 404 while the app's operator
|
|
958
1020
|
has it off. Send `block: 'top'` and the item's position with a visible view of a top item.
|
|
959
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
|
+
|
|
960
1032
|
A feed session opens with it when asked: `createFeed({ networks, top: { ref, session? }, seen,
|
|
961
1033
|
seenClusters?, bucket? })` (or `new DiscoveryFeedSession(..., { top: { ref, read, post? }, seen })`
|
|
962
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';
|
|
@@ -191,6 +194,7 @@ export { OrganizationsResource } from './resources/organizations.js';
|
|
|
191
194
|
export { NotificationsResource } from './resources/notifications.js';
|
|
192
195
|
export type { Notification, NotificationActor, NotificationCategory, NotificationPostPreview, NotificationPostTag, NotificationScopeParams, NotificationUnreadCount, ListNotificationsParams, NotificationListResponse, } from './resources/notifications.js';
|
|
193
196
|
export { SettingsResource } from './resources/settings.js';
|
|
197
|
+
export type { ExperienceGoal, ExperienceCategory, MemberExperience, UpdateMemberExperienceInput } from './resources/member-experience.js';
|
|
194
198
|
export { BillingResource } from './resources/billing.js';
|
|
195
199
|
export { FreeTierResource } from './resources/free-tier.js';
|
|
196
200
|
export { InviteCodesResource } from './resources/invite-codes.js';
|
|
@@ -204,7 +208,7 @@ export { EnvVarsResource } from './resources/env-vars.js';
|
|
|
204
208
|
export type { QueryDatabaseInput, QueryResult } from './resources/databases.js';
|
|
205
209
|
export { GitHubResource } from './resources/github.js';
|
|
206
210
|
export { DeploymentsResource } from './resources/deployments.js';
|
|
207
|
-
export type { DeploymentReleaseInput, DeploymentRelease, DeploymentReleaseOperation, DeploymentReleaseRecoveryInput } from './resources/deployments.js';
|
|
211
|
+
export type { DeploymentReleaseInput, DeploymentReleaseReservationInput, DeploymentRelease, DeploymentReleaseOperation, DeploymentReleaseRecoveryInput } from './resources/deployments.js';
|
|
208
212
|
export type { PrepareProtocolServersInput, PreparedProtocolServers, ProtocolServerPreparation, ProtocolServerUpgradePreview, ProtocolServerUpgradeInput, ProtocolServerUpgradeStatus } from './resources/deployments.js';
|
|
209
213
|
export { IntegrationsResource } from './resources/integrations.js';
|
|
210
214
|
export type { ExecuteToolInput, ExecuteToolResult } from './resources/integrations.js';
|
|
@@ -228,10 +232,12 @@ export { TrustResource } from './resources/trust.js';
|
|
|
228
232
|
export type { TrustEnvelope, OwnTrustEvent, TrustPublicKey, OwnTrustEvents } from './resources/trust.js';
|
|
229
233
|
export { LinkPreviewResource } from './resources/link-preview.js';
|
|
230
234
|
export { SEARCH_MEDIA_KINDS, SEARCH_SECTIONS, SearchResource } from './resources/search.js';
|
|
231
|
-
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';
|
|
232
236
|
export { BOOKMARK_MERGE_MAX_ITEMS, BookmarkCollectionsResource, BookmarksResource } from './resources/bookmarks.js';
|
|
233
237
|
export { FEED_TOP_NETWORKS, FeedsResource } from './resources/feeds.js';
|
|
234
|
-
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';
|
|
235
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';
|
|
236
242
|
export { AccountsResource } from './resources/accounts.js';
|
|
237
243
|
export { SIGNAL_BATCH_MAX, SignalsResource, newClientEventId } from './resources/signals.js';
|
|
@@ -248,11 +254,11 @@ export { UploadsResource } from './resources/uploads.js';
|
|
|
248
254
|
export type { UploadMediaInput, UploadUrlInput, UploadUrlResult } from './resources/uploads.js';
|
|
249
255
|
export { WalletResource } from './resources/wallet.js';
|
|
250
256
|
export type { LinkedTokenWallet, PayoutState, TokenBalance, TokenLedgerEntry, WalletLink, WalletLinkNonce } from './resources/wallet.js';
|
|
251
|
-
export { BoostsResource } from './resources/boosts.js';
|
|
252
|
-
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';
|
|
253
259
|
export { ProtocolsResource } from './resources/protocols.js';
|
|
254
260
|
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, SOCIAL_FOLLOWING_SOURCE_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
|
|
255
|
-
export type { SocialProfile, SocialBridge, 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, 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';
|
|
256
262
|
export { InboxResource } from './resources/inbox.js';
|
|
257
263
|
export { NetworkResource } from './resources/network.js';
|
|
258
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';
|
|
@@ -47,7 +47,7 @@ export declare const PRIVACY_FACTS: readonly [{
|
|
|
47
47
|
readonly enforcement: "server";
|
|
48
48
|
readonly capability: "chat_tier";
|
|
49
49
|
readonly step: "S28";
|
|
50
|
-
readonly says: "The Sealed gateway passes each Sealed request and answer on as bytes it does not read: it never parses, stores or logs a request or answer body. It refuses a request that carries no EHBP encapsulated key, the mark of a sealed body, and a success answer that carries no well-formed EHBP response nonce, the mark of a sealed answer; it cannot tell from the bytes themselves whether a body is sealed.";
|
|
50
|
+
readonly says: "The Sealed gateway passes each Sealed request and answer on as bytes it does not read: it never parses, stores or logs a request or answer body, except the report a member chooses to file (below). It refuses a request that carries no EHBP encapsulated key, the mark of a sealed body, and a success answer that carries no well-formed EHBP response nonce, the mark of a sealed answer; it cannot tell from the bytes themselves whether a body is sealed. Two routes the Sealed frame uses relay nothing, and answer only while Sealed in a browser is switched on: GET /sealed/me answers the member's own age view and adult setting, and POST /sealed/reports reads the report a member chooses to file (a reason, and details they write) and files it as any report is filed.";
|
|
51
51
|
}, {
|
|
52
52
|
readonly id: "sealed.dest_tinfoil_only";
|
|
53
53
|
readonly status: "enforced";
|
|
@@ -61,7 +61,7 @@ export declare const PRIVACY_FACTS: readonly [{
|
|
|
61
61
|
readonly enforcement: "server";
|
|
62
62
|
readonly capability: "sealed_history";
|
|
63
63
|
readonly step: "S29";
|
|
64
|
-
readonly says: "The platform keeps no Sealed chat history: no Sealed route writes a conversation or message row, and the gateway stores no request or answer body.";
|
|
64
|
+
readonly says: "The platform keeps no Sealed chat history: no Sealed route writes a conversation or message row, and the gateway stores no request or answer body, except a report the member chooses to file at POST /sealed/reports, whose reason and the details they write (which may quote the exchange they report) are kept as any report is. GET /sealed/me, which answers the member's own age view and adult setting, writes no row and keeps nothing it answers; it counts the member's requests for a minute in the shared counters, as the attestation relay does.";
|
|
65
65
|
}, {
|
|
66
66
|
readonly id: "sealed.backup_excluded";
|
|
67
67
|
readonly status: "planned";
|
|
@@ -75,7 +75,7 @@ export declare const PRIVACY_FACTS: readonly [{
|
|
|
75
75
|
readonly enforcement: "server";
|
|
76
76
|
readonly capability: "chat_tier";
|
|
77
77
|
readonly step: "S29";
|
|
78
|
-
readonly says: "No Sealed route sends a push notification or writes a notification: a Sealed answer goes back only on the request that asked for it.";
|
|
78
|
+
readonly says: "No Sealed route sends a push notification or writes a notification: a Sealed answer goes back only on the request that asked for it. The one exception is the report a member chooses to file at POST /sealed/reports, which answers only while Sealed in a browser is switched on: it is filed as any report is, so a report whose reason is child sexual abuse material, intimate images shared without consent or child safety may page Minds staff by email and on the safety rota's pager webhook, carrying the report's ids and the reason's category, never the details the member wrote.";
|
|
79
79
|
}, {
|
|
80
80
|
readonly id: "ai_prefs.agent_enabled";
|
|
81
81
|
readonly status: "planned";
|
|
@@ -307,4 +307,53 @@ export declare const PRIVACY_FACTS: readonly [{
|
|
|
307
307
|
readonly capability: "sealed_history";
|
|
308
308
|
readonly step: "S29";
|
|
309
309
|
readonly says: "Exporting a Sealed chat writes a file on the phone and sends nothing.";
|
|
310
|
+
}, {
|
|
311
|
+
readonly id: "sealed.attest_before_send_browser";
|
|
312
|
+
readonly status: "planned";
|
|
313
|
+
readonly enforcement: "device";
|
|
314
|
+
readonly capability: "chat_tier";
|
|
315
|
+
readonly step: "S28";
|
|
316
|
+
readonly says: "In a browser, the Sealed frame seals a Sealed request only to the key of a router it checked against a fresh challenge of its own, with the phone's checks: the router's report, signed by its AMD hardware, must answer that challenge with debug mode off and firmware at or above a floor, and its software must be a release Tinfoil signed and listed in a public log. The checks and the sealing are the phone's own Sealed core, built for the browser and run in a Worker inside the frame. If any check fails there is no key to seal to, so nothing is sealed or sent. How long a checked router is used before it is checked again is up to the app.";
|
|
317
|
+
}, {
|
|
318
|
+
readonly id: "sealed.frame_separate_origin";
|
|
319
|
+
readonly status: "planned";
|
|
320
|
+
readonly enforcement: "server_and_client";
|
|
321
|
+
readonly capability: "chat_tier";
|
|
322
|
+
readonly step: "S29";
|
|
323
|
+
readonly says: "In a browser, Sealed runs only in the Sealed frame, a page of its own loaded from sealed.minds.com, so the Minds page it sits in (such as minds.com or build.minds.com) cannot read what is typed or answered there. The frame tells that page only fixed signals (that it is ready, its state, that it needs a new token, where to go, and that a sign-out clear finished), never words, answers, chat names or counts, and its content security policy, enforced and never report-only, lets only Minds' own pages embed it and lets it connect only to its own origin and the Minds API.";
|
|
324
|
+
}, {
|
|
325
|
+
readonly id: "sealed.frame_token_scoped";
|
|
326
|
+
readonly status: "planned";
|
|
327
|
+
readonly enforcement: "server_and_client";
|
|
328
|
+
readonly capability: "chat_tier";
|
|
329
|
+
readonly step: "S28";
|
|
330
|
+
readonly says: "The Sealed frame never holds the member's app key. The page around it mints a Sealed frame token from that key and hands the frame only that token, which lasts at most 15 minutes, works only on the Sealed routes the frame uses and only from the frame's own origin, cannot mint another, and stops working on its next request once the key it was minted from is revoked.";
|
|
331
|
+
}, {
|
|
332
|
+
readonly id: "sealed.history_browser_only";
|
|
333
|
+
readonly status: "planned";
|
|
334
|
+
readonly enforcement: "device";
|
|
335
|
+
readonly capability: "sealed_history";
|
|
336
|
+
readonly step: "S29";
|
|
337
|
+
readonly says: "In a browser, Sealed chats are saved only in that browser, in the storage it keeps for sealed.minds.com (the Sealed frame's origin), under the account; Minds keeps none of them, apart from what a member chooses to put in a report.";
|
|
338
|
+
}, {
|
|
339
|
+
readonly id: "sealed.signout_clears_browser";
|
|
340
|
+
readonly status: "planned";
|
|
341
|
+
readonly enforcement: "client";
|
|
342
|
+
readonly capability: "sealed_history";
|
|
343
|
+
readonly step: "S29";
|
|
344
|
+
readonly says: "Signing out of Minds in a browser clears the account's Sealed chats from that browser when the Sealed frame or its sign-out page answers that they are gone; sign-out waits at most 1.5 seconds for that answer. If neither answers in time but the sign-out page had noted the clear in that browser, the clear finishes the next time the Sealed frame loads there. If the sign-out page could not load, or was stopped before it noted the clear, nothing is noted: the chats can stay in that browser until the Sealed frame next loads there with no one signed in to Minds, which clears every account's Sealed chats in it, or until the member clears the site's data.";
|
|
345
|
+
}, {
|
|
346
|
+
readonly id: "sealed.frame_no_telemetry";
|
|
347
|
+
readonly status: "planned";
|
|
348
|
+
readonly enforcement: "client";
|
|
349
|
+
readonly capability: "chat_tier";
|
|
350
|
+
readonly step: "S29";
|
|
351
|
+
readonly says: "The Sealed frame runs no analytics or error-reporting code, and its content security policy names no address for violation reports: besides its own origin, the only place it connects to is the Minds API.";
|
|
352
|
+
}, {
|
|
353
|
+
readonly id: "sealed.web_switch_enforced";
|
|
354
|
+
readonly status: "planned";
|
|
355
|
+
readonly enforcement: "server";
|
|
356
|
+
readonly capability: "chat_tier";
|
|
357
|
+
readonly step: "S28";
|
|
358
|
+
readonly says: "While Sealed in a browser is switched off on the server (SEALED_GATEWAY_WEB, off unless set), the Sealed gateway mints no frame token and accepts none, and refuses every Sealed request that carries an Origin header, as a web page's requests do, whatever its credential, except GET /sealed/config, which reports the switch. Turning it off stops each frame token on its next request.";
|
|
310
359
|
}];
|
|
@@ -56,7 +56,7 @@ export const PRIVACY_FACTS = [
|
|
|
56
56
|
enforcement: "server",
|
|
57
57
|
capability: "chat_tier",
|
|
58
58
|
step: "S28",
|
|
59
|
-
says: "The Sealed gateway passes each Sealed request and answer on as bytes it does not read: it never parses, stores or logs a request or answer body. It refuses a request that carries no EHBP encapsulated key, the mark of a sealed body, and a success answer that carries no well-formed EHBP response nonce, the mark of a sealed answer; it cannot tell from the bytes themselves whether a body is sealed.",
|
|
59
|
+
says: "The Sealed gateway passes each Sealed request and answer on as bytes it does not read: it never parses, stores or logs a request or answer body, except the report a member chooses to file (below). It refuses a request that carries no EHBP encapsulated key, the mark of a sealed body, and a success answer that carries no well-formed EHBP response nonce, the mark of a sealed answer; it cannot tell from the bytes themselves whether a body is sealed. Two routes the Sealed frame uses relay nothing, and answer only while Sealed in a browser is switched on: GET /sealed/me answers the member's own age view and adult setting, and POST /sealed/reports reads the report a member chooses to file (a reason, and details they write) and files it as any report is filed.",
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
id: "sealed.dest_tinfoil_only",
|
|
@@ -72,7 +72,7 @@ export const PRIVACY_FACTS = [
|
|
|
72
72
|
enforcement: "server",
|
|
73
73
|
capability: "sealed_history",
|
|
74
74
|
step: "S29",
|
|
75
|
-
says: "The platform keeps no Sealed chat history: no Sealed route writes a conversation or message row, and the gateway stores no request or answer body.",
|
|
75
|
+
says: "The platform keeps no Sealed chat history: no Sealed route writes a conversation or message row, and the gateway stores no request or answer body, except a report the member chooses to file at POST /sealed/reports, whose reason and the details they write (which may quote the exchange they report) are kept as any report is. GET /sealed/me, which answers the member's own age view and adult setting, writes no row and keeps nothing it answers; it counts the member's requests for a minute in the shared counters, as the attestation relay does.",
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
id: "sealed.backup_excluded",
|
|
@@ -88,7 +88,7 @@ export const PRIVACY_FACTS = [
|
|
|
88
88
|
enforcement: "server",
|
|
89
89
|
capability: "chat_tier",
|
|
90
90
|
step: "S29",
|
|
91
|
-
says: "No Sealed route sends a push notification or writes a notification: a Sealed answer goes back only on the request that asked for it.",
|
|
91
|
+
says: "No Sealed route sends a push notification or writes a notification: a Sealed answer goes back only on the request that asked for it. The one exception is the report a member chooses to file at POST /sealed/reports, which answers only while Sealed in a browser is switched on: it is filed as any report is, so a report whose reason is child sexual abuse material, intimate images shared without consent or child safety may page Minds staff by email and on the safety rota's pager webhook, carrying the report's ids and the reason's category, never the details the member wrote.",
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
id: "ai_prefs.agent_enabled",
|
|
@@ -354,4 +354,60 @@ export const PRIVACY_FACTS = [
|
|
|
354
354
|
step: "S29",
|
|
355
355
|
says: "Exporting a Sealed chat writes a file on the phone and sends nothing.",
|
|
356
356
|
},
|
|
357
|
+
{
|
|
358
|
+
id: "sealed.attest_before_send_browser",
|
|
359
|
+
status: "planned",
|
|
360
|
+
enforcement: "device",
|
|
361
|
+
capability: "chat_tier",
|
|
362
|
+
step: "S28",
|
|
363
|
+
says: "In a browser, the Sealed frame seals a Sealed request only to the key of a router it checked against a fresh challenge of its own, with the phone's checks: the router's report, signed by its AMD hardware, must answer that challenge with debug mode off and firmware at or above a floor, and its software must be a release Tinfoil signed and listed in a public log. The checks and the sealing are the phone's own Sealed core, built for the browser and run in a Worker inside the frame. If any check fails there is no key to seal to, so nothing is sealed or sent. How long a checked router is used before it is checked again is up to the app.",
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
id: "sealed.frame_separate_origin",
|
|
367
|
+
status: "planned",
|
|
368
|
+
enforcement: "server_and_client",
|
|
369
|
+
capability: "chat_tier",
|
|
370
|
+
step: "S29",
|
|
371
|
+
says: "In a browser, Sealed runs only in the Sealed frame, a page of its own loaded from sealed.minds.com, so the Minds page it sits in (such as minds.com or build.minds.com) cannot read what is typed or answered there. The frame tells that page only fixed signals (that it is ready, its state, that it needs a new token, where to go, and that a sign-out clear finished), never words, answers, chat names or counts, and its content security policy, enforced and never report-only, lets only Minds' own pages embed it and lets it connect only to its own origin and the Minds API.",
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
id: "sealed.frame_token_scoped",
|
|
375
|
+
status: "planned",
|
|
376
|
+
enforcement: "server_and_client",
|
|
377
|
+
capability: "chat_tier",
|
|
378
|
+
step: "S28",
|
|
379
|
+
says: "The Sealed frame never holds the member's app key. The page around it mints a Sealed frame token from that key and hands the frame only that token, which lasts at most 15 minutes, works only on the Sealed routes the frame uses and only from the frame's own origin, cannot mint another, and stops working on its next request once the key it was minted from is revoked.",
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
id: "sealed.history_browser_only",
|
|
383
|
+
status: "planned",
|
|
384
|
+
enforcement: "device",
|
|
385
|
+
capability: "sealed_history",
|
|
386
|
+
step: "S29",
|
|
387
|
+
says: "In a browser, Sealed chats are saved only in that browser, in the storage it keeps for sealed.minds.com (the Sealed frame's origin), under the account; Minds keeps none of them, apart from what a member chooses to put in a report.",
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
id: "sealed.signout_clears_browser",
|
|
391
|
+
status: "planned",
|
|
392
|
+
enforcement: "client",
|
|
393
|
+
capability: "sealed_history",
|
|
394
|
+
step: "S29",
|
|
395
|
+
says: "Signing out of Minds in a browser clears the account's Sealed chats from that browser when the Sealed frame or its sign-out page answers that they are gone; sign-out waits at most 1.5 seconds for that answer. If neither answers in time but the sign-out page had noted the clear in that browser, the clear finishes the next time the Sealed frame loads there. If the sign-out page could not load, or was stopped before it noted the clear, nothing is noted: the chats can stay in that browser until the Sealed frame next loads there with no one signed in to Minds, which clears every account's Sealed chats in it, or until the member clears the site's data.",
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
id: "sealed.frame_no_telemetry",
|
|
399
|
+
status: "planned",
|
|
400
|
+
enforcement: "client",
|
|
401
|
+
capability: "chat_tier",
|
|
402
|
+
step: "S29",
|
|
403
|
+
says: "The Sealed frame runs no analytics or error-reporting code, and its content security policy names no address for violation reports: besides its own origin, the only place it connects to is the Minds API.",
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
id: "sealed.web_switch_enforced",
|
|
407
|
+
status: "planned",
|
|
408
|
+
enforcement: "server",
|
|
409
|
+
capability: "chat_tier",
|
|
410
|
+
step: "S28",
|
|
411
|
+
says: "While Sealed in a browser is switched off on the server (SEALED_GATEWAY_WEB, off unless set), the Sealed gateway mints no frame token and accepts none, and refuses every Sealed request that carries an Origin header, as a web page's requests do, whatever its credential, except GET /sealed/config, which reports the switch. Turning it off stops each frame token on its next request.",
|
|
412
|
+
},
|
|
357
413
|
];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { HttpClient } from '../client.js';
|
|
2
|
-
import type { PaginatedResponse, SingleResponse, DeleteResponse, Agent, AgentDetail, CreateAgentInput, CreatedAgent, UpdateAgentInput, UpdatedAgent, AgentChatInput, AgentChatRetryInput, AgentChatResult, AgentConversation, AgentConversationMessage, PaginationParams, StreamChunk } from '../types.js';
|
|
2
|
+
import type { PaginatedResponse, SingleResponse, DeleteResponse, Agent, AgentDetail, CreateAgentInput, CreatedAgent, UpdateAgentInput, UpdatedAgent, AgentChatInput, AgentChatRetryInput, AgentChatResult, AgentConversation, AgentConversationMessage, CreatedAgentConversation, PaginationParams, StreamChunk } from '../types.js';
|
|
3
3
|
export interface AgentMessage {
|
|
4
4
|
id: string;
|
|
5
5
|
networkId: string;
|
|
@@ -241,6 +241,15 @@ export declare class AgentsResource {
|
|
|
241
241
|
chat(id: string, input: AgentChatInput): Promise<SingleResponse<AgentChatResult>>;
|
|
242
242
|
/** List an agent's conversations */
|
|
243
243
|
conversations(id: string, params?: PaginationParams): Promise<PaginatedResponse<AgentConversation>>;
|
|
244
|
+
/**
|
|
245
|
+
* Start a new chat with the caller's own personal agent (`id`): an empty thread in this key's app. Send its first
|
|
246
|
+
* message with `chatStream(id, { message, conversation_id })`; `conversations()` then lists it with its `name`.
|
|
247
|
+
* When the member already has an empty chat with the agent there, that one comes back with `created: false`, so a
|
|
248
|
+
* second tap (or a resent request) never makes another blank thread. An id that names no agent, or an agent outside
|
|
249
|
+
* the network of this key and its app, is 404 `agent_not_found` (the same answer for both); in the caller's network,
|
|
250
|
+
* any agent that is not the caller's own personal agent, or a key acting as an agent, is 403 `not_owner`.
|
|
251
|
+
*/
|
|
252
|
+
createConversation(id: string): Promise<SingleResponse<CreatedAgentConversation>>;
|
|
244
253
|
/**
|
|
245
254
|
* Read the messages in one of an agent's conversations, oldest first.
|
|
246
255
|
*
|
package/dist/resources/agents.js
CHANGED
|
@@ -103,6 +103,17 @@ export class AgentsResource {
|
|
|
103
103
|
conversations(id, params) {
|
|
104
104
|
return this.client.get(`/agents/${id}/conversations`, params);
|
|
105
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Start a new chat with the caller's own personal agent (`id`): an empty thread in this key's app. Send its first
|
|
108
|
+
* message with `chatStream(id, { message, conversation_id })`; `conversations()` then lists it with its `name`.
|
|
109
|
+
* When the member already has an empty chat with the agent there, that one comes back with `created: false`, so a
|
|
110
|
+
* second tap (or a resent request) never makes another blank thread. An id that names no agent, or an agent outside
|
|
111
|
+
* the network of this key and its app, is 404 `agent_not_found` (the same answer for both); in the caller's network,
|
|
112
|
+
* any agent that is not the caller's own personal agent, or a key acting as an agent, is 403 `not_owner`.
|
|
113
|
+
*/
|
|
114
|
+
createConversation(id) {
|
|
115
|
+
return this.client.post(`/agents/${id}/conversations`, {});
|
|
116
|
+
}
|
|
106
117
|
/**
|
|
107
118
|
* Read the messages in one of an agent's conversations, oldest first.
|
|
108
119
|
*
|
|
@@ -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
|
+
}
|