pareta 1.4.0 → 2.1.0

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.cts CHANGED
@@ -47,6 +47,17 @@ declare class ChatCompletion extends BaseModel {
47
47
  get created(): number | null;
48
48
  get choices(): Choice[];
49
49
  get usage(): Usage;
50
+ /** #164 receipt, held OFF `.raw` so `toDict()` stays the raw server JSON. */
51
+ private _cost?;
52
+ /** #164: attach the per-call receipt from the response headers (billed +
53
+ * the frontier counterfactual, micro-USD ints). Chainable. */
54
+ withCost(headers?: Headers): ChatCompletion;
55
+ /** What Pareta charged, micro-USD (0 on an idempotent replay); null if absent. */
56
+ get billedMicroUsd(): number | null;
57
+ /** What one list-priced frontier call would have cost, micro-USD. */
58
+ get frontierWouldHaveCostMicroUsd(): number | null;
59
+ /** frontier / billed — e.g. 17 = 17× cheaper; null if either is missing or billed is 0. */
60
+ get savingsFactor(): number | null;
50
61
  }
51
62
  /** One SSE delta. `chunk.choices[0].delta.content` is the incremental text. */
52
63
  declare class ChatCompletionChunk extends ChatCompletion {
@@ -87,6 +98,44 @@ declare class EvalSet extends BaseModel {
87
98
  get name(): string | null;
88
99
  get itemCount(): number | null;
89
100
  get scoringStrategy(): string | null;
101
+ /** The one-sentence success criterion this set was created with (CB1:
102
+ * DATA + INTENT). Required at create. */
103
+ get intent(): string | null;
104
+ }
105
+ /**
106
+ * One proposed grading contract for an uploaded dataset (a row of
107
+ * `ProposalResult.proposals`). `warning` is set on the custom-eval floor when
108
+ * the data looks extraction-shaped (judge grading is weaker there).
109
+ */
110
+ declare class ContractProposal extends BaseModel {
111
+ get taskId(): string | null;
112
+ get confidence(): string | null;
113
+ get evidence(): Raw;
114
+ get warning(): string | null;
115
+ }
116
+ /**
117
+ * The binder's answer for `evals.proposeContract` (POST
118
+ * /v1/eval-sets/propose-contract): which grading contract(s) fit your data
119
+ * under your stated intent. Nothing is persisted — confirm by passing the
120
+ * chosen `taskId` (or letting `create` auto-bind a clean single proposal).
121
+ */
122
+ declare class ProposalResult extends BaseModel {
123
+ get proposals(): ContractProposal[];
124
+ get homogeneous(): boolean;
125
+ get split(): Raw | null;
126
+ get conflict(): Raw | null;
127
+ get closestTask(): string | null;
128
+ get intent(): string | null;
129
+ get message(): string | null;
130
+ /** True when the binder matched exactly ONE homogeneous SPECIFIC contract at
131
+ * high/medium confidence and no conflict/split — the case `create` auto-binds
132
+ * without a human confirming. The `custom-eval` universal FLOOR is EXCLUDED:
133
+ * the binder offers it only when no specific contract fits, and per the
134
+ * precision ladder the floor is a CHOICE — the user opts in with
135
+ * `task: "custom-eval"`, never a silent auto-bind. */
136
+ get isClean(): boolean;
137
+ /** The task `create` would auto-bind, or null if the result isn't clean. */
138
+ get boundTask(): string | null;
90
139
  }
91
140
  /**
92
141
  * One scored item inside `EvalResult.perItem`. `prediction` is the model's raw
@@ -281,10 +330,18 @@ declare class Tasks {
281
330
  /**
282
331
  * `client.evals` — eval sets + runs (bring-your-own-data evaluation).
283
332
  *
284
- * const set = await pa.evals.sets.create({ task, items: [...] });
333
+ * // An eval set is DATA + INTENT (v2, breaking): intent REQUIRED, task
334
+ * // OPTIONAL — the binder resolves your intent + the data's shape.
335
+ * await pa.evals.proposeContract({ items: [...], intent: "…" }); // preview
336
+ * const set = await pa.evals.sets.create({ items: [...], intent: "…" }); // auto-binds
285
337
  * await pa.evals.sets.uploadDocument(set.id, file, { idx, fieldName }); // blob tasks
286
338
  * const run = await pa.evals.runs.create({ evalSet: set.id, models: [...], wait: true });
287
- * // or, in one call: runs.create({ task, items, models, wait: true })
339
+ * // or, in one call: runs.create({ items, intent: "…", models, wait: true })
340
+ *
341
+ * `create` (and the inline `runs.create` sugar) require `intent`; with no
342
+ * `task` they call `proposeContract` and auto-bind ONLY a clean single
343
+ * high/medium match — a conflict, split, or ambiguity throws with the
344
+ * proposals so you pin `task`.
288
345
  *
289
346
  * Runs are metered (the org balance is debited for compute); `run.cost` is the
290
347
  * billed total in dollars (floored to cents). `frontier` accepts an explicit
@@ -299,11 +356,22 @@ type FileInput = string | Blob | ArrayBuffer | Uint8Array;
299
356
  declare class EvalSets {
300
357
  private readonly client;
301
358
  constructor(client: Transport);
359
+ /**
360
+ * Persist an eval set from your rows. `intent` is REQUIRED (v2): one sentence
361
+ * on what the model should do with each item. `task` is OPTIONAL — omit it and
362
+ * the binder resolves your intent + the data's shape to a grading contract
363
+ * (auto-binds a clean single match; throws with the proposals otherwise). Pass
364
+ * `task` to pin one explicitly.
365
+ */
302
366
  create(params: {
303
- task: string;
304
367
  items: Array<Record<string, unknown>>;
368
+ intent: string;
369
+ task?: string;
305
370
  name?: string;
306
371
  }): Promise<EvalSet>;
372
+ /** Internal: the binder call `create` uses when no task is pinned. Public on
373
+ * `Evals` as `proposeContract`; kept here so `sets.create` can reach it. */
374
+ proposeContract(items: Array<Record<string, unknown>>, intent: string): Promise<ProposalResult>;
307
375
  list(): Promise<EvalSet[]>;
308
376
  retrieve(evalSetId: string): Promise<EvalSet>;
309
377
  delete(evalSetId: string): Promise<void>;
@@ -322,6 +390,7 @@ interface EvalRunCreateParams {
322
390
  evalSet?: string;
323
391
  task?: string;
324
392
  items?: Array<Record<string, unknown>>;
393
+ intent?: string;
325
394
  models: string[];
326
395
  frontier?: FrontierSpec;
327
396
  name?: string;
@@ -346,6 +415,16 @@ declare class Evals {
346
415
  readonly runs: EvalRuns;
347
416
  constructor(client: Transport);
348
417
  private readonly client;
418
+ /**
419
+ * Which grading contract fits your data under your stated `intent`? Stateless
420
+ * discovery — nothing is persisted. Returns a ProposalResult (ranked
421
+ * proposals, the auto-bind decision, conflict/split reporting). `sets.create`
422
+ * calls this under the hood; use it directly to preview the binding first.
423
+ */
424
+ proposeContract(params: {
425
+ items: Array<Record<string, unknown>>;
426
+ intent: string;
427
+ }): Promise<ProposalResult>;
349
428
  /**
350
429
  * The frontier (vendor) roster you can evaluate against. With `task`, each is
351
430
  * annotated `benchmarked` + the roster is vision-filtered for document tasks.
@@ -564,6 +643,9 @@ interface RequestOptions {
564
643
  files?: Record<string, FilePart>;
565
644
  data?: Record<string, string>;
566
645
  cast?: (raw: unknown) => unknown;
646
+ /** Invoked with the response headers on success (before the body is cast) —
647
+ * lets a caller read receipt headers (#164: X-Pareta-Billed + counterfactual). */
648
+ onHeaders?: (headers: Headers) => void;
567
649
  }
568
650
  interface StreamOptions {
569
651
  body?: unknown;
@@ -630,7 +712,7 @@ declare class Pareta implements Transport {
630
712
  stream<T = unknown>(method: string, path: string, opts?: StreamOptions): AsyncGenerator<T>;
631
713
  }
632
714
 
633
- declare const VERSION = "1.4.0";
715
+ declare const VERSION = "2.1.0";
634
716
 
635
717
  /**
636
718
  * Typed error hierarchy for the Pareta SDK — a faithful port of the Python
@@ -722,4 +804,4 @@ declare class EndpointNotReadyError extends APIStatusError {
722
804
  constructor(message: string, init: APIStatusErrorInit);
723
805
  }
724
806
 
725
- export { APIConnectionError, APIStatusError, APITimeoutError, Audio, type AudioInput, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, Embeddings, type EmbeddingsFn, type EmbeddingsOptions, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, type ImageEditOptions, type ImageGenerateOptions, ImageGeneration, type ImageInput, Images, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, RateLimitError, Rerank, type RerankFn, type RerankOptions, RerankResult, type SSEEvent, Speech, type SpeechOptions, Task, TaskMatch, TaskMatchCandidate, Transcription, type TranscriptionOptions, type Transport, Usage, VERSION, type ValidationErrorItem };
807
+ export { APIConnectionError, APIStatusError, APITimeoutError, Audio, type AudioInput, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, ContractProposal, Embeddings, type EmbeddingsFn, type EmbeddingsOptions, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, type ImageEditOptions, type ImageGenerateOptions, ImageGeneration, type ImageInput, Images, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, ProposalResult, RateLimitError, Rerank, type RerankFn, type RerankOptions, RerankResult, type SSEEvent, Speech, type SpeechOptions, Task, TaskMatch, TaskMatchCandidate, Transcription, type TranscriptionOptions, type Transport, Usage, VERSION, type ValidationErrorItem };
package/dist/index.d.ts CHANGED
@@ -47,6 +47,17 @@ declare class ChatCompletion extends BaseModel {
47
47
  get created(): number | null;
48
48
  get choices(): Choice[];
49
49
  get usage(): Usage;
50
+ /** #164 receipt, held OFF `.raw` so `toDict()` stays the raw server JSON. */
51
+ private _cost?;
52
+ /** #164: attach the per-call receipt from the response headers (billed +
53
+ * the frontier counterfactual, micro-USD ints). Chainable. */
54
+ withCost(headers?: Headers): ChatCompletion;
55
+ /** What Pareta charged, micro-USD (0 on an idempotent replay); null if absent. */
56
+ get billedMicroUsd(): number | null;
57
+ /** What one list-priced frontier call would have cost, micro-USD. */
58
+ get frontierWouldHaveCostMicroUsd(): number | null;
59
+ /** frontier / billed — e.g. 17 = 17× cheaper; null if either is missing or billed is 0. */
60
+ get savingsFactor(): number | null;
50
61
  }
51
62
  /** One SSE delta. `chunk.choices[0].delta.content` is the incremental text. */
52
63
  declare class ChatCompletionChunk extends ChatCompletion {
@@ -87,6 +98,44 @@ declare class EvalSet extends BaseModel {
87
98
  get name(): string | null;
88
99
  get itemCount(): number | null;
89
100
  get scoringStrategy(): string | null;
101
+ /** The one-sentence success criterion this set was created with (CB1:
102
+ * DATA + INTENT). Required at create. */
103
+ get intent(): string | null;
104
+ }
105
+ /**
106
+ * One proposed grading contract for an uploaded dataset (a row of
107
+ * `ProposalResult.proposals`). `warning` is set on the custom-eval floor when
108
+ * the data looks extraction-shaped (judge grading is weaker there).
109
+ */
110
+ declare class ContractProposal extends BaseModel {
111
+ get taskId(): string | null;
112
+ get confidence(): string | null;
113
+ get evidence(): Raw;
114
+ get warning(): string | null;
115
+ }
116
+ /**
117
+ * The binder's answer for `evals.proposeContract` (POST
118
+ * /v1/eval-sets/propose-contract): which grading contract(s) fit your data
119
+ * under your stated intent. Nothing is persisted — confirm by passing the
120
+ * chosen `taskId` (or letting `create` auto-bind a clean single proposal).
121
+ */
122
+ declare class ProposalResult extends BaseModel {
123
+ get proposals(): ContractProposal[];
124
+ get homogeneous(): boolean;
125
+ get split(): Raw | null;
126
+ get conflict(): Raw | null;
127
+ get closestTask(): string | null;
128
+ get intent(): string | null;
129
+ get message(): string | null;
130
+ /** True when the binder matched exactly ONE homogeneous SPECIFIC contract at
131
+ * high/medium confidence and no conflict/split — the case `create` auto-binds
132
+ * without a human confirming. The `custom-eval` universal FLOOR is EXCLUDED:
133
+ * the binder offers it only when no specific contract fits, and per the
134
+ * precision ladder the floor is a CHOICE — the user opts in with
135
+ * `task: "custom-eval"`, never a silent auto-bind. */
136
+ get isClean(): boolean;
137
+ /** The task `create` would auto-bind, or null if the result isn't clean. */
138
+ get boundTask(): string | null;
90
139
  }
91
140
  /**
92
141
  * One scored item inside `EvalResult.perItem`. `prediction` is the model's raw
@@ -281,10 +330,18 @@ declare class Tasks {
281
330
  /**
282
331
  * `client.evals` — eval sets + runs (bring-your-own-data evaluation).
283
332
  *
284
- * const set = await pa.evals.sets.create({ task, items: [...] });
333
+ * // An eval set is DATA + INTENT (v2, breaking): intent REQUIRED, task
334
+ * // OPTIONAL — the binder resolves your intent + the data's shape.
335
+ * await pa.evals.proposeContract({ items: [...], intent: "…" }); // preview
336
+ * const set = await pa.evals.sets.create({ items: [...], intent: "…" }); // auto-binds
285
337
  * await pa.evals.sets.uploadDocument(set.id, file, { idx, fieldName }); // blob tasks
286
338
  * const run = await pa.evals.runs.create({ evalSet: set.id, models: [...], wait: true });
287
- * // or, in one call: runs.create({ task, items, models, wait: true })
339
+ * // or, in one call: runs.create({ items, intent: "…", models, wait: true })
340
+ *
341
+ * `create` (and the inline `runs.create` sugar) require `intent`; with no
342
+ * `task` they call `proposeContract` and auto-bind ONLY a clean single
343
+ * high/medium match — a conflict, split, or ambiguity throws with the
344
+ * proposals so you pin `task`.
288
345
  *
289
346
  * Runs are metered (the org balance is debited for compute); `run.cost` is the
290
347
  * billed total in dollars (floored to cents). `frontier` accepts an explicit
@@ -299,11 +356,22 @@ type FileInput = string | Blob | ArrayBuffer | Uint8Array;
299
356
  declare class EvalSets {
300
357
  private readonly client;
301
358
  constructor(client: Transport);
359
+ /**
360
+ * Persist an eval set from your rows. `intent` is REQUIRED (v2): one sentence
361
+ * on what the model should do with each item. `task` is OPTIONAL — omit it and
362
+ * the binder resolves your intent + the data's shape to a grading contract
363
+ * (auto-binds a clean single match; throws with the proposals otherwise). Pass
364
+ * `task` to pin one explicitly.
365
+ */
302
366
  create(params: {
303
- task: string;
304
367
  items: Array<Record<string, unknown>>;
368
+ intent: string;
369
+ task?: string;
305
370
  name?: string;
306
371
  }): Promise<EvalSet>;
372
+ /** Internal: the binder call `create` uses when no task is pinned. Public on
373
+ * `Evals` as `proposeContract`; kept here so `sets.create` can reach it. */
374
+ proposeContract(items: Array<Record<string, unknown>>, intent: string): Promise<ProposalResult>;
307
375
  list(): Promise<EvalSet[]>;
308
376
  retrieve(evalSetId: string): Promise<EvalSet>;
309
377
  delete(evalSetId: string): Promise<void>;
@@ -322,6 +390,7 @@ interface EvalRunCreateParams {
322
390
  evalSet?: string;
323
391
  task?: string;
324
392
  items?: Array<Record<string, unknown>>;
393
+ intent?: string;
325
394
  models: string[];
326
395
  frontier?: FrontierSpec;
327
396
  name?: string;
@@ -346,6 +415,16 @@ declare class Evals {
346
415
  readonly runs: EvalRuns;
347
416
  constructor(client: Transport);
348
417
  private readonly client;
418
+ /**
419
+ * Which grading contract fits your data under your stated `intent`? Stateless
420
+ * discovery — nothing is persisted. Returns a ProposalResult (ranked
421
+ * proposals, the auto-bind decision, conflict/split reporting). `sets.create`
422
+ * calls this under the hood; use it directly to preview the binding first.
423
+ */
424
+ proposeContract(params: {
425
+ items: Array<Record<string, unknown>>;
426
+ intent: string;
427
+ }): Promise<ProposalResult>;
349
428
  /**
350
429
  * The frontier (vendor) roster you can evaluate against. With `task`, each is
351
430
  * annotated `benchmarked` + the roster is vision-filtered for document tasks.
@@ -564,6 +643,9 @@ interface RequestOptions {
564
643
  files?: Record<string, FilePart>;
565
644
  data?: Record<string, string>;
566
645
  cast?: (raw: unknown) => unknown;
646
+ /** Invoked with the response headers on success (before the body is cast) —
647
+ * lets a caller read receipt headers (#164: X-Pareta-Billed + counterfactual). */
648
+ onHeaders?: (headers: Headers) => void;
567
649
  }
568
650
  interface StreamOptions {
569
651
  body?: unknown;
@@ -630,7 +712,7 @@ declare class Pareta implements Transport {
630
712
  stream<T = unknown>(method: string, path: string, opts?: StreamOptions): AsyncGenerator<T>;
631
713
  }
632
714
 
633
- declare const VERSION = "1.4.0";
715
+ declare const VERSION = "2.1.0";
634
716
 
635
717
  /**
636
718
  * Typed error hierarchy for the Pareta SDK — a faithful port of the Python
@@ -722,4 +804,4 @@ declare class EndpointNotReadyError extends APIStatusError {
722
804
  constructor(message: string, init: APIStatusErrorInit);
723
805
  }
724
806
 
725
- export { APIConnectionError, APIStatusError, APITimeoutError, Audio, type AudioInput, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, Embeddings, type EmbeddingsFn, type EmbeddingsOptions, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, type ImageEditOptions, type ImageGenerateOptions, ImageGeneration, type ImageInput, Images, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, RateLimitError, Rerank, type RerankFn, type RerankOptions, RerankResult, type SSEEvent, Speech, type SpeechOptions, Task, TaskMatch, TaskMatchCandidate, Transcription, type TranscriptionOptions, type Transport, Usage, VERSION, type ValidationErrorItem };
807
+ export { APIConnectionError, APIStatusError, APITimeoutError, Audio, type AudioInput, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, ContractProposal, Embeddings, type EmbeddingsFn, type EmbeddingsOptions, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, type ImageEditOptions, type ImageGenerateOptions, ImageGeneration, type ImageInput, Images, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, ProposalResult, RateLimitError, Rerank, type RerankFn, type RerankOptions, RerankResult, type SSEEvent, Speech, type SpeechOptions, Task, TaskMatch, TaskMatchCandidate, Transcription, type TranscriptionOptions, type Transport, Usage, VERSION, type ValidationErrorItem };
package/dist/index.mjs CHANGED
@@ -172,7 +172,7 @@ function parseSSE(reader, opts) {
172
172
  }
173
173
 
174
174
  // src/version.ts
175
- var VERSION = "1.4.0";
175
+ var VERSION = "2.1.0";
176
176
 
177
177
  // src/money.ts
178
178
  var MICRO_PER_CENT = 10000n;
@@ -253,6 +253,36 @@ var ChatCompletion = class extends BaseModel {
253
253
  get usage() {
254
254
  return new Usage(this.raw.usage ?? {});
255
255
  }
256
+ /** #164 receipt, held OFF `.raw` so `toDict()` stays the raw server JSON. */
257
+ _cost;
258
+ /** #164: attach the per-call receipt from the response headers (billed +
259
+ * the frontier counterfactual, micro-USD ints). Chainable. */
260
+ withCost(headers) {
261
+ const int = (name) => {
262
+ const v = headers?.get(name);
263
+ if (v == null) return null;
264
+ const n = parseInt(v, 10);
265
+ return Number.isNaN(n) ? null : n;
266
+ };
267
+ this._cost = {
268
+ billed: int("X-Pareta-Billed"),
269
+ frontier: int("X-Pareta-Frontier-Would-Have-Cost")
270
+ };
271
+ return this;
272
+ }
273
+ /** What Pareta charged, micro-USD (0 on an idempotent replay); null if absent. */
274
+ get billedMicroUsd() {
275
+ return this._cost?.billed ?? null;
276
+ }
277
+ /** What one list-priced frontier call would have cost, micro-USD. */
278
+ get frontierWouldHaveCostMicroUsd() {
279
+ return this._cost?.frontier ?? null;
280
+ }
281
+ /** frontier / billed — e.g. 17 = 17× cheaper; null if either is missing or billed is 0. */
282
+ get savingsFactor() {
283
+ const b = this.billedMicroUsd, f = this.frontierWouldHaveCostMicroUsd;
284
+ return b && f && b > 0 ? Math.round(f / b * 10) / 10 : null;
285
+ }
256
286
  };
257
287
  var ChatCompletionChunk = class extends ChatCompletion {
258
288
  };
@@ -339,6 +369,11 @@ var EvalSet = class extends BaseModel {
339
369
  get scoringStrategy() {
340
370
  return this.raw.scoring_strategy ?? null;
341
371
  }
372
+ /** The one-sentence success criterion this set was created with (CB1:
373
+ * DATA + INTENT). Required at create. */
374
+ get intent() {
375
+ return this.raw.intent ?? null;
376
+ }
342
377
  };
343
378
  function evalSetFromCreate(raw) {
344
379
  return new EvalSet(raw?.eval_set ?? {});
@@ -346,6 +381,60 @@ function evalSetFromCreate(raw) {
346
381
  function evalSetList(raw) {
347
382
  return (raw?.eval_sets ?? []).map((e) => new EvalSet(e));
348
383
  }
384
+ var ContractProposal = class extends BaseModel {
385
+ get taskId() {
386
+ return this.raw.task_id ?? null;
387
+ }
388
+ get confidence() {
389
+ return this.raw.confidence ?? null;
390
+ }
391
+ get evidence() {
392
+ return this.raw.evidence ?? {};
393
+ }
394
+ get warning() {
395
+ return this.raw.warning ?? null;
396
+ }
397
+ };
398
+ var ProposalResult = class extends BaseModel {
399
+ get proposals() {
400
+ return (this.raw.proposals ?? []).map((p) => new ContractProposal(p));
401
+ }
402
+ get homogeneous() {
403
+ return Boolean(this.raw.homogeneous);
404
+ }
405
+ get split() {
406
+ return this.raw.split ?? null;
407
+ }
408
+ get conflict() {
409
+ return this.raw.conflict ?? null;
410
+ }
411
+ get closestTask() {
412
+ return this.raw.closest_task ?? null;
413
+ }
414
+ get intent() {
415
+ return this.raw.intent ?? null;
416
+ }
417
+ get message() {
418
+ return this.raw.message ?? null;
419
+ }
420
+ /** True when the binder matched exactly ONE homogeneous SPECIFIC contract at
421
+ * high/medium confidence and no conflict/split — the case `create` auto-binds
422
+ * without a human confirming. The `custom-eval` universal FLOOR is EXCLUDED:
423
+ * the binder offers it only when no specific contract fits, and per the
424
+ * precision ladder the floor is a CHOICE — the user opts in with
425
+ * `task: "custom-eval"`, never a silent auto-bind. */
426
+ get isClean() {
427
+ const props = this.proposals;
428
+ return this.homogeneous && this.conflict == null && this.split == null && props.length === 1 && (props[0].confidence === "high" || props[0].confidence === "medium") && Boolean(props[0].taskId) && props[0].taskId !== "custom-eval";
429
+ }
430
+ /** The task `create` would auto-bind, or null if the result isn't clean. */
431
+ get boundTask() {
432
+ return this.isClean ? this.proposals[0].taskId : null;
433
+ }
434
+ };
435
+ function proposalResult(raw) {
436
+ return new ProposalResult(raw ?? {});
437
+ }
349
438
  var EvalItemResult = class extends BaseModel {
350
439
  get idx() {
351
440
  return this.raw.idx ?? null;
@@ -583,10 +672,14 @@ var Completions = class {
583
672
  cast: (raw) => new ChatCompletionChunk(raw)
584
673
  });
585
674
  }
675
+ let headers;
586
676
  return this.client.request("POST", PATH, {
587
677
  body,
588
- cast: (raw) => new ChatCompletion(raw)
589
- });
678
+ cast: (raw) => new ChatCompletion(raw),
679
+ onHeaders: (h) => {
680
+ headers = h;
681
+ }
682
+ }).then((completion) => completion.withCost(headers));
590
683
  }
591
684
  };
592
685
  var Chat = class {
@@ -639,6 +732,7 @@ var Tasks = class {
639
732
 
640
733
  // src/resources/evals.ts
641
734
  var BASE2 = "/v1/eval-sets";
735
+ var PROPOSE = "/v1/eval-sets/propose-contract";
642
736
  var RUNS = "/v1/eval-runs";
643
737
  var FRONTIER = "/v1/eval/frontier-models";
644
738
  var INLINE_MAX = 5 * 1024 * 1024;
@@ -682,14 +776,59 @@ async function toBlob(file, mimeOverride) {
682
776
  const mime = mimeOverride || "application/octet-stream";
683
777
  return { blob: new Blob([bytes], { type: mime }), filename: "upload", size: bytes.byteLength, mime };
684
778
  }
685
- function itemsJsonl(task, items, name) {
779
+ function requireIntent(intent) {
780
+ const s = (intent ?? "").trim();
781
+ if (!s) {
782
+ throw new ParetaError(
783
+ 'intent is required: one sentence describing what the model should do with each item (e.g. "extract vendor, total and date from each invoice"). Pass intent to evals.create / proposeContract.'
784
+ );
785
+ }
786
+ return s.slice(0, 500);
787
+ }
788
+ function itemsJsonl(task, items, intent, name) {
686
789
  if (!items || items.length === 0) throw new ParetaError("items is required and must be non-empty");
687
790
  const jsonl = items.map((it) => JSON.stringify(it)).join("\n");
688
791
  return {
689
792
  files: { items: { filename: `items.${task}.jsonl`, content: jsonl, contentType: "application/jsonl" } },
690
- data: { task_id: task, name: name || `sdk eval set (${items.length} items)` }
793
+ data: { task_id: task, intent, name: name || `sdk eval set (${items.length} items)` }
794
+ };
795
+ }
796
+ function proposeMultipart(items, intent) {
797
+ if (!items || items.length === 0) throw new ParetaError("items is required and must be non-empty");
798
+ const jsonl = items.map((it) => JSON.stringify(it)).join("\n");
799
+ return {
800
+ files: { items: { filename: "items.jsonl", content: jsonl, contentType: "application/jsonl" } },
801
+ data: { intent }
691
802
  };
692
803
  }
804
+ function bindError(result) {
805
+ const intent = result.intent ?? "";
806
+ if (result.conflict) {
807
+ const c = result.conflict;
808
+ return new ParetaError(
809
+ `intent '${intent}' describes a different job than the data's shape supports (reads as '${c.intended_task}': ${c.reasoning}). Pass a task to pin a contract, or revise the intent.`
810
+ );
811
+ }
812
+ if (result.split) {
813
+ const s = result.split;
814
+ return new ParetaError(
815
+ `the dataset looks MIXED \u2014 ${s.validated_n}/${s.total_n} items fit '${s.closest_task}', the rest a different shape. Split the set or pass a task.`
816
+ );
817
+ }
818
+ const props = result.proposals;
819
+ if (props.length === 1 && props[0].taskId === "custom-eval") {
820
+ const warn = props[0].warning ? ` (${props[0].warning})` : "";
821
+ return new ParetaError(
822
+ `no specific grading contract fits this data for intent '${intent}'. The custom-eval universal floor is available \u2014 it grades by judged win-rate vs the frontier anchor.${warn} Pass task: "custom-eval" to use it, or revise the data/intent for a specific contract.`
823
+ );
824
+ }
825
+ const options = props.map((p) => p.taskId).filter(Boolean);
826
+ if (options.length === 0 && result.closestTask) options.push(result.closestTask);
827
+ const hint = options.length ? ` Candidates: ${options.join(", ")}.` : "";
828
+ return new ParetaError(
829
+ `could not confidently bind a grading contract for intent '${intent}'.${hint} Pass a task to pin one, or inspect evals.proposeContract({ items, intent }).`
830
+ );
831
+ }
693
832
  function mergeCandidates(models, frontierIds) {
694
833
  const cands = [...models ?? [], ...frontierIds ?? []];
695
834
  if (cands.length === 0) throw new ParetaError("models is required (the open candidates to evaluate)");
@@ -710,10 +849,30 @@ var EvalSets = class {
710
849
  this.client = client;
711
850
  }
712
851
  client;
713
- create(params) {
714
- const { files, data } = itemsJsonl(params.task, params.items, params.name);
852
+ /**
853
+ * Persist an eval set from your rows. `intent` is REQUIRED (v2): one sentence
854
+ * on what the model should do with each item. `task` is OPTIONAL — omit it and
855
+ * the binder resolves your intent + the data's shape to a grading contract
856
+ * (auto-binds a clean single match; throws with the proposals otherwise). Pass
857
+ * `task` to pin one explicitly.
858
+ */
859
+ async create(params) {
860
+ const intent = requireIntent(params.intent);
861
+ let task = params.task;
862
+ if (task == null) {
863
+ const proposal = await this.proposeContract(params.items, intent);
864
+ task = proposal.boundTask ?? void 0;
865
+ if (task == null) throw bindError(proposal);
866
+ }
867
+ const { files, data } = itemsJsonl(task, params.items, intent, params.name);
715
868
  return this.client.request("POST", BASE2, { files, data, cast: evalSetFromCreate });
716
869
  }
870
+ /** Internal: the binder call `create` uses when no task is pinned. Public on
871
+ * `Evals` as `proposeContract`; kept here so `sets.create` can reach it. */
872
+ proposeContract(items, intent) {
873
+ const { files, data } = proposeMultipart(items, requireIntent(intent));
874
+ return this.client.request("POST", PROPOSE, { files, data, cast: proposalResult });
875
+ }
717
876
  list() {
718
877
  return this.client.request("GET", BASE2, { cast: evalSetList });
719
878
  }
@@ -781,10 +940,15 @@ var EvalRuns = class {
781
940
  async create(params) {
782
941
  let evalSet = params.evalSet;
783
942
  if (evalSet == null) {
784
- if (!(params.task && params.items)) {
785
- throw new ParetaError("pass evalSet: <id>, or task + items to create one");
943
+ if (!params.items) {
944
+ throw new ParetaError("pass evalSet: <id>, or items (+ intent) to create one");
786
945
  }
787
- evalSet = (await this.sets.create({ task: params.task, items: params.items, name: params.name })).id ?? void 0;
946
+ evalSet = (await this.sets.create({
947
+ items: params.items,
948
+ intent: params.intent,
949
+ task: params.task,
950
+ name: params.name
951
+ })).id ?? void 0;
788
952
  }
789
953
  const frontierIds = await this.frontierIds(params.frontier, evalSet, params.task);
790
954
  const candidateModelIds = mergeCandidates(params.models, frontierIds);
@@ -824,6 +988,15 @@ var Evals = class {
824
988
  this.client = client;
825
989
  }
826
990
  client;
991
+ /**
992
+ * Which grading contract fits your data under your stated `intent`? Stateless
993
+ * discovery — nothing is persisted. Returns a ProposalResult (ranked
994
+ * proposals, the auto-bind decision, conflict/split reporting). `sets.create`
995
+ * calls this under the hood; use it directly to preview the binding first.
996
+ */
997
+ proposeContract(params) {
998
+ return this.sets.proposeContract(params.items, params.intent);
999
+ }
827
1000
  /**
828
1001
  * The frontier (vendor) roster you can evaluate against. With `task`, each is
829
1002
  * annotated `benchmarked` + the roster is vision-filtered for document tasks.
@@ -1169,6 +1342,7 @@ var Pareta = class _Pareta {
1169
1342
  break;
1170
1343
  }
1171
1344
  if (res.ok) {
1345
+ if (opts.onHeaders) opts.onHeaders(res.headers);
1172
1346
  const text = await res.text();
1173
1347
  const raw = text ? JSON.parse(text) : {};
1174
1348
  return cast ? cast(raw) : raw;
@@ -1235,6 +1409,6 @@ var Pareta = class _Pareta {
1235
1409
  }
1236
1410
  };
1237
1411
 
1238
- export { APIConnectionError, APIStatusError, APITimeoutError, Audio, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, Choice, ConflictError, Embeddings, EndpointNotReadyError, EvalItemResult, EvalResult, EvalRun, EvalRuns, EvalSet, EvalSets, FrontierModel, ImageGeneration, Images, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, PermissionDeniedError, RateLimitError, Rerank, RerankResult, Speech, Task, TaskMatch, TaskMatchCandidate, Transcription, Usage, VERSION };
1412
+ export { APIConnectionError, APIStatusError, APITimeoutError, Audio, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, Choice, ConflictError, ContractProposal, Embeddings, EndpointNotReadyError, EvalItemResult, EvalResult, EvalRun, EvalRuns, EvalSet, EvalSets, FrontierModel, ImageGeneration, Images, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, PermissionDeniedError, ProposalResult, RateLimitError, Rerank, RerankResult, Speech, Task, TaskMatch, TaskMatchCandidate, Transcription, Usage, VERSION };
1239
1413
  //# sourceMappingURL=index.mjs.map
1240
1414
  //# sourceMappingURL=index.mjs.map