stageflow 0.42.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/dist/agent/activity.d.ts +18 -0
- package/dist/agent/claudeAdapter.js +7 -0
- package/dist/agent/claudeTools.d.ts +27 -18
- package/dist/agent/claudeTools.js +54 -15
- package/dist/agent/compactionEvents.d.ts +34 -0
- package/dist/agent/compactionEvents.js +37 -0
- package/dist/agent/openRouterRouting.d.ts +7 -0
- package/dist/agent/openRouterRouting.js +23 -0
- package/dist/agent/piAdapter.d.ts +6 -0
- package/dist/agent/piAdapter.js +128 -27
- package/dist/agent/piSettings.d.ts +7 -0
- package/dist/agent/piSettings.js +9 -0
- package/dist/agent/sandboxPiTools.d.ts +3 -1
- package/dist/agent/sandboxPiTools.js +8 -2
- package/dist/agent/stageTurnDriver.d.ts +11 -2
- package/dist/agent/stageTurnDriver.js +45 -4
- package/dist/agent/toolOutputBudget.d.ts +15 -1
- package/dist/agent/toolOutputBudget.js +18 -0
- package/dist/agent/toolOutputBudgetExtension.d.ts +2 -0
- package/dist/agent/toolOutputBudgetExtension.js +40 -3
- package/dist/agents/authorChat.d.ts +1 -0
- package/dist/agents/authorChat.js +7 -0
- package/dist/agents/authorSessionStore.d.ts +3 -0
- package/dist/agents/authorSessionStore.js +17 -2
- package/dist/agents/evalGate.js +1 -0
- package/dist/agents/hostContext.d.ts +1 -1
- package/dist/agents/runtime/piRuntime.d.ts +5 -1
- package/dist/agents/runtime/piRuntime.js +46 -12
- package/dist/agents/service.js +3 -2
- package/dist/agents/sessions.js +3 -1
- package/dist/cli/evalCommand.d.ts +1 -1
- package/dist/cli/evalCommand.js +39 -2
- package/dist/cli/hostClient.d.ts +6 -0
- package/dist/cli/hostClient.js +4 -0
- package/dist/compaction/directives.d.ts +18 -0
- package/dist/compaction/directives.js +119 -0
- package/dist/compaction/extension.d.ts +20 -0
- package/dist/compaction/extension.js +78 -0
- package/dist/compaction/mask.d.ts +18 -0
- package/dist/compaction/mask.js +155 -0
- package/dist/compaction/pin.d.ts +21 -0
- package/dist/compaction/pin.js +270 -0
- package/dist/compaction/scrub.d.ts +7 -0
- package/dist/compaction/scrub.js +26 -0
- package/dist/compaction/sessionWiring.d.ts +22 -0
- package/dist/compaction/sessionWiring.js +26 -0
- package/dist/compaction/summarize.d.ts +79 -0
- package/dist/compaction/summarize.js +171 -0
- package/dist/compaction/toolPolicy.d.ts +3 -0
- package/dist/compaction/toolPolicy.js +33 -0
- package/dist/compaction/types.d.ts +45 -0
- package/dist/compaction/types.js +7 -0
- package/dist/compaction/workingState.d.ts +56 -0
- package/dist/compaction/workingState.js +198 -0
- package/dist/config/createPipeline.js +2 -0
- package/dist/config/createTrigger.js +7 -1
- package/dist/config/ensureCatalogScanRoot.d.ts +2 -0
- package/dist/config/ensureCatalogScanRoot.js +6 -0
- package/dist/config/evalCatalog.js +30 -2
- package/dist/config/githubTriggerAction.d.ts +8 -0
- package/dist/config/githubTriggerAction.js +29 -0
- package/dist/config/hostConfig.js +2 -0
- package/dist/config/loadEval.d.ts +3 -1
- package/dist/config/loadEval.js +96 -10
- package/dist/config/pipelineNeeds.d.ts +2 -0
- package/dist/config/pipelineNeeds.js +16 -3
- package/dist/config/pipelineRoute.js +5 -4
- package/dist/config/validateCatalog.d.ts +1 -1
- package/dist/config/validateCatalog.js +12 -0
- package/dist/config/validateEval.js +60 -3
- package/dist/config/writeEval.js +2 -2
- package/dist/envelope/assertEmittedArtifacts.d.ts +12 -0
- package/dist/envelope/assertEmittedArtifacts.js +43 -0
- package/dist/envelope/preEmitChecks.d.ts +3 -0
- package/dist/evals/calibration.d.ts +21 -0
- package/dist/evals/calibration.js +69 -0
- package/dist/evals/calibrationSuggest.d.ts +29 -0
- package/dist/evals/calibrationSuggest.js +72 -0
- package/dist/evals/calibrator.d.ts +46 -0
- package/dist/evals/calibrator.js +148 -0
- package/dist/evals/compare.d.ts +1 -1
- package/dist/evals/compare.js +3 -0
- package/dist/evals/constants.d.ts +7 -3
- package/dist/evals/constants.js +7 -1
- package/dist/evals/engine/FakeEngine.d.ts +2 -1
- package/dist/evals/engine/FakeEngine.js +9 -3
- package/dist/evals/engine/promptfoo/PromptfooEngine.d.ts +1 -1
- package/dist/evals/engine/promptfoo/PromptfooEngine.js +4 -2
- package/dist/evals/engine/promptfoo/generate.d.ts +3 -1
- package/dist/evals/engine/promptfoo/generate.js +43 -23
- package/dist/evals/engine/promptfoo/judgeProviders.js +2 -1
- package/dist/evals/engine/promptfoo/normalize.d.ts +4 -1
- package/dist/evals/engine/promptfoo/normalize.js +16 -3
- package/dist/evals/engine/promptfoo/rubricPrompt.d.ts +3 -1
- package/dist/evals/engine/promptfoo/rubricPrompt.js +15 -5
- package/dist/evals/errors.d.ts +7 -0
- package/dist/evals/errors.js +10 -0
- package/dist/evals/judgeProviders.d.ts +6 -0
- package/dist/evals/judgeProviders.js +14 -0
- package/dist/evals/judged.d.ts +7 -0
- package/dist/evals/judged.js +7 -0
- package/dist/evals/manager.d.ts +27 -8
- package/dist/evals/manager.js +73 -12
- package/dist/evals/plan.d.ts +10 -1
- package/dist/evals/plan.js +33 -13
- package/dist/evals/planInternalAgent.d.ts +19 -0
- package/dist/evals/planInternalAgent.js +201 -0
- package/dist/evals/read/api.d.ts +18 -0
- package/dist/evals/read/api.js +10 -1
- package/dist/evals/read/labelQueue.d.ts +45 -0
- package/dist/evals/read/labelQueue.js +83 -0
- package/dist/evals/read/list.js +10 -1
- package/dist/evals/read/runs.d.ts +5 -0
- package/dist/evals/read/runs.js +7 -1
- package/dist/evals/runner/caseRunner.d.ts +2 -1
- package/dist/evals/runner/caseRunner.js +16 -5
- package/dist/evals/runner/internalAgentCaseRunner.d.ts +6 -0
- package/dist/evals/runner/internalAgentCaseRunner.js +250 -0
- package/dist/evals/snapshot.d.ts +10 -2
- package/dist/evals/snapshot.js +8 -3
- package/dist/evals/stats.d.ts +40 -0
- package/dist/evals/stats.js +69 -0
- package/dist/evals/storeTypes.d.ts +42 -0
- package/dist/evals/types.d.ts +25 -2
- package/dist/evals/types.js +4 -1
- package/dist/evals/votes.d.ts +10 -0
- package/dist/evals/votes.js +60 -0
- package/dist/guide/cardContract.d.ts +133 -0
- package/dist/guide/cardContract.js +156 -0
- package/dist/guide/chat.d.ts +45 -0
- package/dist/guide/chat.js +378 -0
- package/dist/guide/knowledge/index.d.ts +14 -0
- package/dist/guide/knowledge/index.js +109 -0
- package/dist/guide/knowledge/topics/agents.d.ts +2 -0
- package/dist/guide/knowledge/topics/agents.js +58 -0
- package/dist/guide/knowledge/topics/bestPractices.d.ts +2 -0
- package/dist/guide/knowledge/topics/bestPractices.js +67 -0
- package/dist/guide/knowledge/topics/connections.d.ts +2 -0
- package/dist/guide/knowledge/topics/connections.js +66 -0
- package/dist/guide/knowledge/topics/consoleMap.d.ts +2 -0
- package/dist/guide/knowledge/topics/consoleMap.js +55 -0
- package/dist/guide/knowledge/topics/evals.d.ts +2 -0
- package/dist/guide/knowledge/topics/evals.js +72 -0
- package/dist/guide/knowledge/topics/limitations.d.ts +2 -0
- package/dist/guide/knowledge/topics/limitations.js +84 -0
- package/dist/guide/knowledge/topics/mcpSkillsBrowser.d.ts +2 -0
- package/dist/guide/knowledge/topics/mcpSkillsBrowser.js +57 -0
- package/dist/guide/knowledge/topics/memories.d.ts +2 -0
- package/dist/guide/knowledge/topics/memories.js +63 -0
- package/dist/guide/knowledge/topics/modelsAndProviders.d.ts +2 -0
- package/dist/guide/knowledge/topics/modelsAndProviders.js +56 -0
- package/dist/guide/knowledge/topics/overview.d.ts +2 -0
- package/dist/guide/knowledge/topics/overview.js +56 -0
- package/dist/guide/knowledge/topics/pipelines.d.ts +2 -0
- package/dist/guide/knowledge/topics/pipelines.js +93 -0
- package/dist/guide/knowledge/topics/stages.d.ts +2 -0
- package/dist/guide/knowledge/topics/stages.js +54 -0
- package/dist/guide/knowledge/topics/tasks.d.ts +2 -0
- package/dist/guide/knowledge/topics/tasks.js +52 -0
- package/dist/guide/knowledge/topics/triggers.d.ts +2 -0
- package/dist/guide/knowledge/topics/triggers.js +68 -0
- package/dist/guide/knowledge/topics/troubleshooting.d.ts +2 -0
- package/dist/guide/knowledge/topics/troubleshooting.js +85 -0
- package/dist/guide/knowledgeTools.d.ts +2 -0
- package/dist/guide/knowledgeTools.js +56 -0
- package/dist/guide/showUi.d.ts +6 -0
- package/dist/guide/showUi.js +546 -0
- package/dist/guide/threadStore.d.ts +48 -0
- package/dist/guide/threadStore.js +189 -0
- package/dist/guide/writeRoot.d.ts +11 -0
- package/dist/guide/writeRoot.js +70 -0
- package/dist/hosted/translate.js +2 -0
- package/dist/mcp/agentTools.js +12 -0
- package/dist/mcp/catalogTools.js +18 -20
- package/dist/mcp/catalogWriteTools.d.ts +8 -0
- package/dist/mcp/catalogWriteTools.js +225 -0
- package/dist/mcp/connectionTools.d.ts +3 -0
- package/dist/mcp/connectionTools.js +85 -0
- package/dist/mcp/controlTools.js +34 -1
- package/dist/mcp/deps.d.ts +9 -0
- package/dist/mcp/evalTools.js +723 -21
- package/dist/mcp/memoryHostTools.d.ts +3 -0
- package/dist/mcp/memoryHostTools.js +72 -0
- package/dist/mcp/pipelineAuthorTools.js +14 -1
- package/dist/mcp/server.js +5 -0
- package/dist/mcp/tools.js +6 -0
- package/dist/mcp/triggerTools.js +77 -31
- package/dist/operatorAgent/evalGate.d.ts +22 -0
- package/dist/operatorAgent/evalGate.js +77 -0
- package/dist/operatorAgent/fakeHost.js +10 -2
- package/dist/operatorAgent/host.js +18 -2
- package/dist/operatorAgent/index.d.ts +1 -0
- package/dist/operatorAgent/index.js +1 -0
- package/dist/operatorAgent/internalAgents.d.ts +11 -0
- package/dist/operatorAgent/internalAgents.js +13 -0
- package/dist/operatorAgent/piModel.d.ts +5 -1
- package/dist/operatorAgent/piModel.js +15 -10
- package/dist/operatorAgent/profiles/agentAuthor.js +66 -22
- package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -1
- package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +1 -1
- package/dist/operatorAgent/profiles/guideConfirm.d.ts +21 -0
- package/dist/operatorAgent/profiles/guideConfirm.js +100 -0
- package/dist/operatorAgent/profiles/guideTools.d.ts +7 -0
- package/dist/operatorAgent/profiles/guideTools.js +123 -0
- package/dist/operatorAgent/profiles/stageflowGuide.d.ts +7 -0
- package/dist/operatorAgent/profiles/stageflowGuide.js +133 -0
- package/dist/operatorAgent/profiles/workshopAuthor.js +23 -0
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +1 -1
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +9 -1
- package/dist/operatorAgent/profiles/workshopAuthorTools.d.ts +2 -0
- package/dist/operatorAgent/profiles/workshopAuthorTools.js +197 -9
- package/dist/operatorAgent/types.d.ts +23 -0
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/runstore/port.d.ts +13 -1
- package/dist/runstore/retention.d.ts +2 -1
- package/dist/runstore/retention.js +3 -7
- package/dist/runstore/runStatusClock.d.ts +17 -0
- package/dist/runstore/runStatusClock.js +19 -0
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +11 -1
- package/dist/runstore/sqlite/SqliteRunStore.js +70 -45
- package/dist/runstore/sqlite/calibrationStore.d.ts +10 -0
- package/dist/runstore/sqlite/calibrationStore.js +106 -0
- package/dist/runstore/sqlite/evalStore.d.ts +5 -0
- package/dist/runstore/sqlite/evalStore.js +7 -0
- package/dist/runstore/sqlite/migrations/018-eval-grader-labels.d.ts +11 -0
- package/dist/runstore/sqlite/migrations/018-eval-grader-labels.js +43 -0
- package/dist/runstore/sqlite/migrations/index.js +2 -0
- package/dist/runstore/workspaceLayout.js +6 -1
- package/dist/runtime/artifactDiskInspect.d.ts +14 -0
- package/dist/runtime/artifactDiskInspect.js +52 -0
- package/dist/runtime/artifactPath.d.ts +24 -0
- package/dist/runtime/artifactPath.js +84 -0
- package/dist/runtime/completionCheckRunner.js +15 -43
- package/dist/runtime/githubPollSource.d.ts +22 -4
- package/dist/runtime/githubPollSource.js +93 -8
- package/dist/runtime/priorArtifactGrants.d.ts +8 -0
- package/dist/runtime/priorArtifactGrants.js +105 -0
- package/dist/runtime/runActionEligibility.d.ts +46 -0
- package/dist/runtime/runActionEligibility.js +123 -0
- package/dist/runtime/runManager.d.ts +4 -1
- package/dist/runtime/runManager.js +52 -10
- package/dist/runtime/runRetryCoordinator.d.ts +2 -14
- package/dist/runtime/runRetryCoordinator.js +3 -67
- package/dist/runtime/sandboxContainer.d.ts +7 -0
- package/dist/runtime/sandboxContainer.js +48 -6
- package/dist/runtime/sandboxDesk.d.ts +2 -1
- package/dist/runtime/sandboxDesk.js +11 -12
- package/dist/runtime/stageEnvironment.js +1 -0
- package/dist/runtime/stageRoots.d.ts +12 -0
- package/dist/runtime/stageSandbox.d.ts +2 -1
- package/dist/runtime/stageSandbox.js +18 -2
- package/dist/runtime/stageWorker.js +20 -0
- package/dist/server/agentAuthorRoutes.js +12 -3
- package/dist/server/bootstrap.d.ts +5 -0
- package/dist/server/bootstrap.js +14 -1
- package/dist/server/evalRoutes.js +251 -12
- package/dist/server/guideRoutes.d.ts +5 -0
- package/dist/server/guideRoutes.js +166 -0
- package/dist/server/http.d.ts +10 -0
- package/dist/server/http.js +35 -1
- package/dist/server/internalAgentRoutes.d.ts +6 -0
- package/dist/server/internalAgentRoutes.js +12 -0
- package/dist/server/mcpHost.js +2 -0
- package/dist/toolkit/meta.d.ts +1 -1
- package/dist/toolkit/meta.js +41 -1
- package/dist/toolkit/profiles.d.ts +5 -0
- package/dist/toolkit/profiles.js +12 -0
- package/dist/tools/askOperator.js +2 -1
- package/dist/tools/emitStageEnvelope.d.ts +17 -16
- package/dist/tools/emitStageEnvelope.js +46 -32
- package/dist/tools/stageToolNames.d.ts +4 -0
- package/dist/tools/stageToolNames.js +4 -0
- package/dist/tools/workingState.d.ts +40 -0
- package/dist/tools/workingState.js +108 -0
- package/dist/tools/writeStageArtifact.d.ts +0 -9
- package/dist/tools/writeStageArtifact.js +2 -1
- package/dist/ui/assets/{MarkdownText-BTrOqu5J.js → MarkdownText-BS2BBbCx.js} +2 -2
- package/dist/ui/assets/adapters-DPD-cAsy.js +17 -0
- package/dist/ui/assets/chat-BD1-VTT6.js +2 -0
- package/dist/ui/assets/chat-DXnQv9st.css +2 -0
- package/dist/ui/assets/main-AX5XNLtX.js +278 -0
- package/dist/ui/assets/{main-CHlmTNJe.css → main-CFX0_n8J.css} +1 -1
- package/dist/ui/chat.html +3 -4
- package/dist/ui/index.html +3 -4
- package/dist/workshop/chatTurn.js +1 -1
- package/dist/workshop/workshopPin.d.ts +3 -3
- package/dist/workshop/workshopPin.js +16 -15
- package/examples/compaction-stress/README.md +30 -0
- package/examples/compaction-stress/check-run.mjs +53 -0
- package/examples/compaction-stress/collect-evidence.yaml +60 -0
- package/examples/compaction-stress/compaction-stress.pipeline.yaml +141 -0
- package/examples/compaction-stress/compaction-stress.task.yaml +15 -0
- package/examples/compaction-stress/generate-evidence.mjs +110 -0
- package/examples/compaction-stress/root-cause.yaml +26 -0
- package/examples/compaction-stress/stageflow.yaml +9 -0
- package/examples/compaction-stress/write-postmortem.yaml +40 -0
- package/examples/evals/README.md +18 -0
- package/examples/evals/guide-behavior.dataset.jsonl +15 -0
- package/examples/evals/guide-behavior.eval.yaml +35 -0
- package/examples/evals/guide-depth.dataset.jsonl +35 -0
- package/examples/evals/guide-depth.eval.yaml +169 -0
- package/examples/memory/evals/guide-behavior.dataset.jsonl +15 -0
- package/examples/memory/evals/guide-behavior.eval.yaml +35 -0
- package/examples/memory/evals/guide-depth.dataset.jsonl +35 -0
- package/examples/memory/evals/guide-depth.eval.yaml +169 -0
- package/package.json +1 -1
- package/skills/stageflow/references/control-surface.md +1 -1
- package/skills/stageflow/references/evals.md +1 -0
- package/dist/ui/assets/AssistantRuntimeProvider-qIX1xNoH.js +0 -9
- package/dist/ui/assets/ReadonlyStore-BfXqHykm.js +0 -6
- package/dist/ui/assets/chat-Df_wCpak.js +0 -5
- package/dist/ui/assets/chat-P7KQznHm.css +0 -2
- package/dist/ui/assets/main-CvVfxmMd.js +0 -271
package/dist/evals/plan.js
CHANGED
|
@@ -11,6 +11,9 @@ import { EVAL_LARGE_RUN, EVAL_TOO_LARGE_RUN, evalFinding, evalFindingsFromIssues
|
|
|
11
11
|
import { canonicalJson, sha256Hex } from "./canonical.js";
|
|
12
12
|
import { EVAL_LIMITS, SIMULATOR_PROMPT_VERSION } from "./constants.js";
|
|
13
13
|
import { buildComponents, buildSnapshot, computeFingerprint, } from "./snapshot.js";
|
|
14
|
+
import { planInternalAgent } from "./planInternalAgent.js";
|
|
15
|
+
import { isConversationTarget } from "./types.js";
|
|
16
|
+
import { isJudged, isJudgedType } from "./judged.js";
|
|
14
17
|
const SELECTION_KEYS = ["case_ids", "tags", "only_failed_from"];
|
|
15
18
|
const RUN_SIZE_CODES = new Set(["eval.large_run", "eval.too_large_run"]);
|
|
16
19
|
function posix(projectRoot, abs) {
|
|
@@ -58,7 +61,7 @@ function checkConversationOverrides(relPath, file, overrides) {
|
|
|
58
61
|
const keys = ["user_model", "tools", "approvals"].filter((key) => overrides[key] !== undefined);
|
|
59
62
|
if (keys.length === 0)
|
|
60
63
|
return out;
|
|
61
|
-
if (file.target.kind
|
|
64
|
+
if (!isConversationTarget(file.target.kind)) {
|
|
62
65
|
out.push(evalFinding(relPath, "error", "eval.conversation_not_applicable", `Override ${keys.map((k) => `"${k}"`).join(", ")} applies to agent targets only`));
|
|
63
66
|
return out;
|
|
64
67
|
}
|
|
@@ -104,10 +107,10 @@ function withOverrides(loaded, overrides) {
|
|
|
104
107
|
...(overrides.max_cost_usd !== undefined ? { max_cost_usd: overrides.max_cost_usd } : {}),
|
|
105
108
|
};
|
|
106
109
|
const graders = loaded.graders.map((grader) => {
|
|
107
|
-
if ((grader
|
|
110
|
+
if (!isJudged(grader) || overrides.judge === undefined)
|
|
108
111
|
return grader;
|
|
109
112
|
const raw = loaded.file.graders.find((g) => g.id === grader.id);
|
|
110
|
-
if (
|
|
113
|
+
if (raw !== undefined && isJudgedType(raw.type) && "judge" in raw && raw.judge !== undefined)
|
|
111
114
|
return grader;
|
|
112
115
|
const { hash: _old, ...rest } = { ...grader, judge: overrides.judge };
|
|
113
116
|
return { ...rest, hash: graderHash(rest) };
|
|
@@ -131,7 +134,7 @@ function selectCases(cases, overrides, failedIds) {
|
|
|
131
134
|
return cases.filter((c) => failedIds.has(c.id));
|
|
132
135
|
return [...cases];
|
|
133
136
|
}
|
|
134
|
-
function evalDefinition(loaded, projectRoot) {
|
|
137
|
+
export function evalDefinition(loaded, projectRoot) {
|
|
135
138
|
const { file } = loaded;
|
|
136
139
|
const paths = resolveEvalPaths(file, loaded.path);
|
|
137
140
|
const rel = (abs) => abs === undefined ? undefined : posix(projectRoot, abs);
|
|
@@ -145,12 +148,14 @@ function evalDefinition(loaded, projectRoot) {
|
|
|
145
148
|
type: file.type ?? "capability",
|
|
146
149
|
target: file.target.kind === "agent"
|
|
147
150
|
? { kind: "agent", agent: file.target.agent }
|
|
148
|
-
:
|
|
149
|
-
kind: file.target.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
: file.target.kind === "internal_agent"
|
|
152
|
+
? { kind: "internal_agent", profile: file.target.profile }
|
|
153
|
+
: {
|
|
154
|
+
kind: file.target.kind,
|
|
155
|
+
pipeline: rel(paths.pipelinePath),
|
|
156
|
+
stage: stageTarget?.stage,
|
|
157
|
+
file: rel(paths.stageFile),
|
|
158
|
+
},
|
|
154
159
|
dataset: rel(paths.datasetPath),
|
|
155
160
|
task: file.task,
|
|
156
161
|
defaults: {
|
|
@@ -160,9 +165,9 @@ function evalDefinition(loaded, projectRoot) {
|
|
|
160
165
|
max_cost_usd: defaults.max_cost_usd ?? EVAL_DEFAULT_MAX_COST_USD,
|
|
161
166
|
concurrency: defaults.concurrency ?? EVAL_DEFAULT_CONCURRENCY,
|
|
162
167
|
model: defaults.model,
|
|
163
|
-
...(file.target.kind
|
|
168
|
+
...(isConversationTarget(file.target.kind) && defaults.user_model !== undefined ? { user_model: defaults.user_model } : {}),
|
|
164
169
|
},
|
|
165
|
-
...(file.target.kind
|
|
170
|
+
...(isConversationTarget(file.target.kind) ? { conversation: file.conversation } : {}),
|
|
166
171
|
graders: file.graders.map((g) => ({ ...g, weight: g.weight ?? 1, must_pass: g.must_pass ?? false })),
|
|
167
172
|
budget: file.budget,
|
|
168
173
|
}));
|
|
@@ -227,6 +232,21 @@ export async function buildEvalPlan(input) {
|
|
|
227
232
|
const findings = [...validation.filter((f) => !RUN_SIZE_CODES.has(f.code)), ...dataset.findings];
|
|
228
233
|
if (findings.some((f) => f.severity === "error"))
|
|
229
234
|
return fail(findings);
|
|
235
|
+
if (file.target.kind === "internal_agent") {
|
|
236
|
+
return planInternalAgent({
|
|
237
|
+
input,
|
|
238
|
+
loaded,
|
|
239
|
+
dataset: {
|
|
240
|
+
path: paths.datasetPath,
|
|
241
|
+
contentHash: dataset.contentHash,
|
|
242
|
+
format: dataset.format,
|
|
243
|
+
cases: dataset.cases,
|
|
244
|
+
},
|
|
245
|
+
findings,
|
|
246
|
+
overrides,
|
|
247
|
+
...(failedIds ? { failedIds } : {}),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
230
250
|
let agentTarget;
|
|
231
251
|
let stageTarget;
|
|
232
252
|
if (file.target.kind === "agent") {
|
|
@@ -489,7 +509,7 @@ async function buildAgentResult(a) {
|
|
|
489
509
|
});
|
|
490
510
|
const fingerprint = computeFingerprint(components);
|
|
491
511
|
const { overrides } = a;
|
|
492
|
-
const hasRubric = loaded.graders.some(
|
|
512
|
+
const hasRubric = loaded.graders.some(isJudged);
|
|
493
513
|
const plainDefinition = JSON.parse(JSON.stringify(definition));
|
|
494
514
|
const snapshot = buildSnapshot({
|
|
495
515
|
evalId: loaded.id,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DatasetCase } from "../config/datasetTypes.js";
|
|
2
|
+
import { type LoadedEval } from "../config/loadEval.js";
|
|
3
|
+
import type { ValidationFinding } from "../config/validateCatalog.js";
|
|
4
|
+
import { type BuildEvalPlanInput, type BuildEvalPlanResult, type EvalOverrides } from "./plan.js";
|
|
5
|
+
type Dataset = {
|
|
6
|
+
path: string;
|
|
7
|
+
contentHash: string;
|
|
8
|
+
format?: string;
|
|
9
|
+
cases: DatasetCase[];
|
|
10
|
+
};
|
|
11
|
+
export declare function planInternalAgent(args: {
|
|
12
|
+
input: BuildEvalPlanInput;
|
|
13
|
+
loaded: LoadedEval;
|
|
14
|
+
dataset: Dataset;
|
|
15
|
+
findings: ValidationFinding[];
|
|
16
|
+
overrides: EvalOverrides;
|
|
17
|
+
failedIds?: Set<string>;
|
|
18
|
+
}): BuildEvalPlanResult;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { checkDatasetAgainstAgent } from "../config/datasetAgentCheck.js";
|
|
3
|
+
import { EVAL_AGENT_DEFAULT_CONCURRENCY, EVAL_AGENT_DEFAULT_MAX_COST_USD, EVAL_DEFAULT_PASS_THRESHOLD, EVAL_DEFAULT_REPEATS, resolveConversation, resolveEvalPaths, } from "../config/loadEval.js";
|
|
4
|
+
import { EVAL_LARGE_RUN, EVAL_TOO_LARGE_RUN, evalFinding } from "../config/validateEval.js";
|
|
5
|
+
import { PACKAGE_VERSION } from "../package-meta.js";
|
|
6
|
+
import { sha256Hex } from "./canonical.js";
|
|
7
|
+
import { EVAL_LIMITS, SIMULATOR_PROMPT_VERSION } from "./constants.js";
|
|
8
|
+
import { evalDefinition } from "./plan.js";
|
|
9
|
+
import { buildComponents, buildSnapshot, computeFingerprint } from "./snapshot.js";
|
|
10
|
+
function posix(projectRoot, abs) {
|
|
11
|
+
return path.relative(projectRoot, abs).split(path.sep).join("/");
|
|
12
|
+
}
|
|
13
|
+
function selectCases(cases, overrides, failedIds) {
|
|
14
|
+
if (overrides.case_ids !== undefined)
|
|
15
|
+
return cases.filter((c) => overrides.case_ids.includes(c.id));
|
|
16
|
+
if (overrides.tags !== undefined) {
|
|
17
|
+
const wanted = new Set(overrides.tags);
|
|
18
|
+
return cases.filter((c) => (c.tags ?? []).some((tag) => wanted.has(tag)));
|
|
19
|
+
}
|
|
20
|
+
if (failedIds !== undefined)
|
|
21
|
+
return cases.filter((c) => failedIds.has(c.id));
|
|
22
|
+
return [...cases];
|
|
23
|
+
}
|
|
24
|
+
export function planInternalAgent(args) {
|
|
25
|
+
const { input, loaded, dataset, overrides, failedIds } = args;
|
|
26
|
+
const findings = [...args.findings];
|
|
27
|
+
const fail = (extra) => ({ ok: false, code: "EVAL_INVALID", findings: [...findings, ...extra] });
|
|
28
|
+
if (loaded.file.target.kind !== "internal_agent")
|
|
29
|
+
return fail([]);
|
|
30
|
+
const profileId = loaded.file.target.profile;
|
|
31
|
+
const profiles = input.internalAgents ?? [];
|
|
32
|
+
const profile = profiles.find((item) => item.id === profileId);
|
|
33
|
+
if (!profile) {
|
|
34
|
+
return fail([
|
|
35
|
+
evalFinding(loaded.relPath, "error", profiles.length === 0 ? "eval.internal_agent_unavailable" : "eval.internal_agent_unknown", profiles.length === 0
|
|
36
|
+
? "This Host is not showing internal agents, so this eval cannot run"
|
|
37
|
+
: `This Host has no internal agent "${profileId}"`),
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
if (overrides.case_ids !== undefined) {
|
|
41
|
+
const known = new Set(dataset.cases.map((c) => c.id));
|
|
42
|
+
const unknown = overrides.case_ids.filter((id) => !known.has(id));
|
|
43
|
+
if (unknown.length > 0) {
|
|
44
|
+
return fail([
|
|
45
|
+
evalFinding(loaded.relPath, "error", "eval.invalid_field", `Override "case_ids" names ${unknown.length} case(s) not in the dataset; first: ${unknown[0]}`),
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const conversation = resolveConversation(loaded.file.conversation);
|
|
50
|
+
if (conversation.tools === "real") {
|
|
51
|
+
return fail([
|
|
52
|
+
evalFinding(loaded.relPath, "error", "eval.internal_agent_real_tools", "An internal agent eval cannot use real tools"),
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
const checks = new Map(checkDatasetAgainstAgent(dataset.cases, { mode: conversation.mode }).map((r) => [r.caseId, r.valid]));
|
|
56
|
+
const validCases = dataset.cases.filter((c) => checks.get(c.id) !== false);
|
|
57
|
+
const selected = selectCases(dataset.cases, overrides, failedIds);
|
|
58
|
+
const skippedCaseIds = selected.filter((c) => checks.get(c.id) === false).map((c) => c.id);
|
|
59
|
+
const runCases = selected.filter((c) => checks.get(c.id) !== false);
|
|
60
|
+
const positionOf = new Map(dataset.cases.map((c, i) => [c.id, i]));
|
|
61
|
+
const planCases = runCases.map((c) => ({
|
|
62
|
+
id: c.id,
|
|
63
|
+
position: positionOf.get(c.id) ?? 0,
|
|
64
|
+
...(c.title !== undefined ? { title: c.title } : {}),
|
|
65
|
+
...(c.goal !== undefined ? { goal: c.goal } : {}),
|
|
66
|
+
input: c.input,
|
|
67
|
+
...(c.expected !== undefined ? { expected: c.expected } : {}),
|
|
68
|
+
tags: c.tags ?? [],
|
|
69
|
+
...(c.metadata !== undefined ? { metadata: c.metadata } : {}),
|
|
70
|
+
}));
|
|
71
|
+
const repeats = loaded.file.defaults?.repeats ?? EVAL_DEFAULT_REPEATS;
|
|
72
|
+
const results = planCases.length * repeats;
|
|
73
|
+
if (planCases.length === 0) {
|
|
74
|
+
return fail([evalFinding(loaded.relPath, "error", "eval.no_valid_cases", "No valid cases are left to run after case selection and skipping")]);
|
|
75
|
+
}
|
|
76
|
+
if (results > EVAL_LIMITS.maxResultsPerRun) {
|
|
77
|
+
return fail([
|
|
78
|
+
evalFinding(loaded.relPath, "error", "eval.too_large_run", `${planCases.length} case(s) x ${repeats} repeat(s) = ${results} results, over the ${EVAL_TOO_LARGE_RUN} limit`),
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
if (results > EVAL_LARGE_RUN) {
|
|
82
|
+
findings.push(evalFinding(loaded.relPath, "warning", "eval.large_run", `${planCases.length} case(s) x ${repeats} repeat(s) = ${results} results, over ${EVAL_LARGE_RUN}`));
|
|
83
|
+
}
|
|
84
|
+
const defaults = loaded.file.defaults ?? {};
|
|
85
|
+
const passThreshold = defaults.pass_threshold ?? EVAL_DEFAULT_PASS_THRESHOLD;
|
|
86
|
+
const concurrency = defaults.concurrency ?? EVAL_AGENT_DEFAULT_CONCURRENCY;
|
|
87
|
+
const maxCostUsd = defaults.max_cost_usd ?? EVAL_AGENT_DEFAULT_MAX_COST_USD;
|
|
88
|
+
const judge = defaults.judge ?? "";
|
|
89
|
+
const model = defaults.model ?? "";
|
|
90
|
+
const playbookHash = sha256Hex(profile.playbook);
|
|
91
|
+
const definitionHash = sha256Hex(JSON.stringify({ playbook: profile.playbook, tools: profile.tools }));
|
|
92
|
+
const userModel = planCases.some((c) => c.input.mode === "simulated") ? (defaults.user_model ?? null) : null;
|
|
93
|
+
const paths = resolveEvalPaths(loaded.file, loaded.path);
|
|
94
|
+
const projectRoot = input.projectRoot;
|
|
95
|
+
const components = buildComponents({
|
|
96
|
+
stageVersionHash: definitionHash,
|
|
97
|
+
model,
|
|
98
|
+
datasetHash: dataset.contentHash,
|
|
99
|
+
caseIds: runCases.length < validCases.length ? runCases.map((c) => c.id) : null,
|
|
100
|
+
graders: loaded.graders,
|
|
101
|
+
judge,
|
|
102
|
+
repeats,
|
|
103
|
+
passThreshold,
|
|
104
|
+
engine: input.engine,
|
|
105
|
+
agent: {
|
|
106
|
+
revision: 0,
|
|
107
|
+
mode: conversation.mode,
|
|
108
|
+
max_turns: conversation.maxTurns,
|
|
109
|
+
turn_timeout_ms: conversation.turnTimeoutMs,
|
|
110
|
+
tools: conversation.tools,
|
|
111
|
+
approvals: conversation.approvals,
|
|
112
|
+
read_only_tools: conversation.readOnlyTools,
|
|
113
|
+
user_model: userModel,
|
|
114
|
+
simulator_prompt_version: SIMULATOR_PROMPT_VERSION,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
const fingerprint = computeFingerprint(components);
|
|
118
|
+
const snapshotOverrides = {
|
|
119
|
+
repeats: overrides.repeats ?? null,
|
|
120
|
+
judge: overrides.judge ?? null,
|
|
121
|
+
model: overrides.model ?? null,
|
|
122
|
+
max_cost_usd: overrides.max_cost_usd ?? null,
|
|
123
|
+
case_ids: overrides.case_ids ?? null,
|
|
124
|
+
tags: overrides.tags ?? null,
|
|
125
|
+
only_failed_from: overrides.only_failed_from ?? null,
|
|
126
|
+
};
|
|
127
|
+
const snapshot = buildSnapshot({
|
|
128
|
+
evalId: loaded.id,
|
|
129
|
+
evalPath: loaded.relPath,
|
|
130
|
+
evalHash: loaded.fileHash,
|
|
131
|
+
evalDefinition: evalDefinition(loaded, projectRoot),
|
|
132
|
+
overrides: snapshotOverrides,
|
|
133
|
+
target: {
|
|
134
|
+
profile_id: profileId,
|
|
135
|
+
title: profile.title,
|
|
136
|
+
playbook_hash: playbookHash,
|
|
137
|
+
tools: profile.tools,
|
|
138
|
+
model,
|
|
139
|
+
},
|
|
140
|
+
dataset: {
|
|
141
|
+
path: posix(projectRoot, paths.datasetPath),
|
|
142
|
+
hash: dataset.contentHash,
|
|
143
|
+
format: dataset.format ?? "jsonl",
|
|
144
|
+
case_count: dataset.cases.length,
|
|
145
|
+
cases_run: planCases.length,
|
|
146
|
+
cases_skipped: skippedCaseIds.length,
|
|
147
|
+
skipped_case_ids: skippedCaseIds,
|
|
148
|
+
},
|
|
149
|
+
graders: loaded.graders.map((g) => ({
|
|
150
|
+
id: g.id,
|
|
151
|
+
type: g.type,
|
|
152
|
+
hash: g.hash,
|
|
153
|
+
version_ordinal: input.graderOrdinals?.[g.id] ?? 1,
|
|
154
|
+
weight: g.weight,
|
|
155
|
+
must_pass: g.mustPass,
|
|
156
|
+
})),
|
|
157
|
+
settings: {
|
|
158
|
+
repeats,
|
|
159
|
+
pass_threshold: passThreshold,
|
|
160
|
+
judge,
|
|
161
|
+
judge_same_as_stage: false,
|
|
162
|
+
max_cost_usd: maxCostUsd,
|
|
163
|
+
concurrency,
|
|
164
|
+
suite_type: loaded.file.type ?? "capability",
|
|
165
|
+
conversation: {
|
|
166
|
+
mode: conversation.mode,
|
|
167
|
+
max_turns: conversation.maxTurns,
|
|
168
|
+
turn_timeout_ms: conversation.turnTimeoutMs,
|
|
169
|
+
tools: conversation.tools,
|
|
170
|
+
approvals: conversation.approvals,
|
|
171
|
+
read_only_tools: conversation.readOnlyTools,
|
|
172
|
+
real_tools_confirmed: false,
|
|
173
|
+
user_model: userModel ?? "",
|
|
174
|
+
user_model_from_judge: false,
|
|
175
|
+
simulator_prompt_version: SIMULATOR_PROMPT_VERSION,
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
engine: input.engine,
|
|
179
|
+
stageflowVersion: PACKAGE_VERSION,
|
|
180
|
+
});
|
|
181
|
+
const plan = {
|
|
182
|
+
evalRunId: input.evalRunId,
|
|
183
|
+
projectRoot,
|
|
184
|
+
evalId: loaded.id,
|
|
185
|
+
target: { kind: "internal_agent", profileId },
|
|
186
|
+
targetVersionHash: definitionHash,
|
|
187
|
+
stageModel: model,
|
|
188
|
+
task: {},
|
|
189
|
+
cases: planCases,
|
|
190
|
+
graders: loaded.graders,
|
|
191
|
+
repeats,
|
|
192
|
+
passThreshold,
|
|
193
|
+
concurrency,
|
|
194
|
+
maxCostUsd,
|
|
195
|
+
...(model !== "" ? { modelOverride: model } : {}),
|
|
196
|
+
conversation,
|
|
197
|
+
userModel,
|
|
198
|
+
agent: { definitionHash, definition: { id: profileId, title: profile.title, tools: profile.tools } },
|
|
199
|
+
};
|
|
200
|
+
return { ok: true, plan, snapshot, fingerprint, components, skippedCaseIds, findings };
|
|
201
|
+
}
|
package/dist/evals/read/api.d.ts
CHANGED
|
@@ -54,6 +54,12 @@ export declare function planFindings(input: {
|
|
|
54
54
|
datasetCases?: readonly unknown[];
|
|
55
55
|
isKnownModel?: IsKnownModel;
|
|
56
56
|
agents?: AgentCatalogPort;
|
|
57
|
+
internalAgents?: ReadonlyArray<{
|
|
58
|
+
id: string;
|
|
59
|
+
title: string;
|
|
60
|
+
playbook: string;
|
|
61
|
+
tools: string[];
|
|
62
|
+
}>;
|
|
57
63
|
}): Promise<{
|
|
58
64
|
ok: boolean;
|
|
59
65
|
findings: ValidationFinding[];
|
|
@@ -65,6 +71,12 @@ export declare function validateEvalText(input: {
|
|
|
65
71
|
datasetCases?: readonly unknown[];
|
|
66
72
|
isKnownModel?: IsKnownModel;
|
|
67
73
|
agents?: AgentCatalogPort;
|
|
74
|
+
internalAgents?: ReadonlyArray<{
|
|
75
|
+
id: string;
|
|
76
|
+
title: string;
|
|
77
|
+
playbook: string;
|
|
78
|
+
tools: string[];
|
|
79
|
+
}>;
|
|
68
80
|
}): Promise<{
|
|
69
81
|
findings: ValidationFinding[];
|
|
70
82
|
parsed: import("../../config/loadOutcome.js").LoadOutcome<LoadedEval>;
|
|
@@ -147,6 +159,12 @@ export declare function buildResultDetail(store: RunStore, id: string, caseId: s
|
|
|
147
159
|
} | null;
|
|
148
160
|
tags: string[];
|
|
149
161
|
suggestion: import("./suggestions.js").WireSuggestion | null;
|
|
162
|
+
grader_labels: {
|
|
163
|
+
[k: string]: {
|
|
164
|
+
label: "fail" | "pass";
|
|
165
|
+
note: string | null;
|
|
166
|
+
};
|
|
167
|
+
};
|
|
150
168
|
}[];
|
|
151
169
|
}>;
|
|
152
170
|
export declare function loadEvalListItems(input: {
|
package/dist/evals/read/api.js
CHANGED
|
@@ -99,6 +99,9 @@ export async function buildEvalDetail(input) {
|
|
|
99
99
|
agent = await liveAgentOf(input.agents, projectRoot, file.target.agent);
|
|
100
100
|
targetModel = file.defaults?.model ?? agent?.model ?? null;
|
|
101
101
|
}
|
|
102
|
+
else if (file.target.kind === "internal_agent") {
|
|
103
|
+
targetModel = file.defaults?.model ?? null;
|
|
104
|
+
}
|
|
102
105
|
else {
|
|
103
106
|
const target = await resolveEvalTarget(file, entry.outcome.value.path, projectRoot);
|
|
104
107
|
if (target.ok)
|
|
@@ -130,6 +133,7 @@ export async function planFindings(input) {
|
|
|
130
133
|
engine: { name: ENGINE_NAME, version: PINNED_PROMPTFOO_VERSION, nodeVersion: process.versions.node },
|
|
131
134
|
...(input.isKnownModel ? { isKnownModel: input.isKnownModel } : {}),
|
|
132
135
|
...(input.agents ? { agents: input.agents } : {}),
|
|
136
|
+
...(input.internalAgents ? { internalAgents: input.internalAgents } : {}),
|
|
133
137
|
});
|
|
134
138
|
return { ok: built.ok, findings: built.findings };
|
|
135
139
|
}
|
|
@@ -143,6 +147,7 @@ export async function validateEvalText(input) {
|
|
|
143
147
|
...(input.datasetCases !== undefined ? { datasetCases: input.datasetCases } : {}),
|
|
144
148
|
...(input.isKnownModel ? { isKnownModel: input.isKnownModel } : {}),
|
|
145
149
|
...(input.agents ? { agents: input.agents } : {}),
|
|
150
|
+
...(input.internalAgents ? { internalAgents: input.internalAgents } : {}),
|
|
146
151
|
});
|
|
147
152
|
const findings = checked.findings.length > 0 || parsed.ok
|
|
148
153
|
? checked.findings
|
|
@@ -222,11 +227,12 @@ export async function buildResultsPage(store, id, input) {
|
|
|
222
227
|
}
|
|
223
228
|
export async function buildResultDetail(store, id, caseId) {
|
|
224
229
|
const row = await runByIdOr404(store, id);
|
|
225
|
-
const [cases, results, reviews, suggestions] = await Promise.all([
|
|
230
|
+
const [cases, results, reviews, suggestions, graderLabels] = await Promise.all([
|
|
226
231
|
store.getEvalCases(row.evalRunId),
|
|
227
232
|
store.getEvalResultsForCase(row.evalRunId, caseId),
|
|
228
233
|
store.getEvalReviews(row.evalRunId),
|
|
229
234
|
store.listEvalSuggestions(row.evalRunId),
|
|
235
|
+
store.listEvalGraderLabels(row.evalRunId),
|
|
230
236
|
]);
|
|
231
237
|
const caseRow = cases.find((x) => x.caseId === caseId);
|
|
232
238
|
if (!caseRow || results.length === 0) {
|
|
@@ -240,6 +246,9 @@ export async function buildResultDetail(store, id, caseId) {
|
|
|
240
246
|
.map((r) => ({
|
|
241
247
|
...resultToWire(r, reviewByKey.get(resultKey(r.caseId, r.repeatIndex)), row.targetKind === "agent" ? (row.targetRef.agent_id ?? "") : undefined),
|
|
242
248
|
suggestion: suggestionFor(suggestions, r.caseId, r.repeatIndex),
|
|
249
|
+
grader_labels: Object.fromEntries(graderLabels
|
|
250
|
+
.filter((l) => l.caseId === r.caseId && l.repeatIndex === r.repeatIndex)
|
|
251
|
+
.map((l) => [l.graderId, { label: l.label, note: l.note }])),
|
|
243
252
|
})),
|
|
244
253
|
};
|
|
245
254
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { RunStore } from "../../runstore/port.js";
|
|
2
|
+
export type LabelCounts = {
|
|
3
|
+
pass: number;
|
|
4
|
+
fail: number;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Everything the console's labeling screen needs in one read: each result the judge graded for one grader, with the
|
|
8
|
+
* conversation, what the case expects, the judge's answer and the author's label so far. Results the judge errored on
|
|
9
|
+
* are left out (there is no verdict to compare with), and so are results that never ran.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildLabelQueue(store: RunStore, id: string, graderId: string): Promise<{
|
|
12
|
+
grader_id: string;
|
|
13
|
+
items: {
|
|
14
|
+
case: {
|
|
15
|
+
position: number;
|
|
16
|
+
};
|
|
17
|
+
result: import("./runs.js").WireResultDetail;
|
|
18
|
+
judge: {
|
|
19
|
+
passed: boolean;
|
|
20
|
+
score: number | null;
|
|
21
|
+
reason: string | null;
|
|
22
|
+
};
|
|
23
|
+
label: {
|
|
24
|
+
label: "fail" | "pass";
|
|
25
|
+
note: string | null;
|
|
26
|
+
} | null;
|
|
27
|
+
}[];
|
|
28
|
+
labeled_here: LabelCounts;
|
|
29
|
+
labeled_eval: LabelCounts;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* The label counts across the eval's runs, and which results of this run the judge graded that still have no label
|
|
33
|
+
* from you. No conversations: this is for a progress line and the Cases filter.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildLabelSummary(store: RunStore, id: string, graderId: string): Promise<{
|
|
36
|
+
grader_id: string;
|
|
37
|
+
labeled_eval: {
|
|
38
|
+
pass: number;
|
|
39
|
+
fail: number;
|
|
40
|
+
};
|
|
41
|
+
unlabeled: {
|
|
42
|
+
case_id: string;
|
|
43
|
+
repeat_index: number;
|
|
44
|
+
}[];
|
|
45
|
+
}>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { resultKey } from "../statsTypes.js";
|
|
2
|
+
import { EvalApiError, runByIdOr404 } from "./api.js";
|
|
3
|
+
import { resultToWire } from "./runs.js";
|
|
4
|
+
import { isJudgedType } from "../judged.js";
|
|
5
|
+
/**
|
|
6
|
+
* Everything the console's labeling screen needs in one read: each result the judge graded for one grader, with the
|
|
7
|
+
* conversation, what the case expects, the judge's answer and the author's label so far. Results the judge errored on
|
|
8
|
+
* are left out (there is no verdict to compare with), and so are results that never ran.
|
|
9
|
+
*/
|
|
10
|
+
export async function buildLabelQueue(store, id, graderId) {
|
|
11
|
+
const row = await runByIdOr404(store, id);
|
|
12
|
+
const [cases, results, labels, evalLabels] = await Promise.all([
|
|
13
|
+
store.getEvalCases(row.evalRunId),
|
|
14
|
+
store.listEvalResults(row.evalRunId),
|
|
15
|
+
store.listEvalGraderLabels(row.evalRunId),
|
|
16
|
+
store.listEvalGraderLabelsForEval(row.projectRoot, row.evalId, graderId),
|
|
17
|
+
]);
|
|
18
|
+
const caseById = new Map(cases.map((c) => [c.caseId, c]));
|
|
19
|
+
const labelByKey = new Map(labels.filter((l) => l.graderId === graderId).map((l) => [resultKey(l.caseId, l.repeatIndex), l]));
|
|
20
|
+
const gradeOf = (grades) => grades.find((g) => g.graderId === graderId);
|
|
21
|
+
const known = results.some((r) => gradeOf(r.grades) !== undefined);
|
|
22
|
+
if (!known) {
|
|
23
|
+
throw new EvalApiError(404, "EVAL_GRADER_NOT_FOUND", `Grader ${graderId} has no grades in run ${id}`);
|
|
24
|
+
}
|
|
25
|
+
const judged = results.find((r) => {
|
|
26
|
+
const g = gradeOf(r.grades);
|
|
27
|
+
return g !== undefined && isJudgedType(g.graderType);
|
|
28
|
+
});
|
|
29
|
+
if (!judged) {
|
|
30
|
+
throw new EvalApiError(400, "invalid_request", `Grader ${graderId} is not judged by a model, so it has nothing to label`);
|
|
31
|
+
}
|
|
32
|
+
const items = [...results]
|
|
33
|
+
.sort((a, b) => (caseById.get(a.caseId)?.position ?? 0) - (caseById.get(b.caseId)?.position ?? 0) || a.repeatIndex - b.repeatIndex)
|
|
34
|
+
.flatMap((r) => {
|
|
35
|
+
const grade = gradeOf(r.grades);
|
|
36
|
+
const caseRow = caseById.get(r.caseId);
|
|
37
|
+
if (!grade || grade.status !== "graded" || !caseRow)
|
|
38
|
+
return [];
|
|
39
|
+
const label = labelByKey.get(resultKey(r.caseId, r.repeatIndex));
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
case: { ...caseRow.case, position: caseRow.position },
|
|
43
|
+
result: resultToWire(r, undefined),
|
|
44
|
+
judge: { passed: grade.passed === true, score: grade.score, reason: grade.reason },
|
|
45
|
+
label: label ? { label: label.label, note: label.note } : null,
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
});
|
|
49
|
+
const count = (rows) => ({
|
|
50
|
+
pass: rows.filter((l) => l.label === "pass").length,
|
|
51
|
+
fail: rows.filter((l) => l.label === "fail").length,
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
grader_id: graderId,
|
|
55
|
+
items,
|
|
56
|
+
labeled_here: count(labels.filter((l) => l.graderId === graderId)),
|
|
57
|
+
labeled_eval: count(evalLabels),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The label counts across the eval's runs, and which results of this run the judge graded that still have no label
|
|
62
|
+
* from you. No conversations: this is for a progress line and the Cases filter.
|
|
63
|
+
*/
|
|
64
|
+
export async function buildLabelSummary(store, id, graderId) {
|
|
65
|
+
const row = await runByIdOr404(store, id);
|
|
66
|
+
const [labels, runLabels, graded] = await Promise.all([
|
|
67
|
+
store.listEvalGraderLabelsForEval(row.projectRoot, row.evalId, graderId),
|
|
68
|
+
store.listEvalGraderLabels(row.evalRunId),
|
|
69
|
+
store.listGradedResultKeys(row.evalRunId, graderId),
|
|
70
|
+
]);
|
|
71
|
+
const labeled = new Set(runLabels.filter((l) => l.graderId === graderId).map((l) => resultKey(l.caseId, l.repeatIndex)));
|
|
72
|
+
const unlabeled = graded
|
|
73
|
+
.filter((r) => !labeled.has(resultKey(r.caseId, r.repeatIndex)))
|
|
74
|
+
.map((r) => ({ case_id: r.caseId, repeat_index: r.repeatIndex }));
|
|
75
|
+
return {
|
|
76
|
+
grader_id: graderId,
|
|
77
|
+
labeled_eval: {
|
|
78
|
+
pass: labels.filter((l) => l.label === "pass").length,
|
|
79
|
+
fail: labels.filter((l) => l.label === "fail").length,
|
|
80
|
+
},
|
|
81
|
+
unlabeled,
|
|
82
|
+
};
|
|
83
|
+
}
|
package/dist/evals/read/list.js
CHANGED
|
@@ -103,7 +103,16 @@ export async function buildEvalListItems(input) {
|
|
|
103
103
|
bannerInputs.push({ evalId: loaded.id, status, last: lastSummary, previous: previousSummary });
|
|
104
104
|
const agentTarget = file.target.kind === "agent"
|
|
105
105
|
? await agentListTarget(file.target.agent, last, input.agents, projectRoot)
|
|
106
|
-
:
|
|
106
|
+
: file.target.kind === "internal_agent"
|
|
107
|
+
? {
|
|
108
|
+
kind: "agent",
|
|
109
|
+
agent_id: file.target.profile,
|
|
110
|
+
agent_name: file.target.profile,
|
|
111
|
+
model: file.defaults?.model ?? null,
|
|
112
|
+
revision: null,
|
|
113
|
+
label: `${file.target.profile} (internal)`,
|
|
114
|
+
}
|
|
115
|
+
: undefined;
|
|
107
116
|
const conv = agentTarget ? resolveConversation(file.conversation) : undefined;
|
|
108
117
|
const pipelinePath = paths.pipelinePath !== undefined ? posix(projectRoot, paths.pipelinePath) : undefined;
|
|
109
118
|
const stageFile = paths.stageFile !== undefined ? posix(projectRoot, paths.stageFile) : undefined;
|
|
@@ -106,6 +106,11 @@ export type EvalRunDetail = {
|
|
|
106
106
|
stats: Stats | null;
|
|
107
107
|
lowest_cases_by_grader: Record<string, LowestCase[]>;
|
|
108
108
|
current: RunCurrent;
|
|
109
|
+
cases: Array<{
|
|
110
|
+
id: string;
|
|
111
|
+
title: string | null;
|
|
112
|
+
position: number;
|
|
113
|
+
}>;
|
|
109
114
|
live?: Array<{
|
|
110
115
|
case_id: string;
|
|
111
116
|
repeat_index: number;
|
package/dist/evals/read/runs.js
CHANGED
|
@@ -218,11 +218,16 @@ export async function currentHashes(row, agents) {
|
|
|
218
218
|
return none;
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
|
+
function plannedCase(row) {
|
|
222
|
+
const title = row.case.title;
|
|
223
|
+
return { id: row.caseId, title: typeof title === "string" && title !== "" ? title : null, position: row.position };
|
|
224
|
+
}
|
|
221
225
|
export async function buildRunDetail(input) {
|
|
222
226
|
const { store, row } = input;
|
|
223
|
-
const [results, reviews] = await Promise.all([
|
|
227
|
+
const [results, reviews, storedCases] = await Promise.all([
|
|
224
228
|
store.listEvalResults(row.evalRunId),
|
|
225
229
|
store.getEvalReviews(row.evalRunId),
|
|
230
|
+
store.getEvalCases(row.evalRunId),
|
|
226
231
|
]);
|
|
227
232
|
const graders = graderRefsOf(row);
|
|
228
233
|
const grades = results.flatMap(toGradeRecords);
|
|
@@ -258,6 +263,7 @@ export async function buildRunDetail(input) {
|
|
|
258
263
|
? Object.fromEntries(graders.map((g) => [g.id, lowestCases(grades.filter((x) => x.graderId === g.id))]))
|
|
259
264
|
: {},
|
|
260
265
|
current: await currentHashes(row, input.agents),
|
|
266
|
+
cases: storedCases.map(plannedCase),
|
|
261
267
|
};
|
|
262
268
|
if (input.live && (row.status === "running" || row.status === "queued")) {
|
|
263
269
|
detail.live = input.live.phases.map((p) => ({
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { StageCaseRunner } from "./stageCaseRunner.js";
|
|
2
2
|
export type EvalCaseRunner = StageCaseRunner;
|
|
3
|
-
/** Routes each case to the stage or agent runner by the plan's target kind. */
|
|
3
|
+
/** Routes each case to the stage, agent, or internal-agent runner by the plan's target kind. */
|
|
4
4
|
export declare function createEvalCaseRunner(deps: {
|
|
5
5
|
stage: StageCaseRunner;
|
|
6
6
|
agent: StageCaseRunner;
|
|
7
|
+
internalAgent?: StageCaseRunner;
|
|
7
8
|
}): EvalCaseRunner;
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
import { isConversationTarget } from "../types.js";
|
|
2
|
+
/** Routes each case to the stage, agent, or internal-agent runner by the plan's target kind. */
|
|
2
3
|
export function createEvalCaseRunner(deps) {
|
|
3
4
|
const kinds = new Map();
|
|
4
|
-
const runnerOf = (evalRunId) =>
|
|
5
|
+
const runnerOf = (evalRunId) => {
|
|
6
|
+
const kind = kinds.get(evalRunId);
|
|
7
|
+
if (kind === "internal_agent" && deps.internalAgent)
|
|
8
|
+
return deps.internalAgent;
|
|
9
|
+
return kind === "agent" ? deps.agent : deps.stage;
|
|
10
|
+
};
|
|
5
11
|
return {
|
|
6
12
|
runCase(plan, req) {
|
|
7
|
-
|
|
13
|
+
const kind = plan.target.kind === "internal_agent" ? "internal_agent" : isConversationTarget(plan.target.kind) ? "agent" : "stage";
|
|
14
|
+
kinds.set(req.evalRunId, kind);
|
|
8
15
|
return runnerOf(req.evalRunId).runCase(plan, req);
|
|
9
16
|
},
|
|
10
17
|
async cancelAll(evalRunId) {
|
|
11
|
-
await Promise.all([
|
|
18
|
+
await Promise.all([
|
|
19
|
+
deps.stage.cancelAll(evalRunId),
|
|
20
|
+
deps.agent.cancelAll(evalRunId),
|
|
21
|
+
deps.internalAgent?.cancelAll(evalRunId),
|
|
22
|
+
]);
|
|
12
23
|
},
|
|
13
|
-
spend: (evalRunId) => deps.stage.spend(evalRunId) + deps.agent.spend(evalRunId),
|
|
24
|
+
spend: (evalRunId) => deps.stage.spend(evalRunId) + deps.agent.spend(evalRunId) + (deps.internalAgent?.spend(evalRunId) ?? 0),
|
|
14
25
|
addSpend: (evalRunId, usd) => runnerOf(evalRunId).addSpend(evalRunId, usd),
|
|
15
26
|
stopReason: (evalRunId) => runnerOf(evalRunId).stopReason?.(evalRunId),
|
|
16
27
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { OperatorAgentHost } from "../../operatorAgent/types.js";
|
|
2
|
+
import type { StageCaseRunner } from "./stageCaseRunner.js";
|
|
3
|
+
export declare function createInternalAgentCaseRunner(deps: {
|
|
4
|
+
host: () => OperatorAgentHost | undefined;
|
|
5
|
+
now?: () => number;
|
|
6
|
+
}): StageCaseRunner;
|