openmerit 0.4.1 → 0.4.2
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 +239 -58
- package/data/catalogue.json +6778 -0
- package/dist/catalogue/catalogue.d.ts +41 -0
- package/dist/catalogue/catalogue.js +33 -0
- package/dist/cli/prompt.d.ts +26 -0
- package/dist/cli/prompt.js +114 -0
- package/dist/cli/render.d.ts +12 -0
- package/dist/cli/render.js +104 -0
- package/dist/cli.js +245 -158
- package/dist/connect.d.ts +34 -0
- package/dist/connect.js +158 -0
- package/dist/connectors/langfuse/index.d.ts +37 -110
- package/dist/connectors/langfuse/index.js +95 -246
- package/dist/daemon/daemon.d.ts +81 -0
- package/dist/daemon/daemon.js +408 -0
- package/dist/daemon/registry.d.ts +111 -0
- package/dist/daemon/registry.js +109 -0
- package/dist/eval/proxy.d.ts +54 -0
- package/dist/eval/proxy.js +174 -0
- package/dist/eval/runner.d.ts +29 -0
- package/dist/eval/runner.js +80 -0
- package/dist/harness/claude-bridge.d.ts +21 -0
- package/dist/harness/claude-bridge.js +65 -0
- package/dist/harness/harness.d.ts +60 -0
- package/dist/harness/harness.js +221 -0
- package/dist/index.d.ts +9 -10
- package/dist/index.js +9 -10
- package/dist/local.d.ts +12 -0
- package/dist/local.js +40 -0
- package/dist/mcp.d.ts +1 -0
- package/dist/mcp.js +155 -0
- package/dist/scout/pool.d.ts +17 -0
- package/dist/scout/pool.js +56 -0
- package/dist/scout/scan.d.ts +42 -0
- package/dist/scout/scan.js +169 -0
- package/dist/scout/search.d.ts +25 -98
- package/dist/scout/search.js +56 -156
- package/dist/scout/workflow.d.ts +221 -0
- package/dist/scout/workflow.js +941 -0
- package/dist/setup.d.ts +44 -0
- package/dist/setup.js +211 -0
- package/dist/state/config.d.ts +116 -0
- package/dist/state/config.js +60 -0
- package/dist/state/db.d.ts +159 -0
- package/dist/state/db.js +260 -0
- package/dist/state/paths.d.ts +12 -0
- package/dist/state/paths.js +23 -0
- package/dist/update.d.ts +22 -0
- package/dist/update.js +58 -0
- package/package.json +12 -17
- package/dist/connectors/langfuse/otlp.d.ts +0 -60
- package/dist/connectors/langfuse/otlp.js +0 -40
- package/dist/pi/extension.d.ts +0 -13
- package/dist/pi/extension.js +0 -148
- package/dist/pi/harness.d.ts +0 -20
- package/dist/pi/harness.js +0 -49
- package/dist/pi/instructions.d.ts +0 -2
- package/dist/pi/instructions.js +0 -12
- package/dist/scout/evaluators/module.d.ts +0 -24
- package/dist/scout/evaluators/module.js +0 -19
- package/dist/scout/evaluators/pi.d.ts +0 -53
- package/dist/scout/evaluators/pi.js +0 -117
- package/dist/scout/pipeline.d.ts +0 -111
- package/dist/scout/pipeline.js +0 -157
- package/dist/scout/report.d.ts +0 -3
- package/dist/scout/report.js +0 -42
- package/dist/scout/service.d.ts +0 -148
- package/dist/scout/service.js +0 -143
- package/examples/health-declaration-codes/dataset.jsonl +0 -14
- package/examples/sahra-enrollment/evaluator.mts +0 -152
package/dist/connect.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { DEFAULT_CLAUDE_MODEL } from "./harness/claude-bridge.js";
|
|
2
|
+
import { loadCatalogue } from "./catalogue/catalogue.js";
|
|
3
|
+
import { CODEX_PROVIDER, createHarness, detectAgents, harnessRuntime, runClaude, verifyHarness } from "./harness/harness.js";
|
|
4
|
+
import { readGlobalConfig, storeSecret, updateGlobalConfig } from "./state/config.js";
|
|
5
|
+
export const HARNESS_LABEL = { "claude-code": "Claude Code", codex: "Codex (ChatGPT sign-in)", api: "an API key" };
|
|
6
|
+
const interactive = (ctx) => !!ctx.prompter && !ctx.flags.nonInteractive;
|
|
7
|
+
export async function confirm(ctx, question, fallback) { return interactive(ctx) ? ctx.prompter.confirm(question, fallback) : fallback; }
|
|
8
|
+
/** A key from an environment variable (kept as a reference) or typed in (stored in ~/.openmerit/secrets.json). */
|
|
9
|
+
export async function credential(ctx, label, envNames, secretName, flagEnv) {
|
|
10
|
+
if (flagEnv)
|
|
11
|
+
return ctx.env[flagEnv] ? { env: flagEnv } : (() => { throw new Error(`$${flagEnv} is not set.`); })();
|
|
12
|
+
const present = envNames.find(name => ctx.env[name]?.trim());
|
|
13
|
+
if (present && await confirm(ctx, `Use $${present} for the ${label}?`, true))
|
|
14
|
+
return { env: present };
|
|
15
|
+
if (!interactive(ctx))
|
|
16
|
+
return null;
|
|
17
|
+
const value = await ctx.prompter.secret(`${label} (input hidden; stored in ~/.openmerit/secrets.json, outside the repository):`);
|
|
18
|
+
return value ? storeSecret(secretName, value, ctx.env) : null;
|
|
19
|
+
}
|
|
20
|
+
/** Pi's login prompts and notices in the terminal, or on stderr only without one (device code). */
|
|
21
|
+
function authInteraction(ctx) {
|
|
22
|
+
return {
|
|
23
|
+
async prompt(prompt) {
|
|
24
|
+
if (prompt.type === "select") {
|
|
25
|
+
const ids = prompt.options.map(option => option.id);
|
|
26
|
+
const device = ids.find(id => id === "device_code");
|
|
27
|
+
if (device && (ctx.flags.deviceCode || !interactive(ctx)))
|
|
28
|
+
return device;
|
|
29
|
+
if (!interactive(ctx))
|
|
30
|
+
return ids[0];
|
|
31
|
+
return ctx.prompter.choose(prompt.message, prompt.options.map(option => ({ value: option.id, label: option.label })), ids[0]);
|
|
32
|
+
}
|
|
33
|
+
if (!interactive(ctx))
|
|
34
|
+
throw new Error(`${prompt.message} needs a terminal. Rerun with --device-code.`);
|
|
35
|
+
return prompt.type === "secret" ? ctx.prompter.secret(prompt.message) : ctx.prompter.ask(prompt.message, "", prompt.signal);
|
|
36
|
+
},
|
|
37
|
+
notify(event) {
|
|
38
|
+
if (event.type === "auth_url")
|
|
39
|
+
ctx.log(` Open this URL to sign in to ChatGPT:\n ${event.url}${event.instructions ? `\n ${event.instructions}` : ""}`);
|
|
40
|
+
else if (event.type === "device_code")
|
|
41
|
+
ctx.log(` On any device, open ${event.verificationUri} and enter the code ${event.userCode}${event.expiresInSeconds ? ` within ${Math.round(event.expiresInSeconds / 60)} minutes` : ""}.`);
|
|
42
|
+
else
|
|
43
|
+
ctx.log(` ${event.message}`);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** OpenAI's reply when a ChatGPT plan does not include a Codex model. */
|
|
48
|
+
const NOT_ON_PLAN = /not supported when using Codex with a ChatGPT account/i;
|
|
49
|
+
/** Pi's Codex models, most capable (by the bundled catalogue's ECI) first. */
|
|
50
|
+
async function codexModelsByEci(env) {
|
|
51
|
+
const eci = new Map(loadCatalogue().models.map(model => [model.id, model.eci ?? 0]));
|
|
52
|
+
const score = (id) => eci.get(`openai/${id}`) ?? 0;
|
|
53
|
+
return (await harnessRuntime(env)).getModels(CODEX_PROVIDER).map(model => model.id).sort((a, b) => score(b) - score(a));
|
|
54
|
+
}
|
|
55
|
+
/** Makes sure the chosen connection is signed in. Returns false when the user declined. */
|
|
56
|
+
async function signIn(ctx, kind) {
|
|
57
|
+
if (kind === "api")
|
|
58
|
+
return true;
|
|
59
|
+
const agent = (await detectAgents(ctx.env)).find(item => item.kind === kind);
|
|
60
|
+
if (agent.loggedIn)
|
|
61
|
+
return true;
|
|
62
|
+
if (kind === "claude-code") {
|
|
63
|
+
if (!interactive(ctx))
|
|
64
|
+
throw new Error("Claude Code is not logged in. Run `openmerit connect claude-code` in a terminal to log in, or on a server set CLAUDE_CODE_OAUTH_TOKEN from `claude setup-token`.");
|
|
65
|
+
if (!(await confirm(ctx, "Claude Code is not logged in. Log in with your Claude subscription now?", true)))
|
|
66
|
+
return false;
|
|
67
|
+
await ctx.prompter.handOver(() => runClaude(["auth", "login"], { env: ctx.env, interactive: true }));
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
ctx.log(" Signing in to ChatGPT (Plus or Pro) for Codex models. OpenMerit keeps the sign-in in ~/.openmerit/agent/auth.json.");
|
|
71
|
+
const runtime = await harnessRuntime(ctx.env);
|
|
72
|
+
await runtime.login(CODEX_PROVIDER, "oauth", authInteraction(ctx));
|
|
73
|
+
await runtime.settleCredentialWrites();
|
|
74
|
+
ctx.log(" ✓ Signed in to ChatGPT.");
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Connects OpenMerit Harness. With `kind`, connects that; without it, keeps a working saved
|
|
79
|
+
* connection when the user agrees, and otherwise asks which to use.
|
|
80
|
+
*/
|
|
81
|
+
export async function connect(ctx, kind) {
|
|
82
|
+
const existing = readGlobalConfig(ctx.env).harness;
|
|
83
|
+
if (existing && !kind) {
|
|
84
|
+
ctx.log(`Checking the current harness connection (${HARNESS_LABEL[existing.kind]}${existing.model ? `, ${existing.model}` : ""})…`);
|
|
85
|
+
const check = await createHarness(existing, ctx.env).then(harness => verifyHarness(harness, ctx.root), (error) => ({ ok: false, detail: error instanceof Error ? error.message : String(error) }));
|
|
86
|
+
if (check.ok) {
|
|
87
|
+
ctx.log(` ✓ OpenMerit Harness runs on ${HARNESS_LABEL[existing.kind]} (${check.detail}).`);
|
|
88
|
+
if (await confirm(ctx, "Keep this harness connection?", true)) {
|
|
89
|
+
const saved = { ...existing, verifiedAt: new Date().toISOString() };
|
|
90
|
+
updateGlobalConfig({ harness: saved }, ctx.env);
|
|
91
|
+
return saved;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else
|
|
95
|
+
ctx.log(` ✗ The saved harness connection failed: ${check.detail}`);
|
|
96
|
+
}
|
|
97
|
+
for (;;) {
|
|
98
|
+
if (!kind) {
|
|
99
|
+
if (!interactive(ctx))
|
|
100
|
+
throw new Error("Choose how to power OpenMerit Harness: `openmerit connect claude-code`, `codex` or `api`.");
|
|
101
|
+
const agents = await detectAgents(ctx.env);
|
|
102
|
+
kind = await ctx.prompter.choose("Which should power OpenMerit Harness?", [
|
|
103
|
+
...agents.map(agent => ({ value: agent.kind, label: `${HARNESS_LABEL[agent.kind]} (${agent.detail})` })),
|
|
104
|
+
{ value: "api", label: "An API provider, key and model" },
|
|
105
|
+
], agents.find(agent => agent.loggedIn)?.kind ?? "claude-code");
|
|
106
|
+
}
|
|
107
|
+
const settings = { kind };
|
|
108
|
+
if (kind === "api") {
|
|
109
|
+
const provider = ctx.flags.apiProvider ?? (interactive(ctx) ? await ctx.prompter.ask("Pi provider for the harness (anthropic, openai, openrouter, google, ...)", existing?.api?.provider ?? "anthropic") : "anthropic");
|
|
110
|
+
const suggested = (existing?.api?.provider === provider ? existing.api.model : undefined) ?? (provider === "openai" ? "gpt-6.1-sol" : provider === "openrouter" ? "anthropic/claude-sonnet-5.5" : "claude-sonnet-5-5");
|
|
111
|
+
const model = ctx.flags.apiModel ?? (interactive(ctx) ? await ctx.prompter.ask("Model", suggested) : suggested);
|
|
112
|
+
const envNames = { anthropic: ["ANTHROPIC_API_KEY"], openai: ["OPENAI_API_KEY"], openrouter: ["OPENROUTER_API_KEY"], google: ["GEMINI_API_KEY", "GOOGLE_API_KEY"] }[provider] ?? [];
|
|
113
|
+
const apiKey = await credential(ctx, `${provider} API key for the harness`, envNames, `harness-${provider}`, ctx.flags.apiKeyEnv);
|
|
114
|
+
if (!apiKey)
|
|
115
|
+
throw new Error("The API harness needs a key: pass --api-key-env <VAR>.");
|
|
116
|
+
settings.api = { provider, model, apiKey };
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const chosen = ctx.flags.model ?? (existing?.kind === kind ? existing.model : undefined);
|
|
120
|
+
if (chosen || kind === "claude-code")
|
|
121
|
+
settings.model = chosen ?? DEFAULT_CLAUDE_MODEL;
|
|
122
|
+
ctx.log(settings.model ? ` Model: ${settings.model} (change it with --model).` : " Model: the most capable Codex model your ChatGPT plan allows (choose one with --model).");
|
|
123
|
+
}
|
|
124
|
+
let check = { ok: false, detail: "no model to try" };
|
|
125
|
+
try {
|
|
126
|
+
if (!(await signIn(ctx, kind)))
|
|
127
|
+
return null;
|
|
128
|
+
// Which Codex models a ChatGPT account may use depends on its plan, and OpenAI does not list them: try them by ECI.
|
|
129
|
+
const models = kind === "codex" && !settings.model ? await codexModelsByEci(ctx.env) : [settings.model];
|
|
130
|
+
for (const model of models) {
|
|
131
|
+
if (model)
|
|
132
|
+
settings.model = model;
|
|
133
|
+
ctx.log(`Verifying that ${HARNESS_LABEL[kind]}${model ? ` (${model})` : ""} powers OpenMerit Harness…`);
|
|
134
|
+
check = await verifyHarness(await createHarness(settings, ctx.env), ctx.root);
|
|
135
|
+
if (check.ok || !NOT_ON_PLAN.test(check.detail))
|
|
136
|
+
break;
|
|
137
|
+
ctx.log(` ${model} is not available on this ChatGPT plan.`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
check = { ok: false, detail: error instanceof Error ? error.message : String(error) };
|
|
142
|
+
}
|
|
143
|
+
if (check.ok) {
|
|
144
|
+
ctx.log(` ✓ ${HARNESS_LABEL[kind]} answered through OpenMerit Harness (${check.detail}).`);
|
|
145
|
+
const saved = { ...settings, verifiedAt: new Date().toISOString() };
|
|
146
|
+
updateGlobalConfig({ harness: saved }, ctx.env);
|
|
147
|
+
return saved;
|
|
148
|
+
}
|
|
149
|
+
ctx.log(` ✗ ${HARNESS_LABEL[kind]} did not answer: ${check.detail}`);
|
|
150
|
+
if (!interactive(ctx))
|
|
151
|
+
throw new Error(`${HARNESS_LABEL[kind]} could not power the harness: ${check.detail}${existing ? ". Your previous harness settings are unchanged." : ""}`);
|
|
152
|
+
const next = await ctx.prompter.choose("What now?", [{ value: "retry", label: `Retry ${HARNESS_LABEL[kind]}` }, { value: "other", label: "Choose another connection" }, { value: "quit", label: existing ? "Stop and keep the previous settings" : "Stop" }], "retry");
|
|
153
|
+
if (next === "quit")
|
|
154
|
+
return null;
|
|
155
|
+
if (next === "other")
|
|
156
|
+
kind = undefined;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -1,27 +1,6 @@
|
|
|
1
1
|
import { type LangfuseConnection, type TransportOptions } from "./client.js";
|
|
2
2
|
export { connectionFromEnv, type LangfuseConnection, LangfuseError, normalizeBaseUrl, type TransportOptions } from "./client.js";
|
|
3
3
|
export type ScoreValue = number | boolean | string;
|
|
4
|
-
export type Metadata = Record<string, string | number | boolean>;
|
|
5
|
-
export interface EvalItem {
|
|
6
|
-
id: string;
|
|
7
|
-
input: unknown;
|
|
8
|
-
expectedOutput: unknown;
|
|
9
|
-
metadata: Record<string, unknown>;
|
|
10
|
-
}
|
|
11
|
-
export interface DatasetSummary {
|
|
12
|
-
id: string;
|
|
13
|
-
name: string;
|
|
14
|
-
}
|
|
15
|
-
export interface ExperimentSummary {
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
datasetId: string | null;
|
|
19
|
-
itemCount: number | null;
|
|
20
|
-
startTime: string | null;
|
|
21
|
-
metadata: Record<string, unknown>;
|
|
22
|
-
/** Experiment metadata `model_<role>` entries, e.g. { enrollment: "openrouter/anthropic/claude-sonnet-5.5" }. */
|
|
23
|
-
models: Record<string, string>;
|
|
24
|
-
}
|
|
25
4
|
/**
|
|
26
5
|
* Decides whether one item passed from one score. With no condition, a BOOLEAN score must be true
|
|
27
6
|
* and a NUMERIC score must be 1. `equals` compares exactly; `min`/`max` are inclusive numeric bounds.
|
|
@@ -38,12 +17,10 @@ export interface ItemResult {
|
|
|
38
17
|
passed: boolean;
|
|
39
18
|
/** The pass score was absent: the item failed to run or was not scored. It never counts as a pass. */
|
|
40
19
|
missingScore: boolean;
|
|
41
|
-
scores: Record<string, ScoreValue>;
|
|
42
|
-
costUsd: number | null;
|
|
43
20
|
}
|
|
44
21
|
export interface ExperimentResult {
|
|
45
|
-
experimentId: string;
|
|
46
22
|
experimentName: string;
|
|
23
|
+
experimentId: string;
|
|
47
24
|
datasetId: string | null;
|
|
48
25
|
items: ItemResult[];
|
|
49
26
|
passes: number;
|
|
@@ -52,74 +29,34 @@ export interface ExperimentResult {
|
|
|
52
29
|
missing: string[];
|
|
53
30
|
/** Item IDs present without the pass score. */
|
|
54
31
|
missingScores: string[];
|
|
55
|
-
/** Sum of generation costs Langfuse recorded for the items; null when not requested or none recorded. */
|
|
56
|
-
costUsd: number | null;
|
|
57
32
|
}
|
|
58
33
|
export interface ExperimentQuery {
|
|
59
|
-
|
|
60
|
-
/** Names are not unique (the playground gives its claims and enrollments runs one name); an ambiguous name throws. */
|
|
61
|
-
experimentName?: string;
|
|
34
|
+
experimentName: string;
|
|
62
35
|
pass: PassRule;
|
|
63
|
-
/** Only these items count
|
|
64
|
-
itemIds?: string[];
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
since?: Date | string;
|
|
36
|
+
/** Only these items count; absent ones are listed in `missing`. */
|
|
37
|
+
itemIds?: readonly string[];
|
|
38
|
+
/** Lower bound for Langfuse's required start-time filter. */
|
|
39
|
+
since: string;
|
|
68
40
|
}
|
|
69
|
-
export interface
|
|
70
|
-
name
|
|
71
|
-
value: ScoreValue;
|
|
72
|
-
/** Inferred from the value when absent: boolean → BOOLEAN, number → NUMERIC, string → CATEGORICAL. */
|
|
73
|
-
dataType?: "NUMERIC" | "BOOLEAN" | "CATEGORICAL";
|
|
74
|
-
comment?: string;
|
|
75
|
-
}
|
|
76
|
-
export interface RecordedItem {
|
|
77
|
-
/** Dataset item ID; it must exist in the experiment's dataset. */
|
|
78
|
-
itemId: string;
|
|
79
|
-
/** Model that produced the output, e.g. "openrouter/deepseek/deepseek-v4-pro". */
|
|
41
|
+
export interface ModelUsage {
|
|
42
|
+
/** Model name as the traces report it (Langfuse `providedModelName`). */
|
|
80
43
|
model: string;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
endMs: number;
|
|
85
|
-
usage?: {
|
|
86
|
-
input?: number;
|
|
87
|
-
output?: number;
|
|
88
|
-
total?: number;
|
|
89
|
-
};
|
|
90
|
-
costUsd?: number;
|
|
91
|
-
/** Set when the run failed; the root observation gets level ERROR. */
|
|
92
|
-
error?: string;
|
|
93
|
-
/** Per-item trace metadata, e.g. { stage: "screen", eci: 142.1 }. */
|
|
94
|
-
metadata?: Metadata;
|
|
95
|
-
scores: RecordedScore[];
|
|
96
|
-
}
|
|
97
|
-
export interface ExperimentRecording {
|
|
98
|
-
datasetId: string;
|
|
99
|
-
experimentId: string;
|
|
100
|
-
experimentName: string;
|
|
101
|
-
/** Experiment metadata. Put the candidate model under `model_<role>` so listExperiments reports it. */
|
|
102
|
-
metadata?: Metadata;
|
|
103
|
-
/** Trace and root observation name. Default "openmerit-eval". */
|
|
104
|
-
traceName?: string;
|
|
105
|
-
items: RecordedItem[];
|
|
106
|
-
}
|
|
107
|
-
export interface RecordedExperiment {
|
|
108
|
-
experimentId: string;
|
|
109
|
-
traceIds: Record<string, string>;
|
|
110
|
-
url: string;
|
|
44
|
+
generations: number;
|
|
45
|
+
costUsd: number | null;
|
|
46
|
+
p50LatencyMs: number | null;
|
|
111
47
|
}
|
|
112
|
-
export interface
|
|
48
|
+
export interface ScoreAggregate {
|
|
113
49
|
name: string;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
50
|
+
average: number;
|
|
51
|
+
count: number;
|
|
52
|
+
}
|
|
53
|
+
export interface TaskEvidence {
|
|
54
|
+
traceName: string;
|
|
55
|
+
from: string;
|
|
56
|
+
to: string;
|
|
57
|
+
models: ModelUsage[];
|
|
58
|
+
/** Score averages over every trace of this name in the window, whichever model produced it. */
|
|
59
|
+
scores: ScoreAggregate[];
|
|
123
60
|
}
|
|
124
61
|
export interface LangfuseConnector {
|
|
125
62
|
readonly baseUrl: string;
|
|
@@ -128,36 +65,26 @@ export interface LangfuseConnector {
|
|
|
128
65
|
projectId: string;
|
|
129
66
|
projectName: string;
|
|
130
67
|
}>;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
datasetId: string;
|
|
136
|
-
itemIds: string[];
|
|
137
|
-
}>;
|
|
138
|
-
listExperiments(query?: {
|
|
139
|
-
datasetName?: string;
|
|
140
|
-
datasetId?: string;
|
|
141
|
-
names?: string[];
|
|
142
|
-
ids?: string[];
|
|
143
|
-
since?: Date | string;
|
|
144
|
-
}): Promise<ExperimentSummary[]>;
|
|
68
|
+
/** Throws unless the key pair is read-only (Viewer). */
|
|
69
|
+
verifyViewer(): Promise<void>;
|
|
70
|
+
/** IDs of the dataset's active items. */
|
|
71
|
+
datasetItemIds(name: string): Promise<string[]>;
|
|
145
72
|
experimentResults(query: ExperimentQuery): Promise<ExperimentResult>;
|
|
73
|
+
/** Polls until every expected item is present and scored, allowing for ingestion lag; throws on timeout. */
|
|
146
74
|
waitForExperiment(query: ExperimentQuery, options: {
|
|
147
75
|
expectItems: number;
|
|
148
76
|
timeoutMs?: number;
|
|
149
77
|
intervalMs?: number;
|
|
150
78
|
}): Promise<ExperimentResult>;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
79
|
+
/** Trace names with generation counts, to suggest task mappings in setup. */
|
|
80
|
+
traceNames(days?: number): Promise<{
|
|
81
|
+
traceName: string;
|
|
82
|
+
generations: number;
|
|
83
|
+
}[]>;
|
|
84
|
+
taskEvidence(mapping: {
|
|
85
|
+
traceName: string;
|
|
86
|
+
scores: string[];
|
|
87
|
+
}, days?: number): Promise<TaskEvidence>;
|
|
157
88
|
}
|
|
158
|
-
/** Version written into recorded traces' scope. */
|
|
159
|
-
export declare const CONNECTOR_VERSION = "0.1.0";
|
|
160
89
|
export declare function evaluatePass(rule: PassRule, value: ScoreValue | undefined): boolean;
|
|
161
|
-
|
|
162
|
-
export declare const recordedTraceId: (experimentId: string, itemId: string) => string;
|
|
163
|
-
export declare function createLangfuseConnector(connection: LangfuseConnection, options?: ConnectorOptions): LangfuseConnector;
|
|
90
|
+
export declare function createLangfuseConnector(connection: LangfuseConnection, options?: TransportOptions): LangfuseConnector;
|