@recursiv/sdk 0.7.152 → 0.7.195

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.
@@ -27,12 +27,14 @@ export interface CreateEvalInput {
27
27
  }
28
28
  export interface SimulateInput {
29
29
  target: EvidenceTarget;
30
- /** The batch of cases to run through the target. */
31
- cases: Array<{
30
+ /** The batch of cases to run through the target. Pass this or `eval_set_id`. */
31
+ cases?: Array<{
32
32
  input: string;
33
33
  expected?: Record<string, unknown>;
34
34
  label?: string;
35
35
  }>;
36
+ /** Run a saved set from {@link EvidenceResource.createEvalSet} instead of inline cases. */
37
+ eval_set_id?: string;
36
38
  /** Optionally attach evals for this run (also saved to the target). */
37
39
  evals?: Array<Omit<CreateEvalInput, 'target'>>;
38
40
  run_type?: 'test' | 'real';
@@ -41,6 +43,40 @@ export interface SimulateInput {
41
43
  /** Attach the run to a project so it appears there, not only on the agent. */
42
44
  project_id?: string;
43
45
  }
46
+ /** A reusable set of cases with known answers, run with `simulate({ eval_set_id })`. */
47
+ export interface CreateEvalSetInput {
48
+ name: string;
49
+ /** 1 to 50 cases. `weight` 1-100 (default 1); `trap` marks a case built to catch a wrong answer. */
50
+ cases: Array<{
51
+ input: string;
52
+ expected?: Record<string, unknown>;
53
+ weight?: number;
54
+ trap?: boolean;
55
+ label?: string;
56
+ }>;
57
+ description?: string;
58
+ scoring_mode?: 'exact' | 'judge';
59
+ /** For judge scoring: what a good answer looks like. */
60
+ rubric?: string;
61
+ /** Defaults to the key's organization; omit both for a personal set. */
62
+ organization_id?: string;
63
+ project_id?: string;
64
+ }
65
+ export interface EvalSetRow {
66
+ id: string;
67
+ name: string;
68
+ description: string | null;
69
+ scoringMode: string;
70
+ organizationId: string | null;
71
+ projectId: string | null;
72
+ createdAt: string;
73
+ }
74
+ /** A run's result matrix as a file body. */
75
+ export interface EvalRunExport {
76
+ filename: string;
77
+ mimeType: string;
78
+ content: string;
79
+ }
44
80
  export interface EvalRunRow {
45
81
  id: string;
46
82
  targetType: string;
@@ -167,6 +203,25 @@ export declare class EvidenceResource {
167
203
  reason: string;
168
204
  }>;
169
205
  }>>;
206
+ /**
207
+ * Save a reusable set of cases with known answers. Run it as often as you
208
+ * like with `simulate({ target, eval_set_id })`, so runs compare like with like.
209
+ */
210
+ createEvalSet(input: CreateEvalSetInput): Promise<SingleResponse<{
211
+ eval_set_id: string;
212
+ case_count: number;
213
+ }>>;
214
+ /**
215
+ * The saved sets you can run: an organization's (the key's own by default),
216
+ * or, for a personal key with no organization, the ones you made.
217
+ */
218
+ listEvalSets(opts?: {
219
+ organizationId?: string;
220
+ }): Promise<{
221
+ data: EvalSetRow[];
222
+ }>;
223
+ /** A run's result matrix as CSV (default) or JSON, for offline analysis. */
224
+ exportRun(runId: string, format?: 'csv' | 'json'): Promise<SingleResponse<EvalRunExport>>;
170
225
  /** Recent runs for a target. */
171
226
  listRuns(target: EvidenceTarget, limit?: number): Promise<{
172
227
  data: EvalRunRow[];
@@ -26,6 +26,25 @@ export class EvidenceResource {
26
26
  runTaskChecks(taskId) {
27
27
  return this.client.post('/evidence/task-checks/run', { task_id: taskId });
28
28
  }
29
+ /**
30
+ * Save a reusable set of cases with known answers. Run it as often as you
31
+ * like with `simulate({ target, eval_set_id })`, so runs compare like with like.
32
+ */
33
+ createEvalSet(input) {
34
+ return this.client.post('/evidence/eval-sets', input);
35
+ }
36
+ /**
37
+ * The saved sets you can run: an organization's (the key's own by default),
38
+ * or, for a personal key with no organization, the ones you made.
39
+ */
40
+ listEvalSets(opts = {}) {
41
+ const query = opts.organizationId ? `?organization_id=${encodeURIComponent(opts.organizationId)}` : '';
42
+ return this.client.get(`/evidence/eval-sets${query}`);
43
+ }
44
+ /** A run's result matrix as CSV (default) or JSON, for offline analysis. */
45
+ exportRun(runId, format = 'csv') {
46
+ return this.client.get(`/evidence/runs/${runId}/export?format=${format}`);
47
+ }
29
48
  /** Recent runs for a target. */
30
49
  listRuns(target, limit = 20) {
31
50
  return this.client.get(`/evidence/runs?target_type=${target.type}&target_id=${encodeURIComponent(target.id)}&limit=${limit}`);
@@ -160,6 +160,57 @@ export interface FeedTopResponse {
160
160
  lead: FeedStory | null;
161
161
  meta: FeedTopMeta;
162
162
  }
163
+ /** The networks a firehose item comes from: Minds, and the open networks the top's lanes carry. */
164
+ export type FeedFirehoseNetwork = 'minds' | 'bluesky' | 'activitypub' | 'nostr';
165
+ /**
166
+ * One firehose item (0.7.195): an item of the top of a feed, with its network, its state, when it was published and when
167
+ * the server chose it. An open-network post carries its `card` to draw (no URL on its network: open it by `target.path`).
168
+ */
169
+ export interface FeedFirehoseItem extends FeedTopItem {
170
+ network: FeedFirehoseNetwork;
171
+ /** 'breaking' (its radar story broke in the last 6 hours) or 'viral'; at most one, else null. */
172
+ state: 'breaking' | 'viral' | null;
173
+ /** When the post was published (ISO). */
174
+ publishedAt: string;
175
+ /** When the server chose it for this answer (ISO, the server's clock). */
176
+ chosenAt: string;
177
+ /** An open-network post's card. */
178
+ card?: FeedTopNetworkCard;
179
+ }
180
+ export interface FeedFirehoseMeta {
181
+ /** The soonest to read again, in ms: longer when the answer was short or the server is busy. */
182
+ refillAfterMs: number;
183
+ /** The oldest shared snapshot the stream's pool was composed from (ISO). */
184
+ poolBuiltAt: string;
185
+ poolSize: number;
186
+ /** 'safe' for a member on safe defaults, 'open' for one who turned them off. */
187
+ safety: 'safe' | 'open';
188
+ /** Fewer items than asked for: supply is thin, so read again after `refillAfterMs`. */
189
+ short: boolean;
190
+ networks: Record<'bluesky' | 'activitypub' | 'nostr', 'ok' | 'unavailable'>;
191
+ /**
192
+ * Whether the server kept this session from repeating: 'on'; 'full' when the session's record is at its cap; and
193
+ * 'unavailable' when it could not (guard against repeats in the app, over more of what it showed).
194
+ */
195
+ sent: 'on' | 'full' | 'unavailable';
196
+ compass_filter?: CompassFilterMeta;
197
+ }
198
+ /** GET /feeds/firehose. `retract` names refs the session was sent that were taken down since: remove them wherever they are held. */
199
+ export interface FeedFirehoseResponse {
200
+ items: FeedFirehoseItem[];
201
+ retract: string[];
202
+ meta: FeedFirehoseMeta;
203
+ }
204
+ export interface FeedFirehoseParams {
205
+ /** Opaque per app session ([A-Za-z0-9_-], up to 64), required: nothing is sent twice within one session. */
206
+ session: string;
207
+ /** 1..25, default 20. */
208
+ limit?: number;
209
+ /** A Politics choice, as `posts.list` takes it. */
210
+ compass?: string;
211
+ /** Only one network's items: `all` (default), `minds`, `bluesky`, `activitypub` or `nostr`. */
212
+ network?: 'all' | FeedFirehoseNetwork;
213
+ }
163
214
  export interface FeedStoriesResponse {
164
215
  data: FeedStory[];
165
216
  meta: {
@@ -230,6 +281,18 @@ export declare class FeedsResource {
230
281
  top(params: FeedTopParams, options?: {
231
282
  retry?: boolean;
232
283
  }): Promise<FeedTopResponse>;
284
+ /**
285
+ * The firehose for the signed-in member, with their own key of the app (0.7.195): the next items of their live stream of
286
+ * the most engaged, viral and breaking posts of Minds and the open networks, every one re-checked for them on the
287
+ * server, none sent twice in one `session`. Reveal them one at a time; read again no sooner than `meta.refillAfterMs`.
288
+ * Off (404) until the app's operator turns it on; 429 `rate_limited` and 503 `firehose_unavailable` carry Retry-After.
289
+ * A Mix or Choose sides `compass` spends one of the member's hourly sided Politics reads at most once per `session` and
290
+ * choice in ten minutes; 429 `compass_rate_limited` when they are spent (choose Everything or Hide politics, or wait).
291
+ * Always private: never cached for anyone else.
292
+ */
293
+ firehose(params: FeedFirehoseParams, options?: {
294
+ retry?: boolean;
295
+ }): Promise<FeedFirehoseResponse>;
233
296
  /** The stories the member should meet next (the story tail), by the same ranker as the top's lead. */
234
297
  stories(params?: FeedStoriesParams, options?: {
235
298
  retry?: boolean;
@@ -14,6 +14,18 @@ export class FeedsResource {
14
14
  top(params, options) {
15
15
  return this.http.get('/feeds/top', { ref: params.ref, limit: params.limit, session: params.session, compass: params.compass }, options);
16
16
  }
17
+ /**
18
+ * The firehose for the signed-in member, with their own key of the app (0.7.195): the next items of their live stream of
19
+ * the most engaged, viral and breaking posts of Minds and the open networks, every one re-checked for them on the
20
+ * server, none sent twice in one `session`. Reveal them one at a time; read again no sooner than `meta.refillAfterMs`.
21
+ * Off (404) until the app's operator turns it on; 429 `rate_limited` and 503 `firehose_unavailable` carry Retry-After.
22
+ * A Mix or Choose sides `compass` spends one of the member's hourly sided Politics reads at most once per `session` and
23
+ * choice in ten minutes; 429 `compass_rate_limited` when they are spent (choose Everything or Hide politics, or wait).
24
+ * Always private: never cached for anyone else.
25
+ */
26
+ firehose(params, options) {
27
+ return this.http.get('/feeds/firehose', { session: params.session, limit: params.limit, compass: params.compass, network: params.network }, options);
28
+ }
17
29
  /** The stories the member should meet next (the story tail), by the same ranker as the top's lead. */
18
30
  stories(params = {}, options) {
19
31
  return this.http.get('/feeds/stories', { after: params.after, limit: params.limit, compass: params.compass }, options);