@recursiv/sdk 0.7.26 → 0.7.28
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 +112 -1
- package/dist/index.d.ts +3 -3
- package/dist/resources/accounts.d.ts +8 -2
- package/dist/resources/accounts.js +1 -1
- package/dist/resources/curator.d.ts +68 -0
- package/dist/resources/curator.js +8 -0
- package/dist/resources/deployments.d.ts +42 -0
- package/dist/resources/deployments.js +14 -0
- package/dist/resources/moderation.d.ts +3 -2
- package/dist/resources/protocols.d.ts +366 -5
- package/dist/resources/protocols.js +143 -10
- package/dist/resources/reports.d.ts +4 -3
- package/llm.md +12 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
|
|
|
110
110
|
| `r.admin` | User management, stats, content reports (`listReports`, `resolveReport`, `dismissReport`) |
|
|
111
111
|
| `r.dispatcher` | Task queue, claims, signals, outcomes, webhooks |
|
|
112
112
|
| `r.goals` | Org goals with task rollups (group dispatcher tasks) |
|
|
113
|
-
| `r.protocols` | Public reading: `publicNetworks`, `searchPublicProfiles`, `getPublicProfile`, `getPublicAuthorFeed`, `getFollowingFeed`, `getPublicConversation`, `getPublicTrends`, `getPublicTrendFeed`; 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` |
|
|
113
|
+
| `r.protocols` | Private Minds safety: `sourceControls` (current enablement and saved choices), `setSourceControl`, `onSourceControlChange`, `reportSource`. Delegated accounts: `nativeSocialAccounts`, `startNativeSocialConnection`, `finishNativeSocialConnection`, `disconnectNativeSocialAccount`. Reviewed replies and optional linked posts: `prepareNativeReply`, `submitNativeReply`, `nativeReplyStatus`, `nativeReplyHistory`, `prepareNativeReplyRemoval`, `removeNativeReply` (require deployed API support and app enablement). Public reading: `publicNetworks`, `searchPublicProfiles`, `getPublicProfile`, `getPublicAuthorFeed`, `getFollowingFeed`, `getPublicConversation`, `getPublicTrends`, `getPublicTrendFeed`; 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` |
|
|
114
114
|
|
|
115
115
|
Full reference: see [llm.md](./llm.md) (ships with this package) or the type definitions in `dist/`.
|
|
116
116
|
|
|
@@ -459,3 +459,114 @@ configured. After an uncertain submission, check
|
|
|
459
459
|
`getNativeNostrPost(identityId, preview.postId ?? preview.eventId)`: deletion uses
|
|
460
460
|
the original note's `postId`, while publication uses the new `eventId`. Any
|
|
461
461
|
user-selected retry must keep the same intent and signed event.
|
|
462
|
+
|
|
463
|
+
When the deployed API advertises `reply_text_note`, the same method can prepare
|
|
464
|
+
`{ action: 'reply', content: draftText, parentId: selectedPost.nativeId }`. Review
|
|
465
|
+
the returned parent, root, participants, relay and exact event before asking the
|
|
466
|
+
signer to sign. The API constructs verified NIP-10 references; callers cannot
|
|
467
|
+
inject tags, participant lists, relay URLs or signing keys. Reply prepare/submit
|
|
468
|
+
also require `posts:read`. This capability remains off until the shared reply UI
|
|
469
|
+
and live delivery are verified. Only public kind-1 notes are supported; additional
|
|
470
|
+
participant selection is unfinished. `textTruncated` labels an abbreviated source
|
|
471
|
+
preview. Preparation and submission never automatically retry; check the event ID
|
|
472
|
+
after an uncertain result before choosing a retry of the identical signed event.
|
|
473
|
+
|
|
474
|
+
### Delegated Bluesky and ActivityPub accounts
|
|
475
|
+
|
|
476
|
+
These methods require the same signed-in human app key throughout. The API must
|
|
477
|
+
enable the app and deploy the authorization schema before use.
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
const { data: connection } = await r.protocols.startNativeSocialConnection({
|
|
481
|
+
protocol: 'bluesky', identifier: 'alice.bsky.social',
|
|
482
|
+
})
|
|
483
|
+
// Navigate to connection.authorizationUrl. On the configured app callback:
|
|
484
|
+
const { data: account } = await r.protocols.finishNativeSocialConnection({
|
|
485
|
+
protocol: 'bluesky', state, code, iss,
|
|
486
|
+
})
|
|
487
|
+
const { data: accounts } = await r.protocols.nativeSocialAccounts()
|
|
488
|
+
await r.protocols.disconnectNativeSocialAccount(account.id)
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
ActivityPub uses an operator-approved HTTPS server origin as `identifier` and
|
|
492
|
+
requires Mastodon-compatible OAuth metadata with S256 PKCE. The server configures
|
|
493
|
+
the exact callback path `/social/connect/callback/:protocol`; the app must remove
|
|
494
|
+
its query from browser history immediately and never log codes. No password or
|
|
495
|
+
native token is sent through these SDK methods. Start and callback are single-use
|
|
496
|
+
requests and are never automatically retried. If a callback result is uncertain,
|
|
497
|
+
refresh the account list before starting again.
|
|
498
|
+
|
|
499
|
+
Connection does not approve publication. The account's `capabilities` lists only
|
|
500
|
+
implemented actions, currently empty for these adapters. Local disconnect takes
|
|
501
|
+
effect even when `providerRevocation` is `unconfirmed`; the user can also revoke
|
|
502
|
+
Minds from their network's authorized-app settings.
|
|
503
|
+
|
|
504
|
+
### One reviewed reply across selected accounts
|
|
505
|
+
|
|
506
|
+
The shared reply API is off by default. Deploy its required schema/API and finish
|
|
507
|
+
live authorization and delivery verification before enabling it. This example
|
|
508
|
+
prepares a preview; it does not publish anything:
|
|
509
|
+
|
|
510
|
+
```ts
|
|
511
|
+
const { data: preview } = await r.protocols.prepareNativeReply({
|
|
512
|
+
clientMutationId: crypto.randomUUID(), text: draftText,
|
|
513
|
+
parent: { protocol: 'bluesky', nativeId: selectedPost.nativeId },
|
|
514
|
+
accountIds: [blueskyAccount.id, activityPubAccount.id],
|
|
515
|
+
linkedPostAccountIds: [activityPubAccount.id],
|
|
516
|
+
})
|
|
517
|
+
// Review each delivery's account, protocol, kind, parent and exact wireText.
|
|
518
|
+
// After the user approves selected delivery IDs:
|
|
519
|
+
await r.protocols.submitNativeReply(preview.id, { approve: true, deliveryIds: approvedDeliveryIds })
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Use `linkedPostAccountIds` only after the user selects a standalone post with the
|
|
523
|
+
source link on that different network. It is not a matching threaded reply, and
|
|
524
|
+
a denied same-network reply never falls back automatically. Verified cross-network
|
|
525
|
+
thread mappings are not implemented here. Nostr uses the connected client signer
|
|
526
|
+
described above. Preserve the mutation
|
|
527
|
+
ID while recovering an uncertain preparation; read `nativeReplyStatus(preview.id)` to
|
|
528
|
+
show each destination's result. Repeated submit reconciles an attempted delivery
|
|
529
|
+
without publishing it again. Removal uses a fresh `prepareNativeReplyRemoval`
|
|
530
|
+
preview and explicit `removeNativeReply` approval for the selected own posts.
|
|
531
|
+
|
|
532
|
+
For a selected unsent or definitively rejected destination, the same prepare
|
|
533
|
+
method accepts `recoverFrom: { batchId: preview.id, deliveryIds: selectedIds }`
|
|
534
|
+
with a **new** mutation ID, the same source/accounts and freshly reviewed text.
|
|
535
|
+
Preserve that new ID if preparation is uncertain. The server creates the fresh
|
|
536
|
+
review and disables only those old destinations atomically; `replacedBy` points
|
|
537
|
+
to the new batch. `recoverable` describes saved eligibility, while current account,
|
|
538
|
+
source and safety checks still apply. Sending, unknown, accepted or published
|
|
539
|
+
destinations cannot be resent this way. The fresh preview still needs explicit
|
|
540
|
+
approval; completed destinations retain their outcomes.
|
|
541
|
+
|
|
542
|
+
`nativeReplyHistory` pages through one private history containing Bluesky/ActivityPub
|
|
543
|
+
drafts and delivery results, plus Nostr replies and linked posts once submitted. It also includes unsent or expired preparations. The
|
|
544
|
+
summary contains a bounded preview of the user's own text and source references,
|
|
545
|
+
not old remote parent text or approval material. Opening a result with
|
|
546
|
+
`nativeReplyStatus(id)` does not send anything. Reading remains available when
|
|
547
|
+
new replies are disabled; it does not refresh credentials or contact a network.
|
|
548
|
+
Nostr items have `type: "nostr"`. `nativeNostrReplyResult(id)` checks the saved event
|
|
549
|
+
on its recorded relay without signing or resending. It requires the same connected
|
|
550
|
+
identity and preserves historical publication/deletion evidence separately from
|
|
551
|
+
`lastReadBack`. A relay absence is not proof of global deletion. Signatures and
|
|
552
|
+
intents are never retained in history.
|
|
553
|
+
|
|
554
|
+
```ts
|
|
555
|
+
const { data: history } = await r.protocols.nativeReplyHistory({ limit: 20 })
|
|
556
|
+
// Read a saved result without submitting it.
|
|
557
|
+
const firstResult = history.items[0]
|
|
558
|
+
if (firstResult) {
|
|
559
|
+
if ('type' in firstResult && firstResult.type === 'nostr') {
|
|
560
|
+
await r.protocols.nativeNostrReplyResult(firstResult.id)
|
|
561
|
+
} else await r.protocols.nativeReplyStatus(firstResult.id)
|
|
562
|
+
}
|
|
563
|
+
if (history.cursor) {
|
|
564
|
+
const { data: next } = await r.protocols.nativeReplyHistory({ limit: 20, cursor: history.cursor })
|
|
565
|
+
console.log(next.items.length)
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
Keep the cursor opaque and discard it when the app or signed-in user changes.
|
|
570
|
+
History order is fixed by creation time, so later delivery updates do not move
|
|
571
|
+
older entries across page boundaries. Reopen each result for its current saved
|
|
572
|
+
state and obtain a fresh review before a new write.
|
package/dist/index.d.ts
CHANGED
|
@@ -160,7 +160,7 @@ export { EnvVarsResource } from './resources/env-vars.js';
|
|
|
160
160
|
export type { QueryDatabaseInput, QueryResult } from './resources/databases.js';
|
|
161
161
|
export { GitHubResource } from './resources/github.js';
|
|
162
162
|
export { DeploymentsResource } from './resources/deployments.js';
|
|
163
|
-
export type { PrepareProtocolServersInput, PreparedProtocolServers, ProtocolServerPreparation } from './resources/deployments.js';
|
|
163
|
+
export type { PrepareProtocolServersInput, PreparedProtocolServers, ProtocolServerPreparation, ProtocolServerUpgradePreview, ProtocolServerUpgradeInput, ProtocolServerUpgradeStatus } from './resources/deployments.js';
|
|
164
164
|
export { IntegrationsResource } from './resources/integrations.js';
|
|
165
165
|
export type { ExecuteToolInput, ExecuteToolResult } from './resources/integrations.js';
|
|
166
166
|
export { ProjectBrainResource } from './resources/project-brain.js';
|
|
@@ -171,7 +171,7 @@ export { VideoResource } from './resources/video.js';
|
|
|
171
171
|
export type { VideoUploadCreds, CreateVideoUploadResult, VideoStatusInfo, VideoPlaybackToken, } from './resources/video.js';
|
|
172
172
|
export { AppSubscriptionsResource } from './resources/app-subscriptions.js';
|
|
173
173
|
export type { AppSubscriptionCheckoutResult, AppSubscriptionPortalResult, AppSubscriptionStatusResult, } from './resources/app-subscriptions.js';
|
|
174
|
-
export type { CuratorSource, CuratorPrompt, CuratorRunInput, CuratorRunResult, } from './resources/curator.js';
|
|
174
|
+
export type { CuratorSource, CuratorPrompt, CuratorRunInput, CuratorRunResult, CuratorTodayEdition, CuratorTodayResponse, CuratorTodaySource, CuratorTodayStory, } from './resources/curator.js';
|
|
175
175
|
export { ReportsResource } from './resources/reports.js';
|
|
176
176
|
export type { ReportTargetType, ReportStatus, CreateReportInput, ReportRecord, ResolveReportInput, } from './resources/reports.js';
|
|
177
177
|
export { ModerationResource } from './resources/moderation.js';
|
|
@@ -189,7 +189,7 @@ export type { UploadMediaInput, UploadUrlInput, UploadUrlResult } from './resour
|
|
|
189
189
|
export { WalletResource } from './resources/wallet.js';
|
|
190
190
|
export { ProtocolsResource } from './resources/protocols.js';
|
|
191
191
|
export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, } from './resources/protocols.js';
|
|
192
|
-
export type { SocialProfile, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendFeed, SocialAuthorFeed, SocialFollowingFeed, SocialFollowingSource, SearchPublicProfilesParams, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, HostedPostPreview, ConnectHostedIdentityInput, PreviewHostedPostInput, PublishHostedPostInput, ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
|
|
192
|
+
export type { SocialProfile, SocialSubscription, SocialSubscriptionChange, SocialProfilePage, SocialNetwork, SocialPost, SocialConversation, SocialTrend, SocialTrendProvenance, SocialTrends, SocialTrendFeed, SocialAuthorFeed, SocialFollowingFeed, SocialFollowingSource, SearchPublicProfilesParams, HostedProtocolConnections, HostedProtocol, HostedProtocolIdentity, HostedNostrChallenge, HostedNostrIdentityProof, NativeNostrPrepareInput, NativeNostrPrepared, NativeNostrAccount, NativeNostrPostState, NativeNostrReceipt, NativeSocialProtocol, FederationIdentity, FederationIdentityView, NativeSocialAccount, NativeSocialCallbackInput, NativeReplyPrepareInput, NativeReplyReceipt, NativeReplyBatch, NativeReplyHistory, NativeDelegatedReplyHistoryItem, NativeNostrReplyResult, NativeNostrReplyHistoryItem, NativeReplyRemovalReceipt, NativeReplyRemovalPreview, SocialSourceRef, SocialSourceControl, SocialSourceControlChange, HostedPostPreview, ConnectHostedIdentityInput, PreviewHostedPostInput, PublishHostedPostInput, ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
|
|
193
193
|
export { InboxResource } from './resources/inbox.js';
|
|
194
194
|
export { NetworkResource } from './resources/network.js';
|
|
195
195
|
export { SimulatorResource } from './resources/simulator.js';
|
|
@@ -6,11 +6,15 @@ export interface SiblingAccount {
|
|
|
6
6
|
username: string;
|
|
7
7
|
name: string;
|
|
8
8
|
image: string | null;
|
|
9
|
-
created_at: string;
|
|
9
|
+
created_at: string | null;
|
|
10
|
+
/** Followers on this account. The main-account rule reads this field. */
|
|
11
|
+
follower_count: number;
|
|
10
12
|
/** The stored primary email is a migration placeholder, not a real inbox. */
|
|
11
13
|
is_placeholder_email: boolean;
|
|
12
14
|
/** Server heuristic used to collapse test/demo identities in account pickers. */
|
|
13
15
|
looks_like_test: boolean;
|
|
16
|
+
/** The account OTP sign-in lands on. Exactly one row carries it. */
|
|
17
|
+
is_primary: boolean;
|
|
14
18
|
is_current: boolean;
|
|
15
19
|
}
|
|
16
20
|
export interface SiblingAccountsResponse {
|
|
@@ -19,6 +23,8 @@ export interface SiblingAccountsResponse {
|
|
|
19
23
|
/** The verified real address shared by the returned accounts. */
|
|
20
24
|
email: string;
|
|
21
25
|
count: number;
|
|
26
|
+
/** Id of the main account, or null when the caller has no usable address. */
|
|
27
|
+
primary_id?: string | null;
|
|
22
28
|
};
|
|
23
29
|
}
|
|
24
30
|
export interface SwitchAccountResult {
|
|
@@ -36,7 +42,7 @@ export interface SwitchAccountResult {
|
|
|
36
42
|
export declare class AccountsResource {
|
|
37
43
|
private client;
|
|
38
44
|
constructor(client: HttpClient);
|
|
39
|
-
/** List every account controlled by the caller's verified real email. */
|
|
45
|
+
/** List every account controlled by the caller's verified real email, main account first. */
|
|
40
46
|
listSiblings(): Promise<SiblingAccountsResponse>;
|
|
41
47
|
/** Mint a replacement key for a sibling account in the caller's project. */
|
|
42
48
|
switchAccount(targetUserId: string): Promise<SingleResponse<SwitchAccountResult>>;
|
|
@@ -11,7 +11,7 @@ export class AccountsResource {
|
|
|
11
11
|
constructor(client) {
|
|
12
12
|
this.client = client;
|
|
13
13
|
}
|
|
14
|
-
/** List every account controlled by the caller's verified real email. */
|
|
14
|
+
/** List every account controlled by the caller's verified real email, main account first. */
|
|
15
15
|
listSiblings() {
|
|
16
16
|
return this.client.get('/accounts/siblings');
|
|
17
17
|
}
|
|
@@ -105,9 +105,77 @@ export interface CuratorSeedDeckResponse {
|
|
|
105
105
|
data: CuratorSeedDeckItem[];
|
|
106
106
|
meta: CuratorSeedDeckMeta;
|
|
107
107
|
}
|
|
108
|
+
/** Which half of the press an outlet belongs to. */
|
|
109
|
+
export type CuratorOutletLane = 'mainstream' | 'independent';
|
|
110
|
+
/** One outlet item behind a world story. Headline and link only, never an article body. */
|
|
111
|
+
export interface CuratorTodaySource {
|
|
112
|
+
outlet: string;
|
|
113
|
+
/** The outlet's lane. Absent on stories written before lanes existed. */
|
|
114
|
+
lane?: CuratorOutletLane;
|
|
115
|
+
title: string;
|
|
116
|
+
url: string;
|
|
117
|
+
published_at: string | null;
|
|
118
|
+
}
|
|
119
|
+
/** Distinct outlets per lane behind a world story. */
|
|
120
|
+
export interface CuratorTodayLaneMix {
|
|
121
|
+
mainstream: number;
|
|
122
|
+
independent: number;
|
|
123
|
+
}
|
|
124
|
+
export interface CuratorTodayStory {
|
|
125
|
+
id: string;
|
|
126
|
+
/** 1 = lead. World stories hold 1..N, Minds stories follow. */
|
|
127
|
+
rank: number;
|
|
128
|
+
/**
|
|
129
|
+
* 'world': the open web set it, ranked by how many outlets moved on it in
|
|
130
|
+
* the last 24 h with an independent outlet weighted above a mainstream one.
|
|
131
|
+
* 'minds': a group of real Minds posts.
|
|
132
|
+
*/
|
|
133
|
+
kind: 'world' | 'minds';
|
|
134
|
+
kicker: string;
|
|
135
|
+
headline: string;
|
|
136
|
+
dek: string | null;
|
|
137
|
+
topic: string | null;
|
|
138
|
+
/** Outlet links for a world story; null for a Minds story. */
|
|
139
|
+
sources: CuratorTodaySource[] | null;
|
|
140
|
+
/** Distinct outlets behind a world story; null for a Minds story. */
|
|
141
|
+
outlet_count: number | null;
|
|
142
|
+
/** Distinct outlets per lane behind a world story; null for a Minds story. */
|
|
143
|
+
lane_mix: CuratorTodayLaneMix | null;
|
|
144
|
+
/**
|
|
145
|
+
* Which lanes carry a world story: 'mainstream', 'independent' (nobody in
|
|
146
|
+
* the mainstream lane ran it) or 'both'. Null for a Minds story.
|
|
147
|
+
*/
|
|
148
|
+
lane: CuratorOutletLane | 'both' | null;
|
|
149
|
+
/** The discussion-room post when one exists. */
|
|
150
|
+
discussion_post_id: string | null;
|
|
151
|
+
/** Replies on the discussion post; 0 when there is none. */
|
|
152
|
+
reply_count: number;
|
|
153
|
+
/** Minds posts in the same shape as `sdk.posts.list()`. May be empty for a world story. */
|
|
154
|
+
posts: Post[];
|
|
155
|
+
}
|
|
156
|
+
export interface CuratorTodayEdition {
|
|
157
|
+
id: string;
|
|
158
|
+
edition_date: string;
|
|
159
|
+
status: 'draft' | 'published';
|
|
160
|
+
generated_at: string;
|
|
161
|
+
stories: CuratorTodayStory[];
|
|
162
|
+
}
|
|
163
|
+
export interface CuratorTodayResponse {
|
|
164
|
+
/** null when the network has no published edition yet. */
|
|
165
|
+
data: CuratorTodayEdition | null;
|
|
166
|
+
meta: {
|
|
167
|
+
generating: boolean;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
108
170
|
export declare class CuratorResource {
|
|
109
171
|
private client;
|
|
110
172
|
constructor(client: HttpClient);
|
|
173
|
+
/**
|
|
174
|
+
* Today: the daily front page for the caller's network. World stories
|
|
175
|
+
* (set by the open web, ranked by outlet count) come first; Minds
|
|
176
|
+
* conversation stories follow. Requires `posts:read`.
|
|
177
|
+
*/
|
|
178
|
+
today(): Promise<CuratorTodayResponse>;
|
|
111
179
|
/**
|
|
112
180
|
* Fetch the supplied sources in parallel, annotate each top item with
|
|
113
181
|
* the supplied prompt template, and insert audience-scoped posts into
|
|
@@ -3,6 +3,14 @@ export class CuratorResource {
|
|
|
3
3
|
constructor(client) {
|
|
4
4
|
this.client = client;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Today: the daily front page for the caller's network. World stories
|
|
8
|
+
* (set by the open web, ranked by outlet count) come first; Minds
|
|
9
|
+
* conversation stories follow. Requires `posts:read`.
|
|
10
|
+
*/
|
|
11
|
+
today() {
|
|
12
|
+
return this.client.get('/curator/today');
|
|
13
|
+
}
|
|
6
14
|
/**
|
|
7
15
|
* Fetch the supplied sources in parallel, annotate each top item with
|
|
8
16
|
* the supplied prompt template, and insert audience-scoped posts into
|
|
@@ -62,6 +62,12 @@ export interface PreparedProtocolServers {
|
|
|
62
62
|
runtime_status: 'unverified';
|
|
63
63
|
}
|
|
64
64
|
export interface ProtocolServerPreparation {
|
|
65
|
+
/** Non-secret locator for recovering inspection after an operator/client restart. */
|
|
66
|
+
upgrade?: {
|
|
67
|
+
revision: string;
|
|
68
|
+
image: string;
|
|
69
|
+
phase: ProtocolServerUpgradeStatus['phase'];
|
|
70
|
+
};
|
|
65
71
|
/** Provider process observation only; protocol interoperability remains unverified. */
|
|
66
72
|
provider_status: 'running' | 'stopped' | 'transitioning' | 'unhealthy' | 'unknown';
|
|
67
73
|
id: string;
|
|
@@ -87,6 +93,32 @@ export interface HostedServiceScope {
|
|
|
87
93
|
export interface HostedServiceOperation extends HostedServiceScope {
|
|
88
94
|
request_hash: string;
|
|
89
95
|
}
|
|
96
|
+
export interface ProtocolServerUpgradePreview {
|
|
97
|
+
id: string;
|
|
98
|
+
provider_service_uuid: string;
|
|
99
|
+
revision: string;
|
|
100
|
+
from_image: string;
|
|
101
|
+
to_image: string;
|
|
102
|
+
restart_services: ['pds', 'activitypub', 'nostr'];
|
|
103
|
+
provider_status: 'running' | 'stopped';
|
|
104
|
+
operation: 'preview';
|
|
105
|
+
runtime_status: 'unverified';
|
|
106
|
+
storage_identity_verification_required: true;
|
|
107
|
+
}
|
|
108
|
+
export interface ProtocolServerUpgradeInput extends HostedServiceOperation {
|
|
109
|
+
image: string;
|
|
110
|
+
revision: string;
|
|
111
|
+
}
|
|
112
|
+
export interface ProtocolServerUpgradeStatus {
|
|
113
|
+
revision: string;
|
|
114
|
+
phase: 'applying' | 'configuration_saved' | 'restarting' | 'restart_requested';
|
|
115
|
+
runtime_status: 'unverified';
|
|
116
|
+
automatic_retry_allowed: false;
|
|
117
|
+
configuration_matches?: boolean;
|
|
118
|
+
provider_status?: ProtocolServerPreparation['provider_status'];
|
|
119
|
+
restart_services?: ['pds', 'activitypub', 'nostr'];
|
|
120
|
+
identity_verification_required?: true;
|
|
121
|
+
}
|
|
90
122
|
export interface HostedServiceReservation {
|
|
91
123
|
id: string;
|
|
92
124
|
provider_service_uuid: string | null;
|
|
@@ -115,6 +147,16 @@ export declare class DeploymentsResource {
|
|
|
115
147
|
project_id: string;
|
|
116
148
|
network_id: string;
|
|
117
149
|
}): Promise<SingleResponse<ProtocolServerPreparation>>;
|
|
150
|
+
/** Read-only staging image proposal; does not update or restart servers.
|
|
151
|
+
* Requires an unbound owner key and the server-configured approved image digest. */
|
|
152
|
+
previewProtocolServerUpgrade(input: HostedServiceOperation & {
|
|
153
|
+
image: string;
|
|
154
|
+
}): Promise<SingleResponse<ProtocolServerUpgradePreview>>;
|
|
155
|
+
/** Apply a reviewed staging upgrade once. Never automatically retry a lost response.
|
|
156
|
+
* Acceptance does not establish live identity, storage contents or interoperability. */
|
|
157
|
+
upgradeProtocolServers(input: ProtocolServerUpgradeInput): Promise<SingleResponse<ProtocolServerUpgradeStatus>>;
|
|
158
|
+
/** Read the saved upgrade and provider configuration; never replays a write. */
|
|
159
|
+
getProtocolServerUpgrade(input: ProtocolServerUpgradeInput): Promise<SingleResponse<ProtocolServerUpgradeStatus>>;
|
|
118
160
|
/** Queue a single activation after verifying the saved provider configuration and secrets.
|
|
119
161
|
* A 202 response is not evidence of live runtime health. */
|
|
120
162
|
startProtocolServers(input: {
|
|
@@ -26,6 +26,20 @@ export class DeploymentsResource {
|
|
|
26
26
|
getProtocolServerPreparation(scope) {
|
|
27
27
|
return this.client.get('/deployments/protocol-servers', { project_id: scope.project_id, network_id: scope.network_id });
|
|
28
28
|
}
|
|
29
|
+
/** Read-only staging image proposal; does not update or restart servers.
|
|
30
|
+
* Requires an unbound owner key and the server-configured approved image digest. */
|
|
31
|
+
previewProtocolServerUpgrade(input) {
|
|
32
|
+
return this.client.post('/deployments/protocol-servers/upgrade-preview', input);
|
|
33
|
+
}
|
|
34
|
+
/** Apply a reviewed staging upgrade once. Never automatically retry a lost response.
|
|
35
|
+
* Acceptance does not establish live identity, storage contents or interoperability. */
|
|
36
|
+
upgradeProtocolServers(input) {
|
|
37
|
+
return this.client.post('/deployments/protocol-servers/upgrade', input, { retry: false });
|
|
38
|
+
}
|
|
39
|
+
/** Read the saved upgrade and provider configuration; never replays a write. */
|
|
40
|
+
getProtocolServerUpgrade(input) {
|
|
41
|
+
return this.client.post('/deployments/protocol-servers/upgrade-status', input);
|
|
42
|
+
}
|
|
29
43
|
/** Queue a single activation after verifying the saved provider configuration and secrets.
|
|
30
44
|
* A 202 response is not evidence of live runtime health. */
|
|
31
45
|
startProtocolServers(input) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HttpClient } from '../client.js';
|
|
2
2
|
import type { SingleResponse } from '../types.js';
|
|
3
|
-
export type ModerationTargetType = 'post' | 'user' | 'message' | 'community' | 'agent';
|
|
3
|
+
export type ModerationTargetType = 'post' | 'user' | 'message' | 'community' | 'agent' | 'source_actor' | 'source_post';
|
|
4
4
|
export type ModerationActionType = 'down_rank' | 'label' | 'remove' | 'suspend' | 'ban';
|
|
5
5
|
export type ModerationAppealStatus = 'none' | 'pending' | 'upheld' | 'overturned';
|
|
6
6
|
export interface ModerationPrinciple {
|
|
@@ -53,7 +53,8 @@ export interface OwnModerationLog {
|
|
|
53
53
|
actions: OwnModerationAction[];
|
|
54
54
|
}
|
|
55
55
|
export interface ApplyModerationActionInput {
|
|
56
|
-
|
|
56
|
+
/** Source actions are resolved through the scoped report queue. */
|
|
57
|
+
target_type: Exclude<ModerationTargetType, 'source_actor' | 'source_post'>;
|
|
57
58
|
target_id: string;
|
|
58
59
|
action: ModerationActionType;
|
|
59
60
|
label?: string;
|
|
@@ -82,7 +82,12 @@ export interface ProtocolQuarantinedCandidate {
|
|
|
82
82
|
provider: string;
|
|
83
83
|
/** Safe IDs are byte-exact; null means unsafe or malformed provenance was withheld. */
|
|
84
84
|
external_id: string | null;
|
|
85
|
-
state:
|
|
85
|
+
state: ProtocolCandidateState;
|
|
86
|
+
/** Increments whenever the payload digest changes; decisions and verdicts are keyed by it. */
|
|
87
|
+
revision: number;
|
|
88
|
+
revision_digest: string | null;
|
|
89
|
+
/** Latest screening verdict on the current revision, or null when unscreened. */
|
|
90
|
+
latest_verdict: ProtocolCandidateVerdictSummary | null;
|
|
86
91
|
title: string | null;
|
|
87
92
|
content: string;
|
|
88
93
|
content_format: 'plain';
|
|
@@ -99,9 +104,37 @@ export interface ProtocolQuarantinedCandidate {
|
|
|
99
104
|
observed_at: string;
|
|
100
105
|
created_at: string;
|
|
101
106
|
}
|
|
107
|
+
export type ProtocolCandidateState = 'quarantined' | 'approved' | 'rejected' | 'escalated' | 'tombstoned';
|
|
108
|
+
export type ProtocolScreeningVerdict = 'pass' | 'hold' | 'fail';
|
|
109
|
+
export type ProtocolCandidateDecision = 'approved' | 'rejected' | 'escalated';
|
|
110
|
+
export interface ProtocolCandidateVerdictSummary {
|
|
111
|
+
verdict: ProtocolScreeningVerdict;
|
|
112
|
+
line: string;
|
|
113
|
+
category: string | null;
|
|
114
|
+
high_risk: boolean;
|
|
115
|
+
reason: string | null;
|
|
116
|
+
created_at: string;
|
|
117
|
+
}
|
|
118
|
+
export interface ProtocolCandidateVerdict extends ProtocolCandidateVerdictSummary {
|
|
119
|
+
id: string;
|
|
120
|
+
revision: number;
|
|
121
|
+
model: string | null;
|
|
122
|
+
confidence: number | null;
|
|
123
|
+
}
|
|
124
|
+
export interface DecideProtocolCandidateInput {
|
|
125
|
+
decision: ProtocolCandidateDecision;
|
|
126
|
+
/** Required for escalation; recorded on every decision. */
|
|
127
|
+
reason?: string;
|
|
128
|
+
}
|
|
129
|
+
export interface ProtocolCandidateDecisionResult {
|
|
130
|
+
candidate: ProtocolQuarantinedCandidate;
|
|
131
|
+
decision_id: string;
|
|
132
|
+
}
|
|
102
133
|
/** App/network scope comes only from the authenticated project-bound key. */
|
|
103
134
|
export interface ListProtocolCandidatesParams {
|
|
104
135
|
protocol?: string;
|
|
136
|
+
/** Candidate state to list; the API defaults to quarantined. */
|
|
137
|
+
state?: ProtocolCandidateState;
|
|
105
138
|
/** Page size, default 20 and maximum 50; enforced by the API. */
|
|
106
139
|
limit?: number;
|
|
107
140
|
/** Opaque cursor from this endpoint's previous page; never an offset. */
|
|
@@ -162,10 +195,199 @@ export interface HostedNostrIdentityProof {
|
|
|
162
195
|
export type NativeNostrPrepareInput = {
|
|
163
196
|
action: 'publish';
|
|
164
197
|
content: string;
|
|
198
|
+
} | {
|
|
199
|
+
action: 'reply';
|
|
200
|
+
content: string;
|
|
201
|
+
parentId: string;
|
|
202
|
+
} | {
|
|
203
|
+
action: 'linked_post';
|
|
204
|
+
content: string;
|
|
205
|
+
source: {
|
|
206
|
+
protocol: NativeSocialProtocol;
|
|
207
|
+
nativeId: string;
|
|
208
|
+
readRef?: string;
|
|
209
|
+
};
|
|
165
210
|
} | {
|
|
166
211
|
action: 'delete';
|
|
167
212
|
postId: string;
|
|
168
213
|
};
|
|
214
|
+
export type NativeSocialProtocol = 'bluesky' | 'activitypub';
|
|
215
|
+
export interface NativeSocialAccount {
|
|
216
|
+
id: string;
|
|
217
|
+
protocol: NativeSocialProtocol;
|
|
218
|
+
nativeId: string;
|
|
219
|
+
serverUrl: string;
|
|
220
|
+
handle: string;
|
|
221
|
+
connectedAt: string;
|
|
222
|
+
capabilities: string[];
|
|
223
|
+
}
|
|
224
|
+
/** A Minds-hosted ActivityPub identity for this app user. Keys never leave the platform. */
|
|
225
|
+
export interface FederationIdentity {
|
|
226
|
+
identifier: string;
|
|
227
|
+
actorUri: string;
|
|
228
|
+
handle: string;
|
|
229
|
+
enabled: boolean;
|
|
230
|
+
origin: string;
|
|
231
|
+
}
|
|
232
|
+
export interface FederationIdentityView {
|
|
233
|
+
enabled: boolean;
|
|
234
|
+
origin: string | null;
|
|
235
|
+
identity: FederationIdentity | null;
|
|
236
|
+
}
|
|
237
|
+
export interface SocialSourceRef {
|
|
238
|
+
protocol: 'bluesky' | 'activitypub' | 'nostr';
|
|
239
|
+
kind: 'actor' | 'post';
|
|
240
|
+
nativeId: string;
|
|
241
|
+
}
|
|
242
|
+
export interface SocialSourceControl {
|
|
243
|
+
id: string;
|
|
244
|
+
source: SocialSourceRef;
|
|
245
|
+
control: 'block' | 'mute' | 'hide';
|
|
246
|
+
scope: 'minds';
|
|
247
|
+
createdAt: string;
|
|
248
|
+
}
|
|
249
|
+
export type SocialSourceControlChange = Omit<SocialSourceControl, 'id' | 'createdAt'> & {
|
|
250
|
+
enabled: boolean;
|
|
251
|
+
};
|
|
252
|
+
export interface NativeReplyPrepareInput {
|
|
253
|
+
clientMutationId: string;
|
|
254
|
+
text: string;
|
|
255
|
+
parent: {
|
|
256
|
+
protocol: SocialSourceRef['protocol'];
|
|
257
|
+
nativeId: string;
|
|
258
|
+
readRef?: string;
|
|
259
|
+
};
|
|
260
|
+
accountIds: string[];
|
|
261
|
+
/** Selected different-network accounts to review as standalone posts with a source link. */
|
|
262
|
+
linkedPostAccountIds?: string[];
|
|
263
|
+
/** Fresh review of selected unsent or definitively rejected deliveries. The original selected reviews are atomically fenced; preserve this mutation ID on retry. */
|
|
264
|
+
recoverFrom?: {
|
|
265
|
+
batchId: string;
|
|
266
|
+
deliveryIds: string[];
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
export interface NativeReplyReceipt {
|
|
270
|
+
state: 'published' | 'accepted' | 'unknown' | 'rejected';
|
|
271
|
+
nativeId: string | null;
|
|
272
|
+
sourceUrl: string | null;
|
|
273
|
+
providerId: string | null;
|
|
274
|
+
acknowledged: boolean;
|
|
275
|
+
readBack: 'matched' | 'absent' | 'unavailable';
|
|
276
|
+
}
|
|
277
|
+
export interface NativeReplyRemovalReceipt {
|
|
278
|
+
/** Absence is observed on the owning server; this is not global erasure. */
|
|
279
|
+
state: 'absent' | 'accepted' | 'unknown' | 'rejected';
|
|
280
|
+
acknowledged: boolean;
|
|
281
|
+
readBack: 'absent' | 'present' | 'unavailable';
|
|
282
|
+
}
|
|
283
|
+
export interface NativeReplyRemovalPreview {
|
|
284
|
+
id: string;
|
|
285
|
+
previews: Array<{
|
|
286
|
+
deliveryId: string;
|
|
287
|
+
removalId: string;
|
|
288
|
+
expiresAt: string;
|
|
289
|
+
protocol: NativeSocialProtocol;
|
|
290
|
+
nativeId: string;
|
|
291
|
+
providerId: string;
|
|
292
|
+
sourceUrl: string;
|
|
293
|
+
revision: string | null;
|
|
294
|
+
text: string | null;
|
|
295
|
+
additionalContent: boolean;
|
|
296
|
+
account: {
|
|
297
|
+
nativeId: string;
|
|
298
|
+
handle: string;
|
|
299
|
+
serverUrl: string;
|
|
300
|
+
} | null;
|
|
301
|
+
}>;
|
|
302
|
+
errors: Record<string, {
|
|
303
|
+
code: string;
|
|
304
|
+
message: string;
|
|
305
|
+
}>;
|
|
306
|
+
}
|
|
307
|
+
export interface NativeReplyBatch {
|
|
308
|
+
id: string;
|
|
309
|
+
clientMutationId: string;
|
|
310
|
+
expiresAt: string;
|
|
311
|
+
deliveries: Array<{
|
|
312
|
+
id: string;
|
|
313
|
+
grantId: string;
|
|
314
|
+
protocol: NativeSocialProtocol;
|
|
315
|
+
kind: 'reply' | 'linked_post';
|
|
316
|
+
state: 'prepared' | 'sending' | NativeReplyReceipt['state'];
|
|
317
|
+
attemptedAt: string | null;
|
|
318
|
+
/** Saved attempt eligibility only; source, account authority and app/provider gates are checked again during preparation. */
|
|
319
|
+
recoverable?: boolean;
|
|
320
|
+
/** Newer batch that replaced this destination's approval. This old destination cannot publish. */
|
|
321
|
+
replacedBy?: string;
|
|
322
|
+
account: {
|
|
323
|
+
nativeId: string;
|
|
324
|
+
handle: string;
|
|
325
|
+
serverUrl: string;
|
|
326
|
+
} | null;
|
|
327
|
+
parent: {
|
|
328
|
+
protocol: SocialSourceRef['protocol'];
|
|
329
|
+
nativeId: string;
|
|
330
|
+
sourceUrl: string;
|
|
331
|
+
authorId: string;
|
|
332
|
+
authorHandle: string;
|
|
333
|
+
text: string;
|
|
334
|
+
textTruncated?: boolean;
|
|
335
|
+
};
|
|
336
|
+
text: string;
|
|
337
|
+
wireText: string;
|
|
338
|
+
receipt: NativeReplyReceipt | null;
|
|
339
|
+
removal: {
|
|
340
|
+
id: string;
|
|
341
|
+
expiresAt: string;
|
|
342
|
+
attemptedAt: string | null;
|
|
343
|
+
receipt: NativeReplyRemovalReceipt | null;
|
|
344
|
+
} | null;
|
|
345
|
+
}>;
|
|
346
|
+
}
|
|
347
|
+
export interface NativeSocialCallbackInput {
|
|
348
|
+
protocol: NativeSocialProtocol;
|
|
349
|
+
state: string;
|
|
350
|
+
code?: string;
|
|
351
|
+
iss?: string;
|
|
352
|
+
error?: string;
|
|
353
|
+
}
|
|
354
|
+
export interface NativeDelegatedReplyHistoryItem {
|
|
355
|
+
id: string;
|
|
356
|
+
createdAt: string;
|
|
357
|
+
text: string;
|
|
358
|
+
textTruncated: boolean;
|
|
359
|
+
source: Pick<NativeReplyBatch['deliveries'][number]['parent'], 'protocol' | 'nativeId' | 'sourceUrl'>;
|
|
360
|
+
deliveries: Array<Pick<NativeReplyBatch['deliveries'][number], 'id' | 'protocol' | 'kind' | 'state' | 'attemptedAt' | 'account' | 'recoverable' | 'replacedBy'> & {
|
|
361
|
+
removalReceipt: NativeReplyRemovalReceipt | null;
|
|
362
|
+
}>;
|
|
363
|
+
}
|
|
364
|
+
export interface NativeNostrReplyResult {
|
|
365
|
+
id: string;
|
|
366
|
+
createdAt: string;
|
|
367
|
+
text: string;
|
|
368
|
+
source: {
|
|
369
|
+
protocol: SocialSourceRef['protocol'];
|
|
370
|
+
nativeId: string;
|
|
371
|
+
sourceUrl: string;
|
|
372
|
+
};
|
|
373
|
+
identityId: string;
|
|
374
|
+
pubkey: string;
|
|
375
|
+
relay: string;
|
|
376
|
+
eventId: string;
|
|
377
|
+
action: 'reply' | 'linked_post';
|
|
378
|
+
receipt: NativeNostrReceipt;
|
|
379
|
+
checkedAt: string | null;
|
|
380
|
+
lastReadBack: NativeNostrReceipt['readBack'];
|
|
381
|
+
}
|
|
382
|
+
export interface NativeNostrReplyHistoryItem extends NativeNostrReplyResult {
|
|
383
|
+
type: 'nostr';
|
|
384
|
+
textTruncated: boolean;
|
|
385
|
+
}
|
|
386
|
+
export interface NativeReplyHistory {
|
|
387
|
+
/** One private history, including client-signed Nostr replies once submitted. */
|
|
388
|
+
items: Array<NativeDelegatedReplyHistoryItem | NativeNostrReplyHistoryItem>;
|
|
389
|
+
cursor: string | null;
|
|
390
|
+
}
|
|
169
391
|
export interface NativeNostrPrepared {
|
|
170
392
|
intent: string;
|
|
171
393
|
event: {
|
|
@@ -175,17 +397,42 @@ export interface NativeNostrPrepared {
|
|
|
175
397
|
tags: string[][];
|
|
176
398
|
};
|
|
177
399
|
eventId: string;
|
|
178
|
-
action: 'publish' | 'delete';
|
|
400
|
+
action: 'publish' | 'reply' | 'linked_post' | 'delete';
|
|
179
401
|
identityId: string;
|
|
180
402
|
pubkey: string;
|
|
181
403
|
relay: string;
|
|
182
404
|
expiresAt: string;
|
|
183
405
|
postId?: string;
|
|
406
|
+
parent?: {
|
|
407
|
+
protocol: 'nostr';
|
|
408
|
+
nativeId: string;
|
|
409
|
+
authorId: string;
|
|
410
|
+
authorHandle: string;
|
|
411
|
+
sourceUrl: string;
|
|
412
|
+
text: string;
|
|
413
|
+
textTruncated: boolean;
|
|
414
|
+
root: {
|
|
415
|
+
nativeId: string;
|
|
416
|
+
authorId: string;
|
|
417
|
+
sourceUrl: string;
|
|
418
|
+
};
|
|
419
|
+
participants: string[];
|
|
420
|
+
tags: string[][];
|
|
421
|
+
};
|
|
422
|
+
source?: {
|
|
423
|
+
protocol: NativeSocialProtocol;
|
|
424
|
+
nativeId: string;
|
|
425
|
+
authorId: string;
|
|
426
|
+
authorHandle: string;
|
|
427
|
+
sourceUrl: string;
|
|
428
|
+
text: string;
|
|
429
|
+
textTruncated?: boolean;
|
|
430
|
+
};
|
|
184
431
|
}
|
|
185
432
|
export interface NativeNostrAccount {
|
|
186
433
|
enabled: boolean;
|
|
187
434
|
identity: HostedProtocolIdentity | null;
|
|
188
|
-
capabilities: Array<'publish_original_text' | 'request_own_post_deletion'>;
|
|
435
|
+
capabilities: Array<'publish_original_text' | 'request_own_post_deletion' | 'reply_text_note' | 'publish_linked_text'>;
|
|
189
436
|
signing?: 'client';
|
|
190
437
|
}
|
|
191
438
|
export interface NativeNostrPostState {
|
|
@@ -202,7 +449,7 @@ export interface NativeNostrReceipt {
|
|
|
202
449
|
eventId: string;
|
|
203
450
|
postId: string;
|
|
204
451
|
relay: string;
|
|
205
|
-
action: 'publish' | 'delete';
|
|
452
|
+
action: 'publish' | 'reply' | 'linked_post' | 'delete';
|
|
206
453
|
state: 'published' | 'deletion_requested' | 'unknown' | 'rejected';
|
|
207
454
|
acknowledged: boolean;
|
|
208
455
|
readBack: 'found' | 'absent' | 'unavailable';
|
|
@@ -380,10 +627,13 @@ export interface SocialFollowingFeed {
|
|
|
380
627
|
export declare class ProtocolsResource {
|
|
381
628
|
private client;
|
|
382
629
|
private subscriptionListeners;
|
|
630
|
+
private sourceControlListeners;
|
|
383
631
|
constructor(client: HttpClient);
|
|
384
632
|
/** Confirmed changes from this SDK instance only. Unsubscribe when a view unmounts or its account changes. */
|
|
385
633
|
onSubscriptionChange(listener: (change: SocialSubscriptionChange) => void): () => void;
|
|
386
634
|
private subscriptionChanged;
|
|
635
|
+
/** Confirmed safety choices from this authenticated SDK instance. Unsubscribe when its account or view changes. */
|
|
636
|
+
onSourceControlChange(listener: (change: SocialSourceControlChange) => void): () => void;
|
|
387
637
|
publicNetworks(): Promise<SingleResponse<SocialNetwork[]>>;
|
|
388
638
|
/** Query the live public network. It does not import users or posts. */
|
|
389
639
|
searchPublicProfiles(params: SearchPublicProfilesParams): Promise<SingleResponse<SocialProfilePage>>;
|
|
@@ -419,17 +669,113 @@ export declare class ProtocolsResource {
|
|
|
419
669
|
limit?: number;
|
|
420
670
|
cursor?: string;
|
|
421
671
|
}): Promise<SingleResponse<SocialTrendFeed>>;
|
|
672
|
+
/** Prepare one exact shared reply preview. Keep the mutation ID across uncertain responses. */
|
|
673
|
+
prepareNativeReply(input: NativeReplyPrepareInput): Promise<SingleResponse<NativeReplyBatch>>;
|
|
674
|
+
/** Send only explicitly approved delivery IDs from this preview. Repeated submissions reconcile; they do not replay a write. */
|
|
675
|
+
submitNativeReply(id: string, input: {
|
|
676
|
+
approve: true;
|
|
677
|
+
deliveryIds: string[];
|
|
678
|
+
}): Promise<SingleResponse<NativeReplyBatch & {
|
|
679
|
+
errors: Record<string, {
|
|
680
|
+
code: string;
|
|
681
|
+
message: string;
|
|
682
|
+
}>;
|
|
683
|
+
}>>;
|
|
684
|
+
/** Read saved delivery results after refresh. This never publishes or contacts a source network. */
|
|
685
|
+
nativeReplyStatus(id: string): Promise<SingleResponse<NativeReplyBatch>>;
|
|
686
|
+
/** Page through this app user's saved delegated drafts/results. This never publishes, refreshes credentials or queries a source network. */
|
|
687
|
+
nativeReplyHistory(params?: {
|
|
688
|
+
limit?: number;
|
|
689
|
+
cursor?: string;
|
|
690
|
+
}): Promise<SingleResponse<NativeReplyHistory>>;
|
|
691
|
+
/** Review the current own posts before removal. A new preview replaces the previous approval. */
|
|
692
|
+
prepareNativeReplyRemoval(id: string, input: {
|
|
693
|
+
deliveryIds: string[];
|
|
694
|
+
}): Promise<SingleResponse<NativeReplyRemovalPreview>>;
|
|
695
|
+
/** Remove only selected, freshly reviewed destinations. Repeating approval never repeats a native delete. */
|
|
696
|
+
removeNativeReply(id: string, input: {
|
|
697
|
+
approve: true;
|
|
698
|
+
removals: Array<{
|
|
699
|
+
deliveryId: string;
|
|
700
|
+
removalId: string;
|
|
701
|
+
}>;
|
|
702
|
+
}): Promise<SingleResponse<NativeReplyBatch & {
|
|
703
|
+
errors: Record<string, {
|
|
704
|
+
code: string;
|
|
705
|
+
message: string;
|
|
706
|
+
}>;
|
|
707
|
+
}>>;
|
|
708
|
+
/** List this app user's delegated accounts. A connection is not approval to post. */
|
|
709
|
+
nativeSocialAccounts(): Promise<SingleResponse<{
|
|
710
|
+
enabled: boolean;
|
|
711
|
+
accounts: NativeSocialAccount[];
|
|
712
|
+
}>>;
|
|
713
|
+
/** Private source controls in this app, with bounded pagination. */
|
|
714
|
+
sourceControls(params?: {
|
|
715
|
+
limit?: number;
|
|
716
|
+
cursor?: string;
|
|
717
|
+
}): Promise<SingleResponse<{
|
|
718
|
+
enabled: boolean;
|
|
719
|
+
items: SocialSourceControl[];
|
|
720
|
+
cursor: string | null;
|
|
721
|
+
}>>;
|
|
722
|
+
/** Block/mute an actor or hide a post in Minds. This does not impersonate a native network block. */
|
|
723
|
+
setSourceControl(input: {
|
|
724
|
+
source: SocialSourceRef;
|
|
725
|
+
control: 'block' | 'mute' | 'hide';
|
|
726
|
+
enabled: boolean;
|
|
727
|
+
scope: 'minds';
|
|
728
|
+
}): Promise<SingleResponse<SocialSourceControlChange>>;
|
|
729
|
+
/** File a report in the app's existing moderation queue, using server-read public source evidence. */
|
|
730
|
+
reportSource(input: {
|
|
731
|
+
source: SocialSourceRef;
|
|
732
|
+
readRef?: string;
|
|
733
|
+
reason: string;
|
|
734
|
+
details?: string;
|
|
735
|
+
scope: 'minds';
|
|
736
|
+
}): Promise<SingleResponse<{
|
|
737
|
+
id: string;
|
|
738
|
+
status: string;
|
|
739
|
+
existing: boolean;
|
|
740
|
+
scope: 'minds';
|
|
741
|
+
}>>;
|
|
742
|
+
/** Open the returned authorization URL in the user's browser; never submit passwords or tokens. */
|
|
743
|
+
startNativeSocialConnection(input: {
|
|
744
|
+
protocol: NativeSocialProtocol;
|
|
745
|
+
identifier: string;
|
|
746
|
+
}): Promise<SingleResponse<{
|
|
747
|
+
protocol: NativeSocialProtocol;
|
|
748
|
+
authorizationUrl: string;
|
|
749
|
+
}>>;
|
|
750
|
+
/** Complete a single-use callback with the same signed-in app user. Remove its query from browser history; do not log codes. */
|
|
751
|
+
finishNativeSocialConnection(input: NativeSocialCallbackInput): Promise<SingleResponse<NativeSocialAccount>>;
|
|
752
|
+
/** Disable this app's saved authority even when the provider cannot acknowledge revocation. */
|
|
753
|
+
disconnectNativeSocialAccount(id: string): Promise<SingleResponse<{
|
|
754
|
+
disconnected: true;
|
|
755
|
+
providerRevocation: 'acknowledged' | 'unconfirmed';
|
|
756
|
+
}>>;
|
|
757
|
+
/** Current Minds-hosted ActivityPub state for this app user; never provisions. */
|
|
758
|
+
federationIdentity(): Promise<SingleResponse<FederationIdentityView>>;
|
|
759
|
+
/** Explicit opt-in; the platform provisions once and never rotates keys or re-enables a disabled identity on retry. */
|
|
760
|
+
enableFederationIdentity(): Promise<SingleResponse<FederationIdentityView>>;
|
|
761
|
+
/** Stops serving and signing for the identity; its stable URL and keys are retained by the platform. */
|
|
762
|
+
disableFederationIdentity(): Promise<SingleResponse<{
|
|
763
|
+
disabled: true;
|
|
764
|
+
identity: FederationIdentity;
|
|
765
|
+
}>>;
|
|
422
766
|
/** Native writes are off unless enabled for this exact app; public readers are independent. */
|
|
423
767
|
nativeNostrAccount(): Promise<SingleResponse<NativeNostrAccount>>;
|
|
424
768
|
/** Prepare an exact event for review. A timeout never automatically creates another signing request. */
|
|
425
769
|
prepareNativeNostr(id: string, input: NativeNostrPrepareInput): Promise<SingleResponse<NativeNostrPrepared>>;
|
|
426
|
-
/** Pass only the public signed event. After a timeout, read the prepared postId (delete) or eventId (publish).
|
|
770
|
+
/** Pass only the public signed event. After a timeout, read the prepared postId (delete) or eventId (publish/reply/linked_post).
|
|
427
771
|
* Any user-selected retry keeps the same intent/event. */
|
|
428
772
|
submitNativeNostr(id: string, input: {
|
|
429
773
|
intent: string;
|
|
430
774
|
event: HostedNostrIdentityProof;
|
|
431
775
|
approve: true;
|
|
432
776
|
}): Promise<SingleResponse<NativeNostrReceipt>>;
|
|
777
|
+
/** Check only the event bound to this private saved result; never sign, prepare or resend it. */
|
|
778
|
+
nativeNostrReplyResult(id: string): Promise<SingleResponse<NativeNostrReplyResult>>;
|
|
433
779
|
getNativeNostrPost(id: string, postId: string): Promise<SingleResponse<NativeNostrPostState>>;
|
|
434
780
|
/** Save a private reading subscription after resolving the immutable native ID. */
|
|
435
781
|
subscribeToProfile(input: {
|
|
@@ -471,6 +817,21 @@ export declare class ProtocolsResource {
|
|
|
471
817
|
* unsupported deployed route) propagate; they are never an empty page.
|
|
472
818
|
*/
|
|
473
819
|
listCandidates(params?: ListProtocolCandidatesParams): Promise<ProtocolCandidateListResponse>;
|
|
820
|
+
/**
|
|
821
|
+
* Run fail-closed screening on a candidate's current revision. Requires the
|
|
822
|
+
* app's content_intelligence_admin binding (404 otherwise) and the same
|
|
823
|
+
* project-admin authorization as listCandidates. A failed or unconfigured
|
|
824
|
+
* classifier records hold, never pass.
|
|
825
|
+
*/
|
|
826
|
+
screenCandidate(id: string): Promise<SingleResponse<ProtocolQuarantinedCandidate>>;
|
|
827
|
+
/** Screening verdict history for a candidate, newest first. */
|
|
828
|
+
listCandidateVerdicts(id: string): Promise<SingleResponse<ProtocolCandidateVerdict[]>>;
|
|
829
|
+
/**
|
|
830
|
+
* Record a decision on the candidate's current revision. Approval needs a
|
|
831
|
+
* signed-in human project admin and a pass verdict on the current digest;
|
|
832
|
+
* an agent key may only reject or escalate; escalation needs a reason.
|
|
833
|
+
*/
|
|
834
|
+
decideCandidate(id: string, input: DecideProtocolCandidateInput): Promise<SingleResponse<ProtocolCandidateDecisionResult>>;
|
|
474
835
|
/**
|
|
475
836
|
* Read one quarantined candidate under the same authorization as listCandidates.
|
|
476
837
|
* Empty and URL dot-segment IDs reject with ValidationError before any request;
|
|
@@ -37,6 +37,7 @@ function hostedIdentityPath(id) {
|
|
|
37
37
|
export class ProtocolsResource {
|
|
38
38
|
client;
|
|
39
39
|
subscriptionListeners = new Set();
|
|
40
|
+
sourceControlListeners = new Set();
|
|
40
41
|
constructor(client) {
|
|
41
42
|
this.client = client;
|
|
42
43
|
}
|
|
@@ -54,6 +55,11 @@ export class ProtocolsResource {
|
|
|
54
55
|
catch { /* Other mounted views still receive the change. */ }
|
|
55
56
|
}
|
|
56
57
|
}
|
|
58
|
+
/** Confirmed safety choices from this authenticated SDK instance. Unsubscribe when its account or view changes. */
|
|
59
|
+
onSourceControlChange(listener) {
|
|
60
|
+
this.sourceControlListeners.add(listener);
|
|
61
|
+
return () => { this.sourceControlListeners.delete(listener); };
|
|
62
|
+
}
|
|
57
63
|
publicNetworks() {
|
|
58
64
|
return this.client.get('/protocols/social/networks');
|
|
59
65
|
}
|
|
@@ -90,6 +96,98 @@ export class ProtocolsResource {
|
|
|
90
96
|
getPublicTrendFeed(params) {
|
|
91
97
|
return this.client.get('/protocols/social/trend-feed', { protocol: params.protocol, topic: params.topic, limit: params.limit, cursor: params.cursor });
|
|
92
98
|
}
|
|
99
|
+
/** Prepare one exact shared reply preview. Keep the mutation ID across uncertain responses. */
|
|
100
|
+
prepareNativeReply(input) {
|
|
101
|
+
return this.client.post('/protocols/social/replies/prepare', { clientMutationId: input.clientMutationId, text: input.text,
|
|
102
|
+
parent: { protocol: input.parent.protocol, nativeId: input.parent.nativeId,
|
|
103
|
+
...(input.parent.readRef !== undefined ? { readRef: input.parent.readRef } : {}) }, accountIds: input.accountIds,
|
|
104
|
+
...(input.linkedPostAccountIds !== undefined ? { linkedPostAccountIds: input.linkedPostAccountIds } : {}),
|
|
105
|
+
...(input.recoverFrom !== undefined ? { recoverFrom: { batchId: input.recoverFrom.batchId, deliveryIds: input.recoverFrom.deliveryIds } } : {}) }, { retry: false });
|
|
106
|
+
}
|
|
107
|
+
/** Send only explicitly approved delivery IDs from this preview. Repeated submissions reconcile; they do not replay a write. */
|
|
108
|
+
submitNativeReply(id, input) {
|
|
109
|
+
hostedIdentityPath(id);
|
|
110
|
+
return this.client.post(`/protocols/social/replies/${encodeURIComponent(id)}/submit`, { approve: input.approve, deliveryIds: input.deliveryIds }, { retry: false });
|
|
111
|
+
}
|
|
112
|
+
/** Read saved delivery results after refresh. This never publishes or contacts a source network. */
|
|
113
|
+
nativeReplyStatus(id) {
|
|
114
|
+
hostedIdentityPath(id);
|
|
115
|
+
return this.client.get(`/protocols/social/replies/${encodeURIComponent(id)}`);
|
|
116
|
+
}
|
|
117
|
+
/** Page through this app user's saved delegated drafts/results. This never publishes, refreshes credentials or queries a source network. */
|
|
118
|
+
nativeReplyHistory(params = {}) {
|
|
119
|
+
return this.client.get('/protocols/social/replies', { limit: params.limit, cursor: params.cursor });
|
|
120
|
+
}
|
|
121
|
+
/** Review the current own posts before removal. A new preview replaces the previous approval. */
|
|
122
|
+
prepareNativeReplyRemoval(id, input) {
|
|
123
|
+
hostedIdentityPath(id);
|
|
124
|
+
return this.client.post(`/protocols/social/replies/${encodeURIComponent(id)}/removals/prepare`, { deliveryIds: input.deliveryIds }, { retry: false });
|
|
125
|
+
}
|
|
126
|
+
/** Remove only selected, freshly reviewed destinations. Repeating approval never repeats a native delete. */
|
|
127
|
+
removeNativeReply(id, input) {
|
|
128
|
+
hostedIdentityPath(id);
|
|
129
|
+
return this.client.post(`/protocols/social/replies/${encodeURIComponent(id)}/removals/submit`, { approve: input.approve,
|
|
130
|
+
removals: input.removals.map(value => ({ deliveryId: value.deliveryId, removalId: value.removalId })) }, { retry: false });
|
|
131
|
+
}
|
|
132
|
+
/** List this app user's delegated accounts. A connection is not approval to post. */
|
|
133
|
+
nativeSocialAccounts() {
|
|
134
|
+
return this.client.get('/protocols/social/accounts');
|
|
135
|
+
}
|
|
136
|
+
/** Private source controls in this app, with bounded pagination. */
|
|
137
|
+
sourceControls(params = {}) {
|
|
138
|
+
return this.client.get('/protocols/social/controls', { limit: params.limit, cursor: params.cursor });
|
|
139
|
+
}
|
|
140
|
+
/** Block/mute an actor or hide a post in Minds. This does not impersonate a native network block. */
|
|
141
|
+
async setSourceControl(input) {
|
|
142
|
+
const choice = { source: { protocol: input.source.protocol, kind: input.source.kind, nativeId: input.source.nativeId },
|
|
143
|
+
control: input.control, enabled: input.enabled, scope: input.scope };
|
|
144
|
+
const response = await this.client.post('/protocols/social/controls', choice, { retry: false });
|
|
145
|
+
const saved = response.data;
|
|
146
|
+
if (!saved || saved.scope !== choice.scope || saved.enabled !== choice.enabled || saved.control !== choice.control
|
|
147
|
+
|| saved.source?.protocol !== choice.source.protocol || saved.source.kind !== choice.source.kind || saved.source.nativeId !== choice.source.nativeId) {
|
|
148
|
+
throw new ValidationError({ type: 'validation_error', code: 'source_control_unconfirmed', message: 'The saved safety choice could not be confirmed. Check your safety settings before trying again.' });
|
|
149
|
+
}
|
|
150
|
+
for (const listener of [...this.sourceControlListeners]) {
|
|
151
|
+
// A broken view must not turn a confirmed preference into a failed write.
|
|
152
|
+
try {
|
|
153
|
+
listener({ ...choice, source: { ...choice.source } });
|
|
154
|
+
}
|
|
155
|
+
catch { /* Continue notifying the other views. */ }
|
|
156
|
+
}
|
|
157
|
+
return response;
|
|
158
|
+
}
|
|
159
|
+
/** File a report in the app's existing moderation queue, using server-read public source evidence. */
|
|
160
|
+
reportSource(input) {
|
|
161
|
+
return this.client.post('/protocols/social/reports', { source: { protocol: input.source.protocol, kind: input.source.kind, nativeId: input.source.nativeId },
|
|
162
|
+
readRef: input.readRef, reason: input.reason, details: input.details, scope: input.scope }, { retry: false });
|
|
163
|
+
}
|
|
164
|
+
/** Open the returned authorization URL in the user's browser; never submit passwords or tokens. */
|
|
165
|
+
startNativeSocialConnection(input) {
|
|
166
|
+
return this.client.post('/protocols/social/oauth/start', { protocol: input.protocol, identifier: input.identifier }, { retry: false });
|
|
167
|
+
}
|
|
168
|
+
/** Complete a single-use callback with the same signed-in app user. Remove its query from browser history; do not log codes. */
|
|
169
|
+
finishNativeSocialConnection(input) {
|
|
170
|
+
const { protocol, state, code, iss, error } = input;
|
|
171
|
+
return this.client.post('/protocols/social/oauth/callback', { protocol, state,
|
|
172
|
+
...(code !== undefined ? { code } : {}), ...(iss !== undefined ? { iss } : {}), ...(error !== undefined ? { error } : {}) }, { retry: false });
|
|
173
|
+
}
|
|
174
|
+
/** Disable this app's saved authority even when the provider cannot acknowledge revocation. */
|
|
175
|
+
disconnectNativeSocialAccount(id) {
|
|
176
|
+
hostedIdentityPath(id);
|
|
177
|
+
return this.client.delete(`/protocols/social/accounts/${encodeURIComponent(id)}`);
|
|
178
|
+
}
|
|
179
|
+
/** Current Minds-hosted ActivityPub state for this app user; never provisions. */
|
|
180
|
+
federationIdentity() {
|
|
181
|
+
return this.client.get('/protocols/social/federation/identity');
|
|
182
|
+
}
|
|
183
|
+
/** Explicit opt-in; the platform provisions once and never rotates keys or re-enables a disabled identity on retry. */
|
|
184
|
+
enableFederationIdentity() {
|
|
185
|
+
return this.client.post('/protocols/social/federation/identity', { consent: true }, { retry: false });
|
|
186
|
+
}
|
|
187
|
+
/** Stops serving and signing for the identity; its stable URL and keys are retained by the platform. */
|
|
188
|
+
disableFederationIdentity() {
|
|
189
|
+
return this.client.delete('/protocols/social/federation/identity');
|
|
190
|
+
}
|
|
93
191
|
/** Native writes are off unless enabled for this exact app; public readers are independent. */
|
|
94
192
|
nativeNostrAccount() {
|
|
95
193
|
return this.client.get('/protocols/social/nostr/account');
|
|
@@ -97,10 +195,15 @@ export class ProtocolsResource {
|
|
|
97
195
|
/** Prepare an exact event for review. A timeout never automatically creates another signing request. */
|
|
98
196
|
prepareNativeNostr(id, input) {
|
|
99
197
|
hostedIdentityPath(id);
|
|
100
|
-
const body = input.action === 'publish' ? { action: input.action, content: input.content }
|
|
198
|
+
const body = input.action === 'publish' ? { action: input.action, content: input.content }
|
|
199
|
+
: input.action === 'reply' ? { action: input.action, content: input.content, parentId: input.parentId }
|
|
200
|
+
: input.action === 'linked_post' ? { action: input.action, content: input.content,
|
|
201
|
+
source: { protocol: input.source.protocol, nativeId: input.source.nativeId,
|
|
202
|
+
...(input.source.readRef !== undefined ? { readRef: input.source.readRef } : {}) } }
|
|
203
|
+
: { action: input.action, postId: input.postId };
|
|
101
204
|
return this.client.post(`/protocols/social/nostr/${encodeURIComponent(id)}/prepare`, body, { retry: false });
|
|
102
205
|
}
|
|
103
|
-
/** Pass only the public signed event. After a timeout, read the prepared postId (delete) or eventId (publish).
|
|
206
|
+
/** Pass only the public signed event. After a timeout, read the prepared postId (delete) or eventId (publish/reply/linked_post).
|
|
104
207
|
* Any user-selected retry keeps the same intent/event. */
|
|
105
208
|
submitNativeNostr(id, input) {
|
|
106
209
|
hostedIdentityPath(id);
|
|
@@ -109,6 +212,11 @@ export class ProtocolsResource {
|
|
|
109
212
|
intent: input.intent, event: { id: eventId, pubkey, sig, kind, content, created_at, tags }, approve: input.approve,
|
|
110
213
|
}, { retry: false });
|
|
111
214
|
}
|
|
215
|
+
/** Check only the event bound to this private saved result; never sign, prepare or resend it. */
|
|
216
|
+
nativeNostrReplyResult(id) {
|
|
217
|
+
hostedIdentityPath(id);
|
|
218
|
+
return this.client.get(`/protocols/social/nostr/replies/${encodeURIComponent(id)}`);
|
|
219
|
+
}
|
|
112
220
|
getNativeNostrPost(id, postId) {
|
|
113
221
|
hostedIdentityPath(id);
|
|
114
222
|
if (!/^[0-9a-f]{64}$/.test(postId))
|
|
@@ -174,24 +282,39 @@ export class ProtocolsResource {
|
|
|
174
282
|
listCandidates(params) {
|
|
175
283
|
return this.client.get('/protocols/candidates', params ? {
|
|
176
284
|
protocol: params.protocol,
|
|
285
|
+
state: params.state,
|
|
177
286
|
limit: params.limit,
|
|
178
287
|
cursor: params.cursor,
|
|
179
288
|
} : undefined);
|
|
180
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Run fail-closed screening on a candidate's current revision. Requires the
|
|
292
|
+
* app's content_intelligence_admin binding (404 otherwise) and the same
|
|
293
|
+
* project-admin authorization as listCandidates. A failed or unconfigured
|
|
294
|
+
* classifier records hold, never pass.
|
|
295
|
+
*/
|
|
296
|
+
async screenCandidate(id) {
|
|
297
|
+
return this.client.post(`/protocols/candidates/${encodeURIComponent(assertCandidateId(id))}/screen`, {});
|
|
298
|
+
}
|
|
299
|
+
/** Screening verdict history for a candidate, newest first. */
|
|
300
|
+
async listCandidateVerdicts(id) {
|
|
301
|
+
return this.client.get(`/protocols/candidates/${encodeURIComponent(assertCandidateId(id))}/verdicts`);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Record a decision on the candidate's current revision. Approval needs a
|
|
305
|
+
* signed-in human project admin and a pass verdict on the current digest;
|
|
306
|
+
* an agent key may only reject or escalate; escalation needs a reason.
|
|
307
|
+
*/
|
|
308
|
+
async decideCandidate(id, input) {
|
|
309
|
+
return this.client.post(`/protocols/candidates/${encodeURIComponent(assertCandidateId(id))}/decision`, input);
|
|
310
|
+
}
|
|
181
311
|
/**
|
|
182
312
|
* Read one quarantined candidate under the same authorization as listCandidates.
|
|
183
313
|
* Empty and URL dot-segment IDs reject with ValidationError before any request;
|
|
184
314
|
* all other IDs are encoded as one path segment and validated by the API.
|
|
185
315
|
*/
|
|
186
316
|
async getCandidate(id) {
|
|
187
|
-
|
|
188
|
-
throw new ValidationError({
|
|
189
|
-
type: 'validation_error',
|
|
190
|
-
code: 'invalid_candidate_id',
|
|
191
|
-
message: 'Candidate ID must be a non-empty identifier, not a URL dot segment.',
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
return this.client.get(`/protocols/candidates/${encodeURIComponent(id)}`);
|
|
317
|
+
return this.client.get(`/protocols/candidates/${encodeURIComponent(assertCandidateId(id))}`);
|
|
195
318
|
}
|
|
196
319
|
/** Cross-protocol full-text search */
|
|
197
320
|
search(params) {
|
|
@@ -210,3 +333,13 @@ export class ProtocolsResource {
|
|
|
210
333
|
return this.client.put('/protocols/settings', input);
|
|
211
334
|
}
|
|
212
335
|
}
|
|
336
|
+
function assertCandidateId(id) {
|
|
337
|
+
if (typeof id !== 'string' || !id.trim() || id === '.' || id === '..') {
|
|
338
|
+
throw new ValidationError({
|
|
339
|
+
type: 'validation_error',
|
|
340
|
+
code: 'invalid_candidate_id',
|
|
341
|
+
message: 'Candidate ID must be a non-empty identifier, not a URL dot segment.',
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
return id;
|
|
345
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { HttpClient } from '../client.js';
|
|
2
2
|
import type { PaginatedResponse, SingleResponse } from '../types.js';
|
|
3
|
-
export type ReportTargetType = 'post' | 'user' | 'community' | 'message';
|
|
4
|
-
export type ReportStatus = 'pending' | 'resolved' | 'dismissed';
|
|
3
|
+
export type ReportTargetType = 'post' | 'user' | 'community' | 'message' | 'source_actor' | 'source_post';
|
|
4
|
+
export type ReportStatus = 'pending' | 'in_review' | 'escalated' | 'resolved' | 'dismissed';
|
|
5
5
|
export interface CreateReportInput {
|
|
6
|
-
|
|
6
|
+
/** External sources require protocols.reportSource so evidence is verified. */
|
|
7
|
+
target_type: Exclude<ReportTargetType, 'source_actor' | 'source_post'>;
|
|
7
8
|
target_id: string;
|
|
8
9
|
reason: string;
|
|
9
10
|
details?: string;
|
package/llm.md
CHANGED
|
@@ -619,8 +619,9 @@ if (subscription.active) {
|
|
|
619
619
|
- `r.admin` — Admin operations (user management, stats, network settings); content reports: `listReports({ status? })`, `resolveReport(id)`, `dismissReport(id)` (project-bound keys see only their app's reports)
|
|
620
620
|
- `r.inviteCodes` / `r.inviteCodesAdmin` — Invite code management
|
|
621
621
|
- `r.organizationSettings` / `r.organizationSecurity` — Org configuration
|
|
622
|
-
-
|
|
623
|
-
|
|
622
|
+
- Delegated social accounts: `r.protocols.nativeSocialAccounts()`, `startNativeSocialConnection({ protocol, identifier })`, `finishNativeSocialConnection({ protocol, state, code?, iss?, error? })`, `disconnectNativeSocialAccount(id)`. Example: `const { data } = await r.protocols.startNativeSocialConnection({ protocol: "bluesky", identifier: "alice.bsky.social" })`; open `data.authorizationUrl`, then complete with the same signed-in app user. Never log callback codes, send passwords, or auto-retry OAuth callbacks. Shared replies (off until schema/API deployment and live verification): `prepareNativeReply({ clientMutationId, text, parent: { protocol, nativeId, readRef? }, accountIds, linkedPostAccountIds?, recoverFrom?: { batchId, deliveryIds } })`, `submitNativeReply(id, { approve: true, deliveryIds })`, `nativeReplyStatus(id)`, `nativeReplyHistory({ limit?, cursor? })`, `prepareNativeReplyRemoval(id, { deliveryIds })`, `removeNativeReply(id, { approve: true, removals })`. Review account, destination, `kind`, source and exact `wireText`; connection is not publication approval. `linkedPostAccountIds` explicitly selects different-network standalone posts with a source link, never matching threaded replies or a same-network denial fallback. Preserve mutation IDs, show per-destination results and reconcile uncertain attempts without reposting. To review selected unsent or definitively rejected deliveries again, use recoverFrom with a new mutation ID, the same source/accounts and freshly reviewed text; preserve that ID on uncertain preparation. Only saved recoverable destinations qualify, current gates still apply, and replacedBy disables old sends atomically. Never restart unknown, accepted or published deliveries. The new preview still needs explicit approval. Saved delegated drafts/results: `const { data: history } = await r.protocols.nativeReplyHistory({ limit: 20 })`; use its opaque cursor for the next page and `nativeReplyStatus(item.id)` for details. This is a private read, not a write or provider refresh, and includes Nostr results marked type=nostr. Use nativeNostrReplyResult(item.id) to check that recorded event on its relay without signing or resending. Discard page state on owner/app changes. See README for examples and the callback, revocation and removal contracts.
|
|
623
|
+
- `r.protocols` — Private app safety: `sourceControls` returns current `enabled` plus paged saved choices; `setSourceControl`, `onSourceControlChange` and `reportSource` share app scope. Example: `const choices = new Map(); const stop = r.protocols.onSourceControlChange(change => choices.set(JSON.stringify([change.source, change.control]), change.enabled));` then `await r.protocols.setSourceControl({ source: { protocol: "bluesky", kind: "actor", nativeId: "did:plc:aaaaaaaaaaaaaaaaaaaaaaaa" }, control: "mute", enabled: true, scope: "minds" });` and call `stop(); choices.clear()` on account change/unmount. Notifications follow an exact server confirmation, never an uncertain response. These preferences and reports apply in Minds, not on the remote network. 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`.
|
|
624
|
+
- 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. For replies, after `nativeNostrAccount()` advertises `reply_text_note`, use `prepareNativeNostr(identityId, { action: "reply", content: draft, parentId: post.nativeId })`. Review returned parent/root/participants/relay and exact event, sign with the connected client signer, then `submitNativeNostr(identityId, { intent, event, approve: true })`. Requires users:read, posts:read and posts:write. Kind1 public notes only; reply enablement and shared UI/live proof remain pending. Do not inherit arbitrary notification tags or relay hints. Signing mutations never auto-retry; check `getNativeNostrPost(identityId, eventId)` after uncertainty before a user-selected identical-event retry.
|
|
624
625
|
- 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.
|
|
625
626
|
- `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.
|
|
626
627
|
- 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`.
|
|
@@ -795,3 +796,12 @@ catch (e) { if (e.status === 404) { /* private or doesn't exist */ } }
|
|
|
795
796
|
9. **`r.memory` rejects secrets.** Facts containing patterns like `sk_`, `api_key=`, `password=`, or private keys are rejected on write. Store secrets in environment variables, not memory.
|
|
796
797
|
10. **Memory is network-scoped.** Facts and decisions are isolated per network (tenant). Two teams on different networks cannot see each other's memory.
|
|
797
798
|
11. **`r.memory.context()` has a token budget.** Default is 2000 tokens (~8000 chars). Pass `max_tokens` to control how much context is returned.
|
|
799
|
+
|
|
800
|
+
Nostr replies and linked posts are saved in the same `protocols.nativeReplyHistory()`
|
|
801
|
+
feed after signed submission. Items with `type: 'nostr'` use
|
|
802
|
+
`protocols.nativeNostrReplyResult(id)` for a read-only check of the saved event and
|
|
803
|
+
its author's deletion requests on the recorded relay. Other history items use
|
|
804
|
+
`nativeReplyStatus(id)`. Do not turn an unknown result into a fresh preparation or
|
|
805
|
+
publication; history stores no signature, signing key or intent. Keep the acting
|
|
806
|
+
user/app-bound result IDs and discard UI state after an account switch. The last
|
|
807
|
+
read-back observation is separate from retained publication/deletion evidence.
|