pi-smart-router 0.1.0 → 0.2.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/.pi/extensions/smart-router/delegation-runtime.ts +12 -2
- package/README.md +55 -17
- package/dist/api/explain/router-explain.d.ts +4 -1
- package/dist/api/explain/router-explain.d.ts.map +1 -1
- package/dist/api/explain/router-explain.js +9 -9
- package/dist/api/explain/router-explain.js.map +1 -1
- package/dist/config/defaults.d.ts +4 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +10 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/domain/delegation/delegation-context.d.ts +23 -1
- package/dist/domain/delegation/delegation-context.d.ts.map +1 -1
- package/dist/domain/delegation/delegation-context.js +93 -0
- package/dist/domain/delegation/delegation-context.js.map +1 -1
- package/dist/domain/pinning/cache-breakeven.d.ts +51 -0
- package/dist/domain/pinning/cache-breakeven.d.ts.map +1 -0
- package/dist/domain/pinning/cache-breakeven.js +124 -0
- package/dist/domain/pinning/cache-breakeven.js.map +1 -0
- package/dist/domain/pinning/saar-session-state.d.ts +36 -0
- package/dist/domain/pinning/saar-session-state.d.ts.map +1 -0
- package/dist/domain/pinning/saar-session-state.js +74 -0
- package/dist/domain/pinning/saar-session-state.js.map +1 -0
- package/dist/domain/pinning/session-pinner.d.ts +35 -3
- package/dist/domain/pinning/session-pinner.d.ts.map +1 -1
- package/dist/domain/pinning/session-pinner.js +149 -1
- package/dist/domain/pinning/session-pinner.js.map +1 -1
- package/dist/domain/pipeline/router-pipeline.d.ts +15 -1
- package/dist/domain/pipeline/router-pipeline.d.ts.map +1 -1
- package/dist/domain/pipeline/router-pipeline.js +118 -6
- package/dist/domain/pipeline/router-pipeline.js.map +1 -1
- package/dist/domain/routing/tool-history-guard.d.ts +21 -5
- package/dist/domain/routing/tool-history-guard.d.ts.map +1 -1
- package/dist/domain/routing/tool-history-guard.js +77 -10
- package/dist/domain/routing/tool-history-guard.js.map +1 -1
- package/dist/domain/types/entities.d.ts +48 -0
- package/dist/domain/types/entities.d.ts.map +1 -1
- package/dist/domain/types/index.d.ts +1 -1
- package/dist/domain/types/index.d.ts.map +1 -1
- package/dist/domain/types/schemas.d.ts +24 -0
- package/dist/domain/types/schemas.d.ts.map +1 -1
- package/dist/domain/types/schemas.js +54 -0
- package/dist/domain/types/schemas.js.map +1 -1
- package/dist/infra/gemini-provider.d.ts.map +1 -1
- package/dist/infra/gemini-provider.js +2 -1
- package/dist/infra/gemini-provider.js.map +1 -1
- package/dist/infrastructure/persistence/sqlite-store.d.ts.map +1 -1
- package/dist/infrastructure/persistence/sqlite-store.js +3 -0
- package/dist/infrastructure/persistence/sqlite-store.js.map +1 -1
- package/dist/infrastructure/telemetry/routing-telemetry.d.ts +30 -2
- package/dist/infrastructure/telemetry/routing-telemetry.d.ts.map +1 -1
- package/dist/infrastructure/telemetry/routing-telemetry.js +221 -3
- package/dist/infrastructure/telemetry/routing-telemetry.js.map +1 -1
- package/package.json +5 -4
- package/src/api/explain/router-explain.ts +14 -10
- package/src/config/defaults.ts +18 -1
- package/src/domain/delegation/delegation-context.ts +124 -0
- package/src/domain/pinning/cache-breakeven.ts +219 -0
- package/src/domain/pinning/saar-session-state.ts +93 -0
- package/src/domain/pinning/session-pinner.ts +244 -3
- package/src/domain/pipeline/router-pipeline.ts +159 -7
- package/src/domain/routing/tool-history-guard.ts +108 -10
- package/src/domain/types/entities.ts +54 -0
- package/src/domain/types/index.ts +4 -0
- package/src/domain/types/schemas.ts +69 -0
- package/src/infra/gemini-provider.ts +2 -1
- package/src/infrastructure/persistence/sqlite-store.ts +6 -0
- package/src/infrastructure/telemetry/routing-telemetry.ts +327 -7
|
@@ -13,7 +13,11 @@ import {
|
|
|
13
13
|
} from '@earendil-works/pi-ai/compat';
|
|
14
14
|
import type { ModelRegistry } from '@earendil-works/pi-coding-agent';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
isGoogleDelegationTarget,
|
|
18
|
+
normalizeDelegationContext,
|
|
19
|
+
repairGeminiReplayContext,
|
|
20
|
+
} from '../../../src/domain/delegation/delegation-context.js';
|
|
17
21
|
import {
|
|
18
22
|
computeOutputHeadroom,
|
|
19
23
|
type OutputHeadroomConfig,
|
|
@@ -147,9 +151,15 @@ export function buildDelegationContext(
|
|
|
147
151
|
? deps.executionLedger.getLastExecution(sessionId)
|
|
148
152
|
: null;
|
|
149
153
|
|
|
150
|
-
|
|
154
|
+
const normalized = normalizeDelegationContext(context, targetModel, {
|
|
151
155
|
sessionExecution,
|
|
152
156
|
});
|
|
157
|
+
|
|
158
|
+
if (isGoogleDelegationTarget(targetModel)) {
|
|
159
|
+
return repairGeminiReplayContext(normalized, targetModel, sessionExecution);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return normalized;
|
|
153
163
|
}
|
|
154
164
|
|
|
155
165
|
export function createErrorMessage(
|
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ pi-smart-router builds on ideas from several production and research routing sys
|
|
|
45
45
|
- **Adopted:** [GitHub Copilot HyDRA](https://arxiv.org/abs/2409.08379) (shortfall matching decoupled from model identities), Zero-Tier local edge-cache pattern, [Weave Router](https://github.com/workweave/router) session pinning and multi-objective selection
|
|
46
46
|
- **Rejected:** FrugalGPT sequential cascading (tail latency), RouteLLM matrix factorization (confounder vulnerability), turn-by-turn dynamic routing (cache destruction)
|
|
47
47
|
|
|
48
|
-
See [docs/PRD.md](docs/PRD.md) for full architectural justification.
|
|
48
|
+
See [docs/PRD.md](docs/PRD.md) for full architectural justification, [docs/deep-research.md](docs/deep-research.md) for the research survey, [docs/routing-roadmap.md](docs/routing-roadmap.md) for the prioritized quality backlog, [docs/gemini-research.md](docs/gemini-research.md) for the second-source agent-router report, and [docs/research/README.md](docs/research/README.md) for research provenance.
|
|
49
49
|
|
|
50
50
|
## Prerequisites
|
|
51
51
|
|
|
@@ -169,7 +169,7 @@ pi exposes two different **auto** models. They are easy to confuse but play diff
|
|
|
169
169
|
| `smart-router/auto` | `smart-router` (this extension) | Runs the routing pipeline on every turn and **delegates** to whichever underlying model HyDRA selects |
|
|
170
170
|
| `cursor/auto` | `cursor` (pi registry) | Cursor's opaque auto model — **direct** inference target when selected; Cursor picks the backend model |
|
|
171
171
|
|
|
172
|
-
**Recommended dogfood setup:** use `/model smart-router/auto` so routing, pinning, and telemetry stay active. Enable `cursor/auto` (and other Cursor models such as `composer-latest`) in your scoped fleet so the router can select them when appropriate — for example on planning turns or when the [Gemini tool-history guard](#gemini-thought_signature-400-errors) excludes Google
|
|
172
|
+
**Recommended dogfood setup:** use `/model smart-router/auto` so routing, pinning, and telemetry stay active. Enable `cursor/auto` (and other Cursor models such as `composer-latest`) in your scoped fleet so the router can select them when appropriate — for example on planning turns or when the [Gemini tool-history guard](#gemini-thought_signature-400-errors) excludes unrepairable Google replay state.
|
|
173
173
|
|
|
174
174
|
**When to pin `/model cursor/auto` directly (bypass the router):**
|
|
175
175
|
|
|
@@ -181,7 +181,7 @@ pi exposes two different **auto** models. They are easy to confuse but play diff
|
|
|
181
181
|
|
|
182
182
|
- You want cost/capability-aware model selection across your full authenticated fleet
|
|
183
183
|
- You rely on session pinning, failover, or `/smart-router status` / `history` telemetry
|
|
184
|
-
- Tool-heavy sessions
|
|
184
|
+
- Tool-heavy sessions with Gemini economical models work via in-repo replay repair; add `cursor/auto` for unrepairable Google replay edge cases (see [pi-smart-router#85](https://github.com/beettlle/pi-smart-router/issues/85))
|
|
185
185
|
|
|
186
186
|
Cursor models (`cursor/*`, `composer-*`, and the opaque fleet id `default`) map to **frontier-cloud** tier in `pi-model-mapper.ts` so HyDRA can score them against Gemini and Claude instead of treating them as unknown economical models ([pi-smart-router#40](https://github.com/beettlle/pi-smart-router/issues/40), [pi-smart-router#70](https://github.com/beettlle/pi-smart-router/issues/70)). Related: [pi-smart-router#23](https://github.com/beettlle/pi-smart-router/issues/23) (turn envelope / pin order), [pi-smart-router#37](https://github.com/beettlle/pi-smart-router/issues/37) (Gemini `thought_signature` errors).
|
|
187
187
|
|
|
@@ -343,9 +343,34 @@ Cluster IDs are stable reason-code prefixes (`cluster_low_stakes_general`, `clus
|
|
|
343
343
|
| `SMART_ROUTER_DATASET` | (unset) | Set to `1` to opt in to privacy-safe routing dataset capture (metadata and feature fields only; 30-day / 10k-row retention). Prompt text, messages, and tool arguments are never stored. Required for outcome labels and P(success) training export. See [#8](https://github.com/beettlle/pi-smart-router/issues/8). |
|
|
344
344
|
| `SMART_ROUTER_DATASET_FINGERPRINT` | (unset) | Set to `1` (requires `SMART_ROUTER_DATASET=1`) to store an install-local HMAC-SHA256 fingerprint of each normalized prompt for duplicate detection within this install. The install pepper lives in `.pi-smart-router/.dataset-key` (gitignored) and is never exported. **Warning:** short or common prompts are vulnerable to offline rainbow-table guessing; use only when you accept that tradeoff. See [#10](https://github.com/beettlle/pi-smart-router/issues/10). |
|
|
345
345
|
| `MODELS_YAML_PATH` | `./config/models.yaml` | Fleet catalog path (library API only) |
|
|
346
|
+
| `SMART_ROUTER_PLANNING_TURN_BUFFER` | `2` | SAAR planning buffer: frontier planning turns allowed before hard-lock ([v0.2.0 Continuity](https://github.com/beettlle/pi-smart-router/issues/72)) |
|
|
347
|
+
| `SMART_ROUTER_PREFIX_CACHE_WEIGHT` | `0.20` | SAAR weight on warm prefix value in cache breakeven math (0–1; [#73](https://github.com/beettlle/pi-smart-router/issues/73)) |
|
|
348
|
+
| `SMART_ROUTER_IDLE_TIMEOUT_SECONDS` | `300` | SAAR idle seconds before pin reopens for full re-route |
|
|
349
|
+
| `SMART_ROUTER_SWITCH_THRESHOLD` | `0.5` | SAAR switch score gate (0–1) for tier upgrades during hard-lock |
|
|
346
350
|
| `ROUTER_SAFE_DEFAULT_TIER` | `economical-cloud` | Fallback tier on any routing failure |
|
|
347
351
|
| `LITELLM_PRICING_URL` | — | LiteLLM pricing JSON source |
|
|
348
352
|
|
|
353
|
+
### SAAR session pin and cache breakeven (v0.2.0 Continuity)
|
|
354
|
+
|
|
355
|
+
v0.2.0 adds **Session-Aware Agentic Routing (SAAR)** pin knobs ([#72](https://github.com/beettlle/pi-smart-router/issues/72)) and a **cache breakeven gate** ([#73](https://github.com/beettlle/pi-smart-router/issues/73)) that blocks tier switches when `marginal_savings + future_cache_value <= cache_reprime_cost` — preventing cheap-turn savings from invalidating a warm prefix cache.
|
|
356
|
+
|
|
357
|
+
| Knob | Env var | Default | Effect |
|
|
358
|
+
|------|---------|---------|--------|
|
|
359
|
+
| Planning buffer | `SMART_ROUTER_PLANNING_TURN_BUFFER` | `2` | First N turns may route planning to frontier while pin metadata stays economical |
|
|
360
|
+
| Prefix cache weight | `SMART_ROUTER_PREFIX_CACHE_WEIGHT` | `0.20` | Discounted future cache credit in breakeven |
|
|
361
|
+
| Idle reopen | `SMART_ROUTER_IDLE_TIMEOUT_SECONDS` | `300` | Seconds of inactivity before SAAR resets and pin reopens |
|
|
362
|
+
| Hard-lock upgrade gate | `SMART_ROUTER_SWITCH_THRESHOLD` | `0.5` | Score threshold for tier upgrades after buffer exhaust |
|
|
363
|
+
|
|
364
|
+
**Dogfood verification (multi-turn planning session)**
|
|
365
|
+
|
|
366
|
+
1. Start pi with routing logs: `SMART_ROUTER_LOG_ROUTING=1 pi` (optional: tune SAAR env vars above).
|
|
367
|
+
2. Run `/model smart-router/auto` and begin a multi-turn planning session (planning turns mixed with tool results).
|
|
368
|
+
3. Inspect stderr JSON lines — confirm `saar_summary.buffer_active` / `saar_reason_code: saar_buffer_active` on early planning turns, then `hard_lock: true` / `saar_hard_lock` after the buffer exhausts.
|
|
369
|
+
4. On a warm pinned session, trigger a `tool_result` sub-route — when breakeven fails, expect `breakeven_summary.decision: "blocked"` and `breakeven_reason_code: breakeven_blocked` while the pin holds.
|
|
370
|
+
5. Use `pi router explain` (or `POST /v1/route/explain`) on the same session — `features.breakeven` and `features.saar` mirror telemetry fields for operator audit.
|
|
371
|
+
|
|
372
|
+
See [routing-roadmap.md](docs/routing-roadmap.md) §2 P0 for design context.
|
|
373
|
+
|
|
349
374
|
### P(success) training export (baseline classifier)
|
|
350
375
|
|
|
351
376
|
When `SMART_ROUTER_DATASET=1`, the router records privacy-safe dataset rows and behavioral outcome labels (model override, compaction pin break, `/smart-router feedback good|bad`). Export labeled training data from pi:
|
|
@@ -458,18 +483,21 @@ The `GatewayDispatch` layer wraps the pipeline with:
|
|
|
458
483
|
|
|
459
484
|
If Gemini returns **400 INVALID_ARGUMENT** mentioning `thought_signature`, the router treats this as a **protocol validation error** (incomplete tool-call replay), not provider unavailability — it will **not** failover to another model.
|
|
460
485
|
|
|
461
|
-
|
|
486
|
+
See [Google's thought signatures documentation](https://ai.google.dev/gemini-api/docs/generate-content/thought-signatures).
|
|
487
|
+
|
|
488
|
+
**Primary fix — replay repair (SP-127/128):** before every Google-target delegation, smart-router repairs tool-call replay state: prior turns keep captured `thoughtSignature` values; tool calls missing a signature receive the Google-accepted skip sentinel so pi-ai can replay without a 400. Typical Gemini-first tool loops on `/model smart-router/auto` no longer require `/new` or switching away from Google models.
|
|
462
489
|
|
|
463
|
-
**
|
|
490
|
+
**Narrowed guard fail-safe (SP-129):** sessions with **unrepairable** Google-origin replay state (e.g. redacted thinking blocks paired with tool calls) exclude Gemini from routing (`reason_code: gemini_tool_history_excluded`) unless the operator sets `force_model_id` via `/model`. Repairable Google tool history is delegated normally.
|
|
464
491
|
|
|
465
|
-
**Empty fleet fail-safe (SP-084):** when the guard filters every model in the scoped fleet (e.g. Google/Gemini-only dogfood configs), the router throws an actionable error instead of delegating with `selected_model_id: unknown`. Add a non-Google model such as `openai/gpt-4o-mini` or `cursor/auto` to the fleet, start `/new`, or pin `/model` to force a specific model.
|
|
492
|
+
**Empty fleet fail-safe (SP-084):** when the guard filters every model in the scoped fleet (e.g. Google/Gemini-only dogfood configs with unrepairable replay risk), the router throws an actionable error instead of delegating with `selected_model_id: unknown`. Add a non-Google model such as `openai/gpt-4o-mini` or `cursor/auto` to the fleet, start `/new`, or pin `/model` to force a specific model.
|
|
466
493
|
|
|
467
|
-
**
|
|
494
|
+
**If you still see a `thought_signature` error:**
|
|
468
495
|
|
|
469
|
-
1. Start a fresh session with `/new` in pi.
|
|
470
|
-
2. Switch to a non-Google model (e.g. `/model openai/gpt-4o-mini`) for
|
|
496
|
+
1. Start a fresh session with `/new` in pi (clears unrepairable history).
|
|
497
|
+
2. Switch to a non-Google model (e.g. `/model openai/gpt-4o-mini`) for that session.
|
|
498
|
+
3. Upstream: [pi#6342](https://github.com/earendil-works/pi/issues/6342) tracks pi preserving thought signatures in session replay; smart-router repair covers the common cross-model routing case without waiting on that fix.
|
|
471
499
|
|
|
472
|
-
Related: [pi-smart-router#37](https://github.com/beettlle/pi-smart-router/issues/37), [pi-smart-router#38](https://github.com/beettlle/pi-smart-router/issues/38), [pi-smart-router#40](https://github.com/beettlle/pi-smart-router/issues/40), [pi-smart-router#41](https://github.com/beettlle/pi-smart-router/issues/41), [pi#
|
|
500
|
+
Related: [pi-smart-router#37](https://github.com/beettlle/pi-smart-router/issues/37), [pi-smart-router#38](https://github.com/beettlle/pi-smart-router/issues/38), [pi-smart-router#40](https://github.com/beettlle/pi-smart-router/issues/40), [pi-smart-router#41](https://github.com/beettlle/pi-smart-router/issues/41), [pi-smart-router#85](https://github.com/beettlle/pi-smart-router/issues/85).
|
|
473
501
|
|
|
474
502
|
### Explain endpoint (library API)
|
|
475
503
|
|
|
@@ -526,7 +554,8 @@ Contributors must run `npm run build` before publishing or consuming the library
|
|
|
526
554
|
| Script | Purpose |
|
|
527
555
|
|--------|---------|
|
|
528
556
|
| `npm run build` | Compile library to `dist/` (`tsc --project tsconfig.build.json`) |
|
|
529
|
-
| `npm run release:check` | Pre-release gate
|
|
557
|
+
| `npm run release:check` | Pre-release gate: `verify:ci` + consumer pack (`npm install --omit=dev` on tarball) |
|
|
558
|
+
| `npm run release:consumer-pack` | Pack tarball and verify production dependencies resolve (catches missing runtime deps) |
|
|
530
559
|
| `npm run verify:ci` | Full CI parity: build, typecheck, lint, test, coverage |
|
|
531
560
|
| `npm run typecheck` | TypeScript strict mode check (`tsc --noEmit`) |
|
|
532
561
|
| `npm test` | Run test suite (`vitest run`) |
|
|
@@ -539,15 +568,14 @@ Contributors must run `npm run build` before publishing or consuming the library
|
|
|
539
568
|
|
|
540
569
|
### Releasing
|
|
541
570
|
|
|
542
|
-
Tag-triggered publish via GitHub Actions (requires `NPMSECRET` repository secret)
|
|
571
|
+
Tag-triggered publish via GitHub Actions (requires `NPMSECRET` repository secret). pi.dev gallery listing syncs automatically from npm (`pi-package` keyword); no separate submit step.
|
|
543
572
|
|
|
544
|
-
1. `npm run release:check`
|
|
545
|
-
2. `npm version 0.1.
|
|
573
|
+
1. `npm run release:check` (includes consumer pack verify)
|
|
574
|
+
2. `npm version 0.1.1` (creates commit + `v0.1.1` tag)
|
|
546
575
|
3. `git push && git push --tags`
|
|
547
|
-
4. Actions → **Release** runs `npm publish
|
|
548
|
-
5. Post-publish smoke: `pi install npm:pi-smart-router` and `/model smart-router/auto`
|
|
576
|
+
4. Actions → **Release** runs pack smoke, consumer pack verify, `npm publish`, and creates a GitHub Release
|
|
549
577
|
|
|
550
|
-
Re-publish a failed release: Actions → Release → Run workflow with existing tag (e.g. `v0.1.
|
|
578
|
+
Re-publish a failed release: Actions → Release → Run workflow with existing tag (e.g. `v0.1.1`).
|
|
551
579
|
|
|
552
580
|
Dry-run tarball contents locally:
|
|
553
581
|
|
|
@@ -556,6 +584,16 @@ npm run release:check
|
|
|
556
584
|
npm pack --dry-run
|
|
557
585
|
```
|
|
558
586
|
|
|
587
|
+
**Post-publish smoke (manual, macOS):** CI does not run `pi install`. After publish:
|
|
588
|
+
|
|
589
|
+
```bash
|
|
590
|
+
pi install npm:pi-smart-router@0.1.1
|
|
591
|
+
pi --list-models | grep smart-router
|
|
592
|
+
# in pi: /model smart-router/auto, /smart-router status
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Confirm https://pi.dev/packages/pi-smart-router shows the new version (may lag npm by a few minutes).
|
|
596
|
+
|
|
559
597
|
### Test suite
|
|
560
598
|
|
|
561
599
|
1117 tests across 61 test files covering:
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
* - MUST produce a decision identical to the live pipeline for the same input
|
|
13
13
|
* - MUST emit no RoutingTelemetry with upstream cost (routing_latency_ms only)
|
|
14
14
|
*/
|
|
15
|
-
import type { ModelProfile, RoutingDecision } from '../../domain/types/index.js';
|
|
15
|
+
import type { ModelProfile, RoutingDecision, SaarConfig } from '../../domain/types/index.js';
|
|
16
16
|
import { RouterPipeline } from '../../domain/pipeline/router-pipeline.js';
|
|
17
17
|
import type { ClusterMatcher } from '../../domain/matching/cluster-matcher.js';
|
|
18
|
+
import type { SessionPinner } from '../../domain/pinning/session-pinner.js';
|
|
18
19
|
export interface ExplainValidationError {
|
|
19
20
|
readonly error: 'validation_failed';
|
|
20
21
|
readonly details: readonly string[];
|
|
@@ -36,6 +37,8 @@ export interface ExplainHandlerDeps {
|
|
|
36
37
|
readonly fleet: readonly ModelProfile[];
|
|
37
38
|
readonly pipeline: RouterPipeline;
|
|
38
39
|
readonly clusterMatcher?: ClusterMatcher;
|
|
40
|
+
readonly sessionPinner?: SessionPinner;
|
|
41
|
+
readonly saarConfig?: SaarConfig;
|
|
39
42
|
}
|
|
40
43
|
/**
|
|
41
44
|
* Create an explain handler bound to a shared pipeline instance.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-explain.d.ts","sourceRoot":"","sources":["../../../src/api/explain/router-explain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAA2B,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"router-explain.d.ts","sourceRoot":"","sources":["../../../src/api/explain/router-explain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAA2B,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEtH,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAE1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAK5E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;CAChC;AAED,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAIpF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC;AAID;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,IAU7B,SAAS,OAAO,KAAG,OAAO,CAAC,aAAa,CAAC,CAyCxE"}
|
|
@@ -23,7 +23,13 @@ import { enrichRoutingDecisionForExplain } from '../../infrastructure/telemetry/
|
|
|
23
23
|
* session pin state and stage ordering are identical.
|
|
24
24
|
*/
|
|
25
25
|
export function createExplainHandler(deps) {
|
|
26
|
-
const { fleet, pipeline, clusterMatcher } = deps;
|
|
26
|
+
const { fleet, pipeline, clusterMatcher, sessionPinner, saarConfig } = deps;
|
|
27
|
+
const explainEnrichmentOptions = {
|
|
28
|
+
fleet,
|
|
29
|
+
...(clusterMatcher !== undefined ? { clusterMatcher } : {}),
|
|
30
|
+
...(sessionPinner !== undefined ? { sessionPinner } : {}),
|
|
31
|
+
...(saarConfig !== undefined ? { saarConfig } : {}),
|
|
32
|
+
};
|
|
27
33
|
return async function explain(rawBody) {
|
|
28
34
|
const parsed = RoutingRequestSchema.safeParse(rawBody);
|
|
29
35
|
if (!parsed.success) {
|
|
@@ -41,10 +47,7 @@ export function createExplainHandler(deps) {
|
|
|
41
47
|
const decision = await pipeline.route(request);
|
|
42
48
|
return {
|
|
43
49
|
status: 200,
|
|
44
|
-
body: await enrichRoutingDecisionForExplain(request, decision,
|
|
45
|
-
fleet,
|
|
46
|
-
...(clusterMatcher !== undefined ? { clusterMatcher } : {}),
|
|
47
|
-
}),
|
|
50
|
+
body: await enrichRoutingDecisionForExplain(request, decision, explainEnrichmentOptions),
|
|
48
51
|
};
|
|
49
52
|
}
|
|
50
53
|
catch {
|
|
@@ -60,10 +63,7 @@ export function createExplainHandler(deps) {
|
|
|
60
63
|
};
|
|
61
64
|
return {
|
|
62
65
|
status: 503,
|
|
63
|
-
body: await enrichRoutingDecisionForExplain(request, decision,
|
|
64
|
-
fleet,
|
|
65
|
-
...(clusterMatcher !== undefined ? { clusterMatcher } : {}),
|
|
66
|
-
}),
|
|
66
|
+
body: await enrichRoutingDecisionForExplain(request, decision, explainEnrichmentOptions),
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-explain.js","sourceRoot":"","sources":["../../../src/api/explain/router-explain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"router-explain.js","sourceRoot":"","sources":["../../../src/api/explain/router-explain.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* Operator configuration defaults (FR-021).
|
|
3
3
|
* Values sourced from specs/001-build-smart-router/data-model.md § Configuration (Operator).
|
|
4
4
|
*/
|
|
5
|
-
import type
|
|
5
|
+
import { type OperatorConfig } from '../domain/types/schemas.js';
|
|
6
|
+
export { DEFAULT_SAAR_CONFIG, resolveSaarConfigFromEnv } from '../domain/types/schemas.js';
|
|
7
|
+
/** Merge operator env overrides onto defaults (SAAR section only today). */
|
|
8
|
+
export declare function resolveOperatorConfigFromEnv(base?: OperatorConfig): OperatorConfig;
|
|
6
9
|
export declare const DEFAULT_OPERATOR_CONFIG: Readonly<OperatorConfig>;
|
|
7
10
|
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3F,4EAA4E;AAC5E,wBAAgB,4BAA4B,CAC1C,IAAI,GAAE,cAAwC,GAC7C,cAAc,CAKhB;AAED,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,cAAc,CA2BnD,CAAC"}
|
package/dist/config/defaults.js
CHANGED
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
* Operator configuration defaults (FR-021).
|
|
3
3
|
* Values sourced from specs/001-build-smart-router/data-model.md § Configuration (Operator).
|
|
4
4
|
*/
|
|
5
|
+
import { DEFAULT_SAAR_CONFIG, resolveSaarConfigFromEnv, } from '../domain/types/schemas.js';
|
|
5
6
|
import { DEFAULT_LOW_INTENSITY_WEIGHTS } from '../domain/routing/tier-features.js';
|
|
7
|
+
export { DEFAULT_SAAR_CONFIG, resolveSaarConfigFromEnv } from '../domain/types/schemas.js';
|
|
8
|
+
/** Merge operator env overrides onto defaults (SAAR section only today). */
|
|
9
|
+
export function resolveOperatorConfigFromEnv(base = DEFAULT_OPERATOR_CONFIG) {
|
|
10
|
+
return {
|
|
11
|
+
...base,
|
|
12
|
+
saar: resolveSaarConfigFromEnv(base.saar),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
6
15
|
export const DEFAULT_OPERATOR_CONFIG = {
|
|
7
16
|
frugality: {
|
|
8
17
|
lambda_cost: 0.5,
|
|
@@ -29,5 +38,6 @@ export const DEFAULT_OPERATOR_CONFIG = {
|
|
|
29
38
|
low_threshold: 0.35,
|
|
30
39
|
p_success_alpha: 0.5,
|
|
31
40
|
},
|
|
41
|
+
saar: DEFAULT_SAAR_CONFIG,
|
|
32
42
|
};
|
|
33
43
|
//# sourceMappingURL=defaults.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GAEzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AAEnF,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3F,4EAA4E;AAC5E,MAAM,UAAU,4BAA4B,CAC1C,OAAuB,uBAAuB;IAE9C,OAAO;QACL,GAAG,IAAI;QACP,IAAI,EAAE,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAA6B;IAC/D,SAAS,EAAE;QACT,WAAW,EAAE,GAAG;QAChB,cAAc,EAAE,GAAG;QACnB,gBAAgB,EAAE,IAAI;KACvB;IACD,eAAe,EAAE;QACf,SAAS,EAAE,CAAC;KACb;IACD,OAAO,EAAE;QACP,cAAc,EAAE,EAAE;KACnB;IACD,KAAK,EAAE;QACL,kBAAkB,EAAE,EAAE;QACtB,4BAA4B,EAAE,CAAC;QAC/B,qBAAqB,EAAE,EAAE;KAC1B;IACD,KAAK,EAAE;QACL,mBAAmB,EAAE,0BAA0B;KAChD;IACD,aAAa,EAAE;QACb,OAAO,EAAE,6BAA6B;QACtC,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,GAAG;KACrB;IACD,IAAI,EAAE,mBAAmB;CACjB,CAAC"}
|
|
@@ -5,11 +5,25 @@
|
|
|
5
5
|
* target model. Virtual smart-router tags break isSameModel and strip replay
|
|
6
6
|
* state (thoughtSignature, thinkingSignature, etc.).
|
|
7
7
|
*/
|
|
8
|
-
import type { Api, Context, Message, Model } from '@earendil-works/pi-ai/compat';
|
|
8
|
+
import type { Api, AssistantMessage, Context, Message, Model } from '@earendil-works/pi-ai/compat';
|
|
9
9
|
import type { ExecutionModel } from './execution-ledger.js';
|
|
10
10
|
export declare const VIRTUAL_ROUTER_PROVIDER: "smart-router";
|
|
11
11
|
export declare const VIRTUAL_ROUTER_MODEL_ID: "auto";
|
|
12
|
+
/**
|
|
13
|
+
* Google Gemini bypass sentinel for tool-call replay when no signature was captured.
|
|
14
|
+
*
|
|
15
|
+
* Semantic value (Google API / pi#1829): `skip_thought_signature_validator`.
|
|
16
|
+
* Wire format (@earendil-works/pi-ai@0.80.3 google-shared): TYPE_BYTES — base64
|
|
17
|
+
* only. Plain string fails `isValidThoughtSignature`, so pi-ai strips it before
|
|
18
|
+
* the request leaves the client. We store/send the base64 encoding of the literal
|
|
19
|
+
* sentinel string so both Google validation and pi-ai serialization accept it.
|
|
20
|
+
*
|
|
21
|
+
* @see https://ai.google.dev/gemini-api/docs/thought-signatures
|
|
22
|
+
*/
|
|
23
|
+
export declare const GEMINI_SKIP_THOUGHT_SIGNATURE_SENTINEL: "c2tpcF90aG91Z2h0X3NpZ25hdHVyZV92YWxpZGF0b3I=";
|
|
12
24
|
export declare function isVirtualRouterIdentity(provider: string, modelId: string): boolean;
|
|
25
|
+
export declare function isGoogleDelegationTarget<TApi extends Api>(model: Model<TApi>): boolean;
|
|
26
|
+
export declare function isGoogleOriginAssistantMessage(message: AssistantMessage): boolean;
|
|
13
27
|
export declare function hasReplaySensitiveState(messages: readonly Message[]): boolean;
|
|
14
28
|
export interface NormalizeDelegationContextOptions {
|
|
15
29
|
readonly virtualProvider?: typeof VIRTUAL_ROUTER_PROVIDER;
|
|
@@ -20,4 +34,12 @@ export interface NormalizeDelegationContextOptions {
|
|
|
20
34
|
* model identity pi-ai expects for same-model replay.
|
|
21
35
|
*/
|
|
22
36
|
export declare function normalizeDelegationContext<TApi extends Api>(context: Context, targetModel: Model<TApi>, options?: NormalizeDelegationContextOptions): Context;
|
|
37
|
+
/**
|
|
38
|
+
* Repair Gemini tool-call replay for cross-model Google delegation.
|
|
39
|
+
*
|
|
40
|
+
* Call after {@link normalizeDelegationContext}. Aligns Google-origin assistant
|
|
41
|
+
* identity to the delegation target and injects the thought-signature sentinel
|
|
42
|
+
* when tool calls lack a captured signature.
|
|
43
|
+
*/
|
|
44
|
+
export declare function repairGeminiReplayContext<TApi extends Api>(context: Context, targetModel: Model<TApi>, sessionExecution?: ExecutionModel | null): Context;
|
|
23
45
|
//# sourceMappingURL=delegation-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegation-context.d.ts","sourceRoot":"","sources":["../../../src/domain/delegation/delegation-context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,GAAG,
|
|
1
|
+
{"version":3,"file":"delegation-context.d.ts","sourceRoot":"","sources":["../../../src/domain/delegation/delegation-context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,GAAG,EACH,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,KAAK,EACN,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,eAAO,MAAM,uBAAuB,EAAG,cAAuB,CAAC;AAC/D,eAAO,MAAM,uBAAuB,EAAG,MAAe,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sCAAsC,EACjD,8CAAuD,CAAC;AAW1D,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAElF;AAED,wBAAgB,wBAAwB,CAAC,IAAI,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAetF;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAmBjF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CA+B7E;AAoCD,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,uBAAuB,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACnD;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,SAAS,GAAG,EACzD,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,EACxB,OAAO,CAAC,EAAE,iCAAiC,GAC1C,OAAO,CA2BT;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,SAAS,GAAG,EACxD,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,EACxB,gBAAgB,CAAC,EAAE,cAAc,GAAG,IAAI,GACvC,OAAO,CA4BT"}
|
|
@@ -7,9 +7,57 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export const VIRTUAL_ROUTER_PROVIDER = 'smart-router';
|
|
9
9
|
export const VIRTUAL_ROUTER_MODEL_ID = 'auto';
|
|
10
|
+
/**
|
|
11
|
+
* Google Gemini bypass sentinel for tool-call replay when no signature was captured.
|
|
12
|
+
*
|
|
13
|
+
* Semantic value (Google API / pi#1829): `skip_thought_signature_validator`.
|
|
14
|
+
* Wire format (@earendil-works/pi-ai@0.80.3 google-shared): TYPE_BYTES — base64
|
|
15
|
+
* only. Plain string fails `isValidThoughtSignature`, so pi-ai strips it before
|
|
16
|
+
* the request leaves the client. We store/send the base64 encoding of the literal
|
|
17
|
+
* sentinel string so both Google validation and pi-ai serialization accept it.
|
|
18
|
+
*
|
|
19
|
+
* @see https://ai.google.dev/gemini-api/docs/thought-signatures
|
|
20
|
+
*/
|
|
21
|
+
export const GEMINI_SKIP_THOUGHT_SIGNATURE_SENTINEL = 'c2tpcF90aG91Z2h0X3NpZ25hdHVyZV92YWxpZGF0b3I=';
|
|
22
|
+
const GOOGLE_DELEGATION_APIS = new Set(['google-generative-ai', 'google-vertex']);
|
|
23
|
+
const GOOGLE_ORIGIN_PROVIDER_ALIASES = new Set([
|
|
24
|
+
'google',
|
|
25
|
+
'google-gemini',
|
|
26
|
+
'google-generative-ai',
|
|
27
|
+
'gemini',
|
|
28
|
+
]);
|
|
10
29
|
export function isVirtualRouterIdentity(provider, modelId) {
|
|
11
30
|
return provider === VIRTUAL_ROUTER_PROVIDER && modelId === VIRTUAL_ROUTER_MODEL_ID;
|
|
12
31
|
}
|
|
32
|
+
export function isGoogleDelegationTarget(model) {
|
|
33
|
+
if (!GOOGLE_DELEGATION_APIS.has(model.api)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const provider = model.provider.trim().toLowerCase();
|
|
37
|
+
if (GOOGLE_ORIGIN_PROVIDER_ALIASES.has(provider)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (provider.includes('google') || provider.includes('gemini')) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return provider === 'cursor' && /gemini/i.test(model.id);
|
|
44
|
+
}
|
|
45
|
+
export function isGoogleOriginAssistantMessage(message) {
|
|
46
|
+
if (isVirtualRouterIdentity(message.provider, message.model)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
if (GOOGLE_DELEGATION_APIS.has(message.api)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
const provider = message.provider.trim().toLowerCase();
|
|
53
|
+
if (GOOGLE_ORIGIN_PROVIDER_ALIASES.has(provider)) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (provider.includes('google') || provider.includes('gemini')) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return provider === 'cursor' && /gemini/i.test(message.model);
|
|
60
|
+
}
|
|
13
61
|
export function hasReplaySensitiveState(messages) {
|
|
14
62
|
for (const message of messages) {
|
|
15
63
|
if (message.role !== 'assistant') {
|
|
@@ -44,6 +92,21 @@ function rewriteAssistantIdentity(message, executionModel) {
|
|
|
44
92
|
model: executionModel.id,
|
|
45
93
|
};
|
|
46
94
|
}
|
|
95
|
+
function repairGoogleOriginAssistantMessage(message, targetExecution) {
|
|
96
|
+
const content = message.content.map((block) => {
|
|
97
|
+
if (block.type !== 'toolCall') {
|
|
98
|
+
return block;
|
|
99
|
+
}
|
|
100
|
+
if (block.thoughtSignature && block.thoughtSignature.length > 0) {
|
|
101
|
+
return block;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
...block,
|
|
105
|
+
thoughtSignature: GEMINI_SKIP_THOUGHT_SIGNATURE_SENTINEL,
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
return rewriteAssistantIdentity({ ...message, content }, targetExecution);
|
|
109
|
+
}
|
|
47
110
|
/**
|
|
48
111
|
* Rewrite assistant messages tagged with the virtual router to the executing
|
|
49
112
|
* model identity pi-ai expects for same-model replay.
|
|
@@ -70,4 +133,34 @@ export function normalizeDelegationContext(context, targetModel, options) {
|
|
|
70
133
|
});
|
|
71
134
|
return { ...context, messages };
|
|
72
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Repair Gemini tool-call replay for cross-model Google delegation.
|
|
138
|
+
*
|
|
139
|
+
* Call after {@link normalizeDelegationContext}. Aligns Google-origin assistant
|
|
140
|
+
* identity to the delegation target and injects the thought-signature sentinel
|
|
141
|
+
* when tool calls lack a captured signature.
|
|
142
|
+
*/
|
|
143
|
+
export function repairGeminiReplayContext(context, targetModel, sessionExecution) {
|
|
144
|
+
// Accepted for SP-128 call-site symmetry with normalizeDelegationContext; identity
|
|
145
|
+
// always aligns to the delegation target so pi-ai isSameModel matches targetModel.
|
|
146
|
+
void sessionExecution;
|
|
147
|
+
if (!isGoogleDelegationTarget(targetModel)) {
|
|
148
|
+
return context;
|
|
149
|
+
}
|
|
150
|
+
const targetExecution = {
|
|
151
|
+
provider: targetModel.provider,
|
|
152
|
+
api: targetModel.api,
|
|
153
|
+
id: targetModel.id,
|
|
154
|
+
};
|
|
155
|
+
const messages = context.messages.map((message) => {
|
|
156
|
+
if (message.role !== 'assistant') {
|
|
157
|
+
return message;
|
|
158
|
+
}
|
|
159
|
+
if (!isGoogleOriginAssistantMessage(message)) {
|
|
160
|
+
return message;
|
|
161
|
+
}
|
|
162
|
+
return repairGoogleOriginAssistantMessage(message, targetExecution);
|
|
163
|
+
});
|
|
164
|
+
return { ...context, messages };
|
|
165
|
+
}
|
|
73
166
|
//# sourceMappingURL=delegation-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegation-context.js","sourceRoot":"","sources":["../../../src/domain/delegation/delegation-context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAuB,CAAC;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAe,CAAC;AAEvD,MAAM,UAAU,uBAAuB,CAAC,QAAgB,EAAE,OAAe;IACvE,OAAO,QAAQ,KAAK,uBAAuB,IAAI,OAAO,KAAK,uBAAuB,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,QAA4B;IAClE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACjC,SAAS;QACX,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACnB,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,IAAI,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClE,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAED,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IACE,KAAK,CAAC,IAAI,KAAK,UAAU;gBACzB,KAAK,CAAC,gBAAgB;gBACtB,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EACjC,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,wBAAwB,CAC/B,OAAyB,EACzB,cAA8B;IAE9B,OAAO;QACL,GAAG,OAAO;QACV,QAAQ,EAAE,cAAc,CAAC,QAAwC;QACjE,GAAG,EAAE,cAAc,CAAC,GAAG;QACvB,KAAK,EAAE,cAAc,CAAC,EAAE;KACzB,CAAC;AACJ,CAAC;AAOD;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAgB,EAChB,WAAwB,EACxB,OAA2C;IAE3C,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,uBAAuB,CAAC;IAC5E,MAAM,iBAAiB,GAAmB;QACxC,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,GAAG,EAAE,WAAW,CAAC,GAAG;QACpB,EAAE,EAAE,WAAW,CAAC,EAAE;KACnB,CAAC;IACF,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,IAAI,IAAI,CAAC;IAC3D,MAAM,mBAAmB,GAAG,gBAAgB,IAAI,iBAAiB,CAAC;IAElE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAChD,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACjC,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC;QAC1B,IACE,SAAS,CAAC,QAAQ,KAAK,eAAe;YACtC,SAAS,CAAC,KAAK,KAAK,uBAAuB,EAC3C,CAAC;YACD,OAAO,wBAAwB,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC;AAClC,CAAC"}
|
|
1
|
+
{"version":3,"file":"delegation-context.js","sourceRoot":"","sources":["../../../src/domain/delegation/delegation-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache breakeven economics — SAAR gate (#73), routing-roadmap P0.
|
|
3
|
+
*
|
|
4
|
+
* Decides whether a proposed tier switch is justified when a warm prefix
|
|
5
|
+
* cache would be invalidated. Switch only when:
|
|
6
|
+
*
|
|
7
|
+
* marginal_savings + future_cache_value > cache_reprime_cost
|
|
8
|
+
*
|
|
9
|
+
* Distinct from legacy FR-008 warmup rule in `cache-economics.ts` (#32).
|
|
10
|
+
*/
|
|
11
|
+
/** SAAR knobs used when deriving future_cache_value from a warm prefix. */
|
|
12
|
+
export interface SaarBreakevenConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Weight applied to discounted prefix value when estimating future cache
|
|
15
|
+
* benefit. SAAR default: 0.20.
|
|
16
|
+
*/
|
|
17
|
+
readonly prefix_cache_weight?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Input-token discount rate for a cache hit on the warm prefix.
|
|
20
|
+
* Default: 0.90 (90 % discount per routing-roadmap / provider caching).
|
|
21
|
+
*/
|
|
22
|
+
readonly prefix_cache_discount?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface CacheBreakevenResult {
|
|
25
|
+
readonly shouldSwitch: boolean;
|
|
26
|
+
readonly marginal_savings: number;
|
|
27
|
+
readonly future_cache_value: number;
|
|
28
|
+
readonly cache_reprime_cost: number;
|
|
29
|
+
readonly total_benefit: number;
|
|
30
|
+
readonly reason: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Estimate the retained value of a warm prefix cache using SAAR
|
|
34
|
+
* `prefix_cache_weight`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function computeFutureCacheValue(warm_prefix_tokens: number, pinned_cost_per_1m: number, config?: SaarBreakevenConfig): number;
|
|
37
|
+
/**
|
|
38
|
+
* Cost to re-transmit a cold prefix on the candidate provider after a switch.
|
|
39
|
+
*/
|
|
40
|
+
export declare function computeCacheReprimeCost(warm_prefix_tokens: number, candidate_cost_per_1m: number): number;
|
|
41
|
+
/**
|
|
42
|
+
* Evaluate whether a proposed switch clears the cache breakeven gate.
|
|
43
|
+
*
|
|
44
|
+
* Returns `shouldSwitch: false` on invalid inputs (fail-safe deny).
|
|
45
|
+
*/
|
|
46
|
+
export declare function evaluateCacheBreakeven(marginal_savings: number, future_cache_value: number, cache_reprime_cost: number): CacheBreakevenResult;
|
|
47
|
+
/**
|
|
48
|
+
* Derive breakeven components from prefix token economics, then evaluate.
|
|
49
|
+
*/
|
|
50
|
+
export declare function evaluateCacheBreakevenForPrefix(marginal_savings: number, warm_prefix_tokens: number, pinned_cost_per_1m: number, candidate_cost_per_1m: number, config?: SaarBreakevenConfig): CacheBreakevenResult;
|
|
51
|
+
//# sourceMappingURL=cache-breakeven.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-breakeven.d.ts","sourceRoot":"","sources":["../../../src/domain/pinning/cache-breakeven.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAEtC;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAoDD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,MAAM,EAC1B,MAAM,CAAC,EAAE,mBAAmB,GAC3B,MAAM,CAiBR;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,kBAAkB,EAAE,MAAM,EAC1B,qBAAqB,EAAE,MAAM,GAC5B,MAAM,CAUR;AAID;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,MAAM,GACzB,oBAAoB,CAmCtB;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,MAAM,EAC1B,qBAAqB,EAAE,MAAM,EAC7B,MAAM,CAAC,EAAE,mBAAmB,GAC3B,oBAAoB,CA6BtB"}
|