@recursiv/sdk 0.7.78 → 0.7.79

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 CHANGED
@@ -94,6 +94,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
94
94
  | Resource | Key methods |
95
95
  |----------|------------|
96
96
  | `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` |
97
+ | `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) |
97
98
  | `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`) |
98
99
  | `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) |
99
100
  | `r.communities` | `create`, `join`, `search`, `members` |
package/dist/index.d.ts CHANGED
@@ -211,7 +211,7 @@ export { ModerationResource } from './resources/moderation.js';
211
211
  export type { ModerationTargetType, ModerationActionType, ModerationAppealStatus, ModerationPrinciple, PublicModerationAction, PublicModerationLog, OwnModerationAppeal, OwnModerationAction, OwnModerationLog, ApplyModerationActionInput, ModerationAction, ListModerationActionsParams, RecordedModerationTargetType, AgentModerationMode, AgentModerationGrant, } from './resources/moderation.js';
212
212
  export { LinkPreviewResource } from './resources/link-preview.js';
213
213
  export { SEARCH_SECTIONS, SearchResource } from './resources/search.js';
214
- export type { SearchAnswer, SearchGroup, SearchOmitReason, SearchParams, SearchPerson, SearchRelated, SearchResponse, SearchSection, SearchStory, SearchTopic } from './resources/search.js';
214
+ export type { PublicSearchPage, PublicSearchTab, SearchAnswer, SearchGroup, SearchLadder, SearchOmitReason, SearchParams, SearchPerson, SearchPost, SearchRelated, SearchResponse, SearchSection, SearchStage, SearchStory, SearchTopic, SearchVia, } from './resources/search.js';
215
215
  export { BOOKMARK_MERGE_MAX_ITEMS, BookmarkCollectionsResource, BookmarksResource } from './resources/bookmarks.js';
216
216
  export { FEED_TOP_NETWORKS, FeedsResource } from './resources/feeds.js';
217
217
  export type { FeedStoriesParams, FeedStoriesResponse, FeedStory, FeedTopExplain, FeedTopItem, FeedTopMeta, FeedTopNetwork, FeedTopNetworkCard, FeedTopNetworkEntry, FeedTopParams, FeedTopResponse, FeedTopTarget, PublicFeedTopMeta, PublicFeedTopParams, PublicFeedTopResponse, } from './resources/feeds.js';
@@ -6,6 +6,58 @@ export declare const SEARCH_SECTIONS: readonly ["top_posts", "latest_posts", "op
6
6
  export type SearchSection = (typeof SEARCH_SECTIONS)[number];
7
7
  /** Why a section is absent: out of time, the server was busy, not available for this app, not allowed for this key, or it failed. */
8
8
  export type SearchOmitReason = 'timeout' | 'saturated' | 'unavailable' | 'scope' | 'error';
9
+ /**
10
+ * Where an item of a search came from (the search ladder, server 0.7.79): the words as written, the word a typo meant,
11
+ * the known words with the rest dropped, and what is popular in the category the words are about or on the app. The
12
+ * deep rungs (`semantic`, `related_topic`, `open_network`) are named ahead of their servers.
13
+ */
14
+ export type SearchVia = 'exact' | 'did_you_mean' | 'relaxed' | 'semantic' | 'related_topic' | 'open_network' | 'trending_category' | 'trending';
15
+ /**
16
+ * The search ladder's account of an answer, so an app labels it honestly: "No exact matches for X" (`exactCount` 0),
17
+ * "Did you mean Y?" (`didYouMean`), "Showing posts about memes" (`keptTerms`, `droppedTerms`), "Related: Comedy"
18
+ * (`inferredCategories`), "Popular in Comedy right now". `steps` names the rungs that answered, in order (`['guarded']`
19
+ * alone: the query gets what is popular and no suggestion). `withheld` and `pending` count posts a visitor's floors held
20
+ * back. `unavailable` names sections this key cannot read: say so, never fill them.
21
+ */
22
+ export interface SearchLadder {
23
+ exactCount: number;
24
+ didYouMean: string | null;
25
+ keptTerms: string[];
26
+ droppedTerms: string[];
27
+ inferredCategories: Array<{
28
+ id: string;
29
+ name: string;
30
+ via: 'name' | 'seed' | 'alias' | 'emoji';
31
+ }>;
32
+ expandedTags: string[];
33
+ steps: string[];
34
+ withheld: number;
35
+ pending: number;
36
+ unavailable: string[];
37
+ }
38
+ /** A post as a search lists it: `via` says how the ladder found it (absent from servers before 0.7.79). */
39
+ export type SearchPost = Post & {
40
+ via?: SearchVia;
41
+ };
42
+ /** A visitor's search tabs (tRPC `publicDiscovery.search`, read keyless through the app's public client). */
43
+ export type PublicSearchTab = 'top' | 'latest' | 'people' | 'groups' | 'videos' | 'news' | 'tag';
44
+ /** `fast` answers within about a second; `deep` waits for the reads `fast` left running. */
45
+ export type SearchStage = 'fast' | 'deep';
46
+ /** One page of a visitor's search: every item labelled `via`, never empty while the app has anything popular. */
47
+ export interface PublicSearchPage<T = Record<string, unknown>> {
48
+ tab: PublicSearchTab;
49
+ q: string;
50
+ items: Array<T & {
51
+ via: SearchVia;
52
+ }>;
53
+ ladder: SearchLadder;
54
+ meta: {
55
+ limit: number;
56
+ stage: SearchStage;
57
+ next_cursor: string | null;
58
+ has_more: boolean;
59
+ };
60
+ }
9
61
  export interface SearchParams {
10
62
  q: string;
11
63
  /** Items per section, 1-20 (default 6). */
@@ -88,9 +140,10 @@ export interface SearchStory {
88
140
  } | null;
89
141
  /**
90
142
  * Where the words were found: the story's headline, or only its members'. `article` (a server newer than 0.7.74): no
91
- * story is about the query, and this is one outlet's article whose headline carries its words.
143
+ * story is about the query, and this is one outlet's article whose headline carries its words. `related` (a server
144
+ * newer than 0.7.78): neither, and a visitor's search ladder served it as a story about what the words are about.
92
145
  */
93
- matched: 'label' | 'member' | 'article';
146
+ matched: 'label' | 'member' | 'article' | 'related';
94
147
  /** An `article`'s link and outlet. */
95
148
  article?: {
96
149
  url: string;
@@ -117,12 +170,12 @@ export interface SearchAnswer {
117
170
  sections: {
118
171
  /** Relevance x recency x engagement, through the promotion safety floor. `has_more`: page further with `posts.search`. */
119
172
  top_posts?: {
120
- items: Post[];
173
+ items: SearchPost[];
121
174
  has_more: boolean;
122
175
  };
123
176
  /** Newest first, never repeating a top post. `partial`: these are the newest of what was read in time. */
124
177
  latest_posts?: {
125
- items: Post[];
178
+ items: SearchPost[];
126
179
  partial: boolean;
127
180
  };
128
181
  open_network?: {
@@ -144,12 +197,13 @@ export interface SearchAnswer {
144
197
  /** Categories and topics around the matches. */
145
198
  related?: SearchRelated;
146
199
  /** Present when the answer is thin or old: what is moving in the nearest category. */
200
+ /** `category` null with the ladder: what is popular on the app right now. */
147
201
  trending?: {
148
202
  category: {
149
203
  id: string;
150
204
  name: string;
151
205
  } | null;
152
- items: Post[];
206
+ items: SearchPost[];
153
207
  };
154
208
  };
155
209
  /** Answered, non-empty sections in the order to render them. */
@@ -161,6 +215,8 @@ export interface SearchAnswer {
161
215
  }>;
162
216
  /** Fewer than five matches across Minds and the open networks. */
163
217
  few_results: boolean;
218
+ /** The search ladder's account of the answer (server 0.7.79): present when the server ran the ladder. */
219
+ ladder?: SearchLadder;
164
220
  }
165
221
  export interface SearchResponse {
166
222
  data: SearchAnswer;
package/llm.md CHANGED
@@ -703,7 +703,7 @@ for (const section of answer.order) render(section, answer.sections[section])
703
703
  // top_posts, latest_posts, open_network, people, groups, topics, stories, related, trending
704
704
  ```
705
705
 
706
- `trending` joins when the answer is thin or old, so a search never dead-ends. `top_posts` is floored as `r.posts.search`'s relevance page is; `people` rows carry `followers_count`, `posts_count`, `empty` and `verified` (see `r.profiles.search`); `groups` rows carry `description` (one line) and `last_active_at`, to tell groups of one name apart. Page further with `r.posts.search`. Needs `posts:read`; `people` needs `users:read`, `groups` `communities:read`; `open_network` and `stories` need `users:read` plus the caller's own app key on its network, `trending` that app key. What the key cannot have is in `omitted` (`scope` / `unavailable`).
706
+ `trending` joins when the answer is thin or old, so a search never dead-ends. A thin answer steps down the search ladder (0.7.79): the word a typo meant, the known words with the rest dropped ("wiggly memes" searches "memes"), what is popular in the category the words are about, then on the app. Every item says how in `via` (`SearchVia`) and `answer.ladder` (`SearchLadder`) says what happened: label it honestly ("No exact matches for X", "Did you mean Y?", "Popular in Comedy right now"); `ladder.unavailable` names sections the key cannot read. Visitors read the same ladder keyless through tRPC `publicDiscovery.search` (`PublicSearchPage`). `top_posts` is floored as `r.posts.search`'s relevance page is; `people` rows carry `followers_count`, `posts_count`, `empty` and `verified` (see `r.profiles.search`); `groups` rows carry `description` (one line) and `last_active_at`, to tell groups of one name apart. Page further with `r.posts.search`. Needs `posts:read`; `people` needs `users:read`, `groups` `communities:read`; `open_network` and `stories` need `users:read` plus the caller's own app key on its network, `trending` that app key. What the key cannot have is in `omitted` (`scope` / `unavailable`).
707
707
 
708
708
  ### r.curator — World Today and its story pages
709
709
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recursiv/sdk",
3
- "version": "0.7.78",
3
+ "version": "0.7.79",
4
4
  "description": "TypeScript SDK for the Recursiv API",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "type": "module",