langwatch 1.19.0 → 2.0.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 (91) hide show
  1. package/README.md +27 -13
  2. package/dist/agent/index.d.mts +122 -79
  3. package/dist/agent/index.d.ts +122 -79
  4. package/dist/agent/index.js +541 -301
  5. package/dist/agent/index.js.map +1 -1
  6. package/dist/agent/index.mjs +540 -302
  7. package/dist/agent/index.mjs.map +1 -1
  8. package/dist/{chunk-NPEK4RSD.mjs → chunk-2GKEMCKT.mjs} +7757 -2409
  9. package/dist/chunk-2GKEMCKT.mjs.map +1 -0
  10. package/dist/chunk-5VYEG3RS.js +117 -0
  11. package/dist/chunk-5VYEG3RS.js.map +1 -0
  12. package/dist/chunk-AYPQNLCC.mjs +852 -0
  13. package/dist/chunk-AYPQNLCC.mjs.map +1 -0
  14. package/dist/chunk-BL3GHEKF.js +59 -0
  15. package/dist/chunk-BL3GHEKF.js.map +1 -0
  16. package/dist/chunk-C7IWJ2GJ.mjs +59 -0
  17. package/dist/chunk-C7IWJ2GJ.mjs.map +1 -0
  18. package/dist/chunk-DLZCOUXC.js +852 -0
  19. package/dist/chunk-DLZCOUXC.js.map +1 -0
  20. package/dist/{chunk-O4J3ZPZY.js → chunk-F7BVJW3S.js} +7912 -2564
  21. package/dist/chunk-F7BVJW3S.js.map +1 -0
  22. package/dist/{chunk-SY5HSL5G.mjs → chunk-M3DSPR5S.mjs} +124 -112
  23. package/dist/chunk-M3DSPR5S.mjs.map +1 -0
  24. package/dist/{chunk-CSV7B7B5.js → chunk-MAO3SIBB.js} +141 -129
  25. package/dist/chunk-MAO3SIBB.js.map +1 -0
  26. package/dist/{chunk-LCG5Y2EG.js → chunk-N76BG37W.js} +15 -101
  27. package/dist/chunk-N76BG37W.js.map +1 -0
  28. package/dist/chunk-SERULD4Z.mjs +117 -0
  29. package/dist/chunk-SERULD4Z.mjs.map +1 -0
  30. package/dist/{chunk-73QOHSHU.js → chunk-WDUUAIG3.js} +2 -2
  31. package/dist/chunk-WDUUAIG3.js.map +1 -0
  32. package/dist/{chunk-WMDQVWA6.mjs → chunk-WSGVZ3J2.mjs} +22 -108
  33. package/dist/chunk-WSGVZ3J2.mjs.map +1 -0
  34. package/dist/{chunk-57L2K66L.mjs → chunk-XQ4CP2JK.mjs} +2 -2
  35. package/dist/chunk-XQ4CP2JK.mjs.map +1 -0
  36. package/dist/cli/bundle.js +853 -552
  37. package/dist/implementation-BXVPzwOt.d.mts +261 -0
  38. package/dist/implementation-DJ-JveZl.d.ts +261 -0
  39. package/dist/index.d.mts +479 -1130
  40. package/dist/index.d.ts +479 -1130
  41. package/dist/index.js +7908 -3525
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +7883 -3500
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/observability-sdk/index.d.mts +16 -76
  46. package/dist/observability-sdk/index.d.ts +16 -76
  47. package/dist/observability-sdk/index.js +8 -5
  48. package/dist/observability-sdk/index.js.map +1 -1
  49. package/dist/observability-sdk/index.mjs +13 -10
  50. package/dist/observability-sdk/instrumentation/langchain/index.d.mts +3 -5
  51. package/dist/observability-sdk/instrumentation/langchain/index.d.ts +3 -5
  52. package/dist/observability-sdk/instrumentation/langchain/index.js +160 -112
  53. package/dist/observability-sdk/instrumentation/langchain/index.js.map +1 -1
  54. package/dist/observability-sdk/instrumentation/langchain/index.mjs +148 -100
  55. package/dist/observability-sdk/instrumentation/langchain/index.mjs.map +1 -1
  56. package/dist/observability-sdk/semconv/index.d.mts +37 -0
  57. package/dist/observability-sdk/semconv/index.d.ts +37 -0
  58. package/dist/observability-sdk/semconv/index.js +121 -0
  59. package/dist/observability-sdk/semconv/index.js.map +1 -0
  60. package/dist/observability-sdk/semconv/index.mjs +121 -0
  61. package/dist/observability-sdk/semconv/index.mjs.map +1 -0
  62. package/dist/observability-sdk/setup/node/index.d.mts +73 -313
  63. package/dist/observability-sdk/setup/node/index.d.ts +73 -313
  64. package/dist/observability-sdk/setup/node/index.js +6 -4
  65. package/dist/observability-sdk/setup/node/index.js.map +1 -1
  66. package/dist/observability-sdk/setup/node/index.mjs +5 -3
  67. package/dist/types--ExXvd26.d.mts +16583 -0
  68. package/dist/{types-VOZv9LYO.d.ts → types-CoS5PmeU.d.mts} +22 -59
  69. package/dist/{types-VOZv9LYO.d.mts → types-CoS5PmeU.d.ts} +22 -59
  70. package/dist/types-CpT3iEIj.d.ts +16583 -0
  71. package/dist/{types-DLfhJb38.d.mts → types-RkiBQZ9j.d.mts} +1 -6
  72. package/dist/{types-DLfhJb38.d.ts → types-RkiBQZ9j.d.ts} +1 -6
  73. package/dist/values-1yj9l0Sa.d.mts +112 -0
  74. package/dist/values-1yj9l0Sa.d.ts +112 -0
  75. package/package.json +94 -64
  76. package/dist/chunk-57L2K66L.mjs.map +0 -1
  77. package/dist/chunk-73QOHSHU.js.map +0 -1
  78. package/dist/chunk-CSV7B7B5.js.map +0 -1
  79. package/dist/chunk-LCG5Y2EG.js.map +0 -1
  80. package/dist/chunk-NPEK4RSD.mjs.map +0 -1
  81. package/dist/chunk-O4J3ZPZY.js.map +0 -1
  82. package/dist/chunk-PIYOJF6V.mjs +0 -566
  83. package/dist/chunk-PIYOJF6V.mjs.map +0 -1
  84. package/dist/chunk-SY5HSL5G.mjs.map +0 -1
  85. package/dist/chunk-WGLVIV4J.js +0 -566
  86. package/dist/chunk-WGLVIV4J.js.map +0 -1
  87. package/dist/chunk-WMDQVWA6.mjs.map +0 -1
  88. package/dist/implementation-CeTvnq6e.d.mts +0 -716
  89. package/dist/implementation-CsQrexpY.d.ts +0 -716
  90. package/dist/types-ofe1fAYQ.d.mts +0 -38143
  91. package/dist/types-wuYJPoFb.d.ts +0 -38143
package/dist/index.d.ts CHANGED
@@ -1,18 +1,18 @@
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-CsQrexpY.js';
2
+ export { F as FilterableBatchSpanProcessor, L as LangWatchExporter, S as SpanProcessingExcludeRule, g as getLangWatchLogger, a as getLangWatchTracer } from './implementation-DJ-JveZl.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-wuYJPoFb.js';
5
4
  import openApiCreateClient from 'openapi-fetch';
6
- export { l as attributes } from './types-VOZv9LYO.js';
7
- import { CliHandledErrorReason, CliHandledError } from '@langwatch/langy/cards/handled-error';
8
- export { CliHandledErrorReason as LangWatchHandledErrorReason, CliHandledError as LangWatchHandledErrorShape } from '@langwatch/langy/cards/handled-error';
5
+ 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-CpT3iEIj.js';
6
+ export { l as attributes } from './types-CoS5PmeU.js';
7
+ import { LangWatchHandledErrorReason, LangWatchHandledErrorShape } from '@langwatch/handled-error/langwatch-handled-error';
8
+ export { LangWatchHandledErrorReason, LangWatchHandledErrorShape } from '@langwatch/handled-error/langwatch-handled-error';
9
9
  import '@opentelemetry/sdk-trace-base';
10
- import '@opentelemetry/exporter-trace-otlp-http';
11
10
  import '@opentelemetry/core';
11
+ import '@opentelemetry/exporter-trace-otlp-proto';
12
+ import '@opentelemetry/otlp-exporter-base';
12
13
  import '@opentelemetry/api-logs';
14
+ import './values-1yj9l0Sa.js';
13
15
  import '@opentelemetry/api';
14
- import '@opentelemetry/semantic-conventions';
15
- import '@opentelemetry/semantic-conventions/incubating';
16
16
 
17
17
  declare const localPromptConfigSchema: z.ZodObject<{
18
18
  model: z.ZodString;
@@ -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.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>>>;
31
+ parameters: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodJSONSchema>>>;
32
32
  }, z.core.$loose>;
33
33
  type LocalPromptConfig = z.infer<typeof localPromptConfigSchema>;
34
34
 
@@ -40,10 +40,9 @@ type PromptsConfig = {
40
40
  prompts: Record<string, PromptDependency>;
41
41
  };
42
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.
43
+ * A JSON value: what runtime parameters persist and the API schema declares.
44
+ * Structurally identical to the generated client's RecursiveJsonValue, so
45
+ * values flow between hand-written and generated types without casts.
47
46
  */
48
47
  type JsonValue = string | number | boolean | null | JsonValue[] | {
49
48
  [key: string]: JsonValue;
@@ -55,15 +54,15 @@ type MaterializedPrompt = {
55
54
  version: number;
56
55
  versionId: string;
57
56
  model: string;
58
- messages: Array<{
57
+ messages: {
59
58
  role: "system" | "user" | "assistant";
60
59
  content: string;
61
- }>;
60
+ }[];
62
61
  prompt: string;
63
62
  temperature?: number;
64
63
  maxTokens?: number;
65
- inputs?: any;
66
- outputs?: any;
64
+ inputs?: unknown;
65
+ outputs?: unknown;
67
66
  parameters: RuntimeParameters;
68
67
  updatedAt: string;
69
68
  };
@@ -79,13 +78,8 @@ type PromptsLock = {
79
78
 
80
79
  /**
81
80
  * Creates a new LangWatch API client.
82
- * @param apiKey - The API key or Personal Access Token used for authentication.
83
- * Defaults to `LANGWATCH_API_KEY`.
84
- * @param endpoint - The endpoint to use for the API client. Defaults to `LANGWATCH_ENDPOINT`
85
- * or the internal `DEFAULT_ENDPOINT`.
86
- * @param projectId - Project identifier. Required when `apiKey` is a PAT
87
- * (`pat-lw-*`). Defaults to `LANGWATCH_PROJECT_ID`.
88
- * @returns A new LangWatch API client.
81
+ * @param apiKey - The API key or Personal Access Token. Defaults to `LANGWATCH_API_KEY`.
82
+ * @param endpoint - The API endpoint. Defaults to `LANGWATCH_ENDPOINT` or `DEFAULT_ENDPOINT`.
89
83
  */
90
84
  declare const createLangWatchApiClient: (apiKey?: string, endpoint?: string, projectId?: string | undefined) => openApiCreateClient.Client<paths, `${string}/${string}`>;
91
85
  type LangwatchApiClient = ReturnType<typeof createLangWatchApiClient>;
@@ -103,7 +97,7 @@ declare const syncActionSchema: z.ZodEnum<{
103
97
  }>;
104
98
  type SyncAction = z.infer<typeof syncActionSchema>;
105
99
  type AssignTagResult = NonNullable<operations["putApiPromptsByIdTagsByTag"]["responses"]["200"]["content"]["application/json"]>;
106
- type ConfigData = NonNullable<paths["/api/prompts/{id}/sync"]["post"]["requestBody"]>["content"]["application/json"]["configData"];
100
+ type ConfigData = NonNullable<paths["/api/v1/prompts/{id}/sync"]["post"]["requestBody"]>["content"]["application/json"]["configData"];
107
101
  interface SyncResult {
108
102
  action: SyncAction;
109
103
  prompt?: PromptResponse;
@@ -116,24 +110,16 @@ interface SyncResult {
116
110
  };
117
111
  }
118
112
  /**
119
- * Service for managing prompt resources via the Langwatch API.
120
- * Constructor creates a proxy that wraps the service and traces all methods.
121
- *
122
- * Responsibilities:
123
- * - CRUD operations for prompts
124
- * - Creating prompt versions
125
- * - Error handling with contextual information
126
- *
127
- * All methods return raw PromptResponse data from the API.
113
+ * Service for managing prompt resources via the Langwatch API. Constructor creates a proxy
114
+ * that wraps the service and traces all methods.
128
115
  */
129
116
  declare class PromptsApiService {
130
117
  private readonly apiClient;
131
118
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
132
119
  /**
133
- * Handles API errors by throwing a PromptsApiError with operation context.
120
+ * Handles API errors by throwing a PromptsApiError with operation context. @throws
134
121
  * @param operation Description of the operation being performed.
135
122
  * @param error The error object returned from the API client.
136
- * @throws {PromptsApiError}
137
123
  */
138
124
  private handleApiError;
139
125
  /**
@@ -145,36 +131,28 @@ declare class PromptsApiService {
145
131
  /**
146
132
  * Fetches a single prompt by its ID.
147
133
  * @param id The prompt's unique identifier.
148
- * @param options Optional parameters for the request.
149
- * @param options.version Specific version to fetch (numeric string or "latest").
150
- * @param options.tag Tag to fetch (e.g., "production", "staging", or a custom tag).
151
- * @returns Raw PromptResponse data.
152
- * @throws {PromptsApiError} If the API call fails.
134
+ * @param options Optional version or tag to fetch.
153
135
  */
154
136
  get: (id: string, options?: {
155
137
  version?: string;
156
138
  tag?: string;
157
139
  }) => Promise<PromptResponse>;
158
140
  /**
159
- * Validates if a prompt exists.
141
+ * Validates if a prompt exists. @throws {PromptsApiError} If the API call fails (not 404).
160
142
  * @param id The prompt's unique identifier.
161
143
  * @returns True if prompt exists, false otherwise.
162
- * @throws {PromptsApiError} If the API call fails (not 404).
163
144
  */
164
145
  exists(id: string): Promise<boolean>;
165
146
  /**
166
- * Creates a new prompt.
147
+ * Creates a new prompt. @throws {PromptsApiError} If the API call fails.
167
148
  * @param params The prompt creation payload, matching the OpenAPI schema.
168
149
  * @returns Raw PromptResponse data of the created prompt.
169
- * @throws {PromptsApiError} If the API call fails.
170
150
  */
171
151
  create(params: CreatePromptBody): Promise<PromptResponse>;
172
152
  /**
173
- * Updates an existing prompt.
174
153
  * @param id The prompt's unique identifier.
175
154
  * @param params The update payload, matching the OpenAPI schema.
176
155
  * @returns Raw PromptResponse data of the updated prompt.
177
- * @throws {PromptsApiError} If the API call fails.
178
156
  */
179
157
  update(id: string, params: UpdatePromptBody): Promise<PromptResponse>;
180
158
  /**
@@ -184,10 +162,9 @@ declare class PromptsApiService {
184
162
  */
185
163
  listTags(): Promise<TagDefinition[]>;
186
164
  /**
187
- * Creates a custom prompt tag for the organization.
165
+ * Creates a custom prompt tag for the organization. @throws {PromptsApiError} If the API
188
166
  * @param params.name The tag name (must match /^[a-z][a-z0-9_-]*$/).
189
167
  * @returns The created tag.
190
- * @throws {PromptsApiError} If the API call fails.
191
168
  */
192
169
  createTag({ name }: {
193
170
  name: string;
@@ -199,10 +176,9 @@ declare class PromptsApiService {
199
176
  */
200
177
  deleteTag(tagName: string): Promise<void>;
201
178
  /**
202
- * Renames an existing prompt tag.
179
+ * Renames an existing prompt tag. @throws {PromptsApiError} If the API call fails.
203
180
  * @param tag The current tag name.
204
181
  * @param name The new tag name.
205
- * @throws {PromptsApiError} If the API call fails.
206
182
  */
207
183
  renameTag({ tag, name }: {
208
184
  tag: string;
@@ -222,18 +198,15 @@ declare class PromptsApiService {
222
198
  success: boolean;
223
199
  }>;
224
200
  /**
225
- * Fetches all versions for a given prompt.
201
+ * Fetches all versions for a given prompt. @throws {PromptsApiError} If the API call
226
202
  * @param id The prompt's unique identifier.
227
203
  * @returns Array of raw PromptResponse data for each version.
228
- * @throws {PromptsApiError} If the API call fails.
229
204
  */
230
205
  getVersions(id: string): Promise<PromptResponse[]>;
231
206
  /**
232
- * Upserts a prompt with local configuration - creates if doesn't exist, updates version if exists.
233
207
  * @param handle The prompt's handle/identifier.
234
208
  * @param config Local prompt configuration.
235
209
  * @returns Object with created flag and raw PromptResponse data.
236
- * @throws {PromptsApiError} If the API call fails.
237
210
  */
238
211
  upsert(handle: string, config: {
239
212
  model: string;
@@ -241,10 +214,10 @@ declare class PromptsApiService {
241
214
  temperature?: number;
242
215
  max_tokens?: number;
243
216
  };
244
- messages: Array<{
217
+ messages: {
245
218
  role: "system" | "user" | "assistant";
246
219
  content: string;
247
- }>;
220
+ }[];
248
221
  parameters?: RuntimeParameters;
249
222
  }): Promise<{
250
223
  created: boolean;
@@ -269,15 +242,8 @@ declare class FileManager {
269
242
  private static readonly PROMPTS_DIR;
270
243
  private static readonly MATERIALIZED_DIR;
271
244
  private static _projectRoot;
272
- /**
273
- * The cwd `_projectRoot` was derived from.
274
- *
275
- * The cache MUST be keyed by it. Memoising a cwd-derived path without that key
276
- * is correct only in a process that serves exactly one command and then dies;
277
- * in a process that serves many from different directories (the CLI daemon, a
278
- * test runner, an embedding host), the second caller silently inherits the
279
- * first caller's project root and reads or writes the wrong prompts.json.
280
- */
245
+ /** The cwd `_projectRoot` was derived from. Cache must be keyed by it or
246
+ * multi-directory processes like daemons will use the wrong root. */
281
247
  private static _projectRootCwd;
282
248
  /** Reset the cached project root. Tests use this to exercise different cwds. */
283
249
  static _resetProjectRootCache(): void;
@@ -320,12 +286,9 @@ interface LocalPromptsServiceConfig {
320
286
  logger?: Logger;
321
287
  }
322
288
  /**
323
- * Service for retrieving prompts from local filesystem sources.
324
- *
325
- * Searches for prompts in the following priority order:
326
- * 1. Explicit file mapping in prompts.json config
327
- * 2. Materialized path from prompts-lock.json
328
- * 3. Direct file scanning in prompts directory
289
+ * Retrieves prompts from local filesystem sources, in priority order:
290
+ * explicit prompts.json mapping, materialized prompts-lock.json path,
291
+ * then direct scanning of the prompts directory.
329
292
  */
330
293
  declare class LocalPromptsService {
331
294
  private readonly fileManager;
@@ -408,11 +371,7 @@ declare class PromptsFacade implements Pick<PromptsApiService, "sync" | "delete"
408
371
  */
409
372
  create(data: CreatePromptBody): Promise<Prompt>;
410
373
  /**
411
- * Retrieves a prompt by handle or ID.
412
- *
413
- * Supports shorthand `handle:tag` syntax — e.g. `get("pizza-prompt:production")`.
414
- * Shorthand is parsed server-side; the SDK passes the string through as-is.
415
- *
374
+ * Retrieves a prompt by handle or ID (supports `handle:tag` shorthand, parsed server-side).
416
375
  * @param handleOrId The prompt's handle, unique identifier, or `handle:tag` shorthand.
417
376
  * @param options Optional parameters for the request.
418
377
  * @returns The Prompt instance.
@@ -597,8 +556,8 @@ type DeleteRecordsResponse = {
597
556
  deletedCount: number;
598
557
  };
599
558
  /**
600
- * API response for uploading a file.
601
- * Covers both upload-to-existing (records) and create-from-file (recordsCreated, datasetId) responses.
559
+ * API response for uploading a file. Covers both upload-to-existing
560
+ * (records) and create-from-file (recordsCreated, datasetId) responses.
602
561
  */
603
562
  type UploadResponse = {
604
563
  dataset?: DatasetMetadata;
@@ -618,7 +577,10 @@ type ListRecordsOptions = {
618
577
  /**
619
578
  * API response for listing records in a dataset.
620
579
  */
621
- type ListRecordsApiResponse = PaginatedResponse<DatasetRecordResponse>;
580
+ type ListRecordsApiResponse = PaginatedResponse<DatasetRecordResponse> & {
581
+ /** The dataset the page belongs to. Absent on servers that do not send it. */
582
+ dataset?: DatasetMetadata;
583
+ };
622
584
  /**
623
585
  * API response for creating a dataset from a file upload.
624
586
  */
@@ -635,91 +597,33 @@ type DatasetsFacadeConfig = {
635
597
  };
636
598
  /**
637
599
  * Facade for dataset operations in the LangWatch SDK.
638
- * Provides a simplified interface for managing datasets, records, and file uploads.
639
- *
640
600
  * @example
641
- * ```typescript
642
- * const langwatch = new LangWatch({ apiKey: "your-api-key" });
643
- *
644
- * // List all datasets
645
601
  * const datasets = await langwatch.datasets.list();
646
- *
647
- * // Get a dataset by slug or ID
648
- * const dataset = await langwatch.datasets.get("my-dataset");
649
- *
650
- * // Create a new dataset
651
- * const newDataset = await langwatch.datasets.create({
652
- * name: "my-dataset",
653
- * columnTypes: [{ name: "input", type: "string" }],
654
- * });
655
- *
656
- * // Update a dataset
657
- * const updated = await langwatch.datasets.update("my-dataset", { name: "new-name" });
658
- *
659
- * // Delete a dataset
660
- * const archived = await langwatch.datasets.delete("my-dataset");
661
- *
662
- * // Create records
663
- * const records = await langwatch.datasets.createRecords("my-dataset", [
664
- * { input: "hello", output: "world" },
665
- * ]);
666
- *
667
- * // Update a record
668
- * const record = await langwatch.datasets.updateRecord("my-dataset", "rec-1", { input: "updated" });
669
- *
670
- * // Delete records
671
- * const result = await langwatch.datasets.deleteRecords("my-dataset", ["rec-1", "rec-2"]);
672
- *
673
- * // Upload a file (append to existing or create new)
674
- * const uploadResult = await langwatch.datasets.upload("my-dataset", file);
675
- *
676
- * // Upload with replace strategy (delete all records first)
677
- * await langwatch.datasets.upload("my-dataset", file, { ifExists: "replace" });
678
- * ```
679
602
  */
680
603
  declare class DatasetsFacade {
681
604
  #private;
682
605
  constructor(config: DatasetsFacadeConfig);
683
606
  /**
684
607
  * Lists all datasets for the project, with optional pagination.
685
- *
686
608
  * @param options - Pagination options (page, limit)
687
609
  * @returns Paginated list of datasets with metadata
688
610
  */
689
611
  list: (options?: ListDatasetsOptions) => Promise<ListDatasetsApiResponse>;
690
612
  /**
691
613
  * Creates a new dataset.
692
- *
693
614
  * @param options - Dataset creation options (name, columnTypes)
694
615
  * @returns The created dataset metadata
695
616
  */
696
617
  create: (options: CreateDatasetOptions) => Promise<DatasetMetadata>;
697
618
  /**
698
619
  * Fetches a dataset by its slug or ID, returning metadata and entries.
699
- *
700
620
  * @param slugOrId - The slug or ID of the dataset to fetch
701
621
  * @param options - Optional configuration
702
622
  * @returns The dataset with metadata and entries
703
- *
704
- * @example
705
- * ```typescript
706
- * // Get dataset by slug
707
- * const dataset = await langwatch.datasets.get("product-qa");
708
- *
709
- * // Typed dataset
710
- * type MyDatasetEntry = { input: string; expected_output: string; };
711
- * const dataset = await langwatch.datasets.get<MyDatasetEntry>("my-dataset");
712
- *
713
- * // Iterate over entries
714
- * for (const entry of dataset.entries) {
715
- * console.log(entry.entry.input);
716
- * }
717
- * ```
718
623
  */
719
624
  get: <T extends Record<string, unknown> = Record<string, unknown>>(slugOrId: string, options?: GetDatasetOptions) => Promise<Dataset<T>>;
720
625
  /**
721
626
  * Updates a dataset by its slug or ID.
722
- *
723
627
  * @param slugOrId - The slug or ID of the dataset to update
724
628
  * @param options - Fields to update (name, columnTypes)
725
629
  * @returns The updated dataset metadata
@@ -727,14 +631,12 @@ declare class DatasetsFacade {
727
631
  update: (slugOrId: string, options: UpdateDatasetOptions) => Promise<DatasetMetadata>;
728
632
  /**
729
633
  * Deletes (archives) a dataset by its slug or ID.
730
- *
731
634
  * @param slugOrId - The slug or ID of the dataset to delete
732
635
  * @returns The archived dataset metadata
733
636
  */
734
637
  delete: (slugOrId: string) => Promise<DatasetMetadata>;
735
638
  /**
736
639
  * Creates records in a dataset in batch.
737
- *
738
640
  * @param slugOrId - The slug or ID of the dataset
739
641
  * @param entries - Array of record entries to create
740
642
  * @returns The created records with IDs
@@ -742,7 +644,6 @@ declare class DatasetsFacade {
742
644
  createRecords: (slugOrId: string, entries: Record<string, unknown>[]) => Promise<BatchCreateRecordsResponse>;
743
645
  /**
744
646
  * Updates a single record in a dataset.
745
- *
746
647
  * @param slugOrId - The slug or ID of the dataset
747
648
  * @param recordId - The ID of the record to update
748
649
  * @param entry - The updated entry data
@@ -751,7 +652,6 @@ declare class DatasetsFacade {
751
652
  updateRecord: (slugOrId: string, recordId: string, entry: Record<string, unknown>) => Promise<DatasetRecordResponse>;
752
653
  /**
753
654
  * Deletes records from a dataset by IDs.
754
- *
755
655
  * @param slugOrId - The slug or ID of the dataset
756
656
  * @param recordIds - Array of record IDs to delete
757
657
  * @returns Object with the count of deleted records
@@ -759,47 +659,17 @@ declare class DatasetsFacade {
759
659
  deleteRecords: (slugOrId: string, recordIds: string[]) => Promise<DeleteRecordsResponse>;
760
660
  /**
761
661
  * Lists records in a dataset with optional pagination.
762
- *
763
662
  * @param slugOrId - The slug or ID of the dataset
764
663
  * @param options - Pagination options (page, limit)
765
664
  * @returns Paginated list of records
766
- *
767
- * @example
768
- * ```typescript
769
- * // List first page of records
770
- * const result = await langwatch.datasets.listRecords("my-dataset");
771
- *
772
- * // With pagination
773
- * const page2 = await langwatch.datasets.listRecords("my-dataset", { page: 2, limit: 25 });
774
- * ```
775
665
  */
776
666
  listRecords: (slugOrId: string, options?: ListRecordsOptions) => Promise<ListRecordsApiResponse>;
777
667
  /**
778
- * Uploads a file to a dataset with a configurable strategy for handling existing datasets.
779
- *
780
- * Strategies:
781
- * - `"append"` (default): Upload to existing dataset; if not found, create a new one.
782
- * - `"replace"`: Delete all existing records, then upload; if not found, create a new one.
783
- * - `"error"`: Throw a 409 error if the dataset already exists; if not found, create a new one.
784
- *
668
+ * Uploads a file to a dataset with a strategy for existing datasets (default "append").
785
669
  * @param slugOrId - The slug or ID of the dataset
786
670
  * @param file - The file to upload (File or Blob)
787
671
  * @param options - Upload options including the ifExists strategy
788
672
  * @returns The upload result
789
- *
790
- * @example
791
- * ```typescript
792
- * const file = new File(["input,output\nhello,world"], "data.csv", { type: "text/csv" });
793
- *
794
- * // Append to existing or create new
795
- * await langwatch.datasets.upload("my-dataset", file);
796
- *
797
- * // Replace all records
798
- * await langwatch.datasets.upload("my-dataset", file, { ifExists: "replace" });
799
- *
800
- * // Fail if dataset already exists
801
- * await langwatch.datasets.upload("my-dataset", file, { ifExists: "error" });
802
- * ```
803
673
  */
804
674
  upload: (slugOrId: string, file: File | Blob, options?: {
805
675
  ifExists?: "append" | "replace" | "error";
@@ -851,15 +721,12 @@ declare class DatasetPlanLimitError extends DatasetError {
851
721
 
852
722
  /**
853
723
  * Types for the Experiments API
854
- *
855
- * These types define the structure for batch experiments, including
856
- * logging metrics, running evaluators, and managing targets.
857
724
  */
858
725
 
859
726
  /**
860
727
  * Status of an evaluation result
861
728
  */
862
- type EvaluationStatus$1 = "processed" | "error" | "skipped";
729
+ type ExperimentEvaluationStatus = "processed" | "error" | "skipped";
863
730
  /**
864
731
  * Target types for batch evaluations
865
732
  */
@@ -872,9 +739,9 @@ declare const targetInfoSchema: z.ZodObject<{
872
739
  id: z.ZodString;
873
740
  name: z.ZodString;
874
741
  type: z.ZodDefault<z.ZodEnum<{
742
+ prompt: "prompt";
875
743
  custom: "custom";
876
744
  agent: "agent";
877
- prompt: "prompt";
878
745
  }>>;
879
746
  metadata: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
880
747
  }, z.core.$strip>;
@@ -884,8 +751,8 @@ declare const evaluationResultSchema: z.ZodObject<{
884
751
  trace_id: z.ZodString;
885
752
  status: z.ZodEnum<{
886
753
  error: "error";
887
- processed: "processed";
888
754
  skipped: "skipped";
755
+ processed: "processed";
889
756
  }>;
890
757
  data: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
891
758
  score: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
@@ -906,7 +773,7 @@ type TargetInfo = z.infer<typeof targetInfoSchema>;
906
773
  /**
907
774
  * Result of an evaluation
908
775
  */
909
- type EvaluationResult$1 = z.infer<typeof evaluationResultSchema>;
776
+ type ExperimentEvaluationResult = z.infer<typeof evaluationResultSchema>;
910
777
  /**
911
778
  * Options for initializing an experiment
912
779
  */
@@ -936,7 +803,7 @@ type LogOptions = {
936
803
  /** Human-readable description of the result */
937
804
  details?: string;
938
805
  /** Status of the evaluation */
939
- status?: EvaluationStatus$1;
806
+ status?: ExperimentEvaluationStatus;
940
807
  /** Duration in milliseconds */
941
808
  duration?: number;
942
809
  /** Cost amount in USD */
@@ -954,7 +821,7 @@ type LogOptions = {
954
821
  /**
955
822
  * Options for the evaluate() method (built-in evaluators)
956
823
  */
957
- type EvaluateOptions$1 = {
824
+ type ExperimentEvaluateOptions = {
958
825
  /**
959
826
  * Row index in the dataset.
960
827
  * Optional when called inside withTarget() - will be auto-inferred from context.
@@ -978,25 +845,10 @@ type EvaluateOptions$1 = {
978
845
  };
979
846
  /**
980
847
  * Per-candidate metric the judge can be asked to weigh alongside quality
981
- *
982
- * Duration is the one the SDK measures itself. Cost is not on offer: the
983
- * platform works a target's cost out from its traces after the run, so there
984
- * is nothing to show the judge at the moment a verdict is asked for.
985
848
  */
986
849
  type ComparisonMetric = "duration";
987
850
  /**
988
851
  * Outcome of a comparison
989
- *
990
- * - `decided`: the judge picked a winner
991
- * - `tie`: the judge judged the candidates and found none clearly better
992
- * - `inconclusive`: the judge judged the candidates and established no winner,
993
- * which under swap-and-reconcile means its two passes disagreed. A finding
994
- * about the candidates, and not a tie: a tie is a measurement, this is the
995
- * absence of one
996
- * - `skipped`: fewer than two targets had an output, so no judge ran
997
- * - `error`: the judge could not be reached or failed, so nothing was measured
998
- * about the candidates at all. Never conflated with `inconclusive`, which
999
- * says something about them
1000
852
  */
1001
853
  type ComparisonStatus = "decided" | "tie" | "inconclusive" | "skipped" | "error";
1002
854
  /**
@@ -1017,20 +869,10 @@ type ComparisonVerdict = {
1017
869
  };
1018
870
  /**
1019
871
  * Options for the compare() method
1020
- *
1021
- * Every option below is optional because the judge already has a default for
1022
- * it. An option left unset is absent from the request, so the judge's own
1023
- * default applies and there is exactly one place where each default is
1024
- * written down. The defaults are documented here for reference only, and are
1025
- * deliberately not restated in code.
1026
872
  */
1027
873
  type ComparisonOptions = {
1028
874
  /**
1029
- * Row index in the dataset. Also seeds the judge's deterministic candidate
1030
- * shuffle.
1031
- *
1032
- * compare() takes the row the way log() does: inside a run() callback it is
1033
- * inferred from the row being processed, and outside one it is required.
875
+ * Row index in the dataset. Also seeds the judge's deterministic candidate shuffle.
1034
876
  */
1035
877
  index?: number;
1036
878
  /** Name the verdict is recorded under (default: "comparison") */
@@ -1130,13 +972,6 @@ type TargetResult<R> = {
1130
972
 
1131
973
  /**
1132
974
  * Experiment - Main class for running batch experiments
1133
- *
1134
- * Provides a clean API for running experiments over datasets with:
1135
- * - Automatic tracing per iteration
1136
- * - Parallel execution with concurrency control
1137
- * - Batched result sending
1138
- * - Built-in evaluator support
1139
- * - Multi-target comparison with withTarget() context isolation
1140
975
  */
1141
976
 
1142
977
  /**
@@ -1158,6 +993,9 @@ declare class Experiment {
1158
993
  private batch;
1159
994
  private lastSentMs;
1160
995
  private pendingFlush;
996
+ /** Every row and verdict sent so far, by the identity the platform stores it under. */
997
+ private readonly sentRows;
998
+ private readonly sentEvaluations;
1161
999
  private flushTimeout;
1162
1000
  private cumulativeEvaluations;
1163
1001
  private cumulativeEntries;
@@ -1181,44 +1019,23 @@ declare class Experiment {
1181
1019
  */
1182
1020
  private initialize;
1183
1021
  /**
1184
- * Run evaluation over a dataset with a callback
1185
- *
1022
+ * Run evaluation over a dataset with a callback.
1186
1023
  * @param dataset - Array of items to evaluate
1187
1024
  * @param callback - Function called for each item with { item, index, span }
1188
- * @param options - Concurrency options
1189
- *
1190
- * @example
1191
- * ```typescript
1192
- * await evaluation.run(dataset, async ({ item, index, span }) => {
1193
- * const response = await myAgent(item.question);
1194
- * evaluation.log('accuracy', { index, score: 0.95 });
1195
- * }, { concurrency: 4 });
1196
- * ```
1197
1025
  */
1198
1026
  run<T>(dataset: T[], callback: RunCallback<T>, options?: RunOptions): Promise<void>;
1199
1027
  /**
1200
1028
  * Execute a single item in the dataset
1201
1029
  */
1030
+ /** Runs one row without a trace of its own: each withTarget() call traces itself. */
1031
+ private runItemUntraced;
1032
+ /** Runs one row inside its own iteration span. */
1033
+ private runItemTraced;
1202
1034
  private executeItem;
1203
1035
  /**
1204
- * Log a custom metric result
1205
- *
1206
1036
  * @param metric - Name of the metric
1207
1037
  * @param options - Metric options including index, score, passed, etc.
1208
- *
1209
- * If called inside a withTarget() block, the target and index are automatically
1210
- * inferred from the context and don't need to be specified.
1211
- *
1212
1038
  * @example
1213
- * ```typescript
1214
- * // Explicit target (outside withTarget)
1215
- * evaluation.log('accuracy', { index, score: 0.95, target: 'gpt-4' });
1216
- *
1217
- * // Implicit target (inside withTarget)
1218
- * await evaluation.withTarget('gpt-4', { model: 'openai/gpt-4' }, async () => {
1219
- * evaluation.log('accuracy', { score: 0.95 }); // target and index auto-inferred
1220
- * });
1221
- * ```
1222
1039
  */
1223
1040
  log(metric: string, options: LogOptions): void;
1224
1041
  /**
@@ -1226,145 +1043,38 @@ declare class Experiment {
1226
1043
  */
1227
1044
  private pushEvaluation;
1228
1045
  /**
1229
- * Run a built-in evaluator
1230
- *
1231
1046
  * @param evaluatorSlug - The evaluator identifier (e.g., 'ragas/faithfulness')
1232
1047
  * @param options - Evaluator options including data and settings
1233
- *
1234
- * If called inside a withTarget() block, the target and index are automatically
1235
- * inferred from the context and don't need to be specified.
1236
- *
1237
1048
  * @example
1238
- * ```typescript
1239
- * // Inside withTarget() - target and index auto-inferred
1240
- * await evaluation.withTarget('gpt-4', { model: 'openai/gpt-4' }, async () => {
1241
- * await evaluation.evaluate('ragas/faithfulness', {
1242
- * data: { input, output, contexts },
1243
- * });
1244
- * });
1245
- *
1246
- * // Or explicit index/target
1247
- * await evaluation.evaluate('ragas/faithfulness', {
1248
- * index,
1249
- * data: { input, output, contexts },
1250
- * target: 'gpt-4',
1251
- * });
1252
- * ```
1253
- */
1254
- evaluate(evaluatorSlug: string, options: EvaluateOptions$1): Promise<void>;
1049
+ */
1050
+ evaluate(evaluatorSlug: string, options: ExperimentEvaluateOptions): Promise<void>;
1255
1051
  /**
1256
1052
  * Call an evaluator and return its raw result
1257
1053
  */
1258
1054
  private callEvaluator;
1259
1055
  /**
1260
- * Compare a row's targets and pick the best one
1261
- *
1262
- * Every target that recorded an output for the row is judged together in a
1263
- * single call, and the winner comes back named with the target name you
1264
- * registered. Call it once the row's withTarget() calls have all settled,
1265
- * which under the usual Promise.all is right after the await.
1266
- *
1267
- * The verdict grades no single target, so it is recorded against the row.
1268
- *
1269
- * The row is named the way log() names it: inside a run() callback it is
1270
- * inferred from the row being processed, and outside one it is required.
1271
- *
1272
- * A row with fewer than two outputs cannot be compared: it is recorded as
1273
- * skipped, naming the targets that produced nothing, and the run carries on.
1274
- * A judge that fails or cannot be reached comes back as an `error` verdict
1275
- * for the same reason, and stays distinct from `inconclusive`, which is the
1276
- * judge telling you something about your candidates. Naming a target that
1277
- * produced no output is a different thing again, and throws, because a
1278
- * two-way verdict read as the three-way one you asked for is worse than a
1279
- * failure.
1280
- *
1281
1056
  * @param options - How the judge should read the row, and which row when
1282
- * it cannot be inferred
1283
1057
  * @returns The verdict, including the candidates it actually saw
1284
- *
1285
1058
  * @example
1286
- * ```typescript
1287
- * await experiment.run(dataset, async ({ item }) => {
1288
- * await Promise.all([
1289
- * experiment.withTarget('gpt-5-mini', () => askGpt(item.question)),
1290
- * experiment.withTarget('claude-sonnet-5', () => askClaude(item.question)),
1291
- * ]);
1292
- *
1293
- * const verdict = await experiment.compare({ input: item.question });
1294
- * console.log(verdict.winner);
1295
- * });
1296
- * ```
1297
1059
  */
1298
1060
  compare(options?: ComparisonOptions): Promise<ComparisonVerdict>;
1299
1061
  /**
1300
1062
  * The row a comparison is about
1301
- *
1302
- * Inferred from the row being processed, the same way withTarget() and
1303
- * log() infer theirs, so a comparison inside a run() callback never repeats
1304
- * an index the SDK already has. It reads that row from the iteration's own
1305
- * context, which is what keeps a run of many rows at once from handing one
1306
- * row's comparison the row a neighbour happens to be on.
1307
- *
1308
- * What it deliberately does not do is fall back to a row: judging row 0
1309
- * because no row was named would hand back a confident verdict about
1310
- * candidates the caller never asked about.
1311
1063
  */
1312
1064
  private resolveComparisonRow;
1313
1065
  /**
1314
1066
  * Record a comparison verdict against the row
1315
- *
1316
- * The verdict the caller is handed is the only input, so the row can never
1317
- * say one thing while the return value says another.
1318
- *
1319
- * Deliberately not routed through log(): a comparison grades no single
1320
- * target, so it must not pick one up from an ambient withTarget() context,
1321
- * and it is recorded under the judge's own evaluator id so the results page
1322
- * can tell it apart from a hand-logged metric.
1323
1067
  */
1324
1068
  private recordComparison;
1325
1069
  /**
1326
- * Execute code within a target context with automatic tracing
1327
- *
1328
- * Creates a new span for this target execution and sets up context
1329
- * so that log() calls inside the callback automatically use this target.
1330
- * Duration and output are captured automatically.
1331
- *
1332
- * This creates a dataset entry per target (like Evaluations V3), enabling
1333
- * proper per-target latency and cost tracking.
1334
- *
1070
+ * Execute code within a target context with automatic tracing.
1335
1071
  * @param targetName - Unique identifier for the target
1336
- * @param metadata - Optional metadata for comparison (e.g., { model: 'gpt-4' })
1337
1072
  * @param callback - Function to execute within the target context
1338
- * @returns The callback result along with captured metrics
1339
- *
1340
- * @example
1341
- * ```typescript
1342
- * await evaluation.run(dataset, async ({ item, index }) => {
1343
- * // Compare GPT-4 and Claude on the same input
1344
- * const [gpt4Result, claudeResult] = await Promise.all([
1345
- * evaluation.withTarget('gpt-4', { model: 'openai/gpt-4' }, async () => {
1346
- * const response = await openai.chat(item.question);
1347
- * evaluation.log('quality', { score: 0.95 }); // target auto-inferred
1348
- * return response;
1349
- * }),
1350
- * evaluation.withTarget('claude-3', { model: 'anthropic/claude-3' }, async () => {
1351
- * const response = await anthropic.messages(item.question);
1352
- * evaluation.log('quality', { score: 0.85 }); // target auto-inferred
1353
- * return response;
1354
- * }),
1355
- * ]);
1356
- * });
1357
- * ```
1358
1073
  */
1359
1074
  withTarget<R>(targetName: string, metadata: TargetMetadata | null, callback: TargetCallback<R>): Promise<TargetResult<R>>;
1360
1075
  withTarget<R>(targetName: string, callback: TargetCallback<R>): Promise<TargetResult<R>>;
1361
1076
  /**
1362
1077
  * Keep a target's output for the row so compare() can reach it later
1363
- *
1364
- * The batch this output also went into is flushed on a timer and cleared, so
1365
- * a comparison that read its candidates from there would find them missing
1366
- * whenever the flush landed first. A target that produced nothing is not
1367
- * captured at all: it has no output to judge.
1368
1078
  */
1369
1079
  private captureTargetOutput;
1370
1080
  /**
@@ -1377,27 +1087,19 @@ declare class Experiment {
1377
1087
  private scheduleSend;
1378
1088
  /**
1379
1089
  * Print a CI-friendly summary and optionally exit with code 1 on failure.
1380
- *
1381
- * Mirrors `ExperimentRunResult.printSummary` for parity — SDK-driven experiments
1382
- * can now fail CI builds the same way platform experiments do.
1383
- *
1384
1090
  * @param exitOnFailure - If true (default), calls `process.exit(1)` when any evaluation failed.
1385
- *
1386
1091
  * @example
1387
- * ```typescript
1388
- * const experiment = await langwatch.experiments.init("ci-quality-check");
1389
- * await experiment.run(dataset, async ({ item, index }) => {
1390
- * const response = await myLLM(item.input);
1391
- * await experiment.evaluate("ragas/faithfulness", { index, data: { input: item.input, output: response } });
1392
- * });
1393
- * experiment.printSummary();
1394
- * ```
1395
1092
  */
1396
1093
  printSummary(exitOnFailure?: boolean): void;
1397
1094
  /**
1398
1095
  * Send current batch to the API
1399
1096
  */
1400
1097
  private sendBatch;
1098
+ /**
1099
+ * Posts one log_results request. A request the server refuses as too large is cut in two
1100
+ * and sent again. When a single entry is refused, the error names it and its size.
1101
+ */
1102
+ private postLogResults;
1401
1103
  /**
1402
1104
  * Flush all pending data
1403
1105
  */
@@ -1434,22 +1136,22 @@ type ExperimentRunSummary = {
1434
1136
  finishedAt?: number;
1435
1137
  stoppedAt?: number;
1436
1138
  };
1437
- targets?: Array<{
1139
+ targets?: {
1438
1140
  targetId: string;
1439
1141
  name: string;
1440
1142
  passed: number;
1441
1143
  failed: number;
1442
1144
  avgLatency: number;
1443
1145
  totalCost: number;
1444
- }>;
1445
- evaluators?: Array<{
1146
+ }[];
1147
+ evaluators?: {
1446
1148
  evaluatorId: string;
1447
1149
  name: string;
1448
1150
  passed: number;
1449
1151
  failed: number;
1450
1152
  passRate: number;
1451
1153
  avgScore?: number;
1452
- }>;
1154
+ }[];
1453
1155
  totalPassed?: number;
1454
1156
  totalFailed?: number;
1455
1157
  passRate?: number;
@@ -1474,16 +1176,14 @@ type RunExperimentOptions = {
1474
1176
  };
1475
1177
  /**
1476
1178
  * Inputs that override a platform experiment or workflow run on the server.
1477
- *
1478
- * `data` and `datasetId` are mutually exclusive (the backend rejects passing
1479
- * both). `parameters` overrides target parameters (e.g. prompt variables) and
1480
- * `rowIndices` restricts execution to a subset of the configured dataset.
1179
+ * `data`/`datasetId` are mutually exclusive (backend rejects both).
1180
+ * `parameters` overrides target params; `rowIndices` subsets the dataset.
1481
1181
  */
1482
1182
  type RunWithResultsOptions = {
1483
1183
  /**
1484
1184
  * Inline rows to evaluate. Mutually exclusive with `datasetId`.
1485
1185
  */
1486
- data?: Array<Record<string, unknown>>;
1186
+ data?: Record<string, unknown>[];
1487
1187
  /**
1488
1188
  * Id of a saved dataset to evaluate. Mutually exclusive with `data`.
1489
1189
  */
@@ -1578,10 +1278,6 @@ type ExperimentRunResult = {
1578
1278
 
1579
1279
  /**
1580
1280
  * ExperimentsFacade - Entry point for the experiments API
1581
- *
1582
- * Provides:
1583
- * - `init()` method to create experiment sessions (SDK-defined experiments)
1584
- * - `run()` method to execute platform-configured experiments (Experiments Workbench)
1585
1281
  */
1586
1282
 
1587
1283
  type ExperimentsFacadeConfig = {
@@ -1598,68 +1294,21 @@ declare class ExperimentsFacade {
1598
1294
  private readonly apiService;
1599
1295
  constructor(config: ExperimentsFacadeConfig);
1600
1296
  /**
1601
- * Initialize a new experiment session (SDK-defined)
1602
- *
1297
+ * Initialize a new experiment session (SDK-defined).
1603
1298
  * @param name - Name of the experiment (used as slug)
1604
1299
  * @param options - Optional configuration
1605
- * @returns An initialized Experiment instance
1606
- *
1607
- * @example
1608
- * ```typescript
1609
- * const experiment = await langwatch.experiments.init('my-experiment');
1610
- *
1611
- * await experiment.run(dataset, async ({ item, index }) => {
1612
- * const response = await myAgent(item.question);
1613
- * experiment.log('accuracy', { index, score: 0.95 });
1614
- * });
1615
- * ```
1616
1300
  */
1617
1301
  init(name: string, options?: ExperimentInitOptions): Promise<Experiment>;
1618
1302
  /**
1619
- * Run a platform-configured experiment (Experiments Workbench)
1620
- *
1621
- * This runs an experiment that was configured in the LangWatch platform.
1622
- * The method automatically prints a summary and exits with code 1 on failure
1623
- * (unless `exitOnFailure: false` is passed).
1624
- *
1303
+ * Run a platform-configured experiment (Experiments Workbench). Prints a
1304
+ * summary and exits with code 1 on failure, unless `exitOnFailure: false`.
1625
1305
  * @param slug - The slug of the experiment (found in the experiment URL)
1626
- * @param options - Optional configuration
1627
- * @returns The experiment results including pass rate and summary
1628
- *
1629
- * @example
1630
- * ```typescript
1631
- * import { LangWatch } from "langwatch";
1632
- *
1633
- * const langwatch = new LangWatch();
1634
- *
1635
- * const result = await langwatch.experiments.run("my-experiment-slug");
1636
- * result.printSummary();
1637
- * ```
1638
1306
  */
1639
1307
  run(slug: string, options?: RunExperimentOptions): Promise<ExperimentRunResult>;
1640
1308
  /**
1641
1309
  * Run a platform experiment and return per-row structured results.
1642
- *
1643
- * Starts the run through the unified evaluations-v3 backend (optionally
1644
- * overriding the configured inputs via `data` / `datasetId` / `parameters` /
1645
- * `rowIndices`), polls to completion, fetches the per-row results, and maps
1646
- * them to the same row structure as the python SDK's results DataFrame.
1647
- *
1648
1310
  * @param slug - The slug of the experiment (found in the experiment URL)
1649
1311
  * @param options - Optional inputs and polling configuration
1650
- * @returns The run id, results URL, status, summary, and per-row results
1651
- *
1652
- * @example
1653
- * ```typescript
1654
- * const langwatch = new LangWatch();
1655
- * const { rows, runUrl } = await langwatch.experiments.runWithResults(
1656
- * "my-experiment-slug",
1657
- * { data: [{ question: "What is 2 + 2?" }] },
1658
- * );
1659
- * for (const row of rows) {
1660
- * console.log(row.output, row.evaluations);
1661
- * }
1662
- * ```
1663
1312
  */
1664
1313
  runWithResults(slug: string, options?: RunWithResultsOptions): Promise<ExperimentRunWithResults>;
1665
1314
  /**
@@ -1717,11 +1366,9 @@ declare class TargetMetadataConflictError extends ExperimentError {
1717
1366
  constructor(targetName: string, existingMetadata: Record<string, unknown>, newMetadata: Record<string, unknown>);
1718
1367
  }
1719
1368
  /**
1720
- * Thrown when a comparison cannot produce a verdict the caller asked for
1721
- *
1722
- * A row that is simply too thin to judge is skipped instead, so this is
1723
- * reserved for a mismatch between what the caller named and what the run
1724
- * actually recorded.
1369
+ * Thrown when a comparison cannot produce a verdict the caller asked for.
1370
+ * A too-thin-to-judge row is skipped instead -- this is reserved for a
1371
+ * mismatch between what the caller named and what the run recorded.
1725
1372
  */
1726
1373
  declare class ComparisonError extends ExperimentError {
1727
1374
  readonly missingTargets: string[];
@@ -1736,12 +1383,7 @@ declare class EvaluatorError extends ExperimentError {
1736
1383
  constructor(evaluatorSlug: string, message: string, cause?: Error | undefined);
1737
1384
  }
1738
1385
 
1739
- /**
1740
- * Types for the Evaluations API (Online Evaluations / Guardrails)
1741
- *
1742
- * These types define the structure for running evaluators and guardrails
1743
- * in real-time against LLM inputs/outputs.
1744
- */
1386
+ /** Types for the Evaluations API: running evaluators/guardrails in real time against LLM I/O. */
1745
1387
  /**
1746
1388
  * Status of an evaluation result
1747
1389
  */
@@ -1785,26 +1427,9 @@ type EvaluateOptions = {
1785
1427
  };
1786
1428
 
1787
1429
  /**
1788
- * EvaluationsFacade - Entry point for the Evaluations API (Online Evaluations / Guardrails)
1789
- *
1790
- * Provides an API for running evaluators and guardrails in real-time against LLM inputs/outputs.
1791
- *
1430
+ * EvaluationsFacade - Entry point for the Evaluations API (Online Evaluations /
1431
+ * Guardrails)
1792
1432
  * @example
1793
- * ```typescript
1794
- * const langwatch = new LangWatch({ apiKey: "your-api-key" });
1795
- *
1796
- * // Run a guardrail
1797
- * const guardrail = await langwatch.evaluations.evaluate("presidio/pii_detection", {
1798
- * data: { input: userInput, output: generatedResponse },
1799
- * name: "PII Detection",
1800
- * asGuardrail: true,
1801
- * settings: {},
1802
- * });
1803
- *
1804
- * if (!guardrail.passed) {
1805
- * return "I'm sorry, I can't do that.";
1806
- * }
1807
- * ```
1808
1433
  */
1809
1434
 
1810
1435
  type EvaluationsFacadeConfig = {
@@ -1816,42 +1441,9 @@ declare class EvaluationsFacade {
1816
1441
  #private;
1817
1442
  constructor(config: EvaluationsFacadeConfig);
1818
1443
  /**
1819
- * Run an evaluator or guardrail against provided data
1820
- *
1821
- * Creates an OpenTelemetry span attached to the current trace context,
1822
- * calls the LangWatch evaluation API, and returns the result.
1823
- *
1444
+ * Run an evaluator or guardrail against provided data.
1824
1445
  * @param slug - The evaluator slug (e.g., "presidio/pii_detection", "langevals/llm_boolean")
1825
1446
  * @param options - Evaluation options including data, name, settings, and asGuardrail flag
1826
- * @returns The evaluation result with status, passed, score, details, label, and cost
1827
- *
1828
- * @example
1829
- * ```typescript
1830
- * // Run as a guardrail (synchronous evaluation that can block responses)
1831
- * const guardrail = await langwatch.evaluations.evaluate("presidio/pii_detection", {
1832
- * data: { input: userInput, output: generatedResponse },
1833
- * name: "PII Detection Guardrail",
1834
- * asGuardrail: true,
1835
- * });
1836
- *
1837
- * if (!guardrail.passed) {
1838
- * console.log("PII detected:", guardrail.details);
1839
- * return "Sorry, I cannot process that request.";
1840
- * }
1841
- * ```
1842
- *
1843
- * @example
1844
- * ```typescript
1845
- * // Run as an online evaluation (async scoring for monitoring)
1846
- * const result = await langwatch.evaluations.evaluate("langevals/llm_boolean", {
1847
- * data: { input: question, output: response },
1848
- * name: "Quality Check",
1849
- * settings: { prompt: "Check if the response answers the question." },
1850
- * });
1851
- *
1852
- * console.log("Score:", result.score);
1853
- * console.log("Details:", result.details);
1854
- * ```
1855
1447
  */
1856
1448
  evaluate: (slug: string, options: EvaluateOptions) => Promise<EvaluationResult>;
1857
1449
  }
@@ -1888,14 +1480,14 @@ declare class EvaluationsApiError extends EvaluationError {
1888
1480
  constructor(message: string, statusCode: number);
1889
1481
  }
1890
1482
 
1891
- type EvaluatorResponse = NonNullable<paths["/api/evaluators"]["get"]["responses"]["200"]["content"]["application/json"]>[number] & {
1483
+ type EvaluatorResponse = NonNullable<paths["/api/v1/evaluators"]["get"]["responses"]["200"]["content"]["application/json"]>[number] & {
1892
1484
  /** URL to view this evaluator on the LangWatch platform */
1893
1485
  platformUrl?: string;
1894
1486
  };
1895
1487
  type EvaluatorField = EvaluatorResponse["fields"][number];
1896
- type CreateEvaluatorBody = NonNullable<paths["/api/evaluators"]["post"]["requestBody"]>["content"]["application/json"];
1897
- type UpdateEvaluatorBody = NonNullable<paths["/api/evaluators/{id}"]["put"]["requestBody"]>["content"]["application/json"];
1898
- type DeleteEvaluatorResponse = paths["/api/evaluators/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
1488
+ type CreateEvaluatorBody = NonNullable<paths["/api/v1/evaluators"]["post"]["requestBody"]>["content"]["application/json"];
1489
+ type UpdateEvaluatorBody = NonNullable<paths["/api/v1/evaluators/{id}"]["put"]["requestBody"]>["content"]["application/json"];
1490
+ type DeleteEvaluatorResponse = paths["/api/v1/evaluators/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
1899
1491
 
1900
1492
  /**
1901
1493
  * Service for retrieving evaluator resources via the LangWatch API.
@@ -1934,15 +1526,15 @@ declare class EvaluatorsApiError extends Error {
1934
1526
  constructor(message: string, operation: string, originalError?: unknown | undefined);
1935
1527
  }
1936
1528
 
1937
- type ScenarioResponse = NonNullable<paths["/api/scenarios"]["get"]["responses"]["200"]["content"]["application/json"]>[number] & {
1529
+ type ScenarioResponse = NonNullable<paths["/api/v1/scenarios"]["get"]["responses"]["200"]["content"]["application/json"]>[number] & {
1938
1530
  /** URL to view this scenario on the LangWatch platform */
1939
1531
  platformUrl?: string;
1940
1532
  };
1941
- type CreateScenarioBody = NonNullable<paths["/api/scenarios"]["post"]["requestBody"]>["content"]["application/json"];
1942
- type UpdateScenarioBody = NonNullable<paths["/api/scenarios/{id}"]["put"]["requestBody"]>["content"]["application/json"];
1943
- type DeleteScenarioResponse = paths["/api/scenarios/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
1944
- type ScenarioVersionListResponse = paths["/api/scenarios/{id}/versions"]["get"]["responses"]["200"]["content"]["application/json"];
1945
- type ScenarioVersionDetail = paths["/api/scenarios/{id}/versions/{version}"]["get"]["responses"]["200"]["content"]["application/json"];
1533
+ type CreateScenarioBody = NonNullable<paths["/api/v1/scenarios"]["post"]["requestBody"]>["content"]["application/json"];
1534
+ type UpdateScenarioBody = NonNullable<paths["/api/v1/scenarios/{id}"]["put"]["requestBody"]>["content"]["application/json"];
1535
+ type DeleteScenarioResponse = paths["/api/v1/scenarios/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
1536
+ type ScenarioVersionListResponse = paths["/api/v1/scenarios/{id}/versions"]["get"]["responses"]["200"]["content"]["application/json"];
1537
+ type ScenarioVersionDetail = paths["/api/v1/scenarios/{id}/versions/{version}"]["get"]["responses"]["200"]["content"]["application/json"];
1946
1538
 
1947
1539
  declare class ScenariosApiService {
1948
1540
  private readonly apiClient;
@@ -1962,19 +1554,19 @@ declare class ScenariosApiService {
1962
1554
  delete(id: string): Promise<DeleteScenarioResponse>;
1963
1555
  }
1964
1556
 
1965
- type SuiteResponse = NonNullable<paths["/api/suites"]["get"]["responses"]["200"]["content"]["application/json"]>[number] & {
1557
+ type SuiteResponse = NonNullable<paths["/api/v1/suites"]["get"]["responses"]["200"]["content"]["application/json"]>[number] & {
1966
1558
  /** URL to view this suite on the LangWatch platform */
1967
1559
  platformUrl?: string;
1968
1560
  };
1969
- type CreateSuiteBody = NonNullable<paths["/api/suites"]["post"]["requestBody"]>["content"]["application/json"];
1970
- type UpdateSuiteBody = NonNullable<paths["/api/suites/{id}"]["patch"]["requestBody"]>["content"]["application/json"];
1971
- type SuiteRunResult = paths["/api/suites/{id}/run"]["post"]["responses"]["200"]["content"]["application/json"];
1972
- /** Options for `POST /api/suites/{id}/run`. */
1561
+ type CreateSuiteBody = NonNullable<paths["/api/v1/suites"]["post"]["requestBody"]>["content"]["application/json"];
1562
+ type UpdateSuiteBody = NonNullable<paths["/api/v1/suites/{id}"]["patch"]["requestBody"]>["content"]["application/json"];
1563
+ type SuiteRunResult = paths["/api/v1/suites/{id}/run"]["post"]["responses"]["200"]["content"]["application/json"];
1564
+ /** Options for `POST /api/v1/suites/{id}/run`. */
1973
1565
  interface SuiteRunOptions {
1974
1566
  /**
1975
- * Key that makes the request safe to retry. Generated per call when omitted,
1976
- * so two retries of the same command schedule two runs unless the caller
1977
- * pins one.
1567
+ * Makes the run safe to retry: the same key on a second call joins the batch
1568
+ * the first started. Omitted, no key is sent and every call schedules its own
1569
+ * run. Pin one per logical run, never per attempt.
1978
1570
  */
1979
1571
  idempotencyKey?: string;
1980
1572
  /**
@@ -1993,7 +1585,7 @@ interface SuiteRunOptions {
1993
1585
  /** Which kind of suite `getAll` returns. Defaults to run plans. */
1994
1586
  type SuiteKind = "custom" | "folder";
1995
1587
  /**
1996
- * @deprecated Use runPlans and testSuites; /api/suites is a frozen alias.
1588
+ * @deprecated Use runPlans and testSuites; /api/v1/suites is a frozen alias.
1997
1589
  */
1998
1590
  declare class SuitesApiService {
1999
1591
  private readonly apiClient;
@@ -2028,12 +1620,6 @@ type RunPlanRunResult = paths["/api/v1/run-plans/run"]["post"]["responses"]["200
2028
1620
  type RunPlanRerunBody = NonNullable<paths["/api/v1/run-plans/{id}/run"]["post"]["requestBody"]>["content"]["application/json"];
2029
1621
  /**
2030
1622
  * Typed client for the run plan family (`/api/v1/run-plans`).
2031
- *
2032
- * A run plan is identified by its NAME. Posting a configuration under a name
2033
- * already in use replaces that plan's configuration and joins its history;
2034
- * posting under a new name creates the plan; posting no name lets the platform
2035
- * derive one from what the run covers and what it runs against.
2036
- *
2037
1623
  * @see specs/typescript-sdk/run-plans-and-test-suites.feature
2038
1624
  */
2039
1625
  declare class RunPlansApiService {
@@ -2047,9 +1633,6 @@ declare class RunPlansApiService {
2047
1633
  get(id: string): Promise<RunPlan>;
2048
1634
  /**
2049
1635
  * Runs a configuration under a name.
2050
- *
2051
- * A note of only spaces is no note: sending an empty string would store a
2052
- * value every reader then has to filter out.
2053
1636
  */
2054
1637
  run(body: RunPlanRunBody): Promise<RunPlanRunResult>;
2055
1638
  /** Runs a plan again with the configuration it already holds. */
@@ -2073,16 +1656,10 @@ type InstantEvalJudgment = InstantEvalResultsPage["judgments"][number];
2073
1656
  /** A few of a run's rows, with the judged text beside the verdict. */
2074
1657
  type InstantEvalSample = paths["/api/v1/instant-evals/{id}/sample"]["get"]["responses"]["200"]["content"]["application/json"];
2075
1658
  /**
2076
- * Typed client for the Instant Evals family (`/api/v1/instant-evals`).
2077
- *
2078
- * A run judges one LangWatchQL statement across the project's history. The
2079
- * statement is the same one the query door runs, so a working query is a
2080
- * working run once it projects `TraceId` and at least one eval function
2081
- * column. Starting one answers the queued run, and its progress is polled.
2082
- *
2083
- * The project comes from the credential, so no method takes a project id.
2084
- *
2085
- * @see specs/instant-evals/instant-eval-api.feature
1659
+ * Typed client for Instant Evals (`/api/v1/instant-evals`): a run judges one LangWatchQL statement
1660
+ * that projects `TraceId` and an eval column. Progress is polled; the project comes from the
1661
+ * credential.
1662
+ * @see modules/instant-eval/specs/instant-eval-api.feature
2086
1663
  */
2087
1664
  declare class InstantEvalsApiService {
2088
1665
  private readonly apiClient;
@@ -2108,10 +1685,8 @@ declare class InstantEvalsApiService {
2108
1685
  /** Asks a run to stop. It stops before its next page. */
2109
1686
  cancel(id: string): Promise<InstantEvalRun>;
2110
1687
  /**
2111
- * One page of a run's judgements.
2112
- *
2113
- * Pass the `nextCursor` a page answers with to read the page after it. The
2114
- * last page carries none.
1688
+ * One page of a run's judgements. Pass the `nextCursor` a page answers with to read the page
1689
+ * after it. The last page carries none.
2115
1690
  */
2116
1691
  results(id: string, options?: {
2117
1692
  questionId?: string;
@@ -2145,11 +1720,6 @@ type RunTestSuiteBody = NonNullable<paths["/api/v1/test-suites/{id}/run"]["post"
2145
1720
  type TestSuiteRunResult = RunPlanRunResult;
2146
1721
  /**
2147
1722
  * Typed client for the test suite family (`/api/v1/test-suites`).
2148
- *
2149
- * A test suite is a group of scenarios: a name, and the scenarios filed in it.
2150
- * It holds no targets and no configuration, so running one sends its targets with
2151
- * the request and the platform files the run under a run plan.
2152
- *
2153
1723
  * @see specs/typescript-sdk/run-plans-and-test-suites.feature
2154
1724
  */
2155
1725
  declare class TestSuitesApiService {
@@ -2182,8 +1752,8 @@ declare class TestSuitesApiService {
2182
1752
  run(id: string, body: RunTestSuiteBody): Promise<TestSuiteRunResult>;
2183
1753
  }
2184
1754
 
2185
- type WorkflowResponse = NonNullable<paths["/api/workflows"]["get"]["responses"]["200"]["content"]["application/json"]>[number];
2186
- type WorkflowDeleteResponse = paths["/api/workflows/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
1755
+ type WorkflowResponse = NonNullable<paths["/api/v1/workflows"]["get"]["responses"]["200"]["content"]["application/json"]>[number];
1756
+ type WorkflowDeleteResponse = paths["/api/v1/workflows/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
2187
1757
  declare class WorkflowsApiService {
2188
1758
  private readonly apiClient;
2189
1759
  private readonly experimentsApiService;
@@ -2198,25 +1768,8 @@ declare class WorkflowsApiService {
2198
1768
  delete(id: string): Promise<WorkflowDeleteResponse>;
2199
1769
  /**
2200
1770
  * Run a studio workflow evaluation and return per-row structured results.
2201
- *
2202
- * Starts the evaluation through the unified evaluations-v3 backend
2203
- * (`POST /api/workflows/{workflowId}/evaluate`), polls to completion, fetches
2204
- * the per-row results, and maps them to the same row structure as the python
2205
- * SDK's results DataFrame.
2206
- *
2207
1771
  * @param workflowId - The studio workflow id
2208
- * @param options - Optional inputs, committed version override, and polling
2209
- * configuration. `data` and `datasetId` are mutually
2210
- * exclusive.
2211
- * @returns The run id, results URL, status, summary, and per-row results
2212
- *
2213
- * @example
2214
- * ```typescript
2215
- * const langwatch = new LangWatch();
2216
- * const { rows, runUrl } = await langwatch.workflows.run("workflow_123", {
2217
- * data: [{ question: "What is 2 + 2?" }],
2218
- * });
2219
- * ```
1772
+ * @param options - Optional inputs and polling configuration
2220
1773
  */
2221
1774
  run(workflowId: string, options?: RunWithResultsOptions & {
2222
1775
  versionId?: string;
@@ -2316,16 +1869,19 @@ declare class AgentsApiService {
2316
1869
  */
2317
1870
  call(id: string, body: AgentCallBody): Promise<AgentCallResponse>;
2318
1871
  /**
2319
- * Runs one scripted scenario against an agent: the user sends "ping", the
2320
- * agent answers, and the run succeeds when the answer arrives. The project
2321
- * gains no scenario, run plan or test suite, and the answer carries the run
2322
- * ids to follow.
1872
+ * Runs one scripted scenario against an agent: the user sends "ping", the agent answers,
1873
+ * and the run succeeds when the answer arrives. The project gains no scenario, run plan or
1874
+ * test suite, and the answer carries the run ids to follow.
2323
1875
  */
2324
1876
  test(id: string): Promise<AgentTestRunResponse>;
2325
1877
  }
2326
1878
 
2327
1879
  type AnnotationResponse = components["schemas"]["Annotation"];
2328
- type CreateAnnotationBody = NonNullable<paths["/api/annotations/trace/{id}"]["post"]["requestBody"]>["content"]["application/json"];
1880
+ type CreateAnnotationBody = NonNullable<paths["/api/v1/annotations/trace/{id}"]["post"]["requestBody"]>["content"]["application/json"];
1881
+ type DeleteAnnotationResponse = {
1882
+ status?: string;
1883
+ message?: string;
1884
+ };
2329
1885
  declare class AnnotationsApiService {
2330
1886
  private readonly apiClient;
2331
1887
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
@@ -2334,13 +1890,76 @@ declare class AnnotationsApiService {
2334
1890
  get(id: string): Promise<AnnotationResponse>;
2335
1891
  getByTrace(traceId: string): Promise<AnnotationResponse[]>;
2336
1892
  create(traceId: string, params: CreateAnnotationBody): Promise<AnnotationResponse>;
2337
- delete(id: string): Promise<{
2338
- status?: string;
2339
- message?: string;
1893
+ delete(id: string): Promise<DeleteAnnotationResponse>;
1894
+ }
1895
+
1896
+ type Json<T> = T extends {
1897
+ content: {
1898
+ "application/json": infer Body;
1899
+ };
1900
+ } ? Body : never;
1901
+ /** A dashboard as `/api/v1/dashboards/{dashboardId}` answers it. */
1902
+ type Dashboard = Json<paths["/api/v1/dashboards/{dashboardId}"]["get"]["responses"]["200"]>;
1903
+ /** One row of the dashboards list, with its widget count. */
1904
+ type DashboardListItem = Json<paths["/api/v1/dashboards"]["get"]["responses"]["200"]>["data"][number];
1905
+ /** A widget on a dashboard, as the dashboard's widget routes answer it. */
1906
+ type DashboardWidget = Json<paths["/api/v1/dashboards/{dashboardId}/widgets/{widgetId}"]["get"]["responses"]["200"]>;
1907
+ /** What creating a widget on a dashboard submits. */
1908
+ type CreateDashboardWidgetInput = NonNullable<paths["/api/v1/dashboards/{dashboardId}/widgets"]["post"]["requestBody"]>["content"]["application/json"];
1909
+ /** What updating a widget on a dashboard submits; a field left out keeps its value. */
1910
+ type UpdateDashboardWidgetInput = NonNullable<paths["/api/v1/dashboards/{dashboardId}/widgets/{widgetId}"]["patch"]["requestBody"]>["content"]["application/json"];
1911
+ /**
1912
+ * Typed client for `/api/v1/dashboards`: the key's project's dashboards and the widgets on them.
1913
+ * The project comes from the API key; while Dashboards is off the routes answer 404.
1914
+ */
1915
+ declare class DashboardsApiService {
1916
+ private readonly apiClient;
1917
+ constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
1918
+ private handleApiError;
1919
+ list(): Promise<{
1920
+ data: DashboardListItem[];
1921
+ }>;
1922
+ get(dashboardId: string): Promise<Dashboard>;
1923
+ create({ name }: {
1924
+ name: string;
1925
+ }): Promise<Dashboard>;
1926
+ /** `description: null` clears it; a field left out keeps its value. */
1927
+ update({ dashboardId, name, description, }: {
1928
+ dashboardId: string;
1929
+ name?: string;
1930
+ description?: string | null;
1931
+ }): Promise<Dashboard>;
1932
+ /** Deletes the dashboard with the widgets on it; answers its id and name. */
1933
+ delete(dashboardId: string): Promise<{
1934
+ id: string;
1935
+ name: string;
1936
+ }>;
1937
+ listWidgets(dashboardId: string): Promise<{
1938
+ data: DashboardWidget[];
2340
1939
  }>;
1940
+ /** Creates a widget placed on this dashboard. */
1941
+ createWidget({ dashboardId, widget, }: {
1942
+ dashboardId: string;
1943
+ widget: CreateDashboardWidgetInput;
1944
+ }): Promise<DashboardWidget>;
1945
+ getWidget({ dashboardId, widgetId, }: {
1946
+ dashboardId: string;
1947
+ widgetId: string;
1948
+ }): Promise<DashboardWidget>;
1949
+ updateWidget({ dashboardId, widgetId, changes, }: {
1950
+ dashboardId: string;
1951
+ widgetId: string;
1952
+ changes: UpdateDashboardWidgetInput;
1953
+ }): Promise<DashboardWidget>;
1954
+ /** The route answers `204` with no body. */
1955
+ deleteWidget({ dashboardId, widgetId, }: {
1956
+ dashboardId: string;
1957
+ widgetId: string;
1958
+ }): Promise<void>;
2341
1959
  }
2342
1960
 
2343
- interface DashboardSummary {
1961
+ /** One Analytics Report in the list, with how many graphs it holds. */
1962
+ interface AnalyticsReportSummary {
2344
1963
  id: string;
2345
1964
  name: string;
2346
1965
  order: number;
@@ -2349,7 +1968,8 @@ interface DashboardSummary {
2349
1968
  updatedAt: string;
2350
1969
  platformUrl?: string;
2351
1970
  }
2352
- interface DashboardDetail {
1971
+ /** One Analytics Report with its graphs. */
1972
+ interface AnalyticsReportDetail {
2353
1973
  id: string;
2354
1974
  name: string;
2355
1975
  order: number;
@@ -2358,28 +1978,32 @@ interface DashboardDetail {
2358
1978
  updatedAt: string;
2359
1979
  platformUrl?: string;
2360
1980
  }
2361
- declare class DashboardsApiService {
1981
+ /**
1982
+ * Typed client for the Analytics Reports at `/api/v1/analytics/reports`, deprecated by the
1983
+ * platform in favour of the Dashboards API (`DashboardsApiService`, `/api/v1/dashboards`).
1984
+ */
1985
+ declare class AnalyticsReportsApiService {
2362
1986
  private readonly apiClient;
2363
1987
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
2364
1988
  private handleApiError;
2365
1989
  list(): Promise<{
2366
- data: DashboardSummary[];
1990
+ data: AnalyticsReportSummary[];
2367
1991
  }>;
2368
- get(id: string): Promise<DashboardDetail>;
1992
+ get(id: string): Promise<AnalyticsReportDetail>;
2369
1993
  create(params: {
2370
1994
  name: string;
2371
- }): Promise<DashboardDetail>;
1995
+ }): Promise<AnalyticsReportDetail>;
2372
1996
  rename(id: string, params: {
2373
1997
  name: string;
2374
- }): Promise<DashboardDetail>;
1998
+ }): Promise<AnalyticsReportDetail>;
2375
1999
  delete(id: string): Promise<{
2376
2000
  id: string;
2377
2001
  name: string;
2378
2002
  }>;
2379
2003
  }
2380
2004
 
2381
- type ModelProvidersListResponse = paths["/api/model-providers"]["get"]["responses"]["200"]["content"]["application/json"];
2382
- type UpdateModelProviderBody = NonNullable<paths["/api/model-providers/{provider}"]["put"]["requestBody"]>["content"]["application/json"];
2005
+ type ModelProvidersListResponse = paths["/api/v1/model-providers"]["get"]["responses"]["200"]["content"]["application/json"];
2006
+ type UpdateModelProviderBody = NonNullable<paths["/api/v1/model-providers/{provider}"]["put"]["requestBody"]>["content"]["application/json"];
2383
2007
  declare class ModelProvidersApiService {
2384
2008
  private readonly apiClient;
2385
2009
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
@@ -2388,8 +2012,8 @@ declare class ModelProvidersApiService {
2388
2012
  set(provider: string, params: UpdateModelProviderBody): Promise<ModelProvidersListResponse>;
2389
2013
  }
2390
2014
 
2391
- type AnalyticsTimeseriesBody = NonNullable<paths["/api/analytics/timeseries"]["post"]["requestBody"]>["content"]["application/json"];
2392
- type AnalyticsTimeseriesResponse = paths["/api/analytics/timeseries"]["post"]["responses"]["200"]["content"]["application/json"];
2015
+ type AnalyticsTimeseriesBody = NonNullable<paths["/api/v1/analytics/timeseries"]["post"]["requestBody"]>["content"]["application/json"];
2016
+ type AnalyticsTimeseriesResponse = paths["/api/v1/analytics/timeseries"]["post"]["responses"]["200"]["content"]["application/json"];
2393
2017
  declare class AnalyticsApiService {
2394
2018
  private readonly apiClient;
2395
2019
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
@@ -2402,42 +2026,18 @@ type QueryRunResult = paths["/api/v1/query"]["post"]["responses"]["200"]["conten
2402
2026
  /** The queryable dataset/column catalog `GET /api/v1/query/schema` answers with. */
2403
2027
  type QuerySchemaResult = paths["/api/v1/query/schema"]["get"]["responses"]["200"]["content"]["application/json"];
2404
2028
  /**
2405
- * Both query languages, as `GET /api/v1/query/reference` describes them.
2406
- *
2407
- * A superset of {@link QuerySchemaResult} in one direction only: it embeds the
2408
- * schema and adds the trace filter language, worked examples and the decision
2409
- * table. Nothing here is tenant data — the values a field holds come from
2410
- * `GET /api/traces/facets`.
2029
+ * Both query languages as `GET /api/v1/query/reference` describes them: {@link QuerySchemaResult}
2030
+ * plus the filter language, examples and decision table. No tenant data; values come from facets.
2411
2031
  */
2412
2032
  type QueryReferenceResult = paths["/api/v1/query/reference"]["get"]["responses"]["200"]["content"]["application/json"];
2413
2033
  /**
2414
2034
  * The body a query request sends.
2415
- *
2416
- * Derived from the generated request body so a contract change to what the
2417
- * endpoint accepts breaks this at compile time rather than drifting silently.
2418
2035
  */
2419
2036
  type QueryRunParams = NonNullable<paths["/api/v1/query"]["post"]["requestBody"]>["content"]["application/json"];
2420
2037
  /**
2421
- * Typed client for the query doors (`POST /api/v1/query`,
2422
- * `GET /api/v1/query/schema` and `GET /api/v1/query/reference`) — the same
2423
- * governed query surface the workbench
2424
- * and saved charts run through, exposed directly rather than only via a saved
2425
- * chart's statement.
2426
- *
2427
- * Unlike the chart family, these routes carry no `projectId` in their path or
2428
- * body — the generated operations declare `path?: never`. Project scope is
2429
- * resolved once, when the underlying `LangwatchApiClient` is built
2430
- * (`createLangWatchApiClient` bakes `scopedProjectId() ?? LANGWATCH_PROJECT_ID`
2431
- * into that client's `Authorization`/`Basic` header at construction time —
2432
- * see `src/internal/api/client.ts` and `src/internal/api/auth.ts`). A
2433
- * per-call `projectId()` resolution the way `ChartsApiService` has one would
2434
- * therefore be dead code here: there is no URL slot to put it in, and it
2435
- * cannot retroactively change a header already baked into an existing
2436
- * client. It would also wrongly force every caller to have a project in
2437
- * scope — legacy `sk-lw-*` project keys carry their own project identity and
2438
- * need none (see `buildAuthHeaders`). So this service takes the plain,
2439
- * project-implicit config `AnalyticsApiService` does, and lets the api
2440
- * client resolve the credential itself.
2038
+ * Typed client for the LangWatchQL query doors (`POST /api/v1/query` and `GET
2039
+ * /api/v1/query/schema`) — the same governed query surface the workbench and saved charts
2040
+ * run through, exposed directly rather than only via a saved chart's statement.
2441
2041
  */
2442
2042
  declare class QueryApiService {
2443
2043
  private readonly apiClient;
@@ -2450,25 +2050,23 @@ declare class QueryApiService {
2450
2050
  */
2451
2051
  query(params: QueryRunParams): Promise<QueryRunResult>;
2452
2052
  /**
2453
- * Lists the LangWatchQL analytics views this key may query, with each
2454
- * column's type, description, the permissions that unlock it, and whether
2455
- * this caller holds them — plus each dataset's grain, join keys,
2456
- * partition-pruning time column, freshness and a runnable example query.
2053
+ * Lists the LangWatchQL analytics datasets this key may query, with each column's type,
2054
+ * description, the permissions that unlock it, and whether this caller holds them — plus
2055
+ * each dataset's grain, join keys, partition-pruning time column, freshness and a runnable
2457
2056
  */
2458
2057
  schema(): Promise<QuerySchemaResult>;
2459
2058
  /**
2460
- * Describes both query languages in one payload: the LangWatchQL schema,
2461
- * limits and endpoints, the trace filter's syntax and fields, worked examples
2462
- * validated in both, and which language answers which kind of
2463
- * question.
2059
+ * Describes both query languages in one payload: the LangWatchQL schema, limits and endpoints,
2060
+ * the trace filter's syntax and fields, worked examples validated in both, and which language
2061
+ * answers which kind of question.
2464
2062
  */
2465
2063
  reference(): Promise<QueryReferenceResult>;
2466
2064
  }
2467
2065
 
2468
- type TriggerResponse = NonNullable<paths["/api/triggers"]["get"]["responses"]["200"]["content"]["application/json"]>[number];
2469
- type CreateTriggerBody = NonNullable<paths["/api/triggers"]["post"]["requestBody"]>["content"]["application/json"];
2470
- type UpdateTriggerBody = NonNullable<paths["/api/triggers/{id}"]["patch"]["requestBody"]>["content"]["application/json"];
2471
- type TriggerDeleteResponse = paths["/api/triggers/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
2066
+ type TriggerResponse = NonNullable<paths["/api/v1/triggers"]["get"]["responses"]["200"]["content"]["application/json"]>[number];
2067
+ type CreateTriggerBody = NonNullable<paths["/api/v1/triggers"]["post"]["requestBody"]>["content"]["application/json"];
2068
+ type UpdateTriggerBody = NonNullable<paths["/api/v1/triggers/{triggerId}"]["patch"]["requestBody"]>["content"]["application/json"];
2069
+ type TriggerDeleteResponse = paths["/api/v1/triggers/{triggerId}"]["delete"]["responses"]["200"]["content"]["application/json"];
2472
2070
  declare class TriggersApiService {
2473
2071
  private readonly apiClient;
2474
2072
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
@@ -2480,10 +2078,10 @@ declare class TriggersApiService {
2480
2078
  delete(id: string): Promise<TriggerDeleteResponse>;
2481
2079
  }
2482
2080
 
2483
- type GraphResponse = NonNullable<paths["/api/graphs"]["get"]["responses"]["200"]["content"]["application/json"]>[number];
2484
- type CreateGraphBody = NonNullable<paths["/api/graphs"]["post"]["requestBody"]>["content"]["application/json"];
2485
- type UpdateGraphBody = NonNullable<paths["/api/graphs/{id}"]["patch"]["requestBody"]>["content"]["application/json"];
2486
- type GraphDeleteResponse = paths["/api/graphs/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
2081
+ type GraphResponse = NonNullable<paths["/api/v1/graphs"]["get"]["responses"]["200"]["content"]["application/json"]>[number];
2082
+ type CreateGraphBody = NonNullable<paths["/api/v1/graphs"]["post"]["requestBody"]>["content"]["application/json"];
2083
+ type UpdateGraphBody = NonNullable<paths["/api/v1/graphs/{id}"]["patch"]["requestBody"]>["content"]["application/json"];
2084
+ type GraphDeleteResponse = paths["/api/v1/graphs/{id}"]["delete"]["responses"]["200"]["content"]["application/json"];
2487
2085
  declare class GraphsApiService {
2488
2086
  private readonly apiClient;
2489
2087
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
@@ -2495,11 +2093,11 @@ declare class GraphsApiService {
2495
2093
  delete(id: string): Promise<GraphDeleteResponse>;
2496
2094
  }
2497
2095
 
2498
- type SimulationRunsListResponse = paths["/api/simulation-runs"]["get"]["responses"]["200"]["content"]["application/json"];
2499
- type SimulationRunResponse = paths["/api/simulation-runs/{scenarioRunId}"]["get"]["responses"]["200"]["content"]["application/json"];
2500
- type SimulationRunsBatchesListResponse = paths["/api/simulation-runs/batches/list"]["get"]["responses"]["200"]["content"]["application/json"];
2501
- type SimulationRunsListParams = NonNullable<paths["/api/simulation-runs"]["get"]["parameters"]["query"]>;
2502
- type SimulationRunsBatchesListParams = paths["/api/simulation-runs/batches/list"]["get"]["parameters"]["query"];
2096
+ type SimulationRunsListResponse = paths["/api/v1/simulation-runs"]["get"]["responses"]["200"]["content"]["application/json"];
2097
+ type SimulationRunResponse = paths["/api/v1/simulation-runs/{scenarioRunId}"]["get"]["responses"]["200"]["content"]["application/json"];
2098
+ type SimulationRunsBatchesListResponse = paths["/api/v1/simulation-runs/batches/list"]["get"]["responses"]["200"]["content"]["application/json"];
2099
+ type SimulationRunsListParams = NonNullable<paths["/api/v1/simulation-runs"]["get"]["parameters"]["query"]>;
2100
+ type SimulationRunsBatchesListParams = paths["/api/v1/simulation-runs/batches/list"]["get"]["parameters"]["query"];
2503
2101
  declare class SimulationRunsApiService {
2504
2102
  private readonly apiClient;
2505
2103
  constructor(config?: Pick<InternalConfig, "langwatchApiClient">);
@@ -2579,10 +2177,13 @@ interface SecretDeleteResponse {
2579
2177
  declare class SecretsApiService {
2580
2178
  private readonly apiKey;
2581
2179
  private readonly endpoint;
2180
+ private readonly configuredProjectId;
2582
2181
  constructor(config?: {
2583
2182
  apiKey?: string;
2584
2183
  endpoint?: string;
2184
+ projectId?: string;
2585
2185
  });
2186
+ private projectId;
2586
2187
  private request;
2587
2188
  getAll(): Promise<SecretResponse[]>;
2588
2189
  get(id: string): Promise<SecretResponse>;
@@ -2597,17 +2198,9 @@ declare class SecretsApiService {
2597
2198
  }
2598
2199
 
2599
2200
  /**
2600
- * The per-call options every mutating call on the billing surfaces takes.
2601
- *
2602
- * WHERE THEY GO. A call whose arguments already ride in an options bag
2603
- * (`disable(id, { reason })`, `reset(id, { endUserId })`) gains these fields in
2604
- * that same bag: one bag per call is what a caller expects. A call that takes a
2605
- * request BODY (`create(input)`, `update(id, input)`) gets a separate trailing
2606
- * parameter instead, because those body types mirror the wire verbatim and must
2607
- * not grow keys the wire has never heard of.
2608
- *
2609
- * They are an interface rather than a bare `signal` so that the next thing a
2610
- * call needs per invocation is an added field rather than an added parameter.
2201
+ * The per-call options every mutating billing call takes. An options-bag
2202
+ * call gains these fields there; a body call (`create(input)`) gets them as
2203
+ * a trailing param, since body types mirror the wire verbatim.
2611
2204
  */
2612
2205
  /** The request header the control plane deduplicates creates on. */
2613
2206
  declare const IDEMPOTENCY_KEY_HEADER = "Idempotency-Key";
@@ -2626,29 +2219,15 @@ interface MutationOptions {
2626
2219
  }
2627
2220
  interface IdempotentCreateOptions extends MutationOptions {
2628
2221
  /**
2629
- * Makes the create safe to retry. A dropped connection after the write but
2630
- * before the response looks exactly like a dropped request, and sending it
2631
- * again without a key mints a SECOND resource. Send the same key on the
2632
- * retry and the server answers with the first response instead, byte for
2633
- * byte, including the one-time secret a create hands back.
2634
- *
2635
- * Any string of 8 to 255 characters; a UUID minted per logical create is the
2636
- * usual choice. Receipts answer for 24 hours, and only successful creates
2637
- * leave one, so a create that failed is safe to run again either way.
2638
- *
2639
- * Reusing a key with a DIFFERENT body is refused with `idempotency_error`
2640
- * rather than quietly answering for the wrong request.
2222
+ * Makes the create safe to retry: the same key replays the first
2223
+ * response verbatim, while a dropped response with no key would mint a
2224
+ * second resource. A DIFFERENT body under the same key is refused.
2641
2225
  */
2642
2226
  idempotencyKey?: string;
2643
2227
  /**
2644
- * Called when the response came from a receipt rather than a fresh write,
2645
- * i.e. this exact create had already succeeded.
2646
- *
2647
- * A hook rather than a field on the returned resource: the resource is
2648
- * identical either way, so nothing about handling it changes, and the
2649
- * distinction is something a caller logs rather than branches on. Keeping it
2650
- * off the return type also keeps the wire-shaped entities free of fields the
2651
- * wire does not have.
2228
+ * Called when the response came from a receipt, not a fresh write. A hook
2229
+ * rather than a resource field, since callers log this rather than branch
2230
+ * on it, keeping wire-shaped entities free of fields the wire lacks.
2652
2231
  */
2653
2232
  onIdempotentReplay?: () => void;
2654
2233
  }
@@ -2677,11 +2256,9 @@ interface VirtualKey {
2677
2256
  display_prefix: string;
2678
2257
  principal_user_id: string | null;
2679
2258
  /**
2680
- * Where this key's traces and costs land. Not a scope: it grants no
2681
- * access to the key. Decided when the key is written and stored on it,
2682
- * so editing what the key is scoped to never moves it. Null only on a
2683
- * key created before this was stored, in an organization that had no
2684
- * governance project to fall back to.
2259
+ * Where this key's traces and costs land. Not a scope: it grants no access to the key.
2260
+ * Decided when the key is written and stored on it, so editing what the key is scoped to
2261
+ * never moves it. Null only on a pre-existing key with no governance project fallback.
2685
2262
  */
2686
2263
  trace_project_id: string | null;
2687
2264
  /**
@@ -2700,10 +2277,9 @@ interface VirtualKey {
2700
2277
  last_used_at: string | null;
2701
2278
  revoked_at: string | null;
2702
2279
  /**
2703
- * When the key stops serving, or null for a key that never expires.
2704
- * Requests presented after this moment are refused with
2705
- * `virtual_key_expired`. `status` stays "active" past the date, so read
2706
- * this field rather than the status to tell an expired key apart.
2280
+ * When the key stops serving, or null for a key that never expires. Requests presented
2281
+ * after this moment are refused with `virtual_key_expired`. `status` stays "active" past
2282
+ * the date, so read this field to tell an expired key apart, not status.
2707
2283
  */
2708
2284
  expires_at: string | null;
2709
2285
  }
@@ -2752,10 +2328,9 @@ interface CreateVirtualKeyInput {
2752
2328
  */
2753
2329
  metadata?: Record<string, string>;
2754
2330
  /**
2755
- * Withhold the secret from the response and get a one-time reveal id
2756
- * instead. The secret is parked for 24 hours and served once, to the
2757
- * person the key is for, through the LangWatch app; the caller never
2758
- * holds it.
2331
+ * Withhold the secret from the response and get a one-time reveal id instead. The secret is
2332
+ * parked for 24 hours and served once, to the person the key is for, through the LangWatch app;
2333
+ * the caller never holds it.
2759
2334
  */
2760
2335
  reveal_once?: boolean;
2761
2336
  }
@@ -2803,10 +2378,9 @@ interface VirtualKeyWithReveal {
2803
2378
  interface VirtualKeyPage {
2804
2379
  data: VirtualKey[];
2805
2380
  /**
2806
- * Pass back as `cursor` for the next page. Null means the walk is
2807
- * exhausted. Neither page length tells you anything here: visibility is
2808
- * applied to each page AFTER it is read, so a page can hold fewer rows
2809
- * than `limit` with more still to come.
2381
+ * Pass back as `cursor` for the next page. Null means the walk is exhausted. Neither page
2382
+ * length tells you anything here: visibility is applied to each page AFTER it is read, so
2383
+ * a page can hold fewer rows than `limit` with more still to come.
2810
2384
  */
2811
2385
  next_cursor: string | null;
2812
2386
  }
@@ -2827,32 +2401,29 @@ declare class VirtualKeysApiError extends Error {
2827
2401
  constructor(message: string, operation: string, originalError?: unknown | undefined);
2828
2402
  }
2829
2403
  /**
2830
- * Client for the gateway virtual-key surface (/api/gateway/v1).
2831
- *
2832
- * Entity types and the create/update bodies mirror the wire verbatim, so
2833
- * their fields are lowercase snake_case. Call options this SDK invents (query
2834
- * filters, per-call behaviour, action arguments) are camelCase like the rest
2835
- * of the SDK.
2404
+ * Client for the gateway virtual-key surface (/api/gateway/v1). Entity types and the
2405
+ * create/update bodies mirror the wire verbatim (lowercase snake_case); call options this
2406
+ * SDK invents (filters, per-call behaviour, action arguments) are camelCase like the rest.
2836
2407
  */
2837
2408
  declare class VirtualKeysApiService {
2838
2409
  private readonly endpoint;
2839
2410
  private readonly apiKey;
2411
+ /** The project the caller asked for. Sent on every request, where it narrows what is read. */
2840
2412
  private readonly projectId;
2413
+ /** Where a key created with no scope lands: the project asked for, else the one resolved. */
2414
+ private readonly defaultProjectId;
2841
2415
  constructor(config?: {
2842
2416
  endpoint?: string;
2843
2417
  apiKey?: string;
2844
2418
  projectId?: string;
2845
2419
  });
2420
+ private mergedHeaders;
2846
2421
  private headers;
2847
2422
  private request;
2848
2423
  /**
2849
- * ONE page of the virtual keys visible to the caller, newest first. Pass
2850
- * `next_cursor` back as `cursor` for the next page, verbatim: a cursor this
2851
- * endpoint did not issue answers 400 rather than restarting the walk.
2852
- *
2853
- * `limit` is the page size (server default 50, capped at 200), and it caps
2854
- * the rows READ, not the rows returned: the visibility filter runs on the
2855
- * page afterwards. Prefer `list()` unless you mean to page deliberately.
2424
+ * ONE page of the virtual keys visible to the caller, newest first. Pass `next_cursor`
2425
+ * back as `cursor` verbatim — an unrecognized cursor answers 400 rather than restarting.
2426
+ * `limit` caps rows READ, not returned. Prefer `list()` unless paging deliberately.
2856
2427
  */
2857
2428
  listPage(options?: {
2858
2429
  cursor?: string;
@@ -2861,17 +2432,9 @@ declare class VirtualKeysApiService {
2861
2432
  externalId?: string;
2862
2433
  }): Promise<VirtualKeyPage>;
2863
2434
  /**
2864
- * Every virtual key visible to the caller: keys scoped to this project, to
2865
- * its team, or to the whole organization.
2866
- *
2867
- * The endpoint pages; this follows `next_cursor` until it comes back null.
2868
- * Stopping on a short page would be wrong here specifically, because the
2869
- * server filters each page for visibility after reading it, so a page can
2870
- * hold fewer rows than the limit with more still to come.
2871
- *
2872
- * `limit` sizes each request in the walk, it does NOT cap what comes back.
2873
- * `cursor` resumes an interrupted walk. Take a single page with
2874
- * `listPage()`, or stream the walk with `iterate()`.
2435
+ * Every virtual key visible to the caller (project, team, or org scoped). Follows
2436
+ * `next_cursor` until null — a short page does NOT mean done, since the visibility filter
2437
+ * runs after each page. `limit` sizes each request, it does not cap the total.
2875
2438
  */
2876
2439
  list(options?: {
2877
2440
  cursor?: string;
@@ -2880,11 +2443,9 @@ declare class VirtualKeysApiService {
2880
2443
  externalId?: string;
2881
2444
  }): Promise<VirtualKey[]>;
2882
2445
  /**
2883
- * Every visible virtual key, one row at a time, fetching each page only
2884
- * when the consumer reaches it. Stop early and the rest is never read,
2885
- * which `list()` cannot offer because it materialises the whole listing
2886
- * first. Raises rather than looping forever on a cursor chain that never
2887
- * ends, exactly like `list()`.
2446
+ * Every visible virtual key, one row at a time, fetching each page only when the
2447
+ * consumer reaches it — stop early and the rest is never read, unlike `list()` which
2448
+ * materialises the whole listing first. Raises rather than looping forever, like `list()`.
2888
2449
  */
2889
2450
  iterate(options?: {
2890
2451
  cursor?: string;
@@ -2894,10 +2455,9 @@ declare class VirtualKeysApiService {
2894
2455
  }): AsyncGenerator<VirtualKey>;
2895
2456
  get(id: string): Promise<VirtualKey>;
2896
2457
  /**
2897
- * Mint a key. The response carries the secret ONCE; nothing ever serves it
2898
- * again, so a create that times out is recovered with `idempotencyKey`
2899
- * rather than by listing. With `reveal_once` the response carries a reveal
2900
- * id in place of the secret.
2458
+ * Mint a key. The response carries the secret ONCE; nothing ever serves it again, so a create
2459
+ * that times out is recovered with `idempotencyKey` rather than by listing. With `reveal_once`
2460
+ * the response carries a reveal id in place of the secret.
2901
2461
  */
2902
2462
  create(input: CreateVirtualKeyInput & {
2903
2463
  reveal_once: true;
@@ -2912,10 +2472,9 @@ declare class VirtualKeysApiService {
2912
2472
  } & MutationOptions): Promise<VirtualKey>;
2913
2473
  enable(id: string, options?: MutationOptions): Promise<VirtualKey>;
2914
2474
  /**
2915
- * Aggregate spend for one key over a window in epoch milliseconds.
2916
- * Defaults to the current UTC calendar month server-side. Reads the same
2917
- * cost path the dashboard reads, so this number and the UI agree by
2918
- * construction.
2475
+ * Aggregate spend for one key over a window in epoch milliseconds. Defaults to the
2476
+ * current UTC calendar month server-side. Reads the same cost path the dashboard reads,
2477
+ * so this number and the UI agree by construction.
2919
2478
  */
2920
2479
  spend(id: string, options?: {
2921
2480
  from?: number;
@@ -2936,11 +2495,9 @@ interface GatewayBudget {
2936
2495
  window: BudgetWindow;
2937
2496
  on_breach: BudgetOnBreach;
2938
2497
  /**
2939
- * For `group` rows this is the PER-MEMBER allowance, not a group total;
2940
- * `spent_usd` sums the whole group and `member_count` says how many
2941
- * members the allowance currently covers. For `attributed_user` rows it is
2942
- * the PER-PERSON cap, and `end_users_seen` / `end_users_over` carry the
2943
- * standing instead of `spent_usd`.
2498
+ * For `group` rows, the PER-MEMBER allowance (`member_count` says how many
2499
+ * it covers); for `attributed_user` rows, the PER-PERSON cap, with
2500
+ * `end_users_seen`/`end_users_over` as the standing instead of `spent_usd`.
2944
2501
  */
2945
2502
  limit_usd: string;
2946
2503
  /** Canonical integer limit, nano-USD. Null past the safe integer range. */
@@ -2971,11 +2528,9 @@ interface GatewayBudget {
2971
2528
  end_users_over?: number;
2972
2529
  }
2973
2530
  /**
2974
- * One page of the budget listing, exactly as the wire serves it.
2975
- *
2976
- * Budgets come back in an envelope where virtual keys come back as a bare
2977
- * array because `spend_available` is a correctness flag about the whole page,
2978
- * and an array cannot carry it.
2531
+ * One page of the budget listing, exactly as the wire serves it. An envelope,
2532
+ * not a bare array, because `spend_available` is a correctness flag about the
2533
+ * whole page and an array cannot carry it.
2979
2534
  */
2980
2535
  interface GatewayBudgetPage {
2981
2536
  data: GatewayBudget[];
@@ -3024,10 +2579,9 @@ interface CreateGatewayBudgetInput {
3024
2579
  /** ModelProvider id to pin the budget to one provider. */
3025
2580
  provider_key?: string | null;
3026
2581
  /**
3027
- * RFC3339 instant that phases the budget's cycle instead of the calendar:
3028
- * a `month` budget anchored `2026-01-17T09:00:00Z` rolls every 17th at
3029
- * 09:00 UTC. Omit for calendar alignment. Immutable once created, and
3030
- * rejected on the windows that never cycle (`total`, `manual`).
2582
+ * RFC3339 instant phasing the cycle instead of the calendar (a `month`
2583
+ * anchored `2026-01-17T09:00:00Z` rolls every 17th at 09:00 UTC). Immutable
2584
+ * once created; rejected on windows that never cycle (`total`, `manual`).
3031
2585
  */
3032
2586
  cycle_anchor_at?: string;
3033
2587
  /**
@@ -3055,12 +2609,9 @@ declare class GatewayBudgetsApiError extends Error {
3055
2609
  constructor(message: string, operation: string, originalError?: unknown | undefined);
3056
2610
  }
3057
2611
  /**
3058
- * Client for the gateway budget surface (/api/gateway/v1).
3059
- *
3060
- * Entity types and the create/update bodies mirror the wire verbatim, so
3061
- * their fields are lowercase snake_case. Call options this SDK invents (query
3062
- * filters, per-call behaviour, action arguments) are camelCase like the rest
3063
- * of the SDK.
2612
+ * Client for the gateway budget surface (/api/gateway/v1). Entity/body fields
2613
+ * mirror the wire verbatim (snake_case); options this SDK invents (filters,
2614
+ * per-call behaviour, actions) are camelCase like the rest.
3064
2615
  */
3065
2616
  declare class GatewayBudgetsApiService {
3066
2617
  private readonly endpoint;
@@ -3074,13 +2625,9 @@ declare class GatewayBudgetsApiService {
3074
2625
  private headers;
3075
2626
  private request;
3076
2627
  /**
3077
- * ONE page of non-archived budgets, exactly as the wire serves it. Pass
3078
- * `next_cursor` back as `cursor` for the next page, verbatim: a cursor this
3079
- * endpoint did not issue answers 400 rather than restarting the walk.
3080
- *
3081
- * `limit` is the page size (server default 50, capped at 200). Prefer
3082
- * `list()` unless you mean to page deliberately: a full page is not a
3083
- * promise of more, and a null `next_cursor` is the only end of the walk.
2628
+ * ONE page of non-archived budgets. Pass `next_cursor` back as `cursor`
2629
+ * verbatim: an unissued cursor answers 400 rather than restarting the walk.
2630
+ * `limit` is the page size (default 50, capped 200) — prefer `list()`.
3084
2631
  */
3085
2632
  listPage(options?: {
3086
2633
  scopeTypes?: BudgetScopeKind[];
@@ -3090,24 +2637,9 @@ declare class GatewayBudgetsApiService {
3090
2637
  externalId?: string;
3091
2638
  }): Promise<GatewayBudgetPage>;
3092
2639
  /**
3093
- * Every non-archived budget in the organization across all seven scope
3094
- * types, optionally filtered by `scopeTypes`.
3095
- *
3096
- * The endpoint pages; this follows `next_cursor` until it comes back null,
3097
- * so the result is the complete listing and carries no cursor of its own.
3098
- * Callers that count, total, or decide an all-clear on this list need that
3099
- * completeness for correctness, not just for display.
3100
- *
3101
- * `limit` sizes each request in the walk, it does NOT cap what comes back.
3102
- * `cursor` resumes an interrupted walk. Take a single page with
3103
- * `listPage()`, or stream the walk with `iterate()`.
3104
- *
3105
- * A plain array, like every other exhaustive `list()` in the SDK: a walk
3106
- * that ran to the end has no cursor left to report. Null `spent_usd` /
3107
- * `spent_nano_usd` on a row is not by itself "spend unavailable": an
3108
- * `attributed_user` template row serves null deliberately, because one
3109
- * allowance per person has no single total. Use `listPage()` when you need
3110
- * `spend_available` stated outright.
2640
+ * Every non-archived budget across all scope types, following `next_cursor`
2641
+ * to completion — callers that count/total need that. Plain array, no
2642
+ * cursor; `limit` sizes requests but doesn't cap the result.
3111
2643
  */
3112
2644
  list(options?: {
3113
2645
  scopeTypes?: BudgetScopeKind[];
@@ -3118,10 +2650,8 @@ declare class GatewayBudgetsApiService {
3118
2650
  }): Promise<GatewayBudget[]>;
3119
2651
  /**
3120
2652
  * Every non-archived budget, one row at a time, fetching each page only
3121
- * when the consumer reaches it.
3122
- *
3123
- * A null `spent_usd` means spend could not be totalled rather than that
3124
- * nothing was spent.
2653
+ * when the consumer reaches it. A null `spent_usd` means spend could not
2654
+ * be totalled, not that nothing was spent.
3125
2655
  */
3126
2656
  iterate(options?: {
3127
2657
  scopeTypes?: BudgetScopeKind[];
@@ -3131,12 +2661,9 @@ declare class GatewayBudgetsApiService {
3131
2661
  externalId?: string;
3132
2662
  }): AsyncGenerator<GatewayBudget>;
3133
2663
  /**
3134
- * One budget by id, in the same row shape the listing serves.
3135
- *
3136
- * Archived budgets are not served, so a budget that existed yesterday can
3137
- * answer 404 today. A null `spent_usd` means spend could not be totalled
3138
- * rather than that nothing was spent, which is the same signal the listing
3139
- * carries as `spend_available`.
2664
+ * One budget by id, in the same row shape the listing serves. Archived
2665
+ * budgets are not served, so a budget that existed yesterday can answer
2666
+ * 404 today.
3140
2667
  */
3141
2668
  get(id: string): Promise<GatewayBudget>;
3142
2669
  create(input: CreateGatewayBudgetInput, options?: IdempotentCreateOptions): Promise<GatewayBudget>;
@@ -3153,16 +2680,9 @@ declare class GatewayBudgetsApiService {
3153
2680
  }
3154
2681
 
3155
2682
  /**
3156
- * The quantities one priced request or rollup carries. Every field is always
3157
- * present; a bucket the request never used reports 0.
3158
- *
3159
- * The token buckets are disjoint, not nested. An image generation reports its
3160
- * render under `output_image_tokens` with `output_tokens` at 0, so reading
3161
- * `output_tokens` alone sees none of the image traffic.
3162
- *
3163
- * Every priced quantity is charged once at its own rate. `reasoning_tokens`
3164
- * is a subset of `output_tokens` and `image_count` is a count of images, so
3165
- * no rate prices either and neither belongs in a cost sum.
2683
+ * The quantities one priced request or rollup carries; every field is
2684
+ * always present (0 when unused) and buckets are disjoint, not nested.
2685
+ * `reasoning_tokens` and `image_count` are subsets already priced elsewhere.
3166
2686
  */
3167
2687
  interface SpendUsage {
3168
2688
  input_tokens: number;
@@ -3228,7 +2748,7 @@ interface SpendSummaryRow {
3228
2748
  * two dimensions, two rows can share a key: read `group` to tell them apart.
3229
2749
  */
3230
2750
  key: string;
3231
- /** Every grouping dimension by name, e.g. `{ model: "gpt-5-mini" }`. */
2751
+ /** Every grouping dimension by name, e.g. `{ model: "gpt-6-luna" }`. */
3232
2752
  group: Record<string, string>;
3233
2753
  /** Start of the time bucket in the requested zone, null when unbucketed. */
3234
2754
  bucket_start: string | null;
@@ -3242,30 +2762,15 @@ interface SpendSummaryRow {
3242
2762
  nano_usd: number;
3243
2763
  };
3244
2764
  }
3245
- /**
3246
- * The states a request can be filtered by, which is more than the two a
3247
- * caller usually thinks in: a request is `admitted` when it starts,
3248
- * `confirmed` or `failed` when it ends, and `settled` once its cost is final.
3249
- * `success` and `error` are the coarse outcome pair over those.
3250
- */
2765
+ /** Request states: admitted at start, confirmed/failed/settled at end. */
3251
2766
  type SpendEventStatus = "success" | "error" | "admitted" | "confirmed" | "failed" | "settled";
3252
- /**
3253
- * The states a ROLLUP can be filtered by. A rollup sums the cost of requests
3254
- * past admission, so `admitted` is refused there rather than answered with a
3255
- * zero; list the events to see those. Derived by exclusion so the two stay one
3256
- * vocabulary.
3257
- */
2767
+ /** Rollup states: excludes admitted (no cost yet). Use events for those. */
3258
2768
  type SpendSummaryStatus = Exclude<SpendEventStatus, "admitted">;
3259
2769
  /** A dimension a rollup can be grouped by. */
3260
2770
  type SpendGroupBy = "virtual_key" | "end_user" | "project" | "model" | "provider" | "principal" | "request_type";
3261
2771
  /**
3262
- * The filters BOTH spend reads accept. A reconciliation checksums the rollups
3263
- * and diffs the events when a checksum disagrees, so the two take the same
3264
- * vocabulary and a divergence can be walked on exactly the narrowing that
3265
- * produced it.
3266
- *
3267
- * Every field takes one value or many; many means "any of these". Naming two
3268
- * different fields narrows.
2772
+ * Shared filters for spend reads. Every field takes one value or many.
2773
+ * Multiple values widen; multiple fields narrow.
3269
2774
  */
3270
2775
  interface SpendFilterOptions {
3271
2776
  projectId?: string | string[];
@@ -3288,24 +2793,12 @@ interface SpendFilterOptions {
3288
2793
  status?: SpendEventStatus;
3289
2794
  }
3290
2795
  /**
3291
- * What a rollup is grouped by, and over what window.
3292
- *
3293
- * Grouping by `model` or `provider`, or into time buckets, is REFUSED with
3294
- * `gateway_spend_group_by_unstable` over a window recent enough that outcomes
3295
- * can still arrive: until a request settles, the model and provider recorded
3296
- * against it are the ones that were asked for, and they are replaced by the
3297
- * ones that actually served it. A page walk over a group that can move counts
3298
- * some requests twice and misses others.
3299
- *
3300
- * Reconcile closed periods and this never fires. For a live view where an
3301
- * approximate shape is enough, send `allowUnstable`.
2796
+ * Grouping by model/provider/time is unstable: outcomes may arrive and change
2797
+ * the recorded values. Use allowUnstable for approximate live views; reconcile
2798
+ * closed periods to avoid this.
3302
2799
  */
3303
2800
  interface SpendSummariesOptions extends Omit<SpendFilterOptions, "status"> {
3304
- /**
3305
- * One lifecycle status, minus `admitted`: a rollup sums the cost of requests
3306
- * past admission, and an admitted request has none yet. List the events for
3307
- * those.
3308
- */
2801
+ /** Lifecycle status; excludes admitted (no cost yet). */
3309
2802
  status?: SpendSummaryStatus;
3310
2803
  /** One or two dimensions. Two rows can share `key`; read `group`. */
3311
2804
  groupBy: SpendGroupBy | SpendGroupBy[];
@@ -3373,29 +2866,8 @@ declare class SpendEventsApiError extends Error {
3373
2866
  constructor(message: string, operation: string, originalError?: unknown | undefined);
3374
2867
  }
3375
2868
  /**
3376
- * Client for the gateway spend reconciliation surface (/api/gateway/v1).
3377
- * Authenticates with an ORGANIZATION API key (sk-lw-*).
3378
- *
3379
- * Entity types mirror the wire verbatim, so their fields are lowercase
3380
- * snake_case. Call options this SDK invents (query filters, per-call
3381
- * behaviour, action arguments) are camelCase like the rest of the SDK.
3382
- *
3383
- * There is no project id here: `/spend-summaries` takes `project_id` as a
3384
- * query filter rather than scoping on a header, so the project belongs to the
3385
- * call, not to the client.
3386
- *
3387
- * The key MUST be an organization API key (`sk-lw-{id}_{secret}`, from
3388
- * Settings > API Keys). A project API key is refused before any permission is
3389
- * consulted, with `credential_class_mismatch`, and no header makes it work:
3390
- * these are organization-scoped routes and a project key names one project.
3391
- * The same organization key also reaches the project-scoped surfaces when
3392
- * given `X-Project-Id`, so one key covers both families and a project key
3393
- * covers only one.
3394
- *
3395
- * Neither collection on this service offers an eager whole-set read. The
3396
- * ledger is unbounded, and materialising a window of it is the very
3397
- * under-counting and out-of-memory footgun the page docstrings warn about:
3398
- * take pages, or stream with `iterate()` / `iterSummaries()`.
2869
+ * Spend reconciliation service (/api/gateway/v1). Requires ORGANIZATION API
2870
+ * key (sk-lw-*). Use iterate/iterSummaries for large windows (no eager read).
3399
2871
  */
3400
2872
  declare class SpendEventsApiService {
3401
2873
  private readonly endpoint;
@@ -3405,15 +2877,7 @@ declare class SpendEventsApiService {
3405
2877
  apiKey?: string;
3406
2878
  });
3407
2879
  private request;
3408
- /**
3409
- * ONE page of the per-request spend ledger for a window. Pass `next_cursor`
3410
- * back as `cursor` for the next page, verbatim.
3411
- *
3412
- * A full page does NOT mean there is more and a short page does NOT mean
3413
- * there is no more: only a null cursor ends the walk. A reconciler that
3414
- * stops on the first page silently under-counts the window, so read every
3415
- * page or stream them with `iterate()`.
3416
- */
2880
+ /** One page of events. Follow next_cursor or use iterate() for the full window. */
3417
2881
  listPage(options: SpendFilterOptions & {
3418
2882
  /** Required: the pull is a ranged read by contract. */
3419
2883
  from: number;
@@ -3421,15 +2885,7 @@ declare class SpendEventsApiService {
3421
2885
  cursor?: string;
3422
2886
  limit?: number;
3423
2887
  }): Promise<SpendEventsPage>;
3424
- /**
3425
- * Every spend event in the window, one row at a time, fetching each page
3426
- * only when the consumer reaches it.
3427
- *
3428
- * This is how a reconciler reads a whole window without holding it: the
3429
- * ledger is unbounded, so there is deliberately no eager `list()` to
3430
- * collect it into an array. Raises rather than looping forever on a cursor
3431
- * chain that never ends.
3432
- */
2888
+ /** Stream events without holding the whole window in memory. */
3433
2889
  iterate(options: SpendFilterOptions & {
3434
2890
  /** Required: the pull is a ranged read by contract. */
3435
2891
  from: number;
@@ -3437,38 +2893,17 @@ declare class SpendEventsApiService {
3437
2893
  cursor?: string;
3438
2894
  limit?: number;
3439
2895
  }): AsyncGenerator<SpendEvent>;
3440
- /**
3441
- * ONE page of per-key spend rollups for a window, paged by group key
3442
- * ascending.
3443
- *
3444
- * The page is a step of a walk, not a whole answer: follow `next_cursor`
3445
- * until it comes back null, or stream the walk with `iterSummaries()`. A
3446
- * reconciler that reads only the first page silently under-counts every
3447
- * tenant past the limit.
3448
- */
2896
+ /** One page of rollups by group key. Use iterSummaries for the full walk. */
3449
2897
  summariesPage(options: SpendSummariesOptions & {
3450
2898
  cursor?: string;
3451
2899
  limit?: number;
3452
2900
  }): Promise<SpendSummariesPage>;
3453
- /**
3454
- * Every rollup row for the window, one at a time, fetching each page only
3455
- * when the consumer reaches it.
3456
- *
3457
- * The rollup has one row per tenant seen in the window, which no bound
3458
- * covers, so there is deliberately no eager whole-set read here either: a
3459
- * checksum that quietly covers part of the window is worse than none.
3460
- */
2901
+ /** Stream rollup rows without holding the whole window in memory. */
3461
2902
  iterSummaries(options: SpendSummariesOptions & {
3462
2903
  cursor?: string;
3463
2904
  limit?: number;
3464
2905
  }): AsyncGenerator<SpendSummaryRow>;
3465
- /**
3466
- * Re-deliver a window's spend envelopes to ONE endpoint through the
3467
- * normal delivery path. Envelope ids are unchanged (your consumer's
3468
- * dedup key); mind your downstream billing system's finite dedup
3469
- * window before replaying old ranges. The window is capped server-side
3470
- * at 7 days per call.
3471
- */
2906
+ /** Re-deliver spend envelopes to an endpoint (max 7 days). */
3472
2907
  replay(options: {
3473
2908
  from: number;
3474
2909
  to: number;
@@ -3547,13 +2982,9 @@ interface CreateWebhookEndpointBase {
3547
2982
  max_in_flight?: number;
3548
2983
  }
3549
2984
  /**
3550
- * The POST body, exactly as the wire takes it.
3551
- *
3552
- * A destination is one kind and one address, so the two are a union rather
3553
- * than independent optional fields: the type refuses `{destination_kind:
3554
- * "sqs"}` with no queue, and `{url, sqs}` together, which is what the server
3555
- * refuses too. `destination_kind` is optional only on the http branch, where
3556
- * absent has always meant http.
2985
+ * The POST body, exactly as the wire takes it. A destination is one kind and
2986
+ * one address, so the two are a union, matching what the server refuses too.
2987
+ * `destination_kind` is optional only on the http branch (absent means http).
3557
2988
  */
3558
2989
  type WebhookDestinationInput = {
3559
2990
  destination_kind?: "http";
@@ -3648,24 +3079,9 @@ declare class WebhooksApiError extends Error {
3648
3079
  constructor(message: string, operation: string, originalError?: unknown | undefined);
3649
3080
  }
3650
3081
  /**
3651
- * Client for the org-anchored webhook platform surface (/api/webhooks/v1).
3652
- * Authenticates with an ORGANIZATION API key (sk-lw-*); project keys are
3653
- * rejected by the server. The surface is anchored on the organization alone,
3654
- * so there is no project id to give this client.
3655
- *
3656
- * The key MUST be an organization API key (`sk-lw-{id}_{secret}`, from
3657
- * Settings > API Keys). A project API key is refused with
3658
- * `credential_class_mismatch` before any permission is consulted, and no
3659
- * header makes it work. The same organization key also reaches the
3660
- * project-scoped surfaces when given `X-Project-Id`, so one key covers both
3661
- * families and a project key covers only one.
3662
- *
3663
- * The endpoint entity and the create/update bodies mirror the wire verbatim,
3664
- * so their fields are lowercase snake_case: virtual keys and gateway budgets
3665
- * already take the wire body as it is, and translating field by field here
3666
- * only made the request bodies of the four billing surfaces disagree. Call
3667
- * options this SDK invents (query filters, per-call behaviour, action
3668
- * arguments) stay camelCase like the rest of the SDK.
3082
+ * Client for the org-anchored webhook platform surface (/api/webhooks/v1) — an ORGANIZATION
3083
+ * API key only; a project key is refused with `credential_class_mismatch`. Fields mirror the
3084
+ * wire verbatim in snake_case, since translating field-by-field made billing surfaces disagree.
3669
3085
  */
3670
3086
  declare class WebhooksApiService {
3671
3087
  private readonly endpoint;
@@ -3685,25 +3101,17 @@ declare class WebhooksApiService {
3685
3101
  create(input: CreateWebhookEndpointInput, options?: IdempotentCreateOptions): Promise<WebhookEndpointWithSecret>;
3686
3102
  update(id: string, input: UpdateWebhookEndpointInput, options?: MutationOptions): Promise<WebhookEndpointSummary>;
3687
3103
  /**
3688
- * Retire an endpoint: the server soft-archives the row, stamping
3689
- * `archived_at` and dropping the status to disabled, so the delivery
3690
- * history stays readable for audit while nothing more is ever sent. The
3691
- * row is archived, not removed, and `gatewayBudgets.archive()` already
3692
- * names that operation, so the billing surfaces agree on the verb.
3693
- *
3694
- * Nothing comes back: the response body carries only an `archived: true`
3695
- * acknowledgement, and a non-2xx already raises.
3104
+ * Retire an endpoint: the server soft-archives the row (stamping `archived_at`, disabling
3105
+ * delivery) so history stays readable for audit. Archived, not removed — same verb as
3106
+ * `gatewayBudgets.archive()`, so the billing surfaces agree.
3696
3107
  */
3697
3108
  archive(id: string, options?: MutationOptions): Promise<void>;
3698
3109
  rollSecret(id: string, options?: MutationOptions): Promise<WebhookEndpointWithSecret>;
3699
3110
  test(id: string, options?: MutationOptions): Promise<WebhookTestResult>;
3700
3111
  /**
3701
- * ONE page of the endpoint's delivery attempts, newest first.
3702
- *
3703
- * The cursor is why this is a page: the route has always served one, and
3704
- * dropping it truncated the delivery log at whatever the first page held,
3705
- * with nothing in the result to say the rest existed. Pass `next_cursor`
3706
- * back as `cursor`, or walk the whole log with `iterDeliveries()`.
3112
+ * ONE page of the endpoint's delivery attempts, newest first. Pass
3113
+ * `next_cursor` back as `cursor` for the next page, or walk the whole log
3114
+ * with `iterDeliveries()`.
3707
3115
  */
3708
3116
  deliveriesPage(id: string, options?: {
3709
3117
  cursor?: string;
@@ -3721,10 +3129,8 @@ declare class WebhooksApiService {
3721
3129
  eventTypes(): Promise<WebhookEventType[]>;
3722
3130
  /**
3723
3131
  * ONE page of the organization's emitted-events log, newest first.
3724
- *
3725
- * Webhooks are a push over this log, never the only copy of it: a consumer
3726
- * that missed a delivery reads the window back from here. Walk the whole
3727
- * window with `iterEvents()`.
3132
+ * Webhooks are a push over this log, never the only copy: a consumer that
3133
+ * missed a delivery reads the window back from here.
3728
3134
  */
3729
3135
  eventsPage(options: {
3730
3136
  type?: string;
@@ -3747,21 +3153,17 @@ declare class WebhooksApiService {
3747
3153
  limit?: number;
3748
3154
  }): AsyncGenerator<EmittedEvent>;
3749
3155
  /**
3750
- * One emitted event by id, the envelope exactly as it was delivered.
3751
- *
3752
- * A 404 covers every reason the log cannot answer: never emitted, past the
3753
- * retention horizon, or belonging to another organization.
3156
+ * One emitted event by id, the envelope exactly as it was delivered. A 404
3157
+ * covers every reason the log cannot answer: never emitted, past
3158
+ * retention, or belonging to another organization.
3754
3159
  */
3755
3160
  getEvent(id: string): Promise<EmittedEvent>;
3756
3161
  }
3757
3162
 
3758
3163
  /**
3759
- * The vocabulary the management REST families share on the wire.
3760
- *
3761
- * A role binding grants a scoped role, and the same three words appear on
3762
- * roles, role bindings, groups, teams and API keys. Declared once here so the
3763
- * CLI's flag parsers validate against one list rather than five copies that
3764
- * can disagree with the platform.
3164
+ * The vocabulary the management REST families share on the wire: the same
3165
+ * three words appear on roles, bindings, groups, teams and API keys.
3166
+ * Declared once so flag parsers validate against one list, not five.
3765
3167
  */
3766
3168
  /** The role a binding grants at its scope. `CUSTOM` defers to a custom role. */
3767
3169
  declare const MANAGEMENT_ROLES: readonly ["ADMIN", "MEMBER", "VIEWER", "CUSTOM"];
@@ -3814,7 +3216,7 @@ declare class TeamsApiService {
3814
3216
  create(input: {
3815
3217
  name: string;
3816
3218
  }): Promise<Team>;
3817
- update({ id, input, }: {
3219
+ update({ id, input }: {
3818
3220
  id: string;
3819
3221
  input: {
3820
3222
  name?: string;
@@ -3864,6 +3266,12 @@ interface UpdateProjectInput {
3864
3266
  language?: string;
3865
3267
  framework?: string;
3866
3268
  piiRedactionLevel?: "STRICT" | "ESSENTIAL" | "DISABLED";
3269
+ /**
3270
+ * Moves the project to this team. The platform refuses a team outside the
3271
+ * organization, an archived one, and a move across the personal workspace
3272
+ * boundary.
3273
+ */
3274
+ teamId?: string;
3867
3275
  }
3868
3276
  interface ProjectWithServiceKey extends Project {
3869
3277
  serviceApiKey: string;
@@ -3887,18 +3295,16 @@ declare class ProjectsApiError extends Error {
3887
3295
  readonly operation: string;
3888
3296
  readonly originalError?: unknown | undefined;
3889
3297
  /**
3890
- * The status the platform answered with. Callers that resolve a
3891
- * `--project` selector through the listing branch on it: a 401/403 means
3892
- * the credential cannot see the listing at all, which is a different
3893
- * answer to the user than "no project of yours matches this name".
3298
+ * The status the platform answered with. A 401/403 means the credential
3299
+ * cannot see the listing at all -- a different answer than "no project
3300
+ * of yours matches this name".
3894
3301
  */
3895
3302
  readonly status?: number | undefined;
3896
3303
  constructor(message: string, operation: string, originalError?: unknown | undefined,
3897
3304
  /**
3898
- * The status the platform answered with. Callers that resolve a
3899
- * `--project` selector through the listing branch on it: a 401/403 means
3900
- * the credential cannot see the listing at all, which is a different
3901
- * answer to the user than "no project of yours matches this name".
3305
+ * The status the platform answered with. A 401/403 means the credential
3306
+ * cannot see the listing at all -- a different answer than "no project
3307
+ * of yours matches this name".
3902
3308
  */
3903
3309
  status?: number | undefined);
3904
3310
  }
@@ -3910,11 +3316,9 @@ declare class ProjectsApiService {
3910
3316
  apiKey?: string;
3911
3317
  });
3912
3318
  /**
3913
- * Bearer, never the project-pinned Basic shape the data routes use. The
3914
- * listing is the question "which projects can this credential see?", so
3915
- * naming one project in the header would scope the answer to that project
3916
- * and defeat the call — including the `--project <slug>` lookup, which reads
3917
- * the listing precisely because it does not know the id yet.
3319
+ * Bearer, never the project-pinned Basic shape: the listing asks "which
3320
+ * projects can this credential see?", so naming one project in the header
3321
+ * would scope the answer and defeat the call, including `--project <slug>`.
3918
3322
  */
3919
3323
  private headers;
3920
3324
  private request;
@@ -3937,17 +3341,107 @@ declare class ProjectsApiService {
3937
3341
  interface GetTraceParams {
3938
3342
  includeSpans?: boolean;
3939
3343
  }
3940
- type GetTraceResponse = NonNullable<paths["/api/trace/{id}"]["get"]["responses"]["200"]["content"]["application/json"]>;
3344
+ /** The error block a trace or one of its parts carries when it failed. */
3345
+ interface TraceErrorCapture {
3346
+ stacktrace?: string[];
3347
+ message?: string;
3348
+ has_error?: boolean;
3349
+ }
3350
+ /** One message in a span's chat input or output. */
3351
+ interface TraceChatMessage {
3352
+ role?: string;
3353
+ content?: string;
3354
+ }
3355
+ /** One span of a trace, as the trace read answers it. */
3356
+ interface TraceSpan {
3357
+ trace_id?: string;
3358
+ span_id?: string;
3359
+ project_id?: string;
3360
+ parent_id?: string | null;
3361
+ name?: string | null;
3362
+ type?: string;
3363
+ model?: string;
3364
+ timestamps?: {
3365
+ started_at?: number;
3366
+ first_token_at?: number;
3367
+ finished_at?: number;
3368
+ inserted_at?: number;
3369
+ updated_at?: number;
3370
+ };
3371
+ error?: TraceErrorCapture | null;
3372
+ params?: {
3373
+ stream?: boolean;
3374
+ temperature?: number;
3375
+ };
3376
+ metrics?: {
3377
+ prompt_tokens?: number;
3378
+ completion_tokens?: number;
3379
+ tokens_estimated?: boolean;
3380
+ };
3381
+ input?: {
3382
+ type?: string;
3383
+ value?: TraceChatMessage[];
3384
+ };
3385
+ output?: {
3386
+ type?: string;
3387
+ value?: TraceChatMessage[];
3388
+ };
3389
+ }
3390
+ /** One evaluation recorded against a trace. */
3391
+ interface TraceEvaluation {
3392
+ evaluation_id?: string;
3393
+ name?: string;
3394
+ type?: string;
3395
+ trace_id?: string;
3396
+ project_id?: string;
3397
+ status?: string;
3398
+ timestamps?: {
3399
+ inserted_at?: number;
3400
+ updated_at?: number;
3401
+ };
3402
+ error?: TraceErrorCapture;
3403
+ }
3404
+ /**
3405
+ * A single trace with its spans and evaluations. Hand-declared because the
3406
+ * served OpenAPI document describes this answer as a free-form object, so the
3407
+ * generated client cannot carry the shape callers read.
3408
+ */
3409
+ interface GetTraceResponse {
3410
+ trace_id?: string;
3411
+ project_id?: string;
3412
+ metadata?: {
3413
+ sdk_version?: string;
3414
+ sdk_language?: string;
3415
+ };
3416
+ timestamps?: {
3417
+ started_at?: number;
3418
+ inserted_at?: number;
3419
+ updated_at?: number;
3420
+ };
3421
+ input?: {
3422
+ value?: string;
3423
+ };
3424
+ output?: {
3425
+ value?: string;
3426
+ };
3427
+ error?: TraceErrorCapture | null;
3428
+ indexing_md5s?: string[];
3429
+ spans?: TraceSpan[];
3430
+ evaluations?: TraceEvaluation[];
3431
+ }
3941
3432
 
3433
+ /** `langwatch.traces`: the CLI's trace read, traced. Failures throw `TracesApiError`. */
3942
3434
  declare class TracesFacade {
3943
3435
  #private;
3944
3436
  constructor(config: InternalConfig);
3945
- get(traceId: string, params?: GetTraceParams): Promise<GetTraceResponse>;
3437
+ /** `params` stays for compatibility; the endpoint takes no such option and never got one. */
3438
+ get(traceId: string, _params?: GetTraceParams): Promise<GetTraceResponse>;
3946
3439
  }
3947
3440
 
3948
3441
  interface LangWatchConstructorOptions {
3949
3442
  apiKey?: string;
3950
3443
  endpoint?: string;
3444
+ projectId?: string;
3951
3445
  options?: {
3952
3446
  logger?: Logger;
3953
3447
  };
@@ -3960,41 +3454,17 @@ declare class LangWatch {
3960
3454
  readonly datasets: DatasetsFacade;
3961
3455
  /**
3962
3456
  * Run experiments on LangWatch platform or via SDK.
3963
- *
3964
- * Platform experiments (CI/CD):
3965
- * ```typescript
3966
- * const result = await langwatch.experiments.run("my-experiment-slug");
3967
- * result.printSummary();
3968
- * ```
3969
- *
3970
- * SDK-defined experiments:
3971
- * ```typescript
3972
- * const experiment = await langwatch.experiments.init("my-experiment");
3973
- * // ... run evaluators using experiment.evaluate()
3974
- * ```
3975
3457
  */
3976
3458
  readonly experiments: ExperimentsFacade;
3977
3459
  /**
3978
3460
  * Run evaluators and guardrails in real-time (Online Evaluations).
3979
- *
3980
3461
  * @example
3981
- * ```typescript
3982
- * const guardrail = await langwatch.evaluations.evaluate("presidio/pii_detection", {
3983
- * data: { input: userInput, output: generatedResponse },
3984
- * name: "PII Detection",
3985
- * asGuardrail: true,
3986
- * });
3987
- *
3988
- * if (!guardrail.passed) {
3989
- * return "I'm sorry, I can't do that.";
3990
- * }
3991
- * ```
3992
3462
  */
3993
3463
  readonly evaluations: EvaluationsFacade;
3994
3464
  readonly evaluators: EvaluatorsApiService;
3995
3465
  readonly scenarios: ScenariosApiService;
3996
3466
  /**
3997
- * @deprecated Use runPlans and testSuites; /api/suites is a frozen alias.
3467
+ * @deprecated Use runPlans and testSuites; /api/v1/suites is a frozen alias.
3998
3468
  */
3999
3469
  readonly suites: SuitesApiService;
4000
3470
  readonly runPlans: RunPlansApiService;
@@ -4004,10 +3474,13 @@ declare class LangWatch {
4004
3474
  readonly workflows: WorkflowsApiService;
4005
3475
  readonly agents: AgentsApiService;
4006
3476
  readonly annotations: AnnotationsApiService;
3477
+ /** The project's dashboards and the widgets on them, over /api/v1/dashboards. */
4007
3478
  readonly dashboards: DashboardsApiService;
3479
+ /** The Analytics Reports, over /api/v1/analytics/reports; the platform deprecates them. */
3480
+ readonly analyticsReports: AnalyticsReportsApiService;
4008
3481
  readonly modelProviders: ModelProvidersApiService;
4009
3482
  readonly analytics: AnalyticsApiService;
4010
- /** The raw LangWatchQL door — run a governed SELECT or discover the analytics schema directly, outside a saved chart. */
3483
+ /** The raw LangWatchQL door: a governed SELECT or schema discovery outside a saved chart. */
4011
3484
  readonly query: QueryApiService;
4012
3485
  readonly triggers: TriggersApiService;
4013
3486
  readonly graphs: GraphsApiService;
@@ -4021,13 +3494,8 @@ declare class LangWatch {
4021
3494
  constructor(options?: LangWatchConstructorOptions);
4022
3495
  get apiClient(): LangwatchApiClient;
4023
3496
  /**
4024
- * Teams, which group projects and the members who can reach them. These
4025
- * routes want an organization API key.
4026
- *
4027
- * Built on first use rather than in the constructor: the management
4028
- * families resolve their credential when constructed and refuse an empty
4029
- * one, so building this eagerly would make `new LangWatch()` throw for
4030
- * every caller that never touches a team.
3497
+ * Teams, which group projects and the members who can reach them. These routes want an
3498
+ * organization API key.
4031
3499
  */
4032
3500
  get teams(): TeamsApiService;
4033
3501
  /**
@@ -4039,43 +3507,10 @@ declare class LangWatch {
4039
3507
 
4040
3508
  /**
4041
3509
  * A failure the platform NAMED.
4042
- *
4043
- * The API does not merely fail — when it declines a request it says precisely
4044
- * why, as a `HandledError` with a serialisable `kind` (`dataset_not_found`,
4045
- * `validation_error`), the HTTP status it answers with, and a `meta` bag of the
4046
- * context that makes the failure actionable. Until now the SDK collapsed all of
4047
- * that into an English sentence on a generic error, so a caller could read the
4048
- * failure but never react to it: a 404 "dataset not found" — a fact you can
4049
- * offer to fix — was indistinguishable from a 500.
4050
- *
4051
- * This is that structure, kept. Narrow with {@link isLangWatchHandledError} (or
4052
- * `instanceof`) and switch on `code`; `body` is the escape hatch to whatever the
4053
- * platform sent that this class did not model.
4054
- *
4055
- * ```ts
4056
- * try {
4057
- * await langwatch.datasets.get("nope");
4058
- * } catch (error) {
4059
- * if (isLangWatchHandledError(error) && error.code === "dataset_not_found") {
4060
- * // Actionable: we know WHAT was not found, and can offer the list.
4061
- * console.error(error.meta.id, error.traceId);
4062
- * }
4063
- * throw error;
4064
- * }
4065
- * ```
4066
- *
4067
- * ONLY raised for a failure the platform named. An infrastructure failure — a
4068
- * 5xx, a dead socket, a proxy's HTML error page — still raises the generic
4069
- * service error it always did, because presenting one of those as a domain
4070
- * error would blame the user for our outage.
4071
3510
  */
4072
3511
  declare class LangWatchHandledError extends Error {
4073
3512
  /**
4074
- * The discriminant. A boolean brand rather than `instanceof` alone because a
4075
- * bundled CLI and a consumer's `node_modules` copy of the SDK can hold two
4076
- * different copies of this class, and `instanceof` is false across that seam —
4077
- * the same reason the platform's own error handler tests for `code` rather
4078
- * than class identity.
3513
+ * The discriminant.
4079
3514
  */
4080
3515
  readonly isLangWatchHandledError: true;
4081
3516
  /** The platform's serialisable discriminant, e.g. `dataset_not_found`. */
@@ -4096,7 +3531,9 @@ declare class LangWatchHandledError extends Error {
4096
3531
  /** A clickable link to the logs for that trace, when the route sent one. */
4097
3532
  readonly logsUrl: string | undefined;
4098
3533
  /** The failure behind the failure, when the route sent the chain. */
4099
- readonly reasons: CliHandledErrorReason[] | undefined;
3534
+ readonly reasons: LangWatchHandledErrorReason[] | undefined;
3535
+ /** Whether the platform explicitly marked this failure safe to retry. */
3536
+ readonly retryable: boolean;
4100
3537
  /** What the user can DO about it, when the platform sent next steps. */
4101
3538
  readonly suggestions: string[] | undefined;
4102
3539
  /** The docs page that explains the failure, when the platform sent one. */
@@ -4106,18 +3543,13 @@ declare class LangWatchHandledError extends Error {
4106
3543
  /** What the SDK was doing, e.g. `get dataset "abc"`. */
4107
3544
  readonly operation: string | undefined;
4108
3545
  /**
4109
- * Alias of {@link httpStatus}, and the raw body again under the name the
4110
- * per-service `*ApiError` classes use.
4111
- *
4112
- * Not redundancy for its own sake: this class is thrown from the SAME code
4113
- * path that used to throw `TracesApiError` & friends, so anything that reads
4114
- * `.status` or `.originalError` off a caught SDK error — including the CLI's
4115
- * own telemetry reader — keeps working unchanged.
3546
+ * Alias of {@link httpStatus}, and the raw body again under the name the per-service
3547
+ * `*ApiError` classes use.
4116
3548
  */
4117
3549
  readonly status: number;
4118
3550
  readonly originalError: unknown;
4119
3551
  constructor({ handled, body, operation, message, }: {
4120
- handled: CliHandledError;
3552
+ handled: LangWatchHandledErrorShape;
4121
3553
  body: unknown;
4122
3554
  operation?: string;
4123
3555
  message: string;
@@ -4135,43 +3567,22 @@ declare class LangWatchApiError extends Error {
4135
3567
  }
4136
3568
 
4137
3569
  /**
4138
- * Receiver-side verification of a LangWatch webhook delivery.
4139
- *
4140
- * Every delivery carries
4141
- *
4142
- * X-LangWatch-Signature: t=<unix seconds>,v1=<hex hmac-sha256>[,v1=<hex>]
4143
- *
4144
- * where each `v1` is HMAC-SHA256 over `"<t>.<raw body>"` under one currently
4145
- * valid signing secret. `v1` REPEATS during a secret rotation, newest first,
4146
- * which is what lets a receiver swap secrets on its own schedule instead of
4147
- * dropping deliveries mid-swap.
4148
- *
4149
- * That repetition is the reason this helper exists. A hand-rolled parser that
4150
- * keeps the LAST `v1` it sees, or splits the header into a flat key/value map,
4151
- * rejects every delivery to a receiver that has already moved to the new
4152
- * secret: the signature it kept is the one computed from the OLD secret. The
4153
- * bug only appears during a rotation, which is exactly when a receiver can
4154
- * least afford to be dropping deliveries.
4155
- *
4156
- * The algorithm here is pinned to the sender's by the vectors in
4157
- * `specs/webhooks/signature-vectors.json`, generated from the server's own
4158
- * signing code and asserted by the suite next to this file.
3570
+ * Verify webhook delivery signature in X-LangWatch-Signature header.
3571
+ * Handles secret rotation: v1 repeats with newest first.
3572
+ * Pinned to sender's algorithm by specs/webhooks/signature-vectors.json.
4159
3573
  */
4160
3574
  /** The header a delivery carries its signature in. */
4161
3575
  declare const WEBHOOK_SIGNATURE_HEADER = "X-LangWatch-Signature";
4162
3576
  /**
4163
- * Identifies one delivery ATTEMPT on the webhook platform's endpoints.
4164
- *
4165
- * The natural idempotency key for a receiver: retries of the same batch repeat
4166
- * it, so a receiver that has already processed this id can acknowledge and
4167
- * stop rather than applying the batch twice.
3577
+ * Identifies one delivery ATTEMPT on the webhook platform's endpoints. The
3578
+ * natural idempotency key: retries of the same batch repeat it, so a
3579
+ * receiver that already processed this id can stop, not apply it twice.
4168
3580
  */
4169
3581
  declare const WEBHOOK_DELIVERY_ID_HEADER = "X-LangWatch-Delivery-Id";
4170
3582
  /**
4171
3583
  * The same role on automation deliveries (graph alerts and friends), which
4172
- * group their attempts by the logical fire rather than by the batch.
4173
- *
4174
- * Two names because they are two senders: read whichever the delivery carries.
3584
+ * group attempts by the logical fire rather than the batch. Two names
3585
+ * because they are two senders: read whichever the delivery carries.
4175
3586
  */
4176
3587
  declare const WEBHOOK_EVENT_ID_HEADER = "X-LangWatch-Event-Id";
4177
3588
  /**
@@ -4180,22 +3591,12 @@ declare const WEBHOOK_EVENT_ID_HEADER = "X-LangWatch-Event-Id";
4180
3591
  */
4181
3592
  declare const WEBHOOK_SIGNATURE_DEFAULT_TOLERANCE_SECONDS = 300;
4182
3593
  /**
4183
- * Why a delivery was refused. Switch on this rather than on the message: the
4184
- * message is written for a human reading a log and will change, the code is
4185
- * the contract.
4186
- *
4187
- * The three mean genuinely different things to an operator. `stale_timestamp`
4188
- * is a clock or a replay and is worth alerting on; `invalid_signature` is a
4189
- * wrong secret or a tampered body; `malformed_header` is almost always
4190
- * something other than LangWatch posting to the URL.
3594
+ * Why a delivery was refused: malformed_header, stale_timestamp, invalid_signature.
3595
+ * Switch on code, not message; message is for logs and may change.
4191
3596
  */
4192
3597
  type WebhookSignatureFailureCode = "malformed_header" | "stale_timestamp" | "invalid_signature";
4193
3598
  /**
4194
- * A delivery that did not verify.
4195
- *
4196
- * One class carrying a `code` rather than three classes, because the SDK and
4197
- * the platform both ask callers to branch on a stable code instead of on the
4198
- * error's identity, which does not survive a serialization boundary.
3599
+ * A delivery that did not verify. Use code, not error type, to branch logic.
4199
3600
  */
4200
3601
  declare class WebhookSignatureVerificationError extends Error {
4201
3602
  readonly code: WebhookSignatureFailureCode;
@@ -4203,22 +3604,17 @@ declare class WebhookSignatureVerificationError extends Error {
4203
3604
  }
4204
3605
  interface VerifyWebhookSignatureOptions {
4205
3606
  /**
4206
- * The EXACT bytes of the request body, as received.
4207
- *
4208
- * Not a parsed object, and not the result of re-serializing one: the digest
4209
- * is over the bytes the sender hashed, and `JSON.parse` followed by
4210
- * `JSON.stringify` reorders keys, drops insignificant whitespace and
4211
- * re-escapes non-ASCII, any of which changes the digest. Read the raw body
4212
- * before your framework's JSON middleware does.
3607
+ * The EXACT bytes of the request body, as received — not a parsed or
3608
+ * re-serialized object: `JSON.stringify` reorders keys and re-escapes
3609
+ * text, changing the digest. Read the raw body before your JSON middleware.
4213
3610
  */
4214
3611
  body: string | Uint8Array;
4215
3612
  /** The `X-LangWatch-Signature` header value, verbatim. */
4216
3613
  header: string;
4217
3614
  /**
4218
3615
  * The signing secret, or every secret this receiver currently accepts.
4219
- *
4220
- * Pass both values during a rotation and the delivery verifies under
4221
- * either, so there is no window where deliveries are refused.
3616
+ * Pass both during a rotation and the delivery verifies under either, so
3617
+ * there is no window where deliveries are refused.
4222
3618
  */
4223
3619
  secret: string | readonly string[];
4224
3620
  /**
@@ -4233,70 +3629,23 @@ interface VerifyWebhookSignatureOptions {
4233
3629
  nowSeconds?: number;
4234
3630
  }
4235
3631
  /**
4236
- * Verify a webhook delivery, or throw explaining which check failed.
4237
- *
4238
- * ```ts
4239
- * app.post("/langwatch", express.raw({ type: "application/json" }), (req, res) => {
4240
- * try {
4241
- * verifyWebhookSignature({
4242
- * body: req.body, // the raw Buffer, before JSON parsing
4243
- * header: req.header("X-LangWatch-Signature") ?? "",
4244
- * secret: [process.env.WEBHOOK_SECRET_NEW, process.env.WEBHOOK_SECRET_OLD],
4245
- * });
4246
- * } catch (error) {
4247
- * return res.status(400).send((error as WebhookSignatureVerificationError).code);
4248
- * }
4249
- * // Trusted from here.
4250
- * });
4251
- * ```
4252
- *
4253
- * Throws rather than returning false so that a delivery cannot be trusted by
4254
- * forgetting to check a return value. The thrown
4255
- * {@link WebhookSignatureVerificationError} carries a
4256
- * {@link WebhookSignatureFailureCode} saying which check failed.
4257
- *
4258
- * Checks run in a fixed order, so a delivery that is both stale and wrongly
4259
- * signed reports the staleness: a header that did not parse has no
4260
- * trustworthy timestamp to judge, and a timestamp outside the window makes
4261
- * the digest moot.
4262
- *
4263
- * A missing or empty secret is a configuration mistake rather than a bad
4264
- * delivery, and raises `TypeError`. Reporting it as a failed verification
4265
- * would let a receiver that lost its secret quietly refuse every delivery as
4266
- * if the sender were at fault.
3632
+ * Verify a webhook delivery, throwing (not returning false) so a check can't
3633
+ * be skipped by accident. A missing/empty secret throws a plain `TypeError`
3634
+ * instead of a verification failure, so it's never mistaken for sender fault.
4267
3635
  */
4268
3636
  declare function verifyWebhookSignature(options: VerifyWebhookSignatureOptions): void;
4269
3637
 
4270
3638
  /**
4271
- * The one HTTP client every request to the LangWatch API goes through.
4272
- *
4273
- * A LangWatch endpoint configured as `http://app.langwatch.ai` answers with a
4274
- * redirect to https. The global `fetch` follows it on its own and, for a 301
4275
- * or 302, turns the POST into a GET and drops the body, so the event is lost
4276
- * without an error. This client sends with `redirect: "manual"` and applies a
4277
- * rule per method to the 3xx it gets back.
4278
- *
4279
- * GET and HEAD follow a 301, 302, 303, 307 or 308 with the same method, up to
4280
- * five hops. A hop that keeps the origin, or only upgrades http to https on
4281
- * the same host and port, keeps every header; any other hop drops the
4282
- * credential headers first. A hop from https to http and a hop without a
4283
- * Location are refused.
4284
- *
4285
- * Every other method follows exactly one redirect, and only when the target is
4286
- * the same URL with the scheme changed from http to https (same host, port,
4287
- * path and query). The replay uses the same method, headers and body bytes.
4288
- *
4289
- * Every refused redirect throws `LangWatchRedirectError`.
4290
- *
4291
- * This module depends on the SDK logger only, so the CLI boot graph and the
4292
- * `agent` entry can import it without pulling anything else in.
3639
+ * The one HTTP client every LangWatch API request goes through, with
3640
+ * `redirect: "manual"` since the global `fetch` turns a POST into a GET on
3641
+ * a redirect. GET/HEAD follow up to `MAX_FOLLOW_HOPS`; refusal throws.
4293
3642
  */
4294
3643
 
4295
3644
  declare class LangWatchRedirectError extends Error {
4296
3645
  readonly url: string;
4297
3646
  readonly location: string | null;
4298
3647
  readonly status: number;
4299
- constructor({ url, location, status, }: {
3648
+ constructor({ url, location, status }: {
4300
3649
  url: string;
4301
3650
  location: string | null;
4302
3651
  status: number;
@@ -4323,4 +3672,4 @@ declare const logger: {
4323
3672
  NoOpLogger: typeof NoOpLogger;
4324
3673
  };
4325
3674
 
4326
- export { type ArchivedProject, type ArchivedTeam, type BatchCreateRecordsResponse, type BudgetOnBreach, type BudgetScopeKind, type BudgetWindow, ComparisonError, type ComparisonMetric, type ComparisonOptions, type ComparisonStatus, type ComparisonVerdict, type CreateDatasetOptions, type CreateEvaluatorBody, type CreateFromUploadResponse, type CreateGatewayBudgetInput, type CreateGatewayBudgetScope, type CreateLangWatchFetchOptions, type CreateProjectInput, 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, type LangWatchFetch, LangWatchHandledError, LangWatchRedirectError, type ListDatasetsApiResponse, type ListDatasetsOptions, type ListRecordsApiResponse, type ListRecordsOptions, type ListTeamsResponse, type LogOptions, type MutationOptions, type PaginatedProjects, type PaginatedResponse, type Pagination, type Project, type ProjectWithServiceKey, ProjectsApiError, ProjectsApiService, type RunCallback, type RunContext, type RunOptions, type RunWithResultsOptions, type SpendEvent, type SpendEventStatus, SpendEventsApiError, SpendEventsApiService, type SpendEventsPage, type SpendFilterOptions, type SpendGroupBy, type SpendReplayResult, type SpendSummariesOptions, type SpendSummariesPage, type SpendSummaryRow, type SpendSummaryStatus, type TargetInfo, type TargetMetadata, TargetMetadataConflictError, type TargetType, type Team, type TeamMember, type TeamPagination, TeamsApiError, TeamsApiService, type UpdateDatasetOptions, type UpdateGatewayBudgetInput, type UpdateProjectInput, 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, createLangWatchFetch, isLangWatchHandledError, langwatchFetch, logger, verifyWebhookSignature };
3675
+ export { type ArchivedProject, type ArchivedTeam, type BatchCreateRecordsResponse, type BudgetOnBreach, type BudgetScopeKind, type BudgetWindow, ComparisonError, type ComparisonMetric, type ComparisonOptions, type ComparisonStatus, type ComparisonVerdict, type CreateDatasetOptions, type CreateEvaluatorBody, type CreateFromUploadResponse, type CreateGatewayBudgetInput, type CreateGatewayBudgetScope, type CreateLangWatchFetchOptions, type CreateProjectInput, 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 ExperimentEvaluateOptions, type ExperimentEvaluationResult, type 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, type LangWatchFetch, LangWatchHandledError, LangWatchRedirectError, type ListDatasetsApiResponse, type ListDatasetsOptions, type ListRecordsApiResponse, type ListRecordsOptions, type ListTeamsResponse, type LogOptions, type MutationOptions, type PaginatedProjects, type PaginatedResponse, type Pagination, type Project, type ProjectWithServiceKey, ProjectsApiError, ProjectsApiService, type RunCallback, type RunContext, type RunOptions, type RunWithResultsOptions, type SpendEvent, type SpendEventStatus, SpendEventsApiError, SpendEventsApiService, type SpendEventsPage, type SpendFilterOptions, type SpendGroupBy, type SpendReplayResult, type SpendSummariesOptions, type SpendSummariesPage, type SpendSummaryRow, type SpendSummaryStatus, type TargetInfo, type TargetMetadata, TargetMetadataConflictError, type TargetType, type Team, type TeamMember, type TeamPagination, TeamsApiError, TeamsApiService, type UpdateDatasetOptions, type UpdateGatewayBudgetInput, type UpdateProjectInput, 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, createLangWatchFetch, isLangWatchHandledError, langwatchFetch, logger, verifyWebhookSignature };