@botpress/evals 1.19.0-beta.9 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/client.d.ts +21 -9
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +103 -36
  4. package/dist/client.js.map +4 -4
  5. package/dist/definition.d.ts +9 -2
  6. package/dist/definition.d.ts.map +1 -1
  7. package/dist/definition.js.map +2 -2
  8. package/dist/graders/index.js +21 -74
  9. package/dist/graders/index.js.map +2 -2
  10. package/dist/graders/llm.d.ts +12 -12
  11. package/dist/graders/llm.d.ts.map +1 -1
  12. package/dist/graders/llm.js +30 -75
  13. package/dist/graders/llm.js.map +2 -2
  14. package/dist/graders/response.js +16 -65
  15. package/dist/graders/response.js.map +2 -2
  16. package/dist/index.d.ts +3 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +10 -0
  19. package/dist/index.js.map +3 -3
  20. package/dist/loader.js.map +2 -2
  21. package/dist/manifest.d.ts +13 -0
  22. package/dist/manifest.d.ts.map +1 -0
  23. package/dist/runner.d.ts +5 -1
  24. package/dist/runner.d.ts.map +1 -1
  25. package/dist/runner.js +316 -183
  26. package/dist/runner.js.map +4 -4
  27. package/dist/spans/index.d.ts +5 -0
  28. package/dist/spans/index.d.ts.map +1 -0
  29. package/dist/spans/index.js +725 -0
  30. package/dist/spans/index.js.map +7 -0
  31. package/dist/spans/local-span-source.d.ts +19 -0
  32. package/dist/spans/local-span-source.d.ts.map +1 -0
  33. package/dist/spans/local-span-source.js +543 -0
  34. package/dist/spans/local-span-source.js.map +7 -0
  35. package/dist/spans/span-source.d.ts +40 -0
  36. package/dist/spans/span-source.d.ts.map +1 -0
  37. package/dist/spans/span-source.js +1 -0
  38. package/dist/{sse-collector.d.ts → spans/sse-collector.d.ts} +44 -5
  39. package/dist/spans/sse-collector.d.ts.map +1 -0
  40. package/dist/{sse-collector.js → spans/sse-collector.js} +97 -20
  41. package/dist/spans/sse-collector.js.map +7 -0
  42. package/dist/spans/trace.d.ts.map +1 -0
  43. package/dist/spans/trace.js.map +7 -0
  44. package/dist/spans/vortex-span-source.d.ts +42 -0
  45. package/dist/spans/vortex-span-source.d.ts.map +1 -0
  46. package/dist/spans/vortex-span-source.js +184 -0
  47. package/dist/spans/vortex-span-source.js.map +7 -0
  48. package/dist/stores/eval-definition-loader.d.ts +4 -0
  49. package/dist/stores/eval-definition-loader.d.ts.map +1 -0
  50. package/dist/stores/eval-definition-loader.js +142 -0
  51. package/dist/stores/eval-definition-loader.js.map +7 -0
  52. package/dist/stores/eval-store.d.ts +61 -0
  53. package/dist/stores/eval-store.d.ts.map +1 -0
  54. package/dist/stores/eval-store.js +1 -0
  55. package/dist/stores/eval-store.js.map +7 -0
  56. package/dist/stores/index.d.ts +8 -0
  57. package/dist/stores/index.d.ts.map +1 -0
  58. package/dist/stores/index.js +1156 -0
  59. package/dist/stores/index.js.map +7 -0
  60. package/dist/stores/local-eval-store.d.ts +66 -0
  61. package/dist/stores/local-eval-store.d.ts.map +1 -0
  62. package/dist/stores/local-eval-store.js +595 -0
  63. package/dist/stores/local-eval-store.js.map +7 -0
  64. package/dist/stores/vortex-eval-store-entry.d.ts +6 -0
  65. package/dist/stores/vortex-eval-store-entry.d.ts.map +1 -0
  66. package/dist/stores/vortex-eval-store-entry.js +702 -0
  67. package/dist/stores/vortex-eval-store-entry.js.map +7 -0
  68. package/dist/stores/vortex-eval-store.d.ts +78 -0
  69. package/dist/stores/vortex-eval-store.d.ts.map +1 -0
  70. package/dist/stores/vortex-eval-store.js +562 -0
  71. package/dist/stores/vortex-eval-store.js.map +7 -0
  72. package/dist/transformer.d.ts +2 -2
  73. package/dist/transformer.d.ts.map +1 -1
  74. package/dist/transformer.js +1 -1
  75. package/dist/transformer.js.map +2 -2
  76. package/dist/types.d.ts +38 -33
  77. package/dist/types.d.ts.map +1 -1
  78. package/dist/types.js.map +2 -2
  79. package/package.json +66 -6
  80. package/dist/sse-collector.d.ts.map +0 -1
  81. package/dist/sse-collector.js.map +0 -7
  82. package/dist/trace.d.ts.map +0 -1
  83. /package/dist/{trace.js.map → spans/span-source.js.map} +0 -0
  84. /package/dist/{trace.d.ts → spans/trace.d.ts} +0 -0
  85. /package/dist/{trace.js → spans/trace.js} +0 -0
@@ -0,0 +1,184 @@
1
+ // src/spans/vortex-span-source.ts
2
+ function spanKey(span) {
3
+ return `${span.id.trace}:${span.id.span}`;
4
+ }
5
+ function spanData(span) {
6
+ return span.data && typeof span.data === "object" ? span.data : {};
7
+ }
8
+ function normalizeSpan(span) {
9
+ if (span.status !== "running") return span;
10
+ const data = spanData(span);
11
+ const autonomousStatus = data["autonomous.status"];
12
+ if (autonomousStatus === "generation_error" || autonomousStatus === "execution_error" || autonomousStatus === "invalid_code_error" || autonomousStatus === "exit_error" || autonomousStatus === "aborted") {
13
+ return { ...span, status: "error" };
14
+ }
15
+ if (autonomousStatus === "thinking_requested" || autonomousStatus === "callback_requested" || autonomousStatus === "exit_success") {
16
+ return { ...span, status: "ok" };
17
+ }
18
+ const { startedAt, endedAt } = span.timing;
19
+ if (typeof endedAt === "number" && Number.isFinite(endedAt) && endedAt > startedAt) {
20
+ return { ...span, status: "ok" };
21
+ }
22
+ return span;
23
+ }
24
+ function sleep(ms, signal) {
25
+ return new Promise((resolve, reject) => {
26
+ if (signal?.aborted) return reject(new Error("aborted"));
27
+ const onAbort = () => {
28
+ clearTimeout(timer);
29
+ reject(new Error("aborted"));
30
+ };
31
+ const timer = setTimeout(() => {
32
+ signal?.removeEventListener("abort", onAbort);
33
+ resolve();
34
+ }, ms);
35
+ signal?.addEventListener("abort", onAbort, { once: true });
36
+ });
37
+ }
38
+ var VortexSpanSource = class _VortexSpanSource {
39
+ config;
40
+ conversationId = "";
41
+ traceIds = /* @__PURE__ */ new Set();
42
+ spanMap = /* @__PURE__ */ new Map();
43
+ turnStartKeys = /* @__PURE__ */ new Set();
44
+ seenHandlerKeys = /* @__PURE__ */ new Set();
45
+ consecutiveFailures = 0;
46
+ constructor(config) {
47
+ this.config = {
48
+ url: config.url.replace(/\/$/, ""),
49
+ botId: config.botId,
50
+ pollIntervalMs: config.pollIntervalMs ?? 500,
51
+ ...config.workspaceId ? { workspaceId: config.workspaceId } : {},
52
+ ...config.token ? { token: config.token } : {}
53
+ };
54
+ }
55
+ async connect(filter) {
56
+ this.conversationId = filter.conversationId;
57
+ await this._pollOnce();
58
+ }
59
+ /**
60
+ * Switch polling to a new conversation, keeping `spanMap` and
61
+ * `seenHandlerKeys`. `traceIds` resets — they belonged to the prior conversation.
62
+ */
63
+ async repoint(filter) {
64
+ this.conversationId = filter.conversationId;
65
+ this.traceIds = /* @__PURE__ */ new Set();
66
+ await this._pollOnce();
67
+ }
68
+ static TURN_HANDLER_SPAN_NAMES = /* @__PURE__ */ new Set(["handler.conversation", "handler.event"]);
69
+ startTurn() {
70
+ this.turnStartKeys = new Set(this.spanMap.keys());
71
+ for (const [key, span] of this.spanMap) {
72
+ if (_VortexSpanSource.TURN_HANDLER_SPAN_NAMES.has(span.name)) {
73
+ this.seenHandlerKeys.add(key);
74
+ }
75
+ }
76
+ }
77
+ static SETTLE_POLLS = 3;
78
+ async waitForTurnComplete(opts) {
79
+ const deadline = Date.now() + opts.timeout;
80
+ const maxPolls = opts.settleMaxMs ? Math.floor(opts.settleMaxMs / this.config.pollIntervalMs) : Infinity;
81
+ const settlePolls = Math.min(
82
+ maxPolls,
83
+ Math.max(
84
+ _VortexSpanSource.SETTLE_POLLS,
85
+ opts.settleQuietMs ? Math.ceil(opts.settleQuietMs / this.config.pollIntervalMs) : 0
86
+ )
87
+ );
88
+ while (Date.now() < deadline) {
89
+ if (opts.abortSignal?.aborted) throw new Error("waitForTurnComplete aborted");
90
+ await this._pollOnce();
91
+ if (this._hasNewCompletedHandler(opts.acceptSpanNames)) {
92
+ for (let i = 0; i < settlePolls; i++) {
93
+ await sleep(this.config.pollIntervalMs, opts.abortSignal).catch(() => {
94
+ });
95
+ await this._pollOnce();
96
+ }
97
+ return;
98
+ }
99
+ await sleep(this.config.pollIntervalMs, opts.abortSignal).catch(() => {
100
+ });
101
+ }
102
+ throw new Error(`waitForTurnComplete timed out after ${opts.timeout}ms`);
103
+ }
104
+ async waitForWorkflow(name, opts) {
105
+ const deadline = Date.now() + opts.timeout;
106
+ while (Date.now() < deadline) {
107
+ if (opts.abortSignal?.aborted) throw new Error(`waitForWorkflow("${name}") aborted`);
108
+ await this._pollOnce();
109
+ if (this._matchesWorkflowCondition(name, opts.signal)) return;
110
+ await sleep(this.config.pollIntervalMs, opts.abortSignal).catch(() => {
111
+ });
112
+ }
113
+ throw new Error(`waitForWorkflow("${name}", { signal: "${opts.signal}" }) timed out after ${opts.timeout}ms`);
114
+ }
115
+ getTurnSpans() {
116
+ const result = [];
117
+ for (const [key, span] of this.spanMap) {
118
+ if (!this.turnStartKeys.has(key)) {
119
+ result.push(span);
120
+ }
121
+ }
122
+ return result;
123
+ }
124
+ getAllSpans() {
125
+ return Array.from(this.spanMap.values());
126
+ }
127
+ disconnect() {
128
+ }
129
+ async _pollOnce() {
130
+ const url = new URL(`${this.config.url}/v1/traces/bot/${this.config.botId}/spans/adk`);
131
+ url.searchParams.set("conversationId", this.conversationId);
132
+ for (const traceId of this.traceIds) {
133
+ url.searchParams.append("traceId", traceId);
134
+ }
135
+ const res = await fetch(url, {
136
+ headers: {
137
+ Accept: "application/json",
138
+ ...this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {}
139
+ }
140
+ });
141
+ if (!res.ok) {
142
+ this.consecutiveFailures++;
143
+ const body = await res.text().catch(() => "");
144
+ const msg = `Vortex poll failed: ${res.status} ${body.slice(0, 200)}`;
145
+ if (this.consecutiveFailures >= 5) {
146
+ throw new Error(`${msg} (${this.consecutiveFailures} consecutive failures)`);
147
+ }
148
+ console.warn(`[VortexSpanSource] ${msg}`);
149
+ return;
150
+ }
151
+ this.consecutiveFailures = 0;
152
+ const payload = await res.json();
153
+ const spans = Array.isArray(payload) ? payload : Array.isArray(payload.spans) ? payload.spans : [];
154
+ for (const rawSpan of spans) {
155
+ const span = normalizeSpan(rawSpan);
156
+ this.spanMap.set(spanKey(span), span);
157
+ this.traceIds.add(span.id.trace);
158
+ }
159
+ }
160
+ _hasNewCompletedHandler(acceptSpanNames) {
161
+ for (const [key, span] of this.spanMap) {
162
+ if (_VortexSpanSource.TURN_HANDLER_SPAN_NAMES.has(span.name) && (!acceptSpanNames || acceptSpanNames.has(span.name)) && !this.seenHandlerKeys.has(key) && (span.status === "ok" || span.status === "error")) {
163
+ this.seenHandlerKeys.add(key);
164
+ return true;
165
+ }
166
+ }
167
+ return false;
168
+ }
169
+ _matchesWorkflowCondition(name, signal) {
170
+ for (const span of this.spanMap.values()) {
171
+ if (span.name !== "handler.workflow") continue;
172
+ const d = spanData(span);
173
+ const wfName = d["workflow.name"] || d["workflowName"];
174
+ if (wfName !== name) continue;
175
+ if (signal === "entered") return true;
176
+ if (signal === "completed") return span.status === "ok" || span.status === "error";
177
+ }
178
+ return false;
179
+ }
180
+ };
181
+ export {
182
+ VortexSpanSource
183
+ };
184
+ //# sourceMappingURL=vortex-span-source.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/spans/vortex-span-source.ts"],
4
+ "sourcesContent": ["import type { SpanSource, TurnWaitOptions, WaitOptions, WorkflowWaitOptions } from './span-source'\nimport type { Span } from './trace'\n\ninterface VortexSpanSourceConfig {\n url: string\n botId: string\n workspaceId?: string\n token?: string\n pollIntervalMs?: number\n}\n\ntype VortexTraceResponse = Span[] | { spans?: Span[] }\n\nfunction spanKey(span: Span): string {\n return `${span.id.trace}:${span.id.span}`\n}\n\nfunction spanData(span: Span): Record<string, unknown> {\n return span.data && typeof span.data === 'object' ? (span.data as Record<string, unknown>) : {}\n}\n\nfunction normalizeSpan(span: Span): Span {\n if (span.status !== 'running') return span\n const data = spanData(span)\n const autonomousStatus = data['autonomous.status']\n\n if (\n autonomousStatus === 'generation_error' ||\n autonomousStatus === 'execution_error' ||\n autonomousStatus === 'invalid_code_error' ||\n autonomousStatus === 'exit_error' ||\n autonomousStatus === 'aborted'\n ) {\n return { ...span, status: 'error' }\n }\n\n if (\n autonomousStatus === 'thinking_requested' ||\n autonomousStatus === 'callback_requested' ||\n autonomousStatus === 'exit_success'\n ) {\n return { ...span, status: 'ok' }\n }\n\n const { startedAt, endedAt } = span.timing\n if (typeof endedAt === 'number' && Number.isFinite(endedAt) && endedAt > startedAt) {\n return { ...span, status: 'ok' }\n }\n\n return span\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(new Error('aborted'))\n const onAbort = () => {\n clearTimeout(timer)\n reject(new Error('aborted'))\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nexport class VortexSpanSource implements SpanSource {\n private config: Required<Omit<VortexSpanSourceConfig, 'workspaceId' | 'token'>> &\n Pick<VortexSpanSourceConfig, 'workspaceId' | 'token'>\n private conversationId = ''\n private traceIds = new Set<string>()\n private spanMap = new Map<string, Span>()\n private turnStartKeys = new Set<string>()\n private seenHandlerKeys = new Set<string>()\n private consecutiveFailures = 0\n\n constructor(config: VortexSpanSourceConfig) {\n this.config = {\n url: config.url.replace(/\\/$/, ''),\n botId: config.botId,\n pollIntervalMs: config.pollIntervalMs ?? 500,\n ...(config.workspaceId ? { workspaceId: config.workspaceId } : {}),\n ...(config.token ? { token: config.token } : {}),\n }\n }\n\n async connect(filter: { conversationId: string }): Promise<void> {\n this.conversationId = filter.conversationId\n await this._pollOnce()\n }\n\n /**\n * Switch polling to a new conversation, keeping `spanMap` and\n * `seenHandlerKeys`. `traceIds` resets \u2014 they belonged to the prior conversation.\n */\n async repoint(filter: { conversationId: string }): Promise<void> {\n this.conversationId = filter.conversationId\n this.traceIds = new Set()\n await this._pollOnce()\n }\n\n private static readonly TURN_HANDLER_SPAN_NAMES = new Set(['handler.conversation', 'handler.event'])\n\n startTurn(): void {\n this.turnStartKeys = new Set(this.spanMap.keys())\n for (const [key, span] of this.spanMap) {\n if (VortexSpanSource.TURN_HANDLER_SPAN_NAMES.has(span.name)) {\n this.seenHandlerKeys.add(key)\n }\n }\n }\n\n private static readonly SETTLE_POLLS = 3\n\n async waitForTurnComplete(opts: TurnWaitOptions): Promise<void> {\n const deadline = Date.now() + opts.timeout\n // Honor the requested quiet window by polling at least that long after the\n // handler closes (async follow-through such as a workflow run + callback\n // only executes after the handler closes).\n const maxPolls = opts.settleMaxMs ? Math.floor(opts.settleMaxMs / this.config.pollIntervalMs) : Infinity\n const settlePolls = Math.min(\n maxPolls,\n Math.max(\n VortexSpanSource.SETTLE_POLLS,\n opts.settleQuietMs ? Math.ceil(opts.settleQuietMs / this.config.pollIntervalMs) : 0\n )\n )\n\n while (Date.now() < deadline) {\n if (opts.abortSignal?.aborted) throw new Error('waitForTurnComplete aborted')\n\n await this._pollOnce()\n\n if (this._hasNewCompletedHandler(opts.acceptSpanNames)) {\n for (let i = 0; i < settlePolls; i++) {\n await sleep(this.config.pollIntervalMs, opts.abortSignal).catch(() => {})\n await this._pollOnce()\n }\n return\n }\n\n await sleep(this.config.pollIntervalMs, opts.abortSignal).catch(() => {})\n }\n\n throw new Error(`waitForTurnComplete timed out after ${opts.timeout}ms`)\n }\n\n async waitForWorkflow(name: string, opts: WorkflowWaitOptions): Promise<void> {\n const deadline = Date.now() + opts.timeout\n\n while (Date.now() < deadline) {\n if (opts.abortSignal?.aborted) throw new Error(`waitForWorkflow(\"${name}\") aborted`)\n\n await this._pollOnce()\n\n if (this._matchesWorkflowCondition(name, opts.signal)) return\n\n await sleep(this.config.pollIntervalMs, opts.abortSignal).catch(() => {})\n }\n\n throw new Error(`waitForWorkflow(\"${name}\", { signal: \"${opts.signal}\" }) timed out after ${opts.timeout}ms`)\n }\n\n getTurnSpans(): Span[] {\n const result: Span[] = []\n for (const [key, span] of this.spanMap) {\n if (!this.turnStartKeys.has(key)) {\n result.push(span)\n }\n }\n return result\n }\n\n getAllSpans(): Span[] {\n return Array.from(this.spanMap.values())\n }\n\n disconnect(): void {\n // Stateless polling client.\n }\n\n private async _pollOnce(): Promise<void> {\n const url = new URL(`${this.config.url}/v1/traces/bot/${this.config.botId}/spans/adk`)\n url.searchParams.set('conversationId', this.conversationId)\n for (const traceId of this.traceIds) {\n url.searchParams.append('traceId', traceId)\n }\n\n const res = await fetch(url, {\n headers: {\n Accept: 'application/json',\n ...(this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {}),\n },\n })\n\n if (!res.ok) {\n this.consecutiveFailures++\n const body = await res.text().catch(() => '')\n const msg = `Vortex poll failed: ${res.status} ${body.slice(0, 200)}`\n if (this.consecutiveFailures >= 5) {\n throw new Error(`${msg} (${this.consecutiveFailures} consecutive failures)`)\n }\n console.warn(`[VortexSpanSource] ${msg}`)\n return\n }\n\n this.consecutiveFailures = 0\n const payload = (await res.json()) as VortexTraceResponse\n const spans = Array.isArray(payload) ? payload : Array.isArray(payload.spans) ? payload.spans : []\n\n for (const rawSpan of spans) {\n const span = normalizeSpan(rawSpan)\n this.spanMap.set(spanKey(span), span)\n this.traceIds.add(span.id.trace)\n }\n }\n\n private _hasNewCompletedHandler(acceptSpanNames?: ReadonlySet<string>): boolean {\n for (const [key, span] of this.spanMap) {\n if (\n VortexSpanSource.TURN_HANDLER_SPAN_NAMES.has(span.name) &&\n (!acceptSpanNames || acceptSpanNames.has(span.name)) &&\n !this.seenHandlerKeys.has(key) &&\n (span.status === 'ok' || span.status === 'error')\n ) {\n this.seenHandlerKeys.add(key)\n return true\n }\n }\n return false\n }\n\n private _matchesWorkflowCondition(name: string, signal: 'entered' | 'completed'): boolean {\n for (const span of this.spanMap.values()) {\n if (span.name !== 'handler.workflow') continue\n const d = spanData(span)\n const wfName = d['workflow.name'] || d['workflowName']\n if (wfName !== name) continue\n if (signal === 'entered') return true\n if (signal === 'completed') return span.status === 'ok' || span.status === 'error'\n }\n return false\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,4 @@
1
+ import type { EvalDefinition } from '../definition';
2
+ export type EvalDefinitionLoader = () => Promise<EvalDefinition[]>;
3
+ export declare function createDiskEvalLoader(evalsDir: string): EvalDefinitionLoader;
4
+ //# sourceMappingURL=eval-definition-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval-definition-loader.d.ts","sourceRoot":"","sources":["../../src/stores/eval-definition-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAGnD,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;AAElE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CAE3E"}
@@ -0,0 +1,142 @@
1
+ // src/loader.ts
2
+ import { readdirSync, existsSync } from "fs";
3
+ import { resolve } from "path";
4
+
5
+ // src/definition.ts
6
+ var Eval = class {
7
+ name;
8
+ description;
9
+ tags;
10
+ type;
11
+ setup;
12
+ conversation;
13
+ outcome;
14
+ options;
15
+ constructor(def) {
16
+ this.name = def.name;
17
+ this.conversation = def.conversation;
18
+ if (def.description !== void 0) this.description = def.description;
19
+ if (def.tags !== void 0) this.tags = def.tags;
20
+ if (def.type !== void 0) this.type = def.type;
21
+ if (def.setup !== void 0) this.setup = def.setup;
22
+ if (def.outcome !== void 0) this.outcome = def.outcome;
23
+ if (def.options !== void 0) this.options = def.options;
24
+ }
25
+ };
26
+
27
+ // ../analytics/src/errors.ts
28
+ var AdkError = class extends Error {
29
+ /**
30
+ * Marker for cross-module-instance checks — `instanceof` breaks when a
31
+ * package is duplicated in the dependency graph.
32
+ * @internal
33
+ */
34
+ static __IS_ADK_BASE_ERROR = true;
35
+ /**
36
+ * Stable SCREAMING_SNAKE_CASE identifier, e.g. 'BOT_NOT_FOUND'. Subclasses
37
+ * pin `Code` to a literal union (`class EvalRunnerError extends
38
+ * AdkError<EvalErrorCode>`) so typos are compile errors and `code` narrows
39
+ * in switches.
40
+ */
41
+ code;
42
+ /**
43
+ * True for user/environment conditions the developer can fix themselves
44
+ * (validation, auth, connectivity). False for internal bugs. Defaults to
45
+ * false so unclassified errors surface as bugs until someone triages them.
46
+ */
47
+ expected;
48
+ /** Structured context. Sanitized before any telemetry leaves the machine. */
49
+ details;
50
+ /** Actionable next step shown to the user, e.g. "Run 'adk login' first." */
51
+ suggestion;
52
+ constructor(opts) {
53
+ super(opts.message, opts.cause !== void 0 ? { cause: opts.cause } : void 0);
54
+ this.name = this.constructor.name;
55
+ this.code = opts.code;
56
+ this.expected = opts.expected ?? false;
57
+ if (opts.details !== void 0) {
58
+ this.details = opts.details;
59
+ }
60
+ if (opts.suggestion !== void 0) {
61
+ this.suggestion = opts.suggestion;
62
+ }
63
+ }
64
+ };
65
+
66
+ // src/errors.ts
67
+ var EvalRunnerError = class extends AdkError {
68
+ };
69
+
70
+ // src/loader.ts
71
+ function isEvalDefinition(value) {
72
+ return value !== null && typeof value === "object" && typeof value.name === "string" && value.name !== "" && Array.isArray(value.conversation);
73
+ }
74
+ async function loadEvalFile(filePath) {
75
+ const absPath = resolve(filePath);
76
+ let mod;
77
+ try {
78
+ mod = await import(absPath);
79
+ } catch (err) {
80
+ const msg = err instanceof Error ? err.message : String(err);
81
+ throw new EvalRunnerError({
82
+ code: "EVAL_LOAD_FAILED",
83
+ message: `Failed to load eval file ${filePath}: ${msg}
84
+
85
+ Make sure your eval file:
86
+ - Has no syntax or type errors
87
+ - Exports one or more \`new Eval({...})\` instances
88
+ - Has all dependencies installed (\`bun install\`)`,
89
+ expected: true,
90
+ cause: err
91
+ });
92
+ }
93
+ const results = [];
94
+ for (const [key, value] of Object.entries(mod)) {
95
+ if (key === "__esModule") continue;
96
+ if (value instanceof Eval || isEvalDefinition(value)) {
97
+ results.push(value);
98
+ }
99
+ }
100
+ if (results.length === 0) {
101
+ throw new EvalRunnerError({
102
+ code: "EVAL_FILE_EMPTY",
103
+ message: `Invalid eval file ${filePath}: no valid evals found. Export one or more \`new Eval({...})\` instances (as default or named exports).`,
104
+ expected: true
105
+ });
106
+ }
107
+ return results;
108
+ }
109
+ async function loadEvalsFromDir(dirPath) {
110
+ const absDir = resolve(dirPath);
111
+ if (!existsSync(absDir)) {
112
+ return [];
113
+ }
114
+ const files = readdirSync(absDir).filter((f) => f.endsWith(".eval.ts"));
115
+ const evals = [];
116
+ for (const f of files) {
117
+ const defs = await loadEvalFile(`${absDir}/${f}`);
118
+ evals.push(...defs);
119
+ }
120
+ const seen = /* @__PURE__ */ new Set();
121
+ for (const e of evals) {
122
+ if (seen.has(e.name)) {
123
+ throw new EvalRunnerError({
124
+ code: "EVAL_DUPLICATE_NAME",
125
+ message: `Duplicate eval name "${e.name}" found in ${dirPath} \u2014 names must be unique across the evals directory.`,
126
+ expected: true,
127
+ details: { name: e.name }
128
+ });
129
+ }
130
+ seen.add(e.name);
131
+ }
132
+ return evals;
133
+ }
134
+
135
+ // src/stores/eval-definition-loader.ts
136
+ function createDiskEvalLoader(evalsDir) {
137
+ return () => loadEvalsFromDir(evalsDir);
138
+ }
139
+ export {
140
+ createDiskEvalLoader
141
+ };
142
+ //# sourceMappingURL=eval-definition-loader.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/loader.ts", "../../src/definition.ts", "../../../analytics/src/errors.ts", "../../src/errors.ts", "../../src/stores/eval-definition-loader.ts"],
4
+ "sourcesContent": ["/**\n * Eval file loader.\n * Loads *.eval.ts files from a directory using dynamic imports.\n * Supports both default and named exports, and multiple evals per file.\n */\n\nimport { readdirSync, existsSync } from 'fs'\nimport { resolve } from 'path'\nimport type { EvalDefinition, EvalFilter } from './types'\nimport { Eval } from './types'\nimport { EvalRunnerError } from './errors'\n\nfunction isEvalDefinition(value: unknown): value is EvalDefinition {\n return (\n value !== null &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>).name === 'string' &&\n (value as Record<string, unknown>).name !== '' &&\n Array.isArray((value as Record<string, unknown>).conversation)\n )\n}\n\nexport async function loadEvalFile(filePath: string): Promise<EvalDefinition[]> {\n const absPath = resolve(filePath)\n\n let mod: Record<string, unknown>\n try {\n mod = await import(absPath)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // Guidance stays in the message until the CLI renders `suggestion`\n // (cli-package remediation) \u2014 report.error/logger.fatal only show message.\n throw new EvalRunnerError({\n code: 'EVAL_LOAD_FAILED',\n message:\n `Failed to load eval file ${filePath}: ${msg}\\n\\n` +\n 'Make sure your eval file:\\n' +\n ' - Has no syntax or type errors\\n' +\n ' - Exports one or more `new Eval({...})` instances\\n' +\n ' - Has all dependencies installed (`bun install`)',\n expected: true,\n cause: err,\n })\n }\n\n const results: EvalDefinition[] = []\n\n for (const [key, value] of Object.entries(mod)) {\n if (key === '__esModule') continue\n if (value instanceof Eval || isEvalDefinition(value)) {\n results.push(value)\n }\n }\n\n if (results.length === 0) {\n throw new EvalRunnerError({\n code: 'EVAL_FILE_EMPTY',\n message: `Invalid eval file ${filePath}: no valid evals found. Export one or more \\`new Eval({...})\\` instances (as default or named exports).`,\n expected: true,\n })\n }\n\n return results\n}\n\nexport async function loadEvalsFromDir(dirPath: string): Promise<EvalDefinition[]> {\n const absDir = resolve(dirPath)\n if (!existsSync(absDir)) {\n return []\n }\n\n const files = readdirSync(absDir).filter((f) => f.endsWith('.eval.ts'))\n const evals: EvalDefinition[] = []\n\n for (const f of files) {\n const defs = await loadEvalFile(`${absDir}/${f}`)\n evals.push(...defs)\n }\n\n const seen = new Set<string>()\n for (const e of evals) {\n if (seen.has(e.name)) {\n throw new EvalRunnerError({\n code: 'EVAL_DUPLICATE_NAME',\n message: `Duplicate eval name \"${e.name}\" found in ${dirPath} \u2014 names must be unique across the evals directory.`,\n expected: true,\n details: { name: e.name },\n })\n }\n seen.add(e.name)\n }\n\n return evals\n}\n\nexport async function loadEvalByName(dirPath: string, name: string): Promise<EvalDefinition | null> {\n const absDir = resolve(dirPath)\n if (!existsSync(absDir)) return null\n\n const files = readdirSync(absDir).filter((f) => f.endsWith('.eval.ts'))\n\n for (const f of files) {\n const defs = await loadEvalFile(`${absDir}/${f}`)\n const found = defs.find((d) => d.name === name)\n if (found) return found\n }\n\n return null\n}\n\nexport function filterEvals(evals: EvalDefinition[], filter?: EvalFilter): EvalDefinition[] {\n if (!filter) return evals\n\n return evals.filter((e) => {\n if (filter.names && filter.names.length > 0) {\n if (!filter.names.includes(e.name)) return false\n }\n if (filter.tags && filter.tags.length > 0) {\n if (!e.tags || !filter.tags.some((t) => e.tags!.includes(t))) return false\n }\n if (filter.type) {\n if (e.type !== filter.type) return false\n }\n return true\n })\n}\n", "export type MatchOperator =\n | string\n | { equals: unknown }\n | { contains: string }\n | { not_contains: string }\n | { matches: string }\n | { in: unknown[] }\n | { exists: boolean }\n | { gte: number }\n | { lte: number }\n\nexport type ResponseAssertion =\n | { contains: string }\n | { not_contains: string }\n | { matches: string }\n | { llm_judge: string }\n// | { similar_to: string } TODO: uncomment this when it gets implemented\n\nexport type ToolAssertion =\n | { called: string; params?: Record<string, MatchOperator> }\n | { not_called: string }\n | { call_order: string[] }\n\nexport interface StateAssertion {\n path: string\n equals?: unknown\n changed?: boolean\n}\n\nexport interface WorkflowAssertion {\n name: string\n entered?: boolean\n completed?: boolean\n}\n\nexport type NumericOperator = { equals: number } | { gte: number } | { lte: number }\n\nexport interface TimingAssertion {\n response_time: NumericOperator\n}\n\nexport interface TurnAssertions {\n response?: ResponseAssertion[]\n tools?: ToolAssertion[]\n state?: StateAssertion[]\n workflow?: WorkflowAssertion[]\n timing?: TimingAssertion[]\n}\n\nexport interface ConversationTurn {\n user?: string\n event?: { payload: Record<string, unknown> }\n expectSilence?: boolean\n assert?: TurnAssertions\n /**\n * Run this turn in a NEW conversation under the same user. The prior\n * transcript is absent, so recall here can only come from user-scoped\n * persistence, not context. Ignored on the first turn.\n */\n newConversation?: boolean\n}\n\nexport interface OutcomeAssertions {\n state?: StateAssertion[]\n workflow?: WorkflowAssertion[]\n}\n\nexport interface EvalSetup {\n state?: {\n bot?: Record<string, unknown>\n user?: Record<string, unknown>\n conversation?: Record<string, unknown>\n }\n workflow?: {\n trigger: string\n input?: Record<string, unknown>\n }\n}\n\nexport interface EvalDefinition {\n name: string\n description?: string\n tags?: string[]\n type?: 'capability' | 'regression'\n setup?: EvalSetup\n conversation: ConversationTurn[]\n outcome?: OutcomeAssertions\n options?: {\n idleTimeout?: number\n /** @deprecated No-op: the LLM judge is boolean (zai.check); there is no score threshold. */\n judgePassThreshold?: number\n }\n}\n\nexport class Eval implements EvalDefinition {\n readonly name: string\n readonly description?: string\n readonly tags?: string[]\n readonly type?: 'capability' | 'regression'\n readonly setup?: EvalSetup\n readonly conversation: ConversationTurn[]\n readonly outcome?: OutcomeAssertions\n readonly options?: {\n idleTimeout?: number\n /** @deprecated No-op: the LLM judge is boolean (zai.check); there is no score threshold. */\n judgePassThreshold?: number\n }\n\n constructor(def: EvalDefinition) {\n this.name = def.name\n this.conversation = def.conversation\n if (def.description !== undefined) this.description = def.description\n if (def.tags !== undefined) this.tags = def.tags\n if (def.type !== undefined) this.type = def.type\n if (def.setup !== undefined) this.setup = def.setup\n if (def.outcome !== undefined) this.outcome = def.outcome\n if (def.options !== undefined) this.options = def.options\n }\n}\n", "/**\n * Shared base error for ADK packages. Lives in `@botpress/analytics` because\n * it's the dependency-light package every surface already shares (cli, adk,\n * ui) \u2014 so all typed errors can genuinely inherit one base instead of\n * mirroring its shape.\n *\n * The policy lives in docs/ERROR-HANDLING.md. The short version: every error\n * we *intend* to throw should carry a stable `code` (so PostHog error\n * tracking can slice issues by code) and an `expected` flag separating\n * user/environment conditions (bad input, not logged in, network down \u2014 render\n * a friendly message, low alert priority) from internal bugs (invariant\n * violations \u2014 full stack, page someone).\n *\n * The runtime package is out of scope and keeps its own `Errors.AbstractError`\n * hierarchy. The adk typed families (`DependencyError`, `Agent0*Error`) extend\n * this base; new code should start here.\n */\nexport class AdkError<Code extends string = string> extends Error {\n /**\n * Marker for cross-module-instance checks \u2014 `instanceof` breaks when a\n * package is duplicated in the dependency graph.\n * @internal\n */\n public static readonly __IS_ADK_BASE_ERROR = true\n\n /**\n * Stable SCREAMING_SNAKE_CASE identifier, e.g. 'BOT_NOT_FOUND'. Subclasses\n * pin `Code` to a literal union (`class EvalRunnerError extends\n * AdkError<EvalErrorCode>`) so typos are compile errors and `code` narrows\n * in switches.\n */\n readonly code: Code\n /**\n * True for user/environment conditions the developer can fix themselves\n * (validation, auth, connectivity). False for internal bugs. Defaults to\n * false so unclassified errors surface as bugs until someone triages them.\n */\n readonly expected: boolean\n /** Structured context. Sanitized before any telemetry leaves the machine. */\n readonly details?: Record<string, unknown>\n /** Actionable next step shown to the user, e.g. \"Run 'adk login' first.\" */\n readonly suggestion?: string\n\n constructor(opts: {\n code: Code\n message: string\n expected?: boolean\n details?: Record<string, unknown>\n suggestion?: string\n cause?: unknown\n }) {\n super(opts.message, opts.cause !== undefined ? { cause: opts.cause } : undefined)\n this.name = this.constructor.name\n this.code = opts.code\n this.expected = opts.expected ?? false\n // Conditional assignment keeps the optional fields absent-not-undefined,\n // which downstream tsconfigs with exactOptionalPropertyTypes require.\n if (opts.details !== undefined) {\n this.details = opts.details\n }\n if (opts.suggestion !== undefined) {\n this.suggestion = opts.suggestion\n }\n }\n}\n\n/**\n * Duck-typed guard that survives duplicated module instances in the\n * dependency graph, where `instanceof AdkError` returns false for an error\n * constructed from another copy of this module. No manual prototype walking\n * needed: static properties are inherited through the constructor chain, so\n * a subclass's constructor resolves the marker in one lookup.\n */\nexport function isAdkError(error: unknown): error is AdkError {\n if (error instanceof AdkError) return true\n if (!(error instanceof Error)) return false\n return (error.constructor as unknown as Record<string, unknown> | undefined)?.__IS_ADK_BASE_ERROR === true\n}\n", "import { AdkError } from '@botpress/analytics'\n\n/**\n * Stable error codes for the eval engine. Typed as a literal union so a typo'd\n * code is a compile error and PostHog issue-slicing stays consistent.\n * Conventions per docs/ERROR-HANDLING.md.\n */\nexport const EVAL_ERROR_CODES = [\n 'EVAL_LOAD_FAILED',\n 'EVAL_FILE_EMPTY',\n 'EVAL_DUPLICATE_NAME',\n 'EVAL_SEED_NO_CONVERSATION',\n 'EVAL_NO_CONVERSATION_ID',\n 'EVAL_TURN_CONFIG_INVALID',\n 'SSE_CONNECT_FAILED',\n 'SSE_NO_BODY',\n 'CHAT_CLIENT_MISSING',\n 'CHAT_NOT_CONNECTED',\n 'CHAT_INTEGRATION_MISSING',\n 'CHAT_CHANNEL_UNBOUND',\n] as const\n\nexport type EvalErrorCode = (typeof EVAL_ERROR_CODES)[number]\n\n/**\n * Typed error for the eval engine. Named EvalRunnerError (not EvalError) to\n * avoid shadowing the JS built-in `EvalError`.\n */\nexport class EvalRunnerError extends AdkError<EvalErrorCode> {}\n", "import type { EvalDefinition } from '../definition'\nimport { loadEvalsFromDir } from '../loader'\n\nexport type EvalDefinitionLoader = () => Promise<EvalDefinition[]>\n\nexport function createDiskEvalLoader(evalsDir: string): EvalDefinitionLoader {\n return () => loadEvalsFromDir(evalsDir)\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,61 @@
1
+ import type { EvalDefinition } from '../definition';
2
+ import type { EvalFilter, EvalProgressEvent, EvalReport, EvalRunReport } from '../types';
3
+ export interface EvalSummary {
4
+ name: string;
5
+ description?: string;
6
+ tags: string[];
7
+ type: 'capability' | 'regression';
8
+ turnCount: number;
9
+ hasOutcome: boolean;
10
+ }
11
+ export interface EvalRunSummary {
12
+ id: string;
13
+ timestamp: string;
14
+ passed: number;
15
+ failed: number;
16
+ total: number;
17
+ duration: number;
18
+ botDuration: number;
19
+ evalDuration: number;
20
+ filter?: EvalFilter;
21
+ evalNames: string[];
22
+ aborted: boolean;
23
+ }
24
+ export interface EvalReportHistoryEntry {
25
+ runId: string;
26
+ timestamp: string;
27
+ report: EvalReport;
28
+ totalEvalsInRun: number;
29
+ filter?: EvalFilter;
30
+ }
31
+ export interface EvalWatchOptions {
32
+ runId?: string;
33
+ workflowId?: string;
34
+ }
35
+ export interface EvalStore {
36
+ listEvals(filter?: EvalFilter): Promise<EvalSummary[]>;
37
+ getEval(name: string): Promise<EvalDefinition | null>;
38
+ createRun(runType?: string, metadata?: Record<string, unknown>): Promise<string>;
39
+ addRunResults(runId: string, evalReport: EvalReport): Promise<void>;
40
+ completeRun(runId: string, report: EvalRunReport): Promise<void>;
41
+ loadRunResult(runId: string): Promise<EvalRunReport | null>;
42
+ getLatestRun(): Promise<EvalRunReport | null>;
43
+ listRunSummaries(opts?: {
44
+ limit?: number;
45
+ since?: number;
46
+ }): Promise<EvalRunSummary[]>;
47
+ listEvalReportsByName(evalName: string, opts?: {
48
+ limit?: number;
49
+ since?: number;
50
+ }): Promise<EvalReportHistoryEntry[]>;
51
+ listEvalReportsBulk(opts?: {
52
+ perEval?: number;
53
+ since?: number;
54
+ }): Promise<Record<string, EvalReportHistoryEntry[]>>;
55
+ watchRun(signal?: AbortSignal, options?: EvalWatchOptions): AsyncIterable<EvalProgressEvent>;
56
+ getRunnerState(): Promise<{
57
+ running: boolean;
58
+ runId: string | null;
59
+ }>;
60
+ }
61
+ //# sourceMappingURL=eval-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval-store.d.ts","sourceRoot":"","sources":["../../src/stores/eval-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=eval-store.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,8 @@
1
+ export type { EvalStore, EvalSummary, EvalRunSummary, EvalReportHistoryEntry, EvalWatchOptions } from './eval-store';
2
+ export { LocalEvalStore, getLocalEvalStore, closeLocalEvalStores } from './local-eval-store';
3
+ export type { LocalEvalStoreConfig } from './local-eval-store';
4
+ export { VortexEvalStore } from './vortex-eval-store';
5
+ export type { VortexEvalStoreConfig } from './vortex-eval-store';
6
+ export { createDiskEvalLoader } from './eval-definition-loader';
7
+ export type { EvalDefinitionLoader } from './eval-definition-loader';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stores/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpH,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC5F,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA"}