@evalgate/sdk 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.
- package/CHANGELOG.md +638 -0
- package/README.md +398 -0
- package/dist/assertions.d.ts +189 -0
- package/dist/assertions.js +662 -0
- package/dist/batch.d.ts +68 -0
- package/dist/batch.js +179 -0
- package/dist/cache.d.ts +65 -0
- package/dist/cache.js +131 -0
- package/dist/cli/api.d.ts +108 -0
- package/dist/cli/api.js +132 -0
- package/dist/cli/baseline.d.ts +10 -0
- package/dist/cli/baseline.js +172 -0
- package/dist/cli/check.d.ts +73 -0
- package/dist/cli/check.js +355 -0
- package/dist/cli/ci-context.d.ts +6 -0
- package/dist/cli/ci-context.js +112 -0
- package/dist/cli/ci.d.ts +45 -0
- package/dist/cli/ci.js +192 -0
- package/dist/cli/config.d.ts +30 -0
- package/dist/cli/config.js +230 -0
- package/dist/cli/constants.d.ts +15 -0
- package/dist/cli/constants.js +18 -0
- package/dist/cli/diff.d.ts +173 -0
- package/dist/cli/diff.js +685 -0
- package/dist/cli/discover.d.ts +84 -0
- package/dist/cli/discover.js +419 -0
- package/dist/cli/doctor.d.ts +88 -0
- package/dist/cli/doctor.js +675 -0
- package/dist/cli/env.d.ts +21 -0
- package/dist/cli/env.js +42 -0
- package/dist/cli/explain.d.ts +58 -0
- package/dist/cli/explain.js +561 -0
- package/dist/cli/formatters/github.d.ts +8 -0
- package/dist/cli/formatters/github.js +135 -0
- package/dist/cli/formatters/human.d.ts +6 -0
- package/dist/cli/formatters/human.js +110 -0
- package/dist/cli/formatters/json.d.ts +6 -0
- package/dist/cli/formatters/json.js +10 -0
- package/dist/cli/formatters/pr-comment.d.ts +12 -0
- package/dist/cli/formatters/pr-comment.js +103 -0
- package/dist/cli/formatters/types.d.ts +103 -0
- package/dist/cli/formatters/types.js +8 -0
- package/dist/cli/gate.d.ts +21 -0
- package/dist/cli/gate.js +179 -0
- package/dist/cli/impact-analysis.d.ts +63 -0
- package/dist/cli/impact-analysis.js +252 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.js +332 -0
- package/dist/cli/init.d.ts +16 -0
- package/dist/cli/init.js +292 -0
- package/dist/cli/manifest.d.ts +103 -0
- package/dist/cli/manifest.js +282 -0
- package/dist/cli/migrate.d.ts +41 -0
- package/dist/cli/migrate.js +349 -0
- package/dist/cli/policy-packs.d.ts +23 -0
- package/dist/cli/policy-packs.js +89 -0
- package/dist/cli/print-config.d.ts +29 -0
- package/dist/cli/print-config.js +270 -0
- package/dist/cli/profiles.d.ts +28 -0
- package/dist/cli/profiles.js +30 -0
- package/dist/cli/reason-codes.d.ts +17 -0
- package/dist/cli/reason-codes.js +19 -0
- package/dist/cli/regression-gate.d.ts +15 -0
- package/dist/cli/regression-gate.js +341 -0
- package/dist/cli/render/snippet.d.ts +5 -0
- package/dist/cli/render/snippet.js +15 -0
- package/dist/cli/render/sort.d.ts +10 -0
- package/dist/cli/render/sort.js +24 -0
- package/dist/cli/report/build-check-report.d.ts +19 -0
- package/dist/cli/report/build-check-report.js +132 -0
- package/dist/cli/run.d.ts +101 -0
- package/dist/cli/run.js +395 -0
- package/dist/cli/share.d.ts +17 -0
- package/dist/cli/share.js +91 -0
- package/dist/cli/upgrade.d.ts +15 -0
- package/dist/cli/upgrade.js +492 -0
- package/dist/cli/workspace.d.ts +31 -0
- package/dist/cli/workspace.js +68 -0
- package/dist/client.d.ts +368 -0
- package/dist/client.js +893 -0
- package/dist/client.request.test.d.ts +1 -0
- package/dist/client.request.test.js +232 -0
- package/dist/context.d.ts +134 -0
- package/dist/context.js +215 -0
- package/dist/errors.d.ts +82 -0
- package/dist/errors.js +298 -0
- package/dist/export.d.ts +195 -0
- package/dist/export.js +344 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +153 -0
- package/dist/integrations/anthropic.d.ts +91 -0
- package/dist/integrations/anthropic.js +163 -0
- package/dist/integrations/openai-eval.d.ts +57 -0
- package/dist/integrations/openai-eval.js +232 -0
- package/dist/integrations/openai.d.ts +92 -0
- package/dist/integrations/openai.js +160 -0
- package/dist/local.d.ts +39 -0
- package/dist/local.js +148 -0
- package/dist/logger.d.ts +128 -0
- package/dist/logger.js +227 -0
- package/dist/matchers/index.d.ts +1 -0
- package/dist/matchers/index.js +6 -0
- package/dist/matchers/to-pass-gate.d.ts +29 -0
- package/dist/matchers/to-pass-gate.js +35 -0
- package/dist/pagination.d.ts +74 -0
- package/dist/pagination.js +139 -0
- package/dist/regression.d.ts +100 -0
- package/dist/regression.js +44 -0
- package/dist/runtime/adapters/config-to-dsl.d.ts +33 -0
- package/dist/runtime/adapters/config-to-dsl.js +400 -0
- package/dist/runtime/adapters/testsuite-to-dsl.d.ts +63 -0
- package/dist/runtime/adapters/testsuite-to-dsl.js +276 -0
- package/dist/runtime/context.d.ts +26 -0
- package/dist/runtime/context.js +74 -0
- package/dist/runtime/eval.d.ts +46 -0
- package/dist/runtime/eval.js +244 -0
- package/dist/runtime/execution-mode.d.ts +80 -0
- package/dist/runtime/execution-mode.js +357 -0
- package/dist/runtime/executor.d.ts +16 -0
- package/dist/runtime/executor.js +152 -0
- package/dist/runtime/registry.d.ts +78 -0
- package/dist/runtime/registry.js +403 -0
- package/dist/runtime/run-report.d.ts +200 -0
- package/dist/runtime/run-report.js +222 -0
- package/dist/runtime/types.d.ts +356 -0
- package/dist/runtime/types.js +76 -0
- package/dist/snapshot.d.ts +176 -0
- package/dist/snapshot.js +322 -0
- package/dist/streaming.d.ts +173 -0
- package/dist/streaming.js +268 -0
- package/dist/testing.d.ts +273 -0
- package/dist/testing.js +317 -0
- package/dist/types.d.ts +754 -0
- package/dist/types.js +54 -0
- package/dist/utils/input-hash.d.ts +8 -0
- package/dist/utils/input-hash.js +41 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.js +10 -0
- package/dist/workflows.d.ts +389 -0
- package/dist/workflows.js +671 -0
- package/package.json +117 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding =
|
|
3
|
+
(this && this.__createBinding) ||
|
|
4
|
+
(Object.create
|
|
5
|
+
? function (o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (
|
|
9
|
+
!desc ||
|
|
10
|
+
("get" in desc ? !m.__esModule : desc.writable || desc.configurable)
|
|
11
|
+
) {
|
|
12
|
+
desc = {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return m[k];
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}
|
|
21
|
+
: function (o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
});
|
|
25
|
+
var __setModuleDefault =
|
|
26
|
+
(this && this.__setModuleDefault) ||
|
|
27
|
+
(Object.create
|
|
28
|
+
? function (o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}
|
|
31
|
+
: function (o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar =
|
|
35
|
+
(this && this.__importStar) ||
|
|
36
|
+
(function () {
|
|
37
|
+
var ownKeys = function (o) {
|
|
38
|
+
ownKeys =
|
|
39
|
+
Object.getOwnPropertyNames ||
|
|
40
|
+
function (o) {
|
|
41
|
+
var ar = [];
|
|
42
|
+
for (var k in o)
|
|
43
|
+
if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
44
|
+
return ar;
|
|
45
|
+
};
|
|
46
|
+
return ownKeys(o);
|
|
47
|
+
};
|
|
48
|
+
return function (mod) {
|
|
49
|
+
if (mod && mod.__esModule) return mod;
|
|
50
|
+
var result = {};
|
|
51
|
+
if (mod != null)
|
|
52
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++)
|
|
53
|
+
if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
54
|
+
__setModuleDefault(result, mod);
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
57
|
+
})();
|
|
58
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
|
+
const vitest_1 = require("vitest");
|
|
60
|
+
const client_1 = require("./client");
|
|
61
|
+
const errorsModule = __importStar(require("./errors"));
|
|
62
|
+
vitest_1.vi.mock("./cache", () => {
|
|
63
|
+
const cacheTracker = { invalidatedPatterns: [] };
|
|
64
|
+
const shouldCache = vitest_1.vi.fn().mockReturnValue(true);
|
|
65
|
+
const getTTL = vitest_1.vi.fn().mockReturnValue(1000);
|
|
66
|
+
const makeKey = (method, url, params) =>
|
|
67
|
+
`${method}:${url}:${JSON.stringify(params ?? null)}`;
|
|
68
|
+
return {
|
|
69
|
+
__esModule: true,
|
|
70
|
+
shouldCache,
|
|
71
|
+
getTTL,
|
|
72
|
+
cacheTracker,
|
|
73
|
+
RequestCache: class RequestCache {
|
|
74
|
+
constructor() {
|
|
75
|
+
this.store = new Map();
|
|
76
|
+
}
|
|
77
|
+
get(method, url, params) {
|
|
78
|
+
const key = makeKey(method, url, params);
|
|
79
|
+
return this.store.get(key) ?? null;
|
|
80
|
+
}
|
|
81
|
+
set(method, url, data, _ttl, params) {
|
|
82
|
+
const key = makeKey(method, url, params);
|
|
83
|
+
this.store.set(key, data);
|
|
84
|
+
}
|
|
85
|
+
invalidatePattern(pattern) {
|
|
86
|
+
cacheTracker.invalidatedPatterns.push(pattern);
|
|
87
|
+
}
|
|
88
|
+
invalidate(_method, _url, _params) {
|
|
89
|
+
// no-op for tests
|
|
90
|
+
}
|
|
91
|
+
clear() {
|
|
92
|
+
this.store.clear();
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
const cache_1 = require("./cache");
|
|
98
|
+
(0, vitest_1.describe)("AIEvalClient.request", () => {
|
|
99
|
+
(0, vitest_1.beforeEach)(() => {
|
|
100
|
+
process.env.EVALAI_API_KEY = "test";
|
|
101
|
+
cache_1.shouldCache.mockReset().mockReturnValue(true);
|
|
102
|
+
cache_1.getTTL.mockReset().mockReturnValue(1000);
|
|
103
|
+
cache_1.cacheTracker.invalidatedPatterns.length = 0;
|
|
104
|
+
});
|
|
105
|
+
(0, vitest_1.it)(
|
|
106
|
+
"caches GET responses and reuses data without re-fetching",
|
|
107
|
+
async () => {
|
|
108
|
+
const client = new client_1.AIEvalClient({
|
|
109
|
+
apiKey: "test",
|
|
110
|
+
baseUrl: "http://localhost",
|
|
111
|
+
timeout: 1000,
|
|
112
|
+
});
|
|
113
|
+
const payload = { items: [1, 2, 3] };
|
|
114
|
+
const fetchMock = vitest_1.vi.fn().mockResolvedValue({
|
|
115
|
+
ok: true,
|
|
116
|
+
status: 200,
|
|
117
|
+
json: async () => payload,
|
|
118
|
+
});
|
|
119
|
+
globalThis.fetch = fetchMock;
|
|
120
|
+
const first = await client.request("/api/traces", { method: "GET" });
|
|
121
|
+
const second = await client.request("/api/traces", { method: "GET" });
|
|
122
|
+
(0, vitest_1.expect)(first).toEqual(payload);
|
|
123
|
+
(0, vitest_1.expect)(second).toEqual(payload);
|
|
124
|
+
(0, vitest_1.expect)(fetchMock).toHaveBeenCalledTimes(1);
|
|
125
|
+
},
|
|
126
|
+
);
|
|
127
|
+
(0, vitest_1.it)("propagates non-ok responses as SDK errors", async () => {
|
|
128
|
+
const client = new client_1.AIEvalClient({
|
|
129
|
+
apiKey: "test",
|
|
130
|
+
baseUrl: "http://localhost",
|
|
131
|
+
});
|
|
132
|
+
const fetchMock = vitest_1.vi.fn().mockResolvedValue({
|
|
133
|
+
ok: false,
|
|
134
|
+
status: 429,
|
|
135
|
+
json: async () => ({ error: { code: "RATE_LIMIT_EXCEEDED" } }),
|
|
136
|
+
});
|
|
137
|
+
globalThis.fetch = fetchMock;
|
|
138
|
+
const createErrorSpy = vitest_1.vi
|
|
139
|
+
.spyOn(errorsModule, "createErrorFromResponse")
|
|
140
|
+
.mockReturnValue(
|
|
141
|
+
new errorsModule.EvalAIError(
|
|
142
|
+
"rate limited",
|
|
143
|
+
"RATE_LIMIT_EXCEEDED",
|
|
144
|
+
429,
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
await (0, vitest_1.expect)(
|
|
148
|
+
client.request("/api/fail", { method: "GET" }),
|
|
149
|
+
).rejects.toHaveProperty("code", "RATE_LIMIT_EXCEEDED");
|
|
150
|
+
createErrorSpy.mockRestore();
|
|
151
|
+
});
|
|
152
|
+
(0, vitest_1.it)(
|
|
153
|
+
"retries on retryable SDK errors and eventually succeeds",
|
|
154
|
+
async () => {
|
|
155
|
+
const client = new client_1.AIEvalClient({
|
|
156
|
+
apiKey: "test",
|
|
157
|
+
baseUrl: "http://localhost",
|
|
158
|
+
timeout: 1000,
|
|
159
|
+
});
|
|
160
|
+
vitest_1.vi.spyOn(client, "calculateBackoff").mockReturnValue(0);
|
|
161
|
+
const failureResponse = {
|
|
162
|
+
ok: false,
|
|
163
|
+
status: 429,
|
|
164
|
+
json: async () => ({ error: { code: "RATE_LIMIT_EXCEEDED" } }),
|
|
165
|
+
};
|
|
166
|
+
const successResponse = {
|
|
167
|
+
ok: true,
|
|
168
|
+
status: 200,
|
|
169
|
+
json: async () => ({ ok: true }),
|
|
170
|
+
};
|
|
171
|
+
const createErrorSpy = vitest_1.vi
|
|
172
|
+
.spyOn(errorsModule, "createErrorFromResponse")
|
|
173
|
+
.mockReturnValue(
|
|
174
|
+
new errorsModule.EvalAIError(
|
|
175
|
+
"rate limited",
|
|
176
|
+
"RATE_LIMIT_EXCEEDED",
|
|
177
|
+
429,
|
|
178
|
+
),
|
|
179
|
+
);
|
|
180
|
+
const fetchMock = vitest_1.vi
|
|
181
|
+
.fn()
|
|
182
|
+
.mockResolvedValueOnce(failureResponse)
|
|
183
|
+
.mockResolvedValueOnce(successResponse);
|
|
184
|
+
globalThis.fetch = fetchMock;
|
|
185
|
+
const result = await client.request("/api/retry", { method: "GET" });
|
|
186
|
+
(0, vitest_1.expect)(result).toEqual({ ok: true });
|
|
187
|
+
(0, vitest_1.expect)(fetchMock).toHaveBeenCalledTimes(2);
|
|
188
|
+
createErrorSpy.mockRestore();
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
(0, vitest_1.it)("throws a TIMEOUT SDK error when fetch aborts", async () => {
|
|
192
|
+
const client = new client_1.AIEvalClient({
|
|
193
|
+
apiKey: "test",
|
|
194
|
+
baseUrl: "http://localhost",
|
|
195
|
+
timeout: 1000,
|
|
196
|
+
});
|
|
197
|
+
const abortError = Object.assign(new Error("aborted"), {
|
|
198
|
+
name: "AbortError",
|
|
199
|
+
});
|
|
200
|
+
const fetchMock = vitest_1.vi.fn().mockRejectedValue(abortError);
|
|
201
|
+
globalThis.fetch = fetchMock;
|
|
202
|
+
await (0, vitest_1.expect)(
|
|
203
|
+
client.request("/api/timeout", { method: "GET" }),
|
|
204
|
+
).rejects.toMatchObject({
|
|
205
|
+
code: "TIMEOUT",
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
(0, vitest_1.it)(
|
|
209
|
+
"invalidates related cache entries for mutation requests",
|
|
210
|
+
async () => {
|
|
211
|
+
const client = new client_1.AIEvalClient({
|
|
212
|
+
apiKey: "test",
|
|
213
|
+
baseUrl: "http://localhost",
|
|
214
|
+
timeout: 1000,
|
|
215
|
+
});
|
|
216
|
+
cache_1.shouldCache.mockReturnValue(false);
|
|
217
|
+
const fetchMock = vitest_1.vi.fn().mockResolvedValue({
|
|
218
|
+
ok: true,
|
|
219
|
+
status: 201,
|
|
220
|
+
json: async () => ({ result: "ok" }),
|
|
221
|
+
});
|
|
222
|
+
globalThis.fetch = fetchMock;
|
|
223
|
+
await client.request("/api/evaluations", {
|
|
224
|
+
method: "POST",
|
|
225
|
+
body: JSON.stringify({}),
|
|
226
|
+
});
|
|
227
|
+
(0, vitest_1.expect)(cache_1.cacheTracker.invalidatedPatterns).toContain(
|
|
228
|
+
"evaluations",
|
|
229
|
+
);
|
|
230
|
+
},
|
|
231
|
+
);
|
|
232
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Propagation System
|
|
3
|
+
* Tier 2.9: Automatic metadata injection
|
|
4
|
+
*
|
|
5
|
+
* NOTE: In Node.js, uses AsyncLocalStorage for true async context propagation.
|
|
6
|
+
* In browsers, uses a simpler stack-based approach (not safe across async boundaries).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { createContext } from '@ai-eval-platform/sdk';
|
|
11
|
+
*
|
|
12
|
+
* const context = createContext({ userId: '123', sessionId: 'abc' });
|
|
13
|
+
*
|
|
14
|
+
* await context.run(async () => {
|
|
15
|
+
* // All SDK calls inherit the context
|
|
16
|
+
* await client.traces.create({ name: 'test' });
|
|
17
|
+
* // ^ Automatically includes userId and sessionId
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Context metadata that will be automatically injected
|
|
23
|
+
*/
|
|
24
|
+
export interface ContextMetadata {
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Context manager for automatic metadata propagation
|
|
29
|
+
*/
|
|
30
|
+
export declare class EvalContext {
|
|
31
|
+
private metadata;
|
|
32
|
+
constructor(metadata: ContextMetadata);
|
|
33
|
+
/**
|
|
34
|
+
* Run a function with this context
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const context = new EvalContext({ userId: '123' });
|
|
39
|
+
*
|
|
40
|
+
* await context.run(async () => {
|
|
41
|
+
* // All operations inherit context
|
|
42
|
+
* await client.traces.create({ name: 'test' });
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
run<T>(fn: () => Promise<T>): Promise<T>;
|
|
47
|
+
/**
|
|
48
|
+
* Run a synchronous function with this context
|
|
49
|
+
*/
|
|
50
|
+
runSync<T>(fn: () => T): T;
|
|
51
|
+
/**
|
|
52
|
+
* Get the current context metadata
|
|
53
|
+
*/
|
|
54
|
+
getMetadata(): ContextMetadata;
|
|
55
|
+
/**
|
|
56
|
+
* Merge additional metadata into context
|
|
57
|
+
*/
|
|
58
|
+
with(additionalMetadata: ContextMetadata): EvalContext;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create a new context with metadata
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const context = createContext({
|
|
66
|
+
* userId: '123',
|
|
67
|
+
* sessionId: 'abc',
|
|
68
|
+
* environment: 'production'
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* await context.run(async () => {
|
|
72
|
+
* // All SDK operations inherit context
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function createContext(metadata: ContextMetadata): EvalContext;
|
|
77
|
+
/**
|
|
78
|
+
* Get the current context metadata (if unknown)
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const metadata = getCurrentContext();
|
|
83
|
+
* if (metadata) {
|
|
84
|
+
* console.log(metadata.userId);
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export declare function getCurrentContext(): ContextMetadata | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* Merge current context with additional metadata
|
|
91
|
+
* Returns combined metadata for use in API calls
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const params = {
|
|
96
|
+
* name: 'My Trace',
|
|
97
|
+
* metadata: mergeWithContext({ custom: 'value' })
|
|
98
|
+
* };
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function mergeWithContext(metadata?: Record<string, unknown>): Record<string, unknown>;
|
|
102
|
+
/**
|
|
103
|
+
* Run with nested context (merges parent context)
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* await withContext({ userId: '123' }, async () => {
|
|
108
|
+
* await withContext({ requestId: 'req-456' }, async () => {
|
|
109
|
+
* // Has both userId and requestId
|
|
110
|
+
* const ctx = getCurrentContext();
|
|
111
|
+
* console.log(ctx); // { userId: '123', requestId: 'req-456' }
|
|
112
|
+
* });
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function withContext<T>(metadata: ContextMetadata, fn: () => Promise<T>): Promise<T>;
|
|
117
|
+
/**
|
|
118
|
+
* Run with nested context (synchronous)
|
|
119
|
+
*/
|
|
120
|
+
export declare function withContextSync<T>(metadata: ContextMetadata, fn: () => T): T;
|
|
121
|
+
/**
|
|
122
|
+
* Decorator for automatic context injection (for class methods)
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* class MyService {
|
|
127
|
+
* @WithContext({ service: 'MyService' })
|
|
128
|
+
* async process() {
|
|
129
|
+
* // Automatically has service context
|
|
130
|
+
* }
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export declare function WithContext(metadata: ContextMetadata): (_target: unknown, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Context Propagation System
|
|
4
|
+
* Tier 2.9: Automatic metadata injection
|
|
5
|
+
*
|
|
6
|
+
* NOTE: In Node.js, uses AsyncLocalStorage for true async context propagation.
|
|
7
|
+
* In browsers, uses a simpler stack-based approach (not safe across async boundaries).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { createContext } from '@ai-eval-platform/sdk';
|
|
12
|
+
*
|
|
13
|
+
* const context = createContext({ userId: '123', sessionId: 'abc' });
|
|
14
|
+
*
|
|
15
|
+
* await context.run(async () => {
|
|
16
|
+
* // All SDK calls inherit the context
|
|
17
|
+
* await client.traces.create({ name: 'test' });
|
|
18
|
+
* // ^ Automatically includes userId and sessionId
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.EvalContext = void 0;
|
|
24
|
+
exports.createContext = createContext;
|
|
25
|
+
exports.getCurrentContext = getCurrentContext;
|
|
26
|
+
exports.mergeWithContext = mergeWithContext;
|
|
27
|
+
exports.withContext = withContext;
|
|
28
|
+
exports.withContextSync = withContextSync;
|
|
29
|
+
exports.WithContext = WithContext;
|
|
30
|
+
// Detect environment
|
|
31
|
+
const isNode = typeof process !== "undefined" &&
|
|
32
|
+
process.versions?.node &&
|
|
33
|
+
typeof require !== "undefined";
|
|
34
|
+
// Browser fallback: simple context stack
|
|
35
|
+
class BrowserContextStorage {
|
|
36
|
+
constructor() {
|
|
37
|
+
this.stack = [];
|
|
38
|
+
}
|
|
39
|
+
run(context, fn) {
|
|
40
|
+
this.stack.push(context);
|
|
41
|
+
try {
|
|
42
|
+
return fn();
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
this.stack.pop();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
getStore() {
|
|
49
|
+
return this.stack[this.stack.length - 1];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Context storage implementation
|
|
54
|
+
* Uses AsyncLocalStorage in Node.js, simple stack in browsers
|
|
55
|
+
*/
|
|
56
|
+
let contextStorage;
|
|
57
|
+
if (isNode) {
|
|
58
|
+
try {
|
|
59
|
+
// Dynamic import for Node.js only
|
|
60
|
+
const { AsyncLocalStorage } = require("node:async_hooks");
|
|
61
|
+
// Create without type argument due to require() being untyped
|
|
62
|
+
contextStorage = new AsyncLocalStorage();
|
|
63
|
+
}
|
|
64
|
+
catch (_error) {
|
|
65
|
+
// Fallback if async_hooks is not available
|
|
66
|
+
contextStorage = new BrowserContextStorage();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Use browser storage for non-Node environments
|
|
71
|
+
contextStorage = new BrowserContextStorage();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Context manager for automatic metadata propagation
|
|
75
|
+
*/
|
|
76
|
+
class EvalContext {
|
|
77
|
+
constructor(metadata) {
|
|
78
|
+
this.metadata = metadata;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Run a function with this context
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const context = new EvalContext({ userId: '123' });
|
|
86
|
+
*
|
|
87
|
+
* await context.run(async () => {
|
|
88
|
+
* // All operations inherit context
|
|
89
|
+
* await client.traces.create({ name: 'test' });
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
async run(fn) {
|
|
94
|
+
return contextStorage.run(this.metadata, fn);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Run a synchronous function with this context
|
|
98
|
+
*/
|
|
99
|
+
runSync(fn) {
|
|
100
|
+
return contextStorage.run(this.metadata, fn);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get the current context metadata
|
|
104
|
+
*/
|
|
105
|
+
getMetadata() {
|
|
106
|
+
return { ...this.metadata };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Merge additional metadata into context
|
|
110
|
+
*/
|
|
111
|
+
with(additionalMetadata) {
|
|
112
|
+
return new EvalContext({ ...this.metadata, ...additionalMetadata });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.EvalContext = EvalContext;
|
|
116
|
+
/**
|
|
117
|
+
* Create a new context with metadata
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const context = createContext({
|
|
122
|
+
* userId: '123',
|
|
123
|
+
* sessionId: 'abc',
|
|
124
|
+
* environment: 'production'
|
|
125
|
+
* });
|
|
126
|
+
*
|
|
127
|
+
* await context.run(async () => {
|
|
128
|
+
* // All SDK operations inherit context
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
function createContext(metadata) {
|
|
133
|
+
return new EvalContext(metadata);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get the current context metadata (if unknown)
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const metadata = getCurrentContext();
|
|
141
|
+
* if (metadata) {
|
|
142
|
+
* console.log(metadata.userId);
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
function getCurrentContext() {
|
|
147
|
+
return contextStorage.getStore();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Merge current context with additional metadata
|
|
151
|
+
* Returns combined metadata for use in API calls
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const params = {
|
|
156
|
+
* name: 'My Trace',
|
|
157
|
+
* metadata: mergeWithContext({ custom: 'value' })
|
|
158
|
+
* };
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
function mergeWithContext(metadata) {
|
|
162
|
+
const current = getCurrentContext();
|
|
163
|
+
if (!current)
|
|
164
|
+
return metadata || {};
|
|
165
|
+
return { ...current, ...metadata };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Run with nested context (merges parent context)
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* await withContext({ userId: '123' }, async () => {
|
|
173
|
+
* await withContext({ requestId: 'req-456' }, async () => {
|
|
174
|
+
* // Has both userId and requestId
|
|
175
|
+
* const ctx = getCurrentContext();
|
|
176
|
+
* console.log(ctx); // { userId: '123', requestId: 'req-456' }
|
|
177
|
+
* });
|
|
178
|
+
* });
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
async function withContext(metadata, fn) {
|
|
182
|
+
const current = getCurrentContext() || {};
|
|
183
|
+
const merged = { ...current, ...metadata };
|
|
184
|
+
return contextStorage.run(merged, fn);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Run with nested context (synchronous)
|
|
188
|
+
*/
|
|
189
|
+
function withContextSync(metadata, fn) {
|
|
190
|
+
const current = getCurrentContext() || {};
|
|
191
|
+
const merged = { ...current, ...metadata };
|
|
192
|
+
return contextStorage.run(merged, fn);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Decorator for automatic context injection (for class methods)
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* class MyService {
|
|
200
|
+
* @WithContext({ service: 'MyService' })
|
|
201
|
+
* async process() {
|
|
202
|
+
* // Automatically has service context
|
|
203
|
+
* }
|
|
204
|
+
* }
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
function WithContext(metadata) {
|
|
208
|
+
return (_target, _propertyKey, descriptor) => {
|
|
209
|
+
const originalMethod = descriptor.value;
|
|
210
|
+
descriptor.value = async function (...args) {
|
|
211
|
+
return withContext(metadata, () => originalMethod.apply(this, args));
|
|
212
|
+
};
|
|
213
|
+
return descriptor;
|
|
214
|
+
};
|
|
215
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced SDK Error system with documentation links
|
|
3
|
+
* Tier 1.5: Rich Error Messages
|
|
4
|
+
*/
|
|
5
|
+
export interface ErrorDocumentation {
|
|
6
|
+
code: string;
|
|
7
|
+
message: string;
|
|
8
|
+
documentation: string;
|
|
9
|
+
solutions: string[];
|
|
10
|
+
retryable: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Enhanced SDK Error class with rich error information and documentation
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* try {
|
|
18
|
+
* await client.traces.create({ ... });
|
|
19
|
+
* } catch (error) {
|
|
20
|
+
* if (error instanceof EvalGateError) {
|
|
21
|
+
* console.log(error.code); // 'RATE_LIMIT_EXCEEDED'
|
|
22
|
+
* console.log(error.documentation); // Link to docs
|
|
23
|
+
* console.log(error.solutions); // Array of solutions
|
|
24
|
+
* console.log(error.retryable); // true/false
|
|
25
|
+
*
|
|
26
|
+
* if (error.retryAfter) {
|
|
27
|
+
* console.log(`Retry after ${error.retryAfter} seconds`);
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class EvalGateError extends Error {
|
|
34
|
+
/** Error code for programmatic handling */
|
|
35
|
+
code: string;
|
|
36
|
+
/** HTTP status code */
|
|
37
|
+
statusCode: number;
|
|
38
|
+
/** Link to detailed documentation */
|
|
39
|
+
documentation: string;
|
|
40
|
+
/** Array of suggested solutions */
|
|
41
|
+
solutions: string[];
|
|
42
|
+
/** Whether this error is retryable */
|
|
43
|
+
retryable: boolean;
|
|
44
|
+
/** Additional error details from the API */
|
|
45
|
+
details?: unknown;
|
|
46
|
+
/** When to retry (for rate limit errors) in seconds */
|
|
47
|
+
retryAfter?: number;
|
|
48
|
+
/** When the limit resets (for feature limit errors) */
|
|
49
|
+
resetAt?: Date;
|
|
50
|
+
/** Request ID from API (for correlation/debugging) */
|
|
51
|
+
requestId?: string;
|
|
52
|
+
constructor(message: string, code: string, statusCode: number, details?: unknown);
|
|
53
|
+
/**
|
|
54
|
+
* Get formatted error message with solutions
|
|
55
|
+
*/
|
|
56
|
+
getDetailedMessage(): string;
|
|
57
|
+
/**
|
|
58
|
+
* Check if this error should be retried
|
|
59
|
+
*/
|
|
60
|
+
shouldRetry(): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Convert to JSON for logging
|
|
63
|
+
*/
|
|
64
|
+
toJSON(): Record<string, unknown>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create an error from an HTTP response
|
|
68
|
+
*/
|
|
69
|
+
export declare function createErrorFromResponse(response: Response, data: unknown): EvalGateError;
|
|
70
|
+
export declare class RateLimitError extends EvalGateError {
|
|
71
|
+
constructor(message: string, retryAfter?: number);
|
|
72
|
+
}
|
|
73
|
+
export declare class AuthenticationError extends EvalGateError {
|
|
74
|
+
constructor(message?: string);
|
|
75
|
+
}
|
|
76
|
+
export declare class ValidationError extends EvalGateError {
|
|
77
|
+
constructor(message?: string, details?: unknown);
|
|
78
|
+
}
|
|
79
|
+
export declare class NetworkError extends EvalGateError {
|
|
80
|
+
constructor(message?: string);
|
|
81
|
+
}
|
|
82
|
+
export { EvalGateError as SDKError };
|