@springbrand/eval-harness 0.0.0-stage → 0.1.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.
- package/README.md +135 -2
- package/dist/index.d.ts +234 -0
- package/dist/index.js +294 -0
- package/package.json +27 -4
package/README.md
CHANGED
|
@@ -1,3 +1,136 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @springbrand/eval-harness
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
SP's service contract for Eval-managed ordinary Chats. This package owns only
|
|
4
|
+
wire validation, stable request facts and service route names. Inbox owns Chat
|
|
5
|
+
creation and routing, Severn owns Submission and canonical Session history,
|
|
6
|
+
Workspace owns files, and API owns billing settlements. Eval Project, Dataset,
|
|
7
|
+
Sampling and scoring remain in `eval-platform`.
|
|
8
|
+
|
|
9
|
+
The Eval Run Worker authenticates with a dedicated service token. Its requests
|
|
10
|
+
include the owning user ID because an SP Inbox is addressed by user. The Chat
|
|
11
|
+
creation facts and each Submission operation key are immutable. Initialization
|
|
12
|
+
receives Eval-provided bundle/resource IDs and their content: material files go
|
|
13
|
+
to the target Chat Workspace; canonical JSON or JSONL context may be imported into
|
|
14
|
+
the Chat Session before the first Submission and need not be copied to Workspace.
|
|
15
|
+
|
|
16
|
+
The service interface is implemented under `apps/agent/src/eval/`. The Agent
|
|
17
|
+
Worker requires the separately provisioned `EVAL_SP_SERVICE_TOKEN` secret and
|
|
18
|
+
the Run Worker sends it as `X-Eval-Service-Token`. No browser Origin is accepted.
|
|
19
|
+
The Eval Worker uses the independently deployed Eval SP origin. Its user ID is
|
|
20
|
+
part of the Agent Worker path because an SP Inbox is addressed by user.
|
|
21
|
+
That Agent Worker's `API_ORIGIN` and SpaceDO binding must point to the same
|
|
22
|
+
independent Eval SP deployment; the shared SP dev API and database are not used.
|
|
23
|
+
|
|
24
|
+
| Operation | Agent Worker route |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| Ensure the ordinary Chat | `PUT /internal/v1/eval-harness/users/{userId}/chats/{chatId}` |
|
|
27
|
+
| Initialize one Data sample's optional Session and materials | `POST /internal/v1/eval-harness/users/{userId}/chats/{chatId}/initialization` |
|
|
28
|
+
| Submit one Prompt | `POST /internal/v1/eval-harness/users/{userId}/chats/{chatId}/submissions` |
|
|
29
|
+
| Recover a Submission by operation key | `GET /internal/v1/eval-harness/users/{userId}/chats/{chatId}/submissions/by-key/{key}` |
|
|
30
|
+
| Stop every unfinished Submission in this Eval Chat | `POST /internal/v1/eval-harness/users/{userId}/chats/{chatId}/submissions/stop` |
|
|
31
|
+
| Observe a Submission | `WS /internal/v1/eval-harness/users/{userId}/chats/{chatId}/submissions/{submissionId}/events` |
|
|
32
|
+
| Collect the complete artifact list and trajectory reference | `GET /internal/v1/eval-harness/users/{userId}/chats/{chatId}/output` |
|
|
33
|
+
| Collect raw resource facts | `GET /internal/v1/eval-harness/users/{userId}/chats/{chatId}/resources/by-key/{key}` |
|
|
34
|
+
| Export: list produced artifacts with size and media type | `GET /internal/v1/eval-harness/users/{userId}/chats/{chatId}/evidence/artifacts` |
|
|
35
|
+
| Export: read one produced file's bytes | `GET /internal/v1/eval-harness/users/{userId}/chats/{chatId}/evidence/files?path=` |
|
|
36
|
+
| Export: page the complete trajectory, oldest first | `GET /internal/v1/eval-harness/users/{userId}/chats/{chatId}/evidence/trajectory?afterSeq=&limit=` |
|
|
37
|
+
| Import: write one evidence file into an Evaluator's own Space | `PUT /internal/v1/eval-harness/users/{userId}/chats/{chatId}/evidence/files?path=` |
|
|
38
|
+
|
|
39
|
+
The initialization body includes the Data sample and, only when referenced by
|
|
40
|
+
that sample, `initialSession: {bundleId, sessionId, context?: {format, content}}`
|
|
41
|
+
and/or `initialMaterials: [{bundleId, materialId, files}]`. `content` is canonical
|
|
42
|
+
Session JSON or JSONL; each material file supplies its path, media type and
|
|
43
|
+
base64 bytes. The material list must match the sample's `initialMaterials`
|
|
44
|
+
references position by position, without duplicates. Supplied Session context is
|
|
45
|
+
imported into the Chat before the Prompt and only files are written to SpaceDO,
|
|
46
|
+
each material under its own `evalMaterialRoot`. A sample may specify either
|
|
47
|
+
source, both, or neither. There is no Dataset-level source binding. An Evaluator
|
|
48
|
+
initialization must carry `evaluationOutputSchema: {content}`, written as UTF-8
|
|
49
|
+
`application/schema+json` to `EVAL_OUTPUT_SCHEMA_PATH`
|
|
50
|
+
(`/evaluation-output.schema.json`); a Subject Chat rejects it. Evaluators do not
|
|
51
|
+
import an initial Session. Schema validity and result validation belong to Eval
|
|
52
|
+
Platform; SP preserves the supplied text. `evalMaterialFilesSchema`
|
|
53
|
+
validates one material's `EvalMaterialFile` list: at most `EVAL_MATERIAL_MAX_FILES`, with unique
|
|
54
|
+
paths. One initialization carries at most `EVAL_INITIAL_FILE_MAX_BYTES` per file
|
|
55
|
+
and `EVAL_INITIALIZATION_MAX_BYTES` in total; size violations are Zod `too_big`
|
|
56
|
+
issues. `evalMaterialFilesByteSize` returns one material's decoded bytes exactly as
|
|
57
|
+
that total counts them. `readEvalCanonicalContext` accepts at most
|
|
58
|
+
`EVAL_SESSION_CONTENT_MAX_CHARS` characters and `EVAL_SESSION_MAX_ENTRIES`
|
|
59
|
+
entries. `EVAL_INITIALIZATION_BODY_MAX_BYTES` bounds transport JSON, accounting
|
|
60
|
+
for base64 material bytes, escaped Session or Schema text, and JSON framing.
|
|
61
|
+
Eval consumes these constants instead of copying the values. Its result is
|
|
62
|
+
`evalInitializationResultSchema`: `{manifestHash, target, materials:
|
|
63
|
+
[{bundleId, materialId, rootPath}], evaluationOutputSchemaPath?}` in request
|
|
64
|
+
order; replaying the same request returns the stored result.
|
|
65
|
+
|
|
66
|
+
An Evaluator is an ordinary Eval Chat with its own Session, Submission and
|
|
67
|
+
Space; its creation facts add only `evaluationId`. It never reads or writes the
|
|
68
|
+
Subject's Space. Eval Platform exports a finished Subject's evidence through the
|
|
69
|
+
read-only export routes and freezes it as a content-addressed bundle, then imports
|
|
70
|
+
that bundle into the Evaluator's own Space under `/evidence` before the first
|
|
71
|
+
Submission. Export routes answer only after the Chat's last Submission ended and
|
|
72
|
+
its whole trajectory was delivered (409 before that). The artifact list covers
|
|
73
|
+
files the Agent produced in its own Space, excluding `/reference`,
|
|
74
|
+
`/initial-materials`, `/userspace`, `/evidence` and uploads; a single file crosses
|
|
75
|
+
one Durable Object RPC, so files over 25 MB are refused with 413. Trajectory pages
|
|
76
|
+
come straight from `trajectory_events` with a forward `afterSeq` cursor
|
|
77
|
+
(`nextAfterSeq` is null after the last page). An import `PUT` carries the raw
|
|
78
|
+
bytes, their `Content-Type` and `X-Eval-Content-Sha256: <hex>`; SP verifies the
|
|
79
|
+
hash, writes `/evidence/<path>` and returns `{path, size, sha256}`. Only an
|
|
80
|
+
Evaluator imports; an identical repeat is a no-op, different content is a 409,
|
|
81
|
+
and imports stop with the Chat's stop latch.
|
|
82
|
+
|
|
83
|
+
The Evaluator Workspace layout is one public contract, exported by this package:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
/initial-materials/{bundleId}/{materialId}/... # Evaluator's own materials
|
|
87
|
+
/evidence/subject-inputs/{bundleId}/{materialId}/... # Subject's original input materials
|
|
88
|
+
/evidence/artifacts/{original-relative-path} # Subject's produced files
|
|
89
|
+
/evidence/trajectory/events-000001.jsonl # Complete raw trajectory, ordered parts
|
|
90
|
+
/evidence/manifest.json # Evidence bundle inventory and provenance
|
|
91
|
+
/evaluation-output.schema.json # Evaluation output format
|
|
92
|
+
/output/result.json # Evaluator's scored result
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`EVAL_EVIDENCE_PATHS` names the bundle-relative directories. The import route takes
|
|
96
|
+
paths **without** the `/evidence` prefix: `/subject-inputs/...`, `/artifacts/...`,
|
|
97
|
+
`/trajectory/...` or `/manifest.json`. Other paths are rejected. The exported
|
|
98
|
+
`evalSubjectInputEvidencePath`, `evalArtifactEvidencePath` and
|
|
99
|
+
`evalTrajectoryEvidencePath` build those import paths; `evalEvidencePath` turns
|
|
100
|
+
an import path into its absolute Workspace path. IDs are encoded as individual
|
|
101
|
+
path segments and original file hierarchy is preserved, so equal basenames in
|
|
102
|
+
different materials or evidence categories cannot overwrite each other.
|
|
103
|
+
|
|
104
|
+
Eval Platform copies Subject inputs from the original immutable Material bundles
|
|
105
|
+
referenced by this Sampling, not from the Subject's potentially edited working
|
|
106
|
+
files. SP continues to exclude these inputs from artifact exports. Eval Platform
|
|
107
|
+
collects **every** trajectory page until `nextAfterSeq` is null, retaining raw
|
|
108
|
+
`{ingestSeq,event}` records in order; it splits oversized JSONL at event boundaries
|
|
109
|
+
so every part fits `EVAL_EVIDENCE_FILE_MAX_BYTES`. Eval Platform owns the frozen
|
|
110
|
+
bundle, manifest body, file hashes and preparation retries. It imports all files,
|
|
111
|
+
verifies their receipts and uploads `manifest.json` last, then submits its Prompt
|
|
112
|
+
with explicit evidence, Schema and result paths.
|
|
113
|
+
|
|
114
|
+
SP requires completed initialization before evidence import, and a nonempty
|
|
115
|
+
evidence manifest before an Evaluator's first Submission. Input writes and
|
|
116
|
+
Submission admission are serialized; the first reserved Submission durably closes
|
|
117
|
+
evidence imports, including after a DO restart. Replaying initialization returns
|
|
118
|
+
its saved result without restoring files. Stop closes admission immediately and
|
|
119
|
+
waits for accepted input writes and submissions. Evidence, initial materials and
|
|
120
|
+
the fixed Schema input path are never exported as produced artifacts. SP does not
|
|
121
|
+
interpret the manifest or implement Eval Platform's bundle assembly or scoring.
|
|
122
|
+
|
|
123
|
+
Eval Platform writes the Evaluator instructions into the Prompt; SP submits it
|
|
124
|
+
unchanged. The Evaluator's `output` adds `structuredOutput: {path, content,
|
|
125
|
+
contentHash}` with the raw UTF-8 text of `/output/result.json` in its own Space
|
|
126
|
+
(at most 1 MB, `contentHash` is `sha256:<hex>`); it is omitted when the Evaluator
|
|
127
|
+
wrote no result file.
|
|
128
|
+
The Chat observer WebSocket carries status only. Browser Chat input and writes
|
|
129
|
+
are rejected. SP API provides its account, Agent Config, and billing facts.
|
|
130
|
+
The service-only stop route delegates to the ordinary Chat Submission lifecycle:
|
|
131
|
+
it persists an Eval Chat stop latch, waits for already accepted submit calls,
|
|
132
|
+
interrupts active work, and returns after terminal status is recorded. New
|
|
133
|
+
initialization and Submission requests are rejected after the latch is saved,
|
|
134
|
+
including after a DO restart.
|
|
135
|
+
It refuses a Chat without an Eval binding. Repeating stop after all Submissions
|
|
136
|
+
finish returns `{ "ok": false }` without changing history.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const EVAL_SERVICE_HEADER = "X-Eval-Service-Token";
|
|
3
|
+
export declare const EVAL_HARNESS_PATH = "/internal/v1/eval-harness";
|
|
4
|
+
export declare const evalEnsureChatSchema: z.ZodObject<{
|
|
5
|
+
chatId: z.ZodUUID;
|
|
6
|
+
role: z.ZodEnum<{
|
|
7
|
+
subject: "subject";
|
|
8
|
+
evaluator: "evaluator";
|
|
9
|
+
}>;
|
|
10
|
+
framework: z.ZodLiteral<"sp">;
|
|
11
|
+
samplingId: z.ZodString;
|
|
12
|
+
projectId: z.ZodString;
|
|
13
|
+
agentConfig: z.ZodObject<{
|
|
14
|
+
ownerUserId: z.ZodUUID;
|
|
15
|
+
userAgentId: z.ZodUUID;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
evaluationId: z.ZodOptional<z.ZodString>;
|
|
18
|
+
runtime: z.ZodOptional<z.ZodObject<{
|
|
19
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
20
|
+
}, z.core.$strict>>;
|
|
21
|
+
}, z.core.$strict>;
|
|
22
|
+
export declare const EVAL_INITIAL_FILE_MAX_BYTES = 5000000;
|
|
23
|
+
export declare const EVAL_INITIALIZATION_MAX_BYTES = 20000000;
|
|
24
|
+
export declare const EVAL_MATERIAL_MAX_FILES = 500;
|
|
25
|
+
export declare const EVAL_SESSION_CONTENT_MAX_CHARS = 2000000;
|
|
26
|
+
export declare const EVAL_SESSION_MAX_ENTRIES = 10000;
|
|
27
|
+
export declare const EVAL_OUTPUT_SCHEMA_PATH = "/evaluation-output.schema.json";
|
|
28
|
+
export declare const EVAL_INITIAL_MATERIALS_ROOT = "/initial-materials";
|
|
29
|
+
/** Subject Session JSON and Evaluator Schema JSON can expand to six bytes per character. */
|
|
30
|
+
export declare const EVAL_INITIALIZATION_BODY_MAX_BYTES: number;
|
|
31
|
+
/** Decoded bytes of validated Material files, counted exactly as the initialization budget counts them. */
|
|
32
|
+
export declare const evalMaterialFilesByteSize: (files: readonly {
|
|
33
|
+
readonly contentBase64: string;
|
|
34
|
+
}[]) => number;
|
|
35
|
+
declare const evalMaterialFileSchema: z.ZodObject<{
|
|
36
|
+
path: z.ZodString;
|
|
37
|
+
mediaType: z.ZodString;
|
|
38
|
+
contentBase64: z.ZodBase64;
|
|
39
|
+
}, z.core.$strict>;
|
|
40
|
+
export declare const evalMaterialFilesSchema: z.ZodArray<z.ZodObject<{
|
|
41
|
+
path: z.ZodString;
|
|
42
|
+
mediaType: z.ZodString;
|
|
43
|
+
contentBase64: z.ZodBase64;
|
|
44
|
+
}, z.core.$strict>>;
|
|
45
|
+
export declare const evalInitialContextSchema: z.ZodObject<{
|
|
46
|
+
format: z.ZodEnum<{
|
|
47
|
+
json: "json";
|
|
48
|
+
jsonl: "jsonl";
|
|
49
|
+
}>;
|
|
50
|
+
content: z.ZodString;
|
|
51
|
+
}, z.core.$strict>;
|
|
52
|
+
export declare const evalInitializationSchema: z.ZodObject<{
|
|
53
|
+
idempotencyKey: z.ZodString;
|
|
54
|
+
data: z.ZodIntersection<z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodObject<{
|
|
55
|
+
userPrompt: z.ZodString;
|
|
56
|
+
}, z.core.$strip>>;
|
|
57
|
+
initialSession: z.ZodOptional<z.ZodObject<{
|
|
58
|
+
bundleId: z.ZodString;
|
|
59
|
+
sessionId: z.ZodString;
|
|
60
|
+
context: z.ZodOptional<z.ZodObject<{
|
|
61
|
+
format: z.ZodEnum<{
|
|
62
|
+
json: "json";
|
|
63
|
+
jsonl: "jsonl";
|
|
64
|
+
}>;
|
|
65
|
+
content: z.ZodString;
|
|
66
|
+
}, z.core.$strict>>;
|
|
67
|
+
}, z.core.$strict>>;
|
|
68
|
+
initialMaterials: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
69
|
+
bundleId: z.ZodString;
|
|
70
|
+
materialId: z.ZodString;
|
|
71
|
+
files: z.ZodArray<z.ZodObject<{
|
|
72
|
+
path: z.ZodString;
|
|
73
|
+
mediaType: z.ZodString;
|
|
74
|
+
contentBase64: z.ZodBase64;
|
|
75
|
+
}, z.core.$strict>>;
|
|
76
|
+
}, z.core.$strict>>>;
|
|
77
|
+
evaluationOutputSchema: z.ZodOptional<z.ZodObject<{
|
|
78
|
+
content: z.ZodString;
|
|
79
|
+
}, z.core.$strict>>;
|
|
80
|
+
}, z.core.$strict>;
|
|
81
|
+
export declare const evalInitializationResultSchema: z.ZodObject<{
|
|
82
|
+
manifestHash: z.ZodString;
|
|
83
|
+
target: z.ZodLiteral<"workspace">;
|
|
84
|
+
materials: z.ZodArray<z.ZodObject<{
|
|
85
|
+
bundleId: z.ZodString;
|
|
86
|
+
materialId: z.ZodString;
|
|
87
|
+
rootPath: z.ZodString;
|
|
88
|
+
}, z.core.$strict>>;
|
|
89
|
+
evaluationOutputSchemaPath: z.ZodExactOptional<z.ZodLiteral<"/evaluation-output.schema.json">>;
|
|
90
|
+
}, z.core.$strict>;
|
|
91
|
+
export declare const evalSubmitSchema: z.ZodObject<{
|
|
92
|
+
idempotencyKey: z.ZodString;
|
|
93
|
+
prompt: z.ZodString;
|
|
94
|
+
unattended: z.ZodLiteral<true>;
|
|
95
|
+
runtime: z.ZodOptional<z.ZodObject<{
|
|
96
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
97
|
+
}, z.core.$strict>>;
|
|
98
|
+
}, z.core.$strict>;
|
|
99
|
+
export type EvalEnsureChat = z.output<typeof evalEnsureChatSchema>;
|
|
100
|
+
export type EvalMaterialFile = z.output<typeof evalMaterialFileSchema>;
|
|
101
|
+
export type EvalInitialization = z.output<typeof evalInitializationSchema>;
|
|
102
|
+
export type EvalInitializationResult = z.output<typeof evalInitializationResultSchema>;
|
|
103
|
+
export type EvalSubmit = z.output<typeof evalSubmitSchema>;
|
|
104
|
+
export type EvalSubmissionReceipt = {
|
|
105
|
+
readonly submissionId: string;
|
|
106
|
+
readonly status: string;
|
|
107
|
+
readonly normalizedStatus: "queued" | "running" | "completed" | "failed" | "interrupted" | "cancelled";
|
|
108
|
+
readonly accepted: boolean;
|
|
109
|
+
readonly error?: string;
|
|
110
|
+
readonly retryable?: boolean;
|
|
111
|
+
readonly createdAt: number;
|
|
112
|
+
readonly completedAt?: number;
|
|
113
|
+
};
|
|
114
|
+
export declare const evalBillingResourcesSchema: z.ZodObject<{
|
|
115
|
+
usageEvents: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
116
|
+
billingSettlements: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
117
|
+
}, z.core.$strict>;
|
|
118
|
+
export type EvalBillingResources = z.output<typeof evalBillingResourcesSchema>;
|
|
119
|
+
export declare function projectEvalSubmission(input: {
|
|
120
|
+
readonly submissionId: string;
|
|
121
|
+
readonly status: string;
|
|
122
|
+
readonly accepted: boolean;
|
|
123
|
+
readonly error?: string;
|
|
124
|
+
readonly retryable?: boolean;
|
|
125
|
+
readonly createdAt: number;
|
|
126
|
+
readonly completedAt?: number;
|
|
127
|
+
}): EvalSubmissionReceipt;
|
|
128
|
+
export type EvalCanonicalContext = {
|
|
129
|
+
readonly entries: readonly {
|
|
130
|
+
readonly id: string;
|
|
131
|
+
readonly message: Readonly<Record<string, unknown>>;
|
|
132
|
+
readonly createdAt: number;
|
|
133
|
+
}[];
|
|
134
|
+
};
|
|
135
|
+
/** JSON stores one canonical snapshot; JSONL stores one canonical entry per line. */
|
|
136
|
+
export declare function readEvalCanonicalContext(input: z.output<typeof evalInitialContextSchema>): EvalCanonicalContext;
|
|
137
|
+
/** The one file an Evaluator writes its scored result to, in its own Space. */
|
|
138
|
+
export declare const EVAL_RESULT_FILE = "result.json";
|
|
139
|
+
export declare const EVAL_RESULT_PATH = "/output/result.json";
|
|
140
|
+
export declare const EVAL_RESULT_MAX_BYTES = 1000000;
|
|
141
|
+
/** The Evaluator result file exactly as written; Eval Platform parses and validates it. */
|
|
142
|
+
export type EvalStructuredOutput = {
|
|
143
|
+
readonly path: string;
|
|
144
|
+
readonly content: string;
|
|
145
|
+
readonly contentHash: string;
|
|
146
|
+
};
|
|
147
|
+
/** Reads the result file as raw UTF-8 text; any byte order mark and formatting are kept. */
|
|
148
|
+
export declare function readEvalStructuredOutput(path: string, bytes: Uint8Array): Promise<EvalStructuredOutput>;
|
|
149
|
+
/** The `output` route body; an Evaluator's `structuredOutput` is omitted when it wrote no result file. */
|
|
150
|
+
export type EvalEvidence = {
|
|
151
|
+
readonly status: "succeeded" | "failed";
|
|
152
|
+
readonly samplingId: string;
|
|
153
|
+
readonly evaluationId?: string;
|
|
154
|
+
readonly artifacts: readonly {
|
|
155
|
+
readonly artifactId: string;
|
|
156
|
+
readonly kind: string;
|
|
157
|
+
readonly path: string;
|
|
158
|
+
}[];
|
|
159
|
+
readonly trajectory: {
|
|
160
|
+
readonly trajectoryId: string;
|
|
161
|
+
readonly source: "subject" | "evaluator";
|
|
162
|
+
readonly path: string;
|
|
163
|
+
};
|
|
164
|
+
readonly structuredOutput?: EvalStructuredOutput;
|
|
165
|
+
readonly error?: string;
|
|
166
|
+
};
|
|
167
|
+
export declare function evalMaterialRoot(bundleId: string, materialId: string): string;
|
|
168
|
+
export declare function evalMaterialPath(root: string, path: string): string;
|
|
169
|
+
/** Where imported evidence lives in the Evaluator's own Space. */
|
|
170
|
+
export declare const EVAL_EVIDENCE_ROOT = "/evidence";
|
|
171
|
+
/** Bundle-relative paths, used by the import route; evalEvidencePath returns their Workspace paths. */
|
|
172
|
+
export declare const EVAL_EVIDENCE_PATHS: {
|
|
173
|
+
readonly subjectInputs: "/subject-inputs";
|
|
174
|
+
readonly artifacts: "/artifacts";
|
|
175
|
+
readonly trajectory: "/trajectory";
|
|
176
|
+
readonly manifest: "/manifest.json";
|
|
177
|
+
};
|
|
178
|
+
/** One exported or imported file crosses a single Durable Object RPC as bytes. */
|
|
179
|
+
export declare const EVAL_EVIDENCE_FILE_MAX_BYTES = 25000000;
|
|
180
|
+
export declare const EVAL_EVIDENCE_TRAJECTORY_PAGE_MAX = 200;
|
|
181
|
+
export declare const EVAL_EVIDENCE_SHA256_HEADER = "X-Eval-Content-Sha256";
|
|
182
|
+
/** One Subject artifact; its bytes are read separately so the inventory stays small. */
|
|
183
|
+
export declare const evalEvidenceArtifactSchema: z.ZodObject<{
|
|
184
|
+
path: z.ZodString;
|
|
185
|
+
size: z.ZodNumber;
|
|
186
|
+
mediaType: z.ZodString;
|
|
187
|
+
}, z.core.$strict>;
|
|
188
|
+
export type EvalEvidenceArtifact = z.output<typeof evalEvidenceArtifactSchema>;
|
|
189
|
+
export declare const evalEvidenceArtifactsSchema: z.ZodObject<{
|
|
190
|
+
artifacts: z.ZodArray<z.ZodObject<{
|
|
191
|
+
path: z.ZodString;
|
|
192
|
+
size: z.ZodNumber;
|
|
193
|
+
mediaType: z.ZodString;
|
|
194
|
+
}, z.core.$strict>>;
|
|
195
|
+
}, z.core.$strict>;
|
|
196
|
+
export type EvalEvidenceArtifacts = z.output<typeof evalEvidenceArtifactsSchema>;
|
|
197
|
+
/** Forward pages of the Chat's complete `trajectory_events`, oldest first. */
|
|
198
|
+
export type EvalEvidenceTrajectoryPage = {
|
|
199
|
+
readonly events: readonly {
|
|
200
|
+
readonly ingestSeq: number;
|
|
201
|
+
readonly event: object;
|
|
202
|
+
}[];
|
|
203
|
+
/** Pass as `afterSeq` for the next page; null once the last event was returned. */
|
|
204
|
+
readonly nextAfterSeq: number | null;
|
|
205
|
+
};
|
|
206
|
+
export declare function readEvalTrajectoryPageQuery(params: URLSearchParams): {
|
|
207
|
+
afterSeq: number;
|
|
208
|
+
limit: number;
|
|
209
|
+
};
|
|
210
|
+
/** A Space path for one evidence file; `relative` keeps the bundle's own layout below `/evidence`. */
|
|
211
|
+
export declare function evalEvidencePath(relative: string): string;
|
|
212
|
+
/** Original Subject inputs stay separate from produced artifacts and the Evaluator's own materials. */
|
|
213
|
+
export declare function evalSubjectInputEvidencePath(bundleId: string, materialId: string, path: string): string;
|
|
214
|
+
export declare function evalArtifactEvidencePath(path: string): string;
|
|
215
|
+
/** Positive part numbers preserve the complete raw JSONL trajectory's order. */
|
|
216
|
+
export declare function evalTrajectoryEvidencePath(part: number): string;
|
|
217
|
+
/** One raw evidence file imported into the Evaluator's own Space. */
|
|
218
|
+
export type EvalEvidenceFileInput = {
|
|
219
|
+
/** Bundle-relative path under one of EVAL_EVIDENCE_PATHS, without the /evidence prefix. */
|
|
220
|
+
readonly path: string;
|
|
221
|
+
readonly mediaType: string;
|
|
222
|
+
readonly sha256: string;
|
|
223
|
+
readonly bytes: Uint8Array;
|
|
224
|
+
};
|
|
225
|
+
/** The receipt for one imported file; identical repeats return the same receipt. */
|
|
226
|
+
export type EvalEvidenceFileReceipt = {
|
|
227
|
+
readonly path: string;
|
|
228
|
+
readonly size: number;
|
|
229
|
+
readonly sha256: string;
|
|
230
|
+
};
|
|
231
|
+
export declare function isEvalSha256(value: string | null): value is string;
|
|
232
|
+
/** Compare creation and operation facts without depending on JSON property order. */
|
|
233
|
+
export declare function stableEvalFacts(value: unknown): string;
|
|
234
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
// packages/eval-harness/src/index.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
// packages/utils/src/json.ts
|
|
5
|
+
function canonicalJsonStringify(value) {
|
|
6
|
+
return JSON.stringify(
|
|
7
|
+
value,
|
|
8
|
+
(_key, item) => item !== null && typeof item === "object" && !Array.isArray(item) ? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) : item
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// packages/utils/src/content-hash.ts
|
|
13
|
+
async function sha256Hex(value) {
|
|
14
|
+
const bytes = typeof value === "string" ? new TextEncoder().encode(value) : value;
|
|
15
|
+
const buffer = new ArrayBuffer(bytes.byteLength);
|
|
16
|
+
new Uint8Array(buffer).set(bytes);
|
|
17
|
+
const digest = await crypto.subtle.digest("SHA-256", buffer);
|
|
18
|
+
return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// packages/eval-harness/src/index.ts
|
|
22
|
+
var EVAL_SERVICE_HEADER = "X-Eval-Service-Token";
|
|
23
|
+
var EVAL_HARNESS_PATH = "/internal/v1/eval-harness";
|
|
24
|
+
var id = z.string().trim().min(1);
|
|
25
|
+
var uuid = z.uuid();
|
|
26
|
+
var evalEnsureChatSchema = z.strictObject({
|
|
27
|
+
chatId: uuid,
|
|
28
|
+
role: z.enum(["subject", "evaluator"]),
|
|
29
|
+
framework: z.literal("sp"),
|
|
30
|
+
samplingId: id,
|
|
31
|
+
projectId: id,
|
|
32
|
+
agentConfig: z.strictObject({ ownerUserId: uuid, userAgentId: uuid }),
|
|
33
|
+
/** Only an Evaluator carries it; the Evaluator still owns an ordinary Chat and its own Space. */
|
|
34
|
+
evaluationId: id.optional(),
|
|
35
|
+
runtime: z.strictObject({ timeoutMs: z.number().finite().positive().optional() }).optional()
|
|
36
|
+
}).superRefine((value, context) => {
|
|
37
|
+
if (value.role === "evaluator" !== (value.evaluationId !== void 0)) {
|
|
38
|
+
context.addIssue({ code: "custom", path: ["evaluationId"], message: "Evaluation ID must match role" });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
var EVAL_INITIAL_FILE_MAX_BYTES = 5e6;
|
|
42
|
+
var EVAL_INITIALIZATION_MAX_BYTES = 2e7;
|
|
43
|
+
var EVAL_MATERIAL_MAX_FILES = 500;
|
|
44
|
+
var EVAL_SESSION_CONTENT_MAX_CHARS = 2e6;
|
|
45
|
+
var EVAL_SESSION_MAX_ENTRIES = 1e4;
|
|
46
|
+
var EVAL_OUTPUT_SCHEMA_PATH = "/evaluation-output.schema.json";
|
|
47
|
+
var EVAL_INITIAL_MATERIALS_ROOT = "/initial-materials";
|
|
48
|
+
var EVAL_INITIALIZATION_BODY_MAX_BYTES = Math.max(
|
|
49
|
+
Math.ceil(EVAL_INITIALIZATION_MAX_BYTES * 4 / 3) + EVAL_SESSION_CONTENT_MAX_CHARS * 6,
|
|
50
|
+
Math.ceil((EVAL_INITIALIZATION_MAX_BYTES - EVAL_INITIAL_FILE_MAX_BYTES) * 4 / 3) + EVAL_INITIAL_FILE_MAX_BYTES * 6
|
|
51
|
+
) + 1e6;
|
|
52
|
+
var base64Bytes = (value) => value.length / 4 * 3 - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0);
|
|
53
|
+
var utf8Bytes = (value) => new TextEncoder().encode(value).byteLength;
|
|
54
|
+
var evalMaterialFilesByteSize = (files) => files.reduce((sum, file) => sum + base64Bytes(file.contentBase64), 0);
|
|
55
|
+
var tooBig = (context, maximum, message, path = []) => context.addIssue({ code: "too_big", origin: "file", maximum, inclusive: true, path, message });
|
|
56
|
+
var maxFileBytes = (bytes) => (value, context) => {
|
|
57
|
+
if (bytes(value) > EVAL_INITIAL_FILE_MAX_BYTES) tooBig(context, EVAL_INITIAL_FILE_MAX_BYTES, "File is too large");
|
|
58
|
+
};
|
|
59
|
+
var evalMaterialFileSchema = z.strictObject({
|
|
60
|
+
path: z.string().refine((path) => evalPathParts(path) !== null, "Invalid initial material path"),
|
|
61
|
+
mediaType: id,
|
|
62
|
+
contentBase64: z.base64().superRefine(maxFileBytes(base64Bytes))
|
|
63
|
+
});
|
|
64
|
+
var evalMaterialFilesSchema = z.array(evalMaterialFileSchema).max(EVAL_MATERIAL_MAX_FILES).superRefine((files, context) => {
|
|
65
|
+
const seen = /* @__PURE__ */ new Set();
|
|
66
|
+
files.forEach(({ path }, index) => {
|
|
67
|
+
if (seen.has(path)) context.addIssue({ code: "custom", path: [index, "path"], message: "Duplicate material path" });
|
|
68
|
+
seen.add(path);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
var evalInitialMaterialSchema = z.strictObject({
|
|
72
|
+
bundleId: id,
|
|
73
|
+
materialId: id,
|
|
74
|
+
files: evalMaterialFilesSchema
|
|
75
|
+
});
|
|
76
|
+
var evalInitialContextSchema = z.strictObject({
|
|
77
|
+
format: z.enum(["json", "jsonl"]),
|
|
78
|
+
content: z.string().min(1)
|
|
79
|
+
});
|
|
80
|
+
var evalInitializationSchema = z.strictObject({
|
|
81
|
+
idempotencyKey: id,
|
|
82
|
+
data: z.record(z.string(), z.unknown()).and(z.object({ userPrompt: z.string().trim().min(1) })),
|
|
83
|
+
initialSession: z.strictObject({
|
|
84
|
+
bundleId: id,
|
|
85
|
+
sessionId: id,
|
|
86
|
+
context: evalInitialContextSchema.optional()
|
|
87
|
+
}).optional(),
|
|
88
|
+
initialMaterials: z.array(evalInitialMaterialSchema).min(1).optional(),
|
|
89
|
+
evaluationOutputSchema: z.strictObject({
|
|
90
|
+
content: z.string().min(1).superRefine(maxFileBytes(utf8Bytes))
|
|
91
|
+
}).optional()
|
|
92
|
+
}).superRefine((value, context) => {
|
|
93
|
+
const session = value.data.initialSession;
|
|
94
|
+
const refs = value.data.initialMaterials;
|
|
95
|
+
const materials = value.initialMaterials;
|
|
96
|
+
if (session ? !value.initialSession || session.bundleId !== value.initialSession.bundleId || session.sessionId !== value.initialSession.sessionId : value.initialSession !== void 0) {
|
|
97
|
+
context.addIssue({ code: "custom", path: ["initialSession"], message: "Session content must match the Data reference" });
|
|
98
|
+
}
|
|
99
|
+
if (refs === void 0 ? materials !== void 0 : !Array.isArray(refs) || refs.length !== materials?.length || materials.some((material, index) => {
|
|
100
|
+
const ref = refs[index];
|
|
101
|
+
return ref?.bundleId !== material.bundleId || ref?.materialId !== material.materialId;
|
|
102
|
+
})) {
|
|
103
|
+
context.addIssue({ code: "custom", path: ["initialMaterials"], message: "Material content must match the Data reference" });
|
|
104
|
+
}
|
|
105
|
+
const seen = /* @__PURE__ */ new Set();
|
|
106
|
+
materials?.forEach(({ bundleId, materialId }, index) => {
|
|
107
|
+
const key = JSON.stringify([bundleId, materialId]);
|
|
108
|
+
if (seen.has(key)) context.addIssue({ code: "custom", path: ["initialMaterials", index], message: "Duplicate material" });
|
|
109
|
+
seen.add(key);
|
|
110
|
+
});
|
|
111
|
+
const total = (materials ?? []).reduce(
|
|
112
|
+
(sum, material) => sum + evalMaterialFilesByteSize(material.files),
|
|
113
|
+
value.evaluationOutputSchema ? utf8Bytes(value.evaluationOutputSchema.content) : 0
|
|
114
|
+
);
|
|
115
|
+
if (total > EVAL_INITIALIZATION_MAX_BYTES) {
|
|
116
|
+
tooBig(context, EVAL_INITIALIZATION_MAX_BYTES, "Initialization files are too large");
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
var evalInitializationResultSchema = z.strictObject({
|
|
120
|
+
manifestHash: id,
|
|
121
|
+
target: z.literal("workspace"),
|
|
122
|
+
materials: z.array(z.strictObject({ bundleId: id, materialId: id, rootPath: z.string().startsWith("/") })),
|
|
123
|
+
evaluationOutputSchemaPath: z.literal(EVAL_OUTPUT_SCHEMA_PATH).exactOptional()
|
|
124
|
+
});
|
|
125
|
+
var evalSubmitSchema = z.strictObject({
|
|
126
|
+
idempotencyKey: id,
|
|
127
|
+
prompt: z.string().trim().min(1),
|
|
128
|
+
unattended: z.literal(true),
|
|
129
|
+
runtime: z.strictObject({ timeoutMs: z.number().finite().positive().optional() }).optional()
|
|
130
|
+
});
|
|
131
|
+
var evalBillingResourcesSchema = z.strictObject({
|
|
132
|
+
usageEvents: z.array(z.record(z.string(), z.unknown())),
|
|
133
|
+
billingSettlements: z.array(z.record(z.string(), z.unknown()))
|
|
134
|
+
});
|
|
135
|
+
function projectEvalSubmission(input) {
|
|
136
|
+
const normalizedStatus = {
|
|
137
|
+
pending: "queued",
|
|
138
|
+
running: "running",
|
|
139
|
+
completed: "completed",
|
|
140
|
+
error: "failed",
|
|
141
|
+
skipped: "failed",
|
|
142
|
+
aborted: "interrupted"
|
|
143
|
+
}[input.status];
|
|
144
|
+
if (!normalizedStatus) throw new Error("Unknown SP Submission status");
|
|
145
|
+
return { ...input, normalizedStatus };
|
|
146
|
+
}
|
|
147
|
+
function readEvalCanonicalContext(input) {
|
|
148
|
+
if (input.content.length > EVAL_SESSION_CONTENT_MAX_CHARS) throw new Error("Initial context is too large");
|
|
149
|
+
const parsed = input.format === "json" ? JSON.parse(input.content) : { entries: input.content.split(/\r?\n/u).filter((line) => line.trim()).map((line) => JSON.parse(line)) };
|
|
150
|
+
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.entries)) {
|
|
151
|
+
throw new Error("Initial context must contain canonical entries");
|
|
152
|
+
}
|
|
153
|
+
const entries = parsed.entries;
|
|
154
|
+
if (entries.length > EVAL_SESSION_MAX_ENTRIES) throw new Error("Initial context has too many entries");
|
|
155
|
+
const seen = /* @__PURE__ */ new Set();
|
|
156
|
+
for (const entry of entries) {
|
|
157
|
+
if (!entry || typeof entry !== "object") throw new Error("Invalid canonical context entry");
|
|
158
|
+
const row = entry;
|
|
159
|
+
if (typeof row.id !== "string" || !row.id || seen.has(row.id) || !Number.isSafeInteger(row.createdAt) || Number(row.createdAt) < 0 || !row.message || typeof row.message !== "object" || Array.isArray(row.message) || !["user", "assistant", "toolResult"].includes(row.message.role ?? "")) {
|
|
160
|
+
throw new Error("Invalid or duplicate canonical context entry");
|
|
161
|
+
}
|
|
162
|
+
seen.add(row.id);
|
|
163
|
+
}
|
|
164
|
+
if (entries.length > 0 && entries[0].message.role !== "user") {
|
|
165
|
+
throw new Error("Initial context must begin with a user message");
|
|
166
|
+
}
|
|
167
|
+
return { entries };
|
|
168
|
+
}
|
|
169
|
+
var EVAL_RESULT_FILE = "result.json";
|
|
170
|
+
var EVAL_RESULT_PATH = `/output/${EVAL_RESULT_FILE}`;
|
|
171
|
+
var EVAL_RESULT_MAX_BYTES = 1e6;
|
|
172
|
+
async function readEvalStructuredOutput(path, bytes) {
|
|
173
|
+
if (bytes.byteLength > EVAL_RESULT_MAX_BYTES) throw new Error(`${EVAL_RESULT_FILE} exceeds ${EVAL_RESULT_MAX_BYTES} bytes`);
|
|
174
|
+
let content;
|
|
175
|
+
try {
|
|
176
|
+
content = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
177
|
+
} catch {
|
|
178
|
+
throw new Error(`${EVAL_RESULT_FILE} is not valid UTF-8`);
|
|
179
|
+
}
|
|
180
|
+
const contentHash = `sha256:${await sha256Hex(bytes)}`;
|
|
181
|
+
return { path, content, contentHash };
|
|
182
|
+
}
|
|
183
|
+
function evalMaterialRoot(bundleId, materialId) {
|
|
184
|
+
return `${EVAL_INITIAL_MATERIALS_ROOT}/${evalPathSegment(bundleId)}/${evalPathSegment(materialId)}`;
|
|
185
|
+
}
|
|
186
|
+
function evalPathSegment(value) {
|
|
187
|
+
return encodeURIComponent(value).replaceAll(".", "%2E");
|
|
188
|
+
}
|
|
189
|
+
function evalPathParts(path) {
|
|
190
|
+
const parts = path.split("/").slice(1);
|
|
191
|
+
if (!path.startsWith("/") || parts.length === 0 || parts.some((part) => !part || part === "." || part === ".." || part === ".git" || part.includes("\\") || part.includes("\0"))) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
return parts;
|
|
195
|
+
}
|
|
196
|
+
function evalMaterialPath(root, path) {
|
|
197
|
+
const parts = evalPathParts(path);
|
|
198
|
+
if (!parts) throw new Error("Invalid initial material path");
|
|
199
|
+
return `${root}/${parts.join("/")}`;
|
|
200
|
+
}
|
|
201
|
+
var EVAL_EVIDENCE_ROOT = "/evidence";
|
|
202
|
+
var EVAL_EVIDENCE_PATHS = {
|
|
203
|
+
subjectInputs: "/subject-inputs",
|
|
204
|
+
artifacts: "/artifacts",
|
|
205
|
+
trajectory: "/trajectory",
|
|
206
|
+
manifest: "/manifest.json"
|
|
207
|
+
};
|
|
208
|
+
var EVAL_EVIDENCE_FILE_MAX_BYTES = 25e6;
|
|
209
|
+
var EVAL_EVIDENCE_TRAJECTORY_PAGE_MAX = 200;
|
|
210
|
+
var EVAL_EVIDENCE_SHA256_HEADER = "X-Eval-Content-Sha256";
|
|
211
|
+
var evalEvidenceArtifactSchema = z.strictObject({
|
|
212
|
+
path: z.string().startsWith("/").min(2),
|
|
213
|
+
size: z.number().int().nonnegative(),
|
|
214
|
+
mediaType: id
|
|
215
|
+
});
|
|
216
|
+
var evalEvidenceArtifactsSchema = z.strictObject({
|
|
217
|
+
artifacts: z.array(evalEvidenceArtifactSchema)
|
|
218
|
+
});
|
|
219
|
+
function readEvalTrajectoryPageQuery(params) {
|
|
220
|
+
const afterSeq = Number(params.get("afterSeq") ?? "0");
|
|
221
|
+
const limit = Number(params.get("limit") ?? String(EVAL_EVIDENCE_TRAJECTORY_PAGE_MAX));
|
|
222
|
+
if (!Number.isSafeInteger(afterSeq) || afterSeq < 0 || !Number.isSafeInteger(limit) || limit < 1 || limit > EVAL_EVIDENCE_TRAJECTORY_PAGE_MAX) {
|
|
223
|
+
throw new Error("Invalid trajectory page");
|
|
224
|
+
}
|
|
225
|
+
return { afterSeq, limit };
|
|
226
|
+
}
|
|
227
|
+
function evalEvidencePath(relative) {
|
|
228
|
+
const parts = evalPathParts(relative);
|
|
229
|
+
if (!parts || relative !== EVAL_EVIDENCE_PATHS.manifest && ![EVAL_EVIDENCE_PATHS.subjectInputs, EVAL_EVIDENCE_PATHS.artifacts, EVAL_EVIDENCE_PATHS.trajectory].some((root) => relative.startsWith(`${root}/`))) throw new Error("Invalid evidence path");
|
|
230
|
+
return `${EVAL_EVIDENCE_ROOT}/${parts.join("/")}`;
|
|
231
|
+
}
|
|
232
|
+
function evalSubjectInputEvidencePath(bundleId, materialId, path) {
|
|
233
|
+
return evalMaterialPath(
|
|
234
|
+
`${EVAL_EVIDENCE_PATHS.subjectInputs}/${evalPathSegment(bundleId)}/${evalPathSegment(materialId)}`,
|
|
235
|
+
path
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
function evalArtifactEvidencePath(path) {
|
|
239
|
+
return evalMaterialPath(EVAL_EVIDENCE_PATHS.artifacts, path);
|
|
240
|
+
}
|
|
241
|
+
function evalTrajectoryEvidencePath(part) {
|
|
242
|
+
if (!Number.isSafeInteger(part) || part < 1) throw new Error("Invalid trajectory part");
|
|
243
|
+
return `${EVAL_EVIDENCE_PATHS.trajectory}/events-${String(part).padStart(6, "0")}.jsonl`;
|
|
244
|
+
}
|
|
245
|
+
function isEvalSha256(value) {
|
|
246
|
+
return value !== null && /^[0-9a-f]{64}$/u.test(value);
|
|
247
|
+
}
|
|
248
|
+
function stableEvalFacts(value) {
|
|
249
|
+
const facts = canonicalJsonStringify(value);
|
|
250
|
+
if (facts === void 0) throw new TypeError("Eval facts must be JSON");
|
|
251
|
+
return facts;
|
|
252
|
+
}
|
|
253
|
+
export {
|
|
254
|
+
EVAL_EVIDENCE_FILE_MAX_BYTES,
|
|
255
|
+
EVAL_EVIDENCE_PATHS,
|
|
256
|
+
EVAL_EVIDENCE_ROOT,
|
|
257
|
+
EVAL_EVIDENCE_SHA256_HEADER,
|
|
258
|
+
EVAL_EVIDENCE_TRAJECTORY_PAGE_MAX,
|
|
259
|
+
EVAL_HARNESS_PATH,
|
|
260
|
+
EVAL_INITIALIZATION_BODY_MAX_BYTES,
|
|
261
|
+
EVAL_INITIALIZATION_MAX_BYTES,
|
|
262
|
+
EVAL_INITIAL_FILE_MAX_BYTES,
|
|
263
|
+
EVAL_INITIAL_MATERIALS_ROOT,
|
|
264
|
+
EVAL_MATERIAL_MAX_FILES,
|
|
265
|
+
EVAL_OUTPUT_SCHEMA_PATH,
|
|
266
|
+
EVAL_RESULT_FILE,
|
|
267
|
+
EVAL_RESULT_MAX_BYTES,
|
|
268
|
+
EVAL_RESULT_PATH,
|
|
269
|
+
EVAL_SERVICE_HEADER,
|
|
270
|
+
EVAL_SESSION_CONTENT_MAX_CHARS,
|
|
271
|
+
EVAL_SESSION_MAX_ENTRIES,
|
|
272
|
+
evalArtifactEvidencePath,
|
|
273
|
+
evalBillingResourcesSchema,
|
|
274
|
+
evalEnsureChatSchema,
|
|
275
|
+
evalEvidenceArtifactSchema,
|
|
276
|
+
evalEvidenceArtifactsSchema,
|
|
277
|
+
evalEvidencePath,
|
|
278
|
+
evalInitialContextSchema,
|
|
279
|
+
evalInitializationResultSchema,
|
|
280
|
+
evalInitializationSchema,
|
|
281
|
+
evalMaterialFilesByteSize,
|
|
282
|
+
evalMaterialFilesSchema,
|
|
283
|
+
evalMaterialPath,
|
|
284
|
+
evalMaterialRoot,
|
|
285
|
+
evalSubjectInputEvidencePath,
|
|
286
|
+
evalSubmitSchema,
|
|
287
|
+
evalTrajectoryEvidencePath,
|
|
288
|
+
isEvalSha256,
|
|
289
|
+
projectEvalSubmission,
|
|
290
|
+
readEvalCanonicalContext,
|
|
291
|
+
readEvalStructuredOutput,
|
|
292
|
+
readEvalTrajectoryPageQuery,
|
|
293
|
+
stableEvalFacts
|
|
294
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@springbrand/eval-harness",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"zod": "^4.6.5"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"tag": "alpha"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/springbrand-lab/sp-platform.git",
|
|
27
|
+
"directory": "packages/eval-harness"
|
|
28
|
+
}
|
|
29
|
+
}
|