langwatch 1.1.0 → 1.2.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.
Files changed (56) hide show
  1. package/README.md +33 -0
  2. package/dist/{chunk-TKSTXX3D.js → chunk-CLTKABMO.js} +52 -2
  3. package/dist/chunk-CLTKABMO.js.map +1 -0
  4. package/dist/{chunk-L5KBRKHS.mjs → chunk-CMZFFKLA.mjs} +51 -1
  5. package/dist/{chunk-L5KBRKHS.mjs.map → chunk-CMZFFKLA.mjs.map} +1 -1
  6. package/dist/{chunk-Z7RP3LP5.js → chunk-DTSULVK5.js} +39 -19
  7. package/dist/chunk-DTSULVK5.js.map +1 -0
  8. package/dist/{chunk-5AGWTUI2.mjs → chunk-JYTJEAOU.mjs} +3 -3
  9. package/dist/chunk-JYTJEAOU.mjs.map +1 -0
  10. package/dist/chunk-K6KPNTQO.js +15624 -0
  11. package/dist/chunk-K6KPNTQO.js.map +1 -0
  12. package/dist/{chunk-2O4ILSP5.mjs → chunk-LTDUROCE.mjs} +2 -2
  13. package/dist/{chunk-EW233MAD.mjs → chunk-PDNXHBSL.mjs} +26 -6
  14. package/dist/chunk-PDNXHBSL.mjs.map +1 -0
  15. package/dist/chunk-SYJIEBJY.mjs +15624 -0
  16. package/dist/chunk-SYJIEBJY.mjs.map +1 -0
  17. package/dist/{chunk-R7NIGAEB.js → chunk-UOFSG6R4.js} +19 -19
  18. package/dist/chunk-UOFSG6R4.js.map +1 -0
  19. package/dist/{chunk-IUSLT65Z.js → chunk-ZTOXEWNX.js} +2 -2
  20. package/dist/chunk-ZTOXEWNX.js.map +1 -0
  21. package/dist/cli/bundle.js +263 -195
  22. package/dist/{implementation-DmWrukzX.d.mts → implementation-CHXrVq_q.d.mts} +1 -1
  23. package/dist/{implementation-Psro9xt4.d.ts → implementation-D_v0fUvU.d.ts} +1 -1
  24. package/dist/index.d.mts +1103 -205
  25. package/dist/index.d.ts +1103 -205
  26. package/dist/index.js +1240 -328
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +1171 -259
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/observability-sdk/index.d.mts +3 -3
  31. package/dist/observability-sdk/index.d.ts +3 -3
  32. package/dist/observability-sdk/index.js +5 -5
  33. package/dist/observability-sdk/index.js.map +1 -1
  34. package/dist/observability-sdk/index.mjs +4 -4
  35. package/dist/observability-sdk/instrumentation/langchain/index.d.mts +1 -1
  36. package/dist/observability-sdk/instrumentation/langchain/index.d.ts +1 -1
  37. package/dist/observability-sdk/instrumentation/langchain/index.js +18 -18
  38. package/dist/observability-sdk/instrumentation/langchain/index.js.map +1 -1
  39. package/dist/observability-sdk/instrumentation/langchain/index.mjs +2 -2
  40. package/dist/observability-sdk/setup/node/index.js +4 -4
  41. package/dist/observability-sdk/setup/node/index.js.map +1 -1
  42. package/dist/observability-sdk/setup/node/index.mjs +3 -3
  43. package/dist/{types-Ck1U3XCH.d.mts → types-DlP7QdqU.d.mts} +14811 -6210
  44. package/dist/{types-DGBGlP9B.d.ts → types-av2kmt_i.d.ts} +14811 -6210
  45. package/package.json +9 -10
  46. package/dist/chunk-5AGWTUI2.mjs.map +0 -1
  47. package/dist/chunk-EW233MAD.mjs.map +0 -1
  48. package/dist/chunk-IUSLT65Z.js.map +0 -1
  49. package/dist/chunk-PYODMDPV.mjs +0 -1005
  50. package/dist/chunk-PYODMDPV.mjs.map +0 -1
  51. package/dist/chunk-R7NIGAEB.js.map +0 -1
  52. package/dist/chunk-SCLFEMNK.js +0 -1005
  53. package/dist/chunk-SCLFEMNK.js.map +0 -1
  54. package/dist/chunk-TKSTXX3D.js.map +0 -1
  55. package/dist/chunk-Z7RP3LP5.js.map +0 -1
  56. /package/dist/{chunk-2O4ILSP5.mjs.map → chunk-LTDUROCE.mjs.map} +0 -0
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { L as Logger, C as ConsoleLogger, N as NoOpLogger } from './index-D7rKIGrO.js';
2
- export { F as FilterableBatchSpanProcessor, L as LangWatchExporter, S as SpanProcessingExcludeRule, g as getLangWatchLogger, a as getLangWatchTracer } from './implementation-Psro9xt4.js';
2
+ export { F as FilterableBatchSpanProcessor, L as LangWatchExporter, S as SpanProcessingExcludeRule, g as getLangWatchLogger, a as getLangWatchTracer } from './implementation-D_v0fUvU.js';
3
3
  import { z } from 'zod';
4
- import { p as paths, P as PromptResponse, C as CreatePromptBody, U as UpdatePromptBody, T as TagDefinition, a as CreatedTag, o as operations, b as PromptData, F as FetchPolicy, c as Prompt, L as LangWatchSpan, d as components } from './types-DGBGlP9B.js';
4
+ import { p as paths, P as PromptResponse, C as CreatePromptBody, U as UpdatePromptBody, T as TagDefinition, a as CreatedTag, o as operations, b as PromptData, F as FetchPolicy, c as Prompt, L as LangWatchSpan, d as components } from './types-av2kmt_i.js';
5
5
  import openApiCreateClient from 'openapi-fetch';
6
6
  export { l as attributes } from './types-VOZv9LYO.js';
7
7
  import { CliHandledErrorReason, CliHandledError } from '@langwatch/langy/cards/handled-error';
@@ -28,7 +28,7 @@ declare const localPromptConfigSchema: z.ZodObject<{
28
28
  }>;
29
29
  content: z.ZodString;
30
30
  }, z.core.$loose>>;
31
- parameters: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
31
+ parameters: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>>>;
32
32
  }, z.core.$loose>;
33
33
  type LocalPromptConfig = z.infer<typeof localPromptConfigSchema>;
34
34
 
@@ -39,7 +39,16 @@ type PromptDependency = string | {
39
39
  type PromptsConfig = {
40
40
  prompts: Record<string, PromptDependency>;
41
41
  };
42
- type RuntimeParameters = Record<string, unknown>;
42
+ /**
43
+ * A JSON value: what runtime parameters actually persist and what the API
44
+ * schema declares (the spec's recursive JsonValue component). Structurally
45
+ * identical to the generated client's RecursiveJsonValue, so values flow
46
+ * between hand-written and generated types without casts.
47
+ */
48
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
49
+ [key: string]: JsonValue;
50
+ };
51
+ type RuntimeParameters = Record<string, JsonValue>;
43
52
  type MaterializedPrompt = {
44
53
  id: string;
45
54
  name: string;
@@ -2064,184 +2073,69 @@ declare class SecretsApiService {
2064
2073
  delete(id: string): Promise<SecretDeleteResponse>;
2065
2074
  }
2066
2075
 
2067
- interface GetTraceParams {
2068
- includeSpans?: boolean;
2069
- }
2070
- type GetTraceResponse = NonNullable<paths["/api/trace/{id}"]["get"]["responses"]["200"]["content"]["application/json"]>;
2071
-
2072
- declare class TracesFacade {
2073
- #private;
2074
- constructor(config: InternalConfig);
2075
- get(traceId: string, params?: GetTraceParams): Promise<GetTraceResponse>;
2076
- }
2077
-
2078
- interface LangWatchConstructorOptions {
2079
- apiKey?: string;
2080
- endpoint?: string;
2081
- options?: {
2082
- logger?: Logger;
2083
- };
2084
- }
2085
- declare class LangWatch {
2086
- #private;
2087
- private readonly config;
2088
- readonly prompts: PromptsFacade;
2089
- readonly traces: TracesFacade;
2090
- readonly datasets: DatasetsFacade;
2091
- /**
2092
- * Run experiments on LangWatch platform or via SDK.
2093
- *
2094
- * Platform experiments (CI/CD):
2095
- * ```typescript
2096
- * const result = await langwatch.experiments.run("my-experiment-slug");
2097
- * result.printSummary();
2098
- * ```
2099
- *
2100
- * SDK-defined experiments:
2101
- * ```typescript
2102
- * const experiment = await langwatch.experiments.init("my-experiment");
2103
- * // ... run evaluators using experiment.evaluate()
2104
- * ```
2105
- */
2106
- readonly experiments: ExperimentsFacade;
2107
- /**
2108
- * Run evaluators and guardrails in real-time (Online Evaluations).
2109
- *
2110
- * @example
2111
- * ```typescript
2112
- * const guardrail = await langwatch.evaluations.evaluate("presidio/pii_detection", {
2113
- * data: { input: userInput, output: generatedResponse },
2114
- * name: "PII Detection",
2115
- * asGuardrail: true,
2116
- * });
2117
- *
2118
- * if (!guardrail.passed) {
2119
- * return "I'm sorry, I can't do that.";
2120
- * }
2121
- * ```
2122
- */
2123
- readonly evaluations: EvaluationsFacade;
2124
- readonly evaluators: EvaluatorsApiService;
2125
- readonly scenarios: ScenariosApiService;
2126
- readonly suites: SuitesApiService;
2127
- readonly workflows: WorkflowsApiService;
2128
- readonly agents: AgentsApiService;
2129
- readonly annotations: AnnotationsApiService;
2130
- readonly dashboards: DashboardsApiService;
2131
- readonly modelProviders: ModelProvidersApiService;
2132
- readonly analytics: AnalyticsApiService;
2133
- readonly triggers: TriggersApiService;
2134
- readonly graphs: GraphsApiService;
2135
- readonly simulationRuns: SimulationRunsApiService;
2136
- readonly monitors: MonitorsApiService;
2137
- readonly secrets: SecretsApiService;
2138
- constructor(options?: LangWatchConstructorOptions);
2139
- get apiClient(): LangwatchApiClient;
2140
- }
2141
-
2142
2076
  /**
2143
- * A failure the platform NAMED.
2144
- *
2145
- * The API does not merely fail — when it declines a request it says precisely
2146
- * why, as a `HandledError` with a serialisable `kind` (`dataset_not_found`,
2147
- * `validation_error`), the HTTP status it answers with, and a `meta` bag of the
2148
- * context that makes the failure actionable. Until now the SDK collapsed all of
2149
- * that into an English sentence on a generic error, so a caller could read the
2150
- * failure but never react to it: a 404 "dataset not found" — a fact you can
2151
- * offer to fix — was indistinguishable from a 500.
2152
- *
2153
- * This is that structure, kept. Narrow with {@link isLangWatchHandledError} (or
2154
- * `instanceof`) and switch on `code`; `body` is the escape hatch to whatever the
2155
- * platform sent that this class did not model.
2077
+ * The per-call options every mutating call on the billing surfaces takes.
2156
2078
  *
2157
- * ```ts
2158
- * try {
2159
- * await langwatch.datasets.get("nope");
2160
- * } catch (error) {
2161
- * if (isLangWatchHandledError(error) && error.code === "dataset_not_found") {
2162
- * // Actionable: we know WHAT was not found, and can offer the list.
2163
- * console.error(error.meta.id, error.traceId);
2164
- * }
2165
- * throw error;
2166
- * }
2167
- * ```
2079
+ * WHERE THEY GO. A call whose arguments already ride in an options bag
2080
+ * (`disable(id, { reason })`, `reset(id, { endUserId })`) gains these fields in
2081
+ * that same bag: one bag per call is what a caller expects. A call that takes a
2082
+ * request BODY (`create(input)`, `update(id, input)`) gets a separate trailing
2083
+ * parameter instead, because those body types mirror the wire verbatim and must
2084
+ * not grow keys the wire has never heard of.
2168
2085
  *
2169
- * ONLY raised for a failure the platform named. An infrastructure failure — a
2170
- * 5xx, a dead socket, a proxy's HTML error page — still raises the generic
2171
- * service error it always did, because presenting one of those as a domain
2172
- * error would blame the user for our outage.
2086
+ * They are an interface rather than a bare `signal` so that the next thing a
2087
+ * call needs per invocation is an added field rather than an added parameter.
2173
2088
  */
2174
- declare class LangWatchHandledError extends Error {
2089
+ /** The request header the control plane deduplicates creates on. */
2090
+ declare const IDEMPOTENCY_KEY_HEADER = "Idempotency-Key";
2091
+ /**
2092
+ * The response header a replayed create carries. Only ever `"true"`, and
2093
+ * ABSENT rather than false on a first execution, so its presence is the whole
2094
+ * signal.
2095
+ */
2096
+ declare const IDEMPOTENT_REPLAY_HEADER = "X-Idempotent-Replay";
2097
+ interface MutationOptions {
2175
2098
  /**
2176
- * The discriminant. A boolean brand rather than `instanceof` alone because a
2177
- * bundled CLI and a consumer's `node_modules` copy of the SDK can hold two
2178
- * different copies of this class, and `instanceof` is false across that seam —
2179
- * the same reason the platform's own error handler tests for `code` rather
2180
- * than class identity.
2099
+ * Cancel the call. Without one, the request is bounded by the SDK's own
2100
+ * 30 second timeout so a hung control plane fails rather than freezes.
2181
2101
  */
2182
- readonly isLangWatchHandledError: true;
2183
- /** The platform's serialisable discriminant, e.g. `dataset_not_found`. */
2184
- readonly code: string;
2102
+ signal?: AbortSignal;
2103
+ }
2104
+ interface IdempotentCreateOptions extends MutationOptions {
2185
2105
  /**
2186
- * @deprecated Back-compat alias of `code`, kept while the platform's
2187
- * `DomainError` → `HandledError` rename rolls out. Read `code` in new code.
2106
+ * Makes the create safe to retry. A dropped connection after the write but
2107
+ * before the response looks exactly like a dropped request, and sending it
2108
+ * again without a key mints a SECOND resource. Send the same key on the
2109
+ * retry and the server answers with the first response instead, byte for
2110
+ * byte, including the one-time secret a create hands back.
2111
+ *
2112
+ * Any string of 8 to 255 characters; a UUID minted per logical create is the
2113
+ * usual choice. Receipts answer for 24 hours, and only successful creates
2114
+ * leave one, so a create that failed is safe to run again either way.
2115
+ *
2116
+ * Reusing a key with a DIFFERENT body is refused with `idempotency_error`
2117
+ * rather than quietly answering for the wrong request.
2188
2118
  */
2189
- readonly kind: string;
2190
- /** The status the platform answered with. */
2191
- readonly httpStatus: number;
2192
- /** The context the platform attached: ids, field errors — whatever makes it actionable. */
2193
- readonly meta: Record<string, unknown>;
2194
- /** The OTel trace to quote at support. Absent unless the route sent one. */
2195
- readonly traceId: string | undefined;
2196
- /** A clickable link to that trace, when the route sent one. */
2197
- readonly traceUrl: string | undefined;
2198
- /** A clickable link to the logs for that trace, when the route sent one. */
2199
- readonly logsUrl: string | undefined;
2200
- /** The failure behind the failure, when the route sent the chain. */
2201
- readonly reasons: CliHandledErrorReason[] | undefined;
2202
- /** What the user can DO about it, when the platform sent next steps. */
2203
- readonly suggestions: string[] | undefined;
2204
- /** The docs page that explains the failure, when the platform sent one. */
2205
- readonly docUrl: string | undefined;
2206
- /** The raw response body, verbatim — the escape hatch for anything unmodelled. */
2207
- readonly body: unknown;
2208
- /** What the SDK was doing, e.g. `get dataset "abc"`. */
2209
- readonly operation: string | undefined;
2119
+ idempotencyKey?: string;
2210
2120
  /**
2211
- * Alias of {@link httpStatus}, and the raw body again under the name the
2212
- * per-service `*ApiError` classes use.
2121
+ * Called when the response came from a receipt rather than a fresh write,
2122
+ * i.e. this exact create had already succeeded.
2213
2123
  *
2214
- * Not redundancy for its own sake: this class is thrown from the SAME code
2215
- * path that used to throw `TracesApiError` & friends, so anything that reads
2216
- * `.status` or `.originalError` off a caught SDK error — including the CLI's
2217
- * own telemetry reader — keeps working unchanged.
2124
+ * A hook rather than a field on the returned resource: the resource is
2125
+ * identical either way, so nothing about handling it changes, and the
2126
+ * distinction is something a caller logs rather than branches on. Keeping it
2127
+ * off the return type also keeps the wire-shaped entities free of fields the
2128
+ * wire does not have.
2218
2129
  */
2219
- readonly status: number;
2220
- readonly originalError: unknown;
2221
- constructor({ handled, body, operation, message, }: {
2222
- handled: CliHandledError;
2223
- body: unknown;
2224
- operation?: string;
2225
- message: string;
2226
- });
2227
- }
2228
- /** Narrows any caught value to a {@link LangWatchHandledError}. */
2229
- declare const isLangWatchHandledError: (error: unknown) => error is LangWatchHandledError;
2230
- declare class LangWatchApiError extends Error {
2231
- readonly httpStatus: number;
2232
- readonly httpStatusText: string;
2233
- apiError: string | undefined;
2234
- body: unknown;
2235
- constructor(message: string, response: Response);
2236
- safeParseBody(response: Response): Promise<void>;
2130
+ onIdempotentReplay?: () => void;
2237
2131
  }
2238
2132
 
2239
- type VirtualKeyScopeType = "ORGANIZATION" | "TEAM" | "PROJECT";
2133
+ type VirtualKeyScopeType = "organization" | "team" | "project";
2240
2134
  interface VirtualKeyScope {
2241
2135
  scope_type: VirtualKeyScopeType;
2242
2136
  scope_id: string;
2243
2137
  }
2244
- type VirtualKeyRoutingMode = "NONE" | "FALLBACK_ALL" | "POLICY";
2138
+ type VirtualKeyRoutingMode = "none" | "fallback_all" | "policy";
2245
2139
  /**
2246
2140
  * The snake DTO the server returns (`toVirtualKeySnakeDto`). The token
2247
2141
  * format is `vk-lw-<ulid>` with no live/test discriminator; the gateway
@@ -2252,7 +2146,8 @@ interface VirtualKey {
2252
2146
  organization_id: string;
2253
2147
  name: string;
2254
2148
  description: string | null;
2255
- status: "active" | "revoked";
2149
+ /** `disabled` is the reversible stop; `revoked` is terminal. */
2150
+ status: "active" | "disabled" | "revoked";
2256
2151
  /** "langy" marks a product-managed key; customers can only mint "user". */
2257
2152
  purpose: "user" | "langy";
2258
2153
  /** e.g. "vk-lw-01HZX9" — the only secret material kept after creation. */
@@ -2280,8 +2175,8 @@ interface VirtualKey {
2280
2175
  */
2281
2176
  interface VirtualKeyBudgetInput {
2282
2177
  limit_usd: string | number;
2283
- window: "DAY" | "WEEK" | "MONTH";
2284
- on_breach?: "BLOCK" | "WARN";
2178
+ window: "day" | "week" | "month";
2179
+ on_breach?: "block" | "warn";
2285
2180
  name?: string;
2286
2181
  }
2287
2182
  interface CreateVirtualKeyInput {
@@ -2300,6 +2195,18 @@ interface CreateVirtualKeyInput {
2300
2195
  /** Optional cap created atomically with the key. */
2301
2196
  budget?: VirtualKeyBudgetInput | null;
2302
2197
  config?: Record<string, unknown>;
2198
+ /**
2199
+ * Your own identifier for this key, unique within the organization. Lets
2200
+ * you look the key up by the id your system already has instead of storing
2201
+ * ours alongside it.
2202
+ */
2203
+ external_id?: string | null;
2204
+ /**
2205
+ * Free-form string labels, up to 40 of them. Sent WHOLE on an update: the
2206
+ * map you pass replaces the stored one rather than merging into it, and
2207
+ * `{}` clears it.
2208
+ */
2209
+ metadata?: Record<string, string>;
2303
2210
  }
2304
2211
  interface UpdateVirtualKeyInput {
2305
2212
  name?: string;
@@ -2311,19 +2218,43 @@ interface UpdateVirtualKeyInput {
2311
2218
  /** Undefined leaves the cap alone; a value upserts it; null archives it. */
2312
2219
  budget?: VirtualKeyBudgetInput | null;
2313
2220
  config?: Record<string, unknown>;
2221
+ /**
2222
+ * Your own identifier for this key, unique within the organization. Lets
2223
+ * you look the key up by the id your system already has instead of storing
2224
+ * ours alongside it.
2225
+ */
2226
+ external_id?: string | null;
2227
+ /**
2228
+ * Free-form string labels, up to 40 of them. Sent WHOLE on an update: the
2229
+ * map you pass replaces the stored one rather than merging into it, and
2230
+ * `{}` clears it.
2231
+ */
2232
+ metadata?: Record<string, string>;
2314
2233
  }
2315
2234
  interface VirtualKeyWithSecret {
2316
2235
  virtual_key: VirtualKey;
2317
2236
  secret: string;
2318
2237
  }
2238
+ /** One page of the virtual-key listing, exactly as the wire serves it. */
2239
+ interface VirtualKeyPage {
2240
+ data: VirtualKey[];
2241
+ /**
2242
+ * Pass back as `cursor` for the next page. Null means the walk is
2243
+ * exhausted. Neither page length tells you anything here: visibility is
2244
+ * applied to each page AFTER it is read, so a page can hold fewer rows
2245
+ * than `limit` with more still to come.
2246
+ */
2247
+ next_cursor: string | null;
2248
+ }
2319
2249
  /** Aggregate spend for one key over a window, from the cost path. */
2320
2250
  interface VirtualKeySpendSummary {
2321
2251
  virtual_key_id: string;
2322
2252
  spent_usd: string;
2323
2253
  requests: number;
2254
+ /** Epoch milliseconds, the unit every spend surface takes and returns. */
2324
2255
  window: {
2325
- from: string;
2326
- to: string;
2256
+ from: number;
2257
+ to: number;
2327
2258
  };
2328
2259
  }
2329
2260
  declare class VirtualKeysApiError extends Error {
@@ -2331,35 +2262,102 @@ declare class VirtualKeysApiError extends Error {
2331
2262
  readonly originalError?: unknown | undefined;
2332
2263
  constructor(message: string, operation: string, originalError?: unknown | undefined);
2333
2264
  }
2265
+ /**
2266
+ * Client for the gateway virtual-key surface (/api/gateway/v1).
2267
+ *
2268
+ * Entity types and the create/update bodies mirror the wire verbatim, so
2269
+ * their fields are lowercase snake_case. Call options this SDK invents (query
2270
+ * filters, per-call behaviour, action arguments) are camelCase like the rest
2271
+ * of the SDK.
2272
+ */
2334
2273
  declare class VirtualKeysApiService {
2335
2274
  private readonly endpoint;
2336
2275
  private readonly apiKey;
2276
+ private readonly projectId;
2337
2277
  constructor(config?: {
2338
2278
  endpoint?: string;
2339
2279
  apiKey?: string;
2280
+ projectId?: string;
2340
2281
  });
2341
2282
  private headers;
2342
2283
  private request;
2343
- list(): Promise<VirtualKey[]>;
2284
+ /**
2285
+ * ONE page of the virtual keys visible to the caller, newest first. Pass
2286
+ * `next_cursor` back as `cursor` for the next page, verbatim: a cursor this
2287
+ * endpoint did not issue answers 400 rather than restarting the walk.
2288
+ *
2289
+ * `limit` is the page size (server default 50, capped at 200), and it caps
2290
+ * the rows READ, not the rows returned: the visibility filter runs on the
2291
+ * page afterwards. Prefer `list()` unless you mean to page deliberately.
2292
+ */
2293
+ listPage(options?: {
2294
+ cursor?: string;
2295
+ limit?: number;
2296
+ /** Exact match on your own identifier, not a prefix or a search. */
2297
+ externalId?: string;
2298
+ }): Promise<VirtualKeyPage>;
2299
+ /**
2300
+ * Every virtual key visible to the caller: keys scoped to this project, to
2301
+ * its team, or to the whole organization.
2302
+ *
2303
+ * The endpoint pages; this follows `next_cursor` until it comes back null.
2304
+ * Stopping on a short page would be wrong here specifically, because the
2305
+ * server filters each page for visibility after reading it, so a page can
2306
+ * hold fewer rows than the limit with more still to come.
2307
+ *
2308
+ * `limit` sizes each request in the walk, it does NOT cap what comes back.
2309
+ * `cursor` resumes an interrupted walk. Take a single page with
2310
+ * `listPage()`, or stream the walk with `iterate()`.
2311
+ */
2312
+ list(options?: {
2313
+ cursor?: string;
2314
+ limit?: number;
2315
+ /** Exact match on your own identifier, not a prefix or a search. */
2316
+ externalId?: string;
2317
+ }): Promise<VirtualKey[]>;
2318
+ /**
2319
+ * Every visible virtual key, one row at a time, fetching each page only
2320
+ * when the consumer reaches it. Stop early and the rest is never read,
2321
+ * which `list()` cannot offer because it materialises the whole listing
2322
+ * first. Raises rather than looping forever on a cursor chain that never
2323
+ * ends, exactly like `list()`.
2324
+ */
2325
+ iterate(options?: {
2326
+ cursor?: string;
2327
+ limit?: number;
2328
+ /** Exact match on your own identifier, not a prefix or a search. */
2329
+ externalId?: string;
2330
+ }): AsyncGenerator<VirtualKey>;
2344
2331
  get(id: string): Promise<VirtualKey>;
2345
- create(input: CreateVirtualKeyInput): Promise<VirtualKeyWithSecret>;
2346
- update(id: string, input: UpdateVirtualKeyInput): Promise<VirtualKey>;
2347
- rotate(id: string): Promise<VirtualKeyWithSecret>;
2348
- revoke(id: string): Promise<VirtualKey>;
2349
- /**
2350
- * Aggregate spend for one key. Defaults to the current UTC calendar
2351
- * month server-side. Reads the same cost path the dashboard reads, so
2352
- * this number and the UI agree by construction.
2353
- */
2354
- spend(id: string, window?: {
2355
- from?: string;
2356
- to?: string;
2332
+ /**
2333
+ * Mint a key. The response carries the secret ONCE; nothing ever serves it
2334
+ * again, so a create that times out is recovered with `idempotencyKey`
2335
+ * rather than by listing.
2336
+ */
2337
+ create(input: CreateVirtualKeyInput, options?: IdempotentCreateOptions): Promise<VirtualKeyWithSecret>;
2338
+ update(id: string, input: UpdateVirtualKeyInput, options?: MutationOptions): Promise<VirtualKey>;
2339
+ rotate(id: string, options?: MutationOptions): Promise<VirtualKeyWithSecret>;
2340
+ revoke(id: string, options?: MutationOptions): Promise<VirtualKey>;
2341
+ /** Reversible stop; enable() restores the key exactly as it was. */
2342
+ disable(id: string, options?: {
2343
+ reason?: string;
2344
+ } & MutationOptions): Promise<VirtualKey>;
2345
+ enable(id: string, options?: MutationOptions): Promise<VirtualKey>;
2346
+ /**
2347
+ * Aggregate spend for one key over a window in epoch milliseconds.
2348
+ * Defaults to the current UTC calendar month server-side. Reads the same
2349
+ * cost path the dashboard reads, so this number and the UI agree by
2350
+ * construction.
2351
+ */
2352
+ spend(id: string, options?: {
2353
+ from?: number;
2354
+ to?: number;
2357
2355
  }): Promise<VirtualKeySpendSummary>;
2358
2356
  }
2359
2357
 
2360
- type BudgetScopeKind = "ORGANIZATION" | "TEAM" | "PROJECT" | "VIRTUAL_KEY" | "PRINCIPAL" | "GROUP";
2361
- type BudgetWindow = "MINUTE" | "HOUR" | "DAY" | "WEEK" | "MONTH" | "TOTAL";
2362
- type BudgetOnBreach = "BLOCK" | "WARN";
2358
+ type BudgetScopeKind = "organization" | "team" | "project" | "virtual_key" | "principal" | "group" | "attributed_user";
2359
+ type BudgetWindow = "minute" | "hour" | "day" | "week" | "month" | "total" | "manual";
2360
+ type BudgetOnBreach = "block" | "warn";
2363
2361
  interface GatewayBudget {
2364
2362
  id: string;
2365
2363
  organization_id: string;
@@ -2370,49 +2368,82 @@ interface GatewayBudget {
2370
2368
  window: BudgetWindow;
2371
2369
  on_breach: BudgetOnBreach;
2372
2370
  /**
2373
- * For GROUP rows this is the PER-MEMBER allowance, not a group total;
2371
+ * For `group` rows this is the PER-MEMBER allowance, not a group total;
2374
2372
  * `spent_usd` sums the whole group and `member_count` says how many
2375
- * members the allowance currently covers.
2373
+ * members the allowance currently covers. For `attributed_user` rows it is
2374
+ * the PER-PERSON cap, and `end_users_seen` / `end_users_over` carry the
2375
+ * standing instead of `spent_usd`.
2376
2376
  */
2377
2377
  limit_usd: string;
2378
- spent_usd: string;
2378
+ /** Canonical integer limit, nano-USD. Null past the safe integer range. */
2379
+ limit_nano_usd: number | null;
2380
+ /**
2381
+ * Display value. NULL when `spend_available` is false: spend could not be
2382
+ * totalled, so there is no figure, and the API sends null rather than a
2383
+ * stale one a caller could mistake for real money.
2384
+ */
2385
+ spent_usd: string | null;
2386
+ /** Canonical integer spend, nano-USD. Null whenever `spent_usd` is. */
2387
+ spent_nano_usd: number | null;
2379
2388
  timezone: string | null;
2380
2389
  /** ModelProvider id the budget counts; null counts every provider. */
2381
2390
  provider_key: string | null;
2382
2391
  current_period_started_at: string;
2383
2392
  resets_at: string;
2393
+ /** Instant the cycle is phased from; null means calendar aligned. */
2394
+ cycle_anchor_at: string | null;
2384
2395
  last_reset_at: string | null;
2385
2396
  archived_at: string | null;
2386
2397
  created_at: string;
2387
- /** GROUP rows only. */
2398
+ /** `group` rows only. */
2388
2399
  member_count?: number;
2400
+ /** `attributed_user` rows only: end users with spend this period. */
2401
+ end_users_seen?: number;
2402
+ /** `attributed_user` rows only: how many of those are at or over the cap. */
2403
+ end_users_over?: number;
2389
2404
  }
2390
- interface GatewayBudgetList {
2391
- budgets: GatewayBudget[];
2405
+ /**
2406
+ * One page of the budget listing, exactly as the wire serves it.
2407
+ *
2408
+ * Budgets come back in an envelope where virtual keys come back as a bare
2409
+ * array because `spend_available` is a correctness flag about the whole page,
2410
+ * and an array cannot carry it.
2411
+ */
2412
+ interface GatewayBudgetPage {
2413
+ data: GatewayBudget[];
2392
2414
  /**
2393
- * False when spend could not be totalled — render "unavailable" rather
2415
+ * False when spend could not be totalled: render "unavailable" rather
2394
2416
  * than trusting `spent_usd` as real spend.
2395
2417
  */
2396
2418
  spend_available: boolean;
2419
+ /**
2420
+ * Pass back as `cursor` for the next page. Null means the walk is
2421
+ * exhausted; a FULL page does not by itself mean there is more.
2422
+ */
2423
+ next_cursor: string | null;
2397
2424
  }
2398
2425
  type CreateGatewayBudgetScope = {
2399
- kind: "ORGANIZATION";
2426
+ kind: "organization";
2400
2427
  organization_id: string;
2401
2428
  } | {
2402
- kind: "TEAM";
2429
+ kind: "team";
2403
2430
  team_id: string;
2404
2431
  } | {
2405
- kind: "PROJECT";
2432
+ kind: "project";
2406
2433
  project_id: string;
2407
2434
  } | {
2408
- kind: "VIRTUAL_KEY";
2435
+ kind: "virtual_key";
2409
2436
  virtual_key_id: string;
2410
2437
  } | {
2411
- kind: "PRINCIPAL";
2438
+ kind: "principal";
2412
2439
  principal_user_id: string;
2413
2440
  } | {
2414
- kind: "GROUP";
2441
+ kind: "group";
2415
2442
  group_id: string;
2443
+ } | {
2444
+ kind: "attributed_user";
2445
+ anchor_virtual_key_id?: string;
2446
+ anchor_project_id?: string;
2416
2447
  };
2417
2448
  interface CreateGatewayBudgetInput {
2418
2449
  scope: CreateGatewayBudgetScope;
@@ -2424,6 +2455,24 @@ interface CreateGatewayBudgetInput {
2424
2455
  timezone?: string | null;
2425
2456
  /** ModelProvider id to pin the budget to one provider. */
2426
2457
  provider_key?: string | null;
2458
+ /**
2459
+ * RFC3339 instant that phases the budget's cycle instead of the calendar:
2460
+ * a `month` budget anchored `2026-01-17T09:00:00Z` rolls every 17th at
2461
+ * 09:00 UTC. Omit for calendar alignment. Immutable once created, and
2462
+ * rejected on the windows that never cycle (`total`, `manual`).
2463
+ */
2464
+ cycle_anchor_at?: string;
2465
+ /**
2466
+ * Your own identifier for this budget. Lets you look it up by the id your
2467
+ * system already has instead of storing ours alongside it.
2468
+ */
2469
+ external_id?: string | null;
2470
+ /**
2471
+ * Free-form string labels, up to 40 of them. Sent WHOLE on an update: the
2472
+ * map you pass replaces the stored one rather than merging into it, and
2473
+ * `{}` clears it.
2474
+ */
2475
+ metadata?: Record<string, string>;
2427
2476
  }
2428
2477
  interface UpdateGatewayBudgetInput {
2429
2478
  name?: string;
@@ -2437,30 +2486,879 @@ declare class GatewayBudgetsApiError extends Error {
2437
2486
  readonly originalError?: unknown | undefined;
2438
2487
  constructor(message: string, operation: string, originalError?: unknown | undefined);
2439
2488
  }
2489
+ /**
2490
+ * Client for the gateway budget surface (/api/gateway/v1).
2491
+ *
2492
+ * Entity types and the create/update bodies mirror the wire verbatim, so
2493
+ * their fields are lowercase snake_case. Call options this SDK invents (query
2494
+ * filters, per-call behaviour, action arguments) are camelCase like the rest
2495
+ * of the SDK.
2496
+ */
2440
2497
  declare class GatewayBudgetsApiService {
2441
2498
  private readonly endpoint;
2442
2499
  private readonly apiKey;
2500
+ private readonly projectId;
2443
2501
  constructor(config?: {
2444
2502
  endpoint?: string;
2445
2503
  apiKey?: string;
2504
+ projectId?: string;
2446
2505
  });
2447
2506
  private headers;
2448
2507
  private request;
2449
2508
  /**
2450
- * Every non-archived budget in the organization across all six scope
2509
+ * ONE page of non-archived budgets, exactly as the wire serves it. Pass
2510
+ * `next_cursor` back as `cursor` for the next page, verbatim: a cursor this
2511
+ * endpoint did not issue answers 400 rather than restarting the walk.
2512
+ *
2513
+ * `limit` is the page size (server default 50, capped at 200). Prefer
2514
+ * `list()` unless you mean to page deliberately: a full page is not a
2515
+ * promise of more, and a null `next_cursor` is the only end of the walk.
2516
+ */
2517
+ listPage(options?: {
2518
+ scopeTypes?: BudgetScopeKind[];
2519
+ cursor?: string;
2520
+ limit?: number;
2521
+ /** Exact match on your own identifier, not a prefix or a search. */
2522
+ externalId?: string;
2523
+ }): Promise<GatewayBudgetPage>;
2524
+ /**
2525
+ * Every non-archived budget in the organization across all seven scope
2451
2526
  * types, optionally filtered by `scopeTypes`.
2527
+ *
2528
+ * The endpoint pages; this follows `next_cursor` until it comes back null,
2529
+ * so the result is the complete listing and carries no cursor of its own.
2530
+ * Callers that count, total, or decide an all-clear on this list need that
2531
+ * completeness for correctness, not just for display.
2532
+ *
2533
+ * `limit` sizes each request in the walk, it does NOT cap what comes back.
2534
+ * `cursor` resumes an interrupted walk. Take a single page with
2535
+ * `listPage()`, or stream the walk with `iterate()`.
2536
+ *
2537
+ * A plain array, like every other exhaustive `list()` in the SDK: a walk
2538
+ * that ran to the end has no cursor left to report. Null `spent_usd` /
2539
+ * `spent_nano_usd` on a row is not by itself "spend unavailable": an
2540
+ * `attributed_user` template row serves null deliberately, because one
2541
+ * allowance per person has no single total. Use `listPage()` when you need
2542
+ * `spend_available` stated outright.
2452
2543
  */
2453
2544
  list(options?: {
2454
2545
  scopeTypes?: BudgetScopeKind[];
2455
- }): Promise<GatewayBudgetList>;
2456
- create(input: CreateGatewayBudgetInput): Promise<GatewayBudget>;
2457
- update(id: string, input: UpdateGatewayBudgetInput): Promise<GatewayBudget>;
2458
- archive(id: string): Promise<GatewayBudget>;
2546
+ cursor?: string;
2547
+ limit?: number;
2548
+ /** Exact match on your own identifier, not a prefix or a search. */
2549
+ externalId?: string;
2550
+ }): Promise<GatewayBudget[]>;
2551
+ /**
2552
+ * Every non-archived budget, one row at a time, fetching each page only
2553
+ * when the consumer reaches it.
2554
+ *
2555
+ * A null `spent_usd` means spend could not be totalled rather than that
2556
+ * nothing was spent.
2557
+ */
2558
+ iterate(options?: {
2559
+ scopeTypes?: BudgetScopeKind[];
2560
+ cursor?: string;
2561
+ limit?: number;
2562
+ /** Exact match on your own identifier, not a prefix or a search. */
2563
+ externalId?: string;
2564
+ }): AsyncGenerator<GatewayBudget>;
2565
+ /**
2566
+ * One budget by id, in the same row shape the listing serves.
2567
+ *
2568
+ * Archived budgets are not served, so a budget that existed yesterday can
2569
+ * answer 404 today. A null `spent_usd` means spend could not be totalled
2570
+ * rather than that nothing was spent, which is the same signal the listing
2571
+ * carries as `spend_available`.
2572
+ */
2573
+ get(id: string): Promise<GatewayBudget>;
2574
+ create(input: CreateGatewayBudgetInput, options?: IdempotentCreateOptions): Promise<GatewayBudget>;
2575
+ update(id: string, input: UpdateGatewayBudgetInput, options?: MutationOptions): Promise<GatewayBudget>;
2576
+ archive(id: string, options?: MutationOptions): Promise<GatewayBudget>;
2577
+ /**
2578
+ * Move the budget's period boundary to now. Recorded spend is never
2579
+ * mutated; with `endUserId` only that end-user bucket's boundary moves.
2580
+ */
2581
+ reset(id: string, options?: {
2582
+ endUserId?: string;
2583
+ reason?: string;
2584
+ } & MutationOptions): Promise<GatewayBudget>;
2585
+ }
2586
+
2587
+ interface SpendEvent {
2588
+ id: string;
2589
+ type: string;
2590
+ created: string;
2591
+ schema_version: string;
2592
+ data: {
2593
+ /** Type-suffixed, unique per (request, event type): a settled and a
2594
+ * completed event for one request never share an id. */
2595
+ event_id: string;
2596
+ /** "gateway.request.completed" (confirmed and failed outcomes) or
2597
+ * "gateway.request.settled" (confirmation never arrived). */
2598
+ event_type: string;
2599
+ /** The join key across a settled/completed pair: a completed event
2600
+ * SUPERSEDES an earlier settled one for the same request; replace the
2601
+ * figure, never sum the pair. */
2602
+ gateway_request_id: string;
2603
+ occurred_at: string;
2604
+ organization_id: string;
2605
+ project_id: string;
2606
+ virtual_key_id: string;
2607
+ principal_user_id: string | null;
2608
+ end_user_id: string | null;
2609
+ trace_id: string;
2610
+ model: string | null;
2611
+ model_provider_id: string | null;
2612
+ request_type: string | null;
2613
+ /** Null on settled events: unknown is not zero. */
2614
+ usage: {
2615
+ input_tokens: number;
2616
+ output_tokens: number;
2617
+ cache_read_input_tokens: number;
2618
+ cache_creation_input_tokens: number;
2619
+ reasoning_tokens: number;
2620
+ } | null;
2621
+ /** Null on settled events: unknown is not zero. */
2622
+ cost: {
2623
+ total_usd: string;
2624
+ nano_usd: number;
2625
+ rate_version: string | null;
2626
+ } | null;
2627
+ /** "success" | "error" on completed events, "settled" on settled ones. */
2628
+ status: string;
2629
+ needs_reconciliation: boolean | null;
2630
+ settle_reason: string | null;
2631
+ error: {
2632
+ class: string;
2633
+ http_status: number | null;
2634
+ } | null;
2635
+ duration_ms: number | null;
2636
+ labels: string[];
2637
+ metadata: Record<string, unknown>;
2638
+ };
2639
+ }
2640
+ interface SpendSummaryRow {
2641
+ key: string;
2642
+ /** Priced outcomes (confirmed and failed). */
2643
+ event_count: number;
2644
+ /** Unpriced settled requests, counted separately: never in cost sums. */
2645
+ settled_count: number;
2646
+ usage: {
2647
+ input_tokens: number;
2648
+ output_tokens: number;
2649
+ cache_read_input_tokens: number;
2650
+ cache_creation_input_tokens: number;
2651
+ reasoning_tokens: number;
2652
+ };
2653
+ cost: {
2654
+ total_usd: string;
2655
+ nano_usd: number;
2656
+ };
2657
+ }
2658
+ /**
2659
+ * The states a request can be filtered by, which is more than the two a
2660
+ * caller usually thinks in: a request is `admitted` when it starts,
2661
+ * `confirmed` or `failed` when it ends, and `settled` once its cost is final.
2662
+ * `success` and `error` are the coarse outcome pair over those.
2663
+ */
2664
+ type SpendEventStatus = "success" | "error" | "admitted" | "confirmed" | "failed" | "settled";
2665
+ interface SpendSummariesPage {
2666
+ data: SpendSummaryRow[];
2667
+ /**
2668
+ * Pass back as `cursor` for the next page; null means the walk is done.
2669
+ * A full page does NOT mean there is more, so follow this until null
2670
+ * rather than stopping when a page comes back short.
2671
+ */
2672
+ next_cursor: string | null;
2673
+ }
2674
+ interface SpendEventsPage {
2675
+ data: SpendEvent[];
2676
+ next_cursor: string | null;
2677
+ }
2678
+ interface SpendReplayResult {
2679
+ endpoint_id: string;
2680
+ replay_id: string;
2681
+ replayed: number;
2682
+ window: {
2683
+ from: string;
2684
+ to: string;
2685
+ };
2686
+ }
2687
+ interface EndUserSpend {
2688
+ end_user_id: string;
2689
+ window: string;
2690
+ from: string;
2691
+ to: string;
2692
+ cost: {
2693
+ total_usd: string;
2694
+ nano_usd?: number;
2695
+ };
2696
+ request_count: number;
2697
+ usage: {
2698
+ input_tokens: number;
2699
+ output_tokens: number;
2700
+ cache_read_input_tokens: number;
2701
+ cache_creation_input_tokens: number;
2702
+ reasoning_tokens: number;
2703
+ };
2704
+ /**
2705
+ * The attributed-user template caps that apply to this end user, each
2706
+ * with its boundary-aware current-period spend. Empty when the
2707
+ * organization runs no templates; never null.
2708
+ */
2709
+ caps: EndUserCap[];
2459
2710
  }
2711
+ interface EndUserCap {
2712
+ budget_id: string;
2713
+ anchor_id: string;
2714
+ window: string;
2715
+ on_breach: "block" | "warn";
2716
+ limit_usd: string;
2717
+ spent_usd: string;
2718
+ period_started_at: string;
2719
+ }
2720
+ declare class SpendEventsApiError extends Error {
2721
+ readonly operation: string;
2722
+ readonly originalError?: unknown | undefined;
2723
+ constructor(message: string, operation: string, originalError?: unknown | undefined);
2724
+ }
2725
+ /**
2726
+ * Client for the gateway spend reconciliation surface (/api/gateway/v1).
2727
+ * Authenticates with an ORGANIZATION API key (sk-lw-*).
2728
+ *
2729
+ * Entity types mirror the wire verbatim, so their fields are lowercase
2730
+ * snake_case. Call options this SDK invents (query filters, per-call
2731
+ * behaviour, action arguments) are camelCase like the rest of the SDK.
2732
+ *
2733
+ * There is no project id here: `/spend-summaries` takes `project_id` as a
2734
+ * query filter rather than scoping on a header, so the project belongs to the
2735
+ * call, not to the client.
2736
+ *
2737
+ * Neither collection on this service offers an eager whole-set read. The
2738
+ * ledger is unbounded, and materialising a window of it is the very
2739
+ * under-counting and out-of-memory footgun the page docstrings warn about:
2740
+ * take pages, or stream with `iterate()` / `iterSummaries()`.
2741
+ */
2742
+ declare class SpendEventsApiService {
2743
+ private readonly endpoint;
2744
+ private readonly apiKey;
2745
+ constructor(config?: {
2746
+ endpoint?: string;
2747
+ apiKey?: string;
2748
+ });
2749
+ private request;
2750
+ /**
2751
+ * ONE page of the per-request spend ledger for a window. Pass `next_cursor`
2752
+ * back as `cursor` for the next page, verbatim.
2753
+ *
2754
+ * A full page does NOT mean there is more and a short page does NOT mean
2755
+ * there is no more: only a null cursor ends the walk. A reconciler that
2756
+ * stops on the first page silently under-counts the window, so read every
2757
+ * page or stream them with `iterate()`.
2758
+ */
2759
+ listPage(options: {
2760
+ /** Required: the pull is a ranged read by contract. */
2761
+ from: number;
2762
+ to: number;
2763
+ cursor?: string;
2764
+ limit?: number;
2765
+ virtualKeyId?: string;
2766
+ endUserId?: string;
2767
+ projectId?: string;
2768
+ model?: string;
2769
+ status?: SpendEventStatus;
2770
+ }): Promise<SpendEventsPage>;
2771
+ /**
2772
+ * Every spend event in the window, one row at a time, fetching each page
2773
+ * only when the consumer reaches it.
2774
+ *
2775
+ * This is how a reconciler reads a whole window without holding it: the
2776
+ * ledger is unbounded, so there is deliberately no eager `list()` to
2777
+ * collect it into an array. Raises rather than looping forever on a cursor
2778
+ * chain that never ends.
2779
+ */
2780
+ iterate(options: {
2781
+ /** Required: the pull is a ranged read by contract. */
2782
+ from: number;
2783
+ to: number;
2784
+ cursor?: string;
2785
+ limit?: number;
2786
+ virtualKeyId?: string;
2787
+ endUserId?: string;
2788
+ projectId?: string;
2789
+ model?: string;
2790
+ status?: SpendEventStatus;
2791
+ }): AsyncGenerator<SpendEvent>;
2792
+ /**
2793
+ * ONE page of per-key spend rollups for a window, paged by group key
2794
+ * ascending.
2795
+ *
2796
+ * The page is a step of a walk, not a whole answer: follow `next_cursor`
2797
+ * until it comes back null, or stream the walk with `iterSummaries()`. A
2798
+ * reconciler that reads only the first page silently under-counts every
2799
+ * tenant past the limit.
2800
+ */
2801
+ summariesPage(options: {
2802
+ groupBy: "virtual_key" | "end_user";
2803
+ from: number;
2804
+ to: number;
2805
+ projectId?: string;
2806
+ /** Narrow the rollup to one key, exact match. */
2807
+ virtualKeyId?: string;
2808
+ cursor?: string;
2809
+ limit?: number;
2810
+ }): Promise<SpendSummariesPage>;
2811
+ /**
2812
+ * Every rollup row for the window, one at a time, fetching each page only
2813
+ * when the consumer reaches it.
2814
+ *
2815
+ * The rollup has one row per tenant seen in the window, which no bound
2816
+ * covers, so there is deliberately no eager whole-set read here either: a
2817
+ * checksum that quietly covers part of the window is worse than none.
2818
+ */
2819
+ iterSummaries(options: {
2820
+ groupBy: "virtual_key" | "end_user";
2821
+ from: number;
2822
+ to: number;
2823
+ projectId?: string;
2824
+ /** Narrow the rollup to one key, exact match. */
2825
+ virtualKeyId?: string;
2826
+ cursor?: string;
2827
+ limit?: number;
2828
+ }): AsyncGenerator<SpendSummaryRow>;
2829
+ /**
2830
+ * Re-deliver a window's spend envelopes to ONE endpoint through the
2831
+ * normal delivery path. Envelope ids are unchanged (your consumer's
2832
+ * dedup key); mind your downstream billing system's finite dedup
2833
+ * window before replaying old ranges. The window is capped server-side
2834
+ * at 7 days per call.
2835
+ */
2836
+ replay(options: {
2837
+ from: number;
2838
+ to: number;
2839
+ endpointId: string;
2840
+ } & MutationOptions): Promise<SpendReplayResult>;
2841
+ endUserSpend(endUserId: string, options?: {
2842
+ window?: "day" | "week" | "month";
2843
+ from?: number;
2844
+ to?: number;
2845
+ virtualKeyId?: string;
2846
+ }): Promise<EndUserSpend>;
2847
+ }
2848
+
2849
+ interface WebhookEndpointSummary {
2850
+ id: string;
2851
+ url: string;
2852
+ max_batch_size: number;
2853
+ max_batch_delay_ms: number;
2854
+ max_in_flight: number;
2855
+ enabled_events: string[];
2856
+ status: "active" | "disabled";
2857
+ disabled_reason: string | null;
2858
+ disabled_at: string | null;
2859
+ failing_since: string | null;
2860
+ last_success_at: string | null;
2861
+ last_failure_at: string | null;
2862
+ created_at: string;
2863
+ updated_at: string;
2864
+ }
2865
+ interface WebhookEndpointWithSecret extends WebhookEndpointSummary {
2866
+ /** Present only on create and roll-secret responses; never again. */
2867
+ secret: string;
2868
+ }
2869
+ /** The POST body, exactly as the wire takes it. */
2870
+ interface CreateWebhookEndpointInput {
2871
+ url: string;
2872
+ enabled_events: string[];
2873
+ /** Envelopes per delivery. The receiver always gets an array. */
2874
+ max_batch_size?: number;
2875
+ /** How long a partial batch waits for company before it is sent. */
2876
+ max_batch_delay_ms?: number;
2877
+ /** Concurrent in-flight deliveries to this endpoint. */
2878
+ max_in_flight?: number;
2879
+ }
2880
+ /** The PATCH body, exactly as the wire takes it. Omitted fields are left alone. */
2881
+ interface UpdateWebhookEndpointInput {
2882
+ url?: string;
2883
+ enabled_events?: string[];
2884
+ status?: "active" | "disabled";
2885
+ max_batch_size?: number;
2886
+ max_batch_delay_ms?: number;
2887
+ max_in_flight?: number;
2888
+ }
2889
+ interface WebhookDeliveryRecord {
2890
+ id: string;
2891
+ dispatch_id: string;
2892
+ attempt: number;
2893
+ event_count: number;
2894
+ outcome: string;
2895
+ response_status: number | null;
2896
+ latency_ms: number | null;
2897
+ error: string | null;
2898
+ fired_at: string;
2899
+ }
2900
+ interface WebhookTestResult {
2901
+ delivered: boolean;
2902
+ response_status: number | null;
2903
+ response_body?: string;
2904
+ error?: string;
2905
+ }
2906
+ interface WebhookEndpointHealth {
2907
+ status: "active" | "disabled";
2908
+ disabled_reason: string | null;
2909
+ failing_since: string | null;
2910
+ last_success_at: string | null;
2911
+ last_failure_at: string | null;
2912
+ /** The headline: age of the oldest envelope still buffered or retrying;
2913
+ * null when the feed is fully delivered. */
2914
+ oldest_undelivered_age_ms: number | null;
2915
+ dlq_depth: number;
2916
+ sends_per_minute: number;
2917
+ success_rate: number | null;
2918
+ p95_latency_ms: number | null;
2919
+ }
2920
+ interface WebhookEventType {
2921
+ type: string;
2922
+ family: string;
2923
+ schema_version: string;
2924
+ is_emitting: boolean;
2925
+ description: string;
2926
+ }
2927
+ interface EmittedEvent {
2928
+ id: string;
2929
+ type: string;
2930
+ created: string;
2931
+ schema_version: string;
2932
+ data: Record<string, unknown>;
2933
+ }
2934
+ /** One page of the organization's emitted-events log. */
2935
+ interface EmittedEventsPage {
2936
+ data: EmittedEvent[];
2937
+ /** Pass back as `cursor` for the next page; null ends the walk. */
2938
+ next_cursor: string | null;
2939
+ }
2940
+ /** One page of an endpoint's delivery log, newest first. */
2941
+ interface WebhookDeliveryPage {
2942
+ data: WebhookDeliveryRecord[];
2943
+ /** Pass back as `cursor` for the next page; null ends the walk. */
2944
+ next_cursor: string | null;
2945
+ }
2946
+ declare class WebhooksApiError extends Error {
2947
+ readonly operation: string;
2948
+ readonly originalError?: unknown | undefined;
2949
+ constructor(message: string, operation: string, originalError?: unknown | undefined);
2950
+ }
2951
+ /**
2952
+ * Client for the org-anchored webhook platform surface (/api/webhooks/v1).
2953
+ * Authenticates with an ORGANIZATION API key (sk-lw-*); project keys are
2954
+ * rejected by the server. The surface is anchored on the organization alone,
2955
+ * so there is no project id to give this client.
2956
+ *
2957
+ * The endpoint entity and the create/update bodies mirror the wire verbatim,
2958
+ * so their fields are lowercase snake_case: virtual keys and gateway budgets
2959
+ * already take the wire body as it is, and translating field by field here
2960
+ * only made the request bodies of the four billing surfaces disagree. Call
2961
+ * options this SDK invents (query filters, per-call behaviour, action
2962
+ * arguments) stay camelCase like the rest of the SDK.
2963
+ */
2964
+ declare class WebhooksApiService {
2965
+ private readonly endpoint;
2966
+ private readonly apiKey;
2967
+ constructor(config?: {
2968
+ endpoint?: string;
2969
+ apiKey?: string;
2970
+ });
2971
+ private request;
2972
+ list(): Promise<WebhookEndpointSummary[]>;
2973
+ get(id: string): Promise<WebhookEndpointSummary>;
2974
+ /**
2975
+ * The signing secret comes back on this response and never again, so a
2976
+ * create that times out is recovered with `idempotencyKey`: the replay
2977
+ * carries the same secret, and nothing else ever will.
2978
+ */
2979
+ create(input: CreateWebhookEndpointInput, options?: IdempotentCreateOptions): Promise<WebhookEndpointWithSecret>;
2980
+ update(id: string, input: UpdateWebhookEndpointInput, options?: MutationOptions): Promise<WebhookEndpointSummary>;
2981
+ /**
2982
+ * Retire an endpoint: the server soft-archives the row, stamping
2983
+ * `archived_at` and dropping the status to disabled, so the delivery
2984
+ * history stays readable for audit while nothing more is ever sent. The
2985
+ * row is archived, not removed, and `gatewayBudgets.archive()` already
2986
+ * names that operation, so the billing surfaces agree on the verb.
2987
+ *
2988
+ * Nothing comes back: the response body carries only an `archived: true`
2989
+ * acknowledgement, and a non-2xx already raises.
2990
+ */
2991
+ archive(id: string, options?: MutationOptions): Promise<void>;
2992
+ rollSecret(id: string, options?: MutationOptions): Promise<WebhookEndpointWithSecret>;
2993
+ test(id: string, options?: MutationOptions): Promise<WebhookTestResult>;
2994
+ /**
2995
+ * ONE page of the endpoint's delivery attempts, newest first.
2996
+ *
2997
+ * The cursor is why this is a page: the route has always served one, and
2998
+ * dropping it truncated the delivery log at whatever the first page held,
2999
+ * with nothing in the result to say the rest existed. Pass `next_cursor`
3000
+ * back as `cursor`, or walk the whole log with `iterDeliveries()`.
3001
+ */
3002
+ deliveriesPage(id: string, options?: {
3003
+ cursor?: string;
3004
+ limit?: number;
3005
+ }): Promise<WebhookDeliveryPage>;
3006
+ /**
3007
+ * Every recorded delivery attempt for the endpoint, one at a time,
3008
+ * fetching each page only when the consumer reaches it.
3009
+ */
3010
+ iterDeliveries(id: string, options?: {
3011
+ cursor?: string;
3012
+ limit?: number;
3013
+ }): AsyncGenerator<WebhookDeliveryRecord>;
3014
+ health(id: string): Promise<WebhookEndpointHealth>;
3015
+ eventTypes(): Promise<WebhookEventType[]>;
3016
+ /**
3017
+ * ONE page of the organization's emitted-events log, newest first.
3018
+ *
3019
+ * Webhooks are a push over this log, never the only copy of it: a consumer
3020
+ * that missed a delivery reads the window back from here. Walk the whole
3021
+ * window with `iterEvents()`.
3022
+ */
3023
+ eventsPage(options?: {
3024
+ type?: string;
3025
+ from?: number;
3026
+ to?: number;
3027
+ cursor?: string;
3028
+ limit?: number;
3029
+ }): Promise<EmittedEventsPage>;
3030
+ /**
3031
+ * Every emitted event matching the filter, one at a time, fetching each
3032
+ * page only when the consumer reaches it.
3033
+ */
3034
+ iterEvents(options?: {
3035
+ type?: string;
3036
+ from?: number;
3037
+ to?: number;
3038
+ cursor?: string;
3039
+ limit?: number;
3040
+ }): AsyncGenerator<EmittedEvent>;
3041
+ /**
3042
+ * One emitted event by id, the envelope exactly as it was delivered.
3043
+ *
3044
+ * A 404 covers every reason the log cannot answer: never emitted, past the
3045
+ * retention horizon, or belonging to another organization.
3046
+ */
3047
+ getEvent(id: string): Promise<EmittedEvent>;
3048
+ }
3049
+
3050
+ interface GetTraceParams {
3051
+ includeSpans?: boolean;
3052
+ }
3053
+ type GetTraceResponse = NonNullable<paths["/api/trace/{id}"]["get"]["responses"]["200"]["content"]["application/json"]>;
3054
+
3055
+ declare class TracesFacade {
3056
+ #private;
3057
+ constructor(config: InternalConfig);
3058
+ get(traceId: string, params?: GetTraceParams): Promise<GetTraceResponse>;
3059
+ }
3060
+
3061
+ interface LangWatchConstructorOptions {
3062
+ apiKey?: string;
3063
+ endpoint?: string;
3064
+ options?: {
3065
+ logger?: Logger;
3066
+ };
3067
+ }
3068
+ declare class LangWatch {
3069
+ #private;
3070
+ private readonly config;
3071
+ readonly prompts: PromptsFacade;
3072
+ readonly traces: TracesFacade;
3073
+ readonly datasets: DatasetsFacade;
3074
+ /**
3075
+ * Run experiments on LangWatch platform or via SDK.
3076
+ *
3077
+ * Platform experiments (CI/CD):
3078
+ * ```typescript
3079
+ * const result = await langwatch.experiments.run("my-experiment-slug");
3080
+ * result.printSummary();
3081
+ * ```
3082
+ *
3083
+ * SDK-defined experiments:
3084
+ * ```typescript
3085
+ * const experiment = await langwatch.experiments.init("my-experiment");
3086
+ * // ... run evaluators using experiment.evaluate()
3087
+ * ```
3088
+ */
3089
+ readonly experiments: ExperimentsFacade;
3090
+ /**
3091
+ * Run evaluators and guardrails in real-time (Online Evaluations).
3092
+ *
3093
+ * @example
3094
+ * ```typescript
3095
+ * const guardrail = await langwatch.evaluations.evaluate("presidio/pii_detection", {
3096
+ * data: { input: userInput, output: generatedResponse },
3097
+ * name: "PII Detection",
3098
+ * asGuardrail: true,
3099
+ * });
3100
+ *
3101
+ * if (!guardrail.passed) {
3102
+ * return "I'm sorry, I can't do that.";
3103
+ * }
3104
+ * ```
3105
+ */
3106
+ readonly evaluations: EvaluationsFacade;
3107
+ readonly evaluators: EvaluatorsApiService;
3108
+ readonly scenarios: ScenariosApiService;
3109
+ readonly suites: SuitesApiService;
3110
+ readonly workflows: WorkflowsApiService;
3111
+ readonly agents: AgentsApiService;
3112
+ readonly annotations: AnnotationsApiService;
3113
+ readonly dashboards: DashboardsApiService;
3114
+ readonly modelProviders: ModelProvidersApiService;
3115
+ readonly analytics: AnalyticsApiService;
3116
+ readonly triggers: TriggersApiService;
3117
+ readonly graphs: GraphsApiService;
3118
+ readonly simulationRuns: SimulationRunsApiService;
3119
+ readonly monitors: MonitorsApiService;
3120
+ readonly secrets: SecretsApiService;
3121
+ readonly virtualKeys: VirtualKeysApiService;
3122
+ readonly gatewayBudgets: GatewayBudgetsApiService;
3123
+ readonly spendEvents: SpendEventsApiService;
3124
+ readonly webhooks: WebhooksApiService;
3125
+ constructor(options?: LangWatchConstructorOptions);
3126
+ get apiClient(): LangwatchApiClient;
3127
+ }
3128
+
3129
+ /**
3130
+ * A failure the platform NAMED.
3131
+ *
3132
+ * The API does not merely fail — when it declines a request it says precisely
3133
+ * why, as a `HandledError` with a serialisable `kind` (`dataset_not_found`,
3134
+ * `validation_error`), the HTTP status it answers with, and a `meta` bag of the
3135
+ * context that makes the failure actionable. Until now the SDK collapsed all of
3136
+ * that into an English sentence on a generic error, so a caller could read the
3137
+ * failure but never react to it: a 404 "dataset not found" — a fact you can
3138
+ * offer to fix — was indistinguishable from a 500.
3139
+ *
3140
+ * This is that structure, kept. Narrow with {@link isLangWatchHandledError} (or
3141
+ * `instanceof`) and switch on `code`; `body` is the escape hatch to whatever the
3142
+ * platform sent that this class did not model.
3143
+ *
3144
+ * ```ts
3145
+ * try {
3146
+ * await langwatch.datasets.get("nope");
3147
+ * } catch (error) {
3148
+ * if (isLangWatchHandledError(error) && error.code === "dataset_not_found") {
3149
+ * // Actionable: we know WHAT was not found, and can offer the list.
3150
+ * console.error(error.meta.id, error.traceId);
3151
+ * }
3152
+ * throw error;
3153
+ * }
3154
+ * ```
3155
+ *
3156
+ * ONLY raised for a failure the platform named. An infrastructure failure — a
3157
+ * 5xx, a dead socket, a proxy's HTML error page — still raises the generic
3158
+ * service error it always did, because presenting one of those as a domain
3159
+ * error would blame the user for our outage.
3160
+ */
3161
+ declare class LangWatchHandledError extends Error {
3162
+ /**
3163
+ * The discriminant. A boolean brand rather than `instanceof` alone because a
3164
+ * bundled CLI and a consumer's `node_modules` copy of the SDK can hold two
3165
+ * different copies of this class, and `instanceof` is false across that seam —
3166
+ * the same reason the platform's own error handler tests for `code` rather
3167
+ * than class identity.
3168
+ */
3169
+ readonly isLangWatchHandledError: true;
3170
+ /** The platform's serialisable discriminant, e.g. `dataset_not_found`. */
3171
+ readonly code: string;
3172
+ /**
3173
+ * @deprecated Back-compat alias of `code`, kept while the platform's
3174
+ * `DomainError` → `HandledError` rename rolls out. Read `code` in new code.
3175
+ */
3176
+ readonly kind: string;
3177
+ /** The status the platform answered with. */
3178
+ readonly httpStatus: number;
3179
+ /** The context the platform attached: ids, field errors — whatever makes it actionable. */
3180
+ readonly meta: Record<string, unknown>;
3181
+ /** The OTel trace to quote at support. Absent unless the route sent one. */
3182
+ readonly traceId: string | undefined;
3183
+ /** A clickable link to that trace, when the route sent one. */
3184
+ readonly traceUrl: string | undefined;
3185
+ /** A clickable link to the logs for that trace, when the route sent one. */
3186
+ readonly logsUrl: string | undefined;
3187
+ /** The failure behind the failure, when the route sent the chain. */
3188
+ readonly reasons: CliHandledErrorReason[] | undefined;
3189
+ /** What the user can DO about it, when the platform sent next steps. */
3190
+ readonly suggestions: string[] | undefined;
3191
+ /** The docs page that explains the failure, when the platform sent one. */
3192
+ readonly docUrl: string | undefined;
3193
+ /** The raw response body, verbatim — the escape hatch for anything unmodelled. */
3194
+ readonly body: unknown;
3195
+ /** What the SDK was doing, e.g. `get dataset "abc"`. */
3196
+ readonly operation: string | undefined;
3197
+ /**
3198
+ * Alias of {@link httpStatus}, and the raw body again under the name the
3199
+ * per-service `*ApiError` classes use.
3200
+ *
3201
+ * Not redundancy for its own sake: this class is thrown from the SAME code
3202
+ * path that used to throw `TracesApiError` & friends, so anything that reads
3203
+ * `.status` or `.originalError` off a caught SDK error — including the CLI's
3204
+ * own telemetry reader — keeps working unchanged.
3205
+ */
3206
+ readonly status: number;
3207
+ readonly originalError: unknown;
3208
+ constructor({ handled, body, operation, message, }: {
3209
+ handled: CliHandledError;
3210
+ body: unknown;
3211
+ operation?: string;
3212
+ message: string;
3213
+ });
3214
+ }
3215
+ /** Narrows any caught value to a {@link LangWatchHandledError}. */
3216
+ declare const isLangWatchHandledError: (error: unknown) => error is LangWatchHandledError;
3217
+ declare class LangWatchApiError extends Error {
3218
+ readonly httpStatus: number;
3219
+ readonly httpStatusText: string;
3220
+ apiError: string | undefined;
3221
+ body: unknown;
3222
+ constructor(message: string, response: Response);
3223
+ safeParseBody(response: Response): Promise<void>;
3224
+ }
3225
+
3226
+ /**
3227
+ * Receiver-side verification of a LangWatch webhook delivery.
3228
+ *
3229
+ * Every delivery carries
3230
+ *
3231
+ * X-LangWatch-Signature: t=<unix seconds>,v1=<hex hmac-sha256>[,v1=<hex>]
3232
+ *
3233
+ * where each `v1` is HMAC-SHA256 over `"<t>.<raw body>"` under one currently
3234
+ * valid signing secret. `v1` REPEATS during a secret rotation, newest first,
3235
+ * which is what lets a receiver swap secrets on its own schedule instead of
3236
+ * dropping deliveries mid-swap.
3237
+ *
3238
+ * That repetition is the reason this helper exists. A hand-rolled parser that
3239
+ * keeps the LAST `v1` it sees, or splits the header into a flat key/value map,
3240
+ * rejects every delivery to a receiver that has already moved to the new
3241
+ * secret: the signature it kept is the one computed from the OLD secret. The
3242
+ * bug only appears during a rotation, which is exactly when a receiver can
3243
+ * least afford to be dropping deliveries.
3244
+ *
3245
+ * The algorithm here is pinned to the sender's by the vectors in
3246
+ * `specs/webhooks/signature-vectors.json`, generated from the server's own
3247
+ * signing code and asserted by the suite next to this file.
3248
+ */
3249
+ /** The header a delivery carries its signature in. */
3250
+ declare const WEBHOOK_SIGNATURE_HEADER = "X-LangWatch-Signature";
3251
+ /**
3252
+ * Identifies one delivery ATTEMPT on the webhook platform's endpoints.
3253
+ *
3254
+ * The natural idempotency key for a receiver: retries of the same batch repeat
3255
+ * it, so a receiver that has already processed this id can acknowledge and
3256
+ * stop rather than applying the batch twice.
3257
+ */
3258
+ declare const WEBHOOK_DELIVERY_ID_HEADER = "X-LangWatch-Delivery-Id";
3259
+ /**
3260
+ * The same role on automation deliveries (graph alerts and friends), which
3261
+ * group their attempts by the logical fire rather than by the batch.
3262
+ *
3263
+ * Two names because they are two senders: read whichever the delivery carries.
3264
+ */
3265
+ declare const WEBHOOK_EVENT_ID_HEADER = "X-LangWatch-Event-Id";
3266
+ /**
3267
+ * How far a delivery's timestamp may sit from the receiver's clock, in
3268
+ * seconds. Matches the sender's documented window.
3269
+ */
3270
+ declare const WEBHOOK_SIGNATURE_DEFAULT_TOLERANCE_SECONDS = 300;
3271
+ /**
3272
+ * Why a delivery was refused. Switch on this rather than on the message: the
3273
+ * message is written for a human reading a log and will change, the code is
3274
+ * the contract.
3275
+ *
3276
+ * The three mean genuinely different things to an operator. `stale_timestamp`
3277
+ * is a clock or a replay and is worth alerting on; `invalid_signature` is a
3278
+ * wrong secret or a tampered body; `malformed_header` is almost always
3279
+ * something other than LangWatch posting to the URL.
3280
+ */
3281
+ type WebhookSignatureFailureCode = "malformed_header" | "stale_timestamp" | "invalid_signature";
3282
+ /**
3283
+ * A delivery that did not verify.
3284
+ *
3285
+ * One class carrying a `code` rather than three classes, because the SDK and
3286
+ * the platform both ask callers to branch on a stable code instead of on the
3287
+ * error's identity, which does not survive a serialization boundary.
3288
+ */
3289
+ declare class WebhookSignatureVerificationError extends Error {
3290
+ readonly code: WebhookSignatureFailureCode;
3291
+ constructor(code: WebhookSignatureFailureCode, message: string);
3292
+ }
3293
+ interface VerifyWebhookSignatureOptions {
3294
+ /**
3295
+ * The EXACT bytes of the request body, as received.
3296
+ *
3297
+ * Not a parsed object, and not the result of re-serializing one: the digest
3298
+ * is over the bytes the sender hashed, and `JSON.parse` followed by
3299
+ * `JSON.stringify` reorders keys, drops insignificant whitespace and
3300
+ * re-escapes non-ASCII, any of which changes the digest. Read the raw body
3301
+ * before your framework's JSON middleware does.
3302
+ */
3303
+ body: string | Uint8Array;
3304
+ /** The `X-LangWatch-Signature` header value, verbatim. */
3305
+ header: string;
3306
+ /**
3307
+ * The signing secret, or every secret this receiver currently accepts.
3308
+ *
3309
+ * Pass both values during a rotation and the delivery verifies under
3310
+ * either, so there is no window where deliveries are refused.
3311
+ */
3312
+ secret: string | readonly string[];
3313
+ /**
3314
+ * Freshness window in seconds, defaulting to the sender's five minutes.
3315
+ * Tighten it only if your clocks are disciplined.
3316
+ */
3317
+ toleranceSeconds?: number;
3318
+ /**
3319
+ * The current time in unix SECONDS. Defaults to the system clock; pass it
3320
+ * to verify a delivery captured earlier, or from a test.
3321
+ */
3322
+ nowSeconds?: number;
3323
+ }
3324
+ /**
3325
+ * Verify a webhook delivery, or throw explaining which check failed.
3326
+ *
3327
+ * ```ts
3328
+ * app.post("/langwatch", express.raw({ type: "application/json" }), (req, res) => {
3329
+ * try {
3330
+ * verifyWebhookSignature({
3331
+ * body: req.body, // the raw Buffer, before JSON parsing
3332
+ * header: req.header("X-LangWatch-Signature") ?? "",
3333
+ * secret: [process.env.WEBHOOK_SECRET_NEW, process.env.WEBHOOK_SECRET_OLD],
3334
+ * });
3335
+ * } catch (error) {
3336
+ * return res.status(400).send((error as WebhookSignatureVerificationError).code);
3337
+ * }
3338
+ * // Trusted from here.
3339
+ * });
3340
+ * ```
3341
+ *
3342
+ * Throws rather than returning false so that a delivery cannot be trusted by
3343
+ * forgetting to check a return value. The thrown
3344
+ * {@link WebhookSignatureVerificationError} carries a
3345
+ * {@link WebhookSignatureFailureCode} saying which check failed.
3346
+ *
3347
+ * Checks run in a fixed order, so a delivery that is both stale and wrongly
3348
+ * signed reports the staleness: a header that did not parse has no
3349
+ * trustworthy timestamp to judge, and a timestamp outside the window makes
3350
+ * the digest moot.
3351
+ *
3352
+ * A missing or empty secret is a configuration mistake rather than a bad
3353
+ * delivery, and raises `TypeError`. Reporting it as a failed verification
3354
+ * would let a receiver that lost its secret quietly refuse every delivery as
3355
+ * if the sender were at fault.
3356
+ */
3357
+ declare function verifyWebhookSignature(options: VerifyWebhookSignatureOptions): void;
2460
3358
 
2461
3359
  declare const logger: {
2462
3360
  ConsoleLogger: typeof ConsoleLogger;
2463
3361
  NoOpLogger: typeof NoOpLogger;
2464
3362
  };
2465
3363
 
2466
- export { type BatchCreateRecordsResponse, type BudgetOnBreach, type BudgetScopeKind, type BudgetWindow, type CreateDatasetOptions, type CreateEvaluatorBody, type CreateFromUploadResponse, type CreateGatewayBudgetInput, type CreateGatewayBudgetScope, type CreateVirtualKeyInput, type Dataset, DatasetApiError, type DatasetColumnType, type DatasetEntry, DatasetError, type DatasetListItem, type DatasetMetadata, DatasetNotFoundError, DatasetPlanLimitError, type DatasetRecordResponse, DatasetValidationError, DatasetsFacade, type DeleteRecordsResponse, type EvaluateOptions, type EvaluationCost, EvaluationError, type EvaluationResult, type EvaluationStatus, EvaluationsApiError, EvaluationsFacade, EvaluatorCallError, EvaluatorError, type EvaluatorField, EvaluatorNotFoundError, type EvaluatorResponse, EvaluatorsApiError, EvaluatorsApiService, Experiment, ExperimentApiError, ExperimentError, type EvaluateOptions$1 as ExperimentEvaluateOptions, type EvaluationResult$1 as ExperimentEvaluationResult, type EvaluationStatus$1 as ExperimentEvaluationStatus, ExperimentInitError, type ExperimentInitOptions, type ExperimentRowResult, type ExperimentRunWithResults, ExperimentsFacade, FetchPolicy, type GatewayBudget, type GatewayBudgetList, GatewayBudgetsApiError, GatewayBudgetsApiService, type GetDatasetOptions, type GetPromptOptions, LangWatch, LangWatchApiError, LangWatchHandledError, type ListDatasetsApiResponse, type ListDatasetsOptions, type ListRecordsApiResponse, type ListRecordsOptions, type LogOptions, type PaginatedResponse, type Pagination, type RunCallback, type RunContext, type RunOptions, type RunWithResultsOptions, type TargetInfo, type TargetMetadata, TargetMetadataConflictError, type TargetType, type UpdateDatasetOptions, type UpdateGatewayBudgetInput, type UpdateVirtualKeyInput, type UploadResponse, type VirtualKey, type VirtualKeyBudgetInput, type VirtualKeyRoutingMode, type VirtualKeyScope, type VirtualKeyScopeType, type VirtualKeySpendSummary, type VirtualKeyWithSecret, VirtualKeysApiError, VirtualKeysApiService, isLangWatchHandledError, logger };
3364
+ export { type BatchCreateRecordsResponse, type BudgetOnBreach, type BudgetScopeKind, type BudgetWindow, type CreateDatasetOptions, type CreateEvaluatorBody, type CreateFromUploadResponse, type CreateGatewayBudgetInput, type CreateGatewayBudgetScope, type CreateVirtualKeyInput, type CreateWebhookEndpointInput, type Dataset, DatasetApiError, type DatasetColumnType, type DatasetEntry, DatasetError, type DatasetListItem, type DatasetMetadata, DatasetNotFoundError, DatasetPlanLimitError, type DatasetRecordResponse, DatasetValidationError, DatasetsFacade, type DeleteRecordsResponse, type EmittedEvent, type EmittedEventsPage, type EndUserCap, type EndUserSpend, type EvaluateOptions, type EvaluationCost, EvaluationError, type EvaluationResult, type EvaluationStatus, EvaluationsApiError, EvaluationsFacade, EvaluatorCallError, EvaluatorError, type EvaluatorField, EvaluatorNotFoundError, type EvaluatorResponse, EvaluatorsApiError, EvaluatorsApiService, Experiment, ExperimentApiError, ExperimentError, type EvaluateOptions$1 as ExperimentEvaluateOptions, type EvaluationResult$1 as ExperimentEvaluationResult, type EvaluationStatus$1 as ExperimentEvaluationStatus, ExperimentInitError, type ExperimentInitOptions, type ExperimentRowResult, type ExperimentRunWithResults, ExperimentsFacade, FetchPolicy, type GatewayBudget, type GatewayBudgetPage, GatewayBudgetsApiError, GatewayBudgetsApiService, type GetDatasetOptions, type GetPromptOptions, IDEMPOTENCY_KEY_HEADER, IDEMPOTENT_REPLAY_HEADER, type IdempotentCreateOptions, LangWatch, LangWatchApiError, LangWatchHandledError, type ListDatasetsApiResponse, type ListDatasetsOptions, type ListRecordsApiResponse, type ListRecordsOptions, type LogOptions, type MutationOptions, type PaginatedResponse, type Pagination, type RunCallback, type RunContext, type RunOptions, type RunWithResultsOptions, type SpendEvent, type SpendEventStatus, SpendEventsApiError, SpendEventsApiService, type SpendEventsPage, type SpendReplayResult, type SpendSummariesPage, type SpendSummaryRow, type TargetInfo, type TargetMetadata, TargetMetadataConflictError, type TargetType, type UpdateDatasetOptions, type UpdateGatewayBudgetInput, type UpdateVirtualKeyInput, type UpdateWebhookEndpointInput, type UploadResponse, type VerifyWebhookSignatureOptions, type VirtualKey, type VirtualKeyBudgetInput, type VirtualKeyPage, type VirtualKeyRoutingMode, type VirtualKeyScope, type VirtualKeyScopeType, type VirtualKeySpendSummary, type VirtualKeyWithSecret, VirtualKeysApiError, VirtualKeysApiService, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_SIGNATURE_DEFAULT_TOLERANCE_SECONDS, WEBHOOK_SIGNATURE_HEADER, type WebhookDeliveryPage, type WebhookDeliveryRecord, type WebhookEndpointHealth, type WebhookEndpointSummary, type WebhookEndpointWithSecret, type WebhookEventType, type WebhookSignatureFailureCode, WebhookSignatureVerificationError, type WebhookTestResult, WebhooksApiError, WebhooksApiService, isLangWatchHandledError, logger, verifyWebhookSignature };