ultimate-pi 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/harness-debate-plan/SKILL.md +1 -1
- package/.agents/skills/harness-decisions/SKILL.md +2 -3
- package/.agents/skills/harness-governor/SKILL.md +6 -5
- package/.agents/skills/harness-orchestration/SKILL.md +4 -4
- package/.agents/skills/harness-review/SKILL.md +7 -7
- package/.agents/skills/harness-sentrux-setup/SKILL.md +4 -3
- package/.agents/skills/harness-steer/SKILL.md +1 -1
- package/.agents/skills/sentrux/SKILL.md +9 -9
- package/.pi/PACKAGING.md +4 -4
- package/.pi/SYSTEM.md +54 -120
- package/.pi/agents/harness/incident-recorder.md +0 -1
- package/.pi/agents/harness/planning/decompose.md +1 -3
- package/.pi/agents/harness/planning/execution-plan-author.md +0 -2
- package/.pi/agents/harness/planning/hypothesis-validator.md +0 -2
- package/.pi/agents/harness/planning/hypothesis.md +0 -2
- package/.pi/agents/harness/planning/implementation-researcher.md +0 -2
- package/.pi/agents/harness/planning/plan-adversary.md +0 -2
- package/.pi/agents/harness/planning/plan-evaluator.md +1 -3
- package/.pi/agents/harness/planning/planning-context.md +0 -2
- package/.pi/agents/harness/planning/review-integrator.md +0 -2
- package/.pi/agents/harness/planning/sprint-contract-auditor.md +0 -2
- package/.pi/agents/harness/planning/stack-researcher.md +0 -2
- package/.pi/agents/harness/{adversary.md → reviewing/adversary.md} +0 -2
- package/.pi/agents/harness/{evaluator.md → reviewing/evaluator.md} +0 -2
- package/.pi/agents/harness/{tie-breaker.md → reviewing/tie-breaker.md} +0 -2
- package/.pi/agents/harness/{executor.md → running/executor.md} +0 -2
- package/.pi/agents/harness/sentrux-bootstrap.md +0 -1
- package/.pi/agents/harness/sentrux-steward.md +0 -2
- package/.pi/agents/harness/trace-librarian.md +0 -1
- package/.pi/extensions/00-harness-project-control.ts +133 -0
- package/.pi/extensions/00-posthog-network-bootstrap.ts +1 -1
- package/.pi/extensions/agt-kill-switch.ts +57 -0
- package/.pi/extensions/agt-prompt-guard.ts +32 -0
- package/.pi/extensions/budget-guard.ts +2 -0
- package/.pi/extensions/custom-footer.ts +46 -145
- package/.pi/extensions/custom-header.ts +1 -1
- package/.pi/extensions/custom-system-prompt.ts +1 -1
- package/.pi/extensions/debate-orchestrator.ts +7 -5
- package/.pi/extensions/harness-ask-user.ts +8 -8
- package/.pi/extensions/harness-debate-tools.ts +27 -43
- package/.pi/extensions/harness-lens.ts +94 -0
- package/.pi/extensions/harness-live-widget.ts +33 -2
- package/.pi/extensions/harness-plan-approval.ts +12 -12
- package/.pi/extensions/harness-run-context.ts +1214 -852
- package/.pi/extensions/harness-subagent-governance.ts +8 -0
- package/.pi/extensions/harness-subagent-submit.ts +36 -164
- package/.pi/extensions/harness-subagents.ts +4 -4
- package/.pi/extensions/harness-telemetry.ts +3 -1
- package/.pi/extensions/harness-web-tools.ts +3 -3
- package/.pi/extensions/observation-bus.ts +2 -0
- package/.pi/extensions/policy-gate.ts +27 -5
- package/.pi/extensions/review-integrity.ts +91 -10
- package/.pi/extensions/sentrux-rules-sync.ts +3 -1
- package/.pi/extensions/subagent-governance.ts +92 -0
- package/.pi/extensions/test-diff-integrity.ts +1 -0
- package/.pi/extensions/trace-recorder.ts +3 -1
- package/.pi/extensions/{ultimate-pi-vcc.ts → vcc-compaction.ts} +1 -1
- package/.pi/harness/README.md +6 -2
- package/.pi/harness/agents.manifest.json +38 -49
- package/.pi/harness/agents.policy.yaml +275 -0
- package/.pi/harness/corpus/graphify-kb-updater.config.json +55 -0
- package/.pi/harness/docs/adrs/0006-sentrux-dual-layer.md +2 -1
- package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +1 -1
- package/.pi/harness/docs/adrs/0035-plan-phase-review-gate.md +1 -1
- package/.pi/harness/docs/adrs/0044-harness-steer-loop.md +3 -2
- package/.pi/harness/docs/adrs/0045-harness-lens-minimal-contract.md +49 -0
- package/.pi/harness/docs/adrs/0045-phase-scoped-agent-directories.md +33 -0
- package/.pi/harness/docs/adrs/0046-agt-policy-engine.md +51 -0
- package/.pi/harness/docs/adrs/0047-agt-layered-security.md +39 -0
- package/.pi/harness/docs/adrs/0048-tool-call-hook-order.md +25 -0
- package/.pi/harness/docs/adrs/0049-agents-policy-manifest.md +36 -0
- package/.pi/harness/docs/adrs/README.md +6 -0
- package/.pi/harness/docs/graphify-kb-updater-runbook.md +11 -5
- package/.pi/harness/docs/practice-map.md +2 -2
- package/.pi/harness/evolution/README.md +1 -2
- package/.pi/harness/examples/agents.policy.project.yaml +19 -0
- package/.pi/harness/examples/policies/custom-deny-bash.yaml +9 -0
- package/.pi/harness/policies/bash-denylists.yaml +5 -0
- package/.pi/harness/policies/defaults.yaml +51 -0
- package/.pi/harness/policies/orchestrator.yaml +18 -0
- package/.pi/harness/policies/phases.yaml +10 -0
- package/.pi/harness/policies/roles.yaml +5 -0
- package/.pi/harness/policies/web-guard.yaml +5 -0
- package/.pi/harness/policies/workflow-sequences.yaml +9 -0
- package/.pi/harness/sentrux/architecture.manifest.json +26 -4
- package/.pi/harness/specs/harness-spawn-context.schema.json +1 -1
- package/.pi/harness/specs/observation.schema.json +2 -1
- package/.pi/lib/agents-policy.d.mts +70 -0
- package/.pi/lib/agents-policy.mjs +325 -0
- package/.pi/lib/agents-policy.ts +19 -0
- package/.pi/lib/agt/audit-run-sink.ts +52 -0
- package/.pi/lib/agt/build-evaluation-context.ts +285 -0
- package/.pi/lib/agt/config.ts +28 -0
- package/.pi/lib/agt/delegation.ts +69 -0
- package/.pi/lib/agt/evaluate-policy.ts +56 -0
- package/.pi/lib/agt/identity-registry.ts +41 -0
- package/.pi/lib/agt/index.ts +55 -0
- package/.pi/lib/agt/kill-switch-state.ts +11 -0
- package/.pi/lib/agt/legacy-evaluate.ts +101 -0
- package/.pi/lib/agt/policy-engine.ts +154 -0
- package/.pi/lib/agt/rings.ts +21 -0
- package/.pi/lib/agt/sre-hooks.ts +45 -0
- package/.pi/lib/agt/trust-run-store.ts +26 -0
- package/.pi/lib/agt/workflow-history.ts +29 -0
- package/.pi/lib/agt-governance-active.ts +14 -0
- package/.pi/lib/agt-tool-guard.ts +78 -0
- package/.pi/lib/ask-user/dialog.ts +314 -0
- package/.pi/{extensions/lib → lib}/debate-bus-core.ts +10 -10
- package/.pi/{extensions/lib → lib}/debate-bus-state.ts +1 -1
- package/.pi/{extensions/lib → lib}/extension-load-guard.ts +21 -0
- package/.pi/lib/harness-agt-tool-guard.ts +5 -0
- package/.pi/{extensions/lib → lib}/harness-artifact-gate.ts +6 -16
- package/.pi/lib/harness-debate-core-deps.ts +14 -0
- package/.pi/lib/harness-debate-workflow-deps.ts +43 -0
- package/.pi/lib/harness-lens/.gitattributes +1 -0
- package/.pi/lib/harness-lens/clients/edit-autopatch.ts +88 -0
- package/.pi/lib/harness-lens/clients/file-kinds.ts +380 -0
- package/.pi/lib/harness-lens/clients/file-time.ts +215 -0
- package/.pi/lib/harness-lens/clients/file-utils.ts +484 -0
- package/.pi/lib/harness-lens/clients/format-service.ts +276 -0
- package/.pi/lib/harness-lens/clients/formatters.ts +1000 -0
- package/.pi/lib/harness-lens/clients/git-guard.ts +31 -0
- package/.pi/lib/harness-lens/clients/indent-retarget.ts +90 -0
- package/.pi/lib/harness-lens/clients/installer/index.ts +2368 -0
- package/.pi/lib/harness-lens/clients/latency-logger.ts +80 -0
- package/.pi/lib/harness-lens/clients/lens-config.ts +43 -0
- package/.pi/lib/harness-lens/clients/lens-events.ts +164 -0
- package/.pi/lib/harness-lens/clients/lsp/aggregation.ts +91 -0
- package/.pi/lib/harness-lens/clients/lsp/client.ts +1466 -0
- package/.pi/lib/harness-lens/clients/lsp/config.ts +216 -0
- package/.pi/lib/harness-lens/clients/lsp/edits.ts +297 -0
- package/.pi/lib/harness-lens/clients/lsp/index.ts +1355 -0
- package/.pi/lib/harness-lens/clients/lsp/interactive-install.ts +424 -0
- package/.pi/lib/harness-lens/clients/lsp/language.ts +223 -0
- package/.pi/lib/harness-lens/clients/lsp/launch.ts +939 -0
- package/.pi/lib/harness-lens/clients/lsp/lsp-index.ts +11 -0
- package/.pi/lib/harness-lens/clients/lsp/path-utils.ts +12 -0
- package/.pi/lib/harness-lens/clients/lsp/server-strategies.ts +81 -0
- package/.pi/lib/harness-lens/clients/lsp/server.ts +1971 -0
- package/.pi/lib/harness-lens/clients/path-utils.ts +182 -0
- package/.pi/lib/harness-lens/clients/pipeline.ts +360 -0
- package/.pi/lib/harness-lens/clients/project-profile.ts +117 -0
- package/.pi/lib/harness-lens/clients/runtime-agent-end.ts +112 -0
- package/.pi/lib/harness-lens/clients/runtime-config.ts +33 -0
- package/.pi/lib/harness-lens/clients/runtime-coordinator.ts +186 -0
- package/.pi/lib/harness-lens/clients/runtime-tool-result.ts +171 -0
- package/.pi/lib/harness-lens/clients/safe-spawn.ts +339 -0
- package/.pi/lib/harness-lens/clients/secrets-scanner.ts +214 -0
- package/.pi/lib/harness-lens/clients/tool-policy.ts +2072 -0
- package/.pi/lib/harness-lens/clients/types.ts +59 -0
- package/.pi/lib/harness-lens/clients/widget-state.ts +283 -0
- package/.pi/lib/harness-lens/index.ts +532 -0
- package/.pi/lib/harness-lens/tools/lsp-diagnostics.ts +706 -0
- package/.pi/lib/harness-lens/tools/lsp-navigation.ts +1246 -0
- package/.pi/{extensions/lib → lib}/harness-posthog.ts +3 -0
- package/.pi/lib/harness-project-config.ts +91 -0
- package/.pi/lib/harness-run-context-responses.ts +9 -0
- package/.pi/lib/harness-run-context.ts +1 -3
- package/.pi/{extensions/lib/spawn-policy.ts → lib/harness-spawn-policy.ts} +4 -3
- package/.pi/{extensions/lib → lib}/harness-spawn-topology.ts +5 -28
- package/.pi/lib/harness-subagent-auth.ts +51 -0
- package/.pi/{extensions/lib → lib}/harness-subagent-precheck.ts +13 -10
- package/.pi/{extensions/lib → lib}/harness-subagent-submit-pipeline.ts +3 -3
- package/.pi/lib/harness-subagent-submit-register.ts +163 -0
- package/.pi/{extensions/lib → lib}/harness-subagent-submit-registry.ts +1 -55
- package/.pi/{extensions/lib → lib}/harness-subagents-bridge.ts +53 -14
- package/.pi/{extensions/lib → lib}/harness-subprocess-bootstrap.ts +1 -1
- package/.pi/lib/harness-ui-state.ts +27 -12
- package/.pi/{extensions/lib → lib}/plan-approval/create-plan.ts +2 -2
- package/.pi/{extensions/lib → lib}/plan-approval/format-plan.ts +2 -2
- package/.pi/{extensions/lib → lib}/plan-approval/plan-review.ts +162 -201
- package/.pi/{extensions/lib → lib}/plan-approval/render.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-approval/resolve-disk.ts +2 -2
- package/.pi/{extensions/lib → lib}/plan-approval/types.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-approval/validate.ts +3 -3
- package/.pi/{extensions/lib → lib}/plan-approval-readiness.ts +3 -52
- package/.pi/{extensions/lib → lib}/plan-debate-envelope.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-debate-gate.ts +1 -1
- package/.pi/{extensions/lib → lib}/plan-debate-lane.ts +1 -4
- package/.pi/{extensions/lib → lib}/plan-messenger.ts +1 -1
- package/.pi/prompts/harness-auto.md +2 -2
- package/.pi/prompts/harness-plan.md +4 -6
- package/.pi/prompts/harness-review.md +9 -9
- package/.pi/prompts/harness-run.md +7 -7
- package/.pi/prompts/harness-setup.md +42 -68
- package/.pi/prompts/harness-steer.md +2 -2
- package/.pi/scripts/README.md +3 -5
- package/.pi/scripts/generate-agents-policy-yaml.mjs +148 -0
- package/.pi/scripts/graphify-kb-updater.mjs +48 -8
- package/.pi/scripts/harness-agents-manifest.mjs +61 -4
- package/.pi/scripts/harness-agt-doctor.ts +36 -0
- package/.pi/scripts/harness-cli-verify.sh +9 -2
- package/.pi/scripts/harness-project-toggle.mjs +129 -0
- package/.pi/scripts/harness-sentrux-cli.mjs +142 -0
- package/.pi/scripts/harness-verify.mjs +113 -39
- package/.pi/scripts/harness-web-policy-guard.mjs +2 -2
- package/.pi/scripts/validate-plan-dag.mjs +65 -74
- package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +2 -2
- package/.pi/scripts/vendor-sync-pi-vcc.sh +1 -1
- package/.pi/skills/architecture/broker-domain/SKILL.md +65 -0
- package/.pi/skills/architecture/cqrs/SKILL.md +63 -0
- package/.pi/skills/architecture/event-driven/SKILL.md +60 -0
- package/.pi/skills/architecture/hexagonal-ports-adapters/SKILL.md +66 -0
- package/.pi/skills/architecture/layered/SKILL.md +68 -0
- package/.pi/skills/architecture/microkernel/SKILL.md +62 -0
- package/.pi/skills/architecture/microservices/SKILL.md +64 -0
- package/.pi/skills/architecture/modular-monolith/SKILL.md +65 -0
- package/.pi/skills/architecture/orchestration-driven-soa/SKILL.md +61 -0
- package/.pi/skills/architecture/pipeline/SKILL.md +63 -0
- package/.pi/skills/architecture/service-based/SKILL.md +64 -0
- package/.pi/skills/architecture/service-mesh/SKILL.md +60 -0
- package/.pi/skills/architecture/space-based/SKILL.md +60 -0
- package/.pi/skills/ast-grep/SKILL.md +40 -321
- package/.pi/skills/delivery/debugging-discipline/SKILL.md +36 -0
- package/.pi/skills/delivery/documentation-update/SKILL.md +33 -0
- package/.pi/skills/delivery/requirements-to-implementation/SKILL.md +34 -0
- package/.pi/skills/delivery/risk-based-verification/SKILL.md +43 -0
- package/.pi/skills/delivery/tradeoff-analysis/SKILL.md +34 -0
- package/.pi/skills/engineering/api-contract-design/SKILL.md +38 -0
- package/.pi/skills/engineering/cohesion-coupling/SKILL.md +43 -0
- package/.pi/skills/engineering/complexity-control/SKILL.md +31 -0
- package/.pi/skills/engineering/defensive-programming/SKILL.md +38 -0
- package/.pi/skills/engineering/dependency-management/SKILL.md +29 -0
- package/.pi/skills/engineering/domain-modeling/SKILL.md +32 -0
- package/.pi/skills/engineering/error-handling/SKILL.md +37 -0
- package/.pi/skills/engineering/legacy-code-seams/SKILL.md +35 -0
- package/.pi/skills/engineering/naming-and-intent/SKILL.md +29 -0
- package/.pi/skills/engineering/refactoring-safe-evolution/SKILL.md +35 -0
- package/.pi/skills/engineering/routine-function-design/SKILL.md +34 -0
- package/.pi/skills/engineering/small-change-discipline/SKILL.md +35 -0
- package/.pi/skills/lsp-navigation/SKILL.md +89 -0
- package/.pi/skills/quality/code-review-self-check/SKILL.md +35 -0
- package/.pi/skills/quality/privacy-data-handling/SKILL.md +26 -0
- package/.pi/skills/quality/security-review/SKILL.md +34 -0
- package/.pi/skills/quality/test-strategy/SKILL.md +33 -0
- package/.pi/skills/quality/testability-design/SKILL.md +33 -0
- package/.pi/skills/systems/concurrency-safety/SKILL.md +32 -0
- package/.pi/skills/systems/data-modeling-migrations/SKILL.md +31 -0
- package/.pi/skills/systems/observability-instrumentation/SKILL.md +32 -0
- package/.pi/skills/systems/performance-measurement/SKILL.md +35 -0
- package/.pi/skills/systems/reliability-design/SKILL.md +32 -0
- package/.sentrux/rules.toml +20 -4
- package/AGENTS.md +5 -0
- package/CHANGELOG.md +26 -0
- package/README.md +85 -58
- package/THIRD_PARTY_NOTICES.md +12 -21
- package/package.json +15 -7
- package/vendor/pi-subagents/src/agents.ts +45 -1
- package/vendor/pi-subagents/src/subagents.ts +866 -811
- package/vendor/pi-vcc/src/core/brief.ts +68 -99
- package/vendor/pi-vcc/src/core/settings.ts +2 -2
- package/.agents/skills/caveman/SKILL.md +0 -67
- package/.pi/agents/harness/meta-optimizer.md +0 -36
- package/.pi/agents/harness/planning/scout-graphify.md +0 -39
- package/.pi/agents/harness/planning/scout-semantic.md +0 -41
- package/.pi/agents/harness/planning/scout-structure.md +0 -37
- package/.pi/extensions/lib/ask-user/dialog.ts +0 -260
- package/.pi/extensions/lib/harness-subagent-auth.ts +0 -209
- package/.pi/extensions/lib/harness-subagent-policy.ts +0 -236
- package/.pi/extensions/pi-model-router-harness.ts +0 -42
- package/.pi/harness/evolution/meta-optimizer.mjs +0 -99
- package/.pi/harness/specs/router-tuning-proposal.schema.json +0 -114
- package/.pi/model-router.example.json +0 -36
- package/.pi/prompts/harness-critic.md +0 -10
- package/.pi/prompts/harness-eval.md +0 -10
- package/.pi/prompts/harness-router-tune.md +0 -52
- package/.pi/scripts/harness-generate-model-router.mjs +0 -327
- package/.pi/scripts/harness-model-router-routing.test.mjs +0 -97
- package/.pi/scripts/harness-sync-model-router.mjs +0 -97
- package/.pi/scripts/vendor-sync-pi-model-router.sh +0 -47
- package/vendor/pi-model-router/.prettierignore +0 -4
- package/vendor/pi-model-router/.prettierrc +0 -5
- package/vendor/pi-model-router/AGENTS.md +0 -39
- package/vendor/pi-model-router/LICENSE +0 -21
- package/vendor/pi-model-router/README.md +0 -99
- package/vendor/pi-model-router/UPSTREAM_PIN.md +0 -10
- package/vendor/pi-model-router/docs/ARCHITECTURE.md +0 -54
- package/vendor/pi-model-router/extensions/commands.ts +0 -720
- package/vendor/pi-model-router/extensions/config.ts +0 -348
- package/vendor/pi-model-router/extensions/constants.ts +0 -1
- package/vendor/pi-model-router/extensions/index.ts +0 -478
- package/vendor/pi-model-router/extensions/provider.ts +0 -580
- package/vendor/pi-model-router/extensions/routing.ts +0 -564
- package/vendor/pi-model-router/extensions/state.ts +0 -52
- package/vendor/pi-model-router/extensions/types.ts +0 -95
- package/vendor/pi-model-router/extensions/ui.ts +0 -144
- package/vendor/pi-model-router/model-router.example.json +0 -48
- package/vendor/pi-model-router/package.json +0 -48
- package/vendor/pi-model-router/tsconfig.json +0 -16
- /package/.pi/{prompts → harness/docs}/planning-rubrics.md +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/fallback.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/render.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/schema.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/types.ts +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/validate-core.mjs +0 -0
- /package/.pi/{extensions/lib → lib}/ask-user/validate.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-cocoindex-refresh.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-paths.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-spawn-budget.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-vcc-settings.ts +0 -0
- /package/.pi/{extensions/lib → lib}/harness-web/run-cli.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-approval/dialog.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-approval/schema.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-eligibility.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-focus.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-id.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-lanes.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-round-status.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-debate-write-guard.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-review-gate.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-review-integrator-rules.ts +0 -0
- /package/.pi/{extensions/lib → lib}/plan-scope-guard.ts +0 -0
- /package/.pi/{extensions/lib → lib}/posthog-client.ts +0 -0
- /package/.pi/{extensions/lib → lib}/posthog-node.d.ts +0 -0
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Unit tests for session-locked pi-model-router routing (no LLM).
|
|
4
|
-
* Run: npx tsx .pi/scripts/harness-model-router-routing.test.mjs
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import assert from "node:assert/strict";
|
|
8
|
-
import { readFileSync } from "node:fs";
|
|
9
|
-
import { join, dirname } from "node:path";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
|
-
import {
|
|
12
|
-
decideSessionLock,
|
|
13
|
-
applyThinkingToDecision,
|
|
14
|
-
buildRoutingDecision,
|
|
15
|
-
decideRouting,
|
|
16
|
-
} from "../../vendor/pi-model-router/extensions/routing.js";
|
|
17
|
-
|
|
18
|
-
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
19
|
-
|
|
20
|
-
const sampleProfile = {
|
|
21
|
-
high: { model: "openai/gpt-5.5", thinking: "high" },
|
|
22
|
-
medium: { model: "openai/gpt-5.5", thinking: "medium" },
|
|
23
|
-
low: { model: "openai/gpt-5.5", thinking: "low" },
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const planningContext = {
|
|
27
|
-
systemPrompt: "You are a harness architect. Design tradeoffs and migration strategy.",
|
|
28
|
-
messages: [
|
|
29
|
-
{
|
|
30
|
-
role: "user",
|
|
31
|
-
content:
|
|
32
|
-
"Plan a multi-phase refactor across modules with architecture review.",
|
|
33
|
-
timestamp: 1,
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const shortContext = {
|
|
39
|
-
systemPrompt: "Summarize briefly.",
|
|
40
|
-
messages: [{ role: "user", content: "changelog", timestamp: 1 }],
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const lockHigh = decideSessionLock(
|
|
44
|
-
planningContext,
|
|
45
|
-
"auto",
|
|
46
|
-
sampleProfile,
|
|
47
|
-
undefined,
|
|
48
|
-
undefined,
|
|
49
|
-
0.5,
|
|
50
|
-
[{ matches: "changelog", tier: "low" }],
|
|
51
|
-
);
|
|
52
|
-
assert.equal(lockHigh.tier, "high", "planning prompt locks high tier");
|
|
53
|
-
|
|
54
|
-
const lockLow = decideSessionLock(shortContext, "auto", sampleProfile);
|
|
55
|
-
assert.equal(lockLow.tier, "low", "short summary locks low tier");
|
|
56
|
-
|
|
57
|
-
const locked = buildRoutingDecision(
|
|
58
|
-
"auto",
|
|
59
|
-
sampleProfile,
|
|
60
|
-
lockHigh.tier,
|
|
61
|
-
"planning",
|
|
62
|
-
lockHigh.reasoning,
|
|
63
|
-
);
|
|
64
|
-
const thinkingTurn = decideRouting(
|
|
65
|
-
{
|
|
66
|
-
...planningContext,
|
|
67
|
-
messages: [
|
|
68
|
-
...planningContext.messages,
|
|
69
|
-
{ role: "user", content: "changelog only", timestamp: 2 },
|
|
70
|
-
],
|
|
71
|
-
},
|
|
72
|
-
"auto",
|
|
73
|
-
sampleProfile,
|
|
74
|
-
locked,
|
|
75
|
-
);
|
|
76
|
-
const merged = applyThinkingToDecision(locked, thinkingTurn, sampleProfile);
|
|
77
|
-
assert.equal(merged.targetLabel, locked.targetLabel, "model stays locked");
|
|
78
|
-
assert.equal(merged.tier, thinkingTurn.tier, "thinking tier follows turn");
|
|
79
|
-
assert.equal(merged.thinking, "low", "low thinking from turn tier config");
|
|
80
|
-
|
|
81
|
-
const examplePath = join(ROOT, ".pi", "model-router.example.json");
|
|
82
|
-
const example = JSON.parse(readFileSync(examplePath, "utf8"));
|
|
83
|
-
for (const [name, profile] of Object.entries(example.profiles ?? {})) {
|
|
84
|
-
const { high, medium, low } = profile;
|
|
85
|
-
assert.equal(
|
|
86
|
-
high.model,
|
|
87
|
-
medium.model,
|
|
88
|
-
`example profile ${name}: medium/high same model`,
|
|
89
|
-
);
|
|
90
|
-
assert.equal(
|
|
91
|
-
medium.model,
|
|
92
|
-
low.model,
|
|
93
|
-
`example profile ${name}: low/medium same model`,
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
console.log("harness-model-router-routing.test: PASS");
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* After `.pi/model-router.json` exists, set sensible Pi defaults (`router` / `auto`)
|
|
4
|
-
* when the project has no `defaultProvider`. Does **not** add/remove npm packages
|
|
5
|
-
* — model routing ships vendored inside ultimate-pi.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
9
|
-
import { join, dirname } from "node:path";
|
|
10
|
-
|
|
11
|
-
function loadSettings(settingsPath) {
|
|
12
|
-
if (!existsSync(settingsPath)) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
try {
|
|
16
|
-
return JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
17
|
-
} catch {
|
|
18
|
-
console.error("[harness-model-router] Invalid JSON:", settingsPath);
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function saveSettings(settingsPath, data) {
|
|
24
|
-
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
25
|
-
writeFileSync(
|
|
26
|
-
settingsPath,
|
|
27
|
-
`${JSON.stringify(data, null, "\t")}\n`,
|
|
28
|
-
"utf8",
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function readDefaultRouterProfile(configPath) {
|
|
33
|
-
if (!existsSync(configPath)) return "auto";
|
|
34
|
-
try {
|
|
35
|
-
const data = JSON.parse(readFileSync(configPath, "utf8"));
|
|
36
|
-
const profile =
|
|
37
|
-
typeof data.defaultProfile === "string" ? data.defaultProfile.trim() : "";
|
|
38
|
-
return profile || "auto";
|
|
39
|
-
} catch {
|
|
40
|
-
return "auto";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function main() {
|
|
45
|
-
const root = process.cwd();
|
|
46
|
-
const configPath = join(root, ".pi", "model-router.json");
|
|
47
|
-
const settingsPath = join(root, ".pi", "settings.json");
|
|
48
|
-
const hasConfig = existsSync(configPath);
|
|
49
|
-
const defaultRouterProfile = readDefaultRouterProfile(configPath);
|
|
50
|
-
|
|
51
|
-
const settings = loadSettings(settingsPath);
|
|
52
|
-
if (!settings) {
|
|
53
|
-
console.warn(
|
|
54
|
-
"[harness-model-router] No .pi/settings.json — skipping (merge Step 3 first)",
|
|
55
|
-
);
|
|
56
|
-
process.exit(0);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let changed = false;
|
|
60
|
-
|
|
61
|
-
if (!hasConfig) {
|
|
62
|
-
if (settings.defaultProvider === "router") {
|
|
63
|
-
delete settings.defaultProvider;
|
|
64
|
-
delete settings.defaultModel;
|
|
65
|
-
changed = true;
|
|
66
|
-
}
|
|
67
|
-
if (changed) {
|
|
68
|
-
saveSettings(settingsPath, settings);
|
|
69
|
-
console.warn(
|
|
70
|
-
"⚠ No .pi/model-router.json — cleared router defaultProvider if present",
|
|
71
|
-
);
|
|
72
|
-
} else {
|
|
73
|
-
console.log("[harness-model-router] No config file; nothing to do");
|
|
74
|
-
}
|
|
75
|
-
process.exit(0);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const noProjectDefault =
|
|
79
|
-
settings.defaultProvider == null || settings.defaultProvider === "";
|
|
80
|
-
|
|
81
|
-
if (noProjectDefault) {
|
|
82
|
-
settings.defaultProvider = "router";
|
|
83
|
-
settings.defaultModel = defaultRouterProfile;
|
|
84
|
-
changed = true;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (changed) {
|
|
88
|
-
saveSettings(settingsPath, settings);
|
|
89
|
-
console.log(
|
|
90
|
-
`✓ Router defaults set (\`router\` / \`${defaultRouterProfile}\`) — run /reload in pi when ready`,
|
|
91
|
-
);
|
|
92
|
-
} else {
|
|
93
|
-
console.log("[harness-model-router] Defaults unchanged (user set defaultProvider)");
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
main();
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Re-fetch upstream pi-model-router and re-apply ultimate-pi patches.
|
|
3
|
-
set -euo pipefail
|
|
4
|
-
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
5
|
-
VEND="$ROOT/vendor/pi-model-router"
|
|
6
|
-
|
|
7
|
-
rm -rf "$VEND"
|
|
8
|
-
git clone --depth 1 https://github.com/yeliu84/pi-model-router.git "$VEND"
|
|
9
|
-
COMMIT="$(git -C "$VEND" rev-parse HEAD)"
|
|
10
|
-
rm -rf "$VEND/.git"
|
|
11
|
-
|
|
12
|
-
for f in "$VEND"/extensions/*.ts; do
|
|
13
|
-
sed -i \
|
|
14
|
-
-e "s|'@earendil-works/pi-agent-core'|'@earendil-works/pi-agent-core'|g" \
|
|
15
|
-
-e "s|'@earendil-works/pi-ai'|'@earendil-works/pi-ai'|g" \
|
|
16
|
-
-e "s|'@earendil-works/pi-coding-agent'|'@earendil-works/pi-coding-agent'|g" \
|
|
17
|
-
-e "s|'@earendil-works/pi-tui'|'@earendil-works/pi-tui'|g" \
|
|
18
|
-
"$f"
|
|
19
|
-
done
|
|
20
|
-
|
|
21
|
-
# Align package.json peers with @earendil-works (upstream lists @earendil-works)
|
|
22
|
-
sed -i \
|
|
23
|
-
-e 's|"@earendil-works/pi-agent-core"|"@earendil-works/pi-agent-core"|g' \
|
|
24
|
-
-e 's|"@earendil-works/pi-ai"|"@earendil-works/pi-ai"|g' \
|
|
25
|
-
-e 's|"@earendil-works/pi-coding-agent"|"@earendil-works/pi-coding-agent"|g' \
|
|
26
|
-
-e 's|"@earendil-works/pi-tui"|"@earendil-works/pi-tui"|g' \
|
|
27
|
-
"$VEND/package.json"
|
|
28
|
-
|
|
29
|
-
python3 -c "
|
|
30
|
-
import re, pathlib
|
|
31
|
-
for p in pathlib.Path('$VEND/extensions').glob('*.ts'):
|
|
32
|
-
t = p.read_text()
|
|
33
|
-
t2 = re.sub(r\"from '\\./([^']+)'\", lambda m: f\"from './{m.group(1)}.js'\" if not m.group(1).endswith('.js') else m.group(0), t)
|
|
34
|
-
p.write_text(t2)
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
cat >"$VEND/UPSTREAM_PIN.md" <<EOF
|
|
38
|
-
# Vendored \`pi-model-router\`
|
|
39
|
-
|
|
40
|
-
- **Repository:** https://github.com/yeliu84/pi-model-router
|
|
41
|
-
- **License:** MIT (\`LICENSE\` in this tree)
|
|
42
|
-
- **Pinned upstream commit:** \`$COMMIT\`
|
|
43
|
-
- **Local changes:** \`extensions/*.ts\` imports use \`@earendil-works/*\` and relative paths end in \`.js\` for TypeScript nodenext.
|
|
44
|
-
EOF
|
|
45
|
-
|
|
46
|
-
rm -f "$VEND/package-lock.json"
|
|
47
|
-
echo "✓ Vendor refreshed at $VEND (commit $COMMIT)"
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Pi Model Router: Core Mandates
|
|
2
|
-
|
|
3
|
-
## Project Overview
|
|
4
|
-
The `pi-model-router` is an extension-first model router for the `pi` coding agent. It registers a custom logical provider (`router`) that exposes "profiles" as models (e.g., `router/auto`). For every turn, the router intelligently selects an underlying concrete model based on task complexity, conversation phase, and user-defined rules.
|
|
5
|
-
|
|
6
|
-
## Architectural Principles
|
|
7
|
-
- **Extension-First**: All functionality must be implemented as a `pi` extension without modifying `pi` core.
|
|
8
|
-
- **Custom Provider**: Use `pi.registerProvider` to hook into the model lifecycle. The logical model (e.g., `router/auto`) should remain stable while the underlying model changes transparently.
|
|
9
|
-
- **Modularized Design**: Strictly follow the modular structure defined in Phase 3:
|
|
10
|
-
- `extensions/types.ts`: All interfaces and type definitions.
|
|
11
|
-
- `extensions/config.ts`: Configuration loading, normalization, and merging.
|
|
12
|
-
- `extensions/routing.ts`: Core routing logic (heuristics, classifier, rule matching).
|
|
13
|
-
- `extensions/provider.ts`: Custom `router` provider registration and delegation stream.
|
|
14
|
-
- `extensions/state.ts`: Session-persisted state management and snapshotting.
|
|
15
|
-
- `extensions/ui.ts`: UI status line and widget rendering logic.
|
|
16
|
-
- `extensions/commands.ts`: CLI command registrations and completions.
|
|
17
|
-
- `extensions/index.ts`: Main entry point (orchestrator).
|
|
18
|
-
|
|
19
|
-
## Routing Decision Logic
|
|
20
|
-
Routing follows a tiered system (`high`, `medium`, `low`) and an ordered decision flow:
|
|
21
|
-
1. **Budget Check**: Downgrade to `medium` if `maxSessionBudget` is exceeded.
|
|
22
|
-
2. **Context Trigger**: Upgrade to `high` if `largeContextThreshold` is reached.
|
|
23
|
-
3. **Manual Pin**: Use tier pinned via `/router pin` or `/router fix`.
|
|
24
|
-
4. **Custom Rules**: Check keyword-based rules against the user prompt.
|
|
25
|
-
5. **LLM Classifier (Optional)**: Call `classifierModel` for intent categorization.
|
|
26
|
-
6. **Heuristics (Fallback)**: Use local heuristics if the classifier is off/fails.
|
|
27
|
-
7. **Phase Bias**: Apply stickiness to maintain a consistent tier during multi-turn tasks.
|
|
28
|
-
|
|
29
|
-
## Coding Standards
|
|
30
|
-
- **TypeScript**: Strictly adhere to TypeScript. NEVER use the `any` type; prefer specific types or `unknown`.
|
|
31
|
-
- **Functions**: Always use arrow functions (`const myFunc = () => ...`) instead of function statements (`function myFunc() ...`) for consistency and lexical scoping.
|
|
32
|
-
- **Imports**: Use top-level static imports over inline `import()` or `require()` calls for consistency and cleaner ESM code.
|
|
33
|
-
- **State Management**: Persist router state via `pi.appendEntry` with a custom `router-state` entry type to ensure branch-safe behavior.
|
|
34
|
-
- **Error Handling**: Implement robust fallback chains for model failures (retrying with alternative models).
|
|
35
|
-
|
|
36
|
-
## Documentation Reference
|
|
37
|
-
- `docs/ARCHITECTURE.md`: Detailed architectural deep dive.
|
|
38
|
-
- `README.md`: Usage and installation guide.
|
|
39
|
-
- `model-router.example.json`: Reference for configuration structure.
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Ye Liu
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# pi-model-router
|
|
2
|
-
|
|
3
|
-
Intelligent per-turn model router extension for the [pi-coding-agent](https://github.com/earendil-works/pi/tree/main/packages/coding-agent). Automatically selects between high, medium, and low-tier LLMs based on task intent, session budget, context size, and custom rules — with automatic fallbacks and phase awareness.
|
|
4
|
-
|
|
5
|
-
## What it does
|
|
6
|
-
|
|
7
|
-
- **Logical Router Provider**: Registers a `router` provider that exposes stable profiles (e.g., `router/auto`) as models.
|
|
8
|
-
- **Per-Turn Routing**: Intelligently chooses between `high`, `medium`, and `low` tiers for every turn based on task intent and complexity.
|
|
9
|
-
- **Task-Aware Heuristics**: Detects planning vs. implementation vs. lightweight tasks using keyword analysis, word count, and conversation history.
|
|
10
|
-
- **Advanced Controls**: Includes built-in support for:
|
|
11
|
-
- **LLM Intent Classifier**: Optionally use a fast model to categorize intent (overrides heuristics).
|
|
12
|
-
- **Custom Rules**: Define keyword-based tier overrides for specific patterns (e.g., `deploy` → `high`).
|
|
13
|
-
- **Context Trigger**: Automatically upgrade to high-tier when token usage exceeds a threshold.
|
|
14
|
-
- **Cost Budgeting**: Set a session spend limit; high tier downgrades to medium once exceeded.
|
|
15
|
-
- **Fallback Chains**: Automatic retry with alternative models if the primary choice fails.
|
|
16
|
-
- **Phase Memory**: Biased stickiness to keep you in the same tier during multi-turn planning or implementation work.
|
|
17
|
-
- **Thinking Control**: Full control over reasoning/thinking levels per tier and profile.
|
|
18
|
-
- **Persistent State**: Pins, profiles, costs, and debug history are remembered across agent restarts and conversation branches.
|
|
19
|
-
|
|
20
|
-
## Installation
|
|
21
|
-
|
|
22
|
-
### As a user
|
|
23
|
-
|
|
24
|
-
Install from npm:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
pi install npm:@yeliu84/pi-model-router
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### For development
|
|
31
|
-
|
|
32
|
-
Clone this repo and install from source:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
pi install .
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Or load directly for one run:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
pi -e ./extensions/index.ts
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Configuration
|
|
45
|
-
|
|
46
|
-
Copy the example config to one of:
|
|
47
|
-
|
|
48
|
-
- `~/.pi/agent/model-router.json` (Global)
|
|
49
|
-
- `.pi/model-router.json` (Project-specific)
|
|
50
|
-
|
|
51
|
-
### Basic Config Shape
|
|
52
|
-
|
|
53
|
-
```json
|
|
54
|
-
{
|
|
55
|
-
"defaultProfile": "auto",
|
|
56
|
-
"classifierModel": "google/gemini-flash-latest",
|
|
57
|
-
"maxSessionBudget": 1.0,
|
|
58
|
-
"profiles": {
|
|
59
|
-
"auto": {
|
|
60
|
-
"high": { "model": "openai/gpt-5.4-pro", "thinking": "high" },
|
|
61
|
-
"medium": { "model": "google/gemini-flash-latest", "thinking": "medium" },
|
|
62
|
-
"low": { "model": "openai/gpt-5.4-nano", "thinking": "low" }
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Configuration Fields
|
|
69
|
-
|
|
70
|
-
| Field | Description |
|
|
71
|
-
| ----------------------- | --------------------------------------------------------------------------------- |
|
|
72
|
-
| `defaultProfile` | The profile to use when starting a new session. |
|
|
73
|
-
| `classifierModel` | (Optional) Model used to categorize intent. If omitted, fast heuristics are used. |
|
|
74
|
-
| `maxSessionBudget` | (Optional) USD budget for the session. Forces `medium` tier once exceeded. |
|
|
75
|
-
| `largeContextThreshold` | (Optional) Token count trigger to force `high` tier for large contexts. |
|
|
76
|
-
| `phaseBias` | (0.0 - 1.0) Stickiness of the current phase. Higher = more stable. Default `0.5`. |
|
|
77
|
-
| `rules` | List of custom keyword rules (e.g. `{ "matches": "deploy", "tier": "high" }`). |
|
|
78
|
-
| `profiles` | Map of profile definitions, each containing `high`, `medium`, and `low` tiers. |
|
|
79
|
-
|
|
80
|
-
## Commands
|
|
81
|
-
|
|
82
|
-
| Command | Description |
|
|
83
|
-
| --------------------------- | ------------------------------------------------------------------------------- |
|
|
84
|
-
| `/router` | Show detailed status, current profile, spend, and settings. |
|
|
85
|
-
| `/router status` | Alias for `/router` (show current status). |
|
|
86
|
-
| `/router profile [name]` | Switch to a profile or list available ones (enables router if off). |
|
|
87
|
-
| `/router pin [prof] <t\|a>` | Pin a tier (high/medium/low/auto) for the current or specified profile. |
|
|
88
|
-
| `/router fix <tier>` | Correct the _last_ decision and pin that tier for the current profile. |
|
|
89
|
-
| `/router thinking ...` | Override thinking levels (e.g. `/router thinking low xhigh`). |
|
|
90
|
-
| `/router disable` | Disable the router and switch back to the last non-router model. |
|
|
91
|
-
| `/router widget <on\|off>` | Toggle the persistent state widget (supports `toggle`). |
|
|
92
|
-
| `/router debug <on\|off>` | Toggle turn-by-turn routing notifications (supports `toggle`, `clear`, `show`). |
|
|
93
|
-
| `/router reload` | Hot-reload the configuration JSON. |
|
|
94
|
-
| `/router help` | Show usage help for all subcommands. |
|
|
95
|
-
|
|
96
|
-
## Documentation
|
|
97
|
-
|
|
98
|
-
- [Architecture Guide](docs/ARCHITECTURE.md): Deep dive into the routing logic and modular design.
|
|
99
|
-
- [Sample Configuration](model-router.example.json): Diverse profile examples (`cheap`, `deep`, `balanced`).
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# Vendored `pi-model-router`
|
|
2
|
-
|
|
3
|
-
- **Repository:** https://github.com/yeliu84/pi-model-router
|
|
4
|
-
- **License:** MIT (`LICENSE` in this tree)
|
|
5
|
-
- **Pinned upstream commit:** `8c60095da0e753c242c4be9bb617b85f4dd3255c`
|
|
6
|
-
- **Local changes:**
|
|
7
|
-
- TypeScript imports in `extensions/*.ts` use `@earendil-works/*`; relative imports end in `.js` for NodeNext; `package.json` peerDependencies list `@earendil-works/*`.
|
|
8
|
-
- **Session-locked routing (ultimate-pi harness):** one concrete model per session/profile, chosen from initial prompt + system prompt complexity; per-turn routing adjusts **thinking tier only** (`sessionLock` persisted in `router-state`). Harness generator emits the same `model` on high/medium/low tiers.
|
|
9
|
-
|
|
10
|
-
**Refresh upstream:** run `npm run vendor:sync-router` from ultimate-pi root (updates this file with the latest commit SHA).
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Architecture: Pi Model Router Extension
|
|
2
|
-
|
|
3
|
-
The `pi-model-router` is an extension-first model router for the `pi` coding agent. It registers a custom logical provider (`router`) that exposes "profiles" as models (e.g., `router/auto`). For every turn, the router intelligently selects an underlying concrete model based on task complexity, conversation phase, and user-defined rules.
|
|
4
|
-
|
|
5
|
-
## Core Concepts
|
|
6
|
-
|
|
7
|
-
### 1. Profiles & Tiers
|
|
8
|
-
|
|
9
|
-
The router is organized into **Profiles** (e.g., `auto`, `cheap`, `deep`). Each profile defines three **Tiers**:
|
|
10
|
-
|
|
11
|
-
- **High**: Reserved for architecture, design, complex debugging, and planning. Uses high-reasoning models.
|
|
12
|
-
- **Medium**: The default for standard implementation, multi-file edits, and focused fixes.
|
|
13
|
-
- **Low**: Used for summaries, changelogs, formatting, and simple read-only lookups.
|
|
14
|
-
|
|
15
|
-
### 2. Custom Provider Implementation
|
|
16
|
-
|
|
17
|
-
The extension uses `pi.registerProvider` to hook into the `pi` model lifecycle. This ensures that the selected model in the `pi` footer remains stable (e.g., `router/auto`) while the underlying model changes transparently turn-by-turn via the `streamSimple` interception.
|
|
18
|
-
|
|
19
|
-
## Routing Decision Flow
|
|
20
|
-
|
|
21
|
-
For every request sent to a `router/*` model, the following logic is executed:
|
|
22
|
-
|
|
23
|
-
1. **Budget Check**: If a `maxSessionBudget` is configured and the session spend exceeds it, the router automatically downgrades `high` tier requests to `medium`.
|
|
24
|
-
2. **Context Trigger**: If `largeContextThreshold` is exceeded (measured in tokens), the router forces the `high` tier to ensure the model can handle the large context.
|
|
25
|
-
3. **Manual Pin**: If the user has pinned a tier via `/router pin` or `/router fix`, that tier is used.
|
|
26
|
-
4. **Custom Rules**: Keyword-based rules defined in the config are checked against the user prompt.
|
|
27
|
-
5. **LLM Classifier (Optional)**: If `classifierModel` is configured, a fast LLM is called to categorize the user's intent.
|
|
28
|
-
6. **Heuristics (Fallback)**: If the classifier is off or fails, a fast local heuristic (keyword/length/tool-use analysis) is used.
|
|
29
|
-
7. **Biased Stickiness**: The `phaseBias` setting modulates thresholds to keep the router in a consistent phase (e.g., staying in `high` tier during a multi-turn planning session).
|
|
30
|
-
|
|
31
|
-
## Module Architecture
|
|
32
|
-
|
|
33
|
-
The extension is modularized for maintainability:
|
|
34
|
-
|
|
35
|
-
- `extensions/index.ts`: Orchestrator. Manages state, hooks into `pi` events, and wires modules together.
|
|
36
|
-
- `extensions/provider.ts`: Implements the `router` provider and the delegation/retry loop.
|
|
37
|
-
- `extensions/routing.ts`: Core decision logic, heuristics, and the LLM classifier.
|
|
38
|
-
- `extensions/config.ts`: Loads, merges, and normalizes the JSON configuration.
|
|
39
|
-
- `extensions/commands.ts`: Registers all `/router` subcommands and their autocompletions.
|
|
40
|
-
- `extensions/ui.ts`: Manages the status line and the optional state widget.
|
|
41
|
-
- `extensions/state.ts`: Handles session-persisted state and snapshots.
|
|
42
|
-
- `extensions/types.ts`: Centralized interface and type definitions.
|
|
43
|
-
|
|
44
|
-
## State & Persistence
|
|
45
|
-
|
|
46
|
-
The router state is persisted using `pi.appendEntry` with a custom type `router-state`. This allows the router to:
|
|
47
|
-
|
|
48
|
-
- Restore the active profile and pins across agent relaunches.
|
|
49
|
-
- Maintain independent pins and state for different conversation branches.
|
|
50
|
-
- Track accumulated session costs safely.
|
|
51
|
-
|
|
52
|
-
## Reliability: Fallback Chains
|
|
53
|
-
|
|
54
|
-
Each tier in a profile can define an optional `fallbacks` list. If the primary model fails (e.g., due to rate limits or provider downtime), the router automatically retries the next model in the chain before surfacing an error to the user.
|