@kimpton-ai/evalrouter 0.1.0 → 0.3.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/README.md CHANGED
@@ -1,16 +1,17 @@
1
1
  # EvalRouter TypeScript client
2
2
 
3
3
  Client for trusted Node.js 22+ applications, using ESM, distributed under the
4
- proprietary [Kimpton EvalRouter SDK License](LICENSE). Install with
5
- `npm install @kimpton-ai/evalrouter@0.1.0`. Discover evaluations and models,
6
- submit bounded evaluation runs, inspect results, and export reports.
4
+ proprietary [Kimpton EvalRouter SDK License](LICENSE). Install the package with
5
+ your Node.js package manager or use a reviewed package archive supplied by your
6
+ operator. Discover evaluations and models, submit bounded evaluation runs,
7
+ inspect results, and export reports.
7
8
 
8
9
  Use API keys only in a trusted server process, never a browser bundle. Set
9
10
  `EVALROUTER_BASE_URL`, `EVALROUTER_API_KEY` and `EVALROUTER_WORKSPACE_ID` after
10
11
  creating and funding an account in the web application. The public API origin is
11
12
  `https://api.evalrouter.ai`. Package download does not grant service access.
12
- While website access is restricted, obtain an invitation from your EvalRouter
13
- operator before setting up the account and workspace key.
13
+ Use an invitation if required by your EvalRouter operator when setting up the
14
+ account and workspace key.
14
15
 
15
16
  ```typescript
16
17
  import { Client } from "@kimpton-ai/evalrouter";
@@ -36,7 +37,8 @@ the same idempotency key. Local timeouts do not establish that a submitted run
36
37
  failed to commit.
37
38
 
38
39
  The supported resources are `catalog`, `evals`, `connections`, `quotes`,
39
- `evaluations` and `runs`. `catalog.evals` and `catalog.eval` are discovery aliases.
40
+ `evaluations`, `runs` and `agent_builds`; `agents` provides only `register`. `catalog.evals` and
41
+ `catalog.eval` are discovery aliases.
40
42
  The package includes named request/response types, `Client` (`EvalRouter` alias),
41
43
  `APIError`, `ClientError`, `RequestTimeout`, `WaitCancelled`, and typed
42
44
  request/wait options. `runs.wait` supports local abort/deadlines; `runs.cancel`
@@ -46,3 +48,87 @@ also be passed in `ClientOptions`.
46
48
 
47
49
  The HTTP service enforces account access and workspace permissions. Configure
48
50
  the client with an existing workspace API key.
51
+
52
+ ## Repository agents
53
+
54
+ Repository methods require version 0.2.0 or later and service enablement for the
55
+ workspace. Package installation does not enable qualification. Stop when options
56
+ report it disabled or do not include the exact requested target and model.
57
+
58
+ Use self-service repository qualification jobs to prepare managed agents.
59
+ Check `client.agent_builds.options()` for available targets and models. The
60
+ flow supports GitHub repositories with the supported locked Node/npm runtime and
61
+ an `evalrouter-agent.json` manifest. Python agent runtimes and custom Docker
62
+ images are not supported by this flow. Public repositories need no GitHub grant.
63
+ For a private repository, first connect GitHub in the web application and
64
+ explicitly select that repository for the current workspace. Include
65
+ `source: {github_connection_id, github_repository_id}` in the same preview JSON,
66
+ using both IDs returned by that connection. The repository URL still identifies
67
+ the selected repository. These IDs select an existing grant; they are not
68
+ credentials. The SDK and CLI do not authorize installations, accept GitHub
69
+ tokens, or bypass revoked access. Repository access remains subject to the
70
+ current workspace grant.
71
+
72
+ Preview resolves an immutable commit and returns the qualification scope, cost
73
+ components, spending cap and expiry. It creates no job, reserves no credit and
74
+ starts no sandbox or model work. Review it before explicitly creating a job;
75
+ creation reserves the quoted cap and may incur the stated costs.
76
+
77
+ ```typescript
78
+ const options = await client.agent_builds.options();
79
+ const preview = await client.agent_builds.preview({
80
+ repository_url: "YOUR_PUBLIC_GITHUB_REPOSITORY_URL",
81
+ ref: "main",
82
+ manifest_path: "evalrouter-agent.json",
83
+ qualification: {
84
+ environment_ref: "EXACT_ENVIRONMENT_FROM_OPTIONS",
85
+ model: { kind: "managed", route_id: "MODEL_FROM_OPTIONS" },
86
+ },
87
+ max_cost_microusd: "1000000",
88
+ });
89
+ console.log(preview); // Review first; this example stops before submitting work.
90
+ ```
91
+
92
+ After review, call
93
+ `client.agent_builds.create({quote_id: preview.id}, durableIdempotencyKey)`.
94
+ Persist the quote ID and key first. If the response is lost, retry that exact
95
+ request and key, or recover with `agent_builds.list({quote_id: preview.id})`.
96
+ A new key is a new submission. Read progress with `agent_builds.get(jobId)` and
97
+ request cancellation with `agent_builds.cancel(jobId)`. Cancellation can remain
98
+ `cancelling` while cleanup finishes; `reconciling` is unresolved, and neither
99
+ state is Ready. Reads do not silently retry failed jobs.
100
+
101
+ An HTTP 429 with code `agent_build_quota` is returned immediately as `APIError`,
102
+ preserving its status and code. Review the quota before another submission;
103
+ transport backoff cannot resolve that refusal. Other transient rate limits retain
104
+ bounded transport retries with the same idempotency key.
105
+
106
+ Ready returns `agent.ref` after qualification and cleanup. It establishes only
107
+ the returned supported scope, not benchmark quality or broad task compatibility.
108
+ Build/qualification costs and later evaluation costs have separate caps. To
109
+ preview an evaluation, use the Ready record's exact scope:
110
+
111
+ ```typescript
112
+ if (ready.status === "ready" && ready.agent) {
113
+ const scope = ready.qualification;
114
+ const quote = await client.quotes.create({
115
+ agent: ready.agent.ref,
116
+ selection: { environment: scope.environment_ref, split: scope.split },
117
+ coverage: scope.evaluation_coverage,
118
+ max_charge_microusd: "1000000",
119
+ });
120
+ console.log(quote); // Review before separately calling runs.create.
121
+ }
122
+ ```
123
+
124
+ Do not substitute a task ID, guess a seed or expand the returned coverage. Money
125
+ values are decimal strings in micro-USD. API errors retain status and code; an
126
+ error or local timeout does not establish that a create request failed to commit.
127
+ Use plain JSON data for job inputs; serialization hooks and private fields are
128
+ rejected before HTTP.
129
+
130
+ The advanced `agents.register` method remains available for an existing
131
+ workspace-scoped admission supplied separately: only `ref`, `kind: "managed_acp"`
132
+ and `admission_id` are accepted. Self-service repository jobs do not require the
133
+ customer to obtain an admission ID. The existing model `Client.run` helper and
134
+ `NewQuote` contract remain unchanged; managed evaluation quotes use `NewAgentQuote`.
@@ -1,2 +1,2 @@
1
1
  /** Validate supported evaluation inputs before issuing a request. */
2
- export declare function validateSubmission(resource: "quotes" | "evaluations", input: unknown): void;
2
+ export declare function validateSubmission(resource: "quotes" | "evaluations" | "agents" | "agent_builds", input: unknown): unknown;
package/dist/boundary.js CHANGED
@@ -2,8 +2,111 @@ import { ClientError } from "./transport.js";
2
2
  /** Validate supported evaluation inputs before issuing a request. */
3
3
  export function validateSubmission(resource, input) {
4
4
  const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
5
+ // Snapshot data properties before validation. JSON.stringify must never run
6
+ // customer accessors or serialization hooks after the boundary has passed.
7
+ const snapshot = (value, seen = new Set()) => {
8
+ const invalid = () => {
9
+ throw new ClientError("unsupported_feature", "Use plain JSON data for registration, repository jobs and quotes.");
10
+ };
11
+ if (value === null || value === undefined || typeof value === "string" || typeof value === "boolean")
12
+ return value;
13
+ if (typeof value === "number")
14
+ return Number.isFinite(value) ? value : invalid();
15
+ if (typeof value !== "object")
16
+ return invalid();
17
+ const array = Array.isArray(value);
18
+ const prototype = Object.getPrototypeOf(value);
19
+ if ((prototype !== null && prototype !== (array ? Array.prototype : Object.prototype)) ||
20
+ "toJSON" in value || seen.has(value))
21
+ return invalid();
22
+ seen.add(value);
23
+ const result = array ? Object.setPrototypeOf([], null) : Object.create(null);
24
+ for (const key of Reflect.ownKeys(value)) {
25
+ if (array && key === "length")
26
+ continue;
27
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
28
+ if (typeof key !== "string" || !descriptor || !descriptor.enumerable || !("value" in descriptor) ||
29
+ (array && !/^(0|[1-9][0-9]*)$/.test(key)))
30
+ return invalid();
31
+ result[key] = snapshot(descriptor.value, seen);
32
+ }
33
+ seen.delete(value);
34
+ return result;
35
+ };
36
+ if (resource === "agents" || resource === "quotes" || resource === "agent_builds") {
37
+ try {
38
+ input = snapshot(input);
39
+ }
40
+ catch {
41
+ throw new ClientError("unsupported_feature", "Use plain JSON data for registration, repository jobs and quotes.");
42
+ }
43
+ }
44
+ if (resource === "agent_builds") {
45
+ const invalid = () => { throw new ClientError("unsupported_feature", "Use the supported repository job input."); };
46
+ if (!object(input))
47
+ return invalid();
48
+ if (Object.keys(input).length === 1 && "quote_id" in input) {
49
+ if (typeof input.quote_id !== "string" || !input.quote_id)
50
+ return invalid();
51
+ return input;
52
+ }
53
+ if (Object.keys(input).some(key => !["repository_url", "ref", "manifest_path", "max_cost_microusd", "qualification", "source"].includes(key)))
54
+ return invalid();
55
+ const repository = input.repository_url;
56
+ const cost = input.max_cost_microusd;
57
+ const ref = input.ref;
58
+ const manifest = input.manifest_path === undefined ? "evalrouter-agent.json" : input.manifest_path;
59
+ const qualification = input.qualification;
60
+ const source = input.source;
61
+ if (source != null && (!object(source) || Object.keys(source).length !== 2 ||
62
+ Object.keys(source).some(key => !["github_connection_id", "github_repository_id"].includes(key)) ||
63
+ typeof source.github_connection_id !== "string" || !/^[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$/.test(source.github_connection_id) ||
64
+ typeof source.github_repository_id !== "number" || !Number.isSafeInteger(source.github_repository_id) || source.github_repository_id < 1))
65
+ return invalid();
66
+ if (typeof repository !== "string" || repository.length > 300 ||
67
+ !/^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository) ||
68
+ typeof cost !== "string" || !/^[0-9]{1,9}$/.test(cost) ||
69
+ (ref != null && (typeof ref !== "string" || !/^[!-~]{1,200}$/.test(ref))) ||
70
+ typeof manifest !== "string" || manifest.length < 1 || manifest.length > 240 ||
71
+ !/^[A-Za-z0-9_./-]+$/.test(manifest) || manifest.split("/").some(part => ["", ".", ".."].includes(part)) ||
72
+ !object(qualification) || Object.keys(qualification).length !== 2 ||
73
+ Object.keys(qualification).some(key => !["environment_ref", "model"].includes(key)))
74
+ return invalid();
75
+ const environment = qualification.environment_ref;
76
+ const model = qualification.model;
77
+ if (typeof environment !== "string" || environment.length < 1 || environment.length > 300 ||
78
+ !object(model) || Object.keys(model).some(key => !["kind", "route_id"].includes(key)) ||
79
+ (model.kind !== undefined && model.kind !== "managed") ||
80
+ typeof model.route_id !== "string" || model.route_id.length < 1 || model.route_id.length > 200)
81
+ return invalid();
82
+ return input;
83
+ }
84
+ if (resource === "agents") {
85
+ if (!object(input) || input.kind !== "managed_acp" ||
86
+ Object.keys(input).length !== 3 ||
87
+ Object.keys(input).some(key => !["ref", "kind", "admission_id"].includes(key)) ||
88
+ !["ref", "admission_id"].every(key => typeof input[key] === "string" && input[key])) {
89
+ throw new ClientError("unsupported_feature", "Registration requires ref, managed_acp kind and admission_id.");
90
+ }
91
+ return input;
92
+ }
93
+ if (resource === "quotes" && object(input) && "concurrency" in input) {
94
+ const value = input.concurrency;
95
+ if (!(value === "auto" || value === "max" ||
96
+ typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 100)) {
97
+ throw new ClientError("invalid_input", "Concurrency must be auto, max, or an integer from 1 to 100.");
98
+ }
99
+ }
100
+ if (resource === "quotes" && object(input) && "agent" in input) {
101
+ if (Object.keys(input).some(key => !["agent", "selection", "coverage", "max_charge_microusd", "concurrency"].includes(key)) ||
102
+ typeof input.agent !== "string" || !input.agent || !object(input.selection) ||
103
+ !("environment" in input.selection) || Object.keys(input.selection).some(key => !["environment", "split"].includes(key))) {
104
+ throw new ClientError("unsupported_feature", "Choose a registered agent and an exact environment reference.");
105
+ }
106
+ return input;
107
+ }
5
108
  const allowed = new Set(resource === "quotes"
6
- ? ["selection", "model", "coverage", "max_charge_microusd"]
109
+ ? ["selection", "model", "coverage", "max_charge_microusd", "concurrency"]
7
110
  : ["model", "eval", "budget_usd", "max_charge_microusd", "provider", "coverage", "name", "metadata", "split"]);
8
111
  const fail = () => { throw new ClientError("unsupported_feature", "Choose an admitted eval and a managed model or checked connection."); };
9
112
  if (!object(input) || Object.keys(input).some((key) => !allowed.has(key)))
@@ -29,4 +132,5 @@ export function validateSubmission(resource, input) {
29
132
  !("eval" in selection && keys.every((key) => ["eval", "provider", "split"].includes(key))))
30
133
  return fail();
31
134
  }
135
+ return input;
32
136
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Catalog, Evals, Evaluations, Connections, Quotes, Runs } from "./resources.js";
1
+ import { AgentBuilds, Agents, Catalog, Connections, Creators, Evals, Evaluations, Protocols, Quotes, Runs } from "./resources.js";
2
2
  import type { RunRecord } from "./types.js";
3
3
  import { Transport } from "./transport.js";
4
4
  export { APIError, ClientError, RequestTimeout, WaitCancelled, } from "./transport.js";
@@ -6,8 +6,12 @@ export type { ClientOptions, RequestOptions } from "./transport.js";
6
6
  export type { WaitOptions } from "./helpers.js";
7
7
  export type * from "./types.js";
8
8
  export declare class Client extends Transport {
9
+ readonly agent_builds: AgentBuilds;
10
+ readonly agents: Agents;
9
11
  readonly catalog: Catalog;
10
12
  readonly connections: Connections;
13
+ readonly creators: Creators;
14
+ readonly protocols: Protocols;
11
15
  readonly quotes: Quotes;
12
16
  readonly runs: Runs;
13
17
  readonly evals: Evals;
package/dist/index.js CHANGED
@@ -1,10 +1,14 @@
1
- import { Catalog, Evals, Evaluations, Connections, Quotes, Runs } from "./resources.js";
1
+ import { AgentBuilds, Agents, Catalog, Connections, Creators, Evals, Evaluations, Protocols, Quotes, Runs, } from "./resources.js";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { Transport } from "./transport.js";
4
4
  export { APIError, ClientError, RequestTimeout, WaitCancelled, } from "./transport.js";
5
5
  export class Client extends Transport {
6
+ agent_builds = new AgentBuilds(this);
7
+ agents = new Agents(this);
6
8
  catalog = new Catalog(this);
7
9
  connections = new Connections(this);
10
+ creators = new Creators(this);
11
+ protocols = new Protocols(this);
8
12
  quotes = new Quotes(this);
9
13
  runs = new Runs(this);
10
14
  evals = new Evals(this);
@@ -19,7 +19,7 @@ export declare class Connections extends Resource {
19
19
  disable(connection_id: string, options?: RequestOptions): Promise<types.OKResponse>;
20
20
  }
21
21
  export declare class Quotes extends Resource {
22
- create(body: types.NewQuote, options?: RequestOptions): Promise<types.QuoteRecord>;
22
+ create(body: types.QuotesCreateBody, options?: RequestOptions): Promise<types.QuoteRecord>;
23
23
  get(quote_id: string, options?: RequestOptions): Promise<types.QuoteRecord>;
24
24
  }
25
25
  export declare class Runs extends RunHelpers {
@@ -41,3 +41,28 @@ export declare class Evaluations extends Resource {
41
41
  create(body: types.NewEvaluation, idempotency_key: string, options?: RequestOptions): Promise<types.RunRecord>;
42
42
  get(evaluation_id: string, options?: RequestOptions): Promise<types.RunRecord>;
43
43
  }
44
+ export declare class Agents extends Resource {
45
+ register(body: types.NewManagedACPAgent, options?: RequestOptions): Promise<types.AgentRecord>;
46
+ }
47
+ export declare class AgentBuilds extends Resource {
48
+ options(options?: RequestOptions): Promise<types.AgentBuildOptions>;
49
+ preview(body: types.AgentBuildPreview, options?: RequestOptions): Promise<types.AgentBuildQuoteRecord>;
50
+ create(body: types.CreateAgentBuild, idempotency_key: string, options?: RequestOptions): Promise<types.AgentBuildRecord>;
51
+ list(params?: types.AgentBuildsListParams, options?: RequestOptions): Promise<types.Page_AgentBuildRecord_>;
52
+ get(job_id: string, options?: RequestOptions): Promise<types.AgentBuildRecord>;
53
+ cancel(job_id: string, options?: RequestOptions): Promise<types.AgentBuildRecord>;
54
+ }
55
+ export declare class Creators extends Resource {
56
+ namespaces(params?: types.CreatorsNamespacesParams, options?: RequestOptions): Promise<types.NamespacePage>;
57
+ create_upload(body: types.NewUpload, idempotency_key: string, options?: RequestOptions): Promise<types.UploadResult>;
58
+ put_part(upload_id: string, part_index: string, body: types.NewPart, options?: RequestOptions): Promise<types.PartResult>;
59
+ submit(upload_id: string, options?: RequestOptions): Promise<types.ValidationResult>;
60
+ validation(job_id: string, options?: RequestOptions): Promise<types.ValidationResult>;
61
+ package(package_id: string, options?: RequestOptions): Promise<types.PackageResult>;
62
+ protocol(package_id: string, options?: RequestOptions): Promise<types.PackageProtocolResult>;
63
+ }
64
+ export declare class Protocols extends Resource {
65
+ grant(protocol_id: string, body: types.GrantRequest, options?: RequestOptions): Promise<types.ProtocolGrant>;
66
+ revoke(grant_id: string, body: types.RevokeRequest, options?: RequestOptions): Promise<types.ProtocolGrant>;
67
+ grants(options?: RequestOptions): Promise<types.Page_ProtocolGrant_>;
68
+ }
package/dist/resources.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Resource, segment } from "./transport.js";
1
+ import { Resource, segment, familyPath } from "./transport.js";
2
2
  import { RunHelpers } from "./helpers.js";
3
3
  import { validateSubmission } from "./boundary.js";
4
4
  export class Catalog extends Resource {
@@ -24,7 +24,7 @@ export class Catalog extends Resource {
24
24
  return this.client.request("GET", `/catalog/environments`, { retry: true, options, query: params });
25
25
  }
26
26
  async environment(family, options) {
27
- return this.client.request("GET", `/catalog/environments/${segment(family)}`, { retry: true, options });
27
+ return this.client.request("GET", `/catalog/environments/${familyPath(family)}`, { retry: true, options });
28
28
  }
29
29
  }
30
30
  export class Connections extends Resource {
@@ -46,7 +46,7 @@ export class Connections extends Resource {
46
46
  }
47
47
  export class Quotes extends Resource {
48
48
  async create(body, options) {
49
- validateSubmission("quotes", body);
49
+ body = validateSubmission("quotes", body);
50
50
  return this.client.request("POST", `/quotes`, { retry: false, options, body: body });
51
51
  }
52
52
  async get(quote_id, options) {
@@ -92,10 +92,72 @@ export class Evals extends Resource {
92
92
  }
93
93
  export class Evaluations extends Resource {
94
94
  async create(body, idempotency_key, options) {
95
- validateSubmission("evaluations", body);
95
+ body = validateSubmission("evaluations", body);
96
96
  return this.client.request("POST", `/evaluations`, { retry: true, options, body: body, idempotency_key: idempotency_key });
97
97
  }
98
98
  async get(evaluation_id, options) {
99
99
  return this.client.request("GET", `/evaluations/${segment(evaluation_id)}`, { retry: true, options });
100
100
  }
101
101
  }
102
+ export class Agents extends Resource {
103
+ async register(body, options) {
104
+ body = validateSubmission("agents", body);
105
+ return this.client.request("POST", `/agents`, { retry: false, options, body: body });
106
+ }
107
+ }
108
+ export class AgentBuilds extends Resource {
109
+ async options(options) {
110
+ return this.client.request("GET", `/agent-builds/options`, { retry: true, options });
111
+ }
112
+ async preview(body, options) {
113
+ body = validateSubmission("agent_builds", body);
114
+ return this.client.request("POST", `/agent-builds/preview`, { retry: false, options, body: body });
115
+ }
116
+ async create(body, idempotency_key, options) {
117
+ body = validateSubmission("agent_builds", body);
118
+ return this.client.request("POST", `/agent-builds`, { retry: true, options, body: body, idempotency_key: idempotency_key });
119
+ }
120
+ async list(params = {}, options) {
121
+ return this.client.request("GET", `/agent-builds`, { retry: true, options, query: params });
122
+ }
123
+ async get(job_id, options) {
124
+ return this.client.request("GET", `/agent-builds/${segment(job_id)}`, { retry: true, options });
125
+ }
126
+ async cancel(job_id, options) {
127
+ return this.client.request("POST", `/agent-builds/${segment(job_id)}/cancel`, { retry: true, options });
128
+ }
129
+ }
130
+ export class Creators extends Resource {
131
+ async namespaces(params = {}, options) {
132
+ return this.client.request("GET", `/creator/namespaces`, { retry: true, options, query: params });
133
+ }
134
+ async create_upload(body, idempotency_key, options) {
135
+ return this.client.request("POST", `/creator/uploads`, { retry: true, options, body: body, idempotency_key: idempotency_key });
136
+ }
137
+ async put_part(upload_id, part_index, body, options) {
138
+ return this.client.request("PUT", `/creator/uploads/${segment(upload_id)}/parts/${segment(part_index)}`, { retry: true, options, body: body });
139
+ }
140
+ async submit(upload_id, options) {
141
+ return this.client.request("POST", `/creator/uploads/${segment(upload_id)}/submit`, { retry: true, options });
142
+ }
143
+ async validation(job_id, options) {
144
+ return this.client.request("GET", `/creator/validation-jobs/${segment(job_id)}`, { retry: true, options });
145
+ }
146
+ async package(package_id, options) {
147
+ return this.client.request("GET", `/creator/packages/${segment(package_id)}`, { retry: true, options });
148
+ }
149
+ async protocol(package_id, options) {
150
+ return this.client.request("GET", `/creator/packages/${segment(package_id)}/protocol`, { retry: true, options });
151
+ }
152
+ }
153
+ export class Protocols extends Resource {
154
+ async grant(protocol_id, body, options) {
155
+ return this.client.request("POST", `/benchmark-protocols/${segment(protocol_id)}/grants`, { retry: false, options, body: body });
156
+ }
157
+ async revoke(grant_id, body, options) {
158
+ return this.client.request("POST", `/benchmark-protocols/grants/${segment(grant_id)}/revoke`, { retry: false, options, body: body });
159
+ }
160
+ async grants(options) {
161
+ return this.client.request("GET", `/benchmark-protocols/grants`, { retry: true, options });
162
+ }
163
+ }
@@ -54,6 +54,7 @@ type Request = {
54
54
  };
55
55
  export declare function positive(value: number, label: string): number;
56
56
  export declare function segment(value: string): string;
57
+ export declare function familyPath(value: string): string;
57
58
  export declare function checkpoint(deadline: number, signal?: AbortSignal): number;
58
59
  export declare function pause(delay: number, deadline: number, signal?: AbortSignal): Promise<void>;
59
60
  export declare class Transport {
package/dist/transport.js CHANGED
@@ -52,6 +52,13 @@ export function segment(value) {
52
52
  throw new ClientError("invalid_input", "Resource identifiers must be nonempty path-safe identifiers.");
53
53
  return encodeURIComponent(value);
54
54
  }
55
+ export function familyPath(value) {
56
+ if (typeof value !== "string" ||
57
+ /^[a-z0-9][a-z0-9_./-]{0,119}$/.exec(value)?.[0] !== value ||
58
+ value.split("/").some((part) => ["", ".", ".."].includes(part)))
59
+ throw new ClientError("invalid_input", "Catalog families must be canonical relative paths.");
60
+ return value.split("/").map(encodeURIComponent).join("/");
61
+ }
55
62
  function normalizeBase(value, allowHttp) {
56
63
  try {
57
64
  if (/[\u0000-\u0020\\]/.test(value))
@@ -336,6 +343,11 @@ export class Transport {
336
343
  secrets.some((secret) => requestId.includes(secret)))
337
344
  requestId = null;
338
345
  error = new APIError(response.status, code, requestId, message, details);
346
+ // A definite build quota refusal cannot become admissible through
347
+ // transport backoff. Preserve its API error instead of masking it
348
+ // with the overall request deadline.
349
+ if (response.status === 429 && code === "agent_build_quota")
350
+ throw error;
339
351
  if (![429, 502, 503, 504].includes(response.status))
340
352
  throw error;
341
353
  delay = retryDelay(attempt, response.headers.get("Retry-After"));
package/dist/types.d.ts CHANGED
@@ -1,3 +1,133 @@
1
+ export type AgentBuildCoverage = {
2
+ mode?: "sample";
3
+ sample_count?: 1;
4
+ seed: number;
5
+ };
6
+ export type AgentBuildInstallationBudget = {
7
+ cleanup_seconds: 35;
8
+ command_seconds: 300;
9
+ cpu_millis: 1000;
10
+ duration_seconds: 660;
11
+ execute_seconds: 325;
12
+ input_seconds: 150 | 300;
13
+ memory_mib: 2048;
14
+ output_seconds: 150;
15
+ schema_version: "agent-build-installation-budget.v1";
16
+ };
17
+ export type AgentBuildModel = {
18
+ kind?: "managed";
19
+ route_id: string;
20
+ };
21
+ export type AgentBuildOptions = {
22
+ enabled: boolean;
23
+ limitations: Array<string>;
24
+ supported_runtimes: Array<"node-npm">;
25
+ targets: Array<AgentBuildTarget>;
26
+ };
27
+ export type AgentBuildPreview = {
28
+ manifest_path?: string;
29
+ max_cost_microusd: string;
30
+ qualification: AgentBuildQualification;
31
+ ref?: string | null;
32
+ repository_url: string;
33
+ source?: GitHubSourceSelection | null;
34
+ };
35
+ export type AgentBuildQualification = {
36
+ environment_ref: string;
37
+ model: AgentBuildModel;
38
+ };
39
+ export type AgentBuildQuoteRecord = {
40
+ cost_components_microusd: {
41
+ [key: string]: string;
42
+ };
43
+ created_at: string;
44
+ expires_at: string;
45
+ full_work_upper_bound_microusd?: string | null;
46
+ funded_phase_caps_microusd?: {
47
+ [key: string]: string;
48
+ } | null;
49
+ id: string;
50
+ max_cost_microusd: string;
51
+ pricing_version: "agent-build-pricing.v1";
52
+ qualification: AgentBuildScope;
53
+ qualification_funding?: "cap_limited" | null;
54
+ reserved_microusd?: string;
55
+ source: AgentBuildSource;
56
+ warnings: Array<string>;
57
+ };
58
+ export type AgentBuildRecord = {
59
+ agent: AgentRecord | null;
60
+ cleanup_confirmed: boolean;
61
+ completed_at: string | null;
62
+ created_at: string;
63
+ error_code: string | null;
64
+ held_microusd: string;
65
+ id: string;
66
+ max_cost_microusd: string;
67
+ phase: "preparing" | "building" | "qualifying" | "cleanup" | "complete";
68
+ pricing_version: "agent-build-pricing.v1";
69
+ qualification: AgentBuildScope;
70
+ qualification_run_id: string | null;
71
+ quote_id: string;
72
+ retry_allowed: boolean;
73
+ source: AgentBuildSource;
74
+ spent_microusd: string;
75
+ status: "queued" | "running" | "cancelling" | "ready" | "failed" | "cancelled" | "reconciling";
76
+ updated_at: string;
77
+ };
78
+ export type AgentBuildResourceLimits = {
79
+ cpu_millis: number;
80
+ duration_seconds: number;
81
+ memory_mib: number;
82
+ };
83
+ export type AgentBuildScope = {
84
+ coverage?: "bounded_qualification";
85
+ environment_manifest_sha256: string;
86
+ environment_ref: string;
87
+ evaluation_coverage: AgentBuildCoverage;
88
+ installation_budget?: AgentBuildInstallationBudget | null;
89
+ limitations: Array<string>;
90
+ model: AgentBuildModel;
91
+ model_label: string;
92
+ model_sha256: string;
93
+ resource_limits: AgentBuildResourceLimits;
94
+ split: "canonical" | "train" | "development" | "test";
95
+ task_count: number;
96
+ task_ids: Array<string>;
97
+ };
98
+ export type AgentBuildSource = {
99
+ commit_sha: string;
100
+ github_connection_id?: string | null;
101
+ github_repository_id?: number | null;
102
+ manifest_path: string;
103
+ manifest_sha256: string;
104
+ name: string;
105
+ repository_url: string;
106
+ requested_ref: string | null;
107
+ runtime: "node-npm";
108
+ tree_sha: string;
109
+ };
110
+ export type AgentBuildTarget = {
111
+ environment_ref: string;
112
+ models: Array<AgentBuildModel>;
113
+ task_ids: Array<string>;
114
+ };
115
+ export type AgentBuildsListParams = {
116
+ quote_id?: string | null;
117
+ limit?: number;
118
+ cursor?: string | null;
119
+ };
120
+ export type AgentRecord = {
121
+ id: string;
122
+ ref: string;
123
+ kind: string;
124
+ revision: string;
125
+ manifest_sha256: string;
126
+ active: boolean;
127
+ qualified: boolean;
128
+ external_costs: boolean;
129
+ created_at: string;
130
+ };
1
131
  export type BenchmarkDetail = {
2
132
  slug: string;
3
133
  versions: Array<BenchmarkRecord>;
@@ -88,6 +218,18 @@ export type ComparisonModel = {
88
218
  model_id: string;
89
219
  models: Array<SelectedModel>;
90
220
  };
221
+ export type ConcurrencyObservation = {
222
+ in_flight: number;
223
+ observed_at: string;
224
+ source: "gateway_dispatch_records";
225
+ uncertain: number;
226
+ };
227
+ export type ConcurrencyPlan = {
228
+ admitted_ceiling: number;
229
+ profiles: Array<ProfileConcurrency>;
230
+ requested: "auto" | "max" | number;
231
+ scope: "run_inference";
232
+ };
91
233
  export type ConnectedModel = {
92
234
  connection_id: string;
93
235
  kind: "connection";
@@ -127,6 +269,13 @@ export type CoverageRecord = {
127
269
  sample_count?: number | null;
128
270
  seed?: number | null;
129
271
  };
272
+ export type CreateAgentBuild = {
273
+ quote_id: string;
274
+ };
275
+ export type CreatorsNamespacesParams = {
276
+ cursor?: string | null;
277
+ limit?: number;
278
+ };
130
279
  export type EnvironmentFamily = {
131
280
  family: string;
132
281
  versions: Array<EnvironmentRecord>;
@@ -176,12 +325,17 @@ export type EnvironmentRights = {
176
325
  training: boolean;
177
326
  underlying_licenses?: Array<string>;
178
327
  };
328
+ export type EnvironmentSelection = {
329
+ environment: string;
330
+ split?: "canonical" | "train" | "development" | "test";
331
+ };
179
332
  export type EvalPricing = {
180
333
  execution_fee_microusd?: string | null;
181
334
  price_version: string;
182
335
  task_fee_microusd?: string | null;
183
336
  };
184
337
  export type EvalRecord = {
338
+ access?: "public" | "private" | "granted";
185
339
  availability?: string;
186
340
  availability_reason?: string;
187
341
  behaviors?: Array<string>;
@@ -236,6 +390,15 @@ export type ExecutionOptions = {
236
390
  export type FullCoverage = {
237
391
  mode: "full";
238
392
  };
393
+ export type GitHubSourceSelection = {
394
+ github_connection_id: string;
395
+ github_repository_id: number;
396
+ };
397
+ export type GrantRequest = {
398
+ grantee_workspace_id: string;
399
+ permissions: Array<"discover" | "execute">;
400
+ reason: string;
401
+ };
239
402
  export type Interval = {
240
403
  approximate: boolean;
241
404
  cluster_count?: number | null;
@@ -297,6 +460,18 @@ export type ManagedRoute = {
297
460
  revision: number;
298
461
  status: string;
299
462
  };
463
+ export type MaterialState = {
464
+ created_at: string;
465
+ error_code: string | null;
466
+ findings: Array<string>;
467
+ name: string;
468
+ prepared_at: string | null;
469
+ receipt_sha256: string | null;
470
+ requested_sha256: string;
471
+ size_bytes: number;
472
+ source_kind: string;
473
+ status: "declared" | "prepared" | "failed";
474
+ };
300
475
  export type MetricRecord = {
301
476
  direction: "higher_is_better" | "lower_is_better" | null;
302
477
  key: string;
@@ -308,6 +483,26 @@ export type MetricRecord = {
308
483
  uncertainty?: Uncertainty | null;
309
484
  value: number;
310
485
  };
486
+ export type NamespacePage = {
487
+ data: Array<NamespaceResult>;
488
+ next_cursor?: string | null;
489
+ };
490
+ export type NamespaceResult = {
491
+ created_at: string;
492
+ id: string;
493
+ slug: string;
494
+ source_url: string;
495
+ status: "requested" | "verified" | "revoked";
496
+ verified_at: string | null;
497
+ workspace_id: string;
498
+ };
499
+ export type NewAgentQuote = {
500
+ agent: string;
501
+ selection: EnvironmentSelection;
502
+ coverage?: SampleCoverage | FullCoverage | null;
503
+ max_charge_microusd: string;
504
+ concurrency?: "auto" | "max" | number | null;
505
+ };
311
506
  export type NewConnection = {
312
507
  api_key: string;
313
508
  base_url: string;
@@ -330,11 +525,20 @@ export type NewEvaluation = {
330
525
  provider?: string | null;
331
526
  split?: string | null;
332
527
  };
528
+ export type NewManagedACPAgent = {
529
+ admission_id: string;
530
+ kind: "managed_acp";
531
+ ref: string;
532
+ };
533
+ export type NewPart = {
534
+ data: string;
535
+ };
333
536
  export type NewQuote = {
334
537
  selection: Profiles | EvalReference;
335
538
  model: ManagedModel | ConnectedModel;
336
539
  coverage?: SampleCoverage | FullCoverage | null;
337
540
  max_charge_microusd: string;
541
+ concurrency?: "auto" | "max" | number | null;
338
542
  };
339
543
  export type NewRun = {
340
544
  metadata?: {
@@ -343,9 +547,57 @@ export type NewRun = {
343
547
  name?: string;
344
548
  quote_id: string;
345
549
  };
550
+ export type NewUpload = {
551
+ archive_sha256: string;
552
+ name: string;
553
+ namespace_id: string;
554
+ size_bytes: number;
555
+ version: string;
556
+ };
346
557
  export type OKResponse = {
347
558
  ok: boolean;
348
559
  };
560
+ export type PackageProtocolResult = {
561
+ compiler_version: string;
562
+ component_sha256: string;
563
+ created_at: string;
564
+ id: string;
565
+ material_receipt_sha256: string | null;
566
+ package_id: string;
567
+ package_sha256: string;
568
+ profile_id: string | null;
569
+ protocol: {
570
+ [key: string]: JsonValue;
571
+ };
572
+ protocol_execution_class: "contributed_sandboxed" | "maintained_native";
573
+ protocol_sha256: string;
574
+ runnable?: false;
575
+ };
576
+ export type PackageResult = {
577
+ created_at: string;
578
+ expires_at: string;
579
+ id: string;
580
+ manifest: {
581
+ [key: string]: JsonValue;
582
+ };
583
+ material?: Array<MaterialState>;
584
+ name: string;
585
+ namespace_id: string;
586
+ package_sha256: string;
587
+ protocol_sha256?: string | null;
588
+ runnable?: false;
589
+ status: string;
590
+ upload_id: string;
591
+ validation: {
592
+ [key: string]: JsonValue;
593
+ };
594
+ version: string;
595
+ workspace_id: string;
596
+ };
597
+ export type Page_AgentBuildRecord_ = {
598
+ data: Array<AgentBuildRecord>;
599
+ next_cursor: string | null;
600
+ };
349
601
  export type Page_BenchmarkRecord_ = {
350
602
  data: Array<BenchmarkRecord>;
351
603
  next_cursor: string | null;
@@ -366,10 +618,26 @@ export type Page_ManagedRoute_ = {
366
618
  data: Array<ManagedRoute>;
367
619
  next_cursor: string | null;
368
620
  };
621
+ export type Page_ProtocolGrant_ = {
622
+ data: Array<ProtocolGrant>;
623
+ next_cursor: string | null;
624
+ };
369
625
  export type Page_RunRecord_ = {
370
626
  data: Array<RunRecord>;
371
627
  next_cursor: string | null;
372
628
  };
629
+ export type PartResult = {
630
+ part_index: number;
631
+ sha256: string | null;
632
+ size_bytes: number;
633
+ stored_at: string | null;
634
+ };
635
+ export type ProfileConcurrency = {
636
+ adapter_ceiling: number;
637
+ admitted_ceiling: number;
638
+ profile_id: string;
639
+ reasons: Array<"auto_heuristic" | "adapter_limit" | "gateway_limit" | "task_count" | "budget_limit">;
640
+ };
373
641
  export type ProfileCost = {
374
642
  charged_microusd: string;
375
643
  model_index?: number | null;
@@ -416,9 +684,16 @@ export type ProfileSelection = {
416
684
  environment?: {
417
685
  [key: string]: JsonValue_Output;
418
686
  } | null;
687
+ generation_config?: {
688
+ [key: string]: JsonValue_Output;
689
+ } | null;
690
+ granted?: {
691
+ [key: string]: JsonValue_Output;
692
+ } | null;
419
693
  id: string;
420
694
  judge?: JudgeSelection | null;
421
695
  manifest_sha256: string;
696
+ max_output_tokens?: number;
422
697
  population_count: number;
423
698
  private_test?: boolean | null;
424
699
  remote?: {
@@ -427,12 +702,34 @@ export type ProfileSelection = {
427
702
  sampling_algorithm: string;
428
703
  sandbox?: SandboxPolicyView | null;
429
704
  selected_count: number;
705
+ selection_sha256?: string | null;
430
706
  task_ids?: Array<string> | null;
431
707
  task_ids_hash: string;
432
708
  };
433
709
  export type Profiles = {
434
710
  profile_ids: Array<string>;
435
711
  };
712
+ export type ProtocolGrant = {
713
+ access: "granted";
714
+ effective_at: string;
715
+ expires_at: string | null;
716
+ grantee_workspace_id: string;
717
+ id: string;
718
+ manifest_sha256: string;
719
+ owner_workspace_id: string | null;
720
+ permissions: Array<string>;
721
+ projection: {
722
+ [key: string]: JsonValue;
723
+ };
724
+ projection_sha256: string;
725
+ protocol_id: string;
726
+ protocol_sha256: string;
727
+ qualification_expires_at: string;
728
+ qualification_policy_version: string;
729
+ reason: string;
730
+ revocation_reason: string | null;
731
+ revoked_at: string | null;
732
+ };
436
733
  export type QuotePlan = {
437
734
  agent?: {
438
735
  [key: string]: JsonValue_Output;
@@ -440,6 +737,7 @@ export type QuotePlan = {
440
737
  agents?: Array<{
441
738
  [key: string]: JsonValue_Output;
442
739
  }> | null;
740
+ concurrency?: ConcurrencyPlan | null;
443
741
  coverage: CoverageRecord;
444
742
  model: SelectedModel | ComparisonModel;
445
743
  pricing: {
@@ -469,6 +767,7 @@ export type QuoteRecord = {
469
767
  price_version: string;
470
768
  retention: RetentionPolicy;
471
769
  };
770
+ export type QuotesCreateBody = NewQuote | NewAgentQuote;
472
771
  export type ResultCosts = {
473
772
  as_of: string;
474
773
  basis: "managed_total" | "platform_fees_only" | "mixed";
@@ -511,6 +810,9 @@ export type RetentionPolicy = {
511
810
  starts_at: "run_created_at";
512
811
  summary_days: number;
513
812
  };
813
+ export type RevokeRequest = {
814
+ reason: string;
815
+ };
514
816
  export type RunEvent = {
515
817
  created_at: string;
516
818
  data: {
@@ -541,6 +843,8 @@ export type RunRecord = {
541
843
  cancel_requested_at: string | null;
542
844
  cap_microusd: string;
543
845
  completed_count: number;
846
+ concurrency?: ConcurrencyPlan | null;
847
+ concurrency_observation?: ConcurrencyObservation | null;
544
848
  coverage: CoverageRecord | null;
545
849
  created_at: string;
546
850
  error_count: number;
@@ -582,7 +886,7 @@ export type RunsExecutionsParams = {
582
886
  limit?: number;
583
887
  };
584
888
  export type RunsExportParams = {
585
- format?: "json" | "csv" | "html";
889
+ format?: "json" | "csv" | "html" | "bundle";
586
890
  version?: number | null;
587
891
  };
588
892
  export type RunsListParams = {
@@ -678,3 +982,29 @@ export type UpdateConnection = {
678
982
  max_output_tokens?: number | null;
679
983
  name?: string | null;
680
984
  };
985
+ export type UploadResult = {
986
+ archive_sha256: string;
987
+ created_at: string;
988
+ expires_at: string;
989
+ id: string;
990
+ name: string;
991
+ namespace_id: string;
992
+ parts: Array<PartResult>;
993
+ size_bytes: number;
994
+ status: string;
995
+ version: string;
996
+ };
997
+ export type ValidationResult = {
998
+ attempts: number;
999
+ completed_at: string | null;
1000
+ created_at: string;
1001
+ error_code: string | null;
1002
+ expires_at: string;
1003
+ id: string;
1004
+ material?: Array<MaterialState>;
1005
+ next_attempt_at: string;
1006
+ package_id: string | null;
1007
+ protocol_version: number;
1008
+ status: "queued" | "running" | "succeeded" | "failed" | "cancelled";
1009
+ upload_id: string;
1010
+ };
package/dist/types.js CHANGED
@@ -1,2 +1,2 @@
1
- // Generated by scripts/generate_clients.py; OpenAPI SHA256 3cea8bc29adf3dd7ab60f48b418a77478e3e4502357e1e23de4a2f7e97088a3f.
1
+ // Generated by scripts/generate_clients.py; OpenAPI SHA256 f24a374d13ff31cbb78a8465babd5fef949c86e7867431fa54d07b16d51245d5.
2
2
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kimpton-ai/evalrouter",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "repository": {
6
6
  "type": "git",