@evalstudio/core 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/connector.d.ts +101 -0
  2. package/dist/connector.d.ts.map +1 -0
  3. package/dist/connector.js +477 -0
  4. package/dist/connector.js.map +1 -0
  5. package/dist/eval.d.ts +66 -0
  6. package/dist/eval.d.ts.map +1 -0
  7. package/dist/eval.js +188 -0
  8. package/dist/eval.js.map +1 -0
  9. package/dist/evaluator.d.ts +37 -0
  10. package/dist/evaluator.d.ts.map +1 -0
  11. package/dist/evaluator.js +121 -0
  12. package/dist/evaluator.js.map +1 -0
  13. package/dist/execution.d.ts +29 -0
  14. package/dist/execution.d.ts.map +1 -0
  15. package/dist/execution.js +94 -0
  16. package/dist/execution.js.map +1 -0
  17. package/dist/index.d.ts +17 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +16 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/llm-client.d.ts +31 -0
  22. package/dist/llm-client.d.ts.map +1 -0
  23. package/dist/llm-client.js +121 -0
  24. package/dist/llm-client.js.map +1 -0
  25. package/dist/llm-provider.d.ts +46 -0
  26. package/dist/llm-provider.d.ts.map +1 -0
  27. package/dist/llm-provider.js +199 -0
  28. package/dist/llm-provider.js.map +1 -0
  29. package/dist/persona-generator.d.ts +34 -0
  30. package/dist/persona-generator.d.ts.map +1 -0
  31. package/dist/persona-generator.js +99 -0
  32. package/dist/persona-generator.js.map +1 -0
  33. package/dist/persona.d.ts +28 -0
  34. package/dist/persona.d.ts.map +1 -0
  35. package/dist/persona.js +100 -0
  36. package/dist/persona.js.map +1 -0
  37. package/dist/project.d.ts +43 -0
  38. package/dist/project.d.ts.map +1 -0
  39. package/dist/project.js +114 -0
  40. package/dist/project.js.map +1 -0
  41. package/dist/prompt.d.ts +31 -0
  42. package/dist/prompt.d.ts.map +1 -0
  43. package/dist/prompt.js +73 -0
  44. package/dist/prompt.js.map +1 -0
  45. package/dist/run-processor.d.ts +127 -0
  46. package/dist/run-processor.d.ts.map +1 -0
  47. package/dist/run-processor.js +495 -0
  48. package/dist/run-processor.js.map +1 -0
  49. package/dist/run.d.ts +101 -0
  50. package/dist/run.d.ts.map +1 -0
  51. package/dist/run.js +279 -0
  52. package/dist/run.js.map +1 -0
  53. package/dist/scenario.d.ts +66 -0
  54. package/dist/scenario.d.ts.map +1 -0
  55. package/dist/scenario.js +110 -0
  56. package/dist/scenario.js.map +1 -0
  57. package/dist/status.d.ts +10 -0
  58. package/dist/status.d.ts.map +1 -0
  59. package/dist/status.js +15 -0
  60. package/dist/status.js.map +1 -0
  61. package/dist/storage.d.ts +11 -0
  62. package/dist/storage.d.ts.map +1 -0
  63. package/dist/storage.js +57 -0
  64. package/dist/storage.js.map +1 -0
  65. package/dist/types.d.ts +46 -0
  66. package/dist/types.d.ts.map +1 -0
  67. package/dist/types.js +26 -0
  68. package/dist/types.js.map +1 -0
  69. package/package.json +51 -0
package/dist/run.js ADDED
@@ -0,0 +1,279 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { getConnector } from "./connector.js";
5
+ import { getEval } from "./eval.js";
6
+ import { createExecution } from "./execution.js";
7
+ import { getPersona } from "./persona.js";
8
+ import { getScenario } from "./scenario.js";
9
+ import { getStorageDir } from "./storage.js";
10
+ function getStoragePath() {
11
+ return join(getStorageDir(), "runs.json");
12
+ }
13
+ function loadRuns() {
14
+ const path = getStoragePath();
15
+ if (!existsSync(path)) {
16
+ return [];
17
+ }
18
+ const data = readFileSync(path, "utf-8");
19
+ return JSON.parse(data);
20
+ }
21
+ function saveRuns(runs) {
22
+ const path = getStoragePath();
23
+ writeFileSync(path, JSON.stringify(runs, null, 2));
24
+ }
25
+ export function createRuns(input) {
26
+ const evalItem = getEval(input.evalId);
27
+ if (!evalItem) {
28
+ throw new Error(`Eval with id "${input.evalId}" not found`);
29
+ }
30
+ // Validate all scenarios exist
31
+ const scenarios = evalItem.scenarioIds.map((scenarioId) => {
32
+ const scenario = getScenario(scenarioId);
33
+ if (!scenario) {
34
+ throw new Error(`Scenario with id "${scenarioId}" not found`);
35
+ }
36
+ return scenario;
37
+ });
38
+ if (scenarios.length === 0) {
39
+ throw new Error("Eval has no scenarios configured");
40
+ }
41
+ // Collect all unique persona IDs and validate they exist
42
+ const allPersonaIds = new Set();
43
+ for (const scenario of scenarios) {
44
+ if (scenario.personaIds) {
45
+ for (const personaId of scenario.personaIds) {
46
+ allPersonaIds.add(personaId);
47
+ }
48
+ }
49
+ }
50
+ for (const personaId of allPersonaIds) {
51
+ const persona = getPersona(personaId);
52
+ if (!persona) {
53
+ throw new Error(`Persona with id "${personaId}" not found`);
54
+ }
55
+ }
56
+ const allRuns = loadRuns();
57
+ const now = new Date().toISOString();
58
+ const createdRuns = [];
59
+ // Create an execution to group all runs created in this batch
60
+ const execution = createExecution({
61
+ projectId: evalItem.projectId,
62
+ evalId: input.evalId,
63
+ });
64
+ // Create runs for each scenario/persona combination
65
+ for (const scenario of scenarios) {
66
+ // Determine personas for this scenario: use scenario.personaIds, or [undefined] if empty
67
+ const personaIds = scenario.personaIds && scenario.personaIds.length > 0
68
+ ? scenario.personaIds
69
+ : [undefined];
70
+ for (const personaId of personaIds) {
71
+ const run = {
72
+ id: randomUUID(),
73
+ evalId: input.evalId,
74
+ projectId: evalItem.projectId,
75
+ personaId,
76
+ scenarioId: scenario.id,
77
+ executionId: execution.id,
78
+ status: "queued",
79
+ messages: [],
80
+ createdAt: now,
81
+ updatedAt: now,
82
+ };
83
+ allRuns.push(run);
84
+ createdRuns.push(run);
85
+ }
86
+ }
87
+ saveRuns(allRuns);
88
+ return createdRuns;
89
+ }
90
+ export function createRun(input) {
91
+ const runs = createRuns(input);
92
+ return runs[0];
93
+ }
94
+ /**
95
+ * Creates a playground run for testing scenarios without an eval.
96
+ * Used by the Scenario Playground to create runs directly.
97
+ */
98
+ export function createPlaygroundRun(input) {
99
+ const { scenarioId, connectorId, personaId } = input;
100
+ // Validate scenario exists
101
+ const scenario = getScenario(scenarioId);
102
+ if (!scenario) {
103
+ throw new Error(`Scenario with id "${scenarioId}" not found`);
104
+ }
105
+ // Validate connector exists
106
+ const connector = getConnector(connectorId);
107
+ if (!connector) {
108
+ throw new Error(`Connector with id "${connectorId}" not found`);
109
+ }
110
+ // Validate persona if provided
111
+ if (personaId) {
112
+ const persona = getPersona(personaId);
113
+ if (!persona) {
114
+ throw new Error(`Persona with id "${personaId}" not found`);
115
+ }
116
+ }
117
+ const allRuns = loadRuns();
118
+ const now = new Date().toISOString();
119
+ const run = {
120
+ id: randomUUID(),
121
+ // No evalId for playground runs
122
+ projectId: scenario.projectId,
123
+ scenarioId,
124
+ connectorId,
125
+ personaId,
126
+ status: "queued",
127
+ messages: [],
128
+ createdAt: now,
129
+ updatedAt: now,
130
+ };
131
+ allRuns.push(run);
132
+ saveRuns(allRuns);
133
+ return run;
134
+ }
135
+ export function getRun(id) {
136
+ const runs = loadRuns();
137
+ return runs.find((r) => r.id === id);
138
+ }
139
+ export function listRuns(evalIdOrOptions, projectId) {
140
+ const runs = loadRuns();
141
+ // Handle new object-based API
142
+ if (typeof evalIdOrOptions === "object" && evalIdOrOptions !== null) {
143
+ const { evalId, projectId, scenarioId, status, limit } = evalIdOrOptions;
144
+ let filtered = runs;
145
+ if (evalId) {
146
+ filtered = filtered.filter((r) => r.evalId === evalId);
147
+ }
148
+ if (projectId) {
149
+ filtered = filtered.filter((r) => r.projectId === projectId);
150
+ }
151
+ if (scenarioId) {
152
+ filtered = filtered.filter((r) => r.scenarioId === scenarioId);
153
+ }
154
+ if (status) {
155
+ filtered = filtered.filter((r) => r.status === status);
156
+ }
157
+ // Sort by createdAt (oldest first for queue processing)
158
+ filtered.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
159
+ if (limit && limit > 0) {
160
+ filtered = filtered.slice(0, limit);
161
+ }
162
+ return filtered;
163
+ }
164
+ // Legacy API compatibility
165
+ const evalId = evalIdOrOptions;
166
+ if (evalId) {
167
+ return runs.filter((r) => r.evalId === evalId);
168
+ }
169
+ if (projectId) {
170
+ return runs.filter((r) => r.projectId === projectId);
171
+ }
172
+ return runs;
173
+ }
174
+ export function listRunsByEval(evalId) {
175
+ const runs = loadRuns();
176
+ return runs
177
+ .filter((r) => r.evalId === evalId)
178
+ .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
179
+ }
180
+ export function listRunsByScenario(scenarioId) {
181
+ const runs = loadRuns();
182
+ return runs
183
+ .filter((r) => r.scenarioId === scenarioId)
184
+ .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
185
+ }
186
+ export function listRunsByPersona(personaId) {
187
+ const runs = loadRuns();
188
+ return runs
189
+ .filter((r) => r.personaId === personaId)
190
+ .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
191
+ }
192
+ export function updateRun(id, input) {
193
+ const runs = loadRuns();
194
+ const index = runs.findIndex((r) => r.id === id);
195
+ if (index === -1) {
196
+ return undefined;
197
+ }
198
+ const run = runs[index];
199
+ // Use "in" check to allow explicitly setting fields to undefined (to clear them)
200
+ const updated = {
201
+ ...run,
202
+ status: input.status ?? run.status,
203
+ startedAt: "startedAt" in input ? input.startedAt : run.startedAt,
204
+ completedAt: "completedAt" in input ? input.completedAt : run.completedAt,
205
+ messages: input.messages ?? run.messages,
206
+ output: "output" in input ? input.output : run.output,
207
+ result: "result" in input ? input.result : run.result,
208
+ error: "error" in input ? input.error : run.error,
209
+ metadata: "metadata" in input ? input.metadata : run.metadata,
210
+ threadId: "threadId" in input ? input.threadId : run.threadId,
211
+ updatedAt: new Date().toISOString(),
212
+ };
213
+ runs[index] = updated;
214
+ saveRuns(runs);
215
+ return updated;
216
+ }
217
+ export function deleteRun(id) {
218
+ const runs = loadRuns();
219
+ const index = runs.findIndex((r) => r.id === id);
220
+ if (index === -1) {
221
+ return false;
222
+ }
223
+ runs.splice(index, 1);
224
+ saveRuns(runs);
225
+ return true;
226
+ }
227
+ export function deleteRunsByEval(evalId) {
228
+ const runs = loadRuns();
229
+ const filtered = runs.filter((r) => r.evalId !== evalId);
230
+ const deletedCount = runs.length - filtered.length;
231
+ if (deletedCount > 0) {
232
+ saveRuns(filtered);
233
+ }
234
+ return deletedCount;
235
+ }
236
+ export function deleteRunsByProject(projectId) {
237
+ const runs = loadRuns();
238
+ const filtered = runs.filter((r) => r.projectId !== projectId);
239
+ const deletedCount = runs.length - filtered.length;
240
+ if (deletedCount > 0) {
241
+ saveRuns(filtered);
242
+ }
243
+ return deletedCount;
244
+ }
245
+ /**
246
+ * Retries a failed run by resetting it to queued status.
247
+ * Clears error, timing info, messages, and output.
248
+ * Increments retryCount to ensure a fresh LangGraph thread is used.
249
+ *
250
+ * @param id - The run ID to retry
251
+ * @returns The updated run, or undefined if not found
252
+ * @throws Error if the run status is not "failed"
253
+ */
254
+ export function retryRun(id) {
255
+ const run = getRun(id);
256
+ if (!run) {
257
+ return undefined;
258
+ }
259
+ // Only allow retry on error runs (system failures)
260
+ // Completed runs with result.success=false are evaluation failures and should not be retried
261
+ if (run.status !== "error") {
262
+ throw new Error(`Cannot retry run with status "${run.status}". Only runs with system errors can be retried.`);
263
+ }
264
+ const updates = {
265
+ status: "queued",
266
+ error: undefined,
267
+ startedAt: undefined,
268
+ completedAt: undefined,
269
+ result: undefined,
270
+ metadata: undefined,
271
+ output: undefined,
272
+ // Always clear messages - they'll be rebuilt when the run starts
273
+ messages: [],
274
+ // Generate a new thread ID to start fresh in LangGraph
275
+ threadId: randomUUID(),
276
+ };
277
+ return updateRun(id, updates);
278
+ }
279
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAgB,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA0E7C,SAAS,cAAc;IACrB,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,QAAQ;IACf,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAU,CAAC;AACnC,CAAC;AAED,SAAS,QAAQ,CAAC,IAAW;IAC3B,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAqB;IAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,CAAC,MAAM,aAAa,CAAC,CAAC;IAC9D,CAAC;IAED,+BAA+B;IAC/B,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,aAAa,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,yDAAyD;IACzD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACxB,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC5C,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,aAAa,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,oBAAoB,SAAS,aAAa,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,WAAW,GAAU,EAAE,CAAC;IAE9B,8DAA8D;IAC9D,MAAM,SAAS,GAAG,eAAe,CAAC;QAChC,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;IAEH,oDAAoD;IACpD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,yFAAyF;QACzF,MAAM,UAAU,GACd,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;YACnD,CAAC,CAAC,QAAQ,CAAC,UAAU;YACrB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAElB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,GAAG,GAAQ;gBACf,EAAE,EAAE,UAAU,EAAE;gBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,SAAS;gBACT,UAAU,EAAE,QAAQ,CAAC,EAAE;gBACvB,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,MAAM,EAAE,QAAQ;gBAChB,QAAQ,EAAE,EAAE;gBACZ,SAAS,EAAE,GAAG;gBACd,SAAS,EAAE,GAAG;aACf,CAAC;YAEF,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClB,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAErD,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,aAAa,CAAC,CAAC;IAChE,CAAC;IAED,4BAA4B;IAC5B,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,sBAAsB,WAAW,aAAa,CAAC,CAAC;IAClE,CAAC;IAED,+BAA+B;IAC/B,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,oBAAoB,SAAS,aAAa,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,MAAM,GAAG,GAAQ;QACf,EAAE,EAAE,UAAU,EAAE;QAChB,gCAAgC;QAChC,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,UAAU;QACV,WAAW;QACX,SAAS;QACT,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf,CAAC;IAEF,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,QAAQ,CAAC,OAAO,CAAC,CAAC;IAElB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EAAU;IAC/B,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACvC,CAAC;AAYD,MAAM,UAAU,QAAQ,CACtB,eAA0C,EAC1C,SAAkB;IAElB,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IAExB,8BAA8B;IAC9B,IAAI,OAAO,eAAe,KAAK,QAAQ,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;QACpE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,CAAC;QAEzE,IAAI,QAAQ,GAAG,IAAI,CAAC;QAEpB,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACzD,CAAC;QAED,wDAAwD;QACxD,QAAQ,CAAC,IAAI,CACX,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACpE,CAAC;QAEF,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACvB,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,2BAA2B;IAC3B,MAAM,MAAM,GAAG,eAAe,CAAC;IAE/B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,OAAO,IAAI;SACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;SAClC,IAAI,CACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACpE,CAAC;AACN,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,OAAO,IAAI;SACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC;SAC1C,IAAI,CACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACpE,CAAC;AACN,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,OAAO,IAAI;SACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC;SACxC,IAAI,CACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACpE,CAAC;AACN,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU,EAAE,KAAqB;IACzD,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAEjD,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAExB,iFAAiF;IACjF,MAAM,OAAO,GAAQ;QACnB,GAAG,GAAG;QACN,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM;QAClC,SAAS,EAAE,WAAW,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS;QACjE,WAAW,EAAE,aAAa,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW;QACzE,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;QACxC,MAAM,EAAE,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM;QACrD,MAAM,EAAE,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM;QACrD,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK;QACjD,QAAQ,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ;QAC7D,QAAQ,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ;QAC7D,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,IAAI,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEf,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAEjD,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEf,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACzD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAEnD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAEnD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAU;IACjC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACvB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,mDAAmD;IACnD,6FAA6F;IAC7F,IAAI,GAAG,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,MAAM,iDAAiD,CAAC,CAAC;IAChH,CAAC;IAED,MAAM,OAAO,GAAmB;QAC9B,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,SAAS;QAChB,SAAS,EAAE,SAAS;QACpB,WAAW,EAAE,SAAS;QACtB,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,SAAS;QACjB,iEAAiE;QACjE,QAAQ,EAAE,EAAE;QACZ,uDAAuD;QACvD,QAAQ,EAAE,UAAU,EAAE;KACvB,CAAC;IAEF,OAAO,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import type { Message } from "./types.js";
2
+ export type { Message };
3
+ /**
4
+ * Controls when failureCriteria is evaluated during a run:
5
+ * - "every_turn": Check at every turn and stop immediately on failure (like successCriteria)
6
+ * - "on_max_messages": Only check when maxMessages is reached without success
7
+ */
8
+ export type FailureCriteriaMode = "every_turn" | "on_max_messages";
9
+ export interface Scenario {
10
+ id: string;
11
+ projectId: string;
12
+ name: string;
13
+ instructions?: string;
14
+ messages?: Message[];
15
+ /** Maximum number of messages in a conversation before stopping */
16
+ maxMessages?: number;
17
+ /** Criteria for determining if the agent passed (used by evaluator) */
18
+ successCriteria?: string;
19
+ /** Criteria for determining if the agent failed (used by evaluator) */
20
+ failureCriteria?: string;
21
+ /** When to check failureCriteria: "on_max_messages" (default) or "every_turn" */
22
+ failureCriteriaMode?: FailureCriteriaMode;
23
+ /** IDs of personas associated with this scenario (optional, can be empty) */
24
+ personaIds?: string[];
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ }
28
+ export interface CreateScenarioInput {
29
+ projectId: string;
30
+ name: string;
31
+ instructions?: string;
32
+ messages?: Message[];
33
+ /** Maximum number of messages in a conversation before stopping */
34
+ maxMessages?: number;
35
+ /** Criteria for determining if the agent passed */
36
+ successCriteria?: string;
37
+ /** Criteria for determining if the agent failed */
38
+ failureCriteria?: string;
39
+ /** When to check failureCriteria: "on_max_messages" (default) or "every_turn" */
40
+ failureCriteriaMode?: FailureCriteriaMode;
41
+ /** IDs of personas associated with this scenario */
42
+ personaIds?: string[];
43
+ }
44
+ export interface UpdateScenarioInput {
45
+ name?: string;
46
+ instructions?: string;
47
+ messages?: Message[];
48
+ /** Maximum number of messages in a conversation before stopping */
49
+ maxMessages?: number;
50
+ /** Criteria for determining if the agent passed */
51
+ successCriteria?: string;
52
+ /** Criteria for determining if the agent failed */
53
+ failureCriteria?: string;
54
+ /** When to check failureCriteria: "on_max_messages" (default) or "every_turn" */
55
+ failureCriteriaMode?: FailureCriteriaMode;
56
+ /** IDs of personas associated with this scenario */
57
+ personaIds?: string[];
58
+ }
59
+ export declare function createScenario(input: CreateScenarioInput): Scenario;
60
+ export declare function getScenario(id: string): Scenario | undefined;
61
+ export declare function getScenarioByName(projectId: string, name: string): Scenario | undefined;
62
+ export declare function listScenarios(projectId?: string): Scenario[];
63
+ export declare function updateScenario(id: string, input: UpdateScenarioInput): Scenario | undefined;
64
+ export declare function deleteScenario(id: string): boolean;
65
+ export declare function deleteScenariosByProject(projectId: string): number;
66
+ //# sourceMappingURL=scenario.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,YAAY,EAAE,OAAO,EAAE,CAAC;AAExB;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,iBAAiB,CAAC;AAEnE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAoBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,QAAQ,CAsCnE;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAG5D;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,QAAQ,GAAG,SAAS,CAGtB;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAM5D;AAED,wBAAgB,cAAc,CAC5B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,mBAAmB,GACzB,QAAQ,GAAG,SAAS,CAuCtB;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAYlD;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAUlE"}
@@ -0,0 +1,110 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { getProject } from "./project.js";
5
+ import { getStorageDir } from "./storage.js";
6
+ function getStoragePath() {
7
+ return join(getStorageDir(), "scenarios.json");
8
+ }
9
+ function loadScenarios() {
10
+ const path = getStoragePath();
11
+ if (!existsSync(path)) {
12
+ return [];
13
+ }
14
+ const data = readFileSync(path, "utf-8");
15
+ return JSON.parse(data);
16
+ }
17
+ function saveScenarios(scenarios) {
18
+ const path = getStoragePath();
19
+ writeFileSync(path, JSON.stringify(scenarios, null, 2));
20
+ }
21
+ export function createScenario(input) {
22
+ const project = getProject(input.projectId);
23
+ if (!project) {
24
+ throw new Error(`Project with id "${input.projectId}" not found`);
25
+ }
26
+ const scenarios = loadScenarios();
27
+ if (scenarios.some((s) => s.projectId === input.projectId && s.name === input.name)) {
28
+ throw new Error(`Scenario with name "${input.name}" already exists in this project`);
29
+ }
30
+ const now = new Date().toISOString();
31
+ const scenario = {
32
+ id: randomUUID(),
33
+ projectId: input.projectId,
34
+ name: input.name,
35
+ instructions: input.instructions,
36
+ messages: input.messages,
37
+ maxMessages: input.maxMessages,
38
+ successCriteria: input.successCriteria,
39
+ failureCriteria: input.failureCriteria,
40
+ failureCriteriaMode: input.failureCriteriaMode,
41
+ personaIds: input.personaIds,
42
+ createdAt: now,
43
+ updatedAt: now,
44
+ };
45
+ scenarios.push(scenario);
46
+ saveScenarios(scenarios);
47
+ return scenario;
48
+ }
49
+ export function getScenario(id) {
50
+ const scenarios = loadScenarios();
51
+ return scenarios.find((s) => s.id === id);
52
+ }
53
+ export function getScenarioByName(projectId, name) {
54
+ const scenarios = loadScenarios();
55
+ return scenarios.find((s) => s.projectId === projectId && s.name === name);
56
+ }
57
+ export function listScenarios(projectId) {
58
+ const scenarios = loadScenarios();
59
+ if (projectId) {
60
+ return scenarios.filter((s) => s.projectId === projectId);
61
+ }
62
+ return scenarios;
63
+ }
64
+ export function updateScenario(id, input) {
65
+ const scenarios = loadScenarios();
66
+ const index = scenarios.findIndex((s) => s.id === id);
67
+ if (index === -1) {
68
+ return undefined;
69
+ }
70
+ const scenario = scenarios[index];
71
+ if (input.name &&
72
+ scenarios.some((s) => s.projectId === scenario.projectId && s.name === input.name && s.id !== id)) {
73
+ throw new Error(`Scenario with name "${input.name}" already exists in this project`);
74
+ }
75
+ const updated = {
76
+ ...scenario,
77
+ name: input.name ?? scenario.name,
78
+ instructions: input.instructions ?? scenario.instructions,
79
+ messages: input.messages ?? scenario.messages,
80
+ maxMessages: input.maxMessages ?? scenario.maxMessages,
81
+ successCriteria: input.successCriteria ?? scenario.successCriteria,
82
+ failureCriteria: input.failureCriteria ?? scenario.failureCriteria,
83
+ failureCriteriaMode: input.failureCriteriaMode ?? scenario.failureCriteriaMode,
84
+ personaIds: input.personaIds ?? scenario.personaIds,
85
+ updatedAt: new Date().toISOString(),
86
+ };
87
+ scenarios[index] = updated;
88
+ saveScenarios(scenarios);
89
+ return updated;
90
+ }
91
+ export function deleteScenario(id) {
92
+ const scenarios = loadScenarios();
93
+ const index = scenarios.findIndex((s) => s.id === id);
94
+ if (index === -1) {
95
+ return false;
96
+ }
97
+ scenarios.splice(index, 1);
98
+ saveScenarios(scenarios);
99
+ return true;
100
+ }
101
+ export function deleteScenariosByProject(projectId) {
102
+ const scenarios = loadScenarios();
103
+ const filtered = scenarios.filter((s) => s.projectId !== projectId);
104
+ const deletedCount = scenarios.length - filtered.length;
105
+ if (deletedCount > 0) {
106
+ saveScenarios(filtered);
107
+ }
108
+ return deletedCount;
109
+ }
110
+ //# sourceMappingURL=scenario.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface Status {
2
+ name: string;
3
+ version: string;
4
+ status: "ok" | "error";
5
+ timestamp: string;
6
+ node: string;
7
+ storageDir: string;
8
+ }
9
+ export declare function getStatus(): Status;
10
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,SAAS,IAAI,MAAM,CASlC"}
package/dist/status.js ADDED
@@ -0,0 +1,15 @@
1
+ import { createRequire } from "module";
2
+ import { getStorageDir } from "./storage.js";
3
+ const require = createRequire(import.meta.url);
4
+ const packageJson = require("../package.json");
5
+ export function getStatus() {
6
+ return {
7
+ name: "evalstudio",
8
+ version: packageJson.version,
9
+ status: "ok",
10
+ timestamp: new Date().toISOString(),
11
+ node: process.version,
12
+ storageDir: getStorageDir(),
13
+ };
14
+ }
15
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAWtE,MAAM,UAAU,SAAS;IACvB,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,UAAU,EAAE,aAAa,EAAE;KAC5B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare const CONFIG_FILENAME = "evalstudio.config.json";
2
+ export declare function getStorageDir(): string;
3
+ export declare function setStorageDir(dir: string | null): void;
4
+ export declare function resetStorageDir(): void;
5
+ export interface InitLocalProjectResult {
6
+ projectDir: string;
7
+ configPath: string;
8
+ storagePath: string;
9
+ }
10
+ export declare function initLocalProject(parentDir: string, name: string): InitLocalProjectResult;
11
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe,2BAA2B,CAAC;AAyBxD,wBAAgB,aAAa,IAAI,MAAM,CAQtC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEtD;AAED,wBAAgB,eAAe,IAAI,IAAI,CAGtC;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,sBAAsB,CAexB"}
@@ -0,0 +1,57 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ export const CONFIG_FILENAME = "evalstudio.config.json";
5
+ const LOCAL_STORAGE_DIRNAME = ".evalstudio";
6
+ let storageDir = null;
7
+ let discoveredDir = undefined;
8
+ function discoverLocalStorageDir(startDir) {
9
+ let current = startDir;
10
+ while (true) {
11
+ if (existsSync(join(current, CONFIG_FILENAME))) {
12
+ return join(current, LOCAL_STORAGE_DIRNAME);
13
+ }
14
+ const parent = dirname(current);
15
+ if (parent === current)
16
+ return null;
17
+ current = parent;
18
+ }
19
+ }
20
+ function ensureDir(dir) {
21
+ if (!existsSync(dir)) {
22
+ mkdirSync(dir, { recursive: true });
23
+ }
24
+ return dir;
25
+ }
26
+ export function getStorageDir() {
27
+ if (storageDir !== null)
28
+ return ensureDir(storageDir);
29
+ if (process.env.EVALSTUDIO_STORAGE_DIR)
30
+ return ensureDir(process.env.EVALSTUDIO_STORAGE_DIR);
31
+ if (discoveredDir === undefined) {
32
+ discoveredDir = discoverLocalStorageDir(process.cwd());
33
+ }
34
+ if (discoveredDir !== null)
35
+ return ensureDir(discoveredDir);
36
+ return ensureDir(join(homedir(), ".evalstudio"));
37
+ }
38
+ export function setStorageDir(dir) {
39
+ storageDir = dir;
40
+ }
41
+ export function resetStorageDir() {
42
+ storageDir = null;
43
+ discoveredDir = undefined;
44
+ }
45
+ export function initLocalProject(parentDir, name) {
46
+ const projectDir = join(parentDir, name);
47
+ const configPath = join(projectDir, CONFIG_FILENAME);
48
+ if (existsSync(configPath)) {
49
+ throw new Error(`Already initialized: ${configPath} already exists`);
50
+ }
51
+ mkdirSync(projectDir, { recursive: true });
52
+ writeFileSync(configPath, JSON.stringify({ version: 1 }, null, 2) + "\n");
53
+ const storagePath = join(projectDir, LOCAL_STORAGE_DIRNAME);
54
+ mkdirSync(storagePath, { recursive: true });
55
+ return { projectDir, configPath, storagePath };
56
+ }
57
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shared types used across multiple modules.
3
+ */
4
+ /**
5
+ * A tool call made by an assistant message.
6
+ */
7
+ export interface ToolCall {
8
+ id?: string;
9
+ name: string;
10
+ args: Record<string, unknown>;
11
+ type?: string;
12
+ }
13
+ /**
14
+ * A content block within a message (for multi-part content).
15
+ */
16
+ export interface ContentBlock {
17
+ type: string;
18
+ text?: string;
19
+ [key: string]: unknown;
20
+ }
21
+ /**
22
+ * A message in OpenAI chat format with optional LangGraph extensions.
23
+ */
24
+ export interface Message {
25
+ role: "user" | "assistant" | "system" | "tool";
26
+ content: string | ContentBlock[];
27
+ /** Tool calls made by the assistant */
28
+ tool_calls?: ToolCall[];
29
+ /** Tool call ID (for tool response messages) */
30
+ tool_call_id?: string;
31
+ /** Message name (e.g., tool name for tool messages) */
32
+ name?: string;
33
+ /** Additional metadata from the model/framework */
34
+ additional_kwargs?: Record<string, unknown>;
35
+ /** Response metadata from the model */
36
+ response_metadata?: Record<string, unknown>;
37
+ /** Message ID */
38
+ id?: string;
39
+ }
40
+ /**
41
+ * Normalizes message content to a string.
42
+ * If content is already a string, returns it as-is.
43
+ * If content is an array of ContentBlocks, extracts and joins text content.
44
+ */
45
+ export declare function getMessageContentAsString(content: string | ContentBlock[]): string;
46
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CAAC;IACjC,uCAAuC;IACvC,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,iBAAiB;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,GAC/B,MAAM,CAgBR"}