@recursiv/sdk 0.7.26 → 0.7.27
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 +2 -2
- 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 +317 -4
- package/dist/resources/protocols.js +110 -2
- 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';
|
|
@@ -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';
|
|
@@ -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;
|
|
@@ -162,10 +162,199 @@ export interface HostedNostrIdentityProof {
|
|
|
162
162
|
export type NativeNostrPrepareInput = {
|
|
163
163
|
action: 'publish';
|
|
164
164
|
content: string;
|
|
165
|
+
} | {
|
|
166
|
+
action: 'reply';
|
|
167
|
+
content: string;
|
|
168
|
+
parentId: string;
|
|
169
|
+
} | {
|
|
170
|
+
action: 'linked_post';
|
|
171
|
+
content: string;
|
|
172
|
+
source: {
|
|
173
|
+
protocol: NativeSocialProtocol;
|
|
174
|
+
nativeId: string;
|
|
175
|
+
readRef?: string;
|
|
176
|
+
};
|
|
165
177
|
} | {
|
|
166
178
|
action: 'delete';
|
|
167
179
|
postId: string;
|
|
168
180
|
};
|
|
181
|
+
export type NativeSocialProtocol = 'bluesky' | 'activitypub';
|
|
182
|
+
export interface NativeSocialAccount {
|
|
183
|
+
id: string;
|
|
184
|
+
protocol: NativeSocialProtocol;
|
|
185
|
+
nativeId: string;
|
|
186
|
+
serverUrl: string;
|
|
187
|
+
handle: string;
|
|
188
|
+
connectedAt: string;
|
|
189
|
+
capabilities: string[];
|
|
190
|
+
}
|
|
191
|
+
/** A Minds-hosted ActivityPub identity for this app user. Keys never leave the platform. */
|
|
192
|
+
export interface FederationIdentity {
|
|
193
|
+
identifier: string;
|
|
194
|
+
actorUri: string;
|
|
195
|
+
handle: string;
|
|
196
|
+
enabled: boolean;
|
|
197
|
+
origin: string;
|
|
198
|
+
}
|
|
199
|
+
export interface FederationIdentityView {
|
|
200
|
+
enabled: boolean;
|
|
201
|
+
origin: string | null;
|
|
202
|
+
identity: FederationIdentity | null;
|
|
203
|
+
}
|
|
204
|
+
export interface SocialSourceRef {
|
|
205
|
+
protocol: 'bluesky' | 'activitypub' | 'nostr';
|
|
206
|
+
kind: 'actor' | 'post';
|
|
207
|
+
nativeId: string;
|
|
208
|
+
}
|
|
209
|
+
export interface SocialSourceControl {
|
|
210
|
+
id: string;
|
|
211
|
+
source: SocialSourceRef;
|
|
212
|
+
control: 'block' | 'mute' | 'hide';
|
|
213
|
+
scope: 'minds';
|
|
214
|
+
createdAt: string;
|
|
215
|
+
}
|
|
216
|
+
export type SocialSourceControlChange = Omit<SocialSourceControl, 'id' | 'createdAt'> & {
|
|
217
|
+
enabled: boolean;
|
|
218
|
+
};
|
|
219
|
+
export interface NativeReplyPrepareInput {
|
|
220
|
+
clientMutationId: string;
|
|
221
|
+
text: string;
|
|
222
|
+
parent: {
|
|
223
|
+
protocol: SocialSourceRef['protocol'];
|
|
224
|
+
nativeId: string;
|
|
225
|
+
readRef?: string;
|
|
226
|
+
};
|
|
227
|
+
accountIds: string[];
|
|
228
|
+
/** Selected different-network accounts to review as standalone posts with a source link. */
|
|
229
|
+
linkedPostAccountIds?: string[];
|
|
230
|
+
/** Fresh review of selected unsent or definitively rejected deliveries. The original selected reviews are atomically fenced; preserve this mutation ID on retry. */
|
|
231
|
+
recoverFrom?: {
|
|
232
|
+
batchId: string;
|
|
233
|
+
deliveryIds: string[];
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
export interface NativeReplyReceipt {
|
|
237
|
+
state: 'published' | 'accepted' | 'unknown' | 'rejected';
|
|
238
|
+
nativeId: string | null;
|
|
239
|
+
sourceUrl: string | null;
|
|
240
|
+
providerId: string | null;
|
|
241
|
+
acknowledged: boolean;
|
|
242
|
+
readBack: 'matched' | 'absent' | 'unavailable';
|
|
243
|
+
}
|
|
244
|
+
export interface NativeReplyRemovalReceipt {
|
|
245
|
+
/** Absence is observed on the owning server; this is not global erasure. */
|
|
246
|
+
state: 'absent' | 'accepted' | 'unknown' | 'rejected';
|
|
247
|
+
acknowledged: boolean;
|
|
248
|
+
readBack: 'absent' | 'present' | 'unavailable';
|
|
249
|
+
}
|
|
250
|
+
export interface NativeReplyRemovalPreview {
|
|
251
|
+
id: string;
|
|
252
|
+
previews: Array<{
|
|
253
|
+
deliveryId: string;
|
|
254
|
+
removalId: string;
|
|
255
|
+
expiresAt: string;
|
|
256
|
+
protocol: NativeSocialProtocol;
|
|
257
|
+
nativeId: string;
|
|
258
|
+
providerId: string;
|
|
259
|
+
sourceUrl: string;
|
|
260
|
+
revision: string | null;
|
|
261
|
+
text: string | null;
|
|
262
|
+
additionalContent: boolean;
|
|
263
|
+
account: {
|
|
264
|
+
nativeId: string;
|
|
265
|
+
handle: string;
|
|
266
|
+
serverUrl: string;
|
|
267
|
+
} | null;
|
|
268
|
+
}>;
|
|
269
|
+
errors: Record<string, {
|
|
270
|
+
code: string;
|
|
271
|
+
message: string;
|
|
272
|
+
}>;
|
|
273
|
+
}
|
|
274
|
+
export interface NativeReplyBatch {
|
|
275
|
+
id: string;
|
|
276
|
+
clientMutationId: string;
|
|
277
|
+
expiresAt: string;
|
|
278
|
+
deliveries: Array<{
|
|
279
|
+
id: string;
|
|
280
|
+
grantId: string;
|
|
281
|
+
protocol: NativeSocialProtocol;
|
|
282
|
+
kind: 'reply' | 'linked_post';
|
|
283
|
+
state: 'prepared' | 'sending' | NativeReplyReceipt['state'];
|
|
284
|
+
attemptedAt: string | null;
|
|
285
|
+
/** Saved attempt eligibility only; source, account authority and app/provider gates are checked again during preparation. */
|
|
286
|
+
recoverable?: boolean;
|
|
287
|
+
/** Newer batch that replaced this destination's approval. This old destination cannot publish. */
|
|
288
|
+
replacedBy?: string;
|
|
289
|
+
account: {
|
|
290
|
+
nativeId: string;
|
|
291
|
+
handle: string;
|
|
292
|
+
serverUrl: string;
|
|
293
|
+
} | null;
|
|
294
|
+
parent: {
|
|
295
|
+
protocol: SocialSourceRef['protocol'];
|
|
296
|
+
nativeId: string;
|
|
297
|
+
sourceUrl: string;
|
|
298
|
+
authorId: string;
|
|
299
|
+
authorHandle: string;
|
|
300
|
+
text: string;
|
|
301
|
+
textTruncated?: boolean;
|
|
302
|
+
};
|
|
303
|
+
text: string;
|
|
304
|
+
wireText: string;
|
|
305
|
+
receipt: NativeReplyReceipt | null;
|
|
306
|
+
removal: {
|
|
307
|
+
id: string;
|
|
308
|
+
expiresAt: string;
|
|
309
|
+
attemptedAt: string | null;
|
|
310
|
+
receipt: NativeReplyRemovalReceipt | null;
|
|
311
|
+
} | null;
|
|
312
|
+
}>;
|
|
313
|
+
}
|
|
314
|
+
export interface NativeSocialCallbackInput {
|
|
315
|
+
protocol: NativeSocialProtocol;
|
|
316
|
+
state: string;
|
|
317
|
+
code?: string;
|
|
318
|
+
iss?: string;
|
|
319
|
+
error?: string;
|
|
320
|
+
}
|
|
321
|
+
export interface NativeDelegatedReplyHistoryItem {
|
|
322
|
+
id: string;
|
|
323
|
+
createdAt: string;
|
|
324
|
+
text: string;
|
|
325
|
+
textTruncated: boolean;
|
|
326
|
+
source: Pick<NativeReplyBatch['deliveries'][number]['parent'], 'protocol' | 'nativeId' | 'sourceUrl'>;
|
|
327
|
+
deliveries: Array<Pick<NativeReplyBatch['deliveries'][number], 'id' | 'protocol' | 'kind' | 'state' | 'attemptedAt' | 'account' | 'recoverable' | 'replacedBy'> & {
|
|
328
|
+
removalReceipt: NativeReplyRemovalReceipt | null;
|
|
329
|
+
}>;
|
|
330
|
+
}
|
|
331
|
+
export interface NativeNostrReplyResult {
|
|
332
|
+
id: string;
|
|
333
|
+
createdAt: string;
|
|
334
|
+
text: string;
|
|
335
|
+
source: {
|
|
336
|
+
protocol: SocialSourceRef['protocol'];
|
|
337
|
+
nativeId: string;
|
|
338
|
+
sourceUrl: string;
|
|
339
|
+
};
|
|
340
|
+
identityId: string;
|
|
341
|
+
pubkey: string;
|
|
342
|
+
relay: string;
|
|
343
|
+
eventId: string;
|
|
344
|
+
action: 'reply' | 'linked_post';
|
|
345
|
+
receipt: NativeNostrReceipt;
|
|
346
|
+
checkedAt: string | null;
|
|
347
|
+
lastReadBack: NativeNostrReceipt['readBack'];
|
|
348
|
+
}
|
|
349
|
+
export interface NativeNostrReplyHistoryItem extends NativeNostrReplyResult {
|
|
350
|
+
type: 'nostr';
|
|
351
|
+
textTruncated: boolean;
|
|
352
|
+
}
|
|
353
|
+
export interface NativeReplyHistory {
|
|
354
|
+
/** One private history, including client-signed Nostr replies once submitted. */
|
|
355
|
+
items: Array<NativeDelegatedReplyHistoryItem | NativeNostrReplyHistoryItem>;
|
|
356
|
+
cursor: string | null;
|
|
357
|
+
}
|
|
169
358
|
export interface NativeNostrPrepared {
|
|
170
359
|
intent: string;
|
|
171
360
|
event: {
|
|
@@ -175,17 +364,42 @@ export interface NativeNostrPrepared {
|
|
|
175
364
|
tags: string[][];
|
|
176
365
|
};
|
|
177
366
|
eventId: string;
|
|
178
|
-
action: 'publish' | 'delete';
|
|
367
|
+
action: 'publish' | 'reply' | 'linked_post' | 'delete';
|
|
179
368
|
identityId: string;
|
|
180
369
|
pubkey: string;
|
|
181
370
|
relay: string;
|
|
182
371
|
expiresAt: string;
|
|
183
372
|
postId?: string;
|
|
373
|
+
parent?: {
|
|
374
|
+
protocol: 'nostr';
|
|
375
|
+
nativeId: string;
|
|
376
|
+
authorId: string;
|
|
377
|
+
authorHandle: string;
|
|
378
|
+
sourceUrl: string;
|
|
379
|
+
text: string;
|
|
380
|
+
textTruncated: boolean;
|
|
381
|
+
root: {
|
|
382
|
+
nativeId: string;
|
|
383
|
+
authorId: string;
|
|
384
|
+
sourceUrl: string;
|
|
385
|
+
};
|
|
386
|
+
participants: string[];
|
|
387
|
+
tags: string[][];
|
|
388
|
+
};
|
|
389
|
+
source?: {
|
|
390
|
+
protocol: NativeSocialProtocol;
|
|
391
|
+
nativeId: string;
|
|
392
|
+
authorId: string;
|
|
393
|
+
authorHandle: string;
|
|
394
|
+
sourceUrl: string;
|
|
395
|
+
text: string;
|
|
396
|
+
textTruncated?: boolean;
|
|
397
|
+
};
|
|
184
398
|
}
|
|
185
399
|
export interface NativeNostrAccount {
|
|
186
400
|
enabled: boolean;
|
|
187
401
|
identity: HostedProtocolIdentity | null;
|
|
188
|
-
capabilities: Array<'publish_original_text' | 'request_own_post_deletion'>;
|
|
402
|
+
capabilities: Array<'publish_original_text' | 'request_own_post_deletion' | 'reply_text_note' | 'publish_linked_text'>;
|
|
189
403
|
signing?: 'client';
|
|
190
404
|
}
|
|
191
405
|
export interface NativeNostrPostState {
|
|
@@ -202,7 +416,7 @@ export interface NativeNostrReceipt {
|
|
|
202
416
|
eventId: string;
|
|
203
417
|
postId: string;
|
|
204
418
|
relay: string;
|
|
205
|
-
action: 'publish' | 'delete';
|
|
419
|
+
action: 'publish' | 'reply' | 'linked_post' | 'delete';
|
|
206
420
|
state: 'published' | 'deletion_requested' | 'unknown' | 'rejected';
|
|
207
421
|
acknowledged: boolean;
|
|
208
422
|
readBack: 'found' | 'absent' | 'unavailable';
|
|
@@ -380,10 +594,13 @@ export interface SocialFollowingFeed {
|
|
|
380
594
|
export declare class ProtocolsResource {
|
|
381
595
|
private client;
|
|
382
596
|
private subscriptionListeners;
|
|
597
|
+
private sourceControlListeners;
|
|
383
598
|
constructor(client: HttpClient);
|
|
384
599
|
/** Confirmed changes from this SDK instance only. Unsubscribe when a view unmounts or its account changes. */
|
|
385
600
|
onSubscriptionChange(listener: (change: SocialSubscriptionChange) => void): () => void;
|
|
386
601
|
private subscriptionChanged;
|
|
602
|
+
/** Confirmed safety choices from this authenticated SDK instance. Unsubscribe when its account or view changes. */
|
|
603
|
+
onSourceControlChange(listener: (change: SocialSourceControlChange) => void): () => void;
|
|
387
604
|
publicNetworks(): Promise<SingleResponse<SocialNetwork[]>>;
|
|
388
605
|
/** Query the live public network. It does not import users or posts. */
|
|
389
606
|
searchPublicProfiles(params: SearchPublicProfilesParams): Promise<SingleResponse<SocialProfilePage>>;
|
|
@@ -419,17 +636,113 @@ export declare class ProtocolsResource {
|
|
|
419
636
|
limit?: number;
|
|
420
637
|
cursor?: string;
|
|
421
638
|
}): Promise<SingleResponse<SocialTrendFeed>>;
|
|
639
|
+
/** Prepare one exact shared reply preview. Keep the mutation ID across uncertain responses. */
|
|
640
|
+
prepareNativeReply(input: NativeReplyPrepareInput): Promise<SingleResponse<NativeReplyBatch>>;
|
|
641
|
+
/** Send only explicitly approved delivery IDs from this preview. Repeated submissions reconcile; they do not replay a write. */
|
|
642
|
+
submitNativeReply(id: string, input: {
|
|
643
|
+
approve: true;
|
|
644
|
+
deliveryIds: string[];
|
|
645
|
+
}): Promise<SingleResponse<NativeReplyBatch & {
|
|
646
|
+
errors: Record<string, {
|
|
647
|
+
code: string;
|
|
648
|
+
message: string;
|
|
649
|
+
}>;
|
|
650
|
+
}>>;
|
|
651
|
+
/** Read saved delivery results after refresh. This never publishes or contacts a source network. */
|
|
652
|
+
nativeReplyStatus(id: string): Promise<SingleResponse<NativeReplyBatch>>;
|
|
653
|
+
/** Page through this app user's saved delegated drafts/results. This never publishes, refreshes credentials or queries a source network. */
|
|
654
|
+
nativeReplyHistory(params?: {
|
|
655
|
+
limit?: number;
|
|
656
|
+
cursor?: string;
|
|
657
|
+
}): Promise<SingleResponse<NativeReplyHistory>>;
|
|
658
|
+
/** Review the current own posts before removal. A new preview replaces the previous approval. */
|
|
659
|
+
prepareNativeReplyRemoval(id: string, input: {
|
|
660
|
+
deliveryIds: string[];
|
|
661
|
+
}): Promise<SingleResponse<NativeReplyRemovalPreview>>;
|
|
662
|
+
/** Remove only selected, freshly reviewed destinations. Repeating approval never repeats a native delete. */
|
|
663
|
+
removeNativeReply(id: string, input: {
|
|
664
|
+
approve: true;
|
|
665
|
+
removals: Array<{
|
|
666
|
+
deliveryId: string;
|
|
667
|
+
removalId: string;
|
|
668
|
+
}>;
|
|
669
|
+
}): Promise<SingleResponse<NativeReplyBatch & {
|
|
670
|
+
errors: Record<string, {
|
|
671
|
+
code: string;
|
|
672
|
+
message: string;
|
|
673
|
+
}>;
|
|
674
|
+
}>>;
|
|
675
|
+
/** List this app user's delegated accounts. A connection is not approval to post. */
|
|
676
|
+
nativeSocialAccounts(): Promise<SingleResponse<{
|
|
677
|
+
enabled: boolean;
|
|
678
|
+
accounts: NativeSocialAccount[];
|
|
679
|
+
}>>;
|
|
680
|
+
/** Private source controls in this app, with bounded pagination. */
|
|
681
|
+
sourceControls(params?: {
|
|
682
|
+
limit?: number;
|
|
683
|
+
cursor?: string;
|
|
684
|
+
}): Promise<SingleResponse<{
|
|
685
|
+
enabled: boolean;
|
|
686
|
+
items: SocialSourceControl[];
|
|
687
|
+
cursor: string | null;
|
|
688
|
+
}>>;
|
|
689
|
+
/** Block/mute an actor or hide a post in Minds. This does not impersonate a native network block. */
|
|
690
|
+
setSourceControl(input: {
|
|
691
|
+
source: SocialSourceRef;
|
|
692
|
+
control: 'block' | 'mute' | 'hide';
|
|
693
|
+
enabled: boolean;
|
|
694
|
+
scope: 'minds';
|
|
695
|
+
}): Promise<SingleResponse<SocialSourceControlChange>>;
|
|
696
|
+
/** File a report in the app's existing moderation queue, using server-read public source evidence. */
|
|
697
|
+
reportSource(input: {
|
|
698
|
+
source: SocialSourceRef;
|
|
699
|
+
readRef?: string;
|
|
700
|
+
reason: string;
|
|
701
|
+
details?: string;
|
|
702
|
+
scope: 'minds';
|
|
703
|
+
}): Promise<SingleResponse<{
|
|
704
|
+
id: string;
|
|
705
|
+
status: string;
|
|
706
|
+
existing: boolean;
|
|
707
|
+
scope: 'minds';
|
|
708
|
+
}>>;
|
|
709
|
+
/** Open the returned authorization URL in the user's browser; never submit passwords or tokens. */
|
|
710
|
+
startNativeSocialConnection(input: {
|
|
711
|
+
protocol: NativeSocialProtocol;
|
|
712
|
+
identifier: string;
|
|
713
|
+
}): Promise<SingleResponse<{
|
|
714
|
+
protocol: NativeSocialProtocol;
|
|
715
|
+
authorizationUrl: string;
|
|
716
|
+
}>>;
|
|
717
|
+
/** Complete a single-use callback with the same signed-in app user. Remove its query from browser history; do not log codes. */
|
|
718
|
+
finishNativeSocialConnection(input: NativeSocialCallbackInput): Promise<SingleResponse<NativeSocialAccount>>;
|
|
719
|
+
/** Disable this app's saved authority even when the provider cannot acknowledge revocation. */
|
|
720
|
+
disconnectNativeSocialAccount(id: string): Promise<SingleResponse<{
|
|
721
|
+
disconnected: true;
|
|
722
|
+
providerRevocation: 'acknowledged' | 'unconfirmed';
|
|
723
|
+
}>>;
|
|
724
|
+
/** Current Minds-hosted ActivityPub state for this app user; never provisions. */
|
|
725
|
+
federationIdentity(): Promise<SingleResponse<FederationIdentityView>>;
|
|
726
|
+
/** Explicit opt-in; the platform provisions once and never rotates keys or re-enables a disabled identity on retry. */
|
|
727
|
+
enableFederationIdentity(): Promise<SingleResponse<FederationIdentityView>>;
|
|
728
|
+
/** Stops serving and signing for the identity; its stable URL and keys are retained by the platform. */
|
|
729
|
+
disableFederationIdentity(): Promise<SingleResponse<{
|
|
730
|
+
disabled: true;
|
|
731
|
+
identity: FederationIdentity;
|
|
732
|
+
}>>;
|
|
422
733
|
/** Native writes are off unless enabled for this exact app; public readers are independent. */
|
|
423
734
|
nativeNostrAccount(): Promise<SingleResponse<NativeNostrAccount>>;
|
|
424
735
|
/** Prepare an exact event for review. A timeout never automatically creates another signing request. */
|
|
425
736
|
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).
|
|
737
|
+
/** Pass only the public signed event. After a timeout, read the prepared postId (delete) or eventId (publish/reply/linked_post).
|
|
427
738
|
* Any user-selected retry keeps the same intent/event. */
|
|
428
739
|
submitNativeNostr(id: string, input: {
|
|
429
740
|
intent: string;
|
|
430
741
|
event: HostedNostrIdentityProof;
|
|
431
742
|
approve: true;
|
|
432
743
|
}): Promise<SingleResponse<NativeNostrReceipt>>;
|
|
744
|
+
/** Check only the event bound to this private saved result; never sign, prepare or resend it. */
|
|
745
|
+
nativeNostrReplyResult(id: string): Promise<SingleResponse<NativeNostrReplyResult>>;
|
|
433
746
|
getNativeNostrPost(id: string, postId: string): Promise<SingleResponse<NativeNostrPostState>>;
|
|
434
747
|
/** Save a private reading subscription after resolving the immutable native ID. */
|
|
435
748
|
subscribeToProfile(input: {
|
|
@@ -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))
|
|
@@ -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.
|