@recursiv/sdk 0.7.82 → 0.7.89
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 +128 -1
- package/dist/assistant/fixedCardData.d.ts +91 -0
- package/dist/assistant/fixedCardData.js +372 -0
- package/dist/assistant/fixedCards.d.ts +35 -0
- package/dist/assistant/fixedCards.js +904 -0
- package/dist/assistant/hiddenText.d.ts +24 -0
- package/dist/assistant/hiddenText.js +263 -0
- package/dist/assistant/index.d.ts +30 -0
- package/dist/assistant/index.js +30 -0
- package/dist/assistant/render.d.ts +31 -0
- package/dist/assistant/render.js +434 -0
- package/dist/assistant/subjectBundle.d.ts +30 -0
- package/dist/assistant/subjectBundle.js +535 -0
- package/dist/assistant/turnCaps.d.ts +3 -0
- package/dist/assistant/turnCaps.js +141 -0
- package/dist/assistant/types.d.ts +569 -0
- package/dist/assistant/types.js +26 -0
- package/dist/assistant-surfaces.d.ts +42 -0
- package/dist/assistant-surfaces.js +113 -0
- package/dist/index.d.ts +15 -6
- package/dist/index.js +8 -1
- package/dist/privacy/facts.generated.d.ts +79 -0
- package/dist/privacy/facts.generated.js +93 -0
- package/dist/privacy/index.d.ts +48 -0
- package/dist/privacy/index.js +42 -0
- package/dist/realtime.d.ts +10 -3
- package/dist/realtime.js +11 -2
- package/dist/resources/agents.d.ts +6 -1
- package/dist/resources/agents.js +12 -2
- package/dist/resources/discovery-merge.d.ts +17 -1
- package/dist/resources/discovery-merge.js +84 -4
- package/dist/resources/discovery-progressive.d.ts +4 -3
- package/dist/resources/discovery-progressive.js +11 -8
- package/dist/resources/discovery.d.ts +9 -1
- package/dist/resources/discovery.js +62 -15
- package/dist/resources/e2ee.d.ts +56 -0
- package/dist/resources/e2ee.js +21 -0
- package/dist/resources/feeds.d.ts +15 -6
- package/dist/resources/feeds.js +2 -1
- package/dist/resources/integrations.d.ts +3 -0
- package/dist/resources/link-preview.d.ts +42 -1
- package/dist/resources/link-preview.js +36 -2
- package/dist/resources/network.d.ts +6 -0
- package/dist/resources/privacy.d.ts +13 -0
- package/dist/resources/privacy.js +14 -0
- package/dist/resources/project-brain.d.ts +8 -0
- package/dist/resources/protocols.d.ts +99 -11
- package/dist/resources/protocols.js +45 -0
- package/dist/resources/sealed.d.ts +127 -7
- package/dist/resources/sealed.js +33 -6
- package/dist/resources/settings.d.ts +3 -1
- package/dist/resources/settings.js +3 -1
- package/dist/resources/users.d.ts +11 -2
- package/dist/resources/users.js +1 -1
- package/dist/social-protocol-ids.d.ts +28 -0
- package/dist/social-protocol-ids.js +30 -0
- package/dist/types.d.ts +71 -0
- package/llm.md +45 -4
- package/package.json +11 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-driven kill switches for the assistant's surfaces (George plan step G7a).
|
|
3
|
+
*
|
|
4
|
+
* A flag compiled into a phone app cannot be switched off once that build ships, so every place an app shows the
|
|
5
|
+
* assistant asks the server first. The switches are the app's project setting `assistant.surfaces`, and they arrive
|
|
6
|
+
* inside responses the app already fetches: `users.me()` (the boot read) and `network.getConfig()` both carry
|
|
7
|
+
* `data.assistant.surfaces`. An app's owner or admin changes them with
|
|
8
|
+
* `projectBrain.updateSettings(projectId, { assistant: { surfaces: { post_button: true } } })`.
|
|
9
|
+
*
|
|
10
|
+
* Fail closed: show a surface only when {@link assistantSurfaceOn} says so, which is only for an explicit `true`. A
|
|
11
|
+
* response from an older server (no `assistant`), a read that failed, a malformed value and an id this SDK does not
|
|
12
|
+
* know are all off.
|
|
13
|
+
*
|
|
14
|
+
* The server keeps the same list (packages/server/src/features/assistant/surfaces.ts); a contract test holds them equal.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Every assistant surface an app may show, one switch each. All default off. Step numbers are the George plan's §8.
|
|
18
|
+
* New ids are appended; an id is never renamed.
|
|
19
|
+
*/
|
|
20
|
+
export const ASSISTANT_SURFACE_IDS = [
|
|
21
|
+
// The G glyph on a post (feed, post page, network or bridged post, clip, article, story), with its long-press item
|
|
22
|
+
// and screen-reader action. G3.
|
|
23
|
+
'post_button',
|
|
24
|
+
// The answer sheet: the answer streamed in place (bottom sheet on phones, right rail on desktop), its chips and
|
|
25
|
+
// follow-ups. G11 (G3's interim sheet rides it too).
|
|
26
|
+
'answer_sheet',
|
|
27
|
+
// "Ask about these results" on a question-shaped search, and the Cmd-K ask. G4; answers G23a.
|
|
28
|
+
'search_row',
|
|
29
|
+
// The glyph in the top bar that opens the assistant tab. G4.
|
|
30
|
+
'top_bar',
|
|
31
|
+
// The assistant's one row in the Chat inbox. G4.
|
|
32
|
+
'inbox_row',
|
|
33
|
+
// Mentioning the assistant in a reply (the `ai:george` chip), raw `@askgeorge` routing, and the push that an answer
|
|
34
|
+
// is ready. G22.
|
|
35
|
+
'mentions',
|
|
36
|
+
// Asking about picked messages in an ordinary (not encrypted) DM or group chat, and mentioning the assistant in a
|
|
37
|
+
// small closed group chat. G20.
|
|
38
|
+
'chats',
|
|
39
|
+
// Asking the Sealed assistant about one message in an encrypted chat, on the phone only. G21.
|
|
40
|
+
'e2ee_asks',
|
|
41
|
+
// "Catch me up" in a group's (community's) header. G24.
|
|
42
|
+
'groups_catch_up',
|
|
43
|
+
// "Translate" under a post in another language. G23a (on-device G25).
|
|
44
|
+
'translate',
|
|
45
|
+
// The compose chip: check tone, shorten, fix spelling, translate, draft a reply. G23a.
|
|
46
|
+
'compose',
|
|
47
|
+
// "About this account": the facts card on a profile, with no model call. G23a.
|
|
48
|
+
'profile_facts',
|
|
49
|
+
// "Why am I seeing this" on a feed post, and asking the assistant to explain it. G28.
|
|
50
|
+
'why_seeing',
|
|
51
|
+
// The opt-in daily brief and routines. G30.
|
|
52
|
+
'daily_brief',
|
|
53
|
+
// Context notes the assistant drafts and people rate. G31.
|
|
54
|
+
'notes',
|
|
55
|
+
// The assistant tab itself: thread list, new chat, the chat screen. G13.
|
|
56
|
+
'george_tab',
|
|
57
|
+
// Sealed chats inside the assistant tab, on the phone. G15b.
|
|
58
|
+
'sealed_in_tab',
|
|
59
|
+
// "Summarise replies" on a thread with 10 or more replies. G11.
|
|
60
|
+
'thread_summary',
|
|
61
|
+
// Ask and Quote on selected text (web selection popover G11; phone apps G32).
|
|
62
|
+
'selection',
|
|
63
|
+
// "What's going on" on a topic bar or Today story. G23a.
|
|
64
|
+
'topic_catch_up',
|
|
65
|
+
// "Describe" on a picture in the media viewer. G23b, only after the upload checks are live.
|
|
66
|
+
'describe_image',
|
|
67
|
+
// "Suggest alt text" for your own picture in compose. G23b, only after the upload checks are live.
|
|
68
|
+
'alt_text',
|
|
69
|
+
// "Tell the assistant what you want more or less of" in feed settings. G29.
|
|
70
|
+
'feed_steering',
|
|
71
|
+
// Sharing an answer as your own post. G27, not before 2026-11-04.
|
|
72
|
+
'share_answer',
|
|
73
|
+
];
|
|
74
|
+
const SURFACE_IDS = new Set(ASSISTANT_SURFACE_IDS);
|
|
75
|
+
/** True for a surface id this SDK knows. */
|
|
76
|
+
export function isAssistantSurfaceId(value) {
|
|
77
|
+
return typeof value === 'string' && SURFACE_IDS.has(value);
|
|
78
|
+
}
|
|
79
|
+
function isPlainObject(value) {
|
|
80
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The surfaces map inside `settings`, which may be a response's `data` (carrying `assistant.surfaces`) or its
|
|
84
|
+
* `assistant` block (carrying `surfaces`). Null when there is none to read.
|
|
85
|
+
*/
|
|
86
|
+
function surfacesIn(settings) {
|
|
87
|
+
if (!isPlainObject(settings))
|
|
88
|
+
return null;
|
|
89
|
+
if (Object.hasOwn(settings, 'assistant')) {
|
|
90
|
+
const assistant = settings.assistant;
|
|
91
|
+
return isPlainObject(assistant) && isPlainObject(assistant.surfaces) ? assistant.surfaces : null;
|
|
92
|
+
}
|
|
93
|
+
return isPlainObject(settings.surfaces) ? settings.surfaces : null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Whether the app may show surface `id`: true only when `settings` holds an explicit `true` for it. `settings` is a
|
|
97
|
+
* response's `data` (`(await sdk.users.me()).data`, `(await sdk.network.getConfig()).data`) or its `assistant` block.
|
|
98
|
+
* Anything else is off: no settings (a read that failed, an older server), a malformed value, a non-boolean, an id
|
|
99
|
+
* this SDK does not know.
|
|
100
|
+
*/
|
|
101
|
+
export function assistantSurfaceOn(settings, id) {
|
|
102
|
+
if (!isAssistantSurfaceId(id))
|
|
103
|
+
return false;
|
|
104
|
+
const surfaces = surfacesIn(settings);
|
|
105
|
+
return !!surfaces && Object.hasOwn(surfaces, id) && surfaces[id] === true;
|
|
106
|
+
}
|
|
107
|
+
/** Every known surface with its switch, read from `settings` by the same rule as {@link assistantSurfaceOn}. */
|
|
108
|
+
export function assistantSurfaces(settings) {
|
|
109
|
+
const out = {};
|
|
110
|
+
for (const id of ASSISTANT_SURFACE_IDS)
|
|
111
|
+
out[id] = assistantSurfaceOn(settings, id);
|
|
112
|
+
return out;
|
|
113
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './resources/discovery-learning.js';
|
|
|
2
2
|
import { DiscoveryResource } from './resources/discovery.js';
|
|
3
3
|
export * from './resources/discovery.js';
|
|
4
4
|
export * from './feed-definition.js';
|
|
5
|
+
export * from './social-protocol-ids.js';
|
|
5
6
|
import { AuthResource } from './resources/auth.js';
|
|
6
7
|
import { PostsResource } from './resources/posts.js';
|
|
7
8
|
import { UsersResource } from './resources/users.js';
|
|
@@ -67,6 +68,7 @@ import { FeedsResource } from './resources/feeds.js';
|
|
|
67
68
|
import { AccountsResource } from './resources/accounts.js';
|
|
68
69
|
import { SignalsResource } from './resources/signals.js';
|
|
69
70
|
import { SealedResource } from './resources/sealed.js';
|
|
71
|
+
import { PrivacyResource } from './resources/privacy.js';
|
|
70
72
|
import { RealtimeClient } from './realtime.js';
|
|
71
73
|
import type { RecursivConfig } from './types.js';
|
|
72
74
|
export declare class Recursiv {
|
|
@@ -144,6 +146,8 @@ export declare class Recursiv {
|
|
|
144
146
|
readonly signals: SignalsResource;
|
|
145
147
|
/** Sealed mode's config and transport: targets, models, allowance, the attestation relay and the sealed send (no crypto; flag-gated). */
|
|
146
148
|
readonly sealed: SealedResource;
|
|
149
|
+
/** Which platform privacy facts the deployed API's build enforces (pair with `@recursiv/sdk/privacy`). */
|
|
150
|
+
readonly privacy: PrivacyResource;
|
|
147
151
|
readonly realtime: RealtimeClient;
|
|
148
152
|
constructor(config?: Partial<RecursivConfig>);
|
|
149
153
|
/**
|
|
@@ -168,7 +172,7 @@ export { CommunitiesResource } from './resources/communities.js';
|
|
|
168
172
|
export { ChatResource, CHAT_ATTACHMENT_REF_PREFIX, chatAttachmentKeysIn, chatAttachmentRefsIn } from './resources/chat.js';
|
|
169
173
|
export type { ChatAttachmentRef, ChatAttachmentUploadInput, ChatAttachmentUploadUrl, ChatAttachmentUploadUrlInput, SignedChatAttachment, } from './resources/chat.js';
|
|
170
174
|
export { E2eeResource } from './resources/e2ee.js';
|
|
171
|
-
export type { E2eeAccountReset, E2eeDevice, E2eeDevicesRealtimeEvent, E2eeEnvelope, E2eeEvent, E2eeHasDependentsDetails, E2eeKeyPackageStatus, E2eeLink, E2eeLinkCancelledBy, E2eeLinkProgress, E2eeLinkRealtimeEvent, E2eeLinkState, E2eeObjectDownload, E2eeObjectUpload, E2eeRealtimeEvent, E2eeResetCodeSent, E2eeResetErrorCode, E2eeRevokeResponse, E2eeStartRequest, E2eeStatus, E2eeStatusReason, } from './resources/e2ee.js';
|
|
175
|
+
export type { E2eeAccountReset, E2eeDevice, E2eeDevicesRealtimeEvent, E2eeEnvelope, E2eeEvent, E2eeHasDependentsDetails, E2eeKeyPackageStatus, E2eeLink, E2eeLinkCancelledBy, E2eeLinkProgress, E2eeLinkRealtimeEvent, E2eeLinkState, E2eeObjectDownload, E2eeObjectUpload, E2eePeerChange, E2eePeerErrorCode, E2eePeerNotJoinedDetails, E2eePeerRealtimeEvent, E2eeRealtimeEvent, E2eeResetCodeSent, E2eeResetErrorCode, E2eeRevokeResponse, E2eeStartRequest, E2eeStatus, E2eeStatusReason, } from './resources/e2ee.js';
|
|
172
176
|
export { ProjectsResource } from './resources/projects.js';
|
|
173
177
|
export { AgentsResource, SUPPORTED_MODELS, AGENT_DIRECTORY_SORTS, AGENT_DIRECTORY_MAX_LIMIT } from './resources/agents.js';
|
|
174
178
|
export { EvidenceResource } from './resources/evidence.js';
|
|
@@ -218,15 +222,15 @@ export { SEARCH_SECTIONS, SearchResource } from './resources/search.js';
|
|
|
218
222
|
export type { PublicSearchPage, PublicSearchTab, SearchAnswer, SearchGroup, SearchLadder, SearchOmitReason, SearchParams, SearchPerson, SearchPost, SearchRelated, SearchResponse, SearchSection, SearchStage, SearchStory, SearchTopic, SearchVia, } from './resources/search.js';
|
|
219
223
|
export { BOOKMARK_MERGE_MAX_ITEMS, BookmarkCollectionsResource, BookmarksResource } from './resources/bookmarks.js';
|
|
220
224
|
export { FEED_TOP_NETWORKS, FeedsResource } from './resources/feeds.js';
|
|
221
|
-
export type { FeedStoriesParams, FeedStoriesResponse, FeedStory, FeedTopExplain, FeedTopItem, FeedTopMeta, FeedTopNetwork, FeedTopNetworkCard, FeedTopNetworkEntry, FeedTopParams, FeedTopResponse, FeedTopTarget, PublicFeedTopMeta, PublicFeedTopParams, PublicFeedTopResponse, } from './resources/feeds.js';
|
|
225
|
+
export type { FeedStoriesParams, FeedStoriesResponse, FeedStory, FeedTopExplain, FeedTopItem, FeedTopMeta, FeedTopNetwork, FeedTopNetworkCard, FeedTopNetworkEntry, FeedTopNetworkMap, FeedTopParams, FeedTopResponse, FeedTopTarget, PublicFeedTopMeta, PublicFeedTopParams, PublicFeedTopResponse, } from './resources/feeds.js';
|
|
222
226
|
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';
|
|
223
227
|
export { AccountsResource } from './resources/accounts.js';
|
|
224
228
|
export { SIGNAL_BATCH_MAX, SignalsResource } from './resources/signals.js';
|
|
225
229
|
export type { SignalBatchResult, SignalEventInput, SignalEventType, SignalNotRecordedReason, SignalRecordResult, SignalSendOptions, } from './resources/signals.js';
|
|
226
230
|
export { SEALED_ALLOWANCE_REMAINING_HEADER, SEALED_REFUSAL_HEADER, SealedResource, SealedTransportError, } from './resources/sealed.js';
|
|
227
|
-
export type { SealedAllowance, SealedAttestationInput, SealedConfig, SealedModel, SealedSendInput, SealedTarget, SealedTargetKind, SealedTransportErrorCode, } from './resources/sealed.js';
|
|
231
|
+
export type { SealedAllowance, SealedAttestationInput, SealedConfig, SealedModel, SealedPlan, SealedPurpose, SealedQuotaDetails, SealedSendInput, SealedTarget, SealedTargetKind, SealedTransportErrorCode, } from './resources/sealed.js';
|
|
228
232
|
export type { SiblingAccount, SiblingAccountsResponse, SwitchAccountResult, } from './resources/accounts.js';
|
|
229
|
-
export type { LinkPreview, LinkPreviewResponse, } from './resources/link-preview.js';
|
|
233
|
+
export type { LinkPreview, LinkPreviewResponse, LinkPreviewSource, } from './resources/link-preview.js';
|
|
230
234
|
export type { AgentCapabilityConsentRequirement, AgentCapabilityDataSensitivity, AgentCapabilityDomain, AgentCapabilityExportBoundary, AgentCapabilityRetentionClass, AgentCapabilitySubdomain, AgentCapabilitySubject, AgentCapabilityTrustTier, AgentToolAudience, AgentToolScope, BrowserUseRunTaskInput, ProjectBrainSettings, ProjectToolBundleClassification, ProjectToolBundleKey, ProjectToolPermission, ProjectToolPermissionOverrides, UpdateProjectSettingsInput, } from './resources/project-brain.js';
|
|
231
235
|
export { OrganizationSettingsResource } from './resources/organization-settings.js';
|
|
232
236
|
export { ProjectSettingsResource } from './resources/project-settings.js';
|
|
@@ -238,8 +242,8 @@ export type { LinkedTokenWallet, PayoutState, TokenBalance, TokenLedgerEntry } f
|
|
|
238
242
|
export { BoostsResource } from './resources/boosts.js';
|
|
239
243
|
export type { BoostBalance, BoostBalanceResponse, BoostCampaign, BoostCampaignResponse, BoostEventResult, BoostLedgerEntry, BoostLedgerKind, BoostPlanCredit, BoostRejectionReason, BoostReviewStatus, BoostStatus, BoostTopupCheckout, BoostTopupConfirmation, BoostTopupLimits, } from './resources/boosts.js';
|
|
240
244
|
export { ProtocolsResource } from './resources/protocols.js';
|
|
241
|
-
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
|
|
242
|
-
export type { SocialProfile, SocialBridge, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialRadar, SocialRadarCluster, SocialRadarMember, SocialRadarParams, 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, SocialFollowingFeed, SocialFollowingSource, SearchPublicProfilesParams, SearchPublicPostsParams, SocialPostSearch, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeSocialCallbackInput, NativeReplyPrepareInput, NativePostPrepareInput, NativeMediaInput, NativeMediaItem, NativePostBatch, 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';
|
|
245
|
+
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, SOCIAL_FOLLOWING_SOURCE_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
|
|
246
|
+
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, 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';
|
|
243
247
|
export { InboxResource } from './resources/inbox.js';
|
|
244
248
|
export { NetworkResource } from './resources/network.js';
|
|
245
249
|
export { SimulatorResource } from './resources/simulator.js';
|
|
@@ -270,3 +274,8 @@ export { parseSSE } from './lib/sse.js';
|
|
|
270
274
|
export * from './lib/webhooks.js';
|
|
271
275
|
export type * from './types.js';
|
|
272
276
|
export type { PrepareHostedServiceInput, HostedServiceScope, HostedServiceOperation, HostedServiceReservation, HostedServiceObservation } from './resources/deployments.js';
|
|
277
|
+
export { ASSISTANT_SURFACE_IDS, assistantSurfaceOn, assistantSurfaces, isAssistantSurfaceId, } from './assistant-surfaces.js';
|
|
278
|
+
export type { AssistantSettings, AssistantSettingsUpdate, AssistantSurfaceId, AssistantSurfaces, } from './assistant-surfaces.js';
|
|
279
|
+
export type { CurrentUser } from './resources/users.js';
|
|
280
|
+
export { PrivacyResource } from './resources/privacy.js';
|
|
281
|
+
export type { LiveFactOptions, PrivacyCapabilities } from './privacy/index.js';
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from './resources/discovery-learning.js';
|
|
|
2
2
|
import { DiscoveryResource } from './resources/discovery.js';
|
|
3
3
|
export * from './resources/discovery.js';
|
|
4
4
|
export * from './feed-definition.js';
|
|
5
|
+
export * from './social-protocol-ids.js';
|
|
5
6
|
import { HttpClient } from './client.js';
|
|
6
7
|
import { AuthResource } from './resources/auth.js';
|
|
7
8
|
import { PostsResource } from './resources/posts.js';
|
|
@@ -68,6 +69,7 @@ import { FeedsResource } from './resources/feeds.js';
|
|
|
68
69
|
import { AccountsResource } from './resources/accounts.js';
|
|
69
70
|
import { SignalsResource } from './resources/signals.js';
|
|
70
71
|
import { SealedResource } from './resources/sealed.js';
|
|
72
|
+
import { PrivacyResource } from './resources/privacy.js';
|
|
71
73
|
import { RealtimeClient } from './realtime.js';
|
|
72
74
|
export class Recursiv {
|
|
73
75
|
/** Shared transport, kept so the client name can be set after construction. */
|
|
@@ -145,6 +147,8 @@ export class Recursiv {
|
|
|
145
147
|
signals;
|
|
146
148
|
/** Sealed mode's config and transport: targets, models, allowance, the attestation relay and the sealed send (no crypto; flag-gated). */
|
|
147
149
|
sealed;
|
|
150
|
+
/** Which platform privacy facts the deployed API's build enforces (pair with `@recursiv/sdk/privacy`). */
|
|
151
|
+
privacy;
|
|
148
152
|
realtime;
|
|
149
153
|
constructor(config) {
|
|
150
154
|
const client = new HttpClient(config);
|
|
@@ -214,6 +218,7 @@ export class Recursiv {
|
|
|
214
218
|
this.accounts = new AccountsResource(client);
|
|
215
219
|
this.signals = new SignalsResource(client);
|
|
216
220
|
this.sealed = new SealedResource(client);
|
|
221
|
+
this.privacy = new PrivacyResource(client);
|
|
217
222
|
this.realtime = new RealtimeClient(client);
|
|
218
223
|
this.#http = client;
|
|
219
224
|
}
|
|
@@ -283,7 +288,7 @@ export { UploadsResource } from './resources/uploads.js';
|
|
|
283
288
|
export { WalletResource } from './resources/wallet.js';
|
|
284
289
|
export { BoostsResource } from './resources/boosts.js';
|
|
285
290
|
export { ProtocolsResource } from './resources/protocols.js';
|
|
286
|
-
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
|
|
291
|
+
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, SOCIAL_FOLLOWING_SOURCE_STATUSES, viralItemHasVideo, } from './resources/protocols.js';
|
|
287
292
|
export { InboxResource } from './resources/inbox.js';
|
|
288
293
|
export { NetworkResource } from './resources/network.js';
|
|
289
294
|
export { SimulatorResource } from './resources/simulator.js';
|
|
@@ -302,3 +307,5 @@ export { MediaResource } from './resources/media.js';
|
|
|
302
307
|
export { RecursivError, AuthenticationError, AuthorizationError, LegacyHandoffError, NotFoundError, ValidationError, InsufficientCreditsError, RateLimitError, ConflictError, isActionRateLimitScope, EmailNotSentError, } from './errors.js';
|
|
303
308
|
export { parseSSE } from './lib/sse.js';
|
|
304
309
|
export * from './lib/webhooks.js';
|
|
310
|
+
export { ASSISTANT_SURFACE_IDS, assistantSurfaceOn, assistantSurfaces, isAssistantSurfaceId, } from './assistant-surfaces.js';
|
|
311
|
+
export { PrivacyResource } from './resources/privacy.js';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export declare const PRIVACY_REGISTRY_VERSION: 0;
|
|
2
|
+
export declare const PRIVACY_FACTS: readonly [{
|
|
3
|
+
readonly id: "agents.tool_mode.chat_only";
|
|
4
|
+
readonly status: "planned";
|
|
5
|
+
readonly enforcement: "server";
|
|
6
|
+
readonly capability: "web_tools";
|
|
7
|
+
readonly step: "S5";
|
|
8
|
+
readonly says: "An agent in chat_only tool mode is given no tools, so it opens no web page.";
|
|
9
|
+
}, {
|
|
10
|
+
readonly id: "agents.turn_stamp";
|
|
11
|
+
readonly status: "enforced";
|
|
12
|
+
readonly enforcement: "server";
|
|
13
|
+
readonly capability: null;
|
|
14
|
+
readonly step: "S7";
|
|
15
|
+
readonly says: "Every reply a model writes in an agent chat through the platform's agent turn records, in metadata.ai, the model, its maker and the route, a model swapped in and whether for usage limits or after a failure, and the tools it called.";
|
|
16
|
+
}, {
|
|
17
|
+
readonly id: "agents.personal_context_sections";
|
|
18
|
+
readonly status: "planned";
|
|
19
|
+
readonly enforcement: "server";
|
|
20
|
+
readonly capability: "activity";
|
|
21
|
+
readonly step: "S26";
|
|
22
|
+
readonly says: "A personal agent's turn carries no follows, upvotes, groups or views of the member unless the member turned that part of their activity on.";
|
|
23
|
+
}, {
|
|
24
|
+
readonly id: "sealed.attest_before_send";
|
|
25
|
+
readonly status: "enforced";
|
|
26
|
+
readonly enforcement: "device";
|
|
27
|
+
readonly capability: "chat_tier";
|
|
28
|
+
readonly step: "S28";
|
|
29
|
+
readonly says: "The phone seals a Sealed request only to the key of a router it checked against a fresh challenge of its own: 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. 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.";
|
|
30
|
+
}, {
|
|
31
|
+
readonly id: "sealed.attest_second_signer";
|
|
32
|
+
readonly status: "planned";
|
|
33
|
+
readonly enforcement: "device";
|
|
34
|
+
readonly capability: "chat_tier";
|
|
35
|
+
readonly step: "S28";
|
|
36
|
+
readonly says: "The phone also requires Recursiv's own signature over the router's release, so a release Tinfoil signed alone is refused.";
|
|
37
|
+
}, {
|
|
38
|
+
readonly id: "sealed.no_standard_fallback";
|
|
39
|
+
readonly status: "enforced";
|
|
40
|
+
readonly enforcement: "client";
|
|
41
|
+
readonly capability: "chat_tier";
|
|
42
|
+
readonly step: "S28";
|
|
43
|
+
readonly says: "The SDK sends a Sealed request only to the Sealed route, marked Sealed, and only once: a refusal, an error or an answer that is not sealed goes back to the app, and the SDK never sends the request again, to Sealed or to any other route.";
|
|
44
|
+
}, {
|
|
45
|
+
readonly id: "sealed.gateway_opaque";
|
|
46
|
+
readonly status: "enforced";
|
|
47
|
+
readonly enforcement: "server";
|
|
48
|
+
readonly capability: "chat_tier";
|
|
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.";
|
|
51
|
+
}, {
|
|
52
|
+
readonly id: "sealed.dest_tinfoil_only";
|
|
53
|
+
readonly status: "enforced";
|
|
54
|
+
readonly enforcement: "server";
|
|
55
|
+
readonly capability: "chat_tier";
|
|
56
|
+
readonly step: "S28";
|
|
57
|
+
readonly says: "The Sealed gateway sends Sealed requests, and asks for attestation documents, only to the router origins its configuration lists, named exactly, and it lists only https origins of Tinfoil router hosts (inference.tinfoil.sh or router-N.tinfoil.sh). It refuses any other server a client names and follows no redirect.";
|
|
58
|
+
}, {
|
|
59
|
+
readonly id: "sealed.no_server_history";
|
|
60
|
+
readonly status: "enforced";
|
|
61
|
+
readonly enforcement: "server";
|
|
62
|
+
readonly capability: "sealed_history";
|
|
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.";
|
|
65
|
+
}, {
|
|
66
|
+
readonly id: "sealed.backup_excluded";
|
|
67
|
+
readonly status: "planned";
|
|
68
|
+
readonly enforcement: "device";
|
|
69
|
+
readonly capability: "sealed_history";
|
|
70
|
+
readonly step: "S29";
|
|
71
|
+
readonly says: "Sealed chats saved on a phone are left out of the phone's backups.";
|
|
72
|
+
}, {
|
|
73
|
+
readonly id: "sealed.no_push";
|
|
74
|
+
readonly status: "enforced";
|
|
75
|
+
readonly enforcement: "server";
|
|
76
|
+
readonly capability: "chat_tier";
|
|
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.";
|
|
79
|
+
}];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Generated by scripts/privacy-claims.mjs from docs/privacy-claims.json. Do not edit: CI refuses a hand edit.
|
|
2
|
+
// Change the registry, then run: node scripts/privacy-claims.mjs --write
|
|
3
|
+
export const PRIVACY_REGISTRY_VERSION = 0;
|
|
4
|
+
export const PRIVACY_FACTS = [
|
|
5
|
+
{
|
|
6
|
+
id: "agents.tool_mode.chat_only",
|
|
7
|
+
status: "planned",
|
|
8
|
+
enforcement: "server",
|
|
9
|
+
capability: "web_tools",
|
|
10
|
+
step: "S5",
|
|
11
|
+
says: "An agent in chat_only tool mode is given no tools, so it opens no web page.",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: "agents.turn_stamp",
|
|
15
|
+
status: "enforced",
|
|
16
|
+
enforcement: "server",
|
|
17
|
+
capability: null,
|
|
18
|
+
step: "S7",
|
|
19
|
+
says: "Every reply a model writes in an agent chat through the platform's agent turn records, in metadata.ai, the model, its maker and the route, a model swapped in and whether for usage limits or after a failure, and the tools it called.",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "agents.personal_context_sections",
|
|
23
|
+
status: "planned",
|
|
24
|
+
enforcement: "server",
|
|
25
|
+
capability: "activity",
|
|
26
|
+
step: "S26",
|
|
27
|
+
says: "A personal agent's turn carries no follows, upvotes, groups or views of the member unless the member turned that part of their activity on.",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "sealed.attest_before_send",
|
|
31
|
+
status: "enforced",
|
|
32
|
+
enforcement: "device",
|
|
33
|
+
capability: "chat_tier",
|
|
34
|
+
step: "S28",
|
|
35
|
+
says: "The phone seals a Sealed request only to the key of a router it checked against a fresh challenge of its own: 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. 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.",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "sealed.attest_second_signer",
|
|
39
|
+
status: "planned",
|
|
40
|
+
enforcement: "device",
|
|
41
|
+
capability: "chat_tier",
|
|
42
|
+
step: "S28",
|
|
43
|
+
says: "The phone also requires Recursiv's own signature over the router's release, so a release Tinfoil signed alone is refused.",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "sealed.no_standard_fallback",
|
|
47
|
+
status: "enforced",
|
|
48
|
+
enforcement: "client",
|
|
49
|
+
capability: "chat_tier",
|
|
50
|
+
step: "S28",
|
|
51
|
+
says: "The SDK sends a Sealed request only to the Sealed route, marked Sealed, and only once: a refusal, an error or an answer that is not sealed goes back to the app, and the SDK never sends the request again, to Sealed or to any other route.",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "sealed.gateway_opaque",
|
|
55
|
+
status: "enforced",
|
|
56
|
+
enforcement: "server",
|
|
57
|
+
capability: "chat_tier",
|
|
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.",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "sealed.dest_tinfoil_only",
|
|
63
|
+
status: "enforced",
|
|
64
|
+
enforcement: "server",
|
|
65
|
+
capability: "chat_tier",
|
|
66
|
+
step: "S28",
|
|
67
|
+
says: "The Sealed gateway sends Sealed requests, and asks for attestation documents, only to the router origins its configuration lists, named exactly, and it lists only https origins of Tinfoil router hosts (inference.tinfoil.sh or router-N.tinfoil.sh). It refuses any other server a client names and follows no redirect.",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "sealed.no_server_history",
|
|
71
|
+
status: "enforced",
|
|
72
|
+
enforcement: "server",
|
|
73
|
+
capability: "sealed_history",
|
|
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.",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "sealed.backup_excluded",
|
|
79
|
+
status: "planned",
|
|
80
|
+
enforcement: "device",
|
|
81
|
+
capability: "sealed_history",
|
|
82
|
+
step: "S29",
|
|
83
|
+
says: "Sealed chats saved on a phone are left out of the phone's backups.",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "sealed.no_push",
|
|
87
|
+
status: "enforced",
|
|
88
|
+
enforcement: "server",
|
|
89
|
+
capability: "chat_tier",
|
|
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.",
|
|
92
|
+
},
|
|
93
|
+
];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@recursiv/sdk/privacy`: the platform privacy facts, generated from the claims registry (docs/privacy-claims.json
|
|
3
|
+
* in recursivlabs/recursiv). Each fact says one thing the platform does with member data and whether this SDK release
|
|
4
|
+
* marks it enforced, which it does only once every test that proves it is real and runs in CI.
|
|
5
|
+
*
|
|
6
|
+
* An app shows a privacy sentence only when the facts it rests on are live: enforced here AND listed by the API it
|
|
7
|
+
* talks to (`sdk.privacy.capabilities()`), so neither a newer SDK nor a newer API can make a claim on its own. A fact
|
|
8
|
+
* held on the phone (`enforcement: 'device'`) needs a third check, the app's own: neither this SDK nor the API can see
|
|
9
|
+
* which native module the phone runs, so the app names the device facts its installed module carries (`deviceFacts`).
|
|
10
|
+
*
|
|
11
|
+
* The types live here, not in the SDK's shared types, so this entry point stands alone.
|
|
12
|
+
*/
|
|
13
|
+
import { PRIVACY_FACTS, PRIVACY_REGISTRY_VERSION } from './facts.generated.js';
|
|
14
|
+
export { PRIVACY_FACTS, PRIVACY_REGISTRY_VERSION };
|
|
15
|
+
export type PrivacyFact = (typeof PRIVACY_FACTS)[number];
|
|
16
|
+
export type PrivacyFactId = PrivacyFact['id'];
|
|
17
|
+
/** `planned`: the platform does not yet prove it. `enforced`: every test that proves it is real and runs in CI. */
|
|
18
|
+
export type PrivacyFactStatus = 'planned' | 'enforced';
|
|
19
|
+
/** Where a fact holds: on the server, on the phone (the native module), in the SDK, or in both server and client. */
|
|
20
|
+
export type PrivacyFactEnforcement = 'server' | 'device' | 'client' | 'server_and_client';
|
|
21
|
+
/** GET /privacy/capabilities: the facts the deployed API's build marks enforced, and the commit it runs. */
|
|
22
|
+
export interface PrivacyCapabilities {
|
|
23
|
+
/** The commit the API was built from, or `unknown`. */
|
|
24
|
+
api_commit: string;
|
|
25
|
+
/** Fact ids, sorted. An id this SDK release does not know is never live here. */
|
|
26
|
+
facts: string[];
|
|
27
|
+
}
|
|
28
|
+
/** The fact with this id, or undefined for an id this SDK release does not know. */
|
|
29
|
+
export declare function privacyFact(id: string): PrivacyFact | undefined;
|
|
30
|
+
/** Whether this SDK release marks the fact enforced. An unknown id is not. */
|
|
31
|
+
export declare function isFactEnforced(id: string): boolean;
|
|
32
|
+
export interface LiveFactOptions {
|
|
33
|
+
/**
|
|
34
|
+
* The device facts (`enforcement: 'device'`) the app's installed native module carries, as the app knows from the
|
|
35
|
+
* module revision it ships (for Sealed, @recursiv/e2ee-react-native). A device fact is live only when it is named
|
|
36
|
+
* here too. Left out, no device fact is live. A fact says what the module does, not what the app does with it: for
|
|
37
|
+
* `sealed.attest_before_send` the app chooses how long a checked router is reused, so copy that says the router is
|
|
38
|
+
* checked before every send needs the app to check before every send.
|
|
39
|
+
*/
|
|
40
|
+
deviceFacts?: Iterable<string>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Enforced in this SDK release AND listed by the deployed API, and for a device fact also named in `deviceFacts`.
|
|
44
|
+
* Missing capabilities mean nothing is live.
|
|
45
|
+
*/
|
|
46
|
+
export declare function isFactLive(id: string, capabilities: PrivacyCapabilities | null | undefined, options?: LiveFactOptions): boolean;
|
|
47
|
+
/** Every fact that is live for this API (and, for device facts, this app's native module), in registry order. */
|
|
48
|
+
export declare function liveFacts(capabilities: PrivacyCapabilities | null | undefined, options?: LiveFactOptions): PrivacyFactId[];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@recursiv/sdk/privacy`: the platform privacy facts, generated from the claims registry (docs/privacy-claims.json
|
|
3
|
+
* in recursivlabs/recursiv). Each fact says one thing the platform does with member data and whether this SDK release
|
|
4
|
+
* marks it enforced, which it does only once every test that proves it is real and runs in CI.
|
|
5
|
+
*
|
|
6
|
+
* An app shows a privacy sentence only when the facts it rests on are live: enforced here AND listed by the API it
|
|
7
|
+
* talks to (`sdk.privacy.capabilities()`), so neither a newer SDK nor a newer API can make a claim on its own. A fact
|
|
8
|
+
* held on the phone (`enforcement: 'device'`) needs a third check, the app's own: neither this SDK nor the API can see
|
|
9
|
+
* which native module the phone runs, so the app names the device facts its installed module carries (`deviceFacts`).
|
|
10
|
+
*
|
|
11
|
+
* The types live here, not in the SDK's shared types, so this entry point stands alone.
|
|
12
|
+
*/
|
|
13
|
+
import { PRIVACY_FACTS, PRIVACY_REGISTRY_VERSION } from './facts.generated.js';
|
|
14
|
+
export { PRIVACY_FACTS, PRIVACY_REGISTRY_VERSION };
|
|
15
|
+
const BY_ID = new Map(PRIVACY_FACTS.map((fact) => [fact.id, fact]));
|
|
16
|
+
/** The fact with this id, or undefined for an id this SDK release does not know. */
|
|
17
|
+
export function privacyFact(id) {
|
|
18
|
+
return BY_ID.get(id);
|
|
19
|
+
}
|
|
20
|
+
/** Whether this SDK release marks the fact enforced. An unknown id is not. */
|
|
21
|
+
export function isFactEnforced(id) {
|
|
22
|
+
return BY_ID.get(id)?.status === 'enforced';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Enforced in this SDK release AND listed by the deployed API, and for a device fact also named in `deviceFacts`.
|
|
26
|
+
* Missing capabilities mean nothing is live.
|
|
27
|
+
*/
|
|
28
|
+
export function isFactLive(id, capabilities, options = {}) {
|
|
29
|
+
const fact = BY_ID.get(id);
|
|
30
|
+
if (!fact || fact.status !== 'enforced')
|
|
31
|
+
return false;
|
|
32
|
+
if (!Array.isArray(capabilities?.facts) || !capabilities.facts.includes(id))
|
|
33
|
+
return false;
|
|
34
|
+
if (fact.enforcement === 'device')
|
|
35
|
+
return new Set(options.deviceFacts ?? []).has(id);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
/** Every fact that is live for this API (and, for device facts, this app's native module), in registry order. */
|
|
39
|
+
export function liveFacts(capabilities, options = {}) {
|
|
40
|
+
const deviceFacts = [...(options.deviceFacts ?? [])];
|
|
41
|
+
return PRIVACY_FACTS.filter((fact) => isFactLive(fact.id, capabilities, { deviceFacts })).map((fact) => fact.id);
|
|
42
|
+
}
|
package/dist/realtime.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Socket } from 'socket.io-client';
|
|
2
2
|
import { HttpClient } from './client.js';
|
|
3
|
-
import type { E2eeDevicesRealtimeEvent, E2eeLinkRealtimeEvent, E2eeRealtimeEvent } from './resources/e2ee.js';
|
|
3
|
+
import type { E2eeDevicesRealtimeEvent, E2eeLinkRealtimeEvent, E2eePeerRealtimeEvent, E2eeRealtimeEvent } from './resources/e2ee.js';
|
|
4
4
|
import type { ChatConversationEvent, ChatMembersEvent } from './types.js';
|
|
5
5
|
export interface ChatMessageEvent {
|
|
6
6
|
id: string;
|
|
@@ -150,8 +150,8 @@ export declare class RealtimeClient {
|
|
|
150
150
|
*
|
|
151
151
|
* Server events include `notification`, `feed_update`,
|
|
152
152
|
* `conversation_created`, `chat_message`, `chat_typing`, `agent_thinking`,
|
|
153
|
-
* `chat:members`, `chat:conversation`, `e2ee:event`, `e2ee:link
|
|
154
|
-
* `e2ee:devices`.
|
|
153
|
+
* `chat:members`, `chat:conversation`, `e2ee:event`, `e2ee:link`,
|
|
154
|
+
* `e2ee:devices` and `e2ee:peer`.
|
|
155
155
|
*/
|
|
156
156
|
on<T = unknown>(event: string, listener: (payload: T) => void): () => void;
|
|
157
157
|
/** Join a conversation room now, and again after every reconnect, until you leave it. */
|
|
@@ -199,4 +199,11 @@ export declare class RealtimeClient {
|
|
|
199
199
|
* `{ deviceId, reason: 'revoked' }`.
|
|
200
200
|
*/
|
|
201
201
|
onE2eeDevices(callback: (event: E2eeDevicesRealtimeEvent) => void): () => void;
|
|
202
|
+
/**
|
|
203
|
+
* Someone this account shares an encrypted conversation with reset encrypted
|
|
204
|
+
* chat: `{ userId, reason: 'root_changed', conversationId }`, once per shared
|
|
205
|
+
* conversation. Look at their devices again (`r.e2ee.devices({ user_id })`);
|
|
206
|
+
* catch up with `r.e2ee.peerChanges()` after time in the background.
|
|
207
|
+
*/
|
|
208
|
+
onE2eePeer(callback: (event: E2eePeerRealtimeEvent) => void): () => void;
|
|
202
209
|
}
|
package/dist/realtime.js
CHANGED
|
@@ -369,8 +369,8 @@ export class RealtimeClient {
|
|
|
369
369
|
*
|
|
370
370
|
* Server events include `notification`, `feed_update`,
|
|
371
371
|
* `conversation_created`, `chat_message`, `chat_typing`, `agent_thinking`,
|
|
372
|
-
* `chat:members`, `chat:conversation`, `e2ee:event`, `e2ee:link
|
|
373
|
-
* `e2ee:devices`.
|
|
372
|
+
* `chat:members`, `chat:conversation`, `e2ee:event`, `e2ee:link`,
|
|
373
|
+
* `e2ee:devices` and `e2ee:peer`.
|
|
374
374
|
*/
|
|
375
375
|
on(event, listener) {
|
|
376
376
|
// Every call is its own subscription, even for a function that is already
|
|
@@ -473,4 +473,13 @@ export class RealtimeClient {
|
|
|
473
473
|
onE2eeDevices(callback) {
|
|
474
474
|
return this.on('e2ee:devices', callback);
|
|
475
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* Someone this account shares an encrypted conversation with reset encrypted
|
|
478
|
+
* chat: `{ userId, reason: 'root_changed', conversationId }`, once per shared
|
|
479
|
+
* conversation. Look at their devices again (`r.e2ee.devices({ user_id })`);
|
|
480
|
+
* catch up with `r.e2ee.peerChanges()` after time in the background.
|
|
481
|
+
*/
|
|
482
|
+
onE2eePeer(callback) {
|
|
483
|
+
return this.on('e2ee:peer', callback);
|
|
484
|
+
}
|
|
476
485
|
}
|
|
@@ -234,7 +234,10 @@ export declare class AgentsResource {
|
|
|
234
234
|
}>;
|
|
235
235
|
/** Delete an agent */
|
|
236
236
|
delete(id: string): Promise<DeleteResponse>;
|
|
237
|
-
/**
|
|
237
|
+
/**
|
|
238
|
+
* Send a message to an agent (async — agent responds asynchronously).
|
|
239
|
+
* `turn: { safe: true }` makes it a safe turn in the caller's Asks thread (see `AgentChatTurn`).
|
|
240
|
+
*/
|
|
238
241
|
chat(id: string, input: AgentChatInput): Promise<SingleResponse<AgentChatResult>>;
|
|
239
242
|
/** List an agent's conversations */
|
|
240
243
|
conversations(id: string, params?: PaginationParams): Promise<PaginatedResponse<AgentConversation>>;
|
|
@@ -398,6 +401,8 @@ export declare class AgentsResource {
|
|
|
398
401
|
*
|
|
399
402
|
* Requires `ReadableStream` support (Node.js, modern browsers).
|
|
400
403
|
* For React Native, use `chatStreamText()` instead.
|
|
404
|
+
* `turn: { safe: true }` streams a safe turn in the caller's Asks thread (see `AgentChatTurn`); a refusal throws a
|
|
405
|
+
* `RecursivError` whose code is a `SafeTurnRefusalCode`, before anything streams.
|
|
401
406
|
*/
|
|
402
407
|
chatStream(id: string, input: AgentChatInput): AsyncGenerator<StreamChunk>;
|
|
403
408
|
/**
|
package/dist/resources/agents.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RecursivError } from '../errors.js';
|
|
1
|
+
import { RateLimitError, rateLimitDetailsFromResponse, RecursivError } from '../errors.js';
|
|
2
2
|
import { parseSSE } from '../lib/sse.js';
|
|
3
3
|
// ── Agent directory (GET /agents/discover) ──
|
|
4
4
|
/** The orders the agent directory serves (server: features/agents/agentDirectory.ts). */
|
|
@@ -83,7 +83,10 @@ export class AgentsResource {
|
|
|
83
83
|
delete(id) {
|
|
84
84
|
return this.client.delete(`/agents/${id}`);
|
|
85
85
|
}
|
|
86
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* Send a message to an agent (async — agent responds asynchronously).
|
|
88
|
+
* `turn: { safe: true }` makes it a safe turn in the caller's Asks thread (see `AgentChatTurn`).
|
|
89
|
+
*/
|
|
87
90
|
chat(id, input) {
|
|
88
91
|
return this.client.post(`/agents/${id}/chat`, input);
|
|
89
92
|
}
|
|
@@ -224,6 +227,8 @@ export class AgentsResource {
|
|
|
224
227
|
*
|
|
225
228
|
* Requires `ReadableStream` support (Node.js, modern browsers).
|
|
226
229
|
* For React Native, use `chatStreamText()` instead.
|
|
230
|
+
* `turn: { safe: true }` streams a safe turn in the caller's Asks thread (see `AgentChatTurn`); a refusal throws a
|
|
231
|
+
* `RecursivError` whose code is a `SafeTurnRefusalCode`, before anything streams.
|
|
227
232
|
*/
|
|
228
233
|
async *chatStream(id, input) {
|
|
229
234
|
yield* this.streamChunks(id, input);
|
|
@@ -286,6 +291,11 @@ export class AgentsResource {
|
|
|
286
291
|
code: 'stream_error',
|
|
287
292
|
});
|
|
288
293
|
}
|
|
294
|
+
// A 429 is a RateLimitError, as on every other request: with its scope and reset (a safe turn's daily cap is
|
|
295
|
+
// `scope: 'action'`, see SafeTurnRefusalCode).
|
|
296
|
+
if (response.status === 429 && errorBody?.error && typeof errorBody.error === 'object') {
|
|
297
|
+
throw new RateLimitError(errorBody.error, rateLimitDetailsFromResponse(response.headers, errorBody.error));
|
|
298
|
+
}
|
|
289
299
|
throw new RecursivError(response.status, errorBody.error);
|
|
290
300
|
}
|
|
291
301
|
return response;
|