@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.
@@ -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)