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