@recursiv/sdk 0.7.25 → 0.7.26
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 +5 -0
- package/dist/client.d.ts +3 -1
- package/dist/client.js +4 -3
- package/dist/resources/protocols.d.ts +3 -1
- package/dist/resources/protocols.js +5 -3
- package/llm.md +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -454,3 +454,8 @@ approve: true })`. Preserve that exact event on uncertain retries. Check
|
|
|
454
454
|
`getNativeNostrPost(identityId, eventId)` for relay visibility. An owned note can
|
|
455
455
|
prepare `{ action: 'delete', postId }`; deletion is a signed request, not a
|
|
456
456
|
promise of erasure across all relays. Keys are never sent to this SDK service.
|
|
457
|
+
Preparation and submission never retry automatically, even when `maxRetries` is
|
|
458
|
+
configured. After an uncertain submission, check
|
|
459
|
+
`getNativeNostrPost(identityId, preview.postId ?? preview.eventId)`: deletion uses
|
|
460
|
+
the original note's `postId`, while publication uses the new `eventId`. Any
|
|
461
|
+
user-selected retry must keep the same intent and signed event.
|
package/dist/client.d.ts
CHANGED
|
@@ -30,7 +30,9 @@ export declare class HttpClient {
|
|
|
30
30
|
private getAuthHeaders;
|
|
31
31
|
private handleResponse;
|
|
32
32
|
get<T>(path: string, params?: Record<string, unknown>): Promise<T>;
|
|
33
|
-
post<T>(path: string, body?: unknown
|
|
33
|
+
post<T>(path: string, body?: unknown, options?: {
|
|
34
|
+
retry?: boolean;
|
|
35
|
+
}): Promise<T>;
|
|
34
36
|
put<T>(path: string, body?: unknown): Promise<T>;
|
|
35
37
|
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
36
38
|
delete<T>(path: string): Promise<T>;
|
package/dist/client.js
CHANGED
|
@@ -165,16 +165,17 @@ export class HttpClient {
|
|
|
165
165
|
});
|
|
166
166
|
return this.handleResponse(response);
|
|
167
167
|
}
|
|
168
|
-
async post(path, body) {
|
|
168
|
+
async post(path, body, options) {
|
|
169
169
|
const url = this.buildUrl(path);
|
|
170
|
-
const
|
|
170
|
+
const request = {
|
|
171
171
|
method: 'POST',
|
|
172
172
|
headers: {
|
|
173
173
|
...this.getAuthHeaders(),
|
|
174
174
|
'Content-Type': 'application/json',
|
|
175
175
|
},
|
|
176
176
|
body: body ? JSON.stringify(body) : undefined,
|
|
177
|
-
}
|
|
177
|
+
};
|
|
178
|
+
const response = await (options?.retry === false ? this.fetchWithTimeout(url, request) : this.fetchWithRetry(url, request));
|
|
178
179
|
return this.handleResponse(response);
|
|
179
180
|
}
|
|
180
181
|
async put(path, body) {
|
|
@@ -421,8 +421,10 @@ export declare class ProtocolsResource {
|
|
|
421
421
|
}): Promise<SingleResponse<SocialTrendFeed>>;
|
|
422
422
|
/** Native writes are off unless enabled for this exact app; public readers are independent. */
|
|
423
423
|
nativeNostrAccount(): Promise<SingleResponse<NativeNostrAccount>>;
|
|
424
|
+
/** Prepare an exact event for review. A timeout never automatically creates another signing request. */
|
|
424
425
|
prepareNativeNostr(id: string, input: NativeNostrPrepareInput): Promise<SingleResponse<NativeNostrPrepared>>;
|
|
425
|
-
/** Pass only the public signed event.
|
|
426
|
+
/** Pass only the public signed event. After a timeout, read the prepared postId (delete) or eventId (publish).
|
|
427
|
+
* Any user-selected retry keeps the same intent/event. */
|
|
426
428
|
submitNativeNostr(id: string, input: {
|
|
427
429
|
intent: string;
|
|
428
430
|
event: HostedNostrIdentityProof;
|
|
@@ -94,18 +94,20 @@ export class ProtocolsResource {
|
|
|
94
94
|
nativeNostrAccount() {
|
|
95
95
|
return this.client.get('/protocols/social/nostr/account');
|
|
96
96
|
}
|
|
97
|
+
/** Prepare an exact event for review. A timeout never automatically creates another signing request. */
|
|
97
98
|
prepareNativeNostr(id, input) {
|
|
98
99
|
hostedIdentityPath(id);
|
|
99
100
|
const body = input.action === 'publish' ? { action: input.action, content: input.content } : { action: input.action, postId: input.postId };
|
|
100
|
-
return this.client.post(`/protocols/social/nostr/${encodeURIComponent(id)}/prepare`, body);
|
|
101
|
+
return this.client.post(`/protocols/social/nostr/${encodeURIComponent(id)}/prepare`, body, { retry: false });
|
|
101
102
|
}
|
|
102
|
-
/** Pass only the public signed event.
|
|
103
|
+
/** Pass only the public signed event. After a timeout, read the prepared postId (delete) or eventId (publish).
|
|
104
|
+
* Any user-selected retry keeps the same intent/event. */
|
|
103
105
|
submitNativeNostr(id, input) {
|
|
104
106
|
hostedIdentityPath(id);
|
|
105
107
|
const { id: eventId, pubkey, sig, kind, content, created_at, tags } = input.event;
|
|
106
108
|
return this.client.post(`/protocols/social/nostr/${encodeURIComponent(id)}/submit`, {
|
|
107
109
|
intent: input.intent, event: { id: eventId, pubkey, sig, kind, content, created_at, tags }, approve: input.approve,
|
|
108
|
-
});
|
|
110
|
+
}, { retry: false });
|
|
109
111
|
}
|
|
110
112
|
getNativeNostrPost(id, postId) {
|
|
111
113
|
hostedIdentityPath(id);
|
package/llm.md
CHANGED
|
@@ -620,6 +620,7 @@ if (subscription.active) {
|
|
|
620
620
|
- `r.inviteCodes` / `r.inviteCodesAdmin` — Invite code management
|
|
621
621
|
- `r.organizationSettings` / `r.organizationSecurity` — Org configuration
|
|
622
622
|
- `r.protocols` — Public reading: `publicNetworks`, `searchPublicProfiles`, `getPublicProfile`, `getPublicAuthorFeed`, `getFollowingFeed`, `getPublicConversation`, `getPublicTrends`, `getPublicTrendFeed`; private app subscriptions: `listSubscriptions`, `subscribeToProfile`, `unsubscribeFromProfile`, `onSubscriptionChange`. Example after selecting a returned source post: `const { data: thread } = await r.protocols.getPublicConversation({ protocol: post.protocol, post: post.nativeId, readRef: post.readRef })`. Render `focus`, oldest-first `ancestors` and direct `replies`; `public_provider_window` never promises every reply, and `limited` marks known omissions. Requires both `users:read` and `posts:read` on the current human app key. Protocol discovery/settings: `const { data: adapters } = await r.protocols.list()` returns bounded `{ id, name, icon, color, maturity, capabilities, limitations }` metadata; `supported` means implemented, not configured, healthy, authorized, or enabled. Methods: `list`, `status`, `listCandidates`, `getCandidate`, `search`, `getSettings`, `refresh`, `updateSettings`.
|
|
623
|
+
- Native Nostr: `const { data: preview } = await r.protocols.prepareNativeNostr(identityId, { action: "publish", content: draft })`; review and sign the exact public event, then `submitNativeNostr(identityId, { intent: preview.intent, event, approve: true })`. Preparation/submission never auto-retry. After uncertainty, use `getNativeNostrPost(identityId, preview.postId ?? preview.eventId)` before a user-selected retry of the identical intent/event: deletion checks the original note's `postId`, publication checks `eventId`. Check `nativeNostrAccount()` enablement first; keys stay with the signer.
|
|
623
624
|
- Public trends: require `public_trends` from `publicNetworks()`, then `getPublicTrends({ protocol, limit?, cursor? })`; render `kind: topics` as source topics and `kind: posts` as source posts. With `trend_feed`, open only a returned current topic using `getPublicTrendFeed({ protocol, topic: trend.nativeId, limit?, cursor? })`. Show provider, observedAt and provider_ranked_window coverage; null rankingWindow is unknown, not a daily/global ranking. Preserve source order, canonical IDs and readRef, and opaque cursors. Topic catalogs do not paginate; Mastodon trends stop at 200 source positions. Both methods require users:read plus posts:read on the current human app key; Nostr trends are unsupported. Propagate errors; trend_unavailable means refresh the topic list. No ingestion or native writes.
|
|
624
625
|
- `listCandidates({ protocol?, limit?, cursor? })` and `getCandidate(id)` are read-only quarantine review, not published-post search. Both require `admin` scope, a project-bound key, a live admin role, and existing project-admin access. The key supplies app/network scope; neither method accepts another project or network. They never invoke refresh, change settings, or publish.
|
|
625
626
|
- Lists return `{ data: ProtocolQuarantinedCandidate[], meta: { limit, has_more, next_cursor } }`; use the opaque `next_cursor`, not offset pagination. The API defaults `limit` to 20 and permits at most 50. Details return `{ data: ProtocolQuarantinedCandidate }`. Every candidate has `state: 'quarantined'` and `content_format: 'plain'`; render its bounded `content` as text, respect `content_truncated`, and distinguish upstream `published_at` from local `observed_at` / `created_at`.
|