@tangle-network/agent-eval 0.20.8 → 0.20.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +302 -0
- package/LICENSE +21 -0
- package/README.md +16 -9
- package/dist/benchmarks/index.d.ts +1 -0
- package/dist/benchmarks/index.js +12 -0
- package/dist/benchmarks/index.js.map +1 -0
- package/dist/chunk-42I2QC2L.js +219 -0
- package/dist/chunk-42I2QC2L.js.map +1 -0
- package/dist/{chunk-CJJSB6ZQ.js → chunk-LSR4IAYN.js} +90 -11
- package/dist/chunk-LSR4IAYN.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index-1PZOtZFr.d.ts +290 -0
- package/dist/index.d.ts +37 -298
- package/dist/index.js +130 -252
- package/dist/index.js.map +1 -1
- package/dist/openapi.json +502 -0
- package/dist/{sink-fetch-C0B8ximv.d.ts → sink-fetch-B1Yg4Til.d.ts} +1 -1
- package/dist/telemetry/file.d.ts +1 -1
- package/dist/telemetry/index.d.ts +2 -2
- package/dist/telemetry/index.js.map +1 -1
- package/dist/wire/index.js +1 -1
- package/docs/concepts.md +4 -4
- package/docs/knowledge-readiness.md +2 -2
- package/docs/wire-protocol.md +3 -3
- package/package.json +13 -5
- package/dist/chunk-CJJSB6ZQ.js.map +0 -1
- package/examples/benchmarks/README.md +0 -44
- package/examples/benchmarks/gsm8k/index.ts +0 -126
- package/examples/benchmarks/swebench-lite/index.ts +0 -178
- package/examples/multi-shot-optimization/index.ts +0 -114
- package/examples/same-sandbox-harness/index.ts +0 -63
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.1.0",
|
|
3
|
+
"info": {
|
|
4
|
+
"title": "@tangle-network/agent-eval — wire protocol",
|
|
5
|
+
"version": "0.20.10",
|
|
6
|
+
"description": "HTTP and stdio RPC interface to agent-eval. The TypeScript runtime is the source of truth; this spec is the contract that cross-language clients (Python, Rust, Go) generate from.\n\nWire-protocol version: 1.0.0. Bumps on breaking changes to request/response schemas.",
|
|
7
|
+
"contact": {
|
|
8
|
+
"name": "Tangle Network",
|
|
9
|
+
"url": "https://github.com/tangle-network/agent-eval"
|
|
10
|
+
},
|
|
11
|
+
"license": {
|
|
12
|
+
"name": "MIT"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"servers": [
|
|
16
|
+
{
|
|
17
|
+
"url": "http://localhost:5005",
|
|
18
|
+
"description": "Local agent-eval serve"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"components": {
|
|
22
|
+
"schemas": {
|
|
23
|
+
"JudgeRequest": {
|
|
24
|
+
"oneOf": [
|
|
25
|
+
{
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": false,
|
|
28
|
+
"required": [
|
|
29
|
+
"rubricName",
|
|
30
|
+
"content"
|
|
31
|
+
],
|
|
32
|
+
"properties": {
|
|
33
|
+
"rubricName": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"minLength": 1
|
|
36
|
+
},
|
|
37
|
+
"content": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"minLength": 1
|
|
40
|
+
},
|
|
41
|
+
"context": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"additionalProperties": true
|
|
44
|
+
},
|
|
45
|
+
"model": {
|
|
46
|
+
"type": "string"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"type": "object",
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"required": [
|
|
54
|
+
"rubric",
|
|
55
|
+
"content"
|
|
56
|
+
],
|
|
57
|
+
"properties": {
|
|
58
|
+
"rubric": {
|
|
59
|
+
"$ref": "#/components/schemas/Rubric"
|
|
60
|
+
},
|
|
61
|
+
"content": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"minLength": 1
|
|
64
|
+
},
|
|
65
|
+
"context": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": true
|
|
68
|
+
},
|
|
69
|
+
"model": {
|
|
70
|
+
"type": "string"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
"description": "Judge request. Provide exactly one of rubricName or rubric."
|
|
76
|
+
},
|
|
77
|
+
"Rubric": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"name": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"minLength": 1,
|
|
83
|
+
"description": "Stable name like \"anti-slop\" — used by clients to invoke this rubric."
|
|
84
|
+
},
|
|
85
|
+
"description": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"minLength": 1,
|
|
88
|
+
"description": "What this rubric measures. Shown in /v1/rubrics listing."
|
|
89
|
+
},
|
|
90
|
+
"systemPrompt": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"minLength": 1,
|
|
93
|
+
"description": "Instructs the judging LLM. Should explain the persona (e.g. \"senior engineer reviewing voice\"), what to score on, and what to return."
|
|
94
|
+
},
|
|
95
|
+
"dimensions": {
|
|
96
|
+
"type": "array",
|
|
97
|
+
"items": {
|
|
98
|
+
"$ref": "#/components/schemas/RubricDimension"
|
|
99
|
+
},
|
|
100
|
+
"minItems": 1,
|
|
101
|
+
"description": "Scoring axes. The composite score is a weighted sum of these."
|
|
102
|
+
},
|
|
103
|
+
"failureModes": {
|
|
104
|
+
"type": "array",
|
|
105
|
+
"items": {
|
|
106
|
+
"$ref": "#/components/schemas/FailureMode"
|
|
107
|
+
},
|
|
108
|
+
"default": [],
|
|
109
|
+
"description": "Patterns to detect; each detected mode appears in the result.failureModes list."
|
|
110
|
+
},
|
|
111
|
+
"wins": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"items": {
|
|
114
|
+
"$ref": "#/components/schemas/FailureMode"
|
|
115
|
+
},
|
|
116
|
+
"default": [],
|
|
117
|
+
"description": "Positive patterns; each detected one appears in the result.wins list."
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"required": [
|
|
121
|
+
"name",
|
|
122
|
+
"description",
|
|
123
|
+
"systemPrompt",
|
|
124
|
+
"dimensions"
|
|
125
|
+
],
|
|
126
|
+
"description": "Inline rubric definition. Mutually exclusive with `rubricName`."
|
|
127
|
+
},
|
|
128
|
+
"RubricDimension": {
|
|
129
|
+
"type": "object",
|
|
130
|
+
"properties": {
|
|
131
|
+
"id": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"minLength": 1,
|
|
134
|
+
"description": "Short stable id like \"buyer_quality\" — used as the key in scoring output."
|
|
135
|
+
},
|
|
136
|
+
"description": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"minLength": 1,
|
|
139
|
+
"description": "One-line plain-English meaning. Read by humans reviewing low scores."
|
|
140
|
+
},
|
|
141
|
+
"weight": {
|
|
142
|
+
"type": "number",
|
|
143
|
+
"minimum": 0,
|
|
144
|
+
"default": 1,
|
|
145
|
+
"description": "Relative weight in the composite score. Default 1; 0 disables."
|
|
146
|
+
},
|
|
147
|
+
"min": {
|
|
148
|
+
"type": "number",
|
|
149
|
+
"default": 0,
|
|
150
|
+
"description": "Lower bound of valid score for this dimension."
|
|
151
|
+
},
|
|
152
|
+
"max": {
|
|
153
|
+
"type": "number",
|
|
154
|
+
"default": 1,
|
|
155
|
+
"description": "Upper bound of valid score for this dimension."
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"required": [
|
|
159
|
+
"id",
|
|
160
|
+
"description"
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
"FailureMode": {
|
|
164
|
+
"type": "object",
|
|
165
|
+
"properties": {
|
|
166
|
+
"id": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"minLength": 1,
|
|
169
|
+
"description": "Short stable id like \"ai-cadence\" — used in detection lists."
|
|
170
|
+
},
|
|
171
|
+
"description": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"minLength": 1,
|
|
174
|
+
"description": "Plain-English description of the failure pattern."
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"required": [
|
|
178
|
+
"id",
|
|
179
|
+
"description"
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
"JudgeResult": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"properties": {
|
|
185
|
+
"composite": {
|
|
186
|
+
"type": "number",
|
|
187
|
+
"minimum": 0,
|
|
188
|
+
"maximum": 1,
|
|
189
|
+
"description": "Weighted combination of dimension scores in 0..1. The single number to gate on."
|
|
190
|
+
},
|
|
191
|
+
"dimensions": {
|
|
192
|
+
"type": "object",
|
|
193
|
+
"additionalProperties": {
|
|
194
|
+
"type": "number"
|
|
195
|
+
},
|
|
196
|
+
"description": "Per-dimension score, keyed by RubricDimension.id."
|
|
197
|
+
},
|
|
198
|
+
"failureModes": {
|
|
199
|
+
"type": "array",
|
|
200
|
+
"items": {
|
|
201
|
+
"type": "string"
|
|
202
|
+
},
|
|
203
|
+
"default": [],
|
|
204
|
+
"description": "Failure-mode ids detected in the content (subset of rubric.failureModes ids)."
|
|
205
|
+
},
|
|
206
|
+
"wins": {
|
|
207
|
+
"type": "array",
|
|
208
|
+
"items": {
|
|
209
|
+
"type": "string"
|
|
210
|
+
},
|
|
211
|
+
"default": [],
|
|
212
|
+
"description": "Win ids detected in the content (subset of rubric.wins ids)."
|
|
213
|
+
},
|
|
214
|
+
"rationale": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"description": "Plain-English explanation of the score. Surfaced to the human reviewer."
|
|
217
|
+
},
|
|
218
|
+
"rubricVersion": {
|
|
219
|
+
"type": "string",
|
|
220
|
+
"description": "Stable hash of the rubric used. Scores are only comparable across runs when this matches."
|
|
221
|
+
},
|
|
222
|
+
"model": {
|
|
223
|
+
"type": "string",
|
|
224
|
+
"description": "Model that produced the judgement, for reproducibility."
|
|
225
|
+
},
|
|
226
|
+
"durationMs": {
|
|
227
|
+
"type": "integer",
|
|
228
|
+
"minimum": 0,
|
|
229
|
+
"description": "End-to-end wall time for this call."
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"required": [
|
|
233
|
+
"composite",
|
|
234
|
+
"dimensions",
|
|
235
|
+
"rationale",
|
|
236
|
+
"rubricVersion",
|
|
237
|
+
"model",
|
|
238
|
+
"durationMs"
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
"ListRubricsResponse": {
|
|
242
|
+
"type": "object",
|
|
243
|
+
"properties": {
|
|
244
|
+
"rubrics": {
|
|
245
|
+
"type": "array",
|
|
246
|
+
"items": {
|
|
247
|
+
"$ref": "#/components/schemas/RubricInfo"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
"required": [
|
|
252
|
+
"rubrics"
|
|
253
|
+
]
|
|
254
|
+
},
|
|
255
|
+
"RubricInfo": {
|
|
256
|
+
"type": "object",
|
|
257
|
+
"properties": {
|
|
258
|
+
"name": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"description": "Pass this to /v1/judge as `rubricName`."
|
|
261
|
+
},
|
|
262
|
+
"description": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"description": "What this rubric measures."
|
|
265
|
+
},
|
|
266
|
+
"dimensions": {
|
|
267
|
+
"type": "array",
|
|
268
|
+
"items": {
|
|
269
|
+
"type": "object",
|
|
270
|
+
"properties": {
|
|
271
|
+
"id": {
|
|
272
|
+
"type": "string"
|
|
273
|
+
},
|
|
274
|
+
"description": {
|
|
275
|
+
"type": "string"
|
|
276
|
+
},
|
|
277
|
+
"weight": {
|
|
278
|
+
"type": "number"
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
"required": [
|
|
282
|
+
"id",
|
|
283
|
+
"description",
|
|
284
|
+
"weight"
|
|
285
|
+
]
|
|
286
|
+
},
|
|
287
|
+
"description": "The scoring axes this rubric uses, with weights."
|
|
288
|
+
},
|
|
289
|
+
"failureModes": {
|
|
290
|
+
"type": "array",
|
|
291
|
+
"items": {
|
|
292
|
+
"type": "string"
|
|
293
|
+
},
|
|
294
|
+
"default": [],
|
|
295
|
+
"description": "Failure-mode ids this rubric detects."
|
|
296
|
+
},
|
|
297
|
+
"rubricVersion": {
|
|
298
|
+
"type": "string",
|
|
299
|
+
"description": "Stable hash — match this to compare scores across runs."
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
"required": [
|
|
303
|
+
"name",
|
|
304
|
+
"description",
|
|
305
|
+
"dimensions",
|
|
306
|
+
"rubricVersion"
|
|
307
|
+
]
|
|
308
|
+
},
|
|
309
|
+
"VersionResponse": {
|
|
310
|
+
"type": "object",
|
|
311
|
+
"properties": {
|
|
312
|
+
"package": {
|
|
313
|
+
"type": "string",
|
|
314
|
+
"description": "Package name (always \"@tangle-network/agent-eval\")."
|
|
315
|
+
},
|
|
316
|
+
"version": {
|
|
317
|
+
"type": "string",
|
|
318
|
+
"description": "Semver of the running server. Match your client to this."
|
|
319
|
+
},
|
|
320
|
+
"wireVersion": {
|
|
321
|
+
"type": "string",
|
|
322
|
+
"description": "Wire-protocol semver. Bumps separately from package version when the schema changes."
|
|
323
|
+
},
|
|
324
|
+
"apiSurface": {
|
|
325
|
+
"type": "array",
|
|
326
|
+
"items": {
|
|
327
|
+
"type": "string"
|
|
328
|
+
},
|
|
329
|
+
"description": "List of supported method names."
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
"required": [
|
|
333
|
+
"package",
|
|
334
|
+
"version",
|
|
335
|
+
"wireVersion",
|
|
336
|
+
"apiSurface"
|
|
337
|
+
]
|
|
338
|
+
},
|
|
339
|
+
"HealthResponse": {
|
|
340
|
+
"type": "object",
|
|
341
|
+
"properties": {
|
|
342
|
+
"status": {
|
|
343
|
+
"type": "string",
|
|
344
|
+
"enum": [
|
|
345
|
+
"ok"
|
|
346
|
+
]
|
|
347
|
+
},
|
|
348
|
+
"uptimeSec": {
|
|
349
|
+
"type": "number"
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
"required": [
|
|
353
|
+
"status",
|
|
354
|
+
"uptimeSec"
|
|
355
|
+
]
|
|
356
|
+
},
|
|
357
|
+
"ErrorResponse": {
|
|
358
|
+
"type": "object",
|
|
359
|
+
"properties": {
|
|
360
|
+
"error": {
|
|
361
|
+
"type": "object",
|
|
362
|
+
"properties": {
|
|
363
|
+
"code": {
|
|
364
|
+
"type": "string",
|
|
365
|
+
"description": "Machine-readable code: \"validation_error\", \"rubric_not_found\", \"judge_error\"."
|
|
366
|
+
},
|
|
367
|
+
"message": {
|
|
368
|
+
"type": "string",
|
|
369
|
+
"description": "Human-readable message."
|
|
370
|
+
},
|
|
371
|
+
"details": {
|
|
372
|
+
"description": "Optional structured detail."
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
"required": [
|
|
376
|
+
"code",
|
|
377
|
+
"message"
|
|
378
|
+
],
|
|
379
|
+
"description": "Errors are always wrapped in this shape across all endpoints."
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
"required": [
|
|
383
|
+
"error"
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"parameters": {}
|
|
388
|
+
},
|
|
389
|
+
"paths": {
|
|
390
|
+
"/v1/judge": {
|
|
391
|
+
"post": {
|
|
392
|
+
"summary": "Score a piece of content against a rubric",
|
|
393
|
+
"description": "Runs the judging LLM with the named (or inline) rubric and returns dimension scores, detected failure modes, wins, and a composite score in 0..1.",
|
|
394
|
+
"requestBody": {
|
|
395
|
+
"content": {
|
|
396
|
+
"application/json": {
|
|
397
|
+
"schema": {
|
|
398
|
+
"$ref": "#/components/schemas/JudgeRequest"
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
"responses": {
|
|
404
|
+
"200": {
|
|
405
|
+
"description": "Successful judgement",
|
|
406
|
+
"content": {
|
|
407
|
+
"application/json": {
|
|
408
|
+
"schema": {
|
|
409
|
+
"$ref": "#/components/schemas/JudgeResult"
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
"400": {
|
|
415
|
+
"description": "Validation error",
|
|
416
|
+
"content": {
|
|
417
|
+
"application/json": {
|
|
418
|
+
"schema": {
|
|
419
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
"404": {
|
|
425
|
+
"description": "Rubric not found",
|
|
426
|
+
"content": {
|
|
427
|
+
"application/json": {
|
|
428
|
+
"schema": {
|
|
429
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
"500": {
|
|
435
|
+
"description": "Judge error",
|
|
436
|
+
"content": {
|
|
437
|
+
"application/json": {
|
|
438
|
+
"schema": {
|
|
439
|
+
"$ref": "#/components/schemas/ErrorResponse"
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
},
|
|
447
|
+
"/v1/rubrics": {
|
|
448
|
+
"get": {
|
|
449
|
+
"summary": "List built-in rubrics",
|
|
450
|
+
"description": "Returns every rubric registered server-side, with their dimensions and stable rubricVersion hash.",
|
|
451
|
+
"responses": {
|
|
452
|
+
"200": {
|
|
453
|
+
"description": "Listing",
|
|
454
|
+
"content": {
|
|
455
|
+
"application/json": {
|
|
456
|
+
"schema": {
|
|
457
|
+
"$ref": "#/components/schemas/ListRubricsResponse"
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
"/v1/version": {
|
|
466
|
+
"get": {
|
|
467
|
+
"summary": "Server and wire-protocol version",
|
|
468
|
+
"description": "Match your client version to `version`; check `wireVersion` for compatibility.",
|
|
469
|
+
"responses": {
|
|
470
|
+
"200": {
|
|
471
|
+
"description": "Version info",
|
|
472
|
+
"content": {
|
|
473
|
+
"application/json": {
|
|
474
|
+
"schema": {
|
|
475
|
+
"$ref": "#/components/schemas/VersionResponse"
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
"/healthz": {
|
|
484
|
+
"get": {
|
|
485
|
+
"summary": "Liveness check",
|
|
486
|
+
"responses": {
|
|
487
|
+
"200": {
|
|
488
|
+
"description": "OK",
|
|
489
|
+
"content": {
|
|
490
|
+
"application/json": {
|
|
491
|
+
"schema": {
|
|
492
|
+
"$ref": "#/components/schemas/HealthResponse"
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
"webhooks": {}
|
|
502
|
+
}
|
|
@@ -64,7 +64,7 @@ interface TelemetryModel {
|
|
|
64
64
|
* `child_process`. Safe to import from a Cloudflare Worker, Lambda, edge
|
|
65
65
|
* function, or browser extension.
|
|
66
66
|
*
|
|
67
|
-
* For Node-only file persistence, import from '
|
|
67
|
+
* For Node-only file persistence, import from '@tangle-network/agent-eval/telemetry/file'.
|
|
68
68
|
*/
|
|
69
69
|
|
|
70
70
|
interface TelemetrySink {
|
package/dist/telemetry/file.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TelemetryKind, a as TelemetryModel, b as TelemetrySource, c as TelemetrySink } from '../sink-fetch-
|
|
2
|
-
export { F as FanoutTelemetrySink, H as HttpTelemetrySink, I as InMemoryTelemetrySink, N as NullTelemetrySink, d as TELEMETRY_SCHEMA_VERSION, e as TelemetryEnvelope } from '../sink-fetch-
|
|
1
|
+
import { T as TelemetryKind, a as TelemetryModel, b as TelemetrySource, c as TelemetrySink } from '../sink-fetch-B1Yg4Til.js';
|
|
2
|
+
export { F as FanoutTelemetrySink, H as HttpTelemetrySink, I as InMemoryTelemetrySink, N as NullTelemetrySink, d as TELEMETRY_SCHEMA_VERSION, e as TelemetryEnvelope } from '../sink-fetch-B1Yg4Til.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Telemetry client — thin wrapper that builds envelopes from `EmitArgs` and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/telemetry/schema.ts","../../src/telemetry/sink-fetch.ts","../../src/telemetry/client.ts"],"sourcesContent":["/**\n * Fleet telemetry envelope — agent-eval's portable observability shape.\n *\n * Designed so any consumer (Node CLI, Cloudflare Worker, Lambda, browser\n * extension) can emit structured rows describing one unit of work — a page\n * audit, a tool call, an evolve round, a full agent run — to a central sink.\n *\n * The schema is intentionally a strict superset of agent-eval's `Run` shape\n * so a future TraceStore adapter can promote envelopes into traces without\n * translation.\n */\n\nexport const TELEMETRY_SCHEMA_VERSION = 1\n\n/** Discriminator for the unit of work this envelope describes. */\nexport type TelemetryKind =\n | 'agent-run'\n | 'design-audit-page'\n | 'design-audit-run'\n | 'design-evolve-round'\n | 'design-evolve-run'\n | 'gepa-trial'\n | 'gepa-generation'\n | 'tool-call'\n | 'judge-verdict'\n | 'custom'\n\nexport interface TelemetryEnvelope {\n schemaVersion: typeof TELEMETRY_SCHEMA_VERSION\n envelopeId: string\n runId: string\n timestamp: string\n parentRunId?: string\n\n source: TelemetrySource\n model?: TelemetryModel\n kind: TelemetryKind\n ok: boolean\n durationMs: number\n\n data: Record<string, unknown>\n metrics: Record<string, number>\n tags?: Record<string, string>\n\n error?: string\n}\n\nexport interface TelemetrySource {\n /** Repo identity — basename of cwd plus git remote if discoverable. */\n repo: string\n cwd: string\n gitSha?: string\n gitBranch?: string\n cliVersion: string\n /** What was invoked, e.g. `design-audit`, `bad run`, `gepa --target`. */\n invocation: string\n /** Sanitised argv minus secrets. */\n argv?: string[]\n /**\n * Multi-tenant identity. Set when the consumer runs inside a hosted\n * product so a fleet rollup can group by tenant without leaking customer\n * URLs or PII.\n */\n tenantId?: string\n /** Optional sub-tenant identity (project, suite, walkthrough, customer). */\n customerId?: string\n /** SHA-256 (12 hex) of the API key used to authenticate this run, when applicable. */\n apiKeyHash?: string\n}\n\nexport interface TelemetryModel {\n provider: string\n name: string\n /** SHA-256 (12 hex chars) of the prompt(s) used. */\n promptHash?: string\n /** SHA-256 (12 hex chars) of the composed rubric body, if applicable. */\n rubricHash?: string\n}\n","/**\n * Workers-safe telemetry sinks — only `fetch` and pure JS. No `fs`, no\n * `child_process`. Safe to import from a Cloudflare Worker, Lambda, edge\n * function, or browser extension.\n *\n * For Node-only file persistence, import from './sink-file' instead.\n */\n\nimport type { TelemetryEnvelope } from './schema'\n\nexport interface TelemetrySink {\n emit(envelope: TelemetryEnvelope): Promise<void> | void\n close?(): Promise<void> | void\n}\n\n/** Best-effort POST to a remote collector. Fire-and-forget; never throws. */\nexport class HttpTelemetrySink implements TelemetrySink {\n private inflight = new Set<Promise<void>>()\n\n constructor(\n private readonly endpoint: string,\n private readonly bearer?: string,\n ) {}\n\n emit(envelope: TelemetryEnvelope): void {\n const body = JSON.stringify(envelope)\n const headers: Record<string, string> = { 'content-type': 'application/json' }\n if (this.bearer) headers.authorization = `Bearer ${this.bearer}`\n const promise = fetch(this.endpoint, { method: 'POST', headers, body })\n .then(() => undefined)\n .catch(() => undefined)\n this.inflight.add(promise)\n promise.finally(() => this.inflight.delete(promise))\n }\n\n async close(): Promise<void> {\n await Promise.allSettled(Array.from(this.inflight))\n }\n}\n\n/** Fanout to multiple sinks — failures in one do not affect others. */\nexport class FanoutTelemetrySink implements TelemetrySink {\n constructor(private readonly sinks: TelemetrySink[]) {}\n\n emit(envelope: TelemetryEnvelope): void {\n for (const sink of this.sinks) {\n try {\n const result = sink.emit(envelope)\n if (result && typeof (result as Promise<unknown>).catch === 'function') {\n ;(result as Promise<unknown>).catch(() => undefined)\n }\n } catch {\n // swallow — telemetry must never break a run\n }\n }\n }\n\n async close(): Promise<void> {\n await Promise.allSettled(this.sinks.map((s) => Promise.resolve(s.close?.())))\n }\n}\n\n/** No-op sink — used when telemetry is explicitly disabled. */\nexport class NullTelemetrySink implements TelemetrySink {\n emit(): void {}\n}\n\n/** In-memory sink — useful for tests + downstream adapters. */\nexport class InMemoryTelemetrySink implements TelemetrySink {\n readonly envelopes: TelemetryEnvelope[] = []\n emit(envelope: TelemetryEnvelope): void {\n this.envelopes.push(envelope)\n }\n clear(): void { this.envelopes.length = 0 }\n}\n","/**\n * Telemetry client — thin wrapper that builds envelopes from `EmitArgs` and\n * delegates to a `TelemetrySink`. Pure logic; no I/O. Use this from any\n * runtime — Workers, Node, browser — and choose the sink accordingly.\n *\n * For an opinionated singleton with env-var-driven sink wiring (the bad CLI\n * pattern), see `./node-client.ts`.\n */\n\nimport type { TelemetryEnvelope, TelemetryKind, TelemetryModel, TelemetrySource } from './schema'\nimport { TELEMETRY_SCHEMA_VERSION } from './schema'\nimport type { TelemetrySink } from './sink-fetch'\n\nexport interface EmitArgs {\n kind: TelemetryKind\n runId: string\n parentRunId?: string\n ok: boolean\n durationMs: number\n data?: Record<string, unknown>\n metrics?: Record<string, number>\n tags?: Record<string, string>\n model?: TelemetryModel\n error?: string\n /** Override the source for this envelope. Falls back to `defaultSource`. */\n source?: TelemetrySource\n}\n\nexport class TelemetryClient {\n constructor(\n private readonly sink: TelemetrySink,\n private readonly defaultSource: TelemetrySource,\n ) {}\n\n emit(args: EmitArgs): void {\n const envelope: TelemetryEnvelope = {\n schemaVersion: TELEMETRY_SCHEMA_VERSION,\n envelopeId: makeEnvelopeId(),\n runId: args.runId,\n timestamp: new Date().toISOString(),\n source: args.source ?? this.defaultSource,\n kind: args.kind,\n ok: args.ok,\n durationMs: args.durationMs,\n data: args.data ?? {},\n metrics: args.metrics ?? {},\n ...(args.parentRunId ? { parentRunId: args.parentRunId } : {}),\n ...(args.model ? { model: args.model } : {}),\n ...(args.tags ? { tags: args.tags } : {}),\n ...(args.error ? { error: args.error } : {}),\n }\n try {\n this.sink.emit(envelope)\n } catch {\n // swallow — telemetry never breaks the calling code path\n }\n }\n\n async close(): Promise<void> {\n await this.sink.close?.()\n }\n}\n\n/** Generate a UUIDv4 with whatever crypto is available (Node, Workers, browsers). */\nfunction makeEnvelopeId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n // Last-resort fallback. Lower entropy but never throws.\n return 'env-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 10)\n}\n\nexport const SECRET_FLAGS = new Set(['--api-key', '--bearer', '--token', '--password'])\n\n/** Strip likely-secret values from argv, preserving structure. */\nexport function sanitiseArgv(argv: string[]): string[] {\n const out: string[] = []\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!\n if (SECRET_FLAGS.has(a)) {\n out.push(a, '<redacted>')\n i++\n continue\n }\n if (/^(?:--api-key|--bearer|--token|--password)=/.test(a)) {\n out.push(a.replace(/=.*$/, '=<redacted>'))\n continue\n }\n out.push(a)\n }\n return out\n}\n"],"mappings":";;;AAYO,IAAM,2BAA2B;;;ACIjC,IAAM,oBAAN,MAAiD;AAAA,EAGtD,YACmB,UACA,QACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAJX,WAAW,oBAAI,IAAmB;AAAA,EAO1C,KAAK,UAAmC;AACtC,UAAM,OAAO,KAAK,UAAU,QAAQ;AACpC,UAAM,UAAkC,EAAE,gBAAgB,mBAAmB;AAC7E,QAAI,KAAK,OAAQ,SAAQ,gBAAgB,UAAU,KAAK,MAAM;AAC9D,UAAM,UAAU,MAAM,KAAK,UAAU,EAAE,QAAQ,QAAQ,SAAS,KAAK,CAAC,EACnE,KAAK,MAAM,MAAS,EACpB,MAAM,MAAM,MAAS;AACxB,SAAK,SAAS,IAAI,OAAO;AACzB,YAAQ,QAAQ,MAAM,KAAK,SAAS,OAAO,OAAO,CAAC;AAAA,EACrD;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,QAAQ,WAAW,MAAM,KAAK,KAAK,QAAQ,CAAC;AAAA,EACpD;AACF;AAGO,IAAM,sBAAN,MAAmD;AAAA,EACxD,YAA6B,OAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAE7B,KAAK,UAAmC;AACtC,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI;AACF,cAAM,SAAS,KAAK,KAAK,QAAQ;AACjC,YAAI,UAAU,OAAQ,OAA4B,UAAU,YAAY;AACtE;AAAC,UAAC,OAA4B,MAAM,MAAM,MAAS;AAAA,QACrD;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,QAAQ,WAAW,KAAK,MAAM,IAAI,CAAC,MAAM,QAAQ,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;AAAA,EAC9E;AACF;AAGO,IAAM,oBAAN,MAAiD;AAAA,EACtD,OAAa;AAAA,EAAC;AAChB;AAGO,IAAM,wBAAN,MAAqD;AAAA,EACjD,YAAiC,CAAC;AAAA,EAC3C,KAAK,UAAmC;AACtC,SAAK,UAAU,KAAK,QAAQ;AAAA,EAC9B;AAAA,EACA,QAAc;AAAE,SAAK,UAAU,SAAS;AAAA,EAAE;AAC5C;;;AC9CO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YACmB,MACA,eACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAGnB,KAAK,MAAsB;AACzB,UAAM,WAA8B;AAAA,MAClC,eAAe;AAAA,MACf,YAAY,eAAe;AAAA,MAC3B,OAAO,KAAK;AAAA,MACZ,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,QAAQ,KAAK,UAAU,KAAK;AAAA,MAC5B,MAAM,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,YAAY,KAAK;AAAA,MACjB,MAAM,KAAK,QAAQ,CAAC;AAAA,MACpB,SAAS,KAAK,WAAW,CAAC;AAAA,MAC1B,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;AAAA,MAC5D,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,MAC1C,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,MACvC,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IAC5C;AACA,QAAI;AACF,WAAK,KAAK,KAAK,QAAQ;AAAA,IACzB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,KAAK,QAAQ;AAAA,EAC1B;AACF;AAGA,SAAS,iBAAyB;AAChC,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E,WAAO,OAAO,WAAW;AAAA,EAC3B;AAEA,SAAO,SAAS,KAAK,IAAI,EAAE,SAAS,EAAE,IAAI,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE;AACxF;AAEO,IAAM,eAAe,oBAAI,IAAI,CAAC,aAAa,YAAY,WAAW,YAAY,CAAC;AAG/E,SAAS,aAAa,MAA0B;AACrD,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,aAAa,IAAI,CAAC,GAAG;AACvB,UAAI,KAAK,GAAG,YAAY;AACxB;AACA;AAAA,IACF;AACA,QAAI,8CAA8C,KAAK,CAAC,GAAG;AACzD,UAAI,KAAK,EAAE,QAAQ,QAAQ,aAAa,CAAC;AACzC;AAAA,IACF;AACA,QAAI,KAAK,CAAC;AAAA,EACZ;AACA,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/telemetry/schema.ts","../../src/telemetry/sink-fetch.ts","../../src/telemetry/client.ts"],"sourcesContent":["/**\n * Fleet telemetry envelope — agent-eval's portable observability shape.\n *\n * Designed so any consumer (Node CLI, Cloudflare Worker, Lambda, browser\n * extension) can emit structured rows describing one unit of work — a page\n * audit, a tool call, an evolve round, a full agent run — to a central sink.\n *\n * The schema is intentionally a strict superset of agent-eval's `Run` shape\n * so a future TraceStore adapter can promote envelopes into traces without\n * translation.\n */\n\nexport const TELEMETRY_SCHEMA_VERSION = 1\n\n/** Discriminator for the unit of work this envelope describes. */\nexport type TelemetryKind =\n | 'agent-run'\n | 'design-audit-page'\n | 'design-audit-run'\n | 'design-evolve-round'\n | 'design-evolve-run'\n | 'gepa-trial'\n | 'gepa-generation'\n | 'tool-call'\n | 'judge-verdict'\n | 'custom'\n\nexport interface TelemetryEnvelope {\n schemaVersion: typeof TELEMETRY_SCHEMA_VERSION\n envelopeId: string\n runId: string\n timestamp: string\n parentRunId?: string\n\n source: TelemetrySource\n model?: TelemetryModel\n kind: TelemetryKind\n ok: boolean\n durationMs: number\n\n data: Record<string, unknown>\n metrics: Record<string, number>\n tags?: Record<string, string>\n\n error?: string\n}\n\nexport interface TelemetrySource {\n /** Repo identity — basename of cwd plus git remote if discoverable. */\n repo: string\n cwd: string\n gitSha?: string\n gitBranch?: string\n cliVersion: string\n /** What was invoked, e.g. `design-audit`, `bad run`, `gepa --target`. */\n invocation: string\n /** Sanitised argv minus secrets. */\n argv?: string[]\n /**\n * Multi-tenant identity. Set when the consumer runs inside a hosted\n * product so a fleet rollup can group by tenant without leaking customer\n * URLs or PII.\n */\n tenantId?: string\n /** Optional sub-tenant identity (project, suite, walkthrough, customer). */\n customerId?: string\n /** SHA-256 (12 hex) of the API key used to authenticate this run, when applicable. */\n apiKeyHash?: string\n}\n\nexport interface TelemetryModel {\n provider: string\n name: string\n /** SHA-256 (12 hex chars) of the prompt(s) used. */\n promptHash?: string\n /** SHA-256 (12 hex chars) of the composed rubric body, if applicable. */\n rubricHash?: string\n}\n","/**\n * Workers-safe telemetry sinks — only `fetch` and pure JS. No `fs`, no\n * `child_process`. Safe to import from a Cloudflare Worker, Lambda, edge\n * function, or browser extension.\n *\n * For Node-only file persistence, import from '@tangle-network/agent-eval/telemetry/file'.\n */\n\nimport type { TelemetryEnvelope } from './schema'\n\nexport interface TelemetrySink {\n emit(envelope: TelemetryEnvelope): Promise<void> | void\n close?(): Promise<void> | void\n}\n\n/** Best-effort POST to a remote collector. Fire-and-forget; never throws. */\nexport class HttpTelemetrySink implements TelemetrySink {\n private inflight = new Set<Promise<void>>()\n\n constructor(\n private readonly endpoint: string,\n private readonly bearer?: string,\n ) {}\n\n emit(envelope: TelemetryEnvelope): void {\n const body = JSON.stringify(envelope)\n const headers: Record<string, string> = { 'content-type': 'application/json' }\n if (this.bearer) headers.authorization = `Bearer ${this.bearer}`\n const promise = fetch(this.endpoint, { method: 'POST', headers, body })\n .then(() => undefined)\n .catch(() => undefined)\n this.inflight.add(promise)\n promise.finally(() => this.inflight.delete(promise))\n }\n\n async close(): Promise<void> {\n await Promise.allSettled(Array.from(this.inflight))\n }\n}\n\n/** Fanout to multiple sinks — failures in one do not affect others. */\nexport class FanoutTelemetrySink implements TelemetrySink {\n constructor(private readonly sinks: TelemetrySink[]) {}\n\n emit(envelope: TelemetryEnvelope): void {\n for (const sink of this.sinks) {\n try {\n const result = sink.emit(envelope)\n if (result && typeof (result as Promise<unknown>).catch === 'function') {\n ;(result as Promise<unknown>).catch(() => undefined)\n }\n } catch {\n // swallow — telemetry must never break a run\n }\n }\n }\n\n async close(): Promise<void> {\n await Promise.allSettled(this.sinks.map((s) => Promise.resolve(s.close?.())))\n }\n}\n\n/** No-op sink — used when telemetry is explicitly disabled. */\nexport class NullTelemetrySink implements TelemetrySink {\n emit(): void {}\n}\n\n/** In-memory sink — useful for tests + downstream adapters. */\nexport class InMemoryTelemetrySink implements TelemetrySink {\n readonly envelopes: TelemetryEnvelope[] = []\n emit(envelope: TelemetryEnvelope): void {\n this.envelopes.push(envelope)\n }\n clear(): void { this.envelopes.length = 0 }\n}\n","/**\n * Telemetry client — thin wrapper that builds envelopes from `EmitArgs` and\n * delegates to a `TelemetrySink`. Pure logic; no I/O. Use this from any\n * runtime — Workers, Node, browser — and choose the sink accordingly.\n *\n * For an opinionated singleton with env-var-driven sink wiring (the bad CLI\n * pattern), see `./node-client.ts`.\n */\n\nimport type { TelemetryEnvelope, TelemetryKind, TelemetryModel, TelemetrySource } from './schema'\nimport { TELEMETRY_SCHEMA_VERSION } from './schema'\nimport type { TelemetrySink } from './sink-fetch'\n\nexport interface EmitArgs {\n kind: TelemetryKind\n runId: string\n parentRunId?: string\n ok: boolean\n durationMs: number\n data?: Record<string, unknown>\n metrics?: Record<string, number>\n tags?: Record<string, string>\n model?: TelemetryModel\n error?: string\n /** Override the source for this envelope. Falls back to `defaultSource`. */\n source?: TelemetrySource\n}\n\nexport class TelemetryClient {\n constructor(\n private readonly sink: TelemetrySink,\n private readonly defaultSource: TelemetrySource,\n ) {}\n\n emit(args: EmitArgs): void {\n const envelope: TelemetryEnvelope = {\n schemaVersion: TELEMETRY_SCHEMA_VERSION,\n envelopeId: makeEnvelopeId(),\n runId: args.runId,\n timestamp: new Date().toISOString(),\n source: args.source ?? this.defaultSource,\n kind: args.kind,\n ok: args.ok,\n durationMs: args.durationMs,\n data: args.data ?? {},\n metrics: args.metrics ?? {},\n ...(args.parentRunId ? { parentRunId: args.parentRunId } : {}),\n ...(args.model ? { model: args.model } : {}),\n ...(args.tags ? { tags: args.tags } : {}),\n ...(args.error ? { error: args.error } : {}),\n }\n try {\n this.sink.emit(envelope)\n } catch {\n // swallow — telemetry never breaks the calling code path\n }\n }\n\n async close(): Promise<void> {\n await this.sink.close?.()\n }\n}\n\n/** Generate a UUIDv4 with whatever crypto is available (Node, Workers, browsers). */\nfunction makeEnvelopeId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n // Last-resort fallback. Lower entropy but never throws.\n return 'env-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2, 10)\n}\n\nexport const SECRET_FLAGS = new Set(['--api-key', '--bearer', '--token', '--password'])\n\n/** Strip likely-secret values from argv, preserving structure. */\nexport function sanitiseArgv(argv: string[]): string[] {\n const out: string[] = []\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!\n if (SECRET_FLAGS.has(a)) {\n out.push(a, '<redacted>')\n i++\n continue\n }\n if (/^(?:--api-key|--bearer|--token|--password)=/.test(a)) {\n out.push(a.replace(/=.*$/, '=<redacted>'))\n continue\n }\n out.push(a)\n }\n return out\n}\n"],"mappings":"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","names":[]}
|
package/dist/wire/index.js
CHANGED
package/docs/concepts.md
CHANGED
|
@@ -43,7 +43,7 @@ that can seed memory, replay scenarios, and optimization.
|
|
|
43
43
|
| **Trace store** | The append-only log of every span/event during a run. Replay = read this back. |
|
|
44
44
|
| **Composite score** | A 0..1 number combining all dimensions. The single number you gate on. |
|
|
45
45
|
| **Rubric version** | A stable hash of the rubric. Scores from different rubric versions are not comparable. |
|
|
46
|
-
| **Muffled gate** | A check that should fail loud but silently passes (e.g. `command || true`). The most expensive bug class in this codebase
|
|
46
|
+
| **Muffled gate** | A check that should fail loud but silently passes (e.g. `command || true`). The most expensive bug class in this codebase. |
|
|
47
47
|
|
|
48
48
|
## The feedback trajectory loop
|
|
49
49
|
|
|
@@ -119,7 +119,7 @@ report.blendedScore // 0..1 — weighted aggregate
|
|
|
119
119
|
report.layers // per-layer status, findings, duration
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
Two rules that will save you bugs
|
|
122
|
+
Two rules that will save you bugs:
|
|
123
123
|
|
|
124
124
|
1. **Run both gates.** Build gates catch code that doesn't compile; structural assertions catch missing files. Run both unconditionally — they catch orthogonal failures.
|
|
125
125
|
|
|
@@ -150,6 +150,6 @@ You don't need to build the trace tree by hand. `BuilderSession` does it for you
|
|
|
150
150
|
- **Just want to score a string against a rubric?** → [wire-protocol.md](./wire-protocol.md) — HTTP/RPC interface, pluggable from any language.
|
|
151
151
|
- **Need a reusable driver/worker/evaluator loop?** → [control-runtime.md](./control-runtime.md) — generic runtime plus coding, browser, computer-use, and research integration patterns.
|
|
152
152
|
- **Want review feedback to become eval/optimization data?** → [feedback-trajectories.md](./feedback-trajectories.md) — turn feedback into datasets, optimizer rows, and preference memory.
|
|
153
|
-
- **Building a code-generator eval?** →
|
|
154
|
-
- **Multi-layer verifier?** →
|
|
153
|
+
- **Building a code-generator eval?** → Start with `BuilderSession`, `SandboxHarness`, and `MultiLayerVerifier`.
|
|
154
|
+
- **Multi-layer verifier?** → Use [control-runtime.md](./control-runtime.md) and `MultiLayerVerifier` for ordered gates with dependencies.
|
|
155
155
|
- **Adding a new judge or rubric?** → `src/wire/rubrics.ts` for the cross-language path; `src/anti-slop.ts` and `src/judges.ts` for the in-process path.
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
`agent-eval` owns the contract for deciding whether an agent had enough
|
|
4
4
|
task-world context to run. It does not own web crawling, connector storage, wiki
|
|
5
|
-
pages, credentials, or product policy. Those live in
|
|
6
|
-
product repos.
|
|
5
|
+
pages, credentials, or product policy. Those live in
|
|
6
|
+
`@tangle-network/agent-knowledge` and product repos.
|
|
7
7
|
|
|
8
8
|
The core loop is:
|
|
9
9
|
|
package/docs/wire-protocol.md
CHANGED
|
@@ -96,13 +96,13 @@ GET /v1/version
|
|
|
96
96
|
```json
|
|
97
97
|
{
|
|
98
98
|
"package": "@tangle-network/agent-eval",
|
|
99
|
-
"version": "0.
|
|
99
|
+
"version": "0.20.10",
|
|
100
100
|
"wireVersion": "1.0.0",
|
|
101
101
|
"apiSurface": ["judge", "listRubrics", "version"]
|
|
102
102
|
}
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
`version` matches the
|
|
105
|
+
`version` matches the package version. `wireVersion` bumps independently — only on breaking request/response schema changes. Package versions can differ across releases as long as `wireVersion` matches.
|
|
106
106
|
|
|
107
107
|
### `GET /healthz` — liveness
|
|
108
108
|
|
|
@@ -176,7 +176,7 @@ Each invocation is one process — Node startup adds ~500 ms. For more than a fe
|
|
|
176
176
|
|
|
177
177
|
## Clients
|
|
178
178
|
|
|
179
|
-
- **Python**: [`tangle-agent-eval
|
|
179
|
+
- **Python**: source lives in [`clients/python`](https://github.com/tangle-network/agent-eval/tree/main/clients/python). Auto-detects HTTP, falls back to subprocess. Version-locked to npm.
|
|
180
180
|
- **TypeScript**: import directly from `@tangle-network/agent-eval` (no wire round-trip needed in-process).
|
|
181
181
|
- **Rust / Go / Other**: generate from `dist/openapi.json`. PRs welcome to add an officially-maintained client.
|
|
182
182
|
|