agent-nuvira 3.3.13 → 3.3.14
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 +67 -1
- package/dist/agents/agents/planner.d.ts.map +1 -1
- package/dist/agents/agents/planner.js +9 -0
- package/dist/agents/agents/planner.js.map +1 -1
- package/dist/agents/orchestrator.d.ts +31 -0
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +74 -126
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/cli/chat.d.ts +89 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +765 -33
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +12 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts +12 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +86 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/decisions.d.ts +28 -0
- package/dist/cli/decisions.d.ts.map +1 -0
- package/dist/cli/decisions.js +140 -0
- package/dist/cli/decisions.js.map +1 -0
- package/dist/cli/doctor.d.ts +6 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +46 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/failover-runner.d.ts.map +1 -1
- package/dist/cli/failover-runner.js +19 -1
- package/dist/cli/failover-runner.js.map +1 -1
- package/dist/cli/feedback.d.ts.map +1 -1
- package/dist/cli/feedback.js +5 -1
- package/dist/cli/feedback.js.map +1 -1
- package/dist/cli/hooks.d.ts +30 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +224 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/knowledge.d.ts +9 -1
- package/dist/cli/knowledge.d.ts.map +1 -1
- package/dist/cli/knowledge.js +93 -2
- package/dist/cli/knowledge.js.map +1 -1
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +47 -12
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/model.d.ts +20 -0
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +294 -14
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/rate.d.ts +78 -0
- package/dist/cli/rate.d.ts.map +1 -0
- package/dist/cli/rate.js +294 -0
- package/dist/cli/rate.js.map +1 -0
- package/dist/config/process-env.d.ts.map +1 -1
- package/dist/config/process-env.js +10 -0
- package/dist/config/process-env.js.map +1 -1
- package/dist/enterprise/vault.d.ts.map +1 -1
- package/dist/enterprise/vault.js +5 -21
- package/dist/enterprise/vault.js.map +1 -1
- package/dist/gateway/hook-contract.d.ts +33 -0
- package/dist/gateway/hook-contract.d.ts.map +1 -1
- package/dist/gateway/hook-contract.js +97 -0
- package/dist/gateway/hook-contract.js.map +1 -1
- package/dist/inference/gemini-adapter.d.ts.map +1 -1
- package/dist/inference/gemini-adapter.js +4 -0
- package/dist/inference/gemini-adapter.js.map +1 -1
- package/dist/inference/interface.d.ts +37 -0
- package/dist/inference/interface.d.ts.map +1 -1
- package/dist/inference/native-tools.d.ts +16 -1
- package/dist/inference/native-tools.d.ts.map +1 -1
- package/dist/inference/native-tools.js +34 -10
- package/dist/inference/native-tools.js.map +1 -1
- package/dist/inference/route-resolver.d.ts +30 -0
- package/dist/inference/route-resolver.d.ts.map +1 -1
- package/dist/inference/route-resolver.js +158 -1
- package/dist/inference/route-resolver.js.map +1 -1
- package/dist/inference/tools.d.ts +16 -1
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +51 -18
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/acceptance-model.d.ts +247 -0
- package/dist/learning/acceptance-model.d.ts.map +1 -0
- package/dist/learning/acceptance-model.js +708 -0
- package/dist/learning/acceptance-model.js.map +1 -0
- package/dist/learning/auto-router.d.ts +68 -24
- package/dist/learning/auto-router.d.ts.map +1 -1
- package/dist/learning/auto-router.js +301 -96
- package/dist/learning/auto-router.js.map +1 -1
- package/dist/learning/autonomy-policy.d.ts +12 -16
- package/dist/learning/autonomy-policy.d.ts.map +1 -1
- package/dist/learning/autonomy-policy.js +50 -48
- package/dist/learning/autonomy-policy.js.map +1 -1
- package/dist/learning/behavioural-labels.d.ts +86 -0
- package/dist/learning/behavioural-labels.d.ts.map +1 -0
- package/dist/learning/behavioural-labels.js +166 -0
- package/dist/learning/behavioural-labels.js.map +1 -0
- package/dist/learning/capability-evidence.d.ts +167 -0
- package/dist/learning/capability-evidence.d.ts.map +1 -0
- package/dist/learning/capability-evidence.js +210 -0
- package/dist/learning/capability-evidence.js.map +1 -0
- package/dist/learning/capability-readiness.d.ts +64 -0
- package/dist/learning/capability-readiness.d.ts.map +1 -0
- package/dist/learning/capability-readiness.js +74 -0
- package/dist/learning/capability-readiness.js.map +1 -0
- package/dist/learning/capability-types.d.ts +169 -0
- package/dist/learning/capability-types.d.ts.map +1 -0
- package/dist/learning/capability-types.js +20 -0
- package/dist/learning/capability-types.js.map +1 -0
- package/dist/learning/catalog-feed.d.ts +89 -0
- package/dist/learning/catalog-feed.d.ts.map +1 -0
- package/dist/learning/catalog-feed.js +211 -0
- package/dist/learning/catalog-feed.js.map +1 -0
- package/dist/learning/cli-intent-effects.d.ts +60 -0
- package/dist/learning/cli-intent-effects.d.ts.map +1 -0
- package/dist/learning/cli-intent-effects.js +153 -0
- package/dist/learning/cli-intent-effects.js.map +1 -0
- package/dist/learning/command-adaptation.d.ts +41 -0
- package/dist/learning/command-adaptation.d.ts.map +1 -0
- package/dist/learning/command-adaptation.js +122 -0
- package/dist/learning/command-adaptation.js.map +1 -0
- package/dist/learning/consent-picture.d.ts +42 -0
- package/dist/learning/consent-picture.d.ts.map +1 -0
- package/dist/learning/consent-picture.js +53 -0
- package/dist/learning/consent-picture.js.map +1 -0
- package/dist/learning/context-budget.d.ts +37 -6
- package/dist/learning/context-budget.d.ts.map +1 -1
- package/dist/learning/context-budget.js +38 -9
- package/dist/learning/context-budget.js.map +1 -1
- package/dist/learning/decision-log.d.ts +114 -0
- package/dist/learning/decision-log.d.ts.map +1 -0
- package/dist/learning/decision-log.js +296 -0
- package/dist/learning/decision-log.js.map +1 -0
- package/dist/learning/deliverable-class.d.ts.map +1 -1
- package/dist/learning/deliverable-class.js +19 -0
- package/dist/learning/deliverable-class.js.map +1 -1
- package/dist/learning/deliverable-corpus.d.ts +117 -0
- package/dist/learning/deliverable-corpus.d.ts.map +1 -0
- package/dist/learning/deliverable-corpus.js +176 -0
- package/dist/learning/deliverable-corpus.js.map +1 -0
- package/dist/learning/error-repair.d.ts +22 -1
- package/dist/learning/error-repair.d.ts.map +1 -1
- package/dist/learning/error-repair.js +37 -0
- package/dist/learning/error-repair.js.map +1 -1
- package/dist/learning/exhaustion-report.d.ts +136 -0
- package/dist/learning/exhaustion-report.d.ts.map +1 -0
- package/dist/learning/exhaustion-report.js +239 -0
- package/dist/learning/exhaustion-report.js.map +1 -0
- package/dist/learning/failure-bookkeeping.d.ts +16 -0
- package/dist/learning/failure-bookkeeping.d.ts.map +1 -1
- package/dist/learning/failure-bookkeeping.js +51 -5
- package/dist/learning/failure-bookkeeping.js.map +1 -1
- package/dist/learning/gate-friction.d.ts +39 -0
- package/dist/learning/gate-friction.d.ts.map +1 -0
- package/dist/learning/gate-friction.js +91 -0
- package/dist/learning/gate-friction.js.map +1 -0
- package/dist/learning/harness-narration.d.ts +34 -0
- package/dist/learning/harness-narration.d.ts.map +1 -0
- package/dist/learning/harness-narration.js +58 -0
- package/dist/learning/harness-narration.js.map +1 -0
- package/dist/learning/hub-skill-catalog.d.ts.map +1 -1
- package/dist/learning/hub-skill-catalog.js +1 -2
- package/dist/learning/hub-skill-catalog.js.map +1 -1
- package/dist/learning/hybrid-router.d.ts +65 -0
- package/dist/learning/hybrid-router.d.ts.map +1 -1
- package/dist/learning/hybrid-router.js +186 -0
- package/dist/learning/hybrid-router.js.map +1 -1
- package/dist/learning/knowledge-base.d.ts +229 -3
- package/dist/learning/knowledge-base.d.ts.map +1 -1
- package/dist/learning/knowledge-base.js +593 -24
- package/dist/learning/knowledge-base.js.map +1 -1
- package/dist/learning/knowledge-eval.d.ts +171 -0
- package/dist/learning/knowledge-eval.d.ts.map +1 -0
- package/dist/learning/knowledge-eval.js +196 -0
- package/dist/learning/knowledge-eval.js.map +1 -0
- package/dist/learning/knowledge-turn.d.ts +92 -0
- package/dist/learning/knowledge-turn.d.ts.map +1 -0
- package/dist/learning/knowledge-turn.js +190 -0
- package/dist/learning/knowledge-turn.js.map +1 -0
- package/dist/learning/learned-commands.d.ts +64 -0
- package/dist/learning/learned-commands.d.ts.map +1 -0
- package/dist/learning/learned-commands.js +108 -0
- package/dist/learning/learned-commands.js.map +1 -0
- package/dist/learning/lexical-search.d.ts +50 -0
- package/dist/learning/lexical-search.d.ts.map +1 -0
- package/dist/learning/lexical-search.js +111 -0
- package/dist/learning/lexical-search.js.map +1 -0
- package/dist/learning/machine-facts.d.ts +71 -0
- package/dist/learning/machine-facts.d.ts.map +1 -0
- package/dist/learning/machine-facts.js +164 -0
- package/dist/learning/machine-facts.js.map +1 -0
- package/dist/learning/markdown-outline.d.ts +73 -0
- package/dist/learning/markdown-outline.d.ts.map +1 -0
- package/dist/learning/markdown-outline.js +136 -0
- package/dist/learning/markdown-outline.js.map +1 -0
- package/dist/learning/model-first-router.d.ts +33 -1
- package/dist/learning/model-first-router.d.ts.map +1 -1
- package/dist/learning/model-first-router.js +123 -9
- package/dist/learning/model-first-router.js.map +1 -1
- package/dist/learning/model-identity.d.ts +80 -0
- package/dist/learning/model-identity.d.ts.map +1 -0
- package/dist/learning/model-identity.js +115 -0
- package/dist/learning/model-identity.js.map +1 -0
- package/dist/learning/model-registry.d.ts +141 -2
- package/dist/learning/model-registry.d.ts.map +1 -1
- package/dist/learning/model-registry.js +324 -38
- package/dist/learning/model-registry.js.map +1 -1
- package/dist/learning/model-scoring.d.ts.map +1 -1
- package/dist/learning/model-scoring.js +8 -1
- package/dist/learning/model-scoring.js.map +1 -1
- package/dist/learning/model-selection.d.ts.map +1 -1
- package/dist/learning/model-selection.js +41 -0
- package/dist/learning/model-selection.js.map +1 -1
- package/dist/learning/outcome-observation.d.ts +49 -0
- package/dist/learning/outcome-observation.d.ts.map +1 -0
- package/dist/learning/outcome-observation.js +95 -0
- package/dist/learning/outcome-observation.js.map +1 -0
- package/dist/learning/pair-entitlement.d.ts +184 -0
- package/dist/learning/pair-entitlement.d.ts.map +1 -0
- package/dist/learning/pair-entitlement.js +214 -0
- package/dist/learning/pair-entitlement.js.map +1 -0
- package/dist/learning/provider-fallback.d.ts +23 -1
- package/dist/learning/provider-fallback.d.ts.map +1 -1
- package/dist/learning/provider-fallback.js +24 -0
- package/dist/learning/provider-fallback.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +65 -1
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +123 -1
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/requirement-probe.d.ts +55 -0
- package/dist/learning/requirement-probe.d.ts.map +1 -0
- package/dist/learning/requirement-probe.js +77 -0
- package/dist/learning/requirement-probe.js.map +1 -0
- package/dist/learning/resilient-call.d.ts +20 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +42 -4
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/response-usability.d.ts +85 -0
- package/dist/learning/response-usability.d.ts.map +1 -0
- package/dist/learning/response-usability.js +135 -0
- package/dist/learning/response-usability.js.map +1 -0
- package/dist/learning/router-bandit.d.ts +132 -0
- package/dist/learning/router-bandit.d.ts.map +1 -1
- package/dist/learning/router-bandit.js +253 -0
- package/dist/learning/router-bandit.js.map +1 -1
- package/dist/learning/routing-history.d.ts +41 -2
- package/dist/learning/routing-history.d.ts.map +1 -1
- package/dist/learning/routing-history.js.map +1 -1
- package/dist/learning/run-trace.d.ts +21 -0
- package/dist/learning/run-trace.d.ts.map +1 -1
- package/dist/learning/run-trace.js +38 -0
- package/dist/learning/run-trace.js.map +1 -1
- package/dist/learning/session-grant.d.ts +75 -0
- package/dist/learning/session-grant.d.ts.map +1 -0
- package/dist/learning/session-grant.js +112 -0
- package/dist/learning/session-grant.js.map +1 -0
- package/dist/learning/task-model-continuity.d.ts +73 -0
- package/dist/learning/task-model-continuity.d.ts.map +1 -0
- package/dist/learning/task-model-continuity.js +87 -0
- package/dist/learning/task-model-continuity.js.map +1 -0
- package/dist/learning/turn-feedback.d.ts +93 -0
- package/dist/learning/turn-feedback.d.ts.map +1 -0
- package/dist/learning/turn-feedback.js +127 -0
- package/dist/learning/turn-feedback.js.map +1 -0
- package/dist/learning/turn-report.d.ts +104 -2
- package/dist/learning/turn-report.d.ts.map +1 -1
- package/dist/learning/turn-report.js +161 -6
- package/dist/learning/turn-report.js.map +1 -1
- package/dist/learning/verdict-routing.d.ts +51 -0
- package/dist/learning/verdict-routing.d.ts.map +1 -0
- package/dist/learning/verdict-routing.js +122 -0
- package/dist/learning/verdict-routing.js.map +1 -0
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +5 -0
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/manager.d.ts +10 -0
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +20 -0
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/mcp-discovery.d.ts +34 -0
- package/dist/mcp/mcp-discovery.d.ts.map +1 -0
- package/dist/mcp/mcp-discovery.js +71 -0
- package/dist/mcp/mcp-discovery.js.map +1 -0
- package/dist/mcp/mcp-schema-cache.d.ts +17 -0
- package/dist/mcp/mcp-schema-cache.d.ts.map +1 -1
- package/dist/mcp/mcp-schema-cache.js +47 -3
- package/dist/mcp/mcp-schema-cache.js.map +1 -1
- package/dist/mcp/types.d.ts +28 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/tools/ask-user.d.ts.map +1 -1
- package/dist/tools/ask-user.js +4 -0
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/capability-registry.d.ts +150 -0
- package/dist/tools/capability-registry.d.ts.map +1 -0
- package/dist/tools/capability-registry.js +400 -0
- package/dist/tools/capability-registry.js.map +1 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -1
- package/dist/tools/child-agent-runtime.js +19 -5
- package/dist/tools/child-agent-runtime.js.map +1 -1
- package/dist/tools/coding-tools.d.ts +17 -5
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +80 -11
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/command-memo.d.ts +116 -0
- package/dist/tools/command-memo.d.ts.map +1 -0
- package/dist/tools/command-memo.js +202 -0
- package/dist/tools/command-memo.js.map +1 -0
- package/dist/tools/git-tool.d.ts.map +1 -1
- package/dist/tools/git-tool.js +13 -3
- package/dist/tools/git-tool.js.map +1 -1
- package/dist/tools/harness-directive.d.ts +42 -0
- package/dist/tools/harness-directive.d.ts.map +1 -0
- package/dist/tools/harness-directive.js +45 -0
- package/dist/tools/harness-directive.js.map +1 -0
- package/dist/tools/loop-skill-hint.d.ts +74 -174
- package/dist/tools/loop-skill-hint.d.ts.map +1 -1
- package/dist/tools/loop-skill-hint.js +110 -536
- package/dist/tools/loop-skill-hint.js.map +1 -1
- package/dist/tools/mcp-client-tool.d.ts +2 -0
- package/dist/tools/mcp-client-tool.d.ts.map +1 -1
- package/dist/tools/mcp-client-tool.js +3 -0
- package/dist/tools/mcp-client-tool.js.map +1 -1
- package/dist/tools/modality/shared.d.ts +1 -4
- package/dist/tools/modality/shared.d.ts.map +1 -1
- package/dist/tools/modality/shared.js +7 -22
- package/dist/tools/modality/shared.js.map +1 -1
- package/dist/tools/plan-store.d.ts +20 -2
- package/dist/tools/plan-store.d.ts.map +1 -1
- package/dist/tools/plan-store.js +51 -7
- package/dist/tools/plan-store.js.map +1 -1
- package/dist/tools/registry.d.ts +76 -3
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +486 -26
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/remediation-ladder.d.ts.map +1 -1
- package/dist/tools/remediation-ladder.js +8 -0
- package/dist/tools/remediation-ladder.js.map +1 -1
- package/dist/tools/run-cli.d.ts.map +1 -1
- package/dist/tools/run-cli.js +29 -4
- package/dist/tools/run-cli.js.map +1 -1
- package/dist/tools/run-terminal.d.ts +11 -0
- package/dist/tools/run-terminal.d.ts.map +1 -1
- package/dist/tools/run-terminal.js +265 -10
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/tool-loop.d.ts +321 -13
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +867 -66
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/utils/atomic-store.d.ts +53 -0
- package/dist/utils/atomic-store.d.ts.map +1 -0
- package/dist/utils/atomic-store.js +178 -0
- package/dist/utils/atomic-store.js.map +1 -0
- package/dist/utils/binary-probe.d.ts +25 -0
- package/dist/utils/binary-probe.d.ts.map +1 -0
- package/dist/utils/binary-probe.js +48 -0
- package/dist/utils/binary-probe.js.map +1 -0
- package/dist/utils/workspace-path.d.ts +50 -0
- package/dist/utils/workspace-path.d.ts.map +1 -0
- package/dist/utils/workspace-path.js +86 -0
- package/dist/utils/workspace-path.js.map +1 -0
- package/dist/web-dashboard/chat-console.d.ts +24 -0
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +38 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/project-context.d.ts +27 -2
- package/dist/web-dashboard/project-context.d.ts.map +1 -1
- package/dist/web-dashboard/project-context.js +32 -2
- package/dist/web-dashboard/project-context.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +11 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +362 -11
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +170 -1
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.d.ts +11 -2
- package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.js +24 -12
- package/dist/web-dashboard/workspace-guard.js.map +1 -1
- package/dist/web-dashboard/workspace-resolution.d.ts +87 -0
- package/dist/web-dashboard/workspace-resolution.d.ts.map +1 -0
- package/dist/web-dashboard/workspace-resolution.js +105 -0
- package/dist/web-dashboard/workspace-resolution.js.map +1 -0
- package/package.json +1 -1
- package/src/web-dashboard/public/assets/index-zjbdJnO-.js +210 -0
- package/src/web-dashboard/public/assets/index-zjbdJnO-.js.map +1 -0
- package/src/web-dashboard/public/index.html +1 -1
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js +0 -210
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js.map +0 -1
package/dist/cli/model.js
CHANGED
|
@@ -25,16 +25,26 @@ import inquirer from 'inquirer';
|
|
|
25
25
|
import { resolveNuviraHome } from '../config/paths.js';
|
|
26
26
|
import { BaseCommand } from './commands.js';
|
|
27
27
|
import { showModelPicker } from './model-picker.js';
|
|
28
|
+
import { CATALOG_PROVIDER_IDS } from '../inference/provider-catalog.js';
|
|
28
29
|
import { getPluginRegistry } from '../plugins/registry.js';
|
|
29
30
|
import { recommendModel } from '../learning/model-router.js';
|
|
30
31
|
import { getModelBadge } from '../inference/model-catalog.js';
|
|
31
32
|
import { getHybridRouter } from '../learning/hybrid-router.js';
|
|
32
33
|
import { AUTO_MODEL, AUTO_PROVIDER, getAutoRouter, isAutoModel, isAutoProvider, PIIPolicyError, GovernancePolicyError, } from '../learning/auto-router.js';
|
|
33
34
|
import { buildAutoResolveOptions } from '../learning/resolve-options.js';
|
|
35
|
+
import { parseRequestSync } from '../nlu/parser.js';
|
|
36
|
+
import { resolveDispatch } from '../nlu/actions.js';
|
|
34
37
|
import { recordRoutingDecision, getExplainSnapshots } from '../learning/routing-history.js';
|
|
35
38
|
import { diffRoutingDecisions, formatDecisionDiff } from '../learning/decision-diff.js';
|
|
36
39
|
import { getRouterBandit, COMPLEXITY_BUCKETS, } from '../learning/router-bandit.js';
|
|
37
40
|
import { getQuotaLedger } from '../learning/quota-ledger.js';
|
|
41
|
+
import { getModelRegistry } from '../learning/model-registry.js';
|
|
42
|
+
import { ENTITLEMENT_LABEL, areTwins, classifyPairEntitlement, entitlementNote, } from '../learning/pair-entitlement.js';
|
|
43
|
+
import { identityKey, identityProvenance } from '../learning/model-identity.js';
|
|
44
|
+
import { DEFAULT_PRIORS, capabilityLines, deriveTier, effectiveParameter, } from '../learning/capability-evidence.js';
|
|
45
|
+
import { externalPriorsFor } from '../learning/catalog-feed.js';
|
|
46
|
+
import { acceptanceSummary, formatAcceptanceSummary } from '../learning/acceptance-model.js';
|
|
47
|
+
import { getProviderFallback } from '../learning/provider-fallback.js';
|
|
38
48
|
import { getRouterPromotion, DEFAULT_MIN_PROMOTION_DECISIONS, } from '../learning/router-promotion.js';
|
|
39
49
|
import { getMlRouter } from '../learning/ml-router.js';
|
|
40
50
|
import { logger } from '../utils/logger.js';
|
|
@@ -124,6 +134,17 @@ const EXPLAIN_SAMPLES = [
|
|
|
124
134
|
{ label: '🟠 complex', task: 'design a distributed event-driven microservices architecture' },
|
|
125
135
|
{ label: '🔴 critical', task: 'deploy to production with zero downtime' },
|
|
126
136
|
];
|
|
137
|
+
/** Repeatable `--exclude-provider <provider>` collector. */
|
|
138
|
+
function collectProvider(value, previous) {
|
|
139
|
+
previous.push(value);
|
|
140
|
+
return previous;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* A session failure sinks a provider by scoring exactly like a live cooldown
|
|
144
|
+
* (`circuitBreakerStatus`). Any positive value parks it, so this is not a real
|
|
145
|
+
* duration — it says "this provider is out for this decision".
|
|
146
|
+
*/
|
|
147
|
+
const SESSION_EXCLUDE_COOLDOWN_MS = 60_000;
|
|
127
148
|
// ─── ModelCommand ───────────────────────────────────────────────────────────
|
|
128
149
|
export class ModelCommand extends BaseCommand {
|
|
129
150
|
create() {
|
|
@@ -159,7 +180,15 @@ export class ModelCommand extends BaseCommand {
|
|
|
159
180
|
.option('-a, --agent <type>', 'Agent type to route for (default: chat)', 'chat')
|
|
160
181
|
.option('-j, --json', 'Output as JSON (for scripting and CI)', false)
|
|
161
182
|
.option('--since <ref>', 'P3-M3.3: diff against a previous decision — an explain id, @n (nth most recent explain), or an epoch-ms timestamp', undefined)
|
|
162
|
-
.
|
|
183
|
+
.option('--context-tokens <n>', 'Item 14: the prompt token count the runtime would have seen (context preflight basis) — reproduce a decision made with a large history', undefined)
|
|
184
|
+
.option('--exclude-provider <provider>', 'Item 14: a provider already failed THIS SESSION, repeatable — it sinks by scoring exactly as the runtime excludes it', collectProvider, [])
|
|
185
|
+
.action((task, opts) => this.showExplain(task, {
|
|
186
|
+
agent: opts.agent,
|
|
187
|
+
json: opts.json,
|
|
188
|
+
since: opts.since,
|
|
189
|
+
contextTokens: opts.contextTokens !== undefined ? Number(opts.contextTokens) : undefined,
|
|
190
|
+
excludeProviders: opts.excludeProvider,
|
|
191
|
+
}));
|
|
163
192
|
cmd
|
|
164
193
|
.command('health')
|
|
165
194
|
.description('Quick health check for the currently active provider')
|
|
@@ -197,7 +226,33 @@ export class ModelCommand extends BaseCommand {
|
|
|
197
226
|
}
|
|
198
227
|
// ── Subcommand: list ───────────────────────────────────────────────────
|
|
199
228
|
async listProviders(opts) {
|
|
200
|
-
|
|
229
|
+
/**
|
|
230
|
+
* The provider set the ROUTER uses — not a hand-written list of five.
|
|
231
|
+
*
|
|
232
|
+
* `rankAvailableProviders` (the router's source of truth) builds its candidate
|
|
233
|
+
* set from the catalog PLUS whatever the user configured. A literal array here
|
|
234
|
+
* made `model list` disagree with routing about which providers even exist:
|
|
235
|
+
* measured live, a machine whose turns were served by `deepseek` — with the
|
|
236
|
+
* debug header and the trace both naming it — printed only
|
|
237
|
+
* local/groq/nim/gemini/openrouter, so `deepseek` (and every other catalog
|
|
238
|
+
* provider: bedrock, openai, mistral, …) was invisible in the one command whose
|
|
239
|
+
* whole job is "what can I use?". One source, one inventory.
|
|
240
|
+
*
|
|
241
|
+
* The familiar five keep their place at the top so the table does not reorder
|
|
242
|
+
* itself for existing users; the rest follow in catalog order.
|
|
243
|
+
*/
|
|
244
|
+
const builtinTypes = (() => {
|
|
245
|
+
const preferred = ['local', 'groq', 'nim', 'gemini', 'openrouter'];
|
|
246
|
+
let configured = [];
|
|
247
|
+
try {
|
|
248
|
+
configured = Object.keys(this.configManager.getAll().providers ?? {});
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// Best-effort — an unreadable config must not empty the table.
|
|
252
|
+
}
|
|
253
|
+
const all = new Set([...preferred, ...CATALOG_PROVIDER_IDS, ...configured]);
|
|
254
|
+
return [...all];
|
|
255
|
+
})();
|
|
201
256
|
const registry = getPluginRegistry();
|
|
202
257
|
const pluginTypes = registry.getAllPlugins().map((p) => p.getProviderType());
|
|
203
258
|
const active = readActiveModelState();
|
|
@@ -291,7 +346,14 @@ export class ModelCommand extends BaseCommand {
|
|
|
291
346
|
console.log(' ┌──────────────────────────────────┬──────────┬──────────┬──────────────────┐');
|
|
292
347
|
console.log(' │ Provider │ Status │ Available│ Model │');
|
|
293
348
|
console.log(' ├──────────────────────────────────┼──────────┼──────────┼──────────────────┤');
|
|
294
|
-
|
|
349
|
+
// Usable first. The table now carries the WHOLE catalog (so it agrees with
|
|
350
|
+
// routing), which means most rows are providers this machine has no key for.
|
|
351
|
+
// Putting the callable ones on top keeps the answer to "what can I use?" in
|
|
352
|
+
// the first few lines rather than below a dozen `Needs key` rows. Stable
|
|
353
|
+
// sort, so the familiar five keep their relative order.
|
|
354
|
+
const rankOf = (r) => r.available ? 0 : r.configured ? 1 : 2;
|
|
355
|
+
const ordered = [...results].sort((a, b) => rankOf(a) - rankOf(b));
|
|
356
|
+
for (const r of ordered) {
|
|
295
357
|
const name = `${r.icon} ${r.label}`.padEnd(30).slice(0, 30);
|
|
296
358
|
const status = r.isActive ? '✅ Active' : r.configured ? '⚙️ Ready' : '⏳ Needs key';
|
|
297
359
|
const avail = r.available ? '✅' : '⛔';
|
|
@@ -304,6 +366,45 @@ export class ModelCommand extends BaseCommand {
|
|
|
304
366
|
logger.success(`Active: ${active.provider}/${active.model}`);
|
|
305
367
|
console.log(` (set ${new Date(active.updatedAt).toLocaleString()})`);
|
|
306
368
|
}
|
|
369
|
+
// ── A1: the SAME model, opposite verdicts ──────────────────────────────
|
|
370
|
+
// Two rows for one model can disagree completely (`openrouter` refuses a
|
|
371
|
+
// model `deepseek` serves), and the table above shows only each provider's own
|
|
372
|
+
// default — so the pair was invisible. Print only the groups whose verdicts
|
|
373
|
+
// genuinely DISAGREE: same identity, different answer about whether it can be
|
|
374
|
+
// called. Each verdict is read from its own row (identity groups capability
|
|
375
|
+
// and legibility, never availability).
|
|
376
|
+
try {
|
|
377
|
+
const registry = getModelRegistry();
|
|
378
|
+
const rows = registry.getTrackedProviders().flatMap((p) => registry.getAllModelsForProvider(p));
|
|
379
|
+
const groups = new Map();
|
|
380
|
+
for (const r of rows) {
|
|
381
|
+
const key = identityKey(r.model);
|
|
382
|
+
if (!key)
|
|
383
|
+
continue;
|
|
384
|
+
const list = groups.get(key);
|
|
385
|
+
if (list)
|
|
386
|
+
list.push(r);
|
|
387
|
+
else
|
|
388
|
+
groups.set(key, [r]);
|
|
389
|
+
}
|
|
390
|
+
const mixed = [...groups.values()].filter((g) => new Set(g.map((r) => classifyPairEntitlement(r))).size > 1);
|
|
391
|
+
if (mixed.length > 0) {
|
|
392
|
+
console.log('');
|
|
393
|
+
logger.highlight(' ── The same model, different verdicts (A1) ──');
|
|
394
|
+
for (const g of mixed.slice(0, 5)) {
|
|
395
|
+
console.log(` ${g[0].model}`);
|
|
396
|
+
for (const r of g) {
|
|
397
|
+
const e = classifyPairEntitlement(r);
|
|
398
|
+
console.log(` ${ENTITLEMENT_LABEL[e]} ${r.provider} — ${entitlementNote(e, r)}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (mixed.length > 5)
|
|
402
|
+
console.log(` … and ${mixed.length - 5} more.`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
catch {
|
|
406
|
+
// Best-effort — this section must never break `model list`.
|
|
407
|
+
}
|
|
307
408
|
console.log('');
|
|
308
409
|
logger.info('Run `nuvira model switch` to change the active provider/model.');
|
|
309
410
|
logger.info('Run `nuvira doctor` for full diagnostic checks.');
|
|
@@ -505,9 +606,13 @@ export class ModelCommand extends BaseCommand {
|
|
|
505
606
|
showExplain(task, opts) {
|
|
506
607
|
const router = getAutoRouter();
|
|
507
608
|
const agentType = opts.agent || 'chat';
|
|
609
|
+
const runtime = {
|
|
610
|
+
contextTokens: opts.contextTokens,
|
|
611
|
+
excludeProviders: opts.excludeProviders,
|
|
612
|
+
};
|
|
508
613
|
if (opts.json) {
|
|
509
614
|
try {
|
|
510
|
-
console.log(JSON.stringify(this.buildExplainJSON(router, agentType, task, opts.since), null, 2));
|
|
615
|
+
console.log(JSON.stringify(this.buildExplainJSON(router, agentType, task, opts.since, runtime), null, 2));
|
|
511
616
|
}
|
|
512
617
|
catch (err) {
|
|
513
618
|
// A PII/governance policy block must not crash the JSON contract —
|
|
@@ -526,6 +631,14 @@ export class ModelCommand extends BaseCommand {
|
|
|
526
631
|
console.log('');
|
|
527
632
|
logger.highlight('═══ Auto Model Routing — Explain ═══');
|
|
528
633
|
console.log('');
|
|
634
|
+
// Item 14 — say plainly what this decision could NOT see, so an offline
|
|
635
|
+
// answer is never read as the live one. `explain` has no session: a
|
|
636
|
+
// continuation's routing text and the session's failed-provider set exist
|
|
637
|
+
// only at runtime, and both change the pick.
|
|
638
|
+
logger.info(`Runtime inputs: context ${runtime.contextTokens !== undefined ? `~${runtime.contextTokens} tokens` : '(estimated from the task)'} · ` +
|
|
639
|
+
`excluded providers: ${runtime.excludeProviders?.length ? runtime.excludeProviders.join(', ') : 'none'}`);
|
|
640
|
+
logger.info('A live session also carries its own failed-provider set; pass --exclude-provider to reproduce it, and --context-tokens to match a large history.');
|
|
641
|
+
console.log('');
|
|
529
642
|
if (task) {
|
|
530
643
|
logger.info(`Task: "${task}" · Agent: ${agentType}`);
|
|
531
644
|
console.log('');
|
|
@@ -533,10 +646,10 @@ export class ModelCommand extends BaseCommand {
|
|
|
533
646
|
// P3-M3.3: `--since <ref>` renders a before → after diff against a
|
|
534
647
|
// previous explain snapshot instead of the full decision view.
|
|
535
648
|
if (opts.since) {
|
|
536
|
-
this.renderRoutingDecisionDiff(router, agentType, task, opts.since);
|
|
649
|
+
this.renderRoutingDecisionDiff(router, agentType, task, opts.since, runtime);
|
|
537
650
|
}
|
|
538
651
|
else {
|
|
539
|
-
this.renderRoutingDecision(router, agentType, task);
|
|
652
|
+
this.renderRoutingDecision(router, agentType, task, false, runtime);
|
|
540
653
|
}
|
|
541
654
|
}
|
|
542
655
|
catch (err) {
|
|
@@ -560,7 +673,7 @@ export class ModelCommand extends BaseCommand {
|
|
|
560
673
|
for (const s of EXPLAIN_SAMPLES) {
|
|
561
674
|
logger.highlight(` ${s.label} — "${s.task}"`);
|
|
562
675
|
try {
|
|
563
|
-
this.renderRoutingDecision(router, agentType, s.task, true);
|
|
676
|
+
this.renderRoutingDecision(router, agentType, s.task, true, runtime);
|
|
564
677
|
}
|
|
565
678
|
catch (err) {
|
|
566
679
|
// A single sample that violates a PII/governance policy renders the
|
|
@@ -599,9 +712,9 @@ export class ModelCommand extends BaseCommand {
|
|
|
599
712
|
* Single task → one decision object; no task → all 5 sample complexities.
|
|
600
713
|
* Includes effective per-provider pricing (with override flags).
|
|
601
714
|
*/
|
|
602
|
-
buildExplainJSON(router, agentType, task, since) {
|
|
715
|
+
buildExplainJSON(router, agentType, task, since, runtime = {}) {
|
|
603
716
|
const toJSON = (t, agent) => {
|
|
604
|
-
const d =
|
|
717
|
+
const d = this.resolveExplainDecision(router, agent, t, runtime);
|
|
605
718
|
const snapshot = this.buildSnapshot(d);
|
|
606
719
|
// Record the explain snapshot for the dashboard audit trail + usage stats
|
|
607
720
|
// (JSON mode returns early in showExplain, so this is the only hook here)
|
|
@@ -678,6 +791,12 @@ export class ModelCommand extends BaseCommand {
|
|
|
678
791
|
: undefined,
|
|
679
792
|
pricing,
|
|
680
793
|
explanation: d.explanation,
|
|
794
|
+
// Item 14 — the runtime inputs this decision was reproduced with, so a
|
|
795
|
+
// script can tell a hypothetical from a reproduced live decision.
|
|
796
|
+
runtimeInputs: {
|
|
797
|
+
contextTokens: runtime.contextTokens,
|
|
798
|
+
excludedProviders: runtime.excludeProviders ?? [],
|
|
799
|
+
},
|
|
681
800
|
...(diff ? { diff } : {}),
|
|
682
801
|
};
|
|
683
802
|
};
|
|
@@ -688,6 +807,62 @@ export class ModelCommand extends BaseCommand {
|
|
|
688
807
|
decisions: EXPLAIN_SAMPLES.map((s) => toJSON(s.task, agentType)),
|
|
689
808
|
};
|
|
690
809
|
}
|
|
810
|
+
/**
|
|
811
|
+
* D4 — resolve an explain decision through the SAME options the RUNTIME uses.
|
|
812
|
+
*
|
|
813
|
+
* `chat.ts` layers two things on top of the shared resolve-options assembly
|
|
814
|
+
* before calling the router, and `explain` passed neither:
|
|
815
|
+
*
|
|
816
|
+
* - `circuitBreakerStatus`, which is what SUNKS a provider sitting in a
|
|
817
|
+
* cooling-down circuit breaker. Without it every row looked healthy and
|
|
818
|
+
* `explain` could name a provider the runtime would never serve.
|
|
819
|
+
* - the NLU `taskIntentHint`, which the runtime derives from the same task
|
|
820
|
+
* string via `parseRequestSync`/`resolveDispatch` and which overrides the
|
|
821
|
+
* profile's intent (e.g. a creative ask), so the two could classify one
|
|
822
|
+
* task differently.
|
|
823
|
+
*
|
|
824
|
+
* Sharing the assembly is the only way the two can agree: both divergences
|
|
825
|
+
* were options the explain path never passed. The NLU derivation is
|
|
826
|
+
* deterministic in the task text, so seeding it here is reproducing the
|
|
827
|
+
* runtime's assembly, not guessing.
|
|
828
|
+
*/
|
|
829
|
+
resolveExplainDecision(router, agentType, task, runtime = {}) {
|
|
830
|
+
let circuitBreakerStatus = [];
|
|
831
|
+
try {
|
|
832
|
+
circuitBreakerStatus = getProviderFallback(this.configManager).getCircuitBreakerStatus();
|
|
833
|
+
}
|
|
834
|
+
catch {
|
|
835
|
+
// Best-effort — a breaker read must never break `explain`.
|
|
836
|
+
}
|
|
837
|
+
// Item 14 — the session's failed-provider set exists only at runtime, so
|
|
838
|
+
// `explain` could not see it and could name a provider the session had
|
|
839
|
+
// already parked. Fold each caller-named exclusion in as an active cooldown:
|
|
840
|
+
// the router sinks it by scoring, exactly as it sinks a live failure.
|
|
841
|
+
if (runtime.excludeProviders?.length) {
|
|
842
|
+
const byProvider = new Map(circuitBreakerStatus.map((c) => [c.provider, c.cooldownRemaining]));
|
|
843
|
+
for (const p of runtime.excludeProviders) {
|
|
844
|
+
byProvider.set(p, Math.max(byProvider.get(p) ?? 0, SESSION_EXCLUDE_COOLDOWN_MS));
|
|
845
|
+
}
|
|
846
|
+
circuitBreakerStatus = [...byProvider].map(([provider, cooldownRemaining]) => ({ provider, cooldownRemaining }));
|
|
847
|
+
}
|
|
848
|
+
// Same NLU seed as the runtime: one parser call on the same text, so an
|
|
849
|
+
// intent the runtime honours is never invisible to `explain`.
|
|
850
|
+
let taskIntentHint;
|
|
851
|
+
try {
|
|
852
|
+
taskIntentHint = resolveDispatch(parseRequestSync(task)).taskIntentHint;
|
|
853
|
+
}
|
|
854
|
+
catch {
|
|
855
|
+
// Best-effort — a parse failure must never break `explain`.
|
|
856
|
+
}
|
|
857
|
+
return router.resolve(agentType, task, {
|
|
858
|
+
// Item 14 — the context preflight is part of the pickup, so the token
|
|
859
|
+
// count the runtime saw must reach it; otherwise `explain` estimates
|
|
860
|
+
// from the task and can name a different provider under a large history.
|
|
861
|
+
...buildAutoResolveOptions(this.configManager, { contextHintTokens: runtime.contextTokens }),
|
|
862
|
+
circuitBreakerStatus,
|
|
863
|
+
...(taskIntentHint ? { taskIntentHint } : {}),
|
|
864
|
+
}, this.configManager);
|
|
865
|
+
}
|
|
691
866
|
/**
|
|
692
867
|
* Build a RoutingSnapshot from a live decision — the ranked breakdown with
|
|
693
868
|
* dimensions and governance context, persisted with explain decisions so
|
|
@@ -750,9 +925,9 @@ export class ModelCommand extends BaseCommand {
|
|
|
750
925
|
* P3-M3.3: resolve the previous explain decision and render the before →
|
|
751
926
|
* after diff for the current decision (which is also recorded).
|
|
752
927
|
*/
|
|
753
|
-
renderRoutingDecisionDiff(router, agentType, task, ref) {
|
|
928
|
+
renderRoutingDecisionDiff(router, agentType, task, ref, runtime = {}) {
|
|
754
929
|
const prev = this.resolveExplainRef(ref);
|
|
755
|
-
const decision =
|
|
930
|
+
const decision = this.resolveExplainDecision(router, agentType, task, runtime);
|
|
756
931
|
const snapshot = this.buildSnapshot(decision);
|
|
757
932
|
recordRoutingDecision({
|
|
758
933
|
source: 'explain',
|
|
@@ -782,8 +957,8 @@ export class ModelCommand extends BaseCommand {
|
|
|
782
957
|
console.log('');
|
|
783
958
|
}
|
|
784
959
|
/** Render a single routing decision (compact or detailed). */
|
|
785
|
-
renderRoutingDecision(router, agentType, task, compact = false) {
|
|
786
|
-
const decision =
|
|
960
|
+
renderRoutingDecision(router, agentType, task, compact = false, runtime = {}) {
|
|
961
|
+
const decision = this.resolveExplainDecision(router, agentType, task, runtime);
|
|
787
962
|
// Record the explain snapshot for the dashboard audit trail + usage stats
|
|
788
963
|
recordRoutingDecision({
|
|
789
964
|
source: 'explain',
|
|
@@ -809,9 +984,17 @@ export class ModelCommand extends BaseCommand {
|
|
|
809
984
|
}
|
|
810
985
|
console.log('');
|
|
811
986
|
logger.highlight(' ── Ranked providers ──');
|
|
987
|
+
// D5 — the list is ordered by AVAILABILITY FIRST (a cooling-down provider
|
|
988
|
+
// sinks, then a quota-parked one, and only then by score within each group),
|
|
989
|
+
// because that IS the routing precedence. But only `score` was printed, so a
|
|
990
|
+
// lower-scored healthy row sitting above a higher-scored cooling one read as
|
|
991
|
+
// an unsorted list (measured: 0.351, 0.465, 0.397, 0.396). The ranking was
|
|
992
|
+
// never wrong — the header was silent about the key. State it, so the display
|
|
993
|
+
// can never appear to contradict the numbers it prints.
|
|
994
|
+
console.log(' (ordered availability-first — cooling-down, then quota-parked, then score within each group)');
|
|
812
995
|
decision.ranked.forEach((r, i) => {
|
|
813
996
|
const mark = r.provider === decision.provider ? '✅' : ' ';
|
|
814
|
-
const cd = r.inCooldown ? ' (circuit-breaker cooldown)' : '';
|
|
997
|
+
const cd = r.inCooldown ? ' (circuit-breaker cooldown)' : r.quotaParked ? ' (quota-parked)' : '';
|
|
815
998
|
const fit = r.capabilityFit !== undefined ? ` 🎯 fit ${Math.round(r.capabilityFit * 100)}%` : '';
|
|
816
999
|
// M2.2/visibility: cost source on EVERY ranked row — 📏 measured (with
|
|
817
1000
|
// the real wire-token basis) or 📐 estimated (length-based default).
|
|
@@ -833,6 +1016,103 @@ export class ModelCommand extends BaseCommand {
|
|
|
833
1016
|
console.log('');
|
|
834
1017
|
logger.success(` Decision: ${decision.provider}/${decision.model}`);
|
|
835
1018
|
console.log(` ${decision.explanation}`);
|
|
1019
|
+
// D7 — PAIR ENTITLEMENT (2026-10-07). Rank said WHICH model; it never said
|
|
1020
|
+
// whether this ACCOUNT may call it. The reported case was four providers
|
|
1021
|
+
// offering one model where only one key had access — identical ranks, so the
|
|
1022
|
+
// decision was not explainable from the ranking at all. Print the verdict for
|
|
1023
|
+
// the chosen pair, and every same-model twin on another provider with ITS
|
|
1024
|
+
// OWN verdict, so "why this provider and not that one" is answerable from the
|
|
1025
|
+
// output instead of from the registry file. Twins are grouped by the honest
|
|
1026
|
+
// exact/bare-id rule (`areTwins`), and each verdict is read from its own row —
|
|
1027
|
+
// never inherited from a sibling.
|
|
1028
|
+
try {
|
|
1029
|
+
const registry = getModelRegistry();
|
|
1030
|
+
const chosenEntry = registry.getEntry(decision.provider, decision.model);
|
|
1031
|
+
const chosen = classifyPairEntitlement(chosenEntry);
|
|
1032
|
+
const twins = registry
|
|
1033
|
+
.getTrackedProviders()
|
|
1034
|
+
.flatMap((p) => registry.getAllModelsForProvider(p))
|
|
1035
|
+
.filter((e) => e.provider !== decision.provider && areTwins(e.model, decision.model));
|
|
1036
|
+
if (chosen !== 'funded' || twins.length > 0) {
|
|
1037
|
+
console.log('');
|
|
1038
|
+
logger.highlight(' ── Pair entitlement ──');
|
|
1039
|
+
console.log(` ${ENTITLEMENT_LABEL[chosen]} ${decision.provider}/${decision.model} — ${entitlementNote(chosen, chosenEntry)}`);
|
|
1040
|
+
if (twins.length > 0) {
|
|
1041
|
+
// WHERE the grouping came from: a declared alias is an assertion, the
|
|
1042
|
+
// bare-id rule is a derivation, and a reader must be able to tell them
|
|
1043
|
+
// apart (`learning/model-identity.ts`).
|
|
1044
|
+
const provenance = identityProvenance(decision.model);
|
|
1045
|
+
console.log(` (grouped as the same model${provenance ? ` — ${provenance}` : ' — exact/bare id rule'})`);
|
|
1046
|
+
}
|
|
1047
|
+
for (const t of twins) {
|
|
1048
|
+
const e = classifyPairEntitlement(t);
|
|
1049
|
+
console.log(` ${ENTITLEMENT_LABEL[e]} ${t.provider}/${t.model} — ${entitlementNote(e, t)}`);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
catch {
|
|
1054
|
+
// Best-effort — an audit section must never break `model explain`.
|
|
1055
|
+
}
|
|
1056
|
+
// Bundle 3b — CAPABILITY BY MEASUREMENT. The scorecard the decision was made
|
|
1057
|
+
// from, in the terms the user asked for: five named parameters, each with its
|
|
1058
|
+
// SAMPLE COUNT, so a number can be weighed instead of trusted. A parameter on
|
|
1059
|
+
// 0 samples is the declared prior by definition (`capability-evidence.ts`),
|
|
1060
|
+
// which is why it is labelled rather than hidden — a bare number with no
|
|
1061
|
+
// basis was the defect, and the same number printed as "prior" is honest.
|
|
1062
|
+
try {
|
|
1063
|
+
const router = getAutoRouter();
|
|
1064
|
+
const registry = getModelRegistry();
|
|
1065
|
+
const base = router.getCapabilities(decision.provider);
|
|
1066
|
+
const record = registry.getCapability(decision.provider, decision.model);
|
|
1067
|
+
// §6 — the external catalogue supplies `cost`/`ecosystem` PRIORS only (never measurements), and
|
|
1068
|
+
// only while the feed is switched on; `externalPriorsFor` enforces that gate itself. Each one
|
|
1069
|
+
// carries the source it came from, so the scorecard can print a borrowed number AS borrowed.
|
|
1070
|
+
const external = externalPriorsFor(decision.provider, decision.model);
|
|
1071
|
+
const externalPriors = {};
|
|
1072
|
+
const priorLabels = {};
|
|
1073
|
+
for (const p of external) {
|
|
1074
|
+
externalPriors[p.parameter] = p.value;
|
|
1075
|
+
priorLabels[p.parameter] = { source: p.source, fetchedAt: p.fetchedAt };
|
|
1076
|
+
}
|
|
1077
|
+
const priors = {
|
|
1078
|
+
accuracy: base.reasoning,
|
|
1079
|
+
performance: base.speed,
|
|
1080
|
+
...externalPriors,
|
|
1081
|
+
};
|
|
1082
|
+
// `accuracy`'s prior is the provider's own declared baseline (the same one
|
|
1083
|
+
// the router's floor uses); anything the feed supplied beats the declared default, so the TIER
|
|
1084
|
+
// below is derived from the same value the line above prints — they cannot disagree.
|
|
1085
|
+
const view = (parameter) => parameter === 'accuracy'
|
|
1086
|
+
? effectiveParameter(record, 'accuracy', base.reasoning)
|
|
1087
|
+
: effectiveParameter(record, parameter, priors[parameter] ?? DEFAULT_PRIORS[parameter] ?? 0);
|
|
1088
|
+
console.log('');
|
|
1089
|
+
logger.highlight(' ── Capability scorecard (measured) ──');
|
|
1090
|
+
console.log(` ${decision.provider}/${decision.model}`);
|
|
1091
|
+
for (const line of capabilityLines(record, priors, priorLabels))
|
|
1092
|
+
console.log(` ${line}`);
|
|
1093
|
+
console.log(` tier ${deriveTier({ accuracy: view('accuracy'), robustness: view('robustness'), ecosystem: view('ecosystem') })}`);
|
|
1094
|
+
console.log(' (0 samples = the declared prior; values fold in real turns, calls and latencies — never from the model id)');
|
|
1095
|
+
}
|
|
1096
|
+
catch {
|
|
1097
|
+
// Best-effort — an audit section must never break `model explain`.
|
|
1098
|
+
}
|
|
1099
|
+
// Bundle 31/33 — ACCEPTANCE BY MEASUREMENT, read-only. Rendered through the
|
|
1100
|
+
// SAME `formatAcceptanceSummary` that `nuvira rate --stats` and the dashboard
|
|
1101
|
+
// Trace card use, so all three surfaces describe the one corpus identically. The
|
|
1102
|
+
// decision's own pair is focused first; the harness-level fit
|
|
1103
|
+
// `P(accepted | features)` follows. NOTHING routes on it, and when the sample is
|
|
1104
|
+
// too thin it says WHY instead of printing a number that would read as one.
|
|
1105
|
+
try {
|
|
1106
|
+
const pairKey = `${decision.provider}/${decision.model}`;
|
|
1107
|
+
console.log('');
|
|
1108
|
+
logger.highlight(' ── Acceptance (labelled turns, read-only) ──');
|
|
1109
|
+
for (const line of formatAcceptanceSummary(acceptanceSummary(), pairKey)) {
|
|
1110
|
+
console.log(` ${line}`);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
catch {
|
|
1114
|
+
// Best-effort — an audit section must never break `model explain`.
|
|
1115
|
+
}
|
|
836
1116
|
// M2.4: governance transparency — show policy-eliminated providers so the
|
|
837
1117
|
// user sees WHY a provider is absent from the ranking (not just that it
|
|
838
1118
|
// is). Renders only when the admin policy actually blocked something.
|