@nklisch/pi-enhanced 0.1.2 → 0.1.4
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/CHANGELOG.md +7 -0
- package/README.md +3 -2
- package/node_modules/@nklisch/pi-clearance/README.md +10 -5
- package/node_modules/@nklisch/pi-clearance/docs/ARCHITECTURE.md +12 -7
- package/node_modules/@nklisch/pi-clearance/docs/CONFIGURATION.md +25 -35
- package/node_modules/@nklisch/pi-clearance/docs/DEVELOPER_GUIDE.md +30 -30
- package/node_modules/@nklisch/pi-clearance/docs/PACK_AUTHORING.md +5 -4
- package/node_modules/@nklisch/pi-clearance/docs/PRINCIPLES.md +14 -10
- package/node_modules/@nklisch/pi-clearance/docs/REFERENCE_PATTERNS.md +1 -1
- package/node_modules/@nklisch/pi-clearance/docs/REVIEWER_PROMPTS.md +12 -8
- package/node_modules/@nklisch/pi-clearance/docs/RULE_PACKS.md +1 -1
- package/node_modules/@nklisch/pi-clearance/docs/SPEC.md +7 -6
- package/node_modules/@nklisch/pi-clearance/docs/TUNE.md +2 -2
- package/node_modules/@nklisch/pi-clearance/docs/USER_GUIDE.md +7 -3
- package/node_modules/@nklisch/pi-clearance/docs/VISION.md +3 -3
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.darwin-arm64.node +0 -0
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.darwin-x64.node +0 -0
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.linux-arm64-gnu.node +0 -0
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.linux-x64-gnu.node +0 -0
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-arm64-msvc.node +0 -0
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-x64-msvc.node +0 -0
- package/node_modules/@nklisch/pi-clearance/package.json +9 -5
- package/node_modules/@nklisch/pi-clearance/src/config/config-command-plans.ts +79 -3
- package/node_modules/@nklisch/pi-clearance/src/config/config-command-writer.ts +7 -1
- package/node_modules/@nklisch/pi-clearance/src/config/defaults.ts +42 -0
- package/node_modules/@nklisch/pi-clearance/src/config/gated-tools.ts +7 -0
- package/node_modules/@nklisch/pi-clearance/src/config/loader.ts +7 -1
- package/node_modules/@nklisch/pi-clearance/src/config/pack-enablement-writer.ts +1 -0
- package/node_modules/@nklisch/pi-clearance/src/config/paths.ts +14 -3
- package/node_modules/@nklisch/pi-clearance/src/config/persistence.ts +135 -0
- package/node_modules/@nklisch/pi-clearance/src/config/schema.ts +74 -26
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCase.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseCategory.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseExpectation.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseResult.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseResultOutcome.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseSource.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialValidationReport.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialValidationStatus.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashBlock.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashCommandShape.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashConditionalArm.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashControlConstruct.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashFlag.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashForLoopKeywordSpans.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashIteratorEntry.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashIteratorEntryKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashListOperator.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashLoopVariableReference.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFact.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFactContext.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFactProvenance.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFactProvenanceEntry.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFacts.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashPipeline.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashStage.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BashStageProgram.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/BlockOperator.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CapturedOutcome.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CommandFamilyKey.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CommandFamilySummary.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CompileError.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CompositionOperator.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundBodyReason.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundFeatureReason.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundForm.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundIteratorReason.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusEntry.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusExpectedLabel.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusFidelity.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusQueryModel.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusQuerySummary.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusQuerySummarySnapshot.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusRecord.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusSource.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/CountByLabel.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/Decision.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/DecisionEffect.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/DecisionProvenance.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/DecisionSource.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/DiagnosticSeverity.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/EffectivePolicy.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/EmbeddedShellProjection.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/EnvironmentAssignment.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/IteratorSourceKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/LoopQuoteKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/LoopVariableUnknownReason.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/MatcherExpr.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/MutationShapeKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/MutationTrustBoundaryClassification.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/MutationTrustBoundaryKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PackCompileResult.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PackWarningLevel.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ParsedEvidence.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ParsedShapeSummary.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathAccess.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathFactProjectScope.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathFactsRequirement.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathFactsResolvedConfig.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathNormalization.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathScope.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathScopeMatcherExpr.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathScopeMatcherMode.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathUnknownReason.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PathUsageKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolOperation.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolPathInput.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolShape.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolSpec.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PiFileMutationToolName.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PiToolMutationFacts.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPack.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackDocLink.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackExample.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackMetadata.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackWarning.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyRule.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ProposalNotRunReason.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ProposalNotRunSeverity.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/QuoteKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/Redirect.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/RedirectStream.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/RedirectTargetKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayCorpus.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDelta.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaBlockedSummary.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaChangedRecord.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaFamily.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaImprovement.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaRegression.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaStatus.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaTransitionCount.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayPathFacts.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayReviewerMode.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayReviewerOutcome.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayStatus.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayedDecision.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ShapeDiagnostic.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/SourceFidelity.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/SourceSpan.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/Substitution.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/SubstitutionKind.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ToolCallIdentity.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathAccess.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathFact.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathFactContext.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathFacts.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathUsage.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/ToolShape.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/UnknownPathBehavior.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/UnknownToolShape.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/contracts/index.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/index.ts +33 -2
- package/node_modules/@nklisch/pi-clearance/src/native/loader.ts +29 -42
- package/node_modules/@nklisch/pi-clearance/src/replay/reviewer-config-proposals.ts +7 -4
- package/node_modules/@nklisch/pi-clearance/src/runtime/allow-request-message.ts +21 -0
- package/node_modules/@nklisch/pi-clearance/src/runtime/auto-reviewer-read-models.ts +165 -8
- package/node_modules/@nklisch/pi-clearance/src/runtime/command-registry.ts +1 -1
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/allow.ts +26 -2
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/packs.ts +6 -6
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/scope.ts +5 -5
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/actions.ts +11 -0
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/dispatcher.ts +274 -1
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/model-options.ts +52 -0
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/native-ui.ts +54 -67
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/panels/reviewer.ts +19 -3
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/panels/scope.ts +2 -11
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/panels.ts +10 -1
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/read-model.ts +47 -13
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings.ts +32 -37
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/status.ts +3 -0
- package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/types.ts +14 -5
- package/node_modules/@nklisch/pi-clearance/src/runtime/handler.ts +36 -0
- package/node_modules/@nklisch/pi-clearance/src/runtime/mode-prompt.ts +0 -1
- package/node_modules/@nklisch/pi-clearance/src/runtime/model-adapter.ts +5 -1
- package/node_modules/@nklisch/pi-clearance/src/runtime/reviewer-context.ts +73 -10
- package/node_modules/@nklisch/pi-clearance/src/runtime/reviewer-prompts.ts +186 -175
- package/node_modules/@nklisch/pi-clearance/src/runtime/reviewer.ts +26 -6
- package/node_modules/@nklisch/pi-plugins/dist/infrastructure/state/local-lock-filesystem.d.ts +23 -1
- package/node_modules/@nklisch/pi-plugins/dist/infrastructure/state/local-lock-filesystem.js +46 -50
- package/node_modules/@nklisch/pi-plugins/dist/infrastructure/state/local-lock-filesystem.js.map +1 -1
- package/node_modules/@nklisch/pi-plugins/dist/runtime/mcp/pi-mcp-adapter-package.js +2 -2
- package/node_modules/@nklisch/pi-plugins/dist/runtime/mcp/pi-mcp-adapter-runtime.js +2 -2
- package/node_modules/@nklisch/pi-plugins/dist/runtime/subagents/pi-subagents-lifecycle.js +1 -1
- package/node_modules/@nklisch/pi-plugins/dist/runtime/subagents/pi-subagents-package.js +2 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/README.md +41 -31
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/dist/public.d.ts +2 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/FORK-MAINTENANCE.md +17 -11
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/VISION.md +14 -7
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/architecture.md +11 -19
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/comparison-with-upstream.md +58 -53
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/package.json +2 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/agent-type-resolution.ts +43 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/agent-types.ts +11 -6
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/custom-agents.ts +13 -6
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/default-agents.ts +0 -52
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/thinking-levels.ts +12 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/handlers/interrupt.ts +5 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/handlers/lifecycle.ts +3 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/index.ts +7 -6
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/create-subagent-session.ts +7 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/parent-snapshot.ts +11 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-manager.ts +26 -56
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-session.ts +48 -9
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-state.ts +32 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent.ts +105 -17
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/composite-subagent-observer.ts +4 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/notification.ts +50 -46
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/renderer.ts +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/subagent-events-observer.ts +15 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/runtime.ts +2 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/service/service-adapter.ts +35 -6
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/service/service.ts +1 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/model-label.ts +19 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/prompts.ts +24 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/session-config.ts +11 -6
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/settings.ts +70 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/agent-tool.ts +27 -10
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/background-spawner.ts +6 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/foreground-runner.ts +12 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-report.ts +17 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-tool.ts +13 -20
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/result-renderer.ts +6 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/spawn-config.ts +16 -16
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/steer-tool.ts +12 -4
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/types.ts +2 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/agent-widget.ts +24 -11
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/display.ts +10 -7
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/glyphs.ts +7 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigation.ts +34 -25
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigator.ts +30 -10
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/subagents-settings.ts +58 -13
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/widget-renderer.ts +32 -19
- package/node_modules/@nklisch/pi-plugins/package.json +3 -3
- package/package.json +1 -1
- package/test/verify-bundle.mjs +28 -1
package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/agent-tool.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
|
4
4
|
import { Text } from "@earendil-works/pi-tui";
|
|
5
5
|
import { Type } from "@sinclair/typebox";
|
|
6
6
|
import { AgentTypeRegistry } from "#src/config/agent-types";
|
|
7
|
+
import { THINKING_LEVELS_DESCRIPTION } from "#src/config/thinking-levels";
|
|
7
8
|
import type { ParentSnapshot } from "#src/lifecycle/parent-snapshot";
|
|
8
9
|
import type { AgentSpawnConfig } from "#src/lifecycle/subagent-manager";
|
|
9
10
|
import { spawnBackground } from "#src/tools/background-spawner";
|
|
@@ -12,7 +13,7 @@ import { buildAgentGuidelines, buildDetails, buildTypeListText, textResult } fro
|
|
|
12
13
|
import { renderAgentResult } from "#src/tools/result-renderer";
|
|
13
14
|
import { type ModelInfo, resolveSpawnConfig } from "#src/tools/spawn-config";
|
|
14
15
|
import type { ParentSessionInfo, Subagent } from "#src/types";
|
|
15
|
-
import { type AgentDetails, getDisplayName } from "#src/ui/display";
|
|
16
|
+
import { type AgentDetails, formatDuration, getDisplayName } from "#src/ui/display";
|
|
16
17
|
|
|
17
18
|
// ---- Deps interfaces ----
|
|
18
19
|
|
|
@@ -35,6 +36,7 @@ export interface AgentToolRuntime {
|
|
|
35
36
|
export type AgentToolSettings = {
|
|
36
37
|
readonly defaultMaxTurns: number | undefined;
|
|
37
38
|
readonly maxConcurrent: number;
|
|
39
|
+
readonly fallbackSubagent?: string | false;
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
// ---- Class ----
|
|
@@ -90,7 +92,9 @@ export class AgentTool {
|
|
|
90
92
|
}
|
|
91
93
|
if (!existing.isSessionReady()) {
|
|
92
94
|
return textResult(
|
|
93
|
-
|
|
95
|
+
existing.sessionReleased
|
|
96
|
+
? `Agent "${params.resume}" retained its result and transcript, but its live session was released after the retention window. Start a new subagent for fresh context.`
|
|
97
|
+
: `Agent "${params.resume}" has no active session to resume.`,
|
|
94
98
|
);
|
|
95
99
|
}
|
|
96
100
|
const record = await this.manager.resume(
|
|
@@ -101,9 +105,19 @@ export class AgentTool {
|
|
|
101
105
|
if (!record) {
|
|
102
106
|
return textResult(`Failed to resume agent "${params.resume}".`);
|
|
103
107
|
}
|
|
108
|
+
record.markConsumed();
|
|
109
|
+
const partial = record.result?.trim();
|
|
110
|
+
const resultText = record.status === "error"
|
|
111
|
+
? partial
|
|
112
|
+
? `Error: ${record.error}\n\nPartial output before the failure:\n${partial}`
|
|
113
|
+
: `Error: ${record.error}`
|
|
114
|
+
: partial ?? "No output.";
|
|
104
115
|
return textResult(
|
|
105
|
-
record.
|
|
106
|
-
buildDetails(
|
|
116
|
+
`Model: ${record.modelLabel}\nRuntime: ${formatDuration(record.startedAt, record.completedAt)}\n\n${resultText}`,
|
|
117
|
+
buildDetails(
|
|
118
|
+
{ ...config.presentation.detailBase, modelName: record.modelLabel },
|
|
119
|
+
record,
|
|
120
|
+
),
|
|
107
121
|
);
|
|
108
122
|
}
|
|
109
123
|
|
|
@@ -135,9 +149,11 @@ export class AgentTool {
|
|
|
135
149
|
...this.agentGuidelines,
|
|
136
150
|
"- Provide clear, detailed prompts so the agent can work autonomously.",
|
|
137
151
|
"- Subagent results are returned as text — summarize them for the user.",
|
|
138
|
-
"-
|
|
139
|
-
"- Use
|
|
140
|
-
"- Use steer_subagent to
|
|
152
|
+
"- Background completion automatically wakes you with a result preview. Continue other work instead of polling.",
|
|
153
|
+
"- Use get_subagent_result only for full output, verbose conversation, an explicit status check or synchronization point, or recovery after a missed notification.",
|
|
154
|
+
"- Use steer_subagent to redirect an agent that is still running.",
|
|
155
|
+
"- Use resume only after an agent finishes when it should continue with the same retained conversation history.",
|
|
156
|
+
"- Launch a new subagent without resume when prior conversation history is unnecessary.",
|
|
141
157
|
'- Use model to specify a different model (as "provider/modelId", or fuzzy e.g. "haiku", "sonnet").',
|
|
142
158
|
"- Use thinking to control extended thinking level.",
|
|
143
159
|
"- Use inherit_context if the agent needs the parent conversation history.",
|
|
@@ -176,7 +192,7 @@ ${guidelines}
|
|
|
176
192
|
thinking: Type.Optional(
|
|
177
193
|
Type.String({
|
|
178
194
|
description:
|
|
179
|
-
|
|
195
|
+
`Thinking level: ${THINKING_LEVELS_DESCRIPTION}. Overrides agent default. Availability depends on the selected model and host Pi version.`,
|
|
180
196
|
}),
|
|
181
197
|
),
|
|
182
198
|
max_turns: Type.Optional(
|
|
@@ -189,12 +205,13 @@ ${guidelines}
|
|
|
189
205
|
run_in_background: Type.Optional(
|
|
190
206
|
Type.Boolean({
|
|
191
207
|
description:
|
|
192
|
-
"Set to true to run in background. Returns agent ID immediately
|
|
208
|
+
"Set to true to run in background. Returns an agent ID immediately; completion automatically wakes you with a result preview.",
|
|
193
209
|
}),
|
|
194
210
|
),
|
|
195
211
|
resume: Type.Optional(
|
|
196
212
|
Type.String({
|
|
197
|
-
description:
|
|
213
|
+
description:
|
|
214
|
+
"Agent ID of a retained, finished session to continue with the same conversation history. Omit to start a new context.",
|
|
198
215
|
}),
|
|
199
216
|
),
|
|
200
217
|
inherit_context: Type.Optional(
|
|
@@ -52,13 +52,17 @@ export function spawnBackground(
|
|
|
52
52
|
`Agent ${isQueued ? "queued" : "started"} in background.\n` +
|
|
53
53
|
`Agent ID: ${id}\n` +
|
|
54
54
|
`Type: ${identity.displayName}\n` +
|
|
55
|
+
`Model: ${presentation.modelName}\n` +
|
|
56
|
+
`Runtime: 0.0s\n` +
|
|
55
57
|
`Description: ${execution.description}\n` +
|
|
58
|
+
(identity.fellBack ? `Fallback: requested ${identity.rawType}; using ${identity.subagentType}\n` : "") +
|
|
56
59
|
(record?.outputFile ? `Output file: ${record.outputFile}\n` : "") +
|
|
57
60
|
(isQueued
|
|
58
61
|
? `Position: queued (max ${params.settings.maxConcurrent} concurrent)\n`
|
|
59
62
|
: "") +
|
|
60
|
-
`\
|
|
61
|
-
`Use
|
|
63
|
+
`\nCompletion will automatically notify and wake you with a result preview. Continue other work; do not poll.\n` +
|
|
64
|
+
`Use steer_subagent to redirect this agent while it runs.\n` +
|
|
65
|
+
`Use get_subagent_result only for full output, verbose conversation, an explicit status check or synchronization point, or recovery after a missed notification.\n` +
|
|
62
66
|
`Do not duplicate this agent's work.`,
|
|
63
67
|
{
|
|
64
68
|
...presentation.detailBase,
|
|
@@ -111,22 +111,31 @@ export async function runForeground(
|
|
|
111
111
|
|
|
112
112
|
clearInterval(spinnerInterval);
|
|
113
113
|
|
|
114
|
+
// Foreground delivery returns the complete outcome inline, so retention can
|
|
115
|
+
// use the shorter consumed-session window.
|
|
116
|
+
record.markConsumed();
|
|
117
|
+
|
|
114
118
|
const tokenText = formatLifetimeTokens(record);
|
|
115
119
|
const details = buildDetails(presentation.detailBase, record, { tokens: tokenText });
|
|
116
120
|
|
|
117
121
|
const fallbackNote = identity.fellBack
|
|
118
|
-
? `Note: Unknown agent type "${identity.rawType}" — using
|
|
122
|
+
? `Note: Unknown agent type "${identity.rawType}" — using ${identity.subagentType}.\n\n`
|
|
119
123
|
: "";
|
|
120
124
|
|
|
121
125
|
if (record.status === "error") {
|
|
122
|
-
|
|
126
|
+
const partial = record.result?.trim();
|
|
127
|
+
return textResult(
|
|
128
|
+
`${fallbackNote}Model: ${record.modelLabel}\nRuntime: ${formatMs(details.durationMs)}\nAgent failed: ${record.error}` +
|
|
129
|
+
(partial ? `\n\nPartial output before the failure:\n${partial}` : ""),
|
|
130
|
+
details,
|
|
131
|
+
);
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
const durationMs = (record.completedAt ?? Date.now()) - record.startedAt;
|
|
126
135
|
const statsParts = [`${record.toolUses} tool uses`];
|
|
127
136
|
if (tokenText) statsParts.push(tokenText);
|
|
128
137
|
return textResult(
|
|
129
|
-
`${fallbackNote}
|
|
138
|
+
`${fallbackNote}Model: ${record.modelLabel}\nRuntime: ${formatMs(durationMs)}\nAgent completed (${statsParts.join(", ")})${getStatusNote(record.status)}.\n\n` +
|
|
130
139
|
(record.result?.trim() ?? "No output."),
|
|
131
140
|
details,
|
|
132
141
|
);
|
|
@@ -13,6 +13,7 @@ import type { SubagentStatus } from "#src/lifecycle/subagent";
|
|
|
13
13
|
export interface AgentReport {
|
|
14
14
|
id: string;
|
|
15
15
|
displayName: string;
|
|
16
|
+
modelLabel: string;
|
|
16
17
|
status: SubagentStatus;
|
|
17
18
|
toolUses: number;
|
|
18
19
|
/** Pre-formatted lifetime token total; "" when zero. */
|
|
@@ -24,8 +25,11 @@ export interface AgentReport {
|
|
|
24
25
|
description: string;
|
|
25
26
|
result: string | undefined;
|
|
26
27
|
error: string | undefined;
|
|
28
|
+
stoppedWhileQueued: boolean;
|
|
27
29
|
/** Present only when verbose was requested and a conversation is available. */
|
|
28
30
|
conversation?: string;
|
|
31
|
+
/** Persisted transcript remains readable after the live session is released. */
|
|
32
|
+
transcriptPath?: string;
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
/** Assemble the stats parts: Tool uses / tokens? / Context? / Compactions? / Duration. */
|
|
@@ -40,9 +44,18 @@ export function renderStatsParts(report: AgentReport): string[] {
|
|
|
40
44
|
|
|
41
45
|
/** Select the per-status body: running note, error line, or trimmed result. */
|
|
42
46
|
export function renderReportBody(report: AgentReport): string {
|
|
47
|
+
if (report.status === "queued")
|
|
48
|
+
return "Agent is queued and has not started. Use wait: true to synchronize, or rely on the automatic completion notification.";
|
|
43
49
|
if (report.status === "running")
|
|
44
|
-
return "Agent is still running. Use wait: true or
|
|
45
|
-
if (report.
|
|
50
|
+
return "Agent is still running. Use wait: true to synchronize, or rely on the automatic completion notification.";
|
|
51
|
+
if (report.stoppedWhileQueued)
|
|
52
|
+
return "Agent was stopped while queued and never started. No work was performed.";
|
|
53
|
+
if (report.status === "error") {
|
|
54
|
+
const partial = report.result?.trim();
|
|
55
|
+
return partial
|
|
56
|
+
? `Error: ${report.error}\n\nPartial output before the failure:\n${partial}`
|
|
57
|
+
: `Error: ${report.error}`;
|
|
58
|
+
}
|
|
46
59
|
return report.result?.trim() ?? "No output.";
|
|
47
60
|
}
|
|
48
61
|
|
|
@@ -50,11 +63,12 @@ export function renderReportBody(report: AgentReport): string {
|
|
|
50
63
|
export function formatAgentReport(report: AgentReport): string {
|
|
51
64
|
let output =
|
|
52
65
|
`Agent: ${report.id}\n` +
|
|
53
|
-
`Type: ${report.displayName} | Status: ${report.status} | ${renderStatsParts(report).join(" | ")}\n` +
|
|
66
|
+
`Type: ${report.displayName} | Model: ${report.modelLabel} | Status: ${report.status} | ${renderStatsParts(report).join(" | ")}\n` +
|
|
54
67
|
`Description: ${report.description}\n\n`;
|
|
55
68
|
output += renderReportBody(report);
|
|
56
69
|
if (report.conversation) {
|
|
57
70
|
output += `\n\n--- Agent Conversation ---\n${report.conversation}`;
|
|
58
71
|
}
|
|
72
|
+
if (report.transcriptPath) output += `\n\nFull transcript: ${report.transcriptPath}`;
|
|
59
73
|
return output;
|
|
60
74
|
}
|
|
@@ -12,23 +12,18 @@ export interface GetResultToolManager {
|
|
|
12
12
|
getRecord(id: string): Subagent | undefined;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export interface GetResultToolNotifications {
|
|
16
|
-
consume(id: string): void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
15
|
// ---- Class ----
|
|
20
16
|
|
|
21
17
|
export class GetResultTool {
|
|
22
18
|
constructor(
|
|
23
19
|
private readonly manager: GetResultToolManager,
|
|
24
|
-
private readonly notifications: GetResultToolNotifications,
|
|
25
20
|
private readonly registry: AgentConfigLookup,
|
|
26
21
|
) {}
|
|
27
22
|
|
|
28
23
|
async execute(
|
|
29
24
|
_toolCallId: string,
|
|
30
25
|
params: { agent_id: string; wait?: boolean; verbose?: boolean },
|
|
31
|
-
|
|
26
|
+
signal: AbortSignal,
|
|
32
27
|
_onUpdate: unknown,
|
|
33
28
|
_ctx: unknown,
|
|
34
29
|
) {
|
|
@@ -37,19 +32,12 @@ export class GetResultTool {
|
|
|
37
32
|
return textResult(`Agent not found: "${params.agent_id}". It may have been cleaned up.`);
|
|
38
33
|
}
|
|
39
34
|
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
// Consuming here prevents a redundant follow-up notification.
|
|
44
|
-
if (params.wait && record.status === "running" && record.promise) {
|
|
45
|
-
this.notifications.consume(params.agent_id);
|
|
46
|
-
await record.promise;
|
|
47
|
-
}
|
|
35
|
+
// A queued record is awaitable from spawn, and a resumed record republishes
|
|
36
|
+
// its live promise. Interrupting this tool stops only the wait.
|
|
37
|
+
if (params.wait) await record.waitUntilSettled(signal);
|
|
48
38
|
|
|
49
|
-
//
|
|
50
|
-
if (record.
|
|
51
|
-
this.notifications.consume(params.agent_id);
|
|
52
|
-
}
|
|
39
|
+
// Pull delivery: only a terminal result was actually collected.
|
|
40
|
+
if (!record.isActive()) record.markConsumed();
|
|
53
41
|
|
|
54
42
|
return textResult(formatAgentReport(this.buildReport(record, params.verbose)));
|
|
55
43
|
}
|
|
@@ -58,6 +46,7 @@ export class GetResultTool {
|
|
|
58
46
|
return {
|
|
59
47
|
id: record.id,
|
|
60
48
|
displayName: getDisplayName(record.type, this.registry),
|
|
49
|
+
modelLabel: record.modelLabel,
|
|
61
50
|
status: record.status,
|
|
62
51
|
toolUses: record.toolUses,
|
|
63
52
|
tokens: formatLifetimeTokens(record),
|
|
@@ -67,7 +56,9 @@ export class GetResultTool {
|
|
|
67
56
|
description: record.description,
|
|
68
57
|
result: record.result,
|
|
69
58
|
error: record.error,
|
|
59
|
+
stoppedWhileQueued: record.stoppedWhileQueued,
|
|
70
60
|
conversation: verbose ? record.getConversation() : undefined,
|
|
61
|
+
transcriptPath: record.outputFile,
|
|
71
62
|
};
|
|
72
63
|
}
|
|
73
64
|
|
|
@@ -76,9 +67,11 @@ export class GetResultTool {
|
|
|
76
67
|
name: "get_subagent_result" as const,
|
|
77
68
|
label: "Get Agent Result",
|
|
78
69
|
promptSnippet:
|
|
79
|
-
"get_subagent_result:
|
|
70
|
+
"get_subagent_result: Inspect status or retrieve full results from a background agent.",
|
|
80
71
|
description:
|
|
81
|
-
"
|
|
72
|
+
"Background completion automatically wakes you with a result preview, so do not poll. " +
|
|
73
|
+
"Use this tool only for full output, verbose conversation, an explicit status check or synchronization point, " +
|
|
74
|
+
"or recovery after a missed notification.",
|
|
82
75
|
parameters: Type.Object({
|
|
83
76
|
agent_id: Type.String({
|
|
84
77
|
description: "The agent ID to check.",
|
|
@@ -33,14 +33,17 @@ export function renderAgentResult(
|
|
|
33
33
|
export function renderRunning(details: AgentDetails, theme: Theme): string {
|
|
34
34
|
const frame = SPINNER[details.spinnerFrame ?? 0];
|
|
35
35
|
const s = renderStats(details, theme);
|
|
36
|
+
const duration = theme.fg("dim", formatMs(details.durationMs));
|
|
36
37
|
let line = theme.fg("accent", frame) + (s ? " " + s : "");
|
|
38
|
+
line += `${s ? " " + theme.fg("dim", "·") + " " : " "}${duration}`;
|
|
37
39
|
line += "\n" + theme.fg("dim", ` ⎿ ${details.activity ?? "thinking\u2026"}`);
|
|
38
40
|
return line;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
/** Render background launch status. */
|
|
42
44
|
export function renderBackground(details: AgentDetails, theme: Theme): string {
|
|
43
|
-
|
|
45
|
+
const identity = [details.modelName, formatMs(details.durationMs)].filter(Boolean).join(" · ");
|
|
46
|
+
return theme.fg("dim", ` \u23BF Running in background (ID: ${details.agentId}) · ${identity}`);
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
/** Render completed or steered status with optional expanded result text. */
|
|
@@ -83,6 +86,7 @@ export function renderCompleted(
|
|
|
83
86
|
export function renderStopped(details: AgentDetails, theme: Theme): string {
|
|
84
87
|
const s = renderStats(details, theme);
|
|
85
88
|
let line = theme.fg("dim", "\u25A0") + (s ? " " + s : "");
|
|
89
|
+
line += ` ${theme.fg("dim", "·")} ${theme.fg("dim", formatMs(details.durationMs))}`;
|
|
86
90
|
line += "\n" + theme.fg("dim", " \u23BF Stopped");
|
|
87
91
|
return line;
|
|
88
92
|
}
|
|
@@ -91,6 +95,7 @@ export function renderStopped(details: AgentDetails, theme: Theme): string {
|
|
|
91
95
|
export function renderFailed(details: AgentDetails, theme: Theme): string {
|
|
92
96
|
const s = renderStats(details, theme);
|
|
93
97
|
let line = theme.fg("error", "\u2717") + (s ? " " + s : "");
|
|
98
|
+
line += ` ${theme.fg("dim", "·")} ${theme.fg("dim", formatMs(details.durationMs))}`;
|
|
94
99
|
|
|
95
100
|
if (details.status === "error") {
|
|
96
101
|
line += "\n" + theme.fg("error", ` \u23BF Error: ${details.error ?? "unknown"}`);
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Model } from "@earendil-works/pi-ai";
|
|
10
|
+
import { resolveDispatchAgentType } from "#src/config/agent-type-resolution";
|
|
10
11
|
import type { AgentTypeRegistry } from "#src/config/agent-types";
|
|
11
12
|
import { resolveAgentInvocationConfig } from "#src/config/invocation-config";
|
|
12
13
|
import { normalizeMaxTurns } from "#src/lifecycle/turn-limits";
|
|
13
14
|
import type { ModelRegistry } from "#src/session/model-resolver";
|
|
15
|
+
import { formatModelLabel } from "#src/session/model-label";
|
|
14
16
|
import { resolveInvocationModel } from "#src/session/model-resolver";
|
|
15
17
|
import type { AgentInvocation, SubagentType, ThinkingLevel } from "#src/types";
|
|
16
18
|
import {
|
|
@@ -75,18 +77,21 @@ export function resolveSpawnConfig(
|
|
|
75
77
|
params: Record<string, unknown>,
|
|
76
78
|
registry: AgentTypeRegistry,
|
|
77
79
|
modelInfo: ModelInfo,
|
|
78
|
-
settings: {
|
|
80
|
+
settings: {
|
|
81
|
+
readonly defaultMaxTurns: number | undefined;
|
|
82
|
+
readonly fallbackSubagent?: string | false;
|
|
83
|
+
},
|
|
79
84
|
): ResolvedSpawnConfig | SpawnConfigError {
|
|
80
85
|
const rawType = params.subagent_type as SubagentType;
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
const typeResolution = resolveDispatchAgentType(
|
|
87
|
+
rawType,
|
|
88
|
+
registry,
|
|
89
|
+
settings.fallbackSubagent,
|
|
90
|
+
);
|
|
91
|
+
if ("error" in typeResolution) return typeResolution;
|
|
87
92
|
|
|
88
|
-
const subagentType =
|
|
89
|
-
const fellBack =
|
|
93
|
+
const subagentType = typeResolution.type;
|
|
94
|
+
const fellBack = typeResolution.fellBack;
|
|
90
95
|
|
|
91
96
|
const displayName = getDisplayName(subagentType, registry);
|
|
92
97
|
|
|
@@ -108,13 +113,8 @@ export function resolveSpawnConfig(
|
|
|
108
113
|
const inheritContext = resolvedConfig.inheritContext;
|
|
109
114
|
const runInBackground = resolvedConfig.runInBackground;
|
|
110
115
|
|
|
111
|
-
//
|
|
112
|
-
const
|
|
113
|
-
const effectiveModelId = model?.id;
|
|
114
|
-
const modelName =
|
|
115
|
-
effectiveModelId && effectiveModelId !== parentModelId
|
|
116
|
-
? model.name.replace(/^Claude\s+/i, "").toLowerCase()
|
|
117
|
-
: undefined;
|
|
116
|
+
// Every status surface shows the exact effective model, including inheritance.
|
|
117
|
+
const modelName = formatModelLabel(model);
|
|
118
118
|
|
|
119
119
|
const effectiveMaxTurns = normalizeMaxTurns(
|
|
120
120
|
resolvedConfig.maxTurns ?? settings.defaultMaxTurns,
|
package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/steer-tool.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
3
|
import { formatLifetimeTokens, textResult } from "#src/tools/helpers";
|
|
4
4
|
import type { SteerOutcome, Subagent } from "#src/types";
|
|
5
|
+
import { formatDuration } from "#src/ui/display";
|
|
5
6
|
|
|
6
7
|
// ---- Deps interfaces ----
|
|
7
8
|
|
|
@@ -40,19 +41,22 @@ export class SteerTool {
|
|
|
40
41
|
outcome = await record.steer(params.message);
|
|
41
42
|
} catch (err) {
|
|
42
43
|
return textResult(
|
|
43
|
-
`Failed to steer agent: ${err instanceof Error ? err.message : String(err)}
|
|
44
|
+
`Failed to steer agent: ${err instanceof Error ? err.message : String(err)}\n`
|
|
45
|
+
+ this.renderRunIdentity(record),
|
|
44
46
|
);
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
switch (outcome.kind) {
|
|
48
50
|
case "rejected":
|
|
49
51
|
return textResult(
|
|
50
|
-
`Agent "${params.agent_id}" is not running (status: ${outcome.status}). Cannot steer a non-running agent
|
|
52
|
+
`Agent "${params.agent_id}" is not running (status: ${outcome.status}). Cannot steer a non-running agent.\n`
|
|
53
|
+
+ this.renderRunIdentity(record),
|
|
51
54
|
);
|
|
52
55
|
case "buffered":
|
|
53
56
|
this.events.emit("subagents:steered", { id: record.id, message: params.message });
|
|
54
57
|
return textResult(
|
|
55
|
-
`Steering message queued for agent ${record.id}. It will be delivered once the session initializes
|
|
58
|
+
`Steering message queued for agent ${record.id}. It will be delivered once the session initializes.\n`
|
|
59
|
+
+ this.renderRunIdentity(record),
|
|
56
60
|
);
|
|
57
61
|
case "delivered":
|
|
58
62
|
this.events.emit("subagents:steered", { id: record.id, message: params.message });
|
|
@@ -64,7 +68,7 @@ export class SteerTool {
|
|
|
64
68
|
private renderDelivered(record: Subagent) {
|
|
65
69
|
const tokens = formatLifetimeTokens(record);
|
|
66
70
|
const contextPercent = record.getContextPercent();
|
|
67
|
-
const stateParts: string[] = [];
|
|
71
|
+
const stateParts: string[] = [record.modelLabel, formatDuration(record.startedAt, record.completedAt)];
|
|
68
72
|
if (tokens) stateParts.push(tokens);
|
|
69
73
|
stateParts.push(`${record.toolUses} tool ${record.toolUses === 1 ? "use" : "uses"}`);
|
|
70
74
|
if (contextPercent !== null)
|
|
@@ -79,6 +83,10 @@ export class SteerTool {
|
|
|
79
83
|
);
|
|
80
84
|
}
|
|
81
85
|
|
|
86
|
+
private renderRunIdentity(record: Subagent): string {
|
|
87
|
+
return `Model: ${record.modelLabel}\nRuntime: ${formatDuration(record.startedAt, record.completedAt)}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
toToolDefinition() {
|
|
83
91
|
return defineTool({
|
|
84
92
|
name: "steer_subagent" as const,
|
|
@@ -63,11 +63,11 @@ export interface AgentConfig extends AgentIdentity, AgentPromptConfig {
|
|
|
63
63
|
/** false = agent is hidden from the registry */
|
|
64
64
|
enabled?: boolean;
|
|
65
65
|
/** Where this agent was loaded from */
|
|
66
|
-
source?: "default" | "project" | "global";
|
|
66
|
+
source?: "default" | "project" | "shared-project" | "global";
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
export interface AgentInvocation {
|
|
70
|
-
/**
|
|
70
|
+
/** Exact effective model label in `provider/id` form. */
|
|
71
71
|
modelName?: string;
|
|
72
72
|
thinking?: ThinkingLevel;
|
|
73
73
|
maxTurns?: number;
|
package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/agent-widget.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { AgentTypeRegistry } from "#src/config/agent-types";
|
|
|
10
10
|
import type { Subagent } from "#src/lifecycle/subagent";
|
|
11
11
|
import type { SubagentManager, SubagentManagerObserver } from "#src/lifecycle/subagent-manager";
|
|
12
12
|
import type { CompactionInfo } from "#src/types";
|
|
13
|
-
import { ERROR_STATUSES, type Theme } from "#src/ui/display";
|
|
13
|
+
import { ERROR_STATUSES, formatMs, type Theme } from "#src/ui/display";
|
|
14
14
|
import { renderWidgetLines, type WidgetAgent } from "#src/ui/widget-renderer";
|
|
15
15
|
|
|
16
16
|
// ---- Types ----
|
|
@@ -51,6 +51,25 @@ export function assembleWidgetState(
|
|
|
51
51
|
return { runningCount, queuedCount, hasFinished, hasActive };
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/** Render the aggregate status bar without hiding per-agent model/runtime details. */
|
|
55
|
+
export function formatStatusBar(
|
|
56
|
+
state: WidgetState,
|
|
57
|
+
agents: readonly Pick<Subagent, "status" | "modelLabel" | "startedAt">[],
|
|
58
|
+
now = Date.now(),
|
|
59
|
+
): string | undefined {
|
|
60
|
+
if (!state.hasActive) return undefined;
|
|
61
|
+
const statusParts: string[] = [];
|
|
62
|
+
if (state.runningCount > 0) statusParts.push(`${state.runningCount} running`);
|
|
63
|
+
if (state.queuedCount > 0) statusParts.push(`${state.queuedCount} queued`);
|
|
64
|
+
const total = state.runningCount + state.queuedCount;
|
|
65
|
+
const activeDetails = agents
|
|
66
|
+
.filter((agent) => agent.status === "running" || agent.status === "queued")
|
|
67
|
+
.map((agent) => agent.status === "running"
|
|
68
|
+
? `${agent.modelLabel} ${formatMs(now - agent.startedAt)}`
|
|
69
|
+
: `${agent.modelLabel} queued`);
|
|
70
|
+
return `${statusParts.join(", ")} agent${total === 1 ? "" : "s"} · ${activeDetails.join(", ")}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
54
73
|
export type UICtx = {
|
|
55
74
|
setStatus(key: string, text: string | undefined): void;
|
|
56
75
|
setWidget(
|
|
@@ -165,6 +184,7 @@ export class AgentWidget implements SubagentManagerObserver {
|
|
|
165
184
|
type: record.type,
|
|
166
185
|
status: record.status,
|
|
167
186
|
description: record.description,
|
|
187
|
+
modelLabel: record.modelLabel,
|
|
168
188
|
toolUses: record.toolUses,
|
|
169
189
|
startedAt: record.startedAt,
|
|
170
190
|
completedAt: record.completedAt,
|
|
@@ -216,15 +236,8 @@ export class AgentWidget implements SubagentManagerObserver {
|
|
|
216
236
|
* Compute the status bar text from the current widget state and call
|
|
217
237
|
* `setStatus` only when it differs from the last cached value.
|
|
218
238
|
*/
|
|
219
|
-
private updateStatusBar(state: WidgetState): void {
|
|
220
|
-
|
|
221
|
-
if (state.hasActive) {
|
|
222
|
-
const statusParts: string[] = [];
|
|
223
|
-
if (state.runningCount > 0) statusParts.push(`${state.runningCount} running`);
|
|
224
|
-
if (state.queuedCount > 0) statusParts.push(`${state.queuedCount} queued`);
|
|
225
|
-
const total = state.runningCount + state.queuedCount;
|
|
226
|
-
newStatusText = `${statusParts.join(", ")} agent${total === 1 ? "" : "s"}`;
|
|
227
|
-
}
|
|
239
|
+
private updateStatusBar(state: WidgetState, agents: readonly Subagent[]): void {
|
|
240
|
+
const newStatusText = formatStatusBar(state, agents);
|
|
228
241
|
if (newStatusText !== this.lastStatusText) {
|
|
229
242
|
this.uiCtx!.setStatus("subagents", newStatusText);
|
|
230
243
|
this.lastStatusText = newStatusText;
|
|
@@ -259,7 +272,7 @@ export class AgentWidget implements SubagentManagerObserver {
|
|
|
259
272
|
return;
|
|
260
273
|
}
|
|
261
274
|
|
|
262
|
-
this.updateStatusBar(state);
|
|
275
|
+
this.updateStatusBar(state, backgroundAgents);
|
|
263
276
|
this.widgetFrame++;
|
|
264
277
|
|
|
265
278
|
// Register widget callback once; subsequent updates use requestRender()
|
package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/display.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { AgentConfigLookup } from "#src/config/agent-types";
|
|
9
|
+
import { GLYPHS } from "#src/ui/glyphs";
|
|
9
10
|
import type { AgentInvocation, SubagentType } from "#src/types";
|
|
10
11
|
|
|
11
12
|
// ---- Types ----
|
|
@@ -28,7 +29,7 @@ export interface AgentDetails {
|
|
|
28
29
|
activity?: string;
|
|
29
30
|
/** Current spinner frame index (for animated running indicator). */
|
|
30
31
|
spinnerFrame?: number;
|
|
31
|
-
/**
|
|
32
|
+
/** Exact effective model label in `provider/id` form. */
|
|
32
33
|
modelName?: string;
|
|
33
34
|
/** Notable config tags (e.g. ["thinking: high", "inherit context"]). */
|
|
34
35
|
tags?: string[];
|
|
@@ -71,12 +72,12 @@ export function formatTokens(count: number): string {
|
|
|
71
72
|
/**
|
|
72
73
|
* Token count with optional context-fill % and compaction-count annotations.
|
|
73
74
|
* Thresholds for percent: <70% dim, 70–85% warning, ≥85% error.
|
|
74
|
-
* Compaction count rendered as
|
|
75
|
+
* Compaction count rendered as `⇊N` in dim.
|
|
75
76
|
*
|
|
76
77
|
* "12.3k token" — no annotations
|
|
77
78
|
* "12.3k token (45%)" — percent only
|
|
78
|
-
* "12.3k token (
|
|
79
|
-
* "12.3k token (45% ·
|
|
79
|
+
* "12.3k token (⇊2)" — compactions only (e.g. right after compact)
|
|
80
|
+
* "12.3k token (45% · ⇊2)" — both
|
|
80
81
|
*/
|
|
81
82
|
export function formatSessionTokens(
|
|
82
83
|
tokens: number,
|
|
@@ -91,16 +92,18 @@ export function formatSessionTokens(
|
|
|
91
92
|
annot.push(theme.fg(color, `${Math.round(percent)}%`));
|
|
92
93
|
}
|
|
93
94
|
if (compactions > 0) {
|
|
94
|
-
annot.push(theme.fg("dim",
|
|
95
|
+
annot.push(theme.fg("dim", `${GLYPHS.compactions}${compactions}`));
|
|
95
96
|
}
|
|
96
97
|
if (annot.length === 0) return tokenStr;
|
|
97
98
|
const sep = theme.fg("dim", " · ");
|
|
98
99
|
return `${tokenStr} ${theme.fg("dim", "(")}${annot.join(sep)}${theme.fg("dim", ")")}`;
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
/** Format turn count with optional max limit: "
|
|
102
|
+
/** Format turn count with optional max limit: "↻5≤30" or "↻5". */
|
|
102
103
|
export function formatTurns(turnCount: number, maxTurns?: number | null): string {
|
|
103
|
-
return maxTurns != null
|
|
104
|
+
return maxTurns != null
|
|
105
|
+
? `${GLYPHS.turns}${turnCount}≤${maxTurns}`
|
|
106
|
+
: `${GLYPHS.turns}${turnCount}`;
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
/** Format milliseconds as human-readable duration. */
|