stageflow 0.40.0 → 0.44.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 +15 -4
- 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 +5 -0
- package/dist/agents/authorChat.js +120 -12
- package/dist/agents/authorSessionStore.d.ts +38 -0
- package/dist/agents/authorSessionStore.js +167 -0
- package/dist/agents/chatTurn.d.ts +2 -0
- package/dist/agents/chatTurn.js +17 -1
- package/dist/agents/errors.d.ts +1 -1
- package/dist/agents/errors.js +1 -0
- package/dist/agents/evalGate.d.ts +61 -0
- package/dist/agents/evalGate.js +103 -0
- package/dist/agents/evalSession.d.ts +26 -0
- package/dist/agents/evalSession.js +29 -0
- package/dist/agents/hostContext.d.ts +4 -1
- package/dist/agents/hostContext.js +4 -1
- package/dist/agents/runtime/piRuntime.d.ts +6 -2
- package/dist/agents/runtime/piRuntime.js +50 -16
- package/dist/agents/runtime/types.d.ts +3 -1
- package/dist/agents/service.d.ts +27 -2
- package/dist/agents/service.js +91 -15
- package/dist/agents/sessions.d.ts +8 -0
- package/dist/agents/sessions.js +53 -11
- package/dist/agents/store.d.ts +14 -3
- package/dist/agents/store.js +45 -7
- package/dist/agents/toolRisk.d.ts +21 -0
- package/dist/agents/toolRisk.js +50 -0
- package/dist/cli/doctorCommand.js +26 -0
- package/dist/cli/evalCommand.d.ts +20 -0
- package/dist/cli/evalCommand.js +720 -0
- package/dist/cli/exportAllCommand.js +1 -1
- package/dist/cli/hostClient.d.ts +60 -0
- package/dist/cli/hostClient.js +71 -0
- package/dist/cli/validateOutput.d.ts +2 -2
- package/dist/cli/validateOutput.js +2 -2
- package/dist/cli.js +10 -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/atomicWrite.d.ts +15 -0
- package/dist/config/atomicWrite.js +43 -0
- package/dist/config/browseCatalog.d.ts +2 -0
- package/dist/config/browseCatalog.js +4 -2
- package/dist/config/createPipeline.js +2 -0
- package/dist/config/createTrigger.js +7 -1
- package/dist/config/csv.d.ts +9 -0
- package/dist/config/csv.js +81 -0
- package/dist/config/datasetAgentCheck.d.ts +18 -0
- package/dist/config/datasetAgentCheck.js +109 -0
- package/dist/config/datasetCandidates.d.ts +22 -0
- package/dist/config/datasetCandidates.js +86 -0
- package/dist/config/datasetFromSessions.d.ts +34 -0
- package/dist/config/datasetFromSessions.js +105 -0
- package/dist/config/datasetHash.d.ts +1 -0
- package/dist/config/datasetHash.js +4 -0
- package/dist/config/datasetImport.d.ts +21 -0
- package/dist/config/datasetImport.js +120 -0
- package/dist/config/datasetStageCheck.d.ts +9 -0
- package/dist/config/datasetStageCheck.js +17 -0
- package/dist/config/datasetTypes.d.ts +27 -0
- package/dist/config/datasetTypes.js +1 -0
- package/dist/config/ensureCatalogScanRoot.d.ts +4 -1
- package/dist/config/ensureCatalogScanRoot.js +8 -6
- package/dist/config/evalCatalog.d.ts +22 -0
- package/dist/config/evalCatalog.js +95 -0
- package/dist/config/evalWriteRoots.d.ts +17 -0
- package/dist/config/evalWriteRoots.js +109 -0
- package/dist/config/githubTriggerAction.d.ts +8 -0
- package/dist/config/githubTriggerAction.js +29 -0
- package/dist/config/hostConfig.js +3 -0
- package/dist/config/installEvalSample.d.ts +34 -0
- package/dist/config/installEvalSample.js +182 -0
- package/dist/config/loadDataset.d.ts +16 -0
- package/dist/config/loadDataset.js +318 -0
- package/dist/config/loadEval.d.ts +32 -0
- package/dist/config/loadEval.js +1103 -0
- package/dist/config/loadOutcome.d.ts +5 -0
- package/dist/config/loadStageflowManifest.js +64 -0
- 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/resolveAgentTarget.d.ts +32 -0
- package/dist/config/resolveAgentTarget.js +118 -0
- package/dist/config/resolveEvalTarget.d.ts +21 -0
- package/dist/config/resolveEvalTarget.js +89 -0
- package/dist/config/scanCatalogPaths.d.ts +1 -1
- package/dist/config/scanCatalogPaths.js +17 -5
- package/dist/config/validateCatalog.d.ts +2 -2
- package/dist/config/validateCatalog.js +21 -1
- package/dist/config/validateEval.d.ts +36 -0
- package/dist/config/validateEval.js +446 -0
- package/dist/config/writeDataset.d.ts +54 -0
- package/dist/config/writeDataset.js +186 -0
- package/dist/config/writeEval.d.ts +25 -0
- package/dist/config/writeEval.js +398 -0
- package/dist/diagnostics/checks.js +1 -1
- 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/agentDiff.d.ts +13 -0
- package/dist/evals/agentDiff.js +11 -0
- package/dist/evals/canonical.d.ts +3 -0
- package/dist/evals/canonical.js +24 -0
- package/dist/evals/caseTask.d.ts +3 -0
- package/dist/evals/caseTask.js +9 -0
- package/dist/evals/compare.d.ts +94 -0
- package/dist/evals/compare.js +201 -0
- package/dist/evals/constants.d.ts +62 -0
- package/dist/evals/constants.js +97 -0
- package/dist/evals/engine/FakeEngine.d.ts +33 -0
- package/dist/evals/engine/FakeEngine.js +177 -0
- package/dist/evals/engine/index.d.ts +9 -0
- package/dist/evals/engine/index.js +19 -0
- package/dist/evals/engine/promptfoo/PromptfooEngine.d.ts +52 -0
- package/dist/evals/engine/promptfoo/PromptfooEngine.js +312 -0
- package/dist/evals/engine/promptfoo/errors.d.ts +5 -0
- package/dist/evals/engine/promptfoo/errors.js +8 -0
- package/dist/evals/engine/promptfoo/generate.d.ts +30 -0
- package/dist/evals/engine/promptfoo/generate.js +345 -0
- package/dist/evals/engine/promptfoo/guard.d.ts +10 -0
- package/dist/evals/engine/promptfoo/guard.js +116 -0
- package/dist/evals/engine/promptfoo/install.d.ts +17 -0
- package/dist/evals/engine/promptfoo/install.js +73 -0
- package/dist/evals/engine/promptfoo/judgeProviders.d.ts +2 -0
- package/dist/evals/engine/promptfoo/judgeProviders.js +9 -0
- package/dist/evals/engine/promptfoo/judgeServices.d.ts +6 -0
- package/dist/evals/engine/promptfoo/judgeServices.js +41 -0
- package/dist/evals/engine/promptfoo/locate.d.ts +21 -0
- package/dist/evals/engine/promptfoo/locate.js +68 -0
- package/dist/evals/engine/promptfoo/nodeVersion.d.ts +7 -0
- package/dist/evals/engine/promptfoo/nodeVersion.js +14 -0
- package/dist/evals/engine/promptfoo/normalize.d.ts +66 -0
- package/dist/evals/engine/promptfoo/normalize.js +261 -0
- package/dist/evals/engine/promptfoo/pinned.d.ts +5 -0
- package/dist/evals/engine/promptfoo/pinned.js +5 -0
- package/dist/evals/engine/promptfoo/rubricPrompt.d.ts +14 -0
- package/dist/evals/engine/promptfoo/rubricPrompt.js +105 -0
- package/dist/evals/engine/promptfoo/runTokens.d.ts +18 -0
- package/dist/evals/engine/promptfoo/runTokens.js +31 -0
- package/dist/evals/engine/promptfoo/status.d.ts +13 -0
- package/dist/evals/engine/promptfoo/status.js +16 -0
- package/dist/evals/estimate.d.ts +56 -0
- package/dist/evals/estimate.js +66 -0
- package/dist/evals/graders/codeGrader.d.ts +6 -0
- package/dist/evals/graders/codeGrader.js +85 -0
- package/dist/evals/graders/conversationCheckGrader.d.ts +6 -0
- package/dist/evals/graders/conversationCheckGrader.js +62 -0
- package/dist/evals/graders/fieldGrader.d.ts +11 -0
- package/dist/evals/graders/fieldGrader.js +117 -0
- package/dist/evals/graders/goal.d.ts +3 -0
- package/dist/evals/graders/goal.js +14 -0
- package/dist/evals/graders/index.d.ts +18 -0
- package/dist/evals/graders/index.js +34 -0
- package/dist/evals/graders/notApplicable.d.ts +5 -0
- package/dist/evals/graders/notApplicable.js +9 -0
- package/dist/evals/graders/path.d.ts +26 -0
- package/dist/evals/graders/path.js +75 -0
- package/dist/evals/graders/referenceGrader.d.ts +5 -0
- package/dist/evals/graders/referenceGrader.js +59 -0
- package/dist/evals/graders/schemaGrader.d.ts +5 -0
- package/dist/evals/graders/schemaGrader.js +29 -0
- package/dist/evals/graders/subject.d.ts +6 -0
- package/dist/evals/graders/subject.js +33 -0
- package/dist/evals/graders/toolCallsGrader.d.ts +6 -0
- package/dist/evals/graders/toolCallsGrader.js +100 -0
- package/dist/evals/graders/transcript.d.ts +12 -0
- package/dist/evals/graders/transcript.js +57 -0
- package/dist/evals/graders/types.d.ts +20 -0
- package/dist/evals/graders/types.js +1 -0
- package/dist/evals/judgeProviders.d.ts +16 -0
- package/dist/evals/judgeProviders.js +27 -0
- package/dist/evals/lineDiff.d.ts +5 -0
- package/dist/evals/lineDiff.js +34 -0
- package/dist/evals/listStatus.d.ts +31 -0
- package/dist/evals/listStatus.js +48 -0
- package/dist/evals/manager.d.ts +187 -0
- package/dist/evals/manager.js +795 -0
- package/dist/evals/plan.d.ts +65 -0
- package/dist/evals/plan.js +621 -0
- package/dist/evals/planInternalAgent.d.ts +19 -0
- package/dist/evals/planInternalAgent.js +205 -0
- package/dist/evals/providerKeys.d.ts +1 -0
- package/dist/evals/providerKeys.js +21 -0
- package/dist/evals/read/agentTargets.d.ts +37 -0
- package/dist/evals/read/agentTargets.js +101 -0
- package/dist/evals/read/api.d.ts +208 -0
- package/dist/evals/read/api.js +363 -0
- package/dist/evals/read/compare.d.ts +4 -0
- package/dist/evals/read/compare.js +39 -0
- package/dist/evals/read/datasets.d.ts +105 -0
- package/dist/evals/read/datasets.js +318 -0
- package/dist/evals/read/list.d.ts +66 -0
- package/dist/evals/read/list.js +182 -0
- package/dist/evals/read/results.d.ts +46 -0
- package/dist/evals/read/results.js +107 -0
- package/dist/evals/read/runs.d.ts +154 -0
- package/dist/evals/read/runs.js +295 -0
- package/dist/evals/read/suggestions.d.ts +43 -0
- package/dist/evals/read/suggestions.js +73 -0
- package/dist/evals/runner/FakeAgentBackend.d.ts +40 -0
- package/dist/evals/runner/FakeAgentBackend.js +82 -0
- package/dist/evals/runner/agentCaseRunner.d.ts +24 -0
- package/dist/evals/runner/agentCaseRunner.js +388 -0
- package/dist/evals/runner/caseRunner.d.ts +8 -0
- package/dist/evals/runner/caseRunner.js +28 -0
- package/dist/evals/runner/conversationSubject.d.ts +18 -0
- package/dist/evals/runner/conversationSubject.js +123 -0
- package/dist/evals/runner/internalAgentCaseRunner.d.ts +6 -0
- package/dist/evals/runner/internalAgentCaseRunner.js +250 -0
- package/dist/evals/runner/simulatorModel.d.ts +51 -0
- package/dist/evals/runner/simulatorModel.js +58 -0
- package/dist/evals/runner/simulatorPrompt.d.ts +29 -0
- package/dist/evals/runner/simulatorPrompt.js +59 -0
- package/dist/evals/runner/stageCaseRunner.d.ts +30 -0
- package/dist/evals/runner/stageCaseRunner.js +279 -0
- package/dist/evals/runner/userDriver.d.ts +71 -0
- package/dist/evals/runner/userDriver.js +104 -0
- package/dist/evals/scoring.d.ts +34 -0
- package/dist/evals/scoring.js +67 -0
- package/dist/evals/snapshot.d.ts +191 -0
- package/dist/evals/snapshot.js +70 -0
- package/dist/evals/stageDiff.d.ts +8 -0
- package/dist/evals/stageDiff.js +48 -0
- package/dist/evals/stats.d.ts +95 -0
- package/dist/evals/stats.js +220 -0
- package/dist/evals/statsAdapter.d.ts +4 -0
- package/dist/evals/statsAdapter.js +30 -0
- package/dist/evals/statsTypes.d.ts +51 -0
- package/dist/evals/statsTypes.js +18 -0
- package/dist/evals/storeError.d.ts +5 -0
- package/dist/evals/storeError.js +8 -0
- package/dist/evals/storeTypes.d.ts +207 -0
- package/dist/evals/storeTypes.js +1 -0
- package/dist/evals/tTable.d.ts +3 -0
- package/dist/evals/tTable.js +15 -0
- package/dist/evals/triage/constants.d.ts +26 -0
- package/dist/evals/triage/constants.js +33 -0
- package/dist/evals/triage/credentials.d.ts +13 -0
- package/dist/evals/triage/credentials.js +20 -0
- package/dist/evals/triage/jevClassifier.d.ts +14 -0
- package/dist/evals/triage/jevClassifier.js +124 -0
- package/dist/evals/triage/judgeClassifier.d.ts +10 -0
- package/dist/evals/triage/judgeClassifier.js +76 -0
- package/dist/evals/triage/prompts.d.ts +16 -0
- package/dist/evals/triage/prompts.js +64 -0
- package/dist/evals/triage/service.d.ts +79 -0
- package/dist/evals/triage/service.js +217 -0
- package/dist/evals/triage/stateBuilder.d.ts +19 -0
- package/dist/evals/triage/stateBuilder.js +125 -0
- package/dist/evals/triage/types.d.ts +60 -0
- package/dist/evals/triage/types.js +8 -0
- package/dist/evals/types.d.ts +357 -0
- package/dist/evals/types.js +4 -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 +16 -0
- package/dist/mcp/evalTools.d.ts +3 -0
- package/dist/mcp/evalTools.js +943 -0
- 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 +6 -0
- package/dist/mcp/tools.js +8 -0
- package/dist/mcp/triggerTools.js +77 -31
- package/dist/models/response.d.ts +7 -2
- package/dist/models/response.js +6 -1
- package/dist/operatorAgent/agentAuthorContext.d.ts +1 -1
- package/dist/operatorAgent/agentAuthorContext.js +1 -1
- 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 +32 -14
- package/dist/operatorAgent/profiles/agentAuthor.d.ts +3 -1
- package/dist/operatorAgent/profiles/agentAuthor.js +201 -32
- package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -1
- package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +48 -15
- package/dist/operatorAgent/profiles/authorReadable.d.ts +2 -0
- package/dist/operatorAgent/profiles/authorReadable.js +26 -0
- 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 +132 -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 +43 -0
- 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 +29 -0
- package/dist/runstore/sqlite/SqliteRunStore.js +144 -50
- package/dist/runstore/sqlite/evalStore.d.ts +20 -0
- package/dist/runstore/sqlite/evalStore.js +541 -0
- package/dist/runstore/sqlite/migrations/015-evals.d.ts +12 -0
- package/dist/runstore/sqlite/migrations/015-evals.js +157 -0
- package/dist/runstore/sqlite/migrations/016-eval-subject-ref.d.ts +12 -0
- package/dist/runstore/sqlite/migrations/016-eval-subject-ref.js +20 -0
- package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.d.ts +11 -0
- package/dist/runstore/sqlite/migrations/017-eval-result-suggestions.js +36 -0
- package/dist/runstore/sqlite/migrations/index.js +6 -0
- package/dist/runstore/sqlite/suggestionStore.d.ts +14 -0
- package/dist/runstore/sqlite/suggestionStore.js +132 -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/pipelineRunner.d.ts +2 -1
- package/dist/runtime/pipelineRunner.js +2 -0
- 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 +6 -2
- package/dist/runtime/runManager.js +60 -16
- package/dist/runtime/runRetentionSweep.js +2 -2
- 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 +59 -1
- package/dist/server/bootstrap.d.ts +13 -0
- package/dist/server/bootstrap.js +69 -0
- package/dist/server/controlToken.js +3 -0
- package/dist/server/evalInternalRoutes.d.ts +14 -0
- package/dist/server/evalInternalRoutes.js +87 -0
- package/dist/server/evalRouteContext.d.ts +46 -0
- package/dist/server/evalRouteContext.js +43 -0
- package/dist/server/evalRoutes.d.ts +5 -0
- package/dist/server/evalRoutes.js +1456 -0
- package/dist/server/evalTriageRoutes.d.ts +2 -0
- package/dist/server/evalTriageRoutes.js +95 -0
- package/dist/server/guideRoutes.d.ts +5 -0
- package/dist/server/guideRoutes.js +166 -0
- package/dist/server/http.d.ts +15 -0
- package/dist/server/http.js +67 -3
- package/dist/server/internalAgentRoutes.d.ts +6 -0
- package/dist/server/internalAgentRoutes.js +12 -0
- package/dist/server/mcpHost.js +5 -0
- package/dist/toolkit/meta.d.ts +1 -1
- package/dist/toolkit/meta.js +53 -0
- package/dist/toolkit/profiles.d.ts +5 -0
- package/dist/toolkit/profiles.js +13 -1
- 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/types/stageflowManifest.d.ts +6 -0
- package/dist/ui/assets/{MarkdownText-D7tYaIFO.js → MarkdownText-S5C_vemc.js} +2 -2
- package/dist/ui/assets/adapters-C0l4ruiR.js +17 -0
- package/dist/ui/assets/chat-CjnsmvqR.js +2 -0
- package/dist/ui/assets/chat-DFDd4UjS.css +2 -0
- package/dist/ui/assets/{main-BFo79krC.css → main-Del1GeLf.css} +1 -1
- package/dist/ui/assets/main-_yXVqcW9.js +277 -0
- 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/README.md +2 -0
- 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/document-policy-review/README.md +35 -0
- package/examples/document-policy-review/agents/compliance.agent.yaml +42 -0
- package/examples/document-policy-review/documents/acme-vendor-sow.md +15 -0
- package/examples/document-policy-review/documents/support-runbook.md +13 -0
- package/examples/document-policy-review/policies/acceptable-use.md +13 -0
- package/examples/document-policy-review/policies/data-handling.md +17 -0
- package/examples/document-policy-review/policies/vendor-security.md +17 -0
- package/examples/evals/README.md +141 -0
- package/examples/evals/critique-sample.dataset.jsonl +8 -0
- package/examples/evals/critique-sample.eval.yaml +34 -0
- package/examples/evals/critique-sample.task.yaml +4 -0
- package/examples/evals/eval-sample.pipeline.yaml +35 -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/evals/support-sample.agent.yaml +20 -0
- package/examples/evals/support-sample.dataset.jsonl +6 -0
- package/examples/evals/support-sample.eval.yaml +38 -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/examples/stageflow.yaml +6 -0
- package/package.json +1 -1
- package/skills/stageflow/SKILL.md +5 -2
- package/skills/stageflow/references/control-surface.md +4 -2
- package/skills/stageflow/references/evals.md +68 -0
- package/skills/stageflow-author/SKILL.md +4 -0
- package/skills/stageflow-run/SKILL.md +4 -0
- package/dist/ui/assets/AssistantRuntimeProvider-CsiPFhCT.js +0 -9
- package/dist/ui/assets/ReadonlyStore-BfXqHykm.js +0 -6
- package/dist/ui/assets/chat-BbLukq9W.js +0 -5
- package/dist/ui/assets/chat-zIZU_bP1.css +0 -2
- package/dist/ui/assets/main-CijYMeM0.js +0 -259
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { GUARD_FILENAME, GUARD_SOURCE } from "./guard.js";
|
|
2
|
+
import { EngineError } from "./errors.js";
|
|
3
|
+
import { JUDGE_MAX_OUTPUT_TOKENS } from "../../constants.js";
|
|
4
|
+
import { mapJudge, unsupportedJudgeMessage } from "../../judgeProviders.js";
|
|
5
|
+
import { caseGoal, goalRubricText } from "../../graders/goal.js";
|
|
6
|
+
import { escapeTemplate, renderConversationRubricPrompt, renderRubricPrompt } from "./rubricPrompt.js";
|
|
7
|
+
import { isConversationTarget } from "../../types.js";
|
|
8
|
+
export const CALLBACK_URL_ENV = "STAGEFLOW_EVAL_CALLBACK_URL";
|
|
9
|
+
export const RUN_TOKEN_ENV = "STAGEFLOW_EVAL_TOKEN";
|
|
10
|
+
export const CONFIG_FILE = "promptfooconfig.json";
|
|
11
|
+
export const PROVIDER_FILE = "provider.mjs";
|
|
12
|
+
export const ASSERTIONS_FILE = "assertions.mjs";
|
|
13
|
+
export const HOOKS_FILE = "hooks.mjs";
|
|
14
|
+
export const DATASET_FILE = "dataset.json";
|
|
15
|
+
export const RESULTS_STREAM_FILE = "results.ndjson";
|
|
16
|
+
export const RESULTS_FILE = "results.json";
|
|
17
|
+
export const EMPTY_EXPECTED = "(none)";
|
|
18
|
+
export function assertionFnName(index) {
|
|
19
|
+
return `grader${index}`;
|
|
20
|
+
}
|
|
21
|
+
export function buildProviderSource(evalRunId, agent = false) {
|
|
22
|
+
const okMeta = agent
|
|
23
|
+
? `
|
|
24
|
+
subjectRef: reply.subjectRef,
|
|
25
|
+
turns: reply.output && reply.output.turns,
|
|
26
|
+
toolCallCount: reply.output && Array.isArray(reply.output.tool_calls) ? reply.output.tool_calls.length : undefined,`
|
|
27
|
+
: "";
|
|
28
|
+
const failKeys = agent ? '["stageRunId", "subjectRef", "latencyMs", "costUsd"]' : '["stageRunId", "latencyMs", "costUsd"]';
|
|
29
|
+
return `import http from "node:http";
|
|
30
|
+
|
|
31
|
+
const EVAL_RUN_ID = ${JSON.stringify(evalRunId)};
|
|
32
|
+
|
|
33
|
+
function post(url, token, payload) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const body = JSON.stringify(payload);
|
|
36
|
+
const req = http.request(
|
|
37
|
+
url,
|
|
38
|
+
{
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: {
|
|
41
|
+
"content-type": "application/json",
|
|
42
|
+
"content-length": Buffer.byteLength(body),
|
|
43
|
+
authorization: "Bearer " + token,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
(res) => {
|
|
47
|
+
const chunks = [];
|
|
48
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
49
|
+
res.on("end", () => resolve({ status: res.statusCode ?? 0, body: Buffer.concat(chunks).toString("utf8") }));
|
|
50
|
+
res.on("error", reject);
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
req.on("error", reject);
|
|
54
|
+
req.end(body);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default class StageflowHostProvider {
|
|
59
|
+
id() {
|
|
60
|
+
return "stageflow-host";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async callApi(_prompt, context) {
|
|
64
|
+
const caseId = String(context?.vars?.caseId ?? "");
|
|
65
|
+
const index = context?.repeatIndex ?? context?.vars?.__repeatIndex;
|
|
66
|
+
const repeatIndex = Number.isInteger(index) ? index : 0;
|
|
67
|
+
const base = { caseId, repeatIndex };
|
|
68
|
+
const failure = (code, message, extra = {}) => ({
|
|
69
|
+
error: code + ": " + message,
|
|
70
|
+
metadata: { ...base, errorCode: code, ...extra },
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const url = process.env.${CALLBACK_URL_ENV};
|
|
74
|
+
const token = process.env.${RUN_TOKEN_ENV};
|
|
75
|
+
if (!url || !token) return failure("EVAL_ENGINE_ERROR", "host callback is not configured");
|
|
76
|
+
const res = await post(url, token, { eval_run_id: EVAL_RUN_ID, case_id: caseId, repeat_index: repeatIndex });
|
|
77
|
+
if (res.status !== 200) return failure("EVAL_ENGINE_ERROR", "host callback answered " + res.status);
|
|
78
|
+
let reply;
|
|
79
|
+
try {
|
|
80
|
+
reply = JSON.parse(res.body);
|
|
81
|
+
} catch {
|
|
82
|
+
return failure("EVAL_ENGINE_ERROR", "host callback reply is not JSON");
|
|
83
|
+
}
|
|
84
|
+
if (reply && reply.ok === true) {
|
|
85
|
+
return {
|
|
86
|
+
output: JSON.stringify(reply.output),
|
|
87
|
+
metadata: {
|
|
88
|
+
...base,
|
|
89
|
+
stageRunId: reply.stageRunId,${okMeta}
|
|
90
|
+
latencyMs: reply.latencyMs,
|
|
91
|
+
costUsd: reply.costUsd,
|
|
92
|
+
tokensIn: reply.tokensIn,
|
|
93
|
+
tokensOut: reply.tokensOut,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const extra = {};
|
|
98
|
+
for (const key of ${failKeys}) {
|
|
99
|
+
if (reply && reply[key] !== undefined) extra[key] = reply[key];
|
|
100
|
+
}
|
|
101
|
+
return failure(
|
|
102
|
+
typeof reply?.code === "string" ? reply.code : "EVAL_ENGINE_ERROR",
|
|
103
|
+
typeof reply?.message === "string" ? reply.message : "stage case failed",
|
|
104
|
+
extra,
|
|
105
|
+
);
|
|
106
|
+
} catch {
|
|
107
|
+
return failure("EVAL_ENGINE_ERROR", "host callback failed");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
export function buildHooksSource(agent = false) {
|
|
114
|
+
const metaKeys = agent
|
|
115
|
+
? '["caseId", "repeatIndex", "stageRunId", "subjectRef", "turns", "toolCallCount", "latencyMs", "costUsd", "tokensIn", "tokensOut", "errorCode"]'
|
|
116
|
+
: '["caseId", "repeatIndex", "stageRunId", "latencyMs", "costUsd", "tokensIn", "tokensOut", "errorCode"]';
|
|
117
|
+
return `import { appendFileSync } from "node:fs";
|
|
118
|
+
|
|
119
|
+
const STREAM = new URL(${JSON.stringify(RESULTS_STREAM_FILE)}, import.meta.url);
|
|
120
|
+
const META_KEYS = ${metaKeys};
|
|
121
|
+
|
|
122
|
+
function pickMeta(meta) {
|
|
123
|
+
const out = {};
|
|
124
|
+
if (meta && typeof meta === "object") {
|
|
125
|
+
for (const key of META_KEYS) if (meta[key] !== undefined) out[key] = meta[key];
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function pickComponent(c) {
|
|
131
|
+
const graderError = c?.metadata?.graderError === true;
|
|
132
|
+
return {
|
|
133
|
+
metric: c?.assertion?.metric,
|
|
134
|
+
type: c?.assertion?.type,
|
|
135
|
+
pass: c?.pass === true,
|
|
136
|
+
score: typeof c?.score === "number" ? c.score : undefined,
|
|
137
|
+
reason: graderError || typeof c?.reason !== "string" ? undefined : c.reason,
|
|
138
|
+
tokensIn: typeof c?.tokensUsed?.prompt === "number" ? c.tokensUsed.prompt : undefined,
|
|
139
|
+
tokensOut: typeof c?.tokensUsed?.completion === "number" ? c.tokensUsed.completion : undefined,
|
|
140
|
+
graderError,
|
|
141
|
+
errorCode: typeof c?.metadata?.errorCode === "string" ? c.metadata.errorCode : undefined,
|
|
142
|
+
stageflow: c?.metadata?.stageflow,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export async function afterEach(context) {
|
|
147
|
+
try {
|
|
148
|
+
const r = context?.result ?? {};
|
|
149
|
+
const record = {
|
|
150
|
+
testIdx: r.testIdx,
|
|
151
|
+
caseId: typeof r.vars?.caseId === "string" ? r.vars.caseId : undefined,
|
|
152
|
+
failureReason: r.failureReason,
|
|
153
|
+
metadata: pickMeta(r.response?.metadata ?? r.metadata),
|
|
154
|
+
output: typeof r.response?.output === "string" ? r.response.output : undefined,
|
|
155
|
+
providerError: typeof r.response?.error === "string" ? r.response.error : undefined,
|
|
156
|
+
components: (r.gradingResult?.componentResults ?? []).map(pickComponent),
|
|
157
|
+
};
|
|
158
|
+
appendFileSync(STREAM, JSON.stringify(record) + "\\n");
|
|
159
|
+
} catch {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
`;
|
|
164
|
+
}
|
|
165
|
+
const STAGE_TO_SUBJECT = `function toSubject(output) {
|
|
166
|
+
const value = typeof output === "string" ? JSON.parse(output) : output;
|
|
167
|
+
return {
|
|
168
|
+
status: value.status,
|
|
169
|
+
summary: value.summary,
|
|
170
|
+
...(value.payload !== undefined ? { payload: value.payload } : {}),
|
|
171
|
+
artifacts: Array.isArray(value.artifacts) ? value.artifacts : [],
|
|
172
|
+
};
|
|
173
|
+
}`;
|
|
174
|
+
const AGENT_TO_SUBJECT = `function toSubject(output) {
|
|
175
|
+
const value = typeof output === "string" ? JSON.parse(output) : output;
|
|
176
|
+
if (value.kind === "conversation") {
|
|
177
|
+
const { transcript: _transport, ...subject } = value;
|
|
178
|
+
return subject;
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
status: value.status,
|
|
182
|
+
summary: value.summary,
|
|
183
|
+
...(value.payload !== undefined ? { payload: value.payload } : {}),
|
|
184
|
+
artifacts: Array.isArray(value.artifacts) ? value.artifacts : [],
|
|
185
|
+
};
|
|
186
|
+
}`;
|
|
187
|
+
const MISSING_GOAL_GRADE = `function missingGoal(index) {
|
|
188
|
+
return {
|
|
189
|
+
pass: false,
|
|
190
|
+
score: 0,
|
|
191
|
+
reason: "EVAL_CASE_MISSING_EXPECTED",
|
|
192
|
+
metadata: {
|
|
193
|
+
graderError: true,
|
|
194
|
+
errorCode: "EVAL_CASE_MISSING_EXPECTED",
|
|
195
|
+
stageflow: {
|
|
196
|
+
graderId: GRADERS[index].id,
|
|
197
|
+
graderType: GRADERS[index].type,
|
|
198
|
+
status: "error",
|
|
199
|
+
errorCode: "EVAL_CASE_MISSING_EXPECTED",
|
|
200
|
+
reason: "case has no input.goal or expected.outcome",
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
`;
|
|
207
|
+
function isJudged(grader) {
|
|
208
|
+
return grader.type === "rubric" || grader.type === "goal_reached";
|
|
209
|
+
}
|
|
210
|
+
export function buildAssertionsSource(plan, graderModuleUrl) {
|
|
211
|
+
const agent = isConversationTarget(plan.target.kind);
|
|
212
|
+
const graders = plan.graders.map((g, index) => ({ index, grader: g }));
|
|
213
|
+
const exports = graders
|
|
214
|
+
.filter(({ grader }) => grader.type !== "rubric" && (agent || grader.type !== "goal_reached"))
|
|
215
|
+
.map(({ index }) => `export const ${assertionFnName(index)} = (output, context) => run(${index}, output, context);`);
|
|
216
|
+
return `import { readFileSync } from "node:fs";
|
|
217
|
+
import { gradeDeterministic } from ${JSON.stringify(graderModuleUrl)};
|
|
218
|
+
|
|
219
|
+
const GRADERS = ${JSON.stringify(plan.graders)};
|
|
220
|
+
const BASE_CONTEXT = ${JSON.stringify({
|
|
221
|
+
evalId: plan.evalId,
|
|
222
|
+
runId: plan.evalRunId,
|
|
223
|
+
passThreshold: plan.passThreshold,
|
|
224
|
+
...(plan.outputSchema !== undefined ? { outputSchema: plan.outputSchema } : {}),
|
|
225
|
+
})};
|
|
226
|
+
const CASES = new Map(
|
|
227
|
+
JSON.parse(readFileSync(new URL(${JSON.stringify(DATASET_FILE)}, import.meta.url), "utf8")).map((c) => [c.id, c]),
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
${agent ? AGENT_TO_SUBJECT : STAGE_TO_SUBJECT}
|
|
231
|
+
|
|
232
|
+
function engineError(index) {
|
|
233
|
+
return {
|
|
234
|
+
pass: false,
|
|
235
|
+
score: 0,
|
|
236
|
+
reason: "grader failed to run",
|
|
237
|
+
metadata: {
|
|
238
|
+
graderError: true,
|
|
239
|
+
errorCode: "EVAL_ENGINE_ERROR",
|
|
240
|
+
stageflow: { graderId: GRADERS[index].id, graderType: GRADERS[index].type, status: "error", errorCode: "EVAL_ENGINE_ERROR" },
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
${agent ? MISSING_GOAL_GRADE : ""}function run(index, output, context) {
|
|
246
|
+
try {
|
|
247
|
+
const grader = GRADERS[index];
|
|
248
|
+
${agent ? ' if (grader.type === "goal_reached") return missingGoal(index);\n' : ""} const testCase = CASES.get(context?.vars?.caseId);
|
|
249
|
+
if (!testCase) return engineError(index);
|
|
250
|
+
const repeat = context?.providerResponse?.metadata?.repeatIndex;
|
|
251
|
+
const grade = gradeDeterministic(grader, toSubject(output), testCase, {
|
|
252
|
+
...BASE_CONTEXT,
|
|
253
|
+
repeat: Number.isInteger(repeat) ? repeat : 0,
|
|
254
|
+
});
|
|
255
|
+
if (grade.status === "error") {
|
|
256
|
+
return {
|
|
257
|
+
pass: false,
|
|
258
|
+
score: 0,
|
|
259
|
+
reason: grade.errorCode ?? "EVAL_ENGINE_ERROR",
|
|
260
|
+
metadata: { graderError: true, errorCode: grade.errorCode ?? "EVAL_ENGINE_ERROR", stageflow: grade },
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
pass: grade.passed === true,
|
|
265
|
+
score: typeof grade.score === "number" ? grade.score : 0,
|
|
266
|
+
reason: grade.reason ?? (grade.passed === true ? "passed" : "failed"),
|
|
267
|
+
metadata: { stageflow: grade },
|
|
268
|
+
};
|
|
269
|
+
} catch {
|
|
270
|
+
return engineError(index);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
${exports.join("\n")}
|
|
275
|
+
`;
|
|
276
|
+
}
|
|
277
|
+
function judgeAssertion(grader, options, agent, testCase) {
|
|
278
|
+
const mapping = mapJudge(grader.judge);
|
|
279
|
+
if (mapping === null)
|
|
280
|
+
throw new EngineError("EVAL_INVALID", unsupportedJudgeMessage(grader.judge));
|
|
281
|
+
let rubric;
|
|
282
|
+
let prompt;
|
|
283
|
+
if (grader.type === "goal_reached") {
|
|
284
|
+
rubric = escapeTemplate(goalRubricText(caseGoal(testCase) ?? "", grader.guidance));
|
|
285
|
+
prompt = renderConversationRubricPrompt({ scale: "pass_fail", examples: [] });
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
rubric = grader.rubric;
|
|
289
|
+
prompt = agent ? renderConversationRubricPrompt(grader) : renderRubricPrompt(grader);
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
type: "llm-rubric",
|
|
293
|
+
value: rubric,
|
|
294
|
+
metric: grader.id,
|
|
295
|
+
weight: 1,
|
|
296
|
+
rubricPrompt: prompt,
|
|
297
|
+
provider: {
|
|
298
|
+
id: mapping.providerSpec,
|
|
299
|
+
config: { max_tokens: JUDGE_MAX_OUTPUT_TOKENS, ...options.judgeProviderConfig },
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function assertionsFor(plan, options, testCase) {
|
|
304
|
+
const agent = isConversationTarget(plan.target.kind);
|
|
305
|
+
return plan.graders.map((grader, index) => {
|
|
306
|
+
if (isJudged(grader) && !(grader.type === "goal_reached" && caseGoal(testCase) === undefined)) {
|
|
307
|
+
return judgeAssertion(grader, options, agent, testCase);
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
type: "javascript",
|
|
311
|
+
value: `file://${ASSERTIONS_FILE}:${assertionFnName(index)}`,
|
|
312
|
+
metric: grader.id,
|
|
313
|
+
weight: 1,
|
|
314
|
+
};
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
export function buildConfig(plan, options) {
|
|
318
|
+
const agent = isConversationTarget(plan.target.kind);
|
|
319
|
+
const shared = agent ? undefined : assertionsFor(plan, options, plan.cases[0] ?? { input: {} });
|
|
320
|
+
return {
|
|
321
|
+
description: `Stageflow eval ${plan.evalId}`,
|
|
322
|
+
prompts: ["{{caseId}}"],
|
|
323
|
+
providers: [{ id: `file://${PROVIDER_FILE}` }],
|
|
324
|
+
extensions: [`file://${HOOKS_FILE}:afterEach`],
|
|
325
|
+
tests: plan.cases.map((c) => ({
|
|
326
|
+
description: c.id,
|
|
327
|
+
vars: {
|
|
328
|
+
caseId: c.id,
|
|
329
|
+
input: JSON.stringify(c.input),
|
|
330
|
+
expected: c.expected === undefined ? EMPTY_EXPECTED : JSON.stringify(c.expected),
|
|
331
|
+
},
|
|
332
|
+
assert: shared ?? assertionsFor(plan, options, c),
|
|
333
|
+
})),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
export function generateFiles(plan, options) {
|
|
337
|
+
return {
|
|
338
|
+
[CONFIG_FILE]: `${JSON.stringify(buildConfig(plan, options), null, 2)}\n`,
|
|
339
|
+
[PROVIDER_FILE]: buildProviderSource(plan.evalRunId, isConversationTarget(plan.target.kind)),
|
|
340
|
+
[ASSERTIONS_FILE]: buildAssertionsSource(plan, options.graderModuleUrl),
|
|
341
|
+
[HOOKS_FILE]: buildHooksSource(isConversationTarget(plan.target.kind)),
|
|
342
|
+
[DATASET_FILE]: `${JSON.stringify(plan.cases, null, 2)}\n`,
|
|
343
|
+
[GUARD_FILENAME]: GUARD_SOURCE,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const GUARD_FILENAME = "guard.cjs";
|
|
2
|
+
export declare const GUARD_SOURCE = "\"use strict\";\nconst http = require(\"node:http\");\nconst https = require(\"node:https\");\nconst { Writable } = require(\"node:stream\");\n\nconst BLOCKED = [\"promptfoo.app\", \"promptfoo.dev\"];\n\nfunction isBlocked(host) {\n if (typeof host !== \"string\") return false;\n const h = host.toLowerCase().replace(/\\.$/, \"\").replace(/^\\[|\\]$/g, \"\");\n return BLOCKED.some((d) => h === d || h.endsWith(\".\" + d));\n}\n\nfunction hostOf(input) {\n if (typeof input === \"string\") {\n try { return new URL(input).hostname; } catch { return undefined; }\n }\n if (input instanceof URL) return input.hostname;\n if (input && typeof input === \"object\") {\n if (typeof input.hostname === \"string\") return input.hostname;\n if (typeof input.host === \"string\") return input.host.replace(/:\\d+$/, \"\");\n if (typeof input.url === \"string\") return hostOf(input.url);\n }\n return undefined;\n}\n\nfunction blockedError(host) {\n const err = new Error(\"Stageflow blocked network access to \" + host);\n err.code = \"ECONNREFUSED\";\n return err;\n}\n\nfunction failedRequest(host) {\n const req = new Writable({ write(_c, _e, cb) { cb(); } });\n for (const name of [\"setHeader\", \"setTimeout\", \"setNoDelay\", \"setSocketKeepAlive\", \"flushHeaders\", \"abort\"]) {\n req[name] = () => req;\n }\n process.nextTick(() => req.emit(\"error\", blockedError(host)));\n return req;\n}\n\nfunction wrap(mod, name) {\n const original = mod[name];\n mod[name] = function (...args) {\n const host = hostOf(args[0]);\n if (isBlocked(host)) return failedRequest(host);\n return original.apply(this, args);\n };\n}\n\nfor (const mod of [http, https]) {\n wrap(mod, \"request\");\n wrap(mod, \"get\");\n}\n\nif (typeof globalThis.fetch === \"function\") {\n const originalFetch = globalThis.fetch;\n globalThis.fetch = function (input, init) {\n const host = hostOf(input);\n if (isBlocked(host)) return Promise.reject(blockedError(host));\n return originalFetch.call(this, input, init);\n };\n}\n\ntry { require(\"node:module\").syncBuiltinESMExports(); } catch {}\n";
|
|
3
|
+
export declare function writeGuardFile(dir: string): string;
|
|
4
|
+
export type GuardVia = "fetch" | "http" | "https";
|
|
5
|
+
export type GuardProbeResult = {
|
|
6
|
+
blocked: boolean;
|
|
7
|
+
status?: number;
|
|
8
|
+
code?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function probeGuard(via: GuardVia, url: string): Promise<GuardProbeResult>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
export const GUARD_FILENAME = "guard.cjs";
|
|
6
|
+
export const GUARD_SOURCE = `"use strict";
|
|
7
|
+
const http = require("node:http");
|
|
8
|
+
const https = require("node:https");
|
|
9
|
+
const { Writable } = require("node:stream");
|
|
10
|
+
|
|
11
|
+
const BLOCKED = ["promptfoo.app", "promptfoo.dev"];
|
|
12
|
+
|
|
13
|
+
function isBlocked(host) {
|
|
14
|
+
if (typeof host !== "string") return false;
|
|
15
|
+
const h = host.toLowerCase().replace(/\\.$/, "").replace(/^\\[|\\]$/g, "");
|
|
16
|
+
return BLOCKED.some((d) => h === d || h.endsWith("." + d));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function hostOf(input) {
|
|
20
|
+
if (typeof input === "string") {
|
|
21
|
+
try { return new URL(input).hostname; } catch { return undefined; }
|
|
22
|
+
}
|
|
23
|
+
if (input instanceof URL) return input.hostname;
|
|
24
|
+
if (input && typeof input === "object") {
|
|
25
|
+
if (typeof input.hostname === "string") return input.hostname;
|
|
26
|
+
if (typeof input.host === "string") return input.host.replace(/:\\d+$/, "");
|
|
27
|
+
if (typeof input.url === "string") return hostOf(input.url);
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function blockedError(host) {
|
|
33
|
+
const err = new Error("Stageflow blocked network access to " + host);
|
|
34
|
+
err.code = "ECONNREFUSED";
|
|
35
|
+
return err;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function failedRequest(host) {
|
|
39
|
+
const req = new Writable({ write(_c, _e, cb) { cb(); } });
|
|
40
|
+
for (const name of ["setHeader", "setTimeout", "setNoDelay", "setSocketKeepAlive", "flushHeaders", "abort"]) {
|
|
41
|
+
req[name] = () => req;
|
|
42
|
+
}
|
|
43
|
+
process.nextTick(() => req.emit("error", blockedError(host)));
|
|
44
|
+
return req;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function wrap(mod, name) {
|
|
48
|
+
const original = mod[name];
|
|
49
|
+
mod[name] = function (...args) {
|
|
50
|
+
const host = hostOf(args[0]);
|
|
51
|
+
if (isBlocked(host)) return failedRequest(host);
|
|
52
|
+
return original.apply(this, args);
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const mod of [http, https]) {
|
|
57
|
+
wrap(mod, "request");
|
|
58
|
+
wrap(mod, "get");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (typeof globalThis.fetch === "function") {
|
|
62
|
+
const originalFetch = globalThis.fetch;
|
|
63
|
+
globalThis.fetch = function (input, init) {
|
|
64
|
+
const host = hostOf(input);
|
|
65
|
+
if (isBlocked(host)) return Promise.reject(blockedError(host));
|
|
66
|
+
return originalFetch.call(this, input, init);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try { require("node:module").syncBuiltinESMExports(); } catch {}
|
|
71
|
+
`;
|
|
72
|
+
export function writeGuardFile(dir) {
|
|
73
|
+
const file = path.join(dir, GUARD_FILENAME);
|
|
74
|
+
writeFileSync(file, GUARD_SOURCE);
|
|
75
|
+
return file;
|
|
76
|
+
}
|
|
77
|
+
const PROBE_SCRIPT = `
|
|
78
|
+
const [via, url] = process.argv.slice(1);
|
|
79
|
+
const out = (o) => { process.stdout.write(JSON.stringify(o)); process.exit(0); };
|
|
80
|
+
const fail = (e) => out({ blocked: true, code: e && e.code });
|
|
81
|
+
if (via === "fetch") {
|
|
82
|
+
fetch(url).then((r) => out({ blocked: false, status: r.status }), fail);
|
|
83
|
+
} else {
|
|
84
|
+
const mod = require(via);
|
|
85
|
+
try {
|
|
86
|
+
const req = mod.request(url, (res) => { res.resume(); out({ blocked: false, status: res.statusCode }); });
|
|
87
|
+
req.on("error", fail);
|
|
88
|
+
req.end();
|
|
89
|
+
} catch (e) { fail(e); }
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
export async function probeGuard(via, url) {
|
|
93
|
+
const dir = mkdtempSync(path.join(tmpdir(), "sf-guard-"));
|
|
94
|
+
try {
|
|
95
|
+
const guard = writeGuardFile(dir);
|
|
96
|
+
return await new Promise((resolve, reject) => {
|
|
97
|
+
const child = spawn(process.execPath, ["--require", guard, "-e", PROBE_SCRIPT, via, url], { stdio: ["ignore", "pipe", "pipe"] });
|
|
98
|
+
let stdout = "";
|
|
99
|
+
let stderr = "";
|
|
100
|
+
child.stdout.on("data", (d) => (stdout += d));
|
|
101
|
+
child.stderr.on("data", (d) => (stderr += d));
|
|
102
|
+
child.on("error", reject);
|
|
103
|
+
child.on("close", () => {
|
|
104
|
+
try {
|
|
105
|
+
resolve(JSON.parse(stdout));
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
reject(new Error(`guard probe failed: ${stderr || stdout}`));
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
rmSync(dir, { recursive: true, force: true });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type RunNpm = (args: string[], opts: {
|
|
2
|
+
cwd: string;
|
|
3
|
+
log: (line: string) => void;
|
|
4
|
+
}) => Promise<{
|
|
5
|
+
code: number;
|
|
6
|
+
}>;
|
|
7
|
+
export type InstallResult = {
|
|
8
|
+
status: "installed" | "already_installed";
|
|
9
|
+
version: string;
|
|
10
|
+
dir: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const realRunNpm: RunNpm;
|
|
13
|
+
export declare function installPromptfoo(opts: {
|
|
14
|
+
home: string;
|
|
15
|
+
runNpm?: RunNpm;
|
|
16
|
+
log?: (line: string) => void;
|
|
17
|
+
}): Promise<InstallResult>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createInterface } from "node:readline";
|
|
5
|
+
import { EngineError } from "./errors.js";
|
|
6
|
+
import { engineDir, engineRoot, locatePromptfoo } from "./locate.js";
|
|
7
|
+
import { assertNode } from "./nodeVersion.js";
|
|
8
|
+
import { ENGINE_INSTALL_COMMAND, ENGINE_MARKER_FILE, PINNED_PROMPTFOO_VERSION, } from "./pinned.js";
|
|
9
|
+
export const realRunNpm = (args, { cwd, log }) => new Promise((resolve, reject) => {
|
|
10
|
+
const nodeDir = path.dirname(process.execPath);
|
|
11
|
+
const npm = path.join(nodeDir, process.platform === "win32" ? "npm.cmd" : "npm");
|
|
12
|
+
const child = spawn(npm, args, {
|
|
13
|
+
cwd,
|
|
14
|
+
env: { ...process.env, PATH: `${nodeDir}${path.delimiter}${process.env.PATH ?? ""}` },
|
|
15
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
16
|
+
shell: process.platform === "win32",
|
|
17
|
+
});
|
|
18
|
+
for (const stream of [child.stdout, child.stderr]) {
|
|
19
|
+
createInterface({ input: stream }).on("line", log);
|
|
20
|
+
}
|
|
21
|
+
child.on("error", reject);
|
|
22
|
+
child.on("close", (code) => resolve({ code: code ?? 1 }));
|
|
23
|
+
});
|
|
24
|
+
function readIntegrity(dir) {
|
|
25
|
+
try {
|
|
26
|
+
const lock = JSON.parse(readFileSync(path.join(dir, "package-lock.json"), "utf8"));
|
|
27
|
+
return lock.packages?.["node_modules/promptfoo"]?.integrity ?? null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function installPromptfoo(opts) {
|
|
34
|
+
const log = opts.log ?? (() => { });
|
|
35
|
+
const runNpm = opts.runNpm ?? realRunNpm;
|
|
36
|
+
assertNode();
|
|
37
|
+
const dir = engineDir(opts.home);
|
|
38
|
+
const existing = locatePromptfoo({ home: opts.home });
|
|
39
|
+
if (existing.installed) {
|
|
40
|
+
log(`promptfoo ${existing.version} is already installed`);
|
|
41
|
+
return { status: "already_installed", version: existing.version, dir };
|
|
42
|
+
}
|
|
43
|
+
const root = engineRoot(opts.home);
|
|
44
|
+
const rootExisted = existsSync(root);
|
|
45
|
+
rmSync(dir, { recursive: true, force: true });
|
|
46
|
+
mkdirSync(dir, { recursive: true });
|
|
47
|
+
try {
|
|
48
|
+
writeFileSync(path.join(dir, "package.json"), `${JSON.stringify({ name: "stageflow-eval-engine", private: true }, null, 2)}\n`);
|
|
49
|
+
const { code } = await runNpm(["install", "--no-audit", "--no-fund", `promptfoo@${PINNED_PROMPTFOO_VERSION}`], { cwd: dir, log });
|
|
50
|
+
if (code !== 0) {
|
|
51
|
+
throw new EngineError("EVAL_ENGINE_UNAVAILABLE", `npm install promptfoo@${PINNED_PROMPTFOO_VERSION} failed (exit ${code}). Retry with \`${ENGINE_INSTALL_COMMAND}\`.`);
|
|
52
|
+
}
|
|
53
|
+
const marker = {
|
|
54
|
+
version: PINNED_PROMPTFOO_VERSION,
|
|
55
|
+
node: process.versions.node,
|
|
56
|
+
installedAt: new Date().toISOString(),
|
|
57
|
+
integrity: readIntegrity(dir),
|
|
58
|
+
};
|
|
59
|
+
writeFileSync(path.join(dir, ENGINE_MARKER_FILE), `${JSON.stringify(marker, null, 2)}\n`);
|
|
60
|
+
const verified = locatePromptfoo({ home: opts.home });
|
|
61
|
+
if (!verified.installed) {
|
|
62
|
+
throw new EngineError("EVAL_ENGINE_UNAVAILABLE", verified.reason);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
rmSync(dir, { recursive: true, force: true });
|
|
67
|
+
if (!rootExisted)
|
|
68
|
+
rmSync(root, { recursive: true, force: true });
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
log(`installed promptfoo ${PINNED_PROMPTFOO_VERSION}`);
|
|
72
|
+
return { status: "installed", version: PINNED_PROMPTFOO_VERSION, dir };
|
|
73
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { mapJudge, unsupportedJudgeMessage } from "../../judgeProviders.js";
|
|
2
|
+
import { EngineError } from "./errors.js";
|
|
3
|
+
export function assertJudgesSupported(graders) {
|
|
4
|
+
for (const grader of graders) {
|
|
5
|
+
if ((grader.type === "rubric" || grader.type === "goal_reached") && mapJudge(grader.judge) === null) {
|
|
6
|
+
throw new EngineError("EVAL_INVALID", unsupportedJudgeMessage(grader.judge));
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { JudgeMapping } from "../../judgeProviders.js";
|
|
2
|
+
import type { JudgePrice } from "./normalize.js";
|
|
3
|
+
export type JudgeKeyResolver = (mapping: JudgeMapping, projectRoot: string) => Promise<string | undefined> | string | undefined;
|
|
4
|
+
export type JudgePriceLoader = (modelIds: readonly string[], projectRoot: string) => Promise<Map<string, JudgePrice>>;
|
|
5
|
+
export declare const defaultResolveJudgeKey: JudgeKeyResolver;
|
|
6
|
+
export declare const defaultLoadJudgePrices: JudgePriceLoader;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { ModelRuntime } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { resolveCredentialBinding } from "../../../runtime/credentialBinding.js";
|
|
5
|
+
import { readAuthKey } from "../../providerKeys.js";
|
|
6
|
+
export const defaultResolveJudgeKey = (mapping, projectRoot) => {
|
|
7
|
+
const fromStore = readAuthKey(resolveCredentialBinding(projectRoot).authPath, mapping.stageflowProvider);
|
|
8
|
+
if (fromStore !== undefined)
|
|
9
|
+
return fromStore;
|
|
10
|
+
const fromEnv = process.env[mapping.envVar];
|
|
11
|
+
return fromEnv !== undefined && fromEnv.length > 0 ? fromEnv : undefined;
|
|
12
|
+
};
|
|
13
|
+
export const defaultLoadJudgePrices = async (modelIds, projectRoot) => {
|
|
14
|
+
const prices = new Map();
|
|
15
|
+
if (modelIds.length === 0)
|
|
16
|
+
return prices;
|
|
17
|
+
try {
|
|
18
|
+
const authPath = resolveCredentialBinding(projectRoot).authPath;
|
|
19
|
+
if (!existsSync(authPath))
|
|
20
|
+
return prices;
|
|
21
|
+
const runtime = await ModelRuntime.create({
|
|
22
|
+
authPath,
|
|
23
|
+
modelsPath: path.join(path.dirname(authPath), "models.json"),
|
|
24
|
+
refreshOnCreate: false,
|
|
25
|
+
});
|
|
26
|
+
for (const id of modelIds) {
|
|
27
|
+
const slash = id.indexOf("/");
|
|
28
|
+
const model = runtime
|
|
29
|
+
.getModels(id.slice(0, slash))
|
|
30
|
+
.find((candidate) => candidate.id === id.slice(slash + 1));
|
|
31
|
+
const cost = model?.cost;
|
|
32
|
+
if (cost !== undefined && typeof cost.input === "number" && typeof cost.output === "number") {
|
|
33
|
+
prices.set(id, { inputPerMillion: cost.input, outputPerMillion: cost.output });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return prices;
|
|
39
|
+
}
|
|
40
|
+
return prices;
|
|
41
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type EngineMarker = {
|
|
2
|
+
version: string;
|
|
3
|
+
node: string;
|
|
4
|
+
installedAt: string;
|
|
5
|
+
integrity: string | null;
|
|
6
|
+
};
|
|
7
|
+
export type LocateResult = {
|
|
8
|
+
installed: true;
|
|
9
|
+
version: string;
|
|
10
|
+
binPath: string;
|
|
11
|
+
dir: string;
|
|
12
|
+
} | {
|
|
13
|
+
installed: false;
|
|
14
|
+
reason: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function engineRoot(home: string): string;
|
|
17
|
+
export declare function engineDir(home: string, version?: string): string;
|
|
18
|
+
export declare function engineBinPath(dir: string): string;
|
|
19
|
+
export declare function locatePromptfoo(opts: {
|
|
20
|
+
home: string;
|
|
21
|
+
}): LocateResult;
|