@eigenpal/sdk 0.7.2 → 0.9.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.
@@ -1,68 +1,56 @@
1
1
  import type { OperationResult } from '../client';
2
- import { EigenpalError } from '../errors';
3
2
  import type { Client } from '../generated/client';
4
3
  import {
4
+ runsArtifactsGet,
5
5
  runsArtifactsList,
6
6
  runsCancel,
7
- runsComparisonGet,
8
- runsConnect,
9
- runsDefinitionGet,
10
- runsExpectedCreate,
11
- runsExpectedFileDelete,
12
- runsExpectedFileGet,
13
- runsExpectedFileUpdate,
14
- runsExpectedGet,
7
+ runsEventsList,
15
8
  runsFeedbackClear,
9
+ runsFeedbackExpectedCreate,
10
+ runsFeedbackExpectedFileDelete,
11
+ runsFeedbackExpectedFileGet,
12
+ runsFeedbackExpectedFileUpdate,
13
+ runsFeedbackExpectedGet,
16
14
  runsFeedbackGet,
17
15
  runsFeedbackUpdate,
18
- runsFilesDelete,
19
- runsFilesList,
20
- runsFilesUpload,
21
- runsFilesZipGet,
22
16
  runsGet,
23
17
  runsList,
18
+ runsPromote,
24
19
  runsRerun,
20
+ runsScoresList,
21
+ runsStepsList,
25
22
  runsTraceGet,
23
+ runsUsageGet,
26
24
  } from '../generated/sdk.gen';
27
25
  import type {
28
- RunArtifactsResponse,
29
- RunDefinitionResponse,
26
+ RunsArtifactsListResponse,
30
27
  RunsCancelResponse,
31
- RunsComparisonGetResponse,
32
- RunsConnectResponse,
33
- RunsExpectedCreateData,
34
- RunsExpectedCreateResponse,
35
- RunsExpectedFileDeleteResponse,
36
- RunsExpectedFileUpdateData,
37
- RunsExpectedFileUpdateResponse,
38
- RunsExpectedGetResponse,
28
+ RunsEventsListResponse,
39
29
  RunsFeedbackClearResponse,
30
+ RunsFeedbackExpectedCreateResponse,
31
+ RunsFeedbackExpectedFileDeleteResponse,
32
+ RunsFeedbackExpectedFileUpdateResponse,
33
+ RunsFeedbackExpectedGetResponse,
40
34
  RunsFeedbackGetResponse,
41
- RunsFeedbackUpdateData,
42
35
  RunsFeedbackUpdateResponse,
43
- RunsFilesDeleteResponse,
44
- RunsFilesListResponse,
45
- RunsFilesUploadData,
46
- RunsFilesUploadResponse,
47
36
  RunsGetResponse,
48
37
  RunsListData,
49
38
  RunsListResponse,
39
+ RunsPromoteResponse,
50
40
  RunsRerunResponse,
41
+ RunsScoresListResponse,
42
+ RunsStepsListResponse,
51
43
  RunsTraceGetResponse,
44
+ RunsUsageGetResponse,
52
45
  } from '../generated/types.gen';
46
+ import { buildSingleFileMultipart, type FileInput } from '../lib/files';
53
47
 
54
48
  type Dispatch = <T>(call: () => Promise<OperationResult<T>>) => Promise<T>;
49
+ type SignalOptions = { signal?: AbortSignal };
55
50
 
56
51
  export type ListRunsOptions = NonNullable<RunsListData['query']> & { signal?: AbortSignal };
57
- type SignalOptions = { signal?: AbortSignal };
58
52
 
59
- /**
60
- * Expandable sections for `runs.get`. Each token adds one nested object with
61
- * the same name. Terminal runs expose top-level `output`, `files`, and `error`.
62
- */
63
53
  export type RunExpandSection = 'input' | 'usage' | 'execution' | 'debug';
64
-
65
- /** Typed section list, or a raw comma-separated string for forward compat. */
66
54
  export type RunExpand = readonly RunExpandSection[] | (string & {});
67
55
 
68
56
  function formatExpand(expand: RunExpand | undefined): string | undefined {
@@ -72,22 +60,18 @@ function formatExpand(expand: RunExpand | undefined): string | undefined {
72
60
  }
73
61
 
74
62
  export class RunsResource {
75
- public readonly feedback: RunsFeedbackResource;
76
- public readonly expected: RunsExpectedResource;
77
- public readonly files: RunsFilesResource;
78
63
  public readonly artifacts: RunsArtifactsResource;
79
- public readonly comparison: RunsComparisonResource;
64
+ public readonly scores: RunsScoresResource;
65
+ public readonly feedback: RunsFeedbackResource;
80
66
  public readonly trace: RunsTraceResource;
81
67
 
82
68
  constructor(
83
69
  private readonly client: Client,
84
70
  private readonly dispatch: Dispatch
85
71
  ) {
86
- this.feedback = new RunsFeedbackResource(client, dispatch);
87
- this.expected = new RunsExpectedResource(client, dispatch);
88
- this.files = new RunsFilesResource(client, dispatch);
89
72
  this.artifacts = new RunsArtifactsResource(client, dispatch);
90
- this.comparison = new RunsComparisonResource(client, dispatch);
73
+ this.scores = new RunsScoresResource(client, dispatch);
74
+ this.feedback = new RunsFeedbackResource(client, dispatch);
91
75
  this.trace = new RunsTraceResource(client, dispatch);
92
76
  }
93
77
 
@@ -96,17 +80,12 @@ export class RunsResource {
96
80
  return this.dispatch(() => runsList({ client: this.client, query, signal }));
97
81
  }
98
82
 
99
- /**
100
- * Fetch the canonical grouped run object. Terminal runs include top-level
101
- * `output`, `files`, and `error`. Pass `expand` (for example
102
- * `['usage', 'execution']`) to add optional nested detail objects.
103
- */
104
83
  async get(
105
84
  runId: string,
106
85
  options: { expand?: RunExpand; signal?: AbortSignal } = {}
107
86
  ): Promise<RunsGetResponse> {
108
87
  const expand = formatExpand(options.expand);
109
- return this.dispatch<RunsGetResponse>(() =>
88
+ return this.dispatch(() =>
110
89
  runsGet({
111
90
  client: this.client,
112
91
  path: { id: runId },
@@ -122,6 +101,21 @@ export class RunsResource {
122
101
  );
123
102
  }
124
103
 
104
+ async promote(
105
+ runId: string,
106
+ body: Record<string, unknown> = {},
107
+ options: SignalOptions = {}
108
+ ): Promise<RunsPromoteResponse> {
109
+ return this.dispatch(() =>
110
+ runsPromote({
111
+ client: this.client,
112
+ path: { id: runId },
113
+ body: body as never,
114
+ signal: options.signal,
115
+ })
116
+ );
117
+ }
118
+
125
119
  async rerun(
126
120
  runId: string,
127
121
  query: { version?: string; wait_for_completion?: number } = {},
@@ -132,99 +126,27 @@ export class RunsResource {
132
126
  );
133
127
  }
134
128
 
135
- async compare(
136
- referenceRunId: string,
137
- runId: string,
138
- options: {
139
- baseline?: boolean;
140
- step?: string;
141
- normalizeDates?: boolean;
142
- signal?: AbortSignal;
143
- } = {}
144
- ): Promise<RunComparisonReport> {
145
- const mode = options.baseline ? 'baseline' : 'expected';
146
- const [reference, target] = await Promise.all([
147
- this.get(referenceRunId, {
148
- expand: ['execution'],
149
- signal: options.signal,
150
- }),
151
- this.get(runId, { expand: ['execution'], signal: options.signal }),
152
- ]);
153
-
154
- if (isWorkflowRun(reference) && isWorkflowRun(target)) {
155
- return compareWorkflowRuns(referenceRunId, reference, runId, target, options.step);
156
- }
157
- if (options.step) {
158
- throw new EigenpalError(
159
- '`step` is only supported when both runs are workflow runs. Agent runs do not have workflow steps.',
160
- { status: 400 }
161
- );
162
- }
163
- if (isWorkflowRun(reference) || isWorkflowRun(target)) {
164
- throw new EigenpalError(
165
- 'Mixed workflow/agent comparisons are not supported. Compare two workflow runs or two agent runs.',
166
- { status: 400 }
167
- );
168
- }
169
- return compareArtifactRuns(
170
- referenceRunId,
171
- reference,
172
- runId,
173
- target,
174
- mode,
175
- Boolean(options.normalizeDates)
129
+ async usage(runId: string, options: SignalOptions = {}): Promise<RunsUsageGetResponse> {
130
+ return this.dispatch(() =>
131
+ runsUsageGet({ client: this.client, path: { id: runId }, signal: options.signal })
176
132
  );
177
133
  }
178
134
 
179
- async connect(runId: string, options: SignalOptions = {}): Promise<RunsConnectResponse> {
135
+ async steps(runId: string, options: SignalOptions = {}): Promise<RunsStepsListResponse> {
180
136
  return this.dispatch(() =>
181
- runsConnect({ client: this.client, path: { id: runId }, signal: options.signal })
137
+ runsStepsList({ client: this.client, path: { id: runId }, signal: options.signal })
182
138
  );
183
139
  }
184
140
 
185
- async definition(runId: string, options: SignalOptions = {}): Promise<RunDefinitionResponse> {
141
+ async events(runId: string, options: SignalOptions = {}): Promise<RunsEventsListResponse> {
186
142
  return this.dispatch(() =>
187
- runsDefinitionGet({ client: this.client, path: { id: runId }, signal: options.signal })
143
+ runsEventsList({ client: this.client, path: { id: runId }, signal: options.signal })
188
144
  );
189
145
  }
190
146
  }
191
147
 
192
- type RunRecord = Record<string, unknown>;
193
- type ComparisonMode = 'expected' | 'baseline';
194
-
195
- export type RunComparisonReport = {
196
- status: 'pass' | 'fail';
197
- runId: string;
198
- comparedWithRunId: string;
199
- mode?: ComparisonMode;
200
- steps?: Array<Record<string, unknown>>;
201
- jsonDifferences?: Array<Record<string, string>>;
202
- matchedFiles?: Array<Record<string, string>>;
203
- missingFiles?: string[];
204
- extraFiles?: string[];
205
- warnings?: string[];
206
- };
207
-
208
- function isWorkflowRun(run: unknown): run is RunRecord {
209
- return isRecord(run) && run.type === 'workflow';
210
- }
211
-
212
- function isRecord(value: unknown): value is RunRecord {
213
- return value != null && typeof value === 'object' && !Array.isArray(value);
214
- }
215
-
216
- function runExecution(run: RunRecord): RunRecord {
217
- return isRecord(run.execution) ? run.execution : {};
218
- }
219
-
220
- function runResult(run: RunRecord): RunRecord {
221
- return isRecord(run.result) ? run.result : {};
222
- }
223
-
224
148
  export function runOutput(run: unknown): unknown {
225
- if (!isRecord(run)) return undefined;
226
- if (run.output !== undefined) return run.output;
227
- return runResult(run).output;
149
+ return isRecord(run) ? run.output : undefined;
228
150
  }
229
151
 
230
152
  export function runUsage(run: unknown): unknown {
@@ -235,150 +157,28 @@ export function runExecutionDetails(run: unknown): unknown {
235
157
  return isRecord(run) ? run.execution : undefined;
236
158
  }
237
159
 
238
- function workflowSteps(run: RunRecord): unknown[] {
239
- const steps = runExecution(run).steps;
240
- return Array.isArray(steps) ? steps : [];
241
- }
242
-
243
- function agentOutputFiles(run: RunRecord): unknown[] {
244
- const rawFiles = runExecution(run).files;
245
- const files: RunRecord = isRecord(rawFiles) ? rawFiles : {};
246
- return Array.isArray(files.output) ? files.output : [];
247
- }
248
-
249
- function agentExpected(run: RunRecord): RunRecord {
250
- const expected = runExecution(run).expected;
251
- return isRecord(expected) ? expected : {};
252
- }
253
-
254
- function compareWorkflowRuns(
255
- referenceRunId: string,
256
- reference: RunRecord,
257
- runId: string,
258
- target: RunRecord,
259
- stepFilter?: string
260
- ): RunComparisonReport {
261
- const wanted = stepFilter
262
- ?.split(',')
263
- .map((step) => step.trim())
264
- .filter(Boolean);
265
- const targetSteps = new Map(
266
- workflowSteps(target)
267
- .filter(isRecord)
268
- .map((step) => [String(step.stepName ?? step.name ?? step.id ?? ''), step])
269
- );
270
- const steps = workflowSteps(reference)
271
- .filter(isRecord)
272
- .filter(
273
- (step) => !wanted?.length || wanted.includes(String(step.stepName ?? step.name ?? step.id))
274
- )
275
- .map((referenceStep) => {
276
- const stepName = String(
277
- referenceStep.stepName ?? referenceStep.name ?? referenceStep.id ?? ''
278
- );
279
- const targetStep = targetSteps.get(stepName);
280
- const referenceOutput = referenceStep.outputData ?? referenceStep.output;
281
- const targetOutput = targetStep?.outputData ?? targetStep?.output;
282
- return {
283
- stepName,
284
- referenceStatus: String(referenceStep.status ?? ''),
285
- targetStatus: String(targetStep?.status ?? 'missing'),
286
- outputState: stableJson(referenceOutput) === stableJson(targetOutput) ? 'match' : 'diff',
287
- };
288
- });
289
- return {
290
- status: steps.every((step) => step.targetStatus !== 'missing' && step.outputState === 'match')
291
- ? 'pass'
292
- : 'fail',
293
- runId,
294
- comparedWithRunId: referenceRunId,
295
- steps,
296
- };
297
- }
298
-
299
- function compareArtifactRuns(
300
- referenceRunId: string,
301
- reference: unknown,
302
- runId: string,
303
- target: unknown,
304
- mode: ComparisonMode,
305
- normalizeDates: boolean
306
- ): RunComparisonReport {
307
- const referenceRun = isRecord(reference) ? reference : {};
308
- const targetRun = isRecord(target) ? target : {};
309
- const expectedValue =
310
- mode === 'baseline' ? runOutput(referenceRun) : agentExpected(referenceRun).output;
311
- const expectedFiles =
312
- mode === 'baseline'
313
- ? names(agentOutputFiles(referenceRun))
314
- : names(agentExpected(referenceRun).files);
315
- const outputFiles = names(agentOutputFiles(targetRun));
316
- const missing = expectedFiles.filter(
317
- (name) =>
318
- !outputFiles.some(
319
- (out) => comparableName(out, normalizeDates) === comparableName(name, normalizeDates)
320
- )
321
- );
322
- const extra = outputFiles.filter(
323
- (name) =>
324
- !expectedFiles.some(
325
- (exp) => comparableName(exp, normalizeDates) === comparableName(name, normalizeDates)
326
- )
327
- );
328
- const matched = expectedFiles
329
- .filter((name) => !missing.includes(name))
330
- .map((name) => ({
331
- expected: name,
332
- actual:
333
- outputFiles.find(
334
- (out) => comparableName(out, normalizeDates) === comparableName(name, normalizeDates)
335
- ) ?? name,
336
- }));
337
- const jsonDifferences = diffJson(expectedValue, runOutput(targetRun));
338
- return {
339
- status:
340
- jsonDifferences.length === 0 && missing.length === 0 && extra.length === 0 ? 'pass' : 'fail',
341
- runId,
342
- comparedWithRunId: referenceRunId,
343
- mode,
344
- jsonDifferences,
345
- matchedFiles: matched,
346
- missingFiles: missing,
347
- extraFiles: extra,
348
- };
349
- }
350
-
351
- function names(value: unknown): string[] {
352
- if (!Array.isArray(value)) return [];
353
- return value.map((item) => (isRecord(item) ? String(item.name ?? '') : '')).filter(Boolean);
354
- }
355
-
356
- function comparableName(value: string, normalizeDates: boolean): string {
357
- if (!normalizeDates) return value;
358
- return value.replace(/\d{4}-\d{2}-\d{2}/g, '<date>').replace(/\d{8}/g, '<date>');
359
- }
160
+ export class RunsArtifactsResource {
161
+ constructor(
162
+ private readonly client: Client,
163
+ private readonly dispatch: Dispatch
164
+ ) {}
360
165
 
361
- function stableJson(value: unknown): string {
362
- return JSON.stringify(value ?? null);
363
- }
166
+ async list(runId: string, options: SignalOptions = {}): Promise<RunsArtifactsListResponse> {
167
+ return this.dispatch(() =>
168
+ runsArtifactsList({ client: this.client, path: { id: runId }, signal: options.signal })
169
+ );
170
+ }
364
171
 
365
- function diffJson(
366
- expected: unknown,
367
- actual: unknown,
368
- basePath = '$'
369
- ): Array<Record<string, string>> {
370
- if (expected == null) return [];
371
- if (Object.is(expected, actual)) return [];
372
- if (isRecord(expected) && isRecord(actual)) {
373
- const keys = new Set([...Object.keys(expected), ...Object.keys(actual)]);
374
- return [...keys].flatMap((key) => {
375
- const next = `${basePath}.${key}`;
376
- if (!(key in actual)) return [{ path: next, type: 'missing' }];
377
- if (!(key in expected)) return [{ path: next, type: 'extra' }];
378
- return diffJson(expected[key], actual[key], next);
172
+ async download(runId: string, path: string, options: SignalOptions = {}): Promise<Blob> {
173
+ return this.dispatch(async () => {
174
+ const response = await runsArtifactsGet({
175
+ client: this.client,
176
+ path: { id: runId, path },
177
+ signal: options.signal,
178
+ });
179
+ return response as OperationResult<Blob>;
379
180
  });
380
181
  }
381
- return [{ path: basePath, type: 'changed' }];
382
182
  }
383
183
 
384
184
  export class RunsFeedbackResource {
@@ -395,212 +195,126 @@ export class RunsFeedbackResource {
395
195
 
396
196
  async update(
397
197
  runId: string,
398
- body: RunsFeedbackUpdateData['body'],
198
+ body: Record<string, unknown>,
399
199
  options: SignalOptions = {}
400
200
  ): Promise<RunsFeedbackUpdateResponse> {
401
201
  return this.dispatch(() =>
402
202
  runsFeedbackUpdate({
403
203
  client: this.client,
404
204
  path: { id: runId },
405
- body,
205
+ body: body as never,
406
206
  signal: options.signal,
407
207
  })
408
208
  );
409
209
  }
410
210
 
411
- async resolve(
412
- runId: string,
413
- body: Omit<NonNullable<RunsFeedbackUpdateData['body']>, 'status'> = {},
414
- options: SignalOptions = {}
415
- ): Promise<RunsFeedbackUpdateResponse> {
416
- return this.update(runId, { ...body, status: 'resolved' }, options);
417
- }
418
-
419
211
  async clear(runId: string, options: SignalOptions = {}): Promise<RunsFeedbackClearResponse> {
420
212
  return this.dispatch(() =>
421
213
  runsFeedbackClear({ client: this.client, path: { id: runId }, signal: options.signal })
422
214
  );
423
215
  }
424
- }
425
216
 
426
- export class RunsExpectedResource {
427
- constructor(
428
- private readonly client: Client,
429
- private readonly dispatch: Dispatch
430
- ) {}
431
-
432
- async list(runId: string, options: SignalOptions = {}): Promise<RunsExpectedGetResponse> {
217
+ async listExpected(
218
+ runId: string,
219
+ options: SignalOptions = {}
220
+ ): Promise<RunsFeedbackExpectedGetResponse> {
433
221
  return this.dispatch(() =>
434
- runsExpectedGet({ client: this.client, path: { id: runId }, signal: options.signal })
222
+ runsFeedbackExpectedGet({ client: this.client, path: { id: runId }, signal: options.signal })
435
223
  );
436
224
  }
437
225
 
438
- async copyOutput(
226
+ async copyOutputToExpected(
439
227
  runId: string,
440
- body: RunsExpectedCreateData['body'],
441
- options: SignalOptions = {}
442
- ): Promise<RunsExpectedCreateResponse> {
228
+ outputFileName: string,
229
+ options: { expectedName?: string; signal?: AbortSignal } = {}
230
+ ): Promise<RunsFeedbackExpectedCreateResponse> {
443
231
  return this.dispatch(() =>
444
- runsExpectedCreate({
232
+ runsFeedbackExpectedCreate({
445
233
  client: this.client,
446
234
  path: { id: runId },
447
- body,
235
+ body: {
236
+ outputFileName,
237
+ ...(options.expectedName ? { expectedName: options.expectedName } : {}),
238
+ },
448
239
  signal: options.signal,
449
240
  })
450
241
  );
451
242
  }
452
243
 
453
- async upload(
244
+ async uploadExpected(
454
245
  runId: string,
455
- file: Blob,
456
- options: { name?: string; filename?: string; signal?: AbortSignal } = {}
457
- ): Promise<RunsExpectedCreateResponse> {
458
- const form = new FormData();
459
- if (options.filename) form.append('file', file, options.filename);
460
- else form.append('file', file);
461
- if (options.name) form.append('name', options.name);
246
+ file: FileInput,
247
+ options: { name?: string; signal?: AbortSignal } = {}
248
+ ): Promise<RunsFeedbackExpectedCreateResponse> {
249
+ const formData = await buildSingleFileMultipart(file, options.name);
462
250
  return this.dispatch(
463
251
  () =>
464
252
  this.client.post({
465
- url: '/api/v1/runs/{id}/expected',
253
+ url: '/api/v1/runs/{id}/feedback/expected',
466
254
  path: { id: runId },
467
- body: form,
255
+ body: formData,
256
+ bodySerializer: null,
257
+ headers: { 'Content-Type': null },
468
258
  signal: options.signal,
469
- }) as Promise<OperationResult<RunsExpectedCreateResponse>>
259
+ }) as Promise<OperationResult<RunsFeedbackExpectedCreateResponse>>
470
260
  );
471
261
  }
472
262
 
473
- async rename(
263
+ async downloadExpected(
474
264
  runId: string,
475
265
  filename: string,
476
- body: RunsExpectedFileUpdateData['body'],
477
266
  options: SignalOptions = {}
478
- ): Promise<RunsExpectedFileUpdateResponse> {
479
- return this.dispatch(() =>
480
- runsExpectedFileUpdate({
267
+ ): Promise<Blob> {
268
+ return this.dispatch(async () => {
269
+ const response = await runsFeedbackExpectedFileGet({
481
270
  client: this.client,
482
271
  path: { id: runId, filename },
483
- body,
484
272
  signal: options.signal,
485
- })
486
- );
273
+ });
274
+ return response as OperationResult<Blob>;
275
+ });
487
276
  }
488
277
 
489
- async delete(
278
+ async renameExpected(
490
279
  runId: string,
491
280
  filename: string,
281
+ newFilename: string,
492
282
  options: SignalOptions = {}
493
- ): Promise<RunsExpectedFileDeleteResponse> {
283
+ ): Promise<RunsFeedbackExpectedFileUpdateResponse> {
494
284
  return this.dispatch(() =>
495
- runsExpectedFileDelete({
285
+ runsFeedbackExpectedFileUpdate({
496
286
  client: this.client,
497
287
  path: { id: runId, filename },
288
+ body: { name: newFilename },
498
289
  signal: options.signal,
499
290
  })
500
291
  );
501
292
  }
502
293
 
503
- async download(runId: string, filename: string, options: SignalOptions = {}): Promise<Blob> {
504
- return downloadBlob(
505
- () =>
506
- runsExpectedFileGet({
507
- client: this.client,
508
- path: { id: runId, filename },
509
- parseAs: 'blob',
510
- signal: options.signal,
511
- }) as Promise<OperationResult<Blob>>
512
- );
513
- }
514
- }
515
-
516
- export class RunsFilesResource {
517
- constructor(
518
- private readonly client: Client,
519
- private readonly dispatch: Dispatch
520
- ) {}
521
-
522
- async list(runId: string, options: SignalOptions = {}): Promise<RunsFilesListResponse> {
523
- return this.dispatch(() =>
524
- runsFilesList({ client: this.client, path: { id: runId }, signal: options.signal })
525
- );
526
- }
527
-
528
- async upload(
529
- runId: string,
530
- body: RunsFilesUploadData['body'],
531
- options: SignalOptions = {}
532
- ): Promise<RunsFilesUploadResponse> {
533
- return this.dispatch(() =>
534
- runsFilesUpload({ client: this.client, path: { id: runId }, body, signal: options.signal })
535
- );
536
- }
537
-
538
- async delete(
294
+ async deleteExpected(
539
295
  runId: string,
540
- fileId: string,
296
+ filename: string,
541
297
  options: SignalOptions = {}
542
- ): Promise<RunsFilesDeleteResponse> {
298
+ ): Promise<RunsFeedbackExpectedFileDeleteResponse> {
543
299
  return this.dispatch(() =>
544
- runsFilesDelete({
300
+ runsFeedbackExpectedFileDelete({
545
301
  client: this.client,
546
- path: { id: runId, fileId },
302
+ path: { id: runId, filename },
547
303
  signal: options.signal,
548
304
  })
549
305
  );
550
306
  }
551
307
  }
552
308
 
553
- export class RunsArtifactsResource {
309
+ export class RunsScoresResource {
554
310
  constructor(
555
311
  private readonly client: Client,
556
312
  private readonly dispatch: Dispatch
557
313
  ) {}
558
314
 
559
- async list(runId: string, options: SignalOptions = {}): Promise<RunArtifactsResponse> {
560
- const { signal } = options;
315
+ async list(runId: string, options: SignalOptions = {}): Promise<RunsScoresListResponse> {
561
316
  return this.dispatch(() =>
562
- runsArtifactsList({ client: this.client, path: { id: runId }, signal })
563
- );
564
- }
565
-
566
- async download(runId: string, path: string, options: SignalOptions = {}): Promise<Blob> {
567
- return downloadBlob(
568
- () =>
569
- this.client.get({
570
- url: `/api/v1/runs/${encodeURIComponent(runId)}/artifacts/${encodeArtifactPath(path)}`,
571
- parseAs: 'blob',
572
- signal: options.signal,
573
- }) as Promise<OperationResult<Blob>>
574
- );
575
- }
576
-
577
- async downloadZip(
578
- runId: string,
579
- options: { files?: string; token?: string; signal?: AbortSignal } = {}
580
- ): Promise<Blob> {
581
- const { signal, ...query } = options;
582
- return downloadBlob(
583
- () =>
584
- runsFilesZipGet({
585
- client: this.client,
586
- path: { id: runId },
587
- query,
588
- parseAs: 'blob',
589
- signal,
590
- }) as Promise<OperationResult<Blob>>
591
- );
592
- }
593
- }
594
-
595
- export class RunsComparisonResource {
596
- constructor(
597
- private readonly client: Client,
598
- private readonly dispatch: Dispatch
599
- ) {}
600
-
601
- async get(runId: string, options: SignalOptions = {}): Promise<RunsComparisonGetResponse> {
602
- return this.dispatch(() =>
603
- runsComparisonGet({ client: this.client, path: { id: runId }, signal: options.signal })
317
+ runsScoresList({ client: this.client, path: { id: runId }, signal: options.signal })
604
318
  );
605
319
  }
606
320
  }
@@ -618,16 +332,6 @@ export class RunsTraceResource {
618
332
  }
619
333
  }
620
334
 
621
- async function downloadBlob(call: () => Promise<OperationResult<Blob>>): Promise<Blob> {
622
- const result = await call();
623
- if (result.response?.ok && result.data instanceof Blob) {
624
- return result.data;
625
- }
626
- throw new EigenpalError('Failed to download run artifact.', {
627
- status: result.response?.status ?? 0,
628
- });
629
- }
630
-
631
- function encodeArtifactPath(path: string): string {
632
- return path.split('/').map(encodeURIComponent).join('/');
335
+ function isRecord(value: unknown): value is Record<string, unknown> {
336
+ return value != null && typeof value === 'object' && !Array.isArray(value);
633
337
  }