@kindgi/client 0.1.4-rc.4 → 0.1.4

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
@@ -72,7 +72,7 @@ try {
72
72
 
73
73
  ## Exports
74
74
 
75
- - **`createClient(options: ClientOptions)`** — returns a `KindgiClient` with one resource client per property (see [Resources](#resources)). `ClientOptions`: `apiUrl` (no trailing slash), `auth` (`{ kind: 'apiToken', token }` or `{ kind: 'oauth', accessToken, refresh? }`), and an optional `fetch`. Creating a client opens no connections.
75
+ - **`createClient(options: ClientOptions)`** — returns a `KindgiClient` with one resource client per property (see [Resources](#resources)). `ClientOptions`: `apiUrl` (no trailing slash), `auth` (`{ kind: 'apiToken', token }` or `{ kind: 'oauth', accessToken, refresh? }`), an optional `fetch`, and an optional `timeoutMs` (below). Creating a client opens no connections.
76
76
  - **Errors** — every method throws **`KindgiApiError`**, whose `error` is a **`KindgiError`** discriminated on `code`: `network`, `auth`, `rate-limited`, `not-found`, `conflict`, `invalid-request`, `guardrail-violation`, `server`, `not-implemented-in-preview`, `not-yet-wired`. **`fromWire(body)`** maps an API error (`{ code, message, details? }`) onto that union; wire codes it does not recognize become `server`, with the original code in `serverCode`. **`notYetWired`** and **`notImplementedInPreview`** build the two preview variants.
77
77
  - **Streaming** — **`readSse`** and **`unwrapSseData`** read a `text/event-stream` response as an `AsyncIterable`, reconnecting with exponential backoff and `Last-Event-Id`. `runs.stream`, `evalRuns.events`, `adapters.prepare` and the `secrets` rotation event stream are built on them.
78
78
  - **Types** — the input, filter, page and record types of every resource; branded ids and `Filter` / `Page` re-exported from [`@kindgi/types`](../../packages/types/); `DefineAgentSpec` and `RunStatus`.
@@ -80,6 +80,8 @@ try {
80
80
 
81
81
  The transport makes one attempt per call and does not retry. Mutating calls accept an `idempotencyKey`, sent as the `Idempotency-Key` header, so a caller's own retries are safe (see [`docs/API-ROUTE-CONVENTIONS.md`](../../docs/API-ROUTE-CONVENTIONS.md)).
82
82
 
83
+ **Timeouts.** One request may take `timeoutMs` (30 000 ms unless `ClientOptions.timeoutMs` says otherwise); then it fails with a `network` error whose `timeoutMs` is set. Streams aren't bound by it. A waited `runs.start` answers only when the run ends, so it's bound by it too, and takes its own `timeoutMs`. When the timeout runs out there, the run may still be going and its id never arrived. Start a run that can take longer with `options: { wait: false }`, whose answer carries the run's id at once, and follow it with `runs.stream(runId)`.
84
+
83
85
  ## JSDoc tags
84
86
 
85
87
  - `@wire` — the method or type mirrors a route or schema in the API's `openapi.json`.
package/dist/index.cjs CHANGED
@@ -2894,7 +2894,157 @@ function subscribeToRun(options) {
2894
2894
  });
2895
2895
  }
2896
2896
 
2897
+ // src/transport.ts
2898
+ var DEFAULT_TIMEOUT_MS = 3e4;
2899
+ var MUTATING = /* @__PURE__ */ new Set([
2900
+ "POST",
2901
+ "PUT",
2902
+ "PATCH",
2903
+ "DELETE"
2904
+ ]);
2905
+ function createTransport(options) {
2906
+ const apiUrl = options.apiUrl.replace(/\/+$/u, "");
2907
+ const fetchImpl = options.fetch ?? fetch;
2908
+ const clientTimeoutMs = checkedTimeoutMs(
2909
+ options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
2910
+ "ClientOptions.timeoutMs"
2911
+ );
2912
+ return {
2913
+ apiUrl,
2914
+ fetchImpl,
2915
+ authHeaders() {
2916
+ return { Authorization: `Bearer ${authTokenFor(options.auth)}` };
2917
+ },
2918
+ async request(input) {
2919
+ const url = buildUrl(apiUrl, input.path, input.query);
2920
+ const headers = buildHeaders(input, options.auth);
2921
+ const timeoutMs = input.timeoutMs === void 0 ? clientTimeoutMs : checkedTimeoutMs(input.timeoutMs, "timeoutMs");
2922
+ const ac = new AbortController();
2923
+ let timedOut = false;
2924
+ const timer = setTimeout(() => {
2925
+ timedOut = true;
2926
+ ac.abort(new Error("timeout"));
2927
+ }, timeoutMs);
2928
+ let response;
2929
+ try {
2930
+ response = await fetchImpl(url, {
2931
+ method: input.method,
2932
+ headers,
2933
+ ...input.body !== void 0 && { body: JSON.stringify(input.body) },
2934
+ signal: ac.signal
2935
+ });
2936
+ } catch (cause) {
2937
+ clearTimeout(timer);
2938
+ const err = timedOut ? {
2939
+ code: "network",
2940
+ message: `No answer within ${seconds(timeoutMs)}, the client's timeout (timeoutMs).`,
2941
+ cause,
2942
+ timeoutMs
2943
+ } : {
2944
+ code: "network",
2945
+ message: cause instanceof Error ? cause.message : "network request failed",
2946
+ cause
2947
+ };
2948
+ throw new KindgiApiError(err);
2949
+ }
2950
+ clearTimeout(timer);
2951
+ if (response.ok) {
2952
+ if (input.discardResponse === true || response.status === 204) {
2953
+ try {
2954
+ await response.arrayBuffer();
2955
+ } catch {
2956
+ }
2957
+ return void 0;
2958
+ }
2959
+ try {
2960
+ return await response.json();
2961
+ } catch (cause) {
2962
+ const err = {
2963
+ code: "network",
2964
+ message: "Response body was not valid JSON",
2965
+ cause
2966
+ };
2967
+ throw new KindgiApiError(err);
2968
+ }
2969
+ }
2970
+ let body;
2971
+ try {
2972
+ body = await response.json();
2973
+ } catch {
2974
+ body = void 0;
2975
+ }
2976
+ throw new KindgiApiError(
2977
+ fromWire(unwrapErrorEnvelope(body, response.status), response.status)
2978
+ );
2979
+ }
2980
+ };
2981
+ }
2982
+ function checkedTimeoutMs(value, name) {
2983
+ if (!Number.isFinite(value) || value <= 0) {
2984
+ throw new TypeError(`${name} must be a positive number of milliseconds. Got ${String(value)}.`);
2985
+ }
2986
+ return value;
2987
+ }
2988
+ function seconds(ms) {
2989
+ return `${ms / 1e3} s`;
2990
+ }
2991
+ function buildUrl(apiUrl, path, query) {
2992
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
2993
+ const base = `${apiUrl}${normalizedPath}`;
2994
+ if (query === void 0) return base;
2995
+ const params = [];
2996
+ for (const key of Object.keys(query)) {
2997
+ const value = query[key];
2998
+ if (value === void 0) continue;
2999
+ const values = typeof value === "object" ? value : [String(value)];
3000
+ for (const v of values) params.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);
3001
+ }
3002
+ return params.length === 0 ? base : `${base}?${params.join("&")}`;
3003
+ }
3004
+ function buildHeaders(input, auth) {
3005
+ const headers = {
3006
+ Accept: "application/json",
3007
+ Authorization: `Bearer ${authTokenFor(auth)}`
3008
+ };
3009
+ if (input.body !== void 0) {
3010
+ headers["Content-Type"] = "application/json; charset=utf-8";
3011
+ }
3012
+ if (input.idempotencyKey !== void 0 && MUTATING.has(input.method)) {
3013
+ headers["Idempotency-Key"] = input.idempotencyKey;
3014
+ }
3015
+ if (input.headers !== void 0) {
3016
+ for (const key of Object.keys(input.headers)) {
3017
+ headers[key] = input.headers[key];
3018
+ }
3019
+ }
3020
+ return headers;
3021
+ }
3022
+ function authTokenFor(auth) {
3023
+ if (auth.kind === "apiToken") return auth.token;
3024
+ return auth.accessToken;
3025
+ }
3026
+ function unwrapErrorEnvelope(body, status) {
3027
+ if (body !== null && typeof body === "object" && !Array.isArray(body)) {
3028
+ const inner = body.error;
3029
+ if (inner !== null && typeof inner === "object" && !Array.isArray(inner)) {
3030
+ return inner;
3031
+ }
3032
+ }
3033
+ return { code: "unknown", message: `HTTP ${status} without recognizable error envelope` };
3034
+ }
3035
+
2897
3036
  // src/resources/runs.ts
3037
+ function waitedStartTimeout(e) {
3038
+ if (!(e instanceof KindgiApiError) || e.error.code !== "network") return e;
3039
+ const { timeoutMs } = e.error;
3040
+ if (timeoutMs === void 0) return e;
3041
+ return new KindgiApiError({
3042
+ code: "network",
3043
+ message: `The run didn't end within ${seconds(timeoutMs)}, the client's timeout (timeoutMs). A waited start answers only when the run ends, so the run may still be going, and its id didn't arrive. Start a run that can take longer with \`options: { wait: false }\`: the answer carries its id at once. Then follow it with \`runs.stream(runId)\` or \`runs.get(runId)\`. Or raise \`timeoutMs\`.`,
3044
+ cause: e.error.cause,
3045
+ timeoutMs
3046
+ });
3047
+ }
2898
3048
  function makeRunsClient(transport) {
2899
3049
  return {
2900
3050
  async start(input) {
@@ -2913,14 +3063,19 @@ function makeRunsClient(transport) {
2913
3063
  input: input.input,
2914
3064
  ...input.options !== void 0 && { options: input.options }
2915
3065
  };
2916
- return transport.request({
2917
- method: "POST",
2918
- path: "/v1/runs",
2919
- body,
2920
- ...input.idempotencyKey !== void 0 && {
2921
- idempotencyKey: input.idempotencyKey
2922
- }
2923
- });
3066
+ try {
3067
+ return await transport.request({
3068
+ method: "POST",
3069
+ path: "/v1/runs",
3070
+ body,
3071
+ ...input.idempotencyKey !== void 0 && {
3072
+ idempotencyKey: input.idempotencyKey
3073
+ },
3074
+ ...input.timeoutMs !== void 0 && { timeoutMs: input.timeoutMs }
3075
+ });
3076
+ } catch (e) {
3077
+ throw input.options?.wait === false ? e : waitedStartTimeout(e);
3078
+ }
2924
3079
  },
2925
3080
  async dryRun(_input) {
2926
3081
  throw new KindgiApiError(
@@ -4050,127 +4205,6 @@ function makeWebhooksClient(transport) {
4050
4205
  };
4051
4206
  }
4052
4207
 
4053
- // src/transport.ts
4054
- var DEFAULT_TIMEOUT_MS = 3e4;
4055
- var MUTATING = /* @__PURE__ */ new Set([
4056
- "POST",
4057
- "PUT",
4058
- "PATCH",
4059
- "DELETE"
4060
- ]);
4061
- function createTransport(options) {
4062
- const apiUrl = options.apiUrl.replace(/\/+$/u, "");
4063
- const fetchImpl = options.fetch ?? fetch;
4064
- const clientTimeoutMs = DEFAULT_TIMEOUT_MS;
4065
- return {
4066
- apiUrl,
4067
- fetchImpl,
4068
- authHeaders() {
4069
- return { Authorization: `Bearer ${authTokenFor(options.auth)}` };
4070
- },
4071
- async request(input) {
4072
- const url = buildUrl(apiUrl, input.path, input.query);
4073
- const headers = buildHeaders(input, options.auth);
4074
- const timeoutMs = input.timeoutMs ?? clientTimeoutMs;
4075
- const ac = new AbortController();
4076
- const timer = setTimeout(
4077
- () => ac.abort(new Error("timeout")),
4078
- timeoutMs
4079
- );
4080
- let response;
4081
- try {
4082
- response = await fetchImpl(url, {
4083
- method: input.method,
4084
- headers,
4085
- ...input.body !== void 0 && { body: JSON.stringify(input.body) },
4086
- signal: ac.signal
4087
- });
4088
- } catch (cause) {
4089
- clearTimeout(timer);
4090
- const err = {
4091
- code: "network",
4092
- message: cause instanceof Error ? cause.message : "network request failed",
4093
- cause
4094
- };
4095
- throw new KindgiApiError(err);
4096
- }
4097
- clearTimeout(timer);
4098
- if (response.ok) {
4099
- if (input.discardResponse === true || response.status === 204) {
4100
- try {
4101
- await response.arrayBuffer();
4102
- } catch {
4103
- }
4104
- return void 0;
4105
- }
4106
- try {
4107
- return await response.json();
4108
- } catch (cause) {
4109
- const err = {
4110
- code: "network",
4111
- message: "Response body was not valid JSON",
4112
- cause
4113
- };
4114
- throw new KindgiApiError(err);
4115
- }
4116
- }
4117
- let body;
4118
- try {
4119
- body = await response.json();
4120
- } catch {
4121
- body = void 0;
4122
- }
4123
- throw new KindgiApiError(
4124
- fromWire(unwrapErrorEnvelope(body, response.status), response.status)
4125
- );
4126
- }
4127
- };
4128
- }
4129
- function buildUrl(apiUrl, path, query) {
4130
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
4131
- const base = `${apiUrl}${normalizedPath}`;
4132
- if (query === void 0) return base;
4133
- const params = [];
4134
- for (const key of Object.keys(query)) {
4135
- const value = query[key];
4136
- if (value === void 0) continue;
4137
- const values = typeof value === "object" ? value : [String(value)];
4138
- for (const v of values) params.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);
4139
- }
4140
- return params.length === 0 ? base : `${base}?${params.join("&")}`;
4141
- }
4142
- function buildHeaders(input, auth) {
4143
- const headers = {
4144
- Accept: "application/json",
4145
- Authorization: `Bearer ${authTokenFor(auth)}`
4146
- };
4147
- if (input.body !== void 0) {
4148
- headers["Content-Type"] = "application/json; charset=utf-8";
4149
- }
4150
- if (input.idempotencyKey !== void 0 && MUTATING.has(input.method)) {
4151
- headers["Idempotency-Key"] = input.idempotencyKey;
4152
- }
4153
- if (input.headers !== void 0) {
4154
- for (const key of Object.keys(input.headers)) {
4155
- headers[key] = input.headers[key];
4156
- }
4157
- }
4158
- return headers;
4159
- }
4160
- function authTokenFor(auth) {
4161
- if (auth.kind === "apiToken") return auth.token;
4162
- return auth.accessToken;
4163
- }
4164
- function unwrapErrorEnvelope(body, status) {
4165
- if (body !== null && typeof body === "object" && !Array.isArray(body)) {
4166
- const inner = body.error;
4167
- if (inner !== null && typeof inner === "object" && !Array.isArray(inner)) {
4168
- return inner;
4169
- }
4170
- }
4171
- return { code: "unknown", message: `HTTP ${status} without recognizable error envelope` };
4172
- }
4173
-
4174
4208
  // src/client.ts
4175
4209
  function createClient(options) {
4176
4210
  const transport = createTransport(options);
package/dist/index.d.cts CHANGED
@@ -1775,7 +1775,9 @@ export interface DefineAgentSpec {
1775
1775
  * Required capabilities the agent needs from a `ModelProvider`.
1776
1776
  * Typically one entry: `[{ needs: [{ feature: 'tool-use' }] }]`
1777
1777
  * for a tool-calling agent, `[{ needs: [{ feature: 'structured-output' }] }]`
1778
- * for an agent that returns schema-constrained JSON. The router uses
1778
+ * for an agent that should run on a model that can follow a JSON schema
1779
+ * natively (its typed `output` is still checked by parse and repair, on
1780
+ * every model). The router uses
1779
1781
  * the first entry to pick a compatible provider from the tenant's
1780
1782
  * `ProviderRegistry`.
1781
1783
  */
@@ -3997,6 +3999,12 @@ export interface ClientOptions {
3997
3999
  readonly auth: AuthConfig;
3998
4000
  /** Overridable fetch impl for testing. Defaults to global `fetch`. */
3999
4001
  readonly fetch?: typeof fetch;
4002
+ /**
4003
+ * How long one request may take, in milliseconds, before it fails with
4004
+ * a `network` error. Default 30 000. Streams (`runs.stream` and the
4005
+ * like) aren't bound by it. `runs.start` also takes its own.
4006
+ */
4007
+ readonly timeoutMs?: number;
4000
4008
  }
4001
4009
  /** The verdict of a judgment. */
4002
4010
  export type Verdict = "yes" | "no";
@@ -4675,6 +4683,10 @@ declare namespace Schemas {
4675
4683
  * The segment path the run was started with (coarse to fine), which picks live agent versions. A child run has its parent's. Absent when there was none.
4676
4684
  */
4677
4685
  segments?: Array<ScopeSegment>;
4686
+ /**
4687
+ * The W3C trace id of the request that started the run: the caller's (from its `traceparent`) or one the API minted. The runtime's records about the run carry it; `GET` responses answer `traceresponse` with each request's own. Absent for a run no request started, and on runs from before runs recorded it.
4688
+ */
4689
+ traceId?: string;
4678
4690
  /**
4679
4691
  * Only in the response to `POST /v1/runs`, when the deployment issues public run tokens: a read-only token for this run (and its descendants) to hand to a browser, for `GET /v1/runs/{runId}/progress` and its stream.
4680
4692
  */
@@ -4805,6 +4817,10 @@ declare namespace Schemas {
4805
4817
  * The segment path the run was started with (coarse to fine), which picks live agent versions. A child run has its parent's. Absent when there was none.
4806
4818
  */
4807
4819
  segments?: Array<ScopeSegment>;
4820
+ /**
4821
+ * The W3C trace id of the request that started the run: the caller's (from its `traceparent`) or one the API minted. The runtime's records about the run carry it; `GET` responses answer `traceresponse` with each request's own. Absent for a run no request started, and on runs from before runs recorded it.
4822
+ */
4823
+ traceId?: string;
4808
4824
  /**
4809
4825
  * Only in the response to `POST /v1/runs`, when the deployment issues public run tokens: a read-only token for this run (and its descendants) to hand to a browser, for `GET /v1/runs/{runId}/progress` and its stream.
4810
4826
  */
@@ -6901,6 +6917,19 @@ declare namespace Schemas {
6901
6917
  nextCursor?: string;
6902
6918
  hasMore: boolean;
6903
6919
  };
6920
+ /**
6921
+ * How the model thinks before it answers, so a call that wants as little as it allows (a judge's) gets it. Absent: it doesn't think, or nothing is known.
6922
+ */
6923
+ export type ModelThinking = {
6924
+ /**
6925
+ * `adaptive`: on unless turned down. `always`: on, and it can only be lowered.
6926
+ */
6927
+ mode: "adaptive" | "always";
6928
+ /**
6929
+ * The vendor's own setting for the least thinking: for Anthropic `disabled`, `between_tools` or an effort (`low`); for Gemini a thinking level (`low`, `minimal`); for OpenAI a reasoning effort (`low`, `none`).
6930
+ */
6931
+ lowest: string;
6932
+ };
6904
6933
  /**
6905
6934
  * USD per 1K tokens. An adapter may take more rate fields (see the adapter's README).
6906
6935
  */
@@ -6930,6 +6959,11 @@ declare namespace Schemas {
6930
6959
  * Fallback cap on output tokens. Adapters that require `max_tokens` on every request (e.g. Anthropic) use this when `ModelCallInput.maxOutputTokens` is unset.
6931
6960
  */
6932
6961
  maxOutputTokens?: number;
6962
+ /**
6963
+ * Whether the model takes sampling settings (`temperature`). `false`: its API rejects a non-default value, so the call goes without one and the answer's `warnings` say so (`sampling-unsupported`). Absent: it takes them.
6964
+ */
6965
+ sampling?: boolean;
6966
+ thinking?: ModelThinking;
6933
6967
  /**
6934
6968
  * Short per-model description surfaced in logs.
6935
6969
  */
@@ -6945,6 +6979,10 @@ declare namespace Schemas {
6945
6979
  * Models this connection exposes. Non-empty. `models[i].name` must be unique within the list.
6946
6980
  */
6947
6981
  models: Array<ModelInfo>;
6982
+ /**
6983
+ * The model to use when an agent doesn't choose: one of `models[].name`. When candidates rank equally, it comes before the provider's other models; without it, ties break by model name. A preset sets it. A runtime before 0.1.4 ignores it.
6984
+ */
6985
+ defaultModel?: string;
6948
6986
  /**
6949
6987
  * Soft attributes for preference-ranking (`local`, `lower-cost`, `higher-accuracy`, ...). Matched by string equality against `Preference.feature`.
6950
6988
  */
@@ -10083,8 +10121,17 @@ declare const ProviderMetadata: z.ZodObject<{
10083
10121
  }, z.core.$catchall<z.ZodUnknown>>;
10084
10122
  p95LatencyMs: z.ZodOptional<z.ZodNumber>;
10085
10123
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
10124
+ sampling: z.ZodOptional<z.ZodBoolean>;
10125
+ thinking: z.ZodOptional<z.ZodObject<{
10126
+ mode: z.ZodEnum<{
10127
+ always: "always";
10128
+ adaptive: "adaptive";
10129
+ }>;
10130
+ lowest: z.ZodString;
10131
+ }, z.core.$strict>>;
10086
10132
  description: z.ZodOptional<z.ZodString>;
10087
10133
  }, z.core.$strict>>;
10134
+ defaultModel: z.ZodOptional<z.ZodString>;
10088
10135
  attributes: z.ZodOptional<z.ZodArray<z.ZodString>>;
10089
10136
  description: z.ZodOptional<z.ZodString>;
10090
10137
  capabilityKind: z.ZodOptional<z.ZodString>;
@@ -10120,8 +10167,17 @@ declare const ProviderCollectionPage: z.ZodObject<{
10120
10167
  }, z.core.$catchall<z.ZodUnknown>>;
10121
10168
  p95LatencyMs: z.ZodOptional<z.ZodNumber>;
10122
10169
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
10170
+ sampling: z.ZodOptional<z.ZodBoolean>;
10171
+ thinking: z.ZodOptional<z.ZodObject<{
10172
+ mode: z.ZodEnum<{
10173
+ always: "always";
10174
+ adaptive: "adaptive";
10175
+ }>;
10176
+ lowest: z.ZodString;
10177
+ }, z.core.$strict>>;
10123
10178
  description: z.ZodOptional<z.ZodString>;
10124
10179
  }, z.core.$strict>>;
10180
+ defaultModel: z.ZodOptional<z.ZodString>;
10125
10181
  attributes: z.ZodOptional<z.ZodArray<z.ZodString>>;
10126
10182
  description: z.ZodOptional<z.ZodString>;
10127
10183
  capabilityKind: z.ZodOptional<z.ZodString>;
@@ -10160,8 +10216,17 @@ declare const RegisterProviderBody: z.ZodObject<{
10160
10216
  }, z.core.$catchall<z.ZodUnknown>>;
10161
10217
  p95LatencyMs: z.ZodOptional<z.ZodNumber>;
10162
10218
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
10219
+ sampling: z.ZodOptional<z.ZodBoolean>;
10220
+ thinking: z.ZodOptional<z.ZodObject<{
10221
+ mode: z.ZodEnum<{
10222
+ always: "always";
10223
+ adaptive: "adaptive";
10224
+ }>;
10225
+ lowest: z.ZodString;
10226
+ }, z.core.$strict>>;
10163
10227
  description: z.ZodOptional<z.ZodString>;
10164
10228
  }, z.core.$strict>>;
10229
+ defaultModel: z.ZodOptional<z.ZodString>;
10165
10230
  attributes: z.ZodOptional<z.ZodArray<z.ZodString>>;
10166
10231
  description: z.ZodOptional<z.ZodString>;
10167
10232
  capabilityKind: z.ZodOptional<z.ZodString>;
@@ -14688,6 +14753,11 @@ export interface RunsClient {
14688
14753
  * with `options.wait: false` as soon as it exists (202) — poll
14689
14754
  * `get(runId)` until it finishes.
14690
14755
  *
14756
+ * A waited start is bound by the client's timeout (`timeoutMs`, 30 s by
14757
+ * default; this call can set its own). When it runs out, the run may
14758
+ * still be going and its id never arrived: the `network` error says so.
14759
+ * Start a run that can take longer with `options.wait: false`.
14760
+ *
14691
14761
  * `idempotencyKey` makes retries safe: two calls with the same key
14692
14762
  * within the server's retention window return the same `Run`.
14693
14763
  *
@@ -14852,6 +14922,13 @@ export type StartRunInput = {
14852
14922
  readonly input: unknown;
14853
14923
  readonly options?: StartRunOptions;
14854
14924
  readonly idempotencyKey?: string;
14925
+ /**
14926
+ * How long to wait for the answer, in milliseconds: this call's
14927
+ * `ClientOptions.timeoutMs`. A waited start answers only when the run
14928
+ * ends, so a run that can take longer is better started with
14929
+ * `options: { wait: false }` and followed.
14930
+ */
14931
+ readonly timeoutMs?: number;
14855
14932
  } | {
14856
14933
  readonly flow: FlowId | string;
14857
14934
  readonly flowVersion?: string;
@@ -14862,6 +14939,13 @@ export type StartRunInput = {
14862
14939
  readonly input: unknown;
14863
14940
  readonly options?: StartRunOptions;
14864
14941
  readonly idempotencyKey?: string;
14942
+ /**
14943
+ * How long to wait for the answer, in milliseconds: this call's
14944
+ * `ClientOptions.timeoutMs`. A waited start answers only when the run
14945
+ * ends, so a run that can take longer is better started with
14946
+ * `options: { wait: false }` and followed.
14947
+ */
14948
+ readonly timeoutMs?: number;
14865
14949
  };
14866
14950
  export interface StartRunOptions {
14867
14951
  /** Run with side-effects mocked; the row is marked `dryRun: true`. */
@@ -14929,6 +15013,12 @@ export interface Run {
14929
15013
  readonly agent?: RunAgent;
14930
15014
  /** The segment path the run was started with; a child run has its parent's. */
14931
15015
  readonly segments?: readonly ScopeSegment[];
15016
+ /**
15017
+ * The W3C trace id of the request that started the run (yours, when you
15018
+ * sent a `traceparent`). Absent for a run no request started, and from
15019
+ * an older runtime.
15020
+ */
15021
+ readonly traceId?: string;
14932
15022
  }
14933
15023
  /**
14934
15024
  * What `runs.start` returns: the run, plus a public run token when the
@@ -16040,6 +16130,8 @@ export interface NetworkError {
16040
16130
  readonly code: "network";
16041
16131
  readonly message: string;
16042
16132
  readonly cause?: unknown;
16133
+ /** Set when the client's own timeout ended the request: that timeout, in milliseconds. */
16134
+ readonly timeoutMs?: number;
16043
16135
  }
16044
16136
  export interface AuthError {
16045
16137
  readonly code: "auth";
package/dist/index.d.ts CHANGED
@@ -1775,7 +1775,9 @@ export interface DefineAgentSpec {
1775
1775
  * Required capabilities the agent needs from a `ModelProvider`.
1776
1776
  * Typically one entry: `[{ needs: [{ feature: 'tool-use' }] }]`
1777
1777
  * for a tool-calling agent, `[{ needs: [{ feature: 'structured-output' }] }]`
1778
- * for an agent that returns schema-constrained JSON. The router uses
1778
+ * for an agent that should run on a model that can follow a JSON schema
1779
+ * natively (its typed `output` is still checked by parse and repair, on
1780
+ * every model). The router uses
1779
1781
  * the first entry to pick a compatible provider from the tenant's
1780
1782
  * `ProviderRegistry`.
1781
1783
  */
@@ -3997,6 +3999,12 @@ export interface ClientOptions {
3997
3999
  readonly auth: AuthConfig;
3998
4000
  /** Overridable fetch impl for testing. Defaults to global `fetch`. */
3999
4001
  readonly fetch?: typeof fetch;
4002
+ /**
4003
+ * How long one request may take, in milliseconds, before it fails with
4004
+ * a `network` error. Default 30 000. Streams (`runs.stream` and the
4005
+ * like) aren't bound by it. `runs.start` also takes its own.
4006
+ */
4007
+ readonly timeoutMs?: number;
4000
4008
  }
4001
4009
  /** The verdict of a judgment. */
4002
4010
  export type Verdict = "yes" | "no";
@@ -4675,6 +4683,10 @@ declare namespace Schemas {
4675
4683
  * The segment path the run was started with (coarse to fine), which picks live agent versions. A child run has its parent's. Absent when there was none.
4676
4684
  */
4677
4685
  segments?: Array<ScopeSegment>;
4686
+ /**
4687
+ * The W3C trace id of the request that started the run: the caller's (from its `traceparent`) or one the API minted. The runtime's records about the run carry it; `GET` responses answer `traceresponse` with each request's own. Absent for a run no request started, and on runs from before runs recorded it.
4688
+ */
4689
+ traceId?: string;
4678
4690
  /**
4679
4691
  * Only in the response to `POST /v1/runs`, when the deployment issues public run tokens: a read-only token for this run (and its descendants) to hand to a browser, for `GET /v1/runs/{runId}/progress` and its stream.
4680
4692
  */
@@ -4805,6 +4817,10 @@ declare namespace Schemas {
4805
4817
  * The segment path the run was started with (coarse to fine), which picks live agent versions. A child run has its parent's. Absent when there was none.
4806
4818
  */
4807
4819
  segments?: Array<ScopeSegment>;
4820
+ /**
4821
+ * The W3C trace id of the request that started the run: the caller's (from its `traceparent`) or one the API minted. The runtime's records about the run carry it; `GET` responses answer `traceresponse` with each request's own. Absent for a run no request started, and on runs from before runs recorded it.
4822
+ */
4823
+ traceId?: string;
4808
4824
  /**
4809
4825
  * Only in the response to `POST /v1/runs`, when the deployment issues public run tokens: a read-only token for this run (and its descendants) to hand to a browser, for `GET /v1/runs/{runId}/progress` and its stream.
4810
4826
  */
@@ -6901,6 +6917,19 @@ declare namespace Schemas {
6901
6917
  nextCursor?: string;
6902
6918
  hasMore: boolean;
6903
6919
  };
6920
+ /**
6921
+ * How the model thinks before it answers, so a call that wants as little as it allows (a judge's) gets it. Absent: it doesn't think, or nothing is known.
6922
+ */
6923
+ export type ModelThinking = {
6924
+ /**
6925
+ * `adaptive`: on unless turned down. `always`: on, and it can only be lowered.
6926
+ */
6927
+ mode: "adaptive" | "always";
6928
+ /**
6929
+ * The vendor's own setting for the least thinking: for Anthropic `disabled`, `between_tools` or an effort (`low`); for Gemini a thinking level (`low`, `minimal`); for OpenAI a reasoning effort (`low`, `none`).
6930
+ */
6931
+ lowest: string;
6932
+ };
6904
6933
  /**
6905
6934
  * USD per 1K tokens. An adapter may take more rate fields (see the adapter's README).
6906
6935
  */
@@ -6930,6 +6959,11 @@ declare namespace Schemas {
6930
6959
  * Fallback cap on output tokens. Adapters that require `max_tokens` on every request (e.g. Anthropic) use this when `ModelCallInput.maxOutputTokens` is unset.
6931
6960
  */
6932
6961
  maxOutputTokens?: number;
6962
+ /**
6963
+ * Whether the model takes sampling settings (`temperature`). `false`: its API rejects a non-default value, so the call goes without one and the answer's `warnings` say so (`sampling-unsupported`). Absent: it takes them.
6964
+ */
6965
+ sampling?: boolean;
6966
+ thinking?: ModelThinking;
6933
6967
  /**
6934
6968
  * Short per-model description surfaced in logs.
6935
6969
  */
@@ -6945,6 +6979,10 @@ declare namespace Schemas {
6945
6979
  * Models this connection exposes. Non-empty. `models[i].name` must be unique within the list.
6946
6980
  */
6947
6981
  models: Array<ModelInfo>;
6982
+ /**
6983
+ * The model to use when an agent doesn't choose: one of `models[].name`. When candidates rank equally, it comes before the provider's other models; without it, ties break by model name. A preset sets it. A runtime before 0.1.4 ignores it.
6984
+ */
6985
+ defaultModel?: string;
6948
6986
  /**
6949
6987
  * Soft attributes for preference-ranking (`local`, `lower-cost`, `higher-accuracy`, ...). Matched by string equality against `Preference.feature`.
6950
6988
  */
@@ -10083,8 +10121,17 @@ declare const ProviderMetadata: z.ZodObject<{
10083
10121
  }, z.core.$catchall<z.ZodUnknown>>;
10084
10122
  p95LatencyMs: z.ZodOptional<z.ZodNumber>;
10085
10123
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
10124
+ sampling: z.ZodOptional<z.ZodBoolean>;
10125
+ thinking: z.ZodOptional<z.ZodObject<{
10126
+ mode: z.ZodEnum<{
10127
+ always: "always";
10128
+ adaptive: "adaptive";
10129
+ }>;
10130
+ lowest: z.ZodString;
10131
+ }, z.core.$strict>>;
10086
10132
  description: z.ZodOptional<z.ZodString>;
10087
10133
  }, z.core.$strict>>;
10134
+ defaultModel: z.ZodOptional<z.ZodString>;
10088
10135
  attributes: z.ZodOptional<z.ZodArray<z.ZodString>>;
10089
10136
  description: z.ZodOptional<z.ZodString>;
10090
10137
  capabilityKind: z.ZodOptional<z.ZodString>;
@@ -10120,8 +10167,17 @@ declare const ProviderCollectionPage: z.ZodObject<{
10120
10167
  }, z.core.$catchall<z.ZodUnknown>>;
10121
10168
  p95LatencyMs: z.ZodOptional<z.ZodNumber>;
10122
10169
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
10170
+ sampling: z.ZodOptional<z.ZodBoolean>;
10171
+ thinking: z.ZodOptional<z.ZodObject<{
10172
+ mode: z.ZodEnum<{
10173
+ always: "always";
10174
+ adaptive: "adaptive";
10175
+ }>;
10176
+ lowest: z.ZodString;
10177
+ }, z.core.$strict>>;
10123
10178
  description: z.ZodOptional<z.ZodString>;
10124
10179
  }, z.core.$strict>>;
10180
+ defaultModel: z.ZodOptional<z.ZodString>;
10125
10181
  attributes: z.ZodOptional<z.ZodArray<z.ZodString>>;
10126
10182
  description: z.ZodOptional<z.ZodString>;
10127
10183
  capabilityKind: z.ZodOptional<z.ZodString>;
@@ -10160,8 +10216,17 @@ declare const RegisterProviderBody: z.ZodObject<{
10160
10216
  }, z.core.$catchall<z.ZodUnknown>>;
10161
10217
  p95LatencyMs: z.ZodOptional<z.ZodNumber>;
10162
10218
  maxOutputTokens: z.ZodOptional<z.ZodNumber>;
10219
+ sampling: z.ZodOptional<z.ZodBoolean>;
10220
+ thinking: z.ZodOptional<z.ZodObject<{
10221
+ mode: z.ZodEnum<{
10222
+ always: "always";
10223
+ adaptive: "adaptive";
10224
+ }>;
10225
+ lowest: z.ZodString;
10226
+ }, z.core.$strict>>;
10163
10227
  description: z.ZodOptional<z.ZodString>;
10164
10228
  }, z.core.$strict>>;
10229
+ defaultModel: z.ZodOptional<z.ZodString>;
10165
10230
  attributes: z.ZodOptional<z.ZodArray<z.ZodString>>;
10166
10231
  description: z.ZodOptional<z.ZodString>;
10167
10232
  capabilityKind: z.ZodOptional<z.ZodString>;
@@ -14688,6 +14753,11 @@ export interface RunsClient {
14688
14753
  * with `options.wait: false` as soon as it exists (202) — poll
14689
14754
  * `get(runId)` until it finishes.
14690
14755
  *
14756
+ * A waited start is bound by the client's timeout (`timeoutMs`, 30 s by
14757
+ * default; this call can set its own). When it runs out, the run may
14758
+ * still be going and its id never arrived: the `network` error says so.
14759
+ * Start a run that can take longer with `options.wait: false`.
14760
+ *
14691
14761
  * `idempotencyKey` makes retries safe: two calls with the same key
14692
14762
  * within the server's retention window return the same `Run`.
14693
14763
  *
@@ -14852,6 +14922,13 @@ export type StartRunInput = {
14852
14922
  readonly input: unknown;
14853
14923
  readonly options?: StartRunOptions;
14854
14924
  readonly idempotencyKey?: string;
14925
+ /**
14926
+ * How long to wait for the answer, in milliseconds: this call's
14927
+ * `ClientOptions.timeoutMs`. A waited start answers only when the run
14928
+ * ends, so a run that can take longer is better started with
14929
+ * `options: { wait: false }` and followed.
14930
+ */
14931
+ readonly timeoutMs?: number;
14855
14932
  } | {
14856
14933
  readonly flow: FlowId | string;
14857
14934
  readonly flowVersion?: string;
@@ -14862,6 +14939,13 @@ export type StartRunInput = {
14862
14939
  readonly input: unknown;
14863
14940
  readonly options?: StartRunOptions;
14864
14941
  readonly idempotencyKey?: string;
14942
+ /**
14943
+ * How long to wait for the answer, in milliseconds: this call's
14944
+ * `ClientOptions.timeoutMs`. A waited start answers only when the run
14945
+ * ends, so a run that can take longer is better started with
14946
+ * `options: { wait: false }` and followed.
14947
+ */
14948
+ readonly timeoutMs?: number;
14865
14949
  };
14866
14950
  export interface StartRunOptions {
14867
14951
  /** Run with side-effects mocked; the row is marked `dryRun: true`. */
@@ -14929,6 +15013,12 @@ export interface Run {
14929
15013
  readonly agent?: RunAgent;
14930
15014
  /** The segment path the run was started with; a child run has its parent's. */
14931
15015
  readonly segments?: readonly ScopeSegment[];
15016
+ /**
15017
+ * The W3C trace id of the request that started the run (yours, when you
15018
+ * sent a `traceparent`). Absent for a run no request started, and from
15019
+ * an older runtime.
15020
+ */
15021
+ readonly traceId?: string;
14932
15022
  }
14933
15023
  /**
14934
15024
  * What `runs.start` returns: the run, plus a public run token when the
@@ -16040,6 +16130,8 @@ export interface NetworkError {
16040
16130
  readonly code: "network";
16041
16131
  readonly message: string;
16042
16132
  readonly cause?: unknown;
16133
+ /** Set when the client's own timeout ended the request: that timeout, in milliseconds. */
16134
+ readonly timeoutMs?: number;
16043
16135
  }
16044
16136
  export interface AuthError {
16045
16137
  readonly code: "auth";
package/dist/index.js CHANGED
@@ -2892,7 +2892,157 @@ function subscribeToRun(options) {
2892
2892
  });
2893
2893
  }
2894
2894
 
2895
+ // src/transport.ts
2896
+ var DEFAULT_TIMEOUT_MS = 3e4;
2897
+ var MUTATING = /* @__PURE__ */ new Set([
2898
+ "POST",
2899
+ "PUT",
2900
+ "PATCH",
2901
+ "DELETE"
2902
+ ]);
2903
+ function createTransport(options) {
2904
+ const apiUrl = options.apiUrl.replace(/\/+$/u, "");
2905
+ const fetchImpl = options.fetch ?? fetch;
2906
+ const clientTimeoutMs = checkedTimeoutMs(
2907
+ options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
2908
+ "ClientOptions.timeoutMs"
2909
+ );
2910
+ return {
2911
+ apiUrl,
2912
+ fetchImpl,
2913
+ authHeaders() {
2914
+ return { Authorization: `Bearer ${authTokenFor(options.auth)}` };
2915
+ },
2916
+ async request(input) {
2917
+ const url = buildUrl(apiUrl, input.path, input.query);
2918
+ const headers = buildHeaders(input, options.auth);
2919
+ const timeoutMs = input.timeoutMs === void 0 ? clientTimeoutMs : checkedTimeoutMs(input.timeoutMs, "timeoutMs");
2920
+ const ac = new AbortController();
2921
+ let timedOut = false;
2922
+ const timer = setTimeout(() => {
2923
+ timedOut = true;
2924
+ ac.abort(new Error("timeout"));
2925
+ }, timeoutMs);
2926
+ let response;
2927
+ try {
2928
+ response = await fetchImpl(url, {
2929
+ method: input.method,
2930
+ headers,
2931
+ ...input.body !== void 0 && { body: JSON.stringify(input.body) },
2932
+ signal: ac.signal
2933
+ });
2934
+ } catch (cause) {
2935
+ clearTimeout(timer);
2936
+ const err = timedOut ? {
2937
+ code: "network",
2938
+ message: `No answer within ${seconds(timeoutMs)}, the client's timeout (timeoutMs).`,
2939
+ cause,
2940
+ timeoutMs
2941
+ } : {
2942
+ code: "network",
2943
+ message: cause instanceof Error ? cause.message : "network request failed",
2944
+ cause
2945
+ };
2946
+ throw new KindgiApiError(err);
2947
+ }
2948
+ clearTimeout(timer);
2949
+ if (response.ok) {
2950
+ if (input.discardResponse === true || response.status === 204) {
2951
+ try {
2952
+ await response.arrayBuffer();
2953
+ } catch {
2954
+ }
2955
+ return void 0;
2956
+ }
2957
+ try {
2958
+ return await response.json();
2959
+ } catch (cause) {
2960
+ const err = {
2961
+ code: "network",
2962
+ message: "Response body was not valid JSON",
2963
+ cause
2964
+ };
2965
+ throw new KindgiApiError(err);
2966
+ }
2967
+ }
2968
+ let body;
2969
+ try {
2970
+ body = await response.json();
2971
+ } catch {
2972
+ body = void 0;
2973
+ }
2974
+ throw new KindgiApiError(
2975
+ fromWire(unwrapErrorEnvelope(body, response.status), response.status)
2976
+ );
2977
+ }
2978
+ };
2979
+ }
2980
+ function checkedTimeoutMs(value, name) {
2981
+ if (!Number.isFinite(value) || value <= 0) {
2982
+ throw new TypeError(`${name} must be a positive number of milliseconds. Got ${String(value)}.`);
2983
+ }
2984
+ return value;
2985
+ }
2986
+ function seconds(ms) {
2987
+ return `${ms / 1e3} s`;
2988
+ }
2989
+ function buildUrl(apiUrl, path, query) {
2990
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
2991
+ const base = `${apiUrl}${normalizedPath}`;
2992
+ if (query === void 0) return base;
2993
+ const params = [];
2994
+ for (const key of Object.keys(query)) {
2995
+ const value = query[key];
2996
+ if (value === void 0) continue;
2997
+ const values = typeof value === "object" ? value : [String(value)];
2998
+ for (const v of values) params.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);
2999
+ }
3000
+ return params.length === 0 ? base : `${base}?${params.join("&")}`;
3001
+ }
3002
+ function buildHeaders(input, auth) {
3003
+ const headers = {
3004
+ Accept: "application/json",
3005
+ Authorization: `Bearer ${authTokenFor(auth)}`
3006
+ };
3007
+ if (input.body !== void 0) {
3008
+ headers["Content-Type"] = "application/json; charset=utf-8";
3009
+ }
3010
+ if (input.idempotencyKey !== void 0 && MUTATING.has(input.method)) {
3011
+ headers["Idempotency-Key"] = input.idempotencyKey;
3012
+ }
3013
+ if (input.headers !== void 0) {
3014
+ for (const key of Object.keys(input.headers)) {
3015
+ headers[key] = input.headers[key];
3016
+ }
3017
+ }
3018
+ return headers;
3019
+ }
3020
+ function authTokenFor(auth) {
3021
+ if (auth.kind === "apiToken") return auth.token;
3022
+ return auth.accessToken;
3023
+ }
3024
+ function unwrapErrorEnvelope(body, status) {
3025
+ if (body !== null && typeof body === "object" && !Array.isArray(body)) {
3026
+ const inner = body.error;
3027
+ if (inner !== null && typeof inner === "object" && !Array.isArray(inner)) {
3028
+ return inner;
3029
+ }
3030
+ }
3031
+ return { code: "unknown", message: `HTTP ${status} without recognizable error envelope` };
3032
+ }
3033
+
2895
3034
  // src/resources/runs.ts
3035
+ function waitedStartTimeout(e) {
3036
+ if (!(e instanceof KindgiApiError) || e.error.code !== "network") return e;
3037
+ const { timeoutMs } = e.error;
3038
+ if (timeoutMs === void 0) return e;
3039
+ return new KindgiApiError({
3040
+ code: "network",
3041
+ message: `The run didn't end within ${seconds(timeoutMs)}, the client's timeout (timeoutMs). A waited start answers only when the run ends, so the run may still be going, and its id didn't arrive. Start a run that can take longer with \`options: { wait: false }\`: the answer carries its id at once. Then follow it with \`runs.stream(runId)\` or \`runs.get(runId)\`. Or raise \`timeoutMs\`.`,
3042
+ cause: e.error.cause,
3043
+ timeoutMs
3044
+ });
3045
+ }
2896
3046
  function makeRunsClient(transport) {
2897
3047
  return {
2898
3048
  async start(input) {
@@ -2911,14 +3061,19 @@ function makeRunsClient(transport) {
2911
3061
  input: input.input,
2912
3062
  ...input.options !== void 0 && { options: input.options }
2913
3063
  };
2914
- return transport.request({
2915
- method: "POST",
2916
- path: "/v1/runs",
2917
- body,
2918
- ...input.idempotencyKey !== void 0 && {
2919
- idempotencyKey: input.idempotencyKey
2920
- }
2921
- });
3064
+ try {
3065
+ return await transport.request({
3066
+ method: "POST",
3067
+ path: "/v1/runs",
3068
+ body,
3069
+ ...input.idempotencyKey !== void 0 && {
3070
+ idempotencyKey: input.idempotencyKey
3071
+ },
3072
+ ...input.timeoutMs !== void 0 && { timeoutMs: input.timeoutMs }
3073
+ });
3074
+ } catch (e) {
3075
+ throw input.options?.wait === false ? e : waitedStartTimeout(e);
3076
+ }
2922
3077
  },
2923
3078
  async dryRun(_input) {
2924
3079
  throw new KindgiApiError(
@@ -4048,127 +4203,6 @@ function makeWebhooksClient(transport) {
4048
4203
  };
4049
4204
  }
4050
4205
 
4051
- // src/transport.ts
4052
- var DEFAULT_TIMEOUT_MS = 3e4;
4053
- var MUTATING = /* @__PURE__ */ new Set([
4054
- "POST",
4055
- "PUT",
4056
- "PATCH",
4057
- "DELETE"
4058
- ]);
4059
- function createTransport(options) {
4060
- const apiUrl = options.apiUrl.replace(/\/+$/u, "");
4061
- const fetchImpl = options.fetch ?? fetch;
4062
- const clientTimeoutMs = DEFAULT_TIMEOUT_MS;
4063
- return {
4064
- apiUrl,
4065
- fetchImpl,
4066
- authHeaders() {
4067
- return { Authorization: `Bearer ${authTokenFor(options.auth)}` };
4068
- },
4069
- async request(input) {
4070
- const url = buildUrl(apiUrl, input.path, input.query);
4071
- const headers = buildHeaders(input, options.auth);
4072
- const timeoutMs = input.timeoutMs ?? clientTimeoutMs;
4073
- const ac = new AbortController();
4074
- const timer = setTimeout(
4075
- () => ac.abort(new Error("timeout")),
4076
- timeoutMs
4077
- );
4078
- let response;
4079
- try {
4080
- response = await fetchImpl(url, {
4081
- method: input.method,
4082
- headers,
4083
- ...input.body !== void 0 && { body: JSON.stringify(input.body) },
4084
- signal: ac.signal
4085
- });
4086
- } catch (cause) {
4087
- clearTimeout(timer);
4088
- const err = {
4089
- code: "network",
4090
- message: cause instanceof Error ? cause.message : "network request failed",
4091
- cause
4092
- };
4093
- throw new KindgiApiError(err);
4094
- }
4095
- clearTimeout(timer);
4096
- if (response.ok) {
4097
- if (input.discardResponse === true || response.status === 204) {
4098
- try {
4099
- await response.arrayBuffer();
4100
- } catch {
4101
- }
4102
- return void 0;
4103
- }
4104
- try {
4105
- return await response.json();
4106
- } catch (cause) {
4107
- const err = {
4108
- code: "network",
4109
- message: "Response body was not valid JSON",
4110
- cause
4111
- };
4112
- throw new KindgiApiError(err);
4113
- }
4114
- }
4115
- let body;
4116
- try {
4117
- body = await response.json();
4118
- } catch {
4119
- body = void 0;
4120
- }
4121
- throw new KindgiApiError(
4122
- fromWire(unwrapErrorEnvelope(body, response.status), response.status)
4123
- );
4124
- }
4125
- };
4126
- }
4127
- function buildUrl(apiUrl, path, query) {
4128
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
4129
- const base = `${apiUrl}${normalizedPath}`;
4130
- if (query === void 0) return base;
4131
- const params = [];
4132
- for (const key of Object.keys(query)) {
4133
- const value = query[key];
4134
- if (value === void 0) continue;
4135
- const values = typeof value === "object" ? value : [String(value)];
4136
- for (const v of values) params.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);
4137
- }
4138
- return params.length === 0 ? base : `${base}?${params.join("&")}`;
4139
- }
4140
- function buildHeaders(input, auth) {
4141
- const headers = {
4142
- Accept: "application/json",
4143
- Authorization: `Bearer ${authTokenFor(auth)}`
4144
- };
4145
- if (input.body !== void 0) {
4146
- headers["Content-Type"] = "application/json; charset=utf-8";
4147
- }
4148
- if (input.idempotencyKey !== void 0 && MUTATING.has(input.method)) {
4149
- headers["Idempotency-Key"] = input.idempotencyKey;
4150
- }
4151
- if (input.headers !== void 0) {
4152
- for (const key of Object.keys(input.headers)) {
4153
- headers[key] = input.headers[key];
4154
- }
4155
- }
4156
- return headers;
4157
- }
4158
- function authTokenFor(auth) {
4159
- if (auth.kind === "apiToken") return auth.token;
4160
- return auth.accessToken;
4161
- }
4162
- function unwrapErrorEnvelope(body, status) {
4163
- if (body !== null && typeof body === "object" && !Array.isArray(body)) {
4164
- const inner = body.error;
4165
- if (inner !== null && typeof inner === "object" && !Array.isArray(inner)) {
4166
- return inner;
4167
- }
4168
- }
4169
- return { code: "unknown", message: `HTTP ${status} without recognizable error envelope` };
4170
- }
4171
-
4172
4206
  // src/client.ts
4173
4207
  function createClient(options) {
4174
4208
  const transport = createTransport(options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kindgi/client",
3
- "version": "0.1.4-rc.4",
3
+ "version": "0.1.4",
4
4
  "description": "TypeScript client SDK for Kindgi™ — the sovereign AI OS. Preview: wire-generated from openapi.json via typed-openapi, ergonomic hand-authored resource clients (Transport, KindgiApiError, SSE with Last-Event-Id resume).",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -45,12 +45,12 @@
45
45
  "zod": "^4.6.5"
46
46
  },
47
47
  "devDependencies": {
48
- "@kindgi/agents": "0.1.4-rc.4",
49
- "@kindgi/api": "0.1.4-rc.4",
50
- "@kindgi/flow": "0.1.4-rc.4",
51
- "@kindgi/platform": "0.1.4-rc.4",
52
- "@kindgi/runtime": "0.1.4-rc.4",
53
- "@kindgi/types": "0.1.4-rc.4",
48
+ "@kindgi/agents": "0.1.4",
49
+ "@kindgi/api": "0.1.4",
50
+ "@kindgi/flow": "0.1.4",
51
+ "@kindgi/platform": "0.1.4",
52
+ "@kindgi/runtime": "0.1.4",
53
+ "@kindgi/types": "0.1.4",
54
54
  "@types/node": "^22.10.5",
55
55
  "dts-bundle-generator": "^9.5.1",
56
56
  "tsup": "^8.5.1",