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,270 @@
|
|
|
1
|
+
import { scrubSecrets, SECRET_KEY_RE } from "./scrub.js";
|
|
2
|
+
const DEFAULTS = {
|
|
3
|
+
maxFactsPerMessage: 300,
|
|
4
|
+
maxFacts: 1500,
|
|
5
|
+
maxLinesPerMessage: 20_000,
|
|
6
|
+
maxLineChars: 2000,
|
|
7
|
+
noiseThreshold: 20,
|
|
8
|
+
};
|
|
9
|
+
const MAX_VALUE_CHARS = 200;
|
|
10
|
+
const MAX_CONTEXT_CHARS = 140;
|
|
11
|
+
const MAX_FACTS_PER_LINE = 12;
|
|
12
|
+
const BASE_SCORE = {
|
|
13
|
+
error: 100,
|
|
14
|
+
id: 60,
|
|
15
|
+
number: 40,
|
|
16
|
+
url: 35,
|
|
17
|
+
timestamp: 28,
|
|
18
|
+
path: 26,
|
|
19
|
+
other: 18,
|
|
20
|
+
};
|
|
21
|
+
const KIND_ORDER = ["error", "id", "number", "timestamp", "url", "path", "other"];
|
|
22
|
+
const KIND_TITLE = {
|
|
23
|
+
error: "Errors",
|
|
24
|
+
id: "Identifiers",
|
|
25
|
+
number: "Numbers",
|
|
26
|
+
timestamp: "Timestamps",
|
|
27
|
+
url: "URLs",
|
|
28
|
+
path: "Paths",
|
|
29
|
+
other: "Other",
|
|
30
|
+
};
|
|
31
|
+
const ERROR_RE = /\b(?:errors?|fail(?:ed|s|ure|ures|ing)?|exceptions?|denied|time[d ]?-?outs?|fatal|panic|traceback|refused|unauthori[sz]ed|forbidden|exit(?:ed)?(?: with)? (?:code|status):? ?[1-9]\d*|exit code:? ?[1-9]\d*|status:? ?[45]\d\d|HTTP\/\d(?:\.\d)? [45]\d\d|\b[45]\d\d (?:error|bad|not|internal|service|gateway|forbidden|unauthorized))\b/i;
|
|
32
|
+
const URL_RE = /https?:\/\/[^\s"'<>`)\]},]+/g;
|
|
33
|
+
const ISO_TS_RE = /\b\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?/g;
|
|
34
|
+
const TIME_RE = /(?<![\d:.])\d{1,2}:\d{2}(?::\d{2})?\s?(?:[AP]M|UTC|GMT)\b|(?<![\d:.\-T])\d{2}:\d{2}:\d{2}(?:\.\d+)?(?![\d:])/gi;
|
|
35
|
+
const UUID_RE = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
|
|
36
|
+
const TICKET_RE = /\b[A-Z][A-Z0-9]{1,9}-\d{1,7}\b/g;
|
|
37
|
+
const TICKET_STOP = new Set(["UTF", "SHA", "ISO", "MD", "AES", "RSA", "HTTP", "TLS", "SSL", "CVE", "RFC", "X", "IPV", "TCP", "UDP", "SSE", "GPT", "COVID"]);
|
|
38
|
+
const PR_RE = /\b(?:PR|pull request|pull|issue|MR)\s*#?\d{1,7}\b|(?<![\w&/#])#\d{2,7}\b/gi;
|
|
39
|
+
const HASH_RE = /\b(?:build|commit|sha\d*|rev|revision|hash|digest|checksum|image|release|tag)\b[^\n]{0,24}?\b([0-9a-f]{7,40})\b/gi;
|
|
40
|
+
const PATH_ABS_RE = /(?<![\w:/.])\/(?:[\w.@+~-]+\/)+[\w.@+~-]+/g;
|
|
41
|
+
const PATH_REL_RE = /(?<![\w:/.@])(?:\.{1,2}\/)?(?:[\w.@+~-]+\/)+[\w.@+~-]*\.[A-Za-z0-9]{1,8}\b/g;
|
|
42
|
+
const KV_EQ_RE = /\b([A-Za-z_][\w.-]{1,40})=("[^"\n]{1,80}"|'[^'\n]{1,80}'|[^\s,;&)}\]"']{1,80})/g;
|
|
43
|
+
const KV_JSON_RE = /"([A-Za-z_][\w.-]{1,40})"\s*:\s*("[^"\n]{1,80}"|-?\d[\d.eE+-]*|true|false|null)/g;
|
|
44
|
+
const KV_COLON_NUM_RE = /\b([A-Za-z_][\w.-]{1,40}):\s+(-?\d[\d,]*(?:\.\d+)?%?)(?![\d:])/g;
|
|
45
|
+
const UNIT_RE = /(?<![\w.:-])\d[\d,]*(?:\.\d+)?\s?(?:ms|sec|secs|seconds|minutes|mins|hours|days|KB|MB|GB|TB|bytes|requests|reqs|errors|failures|users|orders|rows|records|retries|events|messages|items|files|tests|connections|jobs|calls|shards)\b/gi;
|
|
46
|
+
const CURRENCY_RE = /(?<![\w])[$€£]\s?\d[\d,]*(?:\.\d+)?(?:[kKmMbB]\b)?|\b\d[\d,]*(?:\.\d+)?\s?(?:USD|EUR|GBP)\b/g;
|
|
47
|
+
const PERCENT_RE = /(?<![\w.])\d+(?:\.\d+)?%/g;
|
|
48
|
+
const ID_KEY_RE = /(?:^|[_.-])(?:id|uuid|key|ref|no|number|num|sha|hash|rev|build|ticket|incident|order|user|account|customer|request|trace)$/i;
|
|
49
|
+
function messageText(message) {
|
|
50
|
+
const role = message.role;
|
|
51
|
+
if (role !== "user" && role !== "toolResult")
|
|
52
|
+
return undefined;
|
|
53
|
+
const content = message.content;
|
|
54
|
+
if (typeof content === "string")
|
|
55
|
+
return content;
|
|
56
|
+
if (!Array.isArray(content))
|
|
57
|
+
return undefined;
|
|
58
|
+
const parts = [];
|
|
59
|
+
for (const block of content) {
|
|
60
|
+
if (block !== null && typeof block === "object" && block.type === "text") {
|
|
61
|
+
const text = block.text;
|
|
62
|
+
if (typeof text === "string")
|
|
63
|
+
parts.push(text);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return parts.join("\n");
|
|
67
|
+
}
|
|
68
|
+
function lineTemplate(line) {
|
|
69
|
+
return line
|
|
70
|
+
.replace(/\b[0-9a-f]{6,}\b/gi, "#")
|
|
71
|
+
.replace(/\d+/g, "#")
|
|
72
|
+
.replace(/"[^"]*"/g, '"#"')
|
|
73
|
+
.replace(/\s+/g, " ")
|
|
74
|
+
.trim()
|
|
75
|
+
.slice(0, 100);
|
|
76
|
+
}
|
|
77
|
+
function singleLine(text) {
|
|
78
|
+
return text.replace(/\s+/g, " ").trim();
|
|
79
|
+
}
|
|
80
|
+
function contextAround(line, index, length) {
|
|
81
|
+
const flat = line.length > 400 ? line.slice(Math.max(0, index - 200), index + length + 200) : line;
|
|
82
|
+
const offset = line.length > 400 ? Math.min(index, 200) : index;
|
|
83
|
+
const start = Math.max(0, offset - 50);
|
|
84
|
+
const end = Math.min(flat.length, offset + length + 60);
|
|
85
|
+
let out = singleLine(flat.slice(start, end));
|
|
86
|
+
if (out.length > MAX_CONTEXT_CHARS)
|
|
87
|
+
out = out.slice(0, MAX_CONTEXT_CHARS);
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
function numericLike(value) {
|
|
91
|
+
return /^-?\d[\d,]*(?:\.\d+)?(?:[eE][+-]?\d+)?%?$/.test(value);
|
|
92
|
+
}
|
|
93
|
+
function collectCandidates(line, isErrorLine, keyFreq, noiseThreshold) {
|
|
94
|
+
const out = [];
|
|
95
|
+
const claimed = [];
|
|
96
|
+
const free = (start, end) => !claimed.some(([s, e]) => start < e && end > s);
|
|
97
|
+
const claim = (start, end) => claimed.push([start, end]);
|
|
98
|
+
const run = (re, on, takeSpan = true) => {
|
|
99
|
+
re.lastIndex = 0;
|
|
100
|
+
let m;
|
|
101
|
+
let guard = 0;
|
|
102
|
+
while ((m = re.exec(line)) !== null && guard++ < 50) {
|
|
103
|
+
if (m[0].length === 0) {
|
|
104
|
+
re.lastIndex++;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const start = m.index;
|
|
108
|
+
const end = start + m[0].length;
|
|
109
|
+
if (!free(start, end))
|
|
110
|
+
continue;
|
|
111
|
+
const cand = on(m);
|
|
112
|
+
if (cand) {
|
|
113
|
+
out.push(cand);
|
|
114
|
+
if (takeSpan)
|
|
115
|
+
claim(start, end);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
run(URL_RE, (m) => ({ kind: "url", value: m[0].replace(/[.;:!?]+$/, ""), index: m.index }));
|
|
120
|
+
run(ISO_TS_RE, (m) => ({ kind: "timestamp", value: m[0], index: m.index }));
|
|
121
|
+
run(UUID_RE, (m) => ({ kind: "id", value: m[0], index: m.index }));
|
|
122
|
+
run(PR_RE, (m) => ({ kind: "id", value: m[0].replace(/\s+/g, " "), index: m.index }));
|
|
123
|
+
run(TICKET_RE, (m) => {
|
|
124
|
+
const prefix = m[0].slice(0, m[0].indexOf("-"));
|
|
125
|
+
if (TICKET_STOP.has(prefix))
|
|
126
|
+
return undefined;
|
|
127
|
+
return { kind: "id", value: m[0], index: m.index };
|
|
128
|
+
});
|
|
129
|
+
run(HASH_RE, (m) => {
|
|
130
|
+
const hex = m[1];
|
|
131
|
+
if (!/\d/.test(hex) || !/[a-f]/i.test(hex))
|
|
132
|
+
return undefined;
|
|
133
|
+
return { kind: "id", value: hex, index: m.index + m[0].length - hex.length };
|
|
134
|
+
}, false);
|
|
135
|
+
run(TIME_RE, (m) => ({ kind: "timestamp", value: m[0].trim(), index: m.index }));
|
|
136
|
+
run(PATH_ABS_RE, (m) => (m[0].length >= 5 ? { kind: "path", value: m[0], index: m.index } : undefined));
|
|
137
|
+
run(PATH_REL_RE, (m) => ({ kind: "path", value: m[0], index: m.index }));
|
|
138
|
+
const kv = (key, raw, index) => {
|
|
139
|
+
if (SECRET_KEY_RE.test(key))
|
|
140
|
+
return undefined;
|
|
141
|
+
const value = raw.replace(/^["']|["']$/g, "");
|
|
142
|
+
if (value.length === 0 || value === "null" || value === "true" || value === "false")
|
|
143
|
+
return undefined;
|
|
144
|
+
const common = (keyFreq.get(key) ?? 0) > noiseThreshold;
|
|
145
|
+
const numeric = numericLike(value);
|
|
146
|
+
const kind = ID_KEY_RE.test(key) && !numeric ? "id" : ID_KEY_RE.test(key) ? "id" : numeric ? "number" : "other";
|
|
147
|
+
return { kind, value: `${key}=${value}`, index, weight: common ? -25 : 0 };
|
|
148
|
+
};
|
|
149
|
+
run(KV_EQ_RE, (m) => kv(m[1], m[2], m.index));
|
|
150
|
+
run(KV_JSON_RE, (m) => kv(m[1], m[2], m.index));
|
|
151
|
+
run(KV_COLON_NUM_RE, (m) => kv(m[1], m[2], m.index));
|
|
152
|
+
run(CURRENCY_RE, (m) => ({ kind: "number", value: m[0].trim(), index: m.index }));
|
|
153
|
+
run(PERCENT_RE, (m) => ({ kind: "number", value: m[0], index: m.index }));
|
|
154
|
+
run(UNIT_RE, (m) => ({ kind: "number", value: m[0].trim(), index: m.index }));
|
|
155
|
+
if (isErrorLine) {
|
|
156
|
+
const value = singleLine(line);
|
|
157
|
+
out.push({ kind: "error", value: value.length > MAX_VALUE_CHARS ? value.slice(0, MAX_VALUE_CHARS) : value, index: 0 });
|
|
158
|
+
}
|
|
159
|
+
return out.slice(0, MAX_FACTS_PER_LINE + (isErrorLine ? 1 : 0));
|
|
160
|
+
}
|
|
161
|
+
export function extractPinnedFacts(messages, options = {}) {
|
|
162
|
+
const cfg = { ...DEFAULTS, ...options };
|
|
163
|
+
const facts = new Map();
|
|
164
|
+
let order = 0;
|
|
165
|
+
messages.forEach((message, messageIndex) => {
|
|
166
|
+
const text = messageText(message);
|
|
167
|
+
if (!text)
|
|
168
|
+
return;
|
|
169
|
+
const isUser = message.role === "user";
|
|
170
|
+
const toolName = !isUser && typeof message.toolName === "string" ? message.toolName : undefined;
|
|
171
|
+
const lines = text.split("\n", cfg.maxLinesPerMessage + 1).slice(0, cfg.maxLinesPerMessage);
|
|
172
|
+
const templates = new Map();
|
|
173
|
+
const keyFreq = new Map();
|
|
174
|
+
const trimmed = [];
|
|
175
|
+
for (const raw of lines) {
|
|
176
|
+
const line = raw.length > cfg.maxLineChars ? raw.slice(0, cfg.maxLineChars) : raw;
|
|
177
|
+
trimmed.push(line);
|
|
178
|
+
if (line.trim().length === 0)
|
|
179
|
+
continue;
|
|
180
|
+
const tpl = lineTemplate(line);
|
|
181
|
+
templates.set(tpl, (templates.get(tpl) ?? 0) + 1);
|
|
182
|
+
if (!isUser) {
|
|
183
|
+
KV_EQ_RE.lastIndex = 0;
|
|
184
|
+
let m;
|
|
185
|
+
let g = 0;
|
|
186
|
+
while ((m = KV_EQ_RE.exec(line)) !== null && g++ < 8)
|
|
187
|
+
keyFreq.set(m[1], (keyFreq.get(m[1]) ?? 0) + 1);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
let messageFacts = 0;
|
|
191
|
+
for (const line of trimmed) {
|
|
192
|
+
if (messageFacts >= cfg.maxFactsPerMessage)
|
|
193
|
+
break;
|
|
194
|
+
if (line.trim().length === 0)
|
|
195
|
+
continue;
|
|
196
|
+
const errorLine = ERROR_RE.test(line);
|
|
197
|
+
const repeats = templates.get(lineTemplate(line)) ?? 1;
|
|
198
|
+
if (!isUser && !errorLine && repeats > cfg.noiseThreshold)
|
|
199
|
+
continue;
|
|
200
|
+
const rarity = errorLine ? 0 : repeats > 1 ? -Math.min(15, Math.log2(repeats) * 3) : 0;
|
|
201
|
+
for (const cand of collectCandidates(line, errorLine, keyFreq, cfg.noiseThreshold)) {
|
|
202
|
+
const value = cand.value.length > MAX_VALUE_CHARS ? cand.value.slice(0, MAX_VALUE_CHARS) : cand.value;
|
|
203
|
+
if (scrubSecrets(value) !== value)
|
|
204
|
+
continue;
|
|
205
|
+
const key = `${cand.kind}\u0000${value}`;
|
|
206
|
+
const existing = facts.get(key);
|
|
207
|
+
if (existing) {
|
|
208
|
+
existing.count++;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (facts.size >= cfg.maxFacts * 2)
|
|
212
|
+
continue;
|
|
213
|
+
const context = scrubSecrets(contextAround(line, cand.index, value.length));
|
|
214
|
+
const score = BASE_SCORE[cand.kind] + (isUser ? 15 : 0) + rarity + (cand.weight ?? 0);
|
|
215
|
+
facts.set(key, {
|
|
216
|
+
kind: cand.kind,
|
|
217
|
+
value,
|
|
218
|
+
context,
|
|
219
|
+
source: toolName ? { messageIndex, toolName } : { messageIndex },
|
|
220
|
+
count: 1,
|
|
221
|
+
score,
|
|
222
|
+
order: order++,
|
|
223
|
+
});
|
|
224
|
+
messageFacts++;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
const ranked = [...facts.values()].map((fact) => ({
|
|
229
|
+
...fact,
|
|
230
|
+
score: fact.score - Math.min(12, Math.log2(fact.count) * 3),
|
|
231
|
+
}));
|
|
232
|
+
ranked.sort((a, b) => b.score - a.score || a.order - b.order);
|
|
233
|
+
return ranked.slice(0, cfg.maxFacts).map(({ order: _order, ...fact }) => fact);
|
|
234
|
+
}
|
|
235
|
+
export function renderPinned(facts, maxChars) {
|
|
236
|
+
const title = "## Pinned facts";
|
|
237
|
+
const omittedLine = (n) => `- (${n} more omitted)`;
|
|
238
|
+
const base = `${title}\n${omittedLine(facts.length)}`;
|
|
239
|
+
if (maxChars < base.length)
|
|
240
|
+
return base.slice(0, Math.max(0, maxChars)).replace(/\n[^\n]*$/, "").slice(0, Math.max(0, maxChars));
|
|
241
|
+
const chosen = new Map();
|
|
242
|
+
let used = title.length + 1;
|
|
243
|
+
let included = 0;
|
|
244
|
+
const reserve = omittedLine(facts.length).length + 1;
|
|
245
|
+
for (const fact of facts) {
|
|
246
|
+
const value = singleLine(scrubSecrets(fact.value));
|
|
247
|
+
const context = singleLine(scrubSecrets(fact.context));
|
|
248
|
+
if (value.length === 0)
|
|
249
|
+
continue;
|
|
250
|
+
const line = context.length > 0 && context !== value ? `- ${value} — ${context}` : `- ${value}`;
|
|
251
|
+
const headerCost = chosen.has(fact.kind) ? 0 : `### ${KIND_TITLE[fact.kind]}`.length + 1;
|
|
252
|
+
const cost = headerCost + line.length + 1;
|
|
253
|
+
if (used + cost + reserve > maxChars)
|
|
254
|
+
continue;
|
|
255
|
+
const bucket = chosen.get(fact.kind) ?? [];
|
|
256
|
+
bucket.push(line);
|
|
257
|
+
chosen.set(fact.kind, bucket);
|
|
258
|
+
used += cost;
|
|
259
|
+
included++;
|
|
260
|
+
}
|
|
261
|
+
const out = [title];
|
|
262
|
+
for (const kind of KIND_ORDER) {
|
|
263
|
+
const bucket = chosen.get(kind);
|
|
264
|
+
if (!bucket)
|
|
265
|
+
continue;
|
|
266
|
+
out.push(`### ${KIND_TITLE[kind]}`, ...bucket);
|
|
267
|
+
}
|
|
268
|
+
out.push(omittedLine(facts.length - included));
|
|
269
|
+
return out.join("\n");
|
|
270
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything the compaction code removes before text reaches a summarizer, a pinned fact, a directive or the
|
|
3
|
+
* working state. Stricter than redactString: it also catches key=value forms, cookies and session ids.
|
|
4
|
+
* It can over-redact harmless text such as `token_count=5`; callers that store model-written text say so.
|
|
5
|
+
*/
|
|
6
|
+
export declare const SECRET_KEY_RE: RegExp;
|
|
7
|
+
export declare function scrubSecrets(text: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { redactString } from "../logging/redact.js";
|
|
2
|
+
/**
|
|
3
|
+
* Everything the compaction code removes before text reaches a summarizer, a pinned fact, a directive or the
|
|
4
|
+
* working state. Stricter than redactString: it also catches key=value forms, cookies and session ids.
|
|
5
|
+
* It can over-redact harmless text such as `token_count=5`; callers that store model-written text say so.
|
|
6
|
+
*/
|
|
7
|
+
export const SECRET_KEY_RE = /secret|token|passw|pwd|api[_-]?key|auth|credential|bearer|cookie|private|session|\bsid\b|csrf|xsrf|jwt|signature/i;
|
|
8
|
+
const EXTRA_SECRET_RES = [
|
|
9
|
+
/\b(?:api[_-]?key|secret|token|password|passwd|authorization|bearer)\b["']?\s*[:=]\s*["']?[^\s"',;]+/gi,
|
|
10
|
+
/\bBearer\s+[A-Za-z0-9\-._~+/]{8,}=*/gi,
|
|
11
|
+
/\b(?:Set-)?Cookie:[^\n]*/gi,
|
|
12
|
+
/\b(?:session|sess|sid|csrf|xsrf|jsessionid|phpsessid)[\w-]*=[^\s;,"']+/gi,
|
|
13
|
+
/\beyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]{8,}/g,
|
|
14
|
+
/\bAKIA[0-9A-Z]{16}\b/g,
|
|
15
|
+
/\bxox[abprs]-[\w-]{8,}/g,
|
|
16
|
+
/\b(?:sk|pk|rk)[-_](?:live|test|proj|ant)?[-_]?[A-Za-z0-9_-]{16,}/g,
|
|
17
|
+
/[?&](?:token|key|api_?key|access_token|auth|signature|sig)=[^\s&"']+/gi,
|
|
18
|
+
];
|
|
19
|
+
export function scrubSecrets(text) {
|
|
20
|
+
let out = redactString(text);
|
|
21
|
+
for (const re of EXTRA_SECRET_RES) {
|
|
22
|
+
re.lastIndex = 0;
|
|
23
|
+
out = out.replace(re, "[redacted]");
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { InlineExtension } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export type SessionContextWiring = {
|
|
3
|
+
/** Inline extensions to register, in order. */
|
|
4
|
+
extensions: InlineExtension[];
|
|
5
|
+
/** Tool names to add to the session's allowlist. */
|
|
6
|
+
toolNames: string[];
|
|
7
|
+
/** Text for the system prompt; empty when the session has no working state. */
|
|
8
|
+
guidance: string;
|
|
9
|
+
/** Tools whose output the tool-output budget must never spill or cap. */
|
|
10
|
+
budgetExemptNames: string[];
|
|
11
|
+
/** Tools the agent tool gate lets through without a grant or an approval. */
|
|
12
|
+
isInternalTool(toolName: string): boolean;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* What a Pi session needs for context management, owned in one place: OpenRouter routing, compaction and
|
|
16
|
+
* (unless `workingState` is false) the working_state tool with its allowlist entry, prompt guidance and
|
|
17
|
+
* gate and budget exemptions. Stage sessions, project agents and the operator agent all call this, so the
|
|
18
|
+
* pieces cannot drift apart.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createSessionContextWiring(options: {
|
|
21
|
+
workingState: boolean;
|
|
22
|
+
}): SessionContextWiring;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createOpenRouterRoutingExtension } from "../agent/openRouterRouting.js";
|
|
2
|
+
import { createWorkingStateExtension } from "../tools/workingState.js";
|
|
3
|
+
import { createCompactionExtension } from "./extension.js";
|
|
4
|
+
import { WORKING_STATE_TOOL_NAME } from "./types.js";
|
|
5
|
+
import { WORKING_STATE_GUIDANCE } from "./workingState.js";
|
|
6
|
+
const warn = (message) => console.error(message);
|
|
7
|
+
/**
|
|
8
|
+
* What a Pi session needs for context management, owned in one place: OpenRouter routing, compaction and
|
|
9
|
+
* (unless `workingState` is false) the working_state tool with its allowlist entry, prompt guidance and
|
|
10
|
+
* gate and budget exemptions. Stage sessions, project agents and the operator agent all call this, so the
|
|
11
|
+
* pieces cannot drift apart.
|
|
12
|
+
*/
|
|
13
|
+
export function createSessionContextWiring(options) {
|
|
14
|
+
const withState = options.workingState;
|
|
15
|
+
return {
|
|
16
|
+
extensions: [
|
|
17
|
+
{ name: "stageflow-openrouter-routing", factory: createOpenRouterRoutingExtension() },
|
|
18
|
+
{ name: "stageflow-compaction", factory: createCompactionExtension({ onWarn: warn }) },
|
|
19
|
+
...(withState ? [{ name: "stageflow-working-state", factory: createWorkingStateExtension() }] : []),
|
|
20
|
+
],
|
|
21
|
+
toolNames: withState ? [WORKING_STATE_TOOL_NAME] : [],
|
|
22
|
+
guidance: withState ? WORKING_STATE_GUIDANCE : "",
|
|
23
|
+
budgetExemptNames: withState ? [WORKING_STATE_TOOL_NAME] : [],
|
|
24
|
+
isInternalTool: (toolName) => withState && toolName === WORKING_STATE_TOOL_NAME,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type ClearingPolicy } from "./mask.js";
|
|
2
|
+
import { type Directive } from "./directives.js";
|
|
3
|
+
import { type LooseMessage } from "./pin.js";
|
|
4
|
+
import { type ClearedResult, type PinnedFact, type WorkingStateEntry } from "./types.js";
|
|
5
|
+
export declare const COMPACTION_FOCUS: string;
|
|
6
|
+
export declare const SECTIONS_MARKER = "<!-- stageflow:compaction-sections -->";
|
|
7
|
+
export declare const PINNED_RENDER_CHARS = 6000;
|
|
8
|
+
export declare const CLEARED_RENDER_CHARS = 3000;
|
|
9
|
+
export declare const STATE_RENDER_CHARS = 6000;
|
|
10
|
+
export declare const DIRECTIVES_RENDER_CHARS = 5000;
|
|
11
|
+
export declare const PINNED_CARRY_MAX = 400;
|
|
12
|
+
export declare const CLEARED_CARRY_MAX = 200;
|
|
13
|
+
export type StageflowCompactionDetails = {
|
|
14
|
+
readFiles?: string[];
|
|
15
|
+
modifiedFiles?: string[];
|
|
16
|
+
stageflowPinned?: PinnedFact[];
|
|
17
|
+
stageflowCleared?: ClearedResult[];
|
|
18
|
+
stageflowDirectives?: Directive[];
|
|
19
|
+
stageflowPromptVersion?: number;
|
|
20
|
+
};
|
|
21
|
+
/** The sections are always appended last, so the last marker at the start of a line is the real one. */
|
|
22
|
+
export declare function splitSummary(summary: string): {
|
|
23
|
+
core: string;
|
|
24
|
+
sections: string;
|
|
25
|
+
};
|
|
26
|
+
/** Details come from the session file, so anything not shaped like ours is dropped rather than trusted. */
|
|
27
|
+
export declare function readStageflowDetails(value: unknown): StageflowCompactionDetails | undefined;
|
|
28
|
+
/** Newest facts first win a tie; capped so repeated compactions cannot grow without bound. */
|
|
29
|
+
export declare function mergePinned(previous: readonly PinnedFact[], fresh: readonly PinnedFact[], max?: number): PinnedFact[];
|
|
30
|
+
export declare function mergeCleared(previous: readonly ClearedResult[], fresh: readonly ClearedResult[], max?: number): ClearedResult[];
|
|
31
|
+
export declare function renderSections(input: {
|
|
32
|
+
pinned: readonly PinnedFact[];
|
|
33
|
+
cleared: readonly ClearedResult[];
|
|
34
|
+
state: readonly WorkingStateEntry[];
|
|
35
|
+
directives?: readonly Directive[];
|
|
36
|
+
}): string;
|
|
37
|
+
/** What the summarizer reads: message text, thinking and tool-call arguments with secrets removed. */
|
|
38
|
+
export declare function redactMessages<T extends LooseMessage>(messages: readonly T[]): T[];
|
|
39
|
+
export type SummaryInputs = {
|
|
40
|
+
messages: readonly LooseMessage[];
|
|
41
|
+
previousDetails?: StageflowCompactionDetails;
|
|
42
|
+
clearInSummary?: ClearingPolicy;
|
|
43
|
+
};
|
|
44
|
+
export type PreparedSummaryInputs = {
|
|
45
|
+
messagesForSummarizer: LooseMessage[];
|
|
46
|
+
pinned: PinnedFact[];
|
|
47
|
+
cleared: ClearedResult[];
|
|
48
|
+
directives: Directive[];
|
|
49
|
+
};
|
|
50
|
+
/** Everything deterministic that happens before the model-written summary is requested. */
|
|
51
|
+
export declare function prepareSummaryInputs(input: SummaryInputs): PreparedSummaryInputs;
|
|
52
|
+
export declare function stageflowDetails(piDetails: {
|
|
53
|
+
readFiles?: string[];
|
|
54
|
+
modifiedFiles?: string[];
|
|
55
|
+
} | undefined, previous: StageflowCompactionDetails | undefined, pinned: readonly PinnedFact[], cleared: readonly ClearedResult[], directives?: readonly Directive[]): StageflowCompactionDetails;
|
|
56
|
+
export type SummarizeCall = {
|
|
57
|
+
messages: LooseMessage[];
|
|
58
|
+
previousSummary: string | undefined;
|
|
59
|
+
};
|
|
60
|
+
export type ComposedSummary<R> = {
|
|
61
|
+
summary: string;
|
|
62
|
+
result: R;
|
|
63
|
+
prepared: PreparedSummaryInputs;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* The whole summary pipeline in one place: pin and redact the input, ask the model for the written part,
|
|
67
|
+
* scrub it, then append the deterministic sections. The Pi hook and the evaluation harness both call this,
|
|
68
|
+
* so what the harness measures is what ships.
|
|
69
|
+
*/
|
|
70
|
+
export declare function composeCompactionSummary<R extends {
|
|
71
|
+
summary: string;
|
|
72
|
+
}>(input: {
|
|
73
|
+
messages: readonly LooseMessage[];
|
|
74
|
+
previousSummary?: string;
|
|
75
|
+
previousDetails?: StageflowCompactionDetails;
|
|
76
|
+
state: readonly WorkingStateEntry[];
|
|
77
|
+
clearInSummary?: ClearingPolicy;
|
|
78
|
+
summarize: (call: SummarizeCall) => Promise<R>;
|
|
79
|
+
}): Promise<ComposedSummary<R>>;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { applyClearing, planClearing, renderClearedIndex } from "./mask.js";
|
|
2
|
+
import { extractDirectives, mergeDirectives, renderDirectives } from "./directives.js";
|
|
3
|
+
import { extractPinnedFacts, renderPinned } from "./pin.js";
|
|
4
|
+
import { scrubSecrets } from "./scrub.js";
|
|
5
|
+
import { COMPACTION_PROMPT_VERSION } from "./types.js";
|
|
6
|
+
import { WorkingStateStore } from "./workingState.js";
|
|
7
|
+
export const COMPACTION_FOCUS = "This is an autonomous agent run, not a chat. Make the summary a working record the agent can continue from without the earlier messages. " +
|
|
8
|
+
"Copy exact identifiers, numbers, counts, timestamps, versions, paths, URLs and quoted error text verbatim; never round, reword or estimate them. " +
|
|
9
|
+
"Keep every failure, rejection and dead end explicit, with why it failed, so it is not retried. " +
|
|
10
|
+
"State what is in flight, which sources or items are already handled and which remain, and the exact next step. " +
|
|
11
|
+
"Keep decisions made by the operator or user and the deliverable the run must produce, including its required format. " +
|
|
12
|
+
"Leave out routine output that carries no decision or value.";
|
|
13
|
+
export const SECTIONS_MARKER = "<!-- stageflow:compaction-sections -->";
|
|
14
|
+
export const PINNED_RENDER_CHARS = 6000;
|
|
15
|
+
export const CLEARED_RENDER_CHARS = 3000;
|
|
16
|
+
export const STATE_RENDER_CHARS = 6000;
|
|
17
|
+
export const DIRECTIVES_RENDER_CHARS = 5000;
|
|
18
|
+
export const PINNED_CARRY_MAX = 400;
|
|
19
|
+
export const CLEARED_CARRY_MAX = 200;
|
|
20
|
+
/** The sections are always appended last, so the last marker at the start of a line is the real one. */
|
|
21
|
+
export function splitSummary(summary) {
|
|
22
|
+
const afterNewline = summary.lastIndexOf(`\n${SECTIONS_MARKER}`);
|
|
23
|
+
const at = afterNewline >= 0 ? afterNewline + 1 : summary.startsWith(SECTIONS_MARKER) ? 0 : -1;
|
|
24
|
+
if (at < 0)
|
|
25
|
+
return { core: summary, sections: "" };
|
|
26
|
+
return { core: summary.slice(0, at).trimEnd(), sections: summary.slice(at) };
|
|
27
|
+
}
|
|
28
|
+
const FACT_KINDS = new Set(["id", "number", "timestamp", "url", "path", "error", "other"]);
|
|
29
|
+
const DIRECTIVE_SOURCES = new Set(["operator", "user", "rejection"]);
|
|
30
|
+
function isRecord(value) {
|
|
31
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
32
|
+
}
|
|
33
|
+
function strings(value) {
|
|
34
|
+
return Array.isArray(value) ? value.filter((x) => typeof x === "string") : undefined;
|
|
35
|
+
}
|
|
36
|
+
function validPinned(x) {
|
|
37
|
+
return isRecord(x) && typeof x.kind === "string" && FACT_KINDS.has(x.kind) && typeof x.value === "string" && typeof x.context === "string" && isRecord(x.source) && typeof x.source.messageIndex === "number";
|
|
38
|
+
}
|
|
39
|
+
function validCleared(x) {
|
|
40
|
+
return isRecord(x) && typeof x.toolName === "string" && typeof x.toolCallId === "string" && typeof x.recoverHint === "string" && typeof x.bytes === "number" && typeof x.descriptor === "string";
|
|
41
|
+
}
|
|
42
|
+
function validDirective(x) {
|
|
43
|
+
return isRecord(x) && typeof x.source === "string" && DIRECTIVE_SOURCES.has(x.source) && typeof x.text === "string";
|
|
44
|
+
}
|
|
45
|
+
/** Details come from the session file, so anything not shaped like ours is dropped rather than trusted. */
|
|
46
|
+
export function readStageflowDetails(value) {
|
|
47
|
+
if (!isRecord(value))
|
|
48
|
+
return undefined;
|
|
49
|
+
const readFiles = strings(value.readFiles);
|
|
50
|
+
const modifiedFiles = strings(value.modifiedFiles);
|
|
51
|
+
return {
|
|
52
|
+
...(readFiles ? { readFiles } : {}),
|
|
53
|
+
...(modifiedFiles ? { modifiedFiles } : {}),
|
|
54
|
+
...(Array.isArray(value.stageflowPinned) ? { stageflowPinned: value.stageflowPinned.filter(validPinned) } : {}),
|
|
55
|
+
...(Array.isArray(value.stageflowCleared) ? { stageflowCleared: value.stageflowCleared.filter(validCleared) } : {}),
|
|
56
|
+
...(Array.isArray(value.stageflowDirectives) ? { stageflowDirectives: value.stageflowDirectives.filter(validDirective) } : {}),
|
|
57
|
+
...(typeof value.stageflowPromptVersion === "number" ? { stageflowPromptVersion: value.stageflowPromptVersion } : {}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function factKey(f) {
|
|
61
|
+
return `${f.kind}\u0000${f.value}`;
|
|
62
|
+
}
|
|
63
|
+
/** Newest facts first win a tie; capped so repeated compactions cannot grow without bound. */
|
|
64
|
+
export function mergePinned(previous, fresh, max = PINNED_CARRY_MAX) {
|
|
65
|
+
const seen = new Set();
|
|
66
|
+
const out = [];
|
|
67
|
+
for (const f of [...fresh, ...previous]) {
|
|
68
|
+
const key = factKey(f);
|
|
69
|
+
if (seen.has(key))
|
|
70
|
+
continue;
|
|
71
|
+
seen.add(key);
|
|
72
|
+
out.push(f);
|
|
73
|
+
if (out.length >= max)
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
export function mergeCleared(previous, fresh, max = CLEARED_CARRY_MAX) {
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
const out = [];
|
|
81
|
+
for (const c of [...fresh, ...previous]) {
|
|
82
|
+
if (seen.has(c.toolCallId))
|
|
83
|
+
continue;
|
|
84
|
+
seen.add(c.toolCallId);
|
|
85
|
+
out.push(c);
|
|
86
|
+
if (out.length >= max)
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
export function renderSections(input) {
|
|
92
|
+
const parts = [];
|
|
93
|
+
if (input.state.length > 0) {
|
|
94
|
+
const store = new WorkingStateStore();
|
|
95
|
+
for (const e of input.state)
|
|
96
|
+
store.set({ key: e.key, kind: e.kind, value: e.value, updatedAt: e.updatedAt });
|
|
97
|
+
const rendered = store.render(STATE_RENDER_CHARS);
|
|
98
|
+
if (rendered)
|
|
99
|
+
parts.push(rendered);
|
|
100
|
+
}
|
|
101
|
+
const directives = renderDirectives(input.directives ?? [], DIRECTIVES_RENDER_CHARS);
|
|
102
|
+
if (directives)
|
|
103
|
+
parts.push(directives);
|
|
104
|
+
if (input.pinned.length > 0)
|
|
105
|
+
parts.push(renderPinned(input.pinned, PINNED_RENDER_CHARS));
|
|
106
|
+
if (input.cleared.length > 0)
|
|
107
|
+
parts.push(renderClearedIndex(input.cleared, CLEARED_RENDER_CHARS));
|
|
108
|
+
if (parts.length === 0)
|
|
109
|
+
return "";
|
|
110
|
+
return `${SECTIONS_MARKER}\n${parts.join("\n\n")}`;
|
|
111
|
+
}
|
|
112
|
+
function scrubValue(value) {
|
|
113
|
+
if (typeof value === "string")
|
|
114
|
+
return scrubSecrets(value);
|
|
115
|
+
if (Array.isArray(value))
|
|
116
|
+
return value.map(scrubValue);
|
|
117
|
+
if (value !== null && typeof value === "object") {
|
|
118
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, scrubValue(v)]));
|
|
119
|
+
}
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
/** What the summarizer reads: message text, thinking and tool-call arguments with secrets removed. */
|
|
123
|
+
export function redactMessages(messages) {
|
|
124
|
+
return messages.map((m) => (Array.isArray(m.content) || typeof m.content === "string" ? { ...m, content: scrubValue(m.content) } : m));
|
|
125
|
+
}
|
|
126
|
+
/** Everything deterministic that happens before the model-written summary is requested. */
|
|
127
|
+
export function prepareSummaryInputs(input) {
|
|
128
|
+
const extracted = extractPinnedFacts(input.messages);
|
|
129
|
+
const pinned = mergePinned(input.previousDetails?.stageflowPinned ?? [], extracted);
|
|
130
|
+
const directives = mergeDirectives(input.previousDetails?.stageflowDirectives ?? [], extractDirectives(input.messages));
|
|
131
|
+
if (!input.clearInSummary) {
|
|
132
|
+
return { messagesForSummarizer: redactMessages(input.messages), pinned, directives, cleared: [...(input.previousDetails?.stageflowCleared ?? [])] };
|
|
133
|
+
}
|
|
134
|
+
const plan = planClearing(input.messages, input.clearInSummary);
|
|
135
|
+
return {
|
|
136
|
+
messagesForSummarizer: redactMessages(applyClearing(input.messages, plan)),
|
|
137
|
+
pinned,
|
|
138
|
+
directives,
|
|
139
|
+
cleared: mergeCleared(input.previousDetails?.stageflowCleared ?? [], plan.cleared),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export function stageflowDetails(piDetails, previous, pinned, cleared, directives = []) {
|
|
143
|
+
const union = (a, b) => [...new Set([...(b ?? []), ...(a ?? [])])];
|
|
144
|
+
return {
|
|
145
|
+
readFiles: union(piDetails?.readFiles, previous?.readFiles),
|
|
146
|
+
modifiedFiles: union(piDetails?.modifiedFiles, previous?.modifiedFiles),
|
|
147
|
+
stageflowPinned: [...pinned],
|
|
148
|
+
stageflowCleared: [...cleared],
|
|
149
|
+
stageflowDirectives: [...directives],
|
|
150
|
+
stageflowPromptVersion: COMPACTION_PROMPT_VERSION,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The whole summary pipeline in one place: pin and redact the input, ask the model for the written part,
|
|
155
|
+
* scrub it, then append the deterministic sections. The Pi hook and the evaluation harness both call this,
|
|
156
|
+
* so what the harness measures is what ships.
|
|
157
|
+
*/
|
|
158
|
+
export async function composeCompactionSummary(input) {
|
|
159
|
+
const prepared = prepareSummaryInputs({
|
|
160
|
+
messages: input.messages,
|
|
161
|
+
...(input.previousDetails ? { previousDetails: input.previousDetails } : {}),
|
|
162
|
+
...(input.clearInSummary ? { clearInSummary: input.clearInSummary } : {}),
|
|
163
|
+
});
|
|
164
|
+
const result = await input.summarize({
|
|
165
|
+
messages: prepared.messagesForSummarizer,
|
|
166
|
+
previousSummary: input.previousSummary !== undefined ? splitSummary(input.previousSummary).core : undefined,
|
|
167
|
+
});
|
|
168
|
+
const core = scrubSecrets(result.summary).split(SECTIONS_MARKER).join("").trimEnd();
|
|
169
|
+
const sections = scrubSecrets(renderSections({ pinned: prepared.pinned, cleared: prepared.cleared, state: input.state, directives: prepared.directives }));
|
|
170
|
+
return { summary: sections ? `${core}\n\n${sections}` : core, result, prepared };
|
|
171
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type ClearingClass = "clearable" | "keep";
|
|
2
|
+
/** Fail closed: only provably re-fetchable read results are clearable; everything else (bash included, it can have side effects) is kept. */
|
|
3
|
+
export declare function classifyForClearing(toolName: string, isError: boolean, _details?: unknown): ClearingClass;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { classifyTool } from "../agents/toolRisk.js";
|
|
2
|
+
import { ASK_OPERATOR_TOOL_NAME, EMIT_STAGE_ENVELOPE_TOOL_NAME, WRITE_STAGE_ARTIFACT_TOOL_NAME } from "../tools/stageToolNames.js";
|
|
3
|
+
import { WORKING_STATE_TOOL_NAME } from "./types.js";
|
|
4
|
+
const ALWAYS_KEEP = new Set([
|
|
5
|
+
ASK_OPERATOR_TOOL_NAME,
|
|
6
|
+
EMIT_STAGE_ENVELOPE_TOOL_NAME,
|
|
7
|
+
WRITE_STAGE_ARTIFACT_TOOL_NAME,
|
|
8
|
+
"write",
|
|
9
|
+
"edit",
|
|
10
|
+
WORKING_STATE_TOOL_NAME,
|
|
11
|
+
]);
|
|
12
|
+
const CLEARABLE_BUILTINS = new Set(["read", "grep", "find", "ls"]);
|
|
13
|
+
/** Fail closed: only provably re-fetchable read results are clearable; everything else (bash included, it can have side effects) is kept. */
|
|
14
|
+
export function classifyForClearing(toolName, isError, _details) {
|
|
15
|
+
if (isError)
|
|
16
|
+
return "keep";
|
|
17
|
+
if (typeof toolName !== "string" || toolName.length === 0)
|
|
18
|
+
return "keep";
|
|
19
|
+
if (ALWAYS_KEEP.has(toolName))
|
|
20
|
+
return "keep";
|
|
21
|
+
if (CLEARABLE_BUILTINS.has(toolName))
|
|
22
|
+
return "clearable";
|
|
23
|
+
if (toolName.startsWith("stageflow_")) {
|
|
24
|
+
const name = toolName.slice("stageflow_".length);
|
|
25
|
+
return ALWAYS_KEEP.has(name) ? "keep" : classifyTool(undefined, `stageflow.${name}`).readOnly ? "clearable" : "keep";
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return classifyTool(undefined, toolName).readOnly ? "clearable" : "keep";
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return "keep";
|
|
32
|
+
}
|
|
33
|
+
}
|