@recursiv/sdk 0.7.27 → 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/dist/index.d.ts +1 -1
- 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/protocols.d.ts +49 -1
- package/dist/resources/protocols.js +33 -8
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -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';
|
|
@@ -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
|
|
@@ -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. */
|
|
@@ -784,6 +817,21 @@ export declare class ProtocolsResource {
|
|
|
784
817
|
* unsupported deployed route) propagate; they are never an empty page.
|
|
785
818
|
*/
|
|
786
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>>;
|
|
787
835
|
/**
|
|
788
836
|
* Read one quarantined candidate under the same authorization as listCandidates.
|
|
789
837
|
* Empty and URL dot-segment IDs reject with ValidationError before any request;
|
|
@@ -282,24 +282,39 @@ export class ProtocolsResource {
|
|
|
282
282
|
listCandidates(params) {
|
|
283
283
|
return this.client.get('/protocols/candidates', params ? {
|
|
284
284
|
protocol: params.protocol,
|
|
285
|
+
state: params.state,
|
|
285
286
|
limit: params.limit,
|
|
286
287
|
cursor: params.cursor,
|
|
287
288
|
} : undefined);
|
|
288
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
|
+
}
|
|
289
311
|
/**
|
|
290
312
|
* Read one quarantined candidate under the same authorization as listCandidates.
|
|
291
313
|
* Empty and URL dot-segment IDs reject with ValidationError before any request;
|
|
292
314
|
* all other IDs are encoded as one path segment and validated by the API.
|
|
293
315
|
*/
|
|
294
316
|
async getCandidate(id) {
|
|
295
|
-
|
|
296
|
-
throw new ValidationError({
|
|
297
|
-
type: 'validation_error',
|
|
298
|
-
code: 'invalid_candidate_id',
|
|
299
|
-
message: 'Candidate ID must be a non-empty identifier, not a URL dot segment.',
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
return this.client.get(`/protocols/candidates/${encodeURIComponent(id)}`);
|
|
317
|
+
return this.client.get(`/protocols/candidates/${encodeURIComponent(assertCandidateId(id))}`);
|
|
303
318
|
}
|
|
304
319
|
/** Cross-protocol full-text search */
|
|
305
320
|
search(params) {
|
|
@@ -318,3 +333,13 @@ export class ProtocolsResource {
|
|
|
318
333
|
return this.client.put('/protocols/settings', input);
|
|
319
334
|
}
|
|
320
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
|
+
}
|