@recursiv/sdk 0.7.122 → 0.7.123
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/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/resources/search.d.ts +72 -4
- package/dist/resources/search.js +3 -1
- package/llm.md +5 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -227,8 +227,8 @@ export type { ModerationTargetType, ModerationActionType, ModerationAppealStatus
|
|
|
227
227
|
export { TrustResource } from './resources/trust.js';
|
|
228
228
|
export type { TrustEnvelope, OwnTrustEvent, TrustPublicKey, OwnTrustEvents } from './resources/trust.js';
|
|
229
229
|
export { LinkPreviewResource } from './resources/link-preview.js';
|
|
230
|
-
export { 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, } from './resources/search.js';
|
|
230
|
+
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';
|
|
232
232
|
export { BOOKMARK_MERGE_MAX_ITEMS, BookmarkCollectionsResource, BookmarksResource } from './resources/bookmarks.js';
|
|
233
233
|
export { FEED_TOP_NETWORKS, FeedsResource } from './resources/feeds.js';
|
|
234
234
|
export type { FeedStoriesParams, FeedStoriesResponse, FeedStory, FeedTopExplain, FeedTopItem, FeedTopMeta, FeedTopNetwork, FeedTopNetworkCard, FeedTopNetworkEntry, FeedTopNetworkMap, FeedTopParams, FeedTopResponse, FeedTopTarget, PublicFeedTopMeta, PublicFeedTopParams, PublicFeedTopResponse, } from './resources/feeds.js';
|
package/dist/index.js
CHANGED
|
@@ -284,7 +284,7 @@ export { JudgmentsResource, isJudgmentSharedWordsError } from './resources/judgm
|
|
|
284
284
|
export { ModerationResource } from './resources/moderation.js';
|
|
285
285
|
export { TrustResource } from './resources/trust.js';
|
|
286
286
|
export { LinkPreviewResource } from './resources/link-preview.js';
|
|
287
|
-
export { SEARCH_SECTIONS, SearchResource } from './resources/search.js';
|
|
287
|
+
export { SEARCH_MEDIA_KINDS, SEARCH_SECTIONS, SearchResource } from './resources/search.js';
|
|
288
288
|
export { BOOKMARK_MERGE_MAX_ITEMS, BookmarkCollectionsResource, BookmarksResource } from './resources/bookmarks.js';
|
|
289
289
|
export { FEED_TOP_NETWORKS, FeedsResource } from './resources/feeds.js';
|
|
290
290
|
export { AccountsResource } from './resources/accounts.js';
|
|
@@ -2,7 +2,7 @@ import type { HttpClient } from '../client.js';
|
|
|
2
2
|
import type { Post, StoryOutlets, ViewerModeration } from '../types.js';
|
|
3
3
|
import type { SocialPost } from './protocols.js';
|
|
4
4
|
/** The sections a blended search can answer, in no particular order (see `SearchAnswer.order`). */
|
|
5
|
-
export declare const SEARCH_SECTIONS: readonly ["top_posts", "latest_posts", "open_network", "people", "groups", "topics", "stories", "related", "trending"];
|
|
5
|
+
export declare const SEARCH_SECTIONS: readonly ["top_posts", "latest_posts", "open_network", "people", "groups", "topics", "stories", "related", "trending", "media"];
|
|
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';
|
|
@@ -39,8 +39,11 @@ export interface SearchLadder {
|
|
|
39
39
|
export type SearchPost = Post & {
|
|
40
40
|
via?: SearchVia;
|
|
41
41
|
};
|
|
42
|
-
/**
|
|
43
|
-
|
|
42
|
+
/**
|
|
43
|
+
* A visitor's search tabs (tRPC `publicDiscovery.search`, read keyless through the app's public client). `media` (server
|
|
44
|
+
* 0.7.123): no items, the page's `media` section instead.
|
|
45
|
+
*/
|
|
46
|
+
export type PublicSearchTab = 'top' | 'latest' | 'people' | 'groups' | 'videos' | 'news' | 'tag' | 'media';
|
|
44
47
|
/** `fast` answers within about a second; `deep` waits for the reads `fast` left running. */
|
|
45
48
|
export type SearchStage = 'fast' | 'deep';
|
|
46
49
|
/** One page of a visitor's search: every item labelled `via`, never empty while the app has anything popular. */
|
|
@@ -57,15 +60,75 @@ export interface PublicSearchPage<T = Record<string, unknown>> {
|
|
|
57
60
|
next_cursor: string | null;
|
|
58
61
|
has_more: boolean;
|
|
59
62
|
};
|
|
63
|
+
/** The `media` tab only: what the web has for the words. Absent where the app does not get it (`ladder.unavailable` names `media`). */
|
|
64
|
+
media?: SearchMedia;
|
|
65
|
+
}
|
|
66
|
+
/** The kinds of a search's media items, in the order the server lists them. */
|
|
67
|
+
export declare const SEARCH_MEDIA_KINDS: readonly ["about", "video", "article", "image", "audio"];
|
|
68
|
+
export type SearchMediaKind = (typeof SEARCH_MEDIA_KINDS)[number];
|
|
69
|
+
/** Where a media item was found. */
|
|
70
|
+
export type SearchMediaSource = 'brave' | 'wikipedia' | 'peertube' | 'openverse';
|
|
71
|
+
/**
|
|
72
|
+
* How a video may play in place: YouTube's own player for `id` (use youtube-nocookie.com and follow its player rules:
|
|
73
|
+
* at least 200x200, nothing drawn over it, YouTube shown as the source), or a PeerTube instance's own embed page.
|
|
74
|
+
*/
|
|
75
|
+
export type SearchMediaEmbed = {
|
|
76
|
+
provider: 'youtube';
|
|
77
|
+
id: string;
|
|
78
|
+
} | {
|
|
79
|
+
provider: 'peertube';
|
|
80
|
+
url: string;
|
|
81
|
+
};
|
|
82
|
+
/** One item of the media section: a video, a picture, a news article, a sound or the about card. */
|
|
83
|
+
export interface SearchMediaItem {
|
|
84
|
+
kind: SearchMediaKind;
|
|
85
|
+
source: SearchMediaSource;
|
|
86
|
+
title: string;
|
|
87
|
+
/** The page it lives on: open it when the item is tapped. */
|
|
88
|
+
url: string;
|
|
89
|
+
/** The picture to draw, always on the API's signed media proxy; null when there is none. A picture item always has one. */
|
|
90
|
+
thumbnail: string | null;
|
|
91
|
+
width: number | null;
|
|
92
|
+
height: number | null;
|
|
93
|
+
duration_s: number | null;
|
|
94
|
+
/** The channel, outlet or creator. */
|
|
95
|
+
publisher: string | null;
|
|
96
|
+
/** ISO 8601. */
|
|
97
|
+
published_at: string | null;
|
|
98
|
+
/** A news description, or the about card's extract. */
|
|
99
|
+
description: string | null;
|
|
100
|
+
embed: SearchMediaEmbed | null;
|
|
101
|
+
/** The credit a licensed work requires: show it with the work. */
|
|
102
|
+
attribution: string | null;
|
|
103
|
+
license: string | null;
|
|
104
|
+
/**
|
|
105
|
+
* Its picture was judged suggestive: present only for a member who turned Show NSFW on, who is shown it blurred.
|
|
106
|
+
* Visitors and members on safe defaults are never served such an item.
|
|
107
|
+
*/
|
|
108
|
+
sensitive?: true;
|
|
109
|
+
}
|
|
110
|
+
export type SearchMediaProvider = 'brave_web' | 'brave_images' | 'wikipedia' | 'peertube' | 'openverse_images' | 'openverse_audio';
|
|
111
|
+
/**
|
|
112
|
+
* What each provider did for this answer; `timeout`: it is still reading, ask again shortly for more; `budget`: a
|
|
113
|
+
* spending limit held it back (the day's Brave calls, or this caller's own calls a day or fresh answers an hour, past
|
|
114
|
+
* which only what is already cached is served).
|
|
115
|
+
*/
|
|
116
|
+
export type SearchMediaProviderStatus = 'ok' | 'cached' | 'empty' | 'skipped' | 'budget' | 'unconfigured' | 'timeout' | 'error';
|
|
117
|
+
/** The media section: what the web has for the words (server 0.7.123). */
|
|
118
|
+
export interface SearchMedia {
|
|
119
|
+
items: SearchMediaItem[];
|
|
120
|
+
providers: Partial<Record<SearchMediaProvider, SearchMediaProviderStatus>>;
|
|
60
121
|
}
|
|
61
122
|
export interface SearchParams {
|
|
62
123
|
q: string;
|
|
63
124
|
/** Items per section, 1-20 (default 6). */
|
|
64
125
|
limit?: number;
|
|
65
|
-
/** Only these sections (default: all). */
|
|
126
|
+
/** Only these sections (default: all but `media`, which answers only when named: each may spend a paid web search). */
|
|
66
127
|
sections?: readonly SearchSection[];
|
|
67
128
|
/** For organization-bound keys, as on `posts.search`. */
|
|
68
129
|
organization_id?: string;
|
|
130
|
+
/** How many pictures the app already shows for the query: the media section asks the web for pictures only when fewer than six. */
|
|
131
|
+
own_images?: number;
|
|
69
132
|
}
|
|
70
133
|
export interface SearchPerson {
|
|
71
134
|
id: string;
|
|
@@ -205,6 +268,11 @@ export interface SearchAnswer {
|
|
|
205
268
|
} | null;
|
|
206
269
|
items: SearchPost[];
|
|
207
270
|
};
|
|
271
|
+
/**
|
|
272
|
+
* What the web has for the words (server 0.7.123): videos, news, pictures, sound and an about card, only on the
|
|
273
|
+
* networks the server offers it to (others list it in `omitted` as `unavailable`).
|
|
274
|
+
*/
|
|
275
|
+
media?: SearchMedia;
|
|
208
276
|
};
|
|
209
277
|
/** Answered, non-empty sections in the order to render them. */
|
|
210
278
|
order: SearchSection[];
|
package/dist/resources/search.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** The sections a blended search can answer, in no particular order (see `SearchAnswer.order`). */
|
|
2
|
-
export const SEARCH_SECTIONS = ['top_posts', 'latest_posts', 'open_network', 'people', 'groups', 'topics', 'stories', 'related', 'trending'];
|
|
2
|
+
export const SEARCH_SECTIONS = ['top_posts', 'latest_posts', 'open_network', 'people', 'groups', 'topics', 'stories', 'related', 'trending', 'media'];
|
|
3
|
+
/** The kinds of a search's media items, in the order the server lists them. */
|
|
4
|
+
export const SEARCH_MEDIA_KINDS = ['about', 'video', 'article', 'image', 'audio'];
|
|
3
5
|
export class SearchResource {
|
|
4
6
|
client;
|
|
5
7
|
constructor(client) {
|
package/llm.md
CHANGED
|
@@ -739,9 +739,13 @@ Each answers 404 while the app's operator has it off; `feeds.top` is private to
|
|
|
739
739
|
// One query, answered as sections. Each has its own time budget; a slow one is listed in `omitted`.
|
|
740
740
|
const { data: answer } = await r.search.query({ q: 'apple', limit: 6 })
|
|
741
741
|
for (const section of answer.order) render(section, answer.sections[section])
|
|
742
|
-
// top_posts, latest_posts, open_network, people, groups, topics, stories, related, trending
|
|
742
|
+
// top_posts, latest_posts, open_network, people, groups, topics, stories, related, trending, media
|
|
743
|
+
// What the web has for the words, alone, so it paints beside the rest (0.7.123):
|
|
744
|
+
const { data: web } = await r.search.query({ q: 'hockey', sections: ['media'], own_images: shownPictures })
|
|
743
745
|
```
|
|
744
746
|
|
|
747
|
+
`media` (0.7.123): videos (YouTube ids as `embed`, PeerTube embed pages), news articles, pictures, sound and one `about` card (Wikipedia), from Brave Search, Wikipedia, PeerTube and Openverse with strict safe search. It answers only when `sections` names it (the default sections leave it out: each answer may spend a paid web search). Every picture passes the same vision check a post's picture does: a visitor sees only pictures judged safe, and a member who turned Show NSFW on gets a suggestive one marked `sensitive` (blur it). Every `thumbnail` is on the API's signed media proxy; play a YouTube embed through youtube-nocookie.com by its player's rules and show each `attribution`. `own_images` (how many pictures the page already shows) lets the server ask for the web's pictures only when fewer than six. Only the networks the server offers it to get it (others: `omitted` `unavailable`); `providers` says what each source did (`timeout`: ask again shortly). Visitors read it as `publicDiscovery.search` `tab: 'media'` (`PublicSearchPage.media`).
|
|
748
|
+
|
|
745
749
|
`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`).
|
|
746
750
|
|
|
747
751
|
### r.curator — World Today and its story pages
|