@lunora/testing 1.0.0-alpha.50 → 1.0.0-alpha.52
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/dist/index.d.mts
CHANGED
|
@@ -110,6 +110,53 @@ declare const agentHarness: (agent: AgentDefinition, options: AgentHarnessOption
|
|
|
110
110
|
declare const finalTurn: (text: string, extra?: Partial<AgentGenerateResult>) => AgentGenerateResult;
|
|
111
111
|
/** A single-tool-call turn: the loop runs the named tool with `input`. */
|
|
112
112
|
declare const toolCallTurn: (id: string, name: string, input: unknown, text?: string) => AgentGenerateResult;
|
|
113
|
+
/** The primitive an eval attaches to a span: a numeric score or a string label. */
|
|
114
|
+
type EvaluationAttributeValue = number | string;
|
|
115
|
+
/**
|
|
116
|
+
* Structural slice of the post-hoc span handle `ctx.trace` hands its body (see the
|
|
117
|
+
* server `SpanHandle`) — enough to attach an eval's attributes. Declared here
|
|
118
|
+
* rather than imported so `@lunora/testing` takes no dependency on `@lunora/server`
|
|
119
|
+
* or `@lunora/do`; the real handle is assignable to it.
|
|
120
|
+
*/
|
|
121
|
+
interface EvaluationSpanHandle {
|
|
122
|
+
setAttributes: (fields: Record<string, EvaluationAttributeValue>) => void;
|
|
123
|
+
}
|
|
124
|
+
/** One eval verdict to emit. */
|
|
125
|
+
interface RecordEvaluationInput {
|
|
126
|
+
/**
|
|
127
|
+
* Optional categorical label (e.g. `"pass"` / `"fail"` / a rubric bucket),
|
|
128
|
+
* emitted as the `.label` attribute. Omitted → no label attribute.
|
|
129
|
+
*/
|
|
130
|
+
label?: string;
|
|
131
|
+
/**
|
|
132
|
+
* The scorer/evaluation name — becomes the key's name segment. Any character
|
|
133
|
+
* outside `[A-Za-z0-9._-]` is replaced with `_` so a scorer name carrying a
|
|
134
|
+
* colon (e.g. `"contains:shipped"`) still yields a well-formed attribute key.
|
|
135
|
+
*/
|
|
136
|
+
name: string;
|
|
137
|
+
/** The numeric score (typically `[0, 1]`), emitted as the `.score` attribute. */
|
|
138
|
+
score: number;
|
|
139
|
+
/**
|
|
140
|
+
* Optional generation span to attach the attributes to — the post-hoc
|
|
141
|
+
* `SpanHandle` a `ctx.trace` body receives. Omitted → nothing is attached and
|
|
142
|
+
* the caller uses the returned bag for a standalone event/metric.
|
|
143
|
+
*/
|
|
144
|
+
span?: EvaluationSpanHandle;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Build the `gen_ai.evaluation.NAME.*` attribute bag for one eval verdict — the
|
|
148
|
+
* `.score` (number) always, the `.label` (string) when a label is given. Exported
|
|
149
|
+
* so a caller can emit the score as a standalone event/metric without a span.
|
|
150
|
+
*/
|
|
151
|
+
declare const evaluationAttributes: (input: Pick<RecordEvaluationInput, "label" | "name" | "score">) => Record<string, EvaluationAttributeValue>;
|
|
152
|
+
/**
|
|
153
|
+
* Emit one eval verdict as `gen_ai.evaluation.NAME.*` attributes. Attaches them to
|
|
154
|
+
* `input.span` when supplied (the post-hoc generation-span handle), and always
|
|
155
|
+
* returns the attribute bag so a span-less caller can ship it as an eval
|
|
156
|
+
* event/metric. Privacy-safe: only the name, score, and optional label are
|
|
157
|
+
* emitted — never the graded prompt or output.
|
|
158
|
+
*/
|
|
159
|
+
declare const recordEvaluation: (input: RecordEvaluationInput) => Record<string, EvaluationAttributeValue>;
|
|
113
160
|
/** A pending job entry in the fake scheduler queue. */
|
|
114
161
|
interface FakeScheduledJob extends ScheduledJob {
|
|
115
162
|
/** The args the job was scheduled with. */
|
|
@@ -460,4 +507,4 @@ declare const scoreSample: (sample: ScorerSample, scorers: ReadonlyArray<Scorer>
|
|
|
460
507
|
* Returns per-case results plus the mean of their averages.
|
|
461
508
|
*/
|
|
462
509
|
declare const evaluate: (cases: ReadonlyArray<EvalCase>, produce: (input: string) => Promise<string> | string, scorers: ReadonlyArray<Scorer>) => Promise<EvalResult>;
|
|
463
|
-
export { type AgentHarness, type AgentHarnessOptions, type AgentRunOverrides, type EvalCase, type EvalItemResult, type EvalResult, type FakeScheduledJob, type FakeSchedulerControls, type FunctionRegistry, type HarnessDispatch, type HarnessMessage, type HarnessThread, type LunoraTestOptions, type ScheduledJobFailure, type ScoreResult, type Scorer, type ScorerSample, type SweepOptions, type TestHarness, type TestIdentity, type TestSubscription, agentHarness, containsScorer, evaluate, exactMatchScorer, finalTurn, keywordScorer, llmScorer, lunoraTest, regexScorer, scoreSample, toolCallTurn };
|
|
510
|
+
export { type AgentHarness, type AgentHarnessOptions, type AgentRunOverrides, type EvalCase, type EvalItemResult, type EvalResult, type EvaluationAttributeValue, type EvaluationSpanHandle, type FakeScheduledJob, type FakeSchedulerControls, type FunctionRegistry, type HarnessDispatch, type HarnessMessage, type HarnessThread, type LunoraTestOptions, type RecordEvaluationInput, type ScheduledJobFailure, type ScoreResult, type Scorer, type ScorerSample, type SweepOptions, type TestHarness, type TestIdentity, type TestSubscription, agentHarness, containsScorer, evaluate, evaluationAttributes, exactMatchScorer, finalTurn, keywordScorer, llmScorer, lunoraTest, recordEvaluation, regexScorer, scoreSample, toolCallTurn };
|
package/dist/index.d.ts
CHANGED
|
@@ -110,6 +110,53 @@ declare const agentHarness: (agent: AgentDefinition, options: AgentHarnessOption
|
|
|
110
110
|
declare const finalTurn: (text: string, extra?: Partial<AgentGenerateResult>) => AgentGenerateResult;
|
|
111
111
|
/** A single-tool-call turn: the loop runs the named tool with `input`. */
|
|
112
112
|
declare const toolCallTurn: (id: string, name: string, input: unknown, text?: string) => AgentGenerateResult;
|
|
113
|
+
/** The primitive an eval attaches to a span: a numeric score or a string label. */
|
|
114
|
+
type EvaluationAttributeValue = number | string;
|
|
115
|
+
/**
|
|
116
|
+
* Structural slice of the post-hoc span handle `ctx.trace` hands its body (see the
|
|
117
|
+
* server `SpanHandle`) — enough to attach an eval's attributes. Declared here
|
|
118
|
+
* rather than imported so `@lunora/testing` takes no dependency on `@lunora/server`
|
|
119
|
+
* or `@lunora/do`; the real handle is assignable to it.
|
|
120
|
+
*/
|
|
121
|
+
interface EvaluationSpanHandle {
|
|
122
|
+
setAttributes: (fields: Record<string, EvaluationAttributeValue>) => void;
|
|
123
|
+
}
|
|
124
|
+
/** One eval verdict to emit. */
|
|
125
|
+
interface RecordEvaluationInput {
|
|
126
|
+
/**
|
|
127
|
+
* Optional categorical label (e.g. `"pass"` / `"fail"` / a rubric bucket),
|
|
128
|
+
* emitted as the `.label` attribute. Omitted → no label attribute.
|
|
129
|
+
*/
|
|
130
|
+
label?: string;
|
|
131
|
+
/**
|
|
132
|
+
* The scorer/evaluation name — becomes the key's name segment. Any character
|
|
133
|
+
* outside `[A-Za-z0-9._-]` is replaced with `_` so a scorer name carrying a
|
|
134
|
+
* colon (e.g. `"contains:shipped"`) still yields a well-formed attribute key.
|
|
135
|
+
*/
|
|
136
|
+
name: string;
|
|
137
|
+
/** The numeric score (typically `[0, 1]`), emitted as the `.score` attribute. */
|
|
138
|
+
score: number;
|
|
139
|
+
/**
|
|
140
|
+
* Optional generation span to attach the attributes to — the post-hoc
|
|
141
|
+
* `SpanHandle` a `ctx.trace` body receives. Omitted → nothing is attached and
|
|
142
|
+
* the caller uses the returned bag for a standalone event/metric.
|
|
143
|
+
*/
|
|
144
|
+
span?: EvaluationSpanHandle;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Build the `gen_ai.evaluation.NAME.*` attribute bag for one eval verdict — the
|
|
148
|
+
* `.score` (number) always, the `.label` (string) when a label is given. Exported
|
|
149
|
+
* so a caller can emit the score as a standalone event/metric without a span.
|
|
150
|
+
*/
|
|
151
|
+
declare const evaluationAttributes: (input: Pick<RecordEvaluationInput, "label" | "name" | "score">) => Record<string, EvaluationAttributeValue>;
|
|
152
|
+
/**
|
|
153
|
+
* Emit one eval verdict as `gen_ai.evaluation.NAME.*` attributes. Attaches them to
|
|
154
|
+
* `input.span` when supplied (the post-hoc generation-span handle), and always
|
|
155
|
+
* returns the attribute bag so a span-less caller can ship it as an eval
|
|
156
|
+
* event/metric. Privacy-safe: only the name, score, and optional label are
|
|
157
|
+
* emitted — never the graded prompt or output.
|
|
158
|
+
*/
|
|
159
|
+
declare const recordEvaluation: (input: RecordEvaluationInput) => Record<string, EvaluationAttributeValue>;
|
|
113
160
|
/** A pending job entry in the fake scheduler queue. */
|
|
114
161
|
interface FakeScheduledJob extends ScheduledJob {
|
|
115
162
|
/** The args the job was scheduled with. */
|
|
@@ -460,4 +507,4 @@ declare const scoreSample: (sample: ScorerSample, scorers: ReadonlyArray<Scorer>
|
|
|
460
507
|
* Returns per-case results plus the mean of their averages.
|
|
461
508
|
*/
|
|
462
509
|
declare const evaluate: (cases: ReadonlyArray<EvalCase>, produce: (input: string) => Promise<string> | string, scorers: ReadonlyArray<Scorer>) => Promise<EvalResult>;
|
|
463
|
-
export { type AgentHarness, type AgentHarnessOptions, type AgentRunOverrides, type EvalCase, type EvalItemResult, type EvalResult, type FakeScheduledJob, type FakeSchedulerControls, type FunctionRegistry, type HarnessDispatch, type HarnessMessage, type HarnessThread, type LunoraTestOptions, type ScheduledJobFailure, type ScoreResult, type Scorer, type ScorerSample, type SweepOptions, type TestHarness, type TestIdentity, type TestSubscription, agentHarness, containsScorer, evaluate, exactMatchScorer, finalTurn, keywordScorer, llmScorer, lunoraTest, regexScorer, scoreSample, toolCallTurn };
|
|
510
|
+
export { type AgentHarness, type AgentHarnessOptions, type AgentRunOverrides, type EvalCase, type EvalItemResult, type EvalResult, type EvaluationAttributeValue, type EvaluationSpanHandle, type FakeScheduledJob, type FakeSchedulerControls, type FunctionRegistry, type HarnessDispatch, type HarnessMessage, type HarnessThread, type LunoraTestOptions, type RecordEvaluationInput, type ScheduledJobFailure, type ScoreResult, type Scorer, type ScorerSample, type SweepOptions, type TestHarness, type TestIdentity, type TestSubscription, agentHarness, containsScorer, evaluate, evaluationAttributes, exactMatchScorer, finalTurn, keywordScorer, llmScorer, lunoraTest, recordEvaluation, regexScorer, scoreSample, toolCallTurn };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { agentHarness, finalTurn, toolCallTurn } from './packem_shared/agentHarness-GTPhWdQ8.mjs';
|
|
2
|
-
export {
|
|
2
|
+
export { evaluationAttributes, recordEvaluation } from './packem_shared/evaluationAttributes-C08Q5MOX.mjs';
|
|
3
|
+
export { lunoraTest } from './packem_shared/lunoraTest-Dv_w_v9z.mjs';
|
|
3
4
|
export { containsScorer, evaluate, exactMatchScorer, keywordScorer, llmScorer, regexScorer, scoreSample } from './packem_shared/containsScorer-DGwtvUNp.mjs';
|
|
4
5
|
export { extractLink, listCapturedMail, waitForMail } from '@lunora/mail/testing';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
3
|
+
const SAFE_NAME_CHAR = /[\w.-]/u;
|
|
4
|
+
const sanitizeName = (name) => {
|
|
5
|
+
let out = "";
|
|
6
|
+
for (const char of name) {
|
|
7
|
+
out += SAFE_NAME_CHAR.test(char) ? char : "_";
|
|
8
|
+
}
|
|
9
|
+
return out;
|
|
10
|
+
};
|
|
11
|
+
const evaluationAttributes = (input) => {
|
|
12
|
+
if (typeof input.name !== "string" || input.name.length === 0) {
|
|
13
|
+
throw new LunoraError("BAD_REQUEST", "@lunora/testing: recordEvaluation requires a non-empty `name`");
|
|
14
|
+
}
|
|
15
|
+
if (typeof input.score !== "number" || !Number.isFinite(input.score)) {
|
|
16
|
+
throw new LunoraError("BAD_REQUEST", "@lunora/testing: recordEvaluation `score` must be a finite number");
|
|
17
|
+
}
|
|
18
|
+
const key = sanitizeName(input.name);
|
|
19
|
+
const attributes = { [`gen_ai.evaluation.${key}.score`]: input.score };
|
|
20
|
+
if (input.label !== void 0) {
|
|
21
|
+
attributes[`gen_ai.evaluation.${key}.label`] = input.label;
|
|
22
|
+
}
|
|
23
|
+
return attributes;
|
|
24
|
+
};
|
|
25
|
+
const recordEvaluation = (input) => {
|
|
26
|
+
const attributes = evaluationAttributes(input);
|
|
27
|
+
input.span?.setAttributes(attributes);
|
|
28
|
+
return attributes;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { evaluationAttributes, recordEvaluation };
|
|
@@ -151,7 +151,11 @@ const stubProxy = (surface) => /* @__PURE__ */ new Proxy((..._args) => unavailab
|
|
|
151
151
|
apply: () => unavailable(surface),
|
|
152
152
|
get: () => unavailable(surface)
|
|
153
153
|
});
|
|
154
|
-
const
|
|
154
|
+
const noopSpan = {
|
|
155
|
+
setAttribute: () => void 0,
|
|
156
|
+
setAttributes: () => void 0
|
|
157
|
+
};
|
|
158
|
+
const passthroughTrace = async (_name, function_) => await function_(passthroughTrace, noopSpan);
|
|
155
159
|
const noopMetrics = {
|
|
156
160
|
count: () => void 0,
|
|
157
161
|
gauge: () => void 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/testing",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.52",
|
|
4
4
|
"description": "Testing toolkit for Lunora: an in-memory harness for queries, mutations, and actions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/agent": "1.0.0-alpha.
|
|
50
|
-
"@lunora/do": "1.0.0-alpha.
|
|
51
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
52
|
-
"@lunora/mail": "1.0.0-alpha.
|
|
53
|
-
"@lunora/server": "1.0.0-alpha.
|
|
49
|
+
"@lunora/agent": "1.0.0-alpha.9",
|
|
50
|
+
"@lunora/do": "1.0.0-alpha.41",
|
|
51
|
+
"@lunora/errors": "1.0.0-alpha.7",
|
|
52
|
+
"@lunora/mail": "1.0.0-alpha.17",
|
|
53
|
+
"@lunora/server": "1.0.0-alpha.30"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": "^22.15.0 || >=24.11.0"
|