@kylebrodeur/pi-model-router 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/CONTRIBUTING.md +310 -0
- package/LEARNINGS.md +181 -0
- package/LICENSE +21 -0
- package/QUICKSTART.md +111 -0
- package/README.md +195 -0
- package/TESTING.md +374 -0
- package/docs/ARCHITECTURE.md +54 -0
- package/docs/UPSTREAM_ISSUE_scoped_models.md +94 -0
- package/extensions/commands.ts +1068 -0
- package/extensions/config.ts +415 -0
- package/extensions/constants.ts +1 -0
- package/extensions/index.ts +583 -0
- package/extensions/ollama-sync.ts +254 -0
- package/extensions/provider.ts +558 -0
- package/extensions/rate-limit.ts +317 -0
- package/extensions/routing.ts +418 -0
- package/extensions/scope-shim.ts +213 -0
- package/extensions/state.ts +49 -0
- package/extensions/types.ts +148 -0
- package/extensions/ui.ts +130 -0
- package/model-router.agent-bus.json +15 -0
- package/model-router.essential.json +31 -0
- package/model-router.example.json +70 -0
- package/model-router.ledger.json +15 -0
- package/package.json +64 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Extension API: expose `setScopedModels` for dynamic model cycle lists
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
`AgentSession` already supports `scopedModels` — a per-session list of models the user cycles through with `Ctrl+P`. This list is currently **not accessible from the extension API**. Exposing `setScopedModels` (and optionally `getScopedModels`) on `ExtensionAPI` or `ExtensionContext` would let extensions curate the cycle list dynamically based on session state.
|
|
6
|
+
|
|
7
|
+
## Prior Context
|
|
8
|
+
|
|
9
|
+
This was raised before in #3328 and #3330 but auto-closed due to new-contributor policy before maintainer review. Re-opening here with a narrower scope focused on the API surface.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What do you want to change?
|
|
14
|
+
|
|
15
|
+
Expose `setScopedModels` to the extension runtime so extensions can modify the `Ctrl+P` model cycle list at runtime.
|
|
16
|
+
|
|
17
|
+
### Proposed API
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// Option A: On ExtensionAPI (preferred — consistent with pi.setModel / pi.registerProvider)
|
|
21
|
+
interface ExtensionAPI {
|
|
22
|
+
// ... existing methods ...
|
|
23
|
+
setScopedModels(models: Array<ScopedModelEntry>): void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ScopedModelEntry {
|
|
27
|
+
model: Model<any>;
|
|
28
|
+
thinkingLevel?: ThinkingLevel;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// Option B: On ExtensionContext (if it needs session awareness)
|
|
34
|
+
interface ExtensionContext {
|
|
35
|
+
// ...
|
|
36
|
+
setScopedModels(entries: Array<ScopedModelEntry>): void;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Behavior
|
|
41
|
+
|
|
42
|
+
- `setScopedModels` replaces the current scoped model list immediately (no reload required)
|
|
43
|
+
- The new list is reflected in the `/scoped-models` UI and `Ctrl+P` cycling
|
|
44
|
+
- If empty, falls back to all available models (current behavior)
|
|
45
|
+
- Should match the existing internal `AgentSession.setScopedModels()` signature
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Why?
|
|
50
|
+
|
|
51
|
+
1. **Dynamic model discovery**: An extension that registers a custom provider (e.g., from a local proxy or Ollama) may want to limit `Ctrl+P` to only the models from that provider for the current session
|
|
52
|
+
2. **Compliance / project-specific scoping**: Different projects require different providers. Extensions should be able to enforce a curated list instead of requiring users to pass `--models` flags
|
|
53
|
+
3. **Dynamic tier lists**: When using tiered routing, an extension may want `Ctrl+P` to cycle only models in the current tier (e.g., `high → medium → low`) rather than every model in the registry
|
|
54
|
+
4. **Session-start initialization**: An extension could read `PI_SCOPED_MODELS` from the environment and set the list during `session_start`, avoiding CLI flags
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## How? (optional)
|
|
59
|
+
|
|
60
|
+
### Minimal Implementation Path
|
|
61
|
+
|
|
62
|
+
The internal `AgentSession._scopedModels` already has a getter and a `setScopedModels()` method. The work is:
|
|
63
|
+
|
|
64
|
+
1. **Add the method to `ExtensionAPI`** (in `core/extensions/types.d.ts`)
|
|
65
|
+
2. **Wire it** in `core/extensions/runner.ts` to delegate to the bound `AgentSession`
|
|
66
|
+
3. **(Optional)** Expose `resolveModelScope` from the model resolver so extensions can parse shorthand references (e.g., `"anthropic/*"` or `"claude-sonnet-4"`) without reimplementing the glob matching
|
|
67
|
+
|
|
68
|
+
### Example Extension Usage
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
pi.on('session_start', async (event, ctx) => {
|
|
72
|
+
if (event.reason !== 'startup') return;
|
|
73
|
+
|
|
74
|
+
// Curate cycle list to only high-reasoning models
|
|
75
|
+
const highReasoning = ctx.modelRegistry.getAvailable()
|
|
76
|
+
.filter(m => m.reasoning)
|
|
77
|
+
.map(m => ({ model: m, thinkingLevel: 'high' as ThinkingLevel }));
|
|
78
|
+
|
|
79
|
+
pi.setScopedModels(highReasoning);
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Does this break anything?
|
|
86
|
+
|
|
87
|
+
No. This is an additive API change. Existing sessions without extensions calling `setScopedModels` behave identically.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Related
|
|
92
|
+
|
|
93
|
+
- #3328 — Original request (closed by bot)
|
|
94
|
+
- #3330 — Duplicate (closed by bot)
|