pi-set-model 0.1.3 → 0.1.5
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 +17 -0
- package/LICENSE +3 -0
- package/README.md +4 -2
- package/package.json +23 -5
- package/set-model.ts +16 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.5 - 2026-08-23
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Add the copyright holder and EUPL licensing notice to the package license and canonical TypeScript source.
|
|
8
|
+
- Identify KAPPER NETWORK-COMMUNICATIONS GmbH and kapper.net in the npm author metadata.
|
|
9
|
+
|
|
10
|
+
## 0.1.4 - 2026-08-23
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Mark Pi's host-provided SDK packages as optional wildcard peers so npm does not install a redundant Pi SDK dependency tree.
|
|
15
|
+
- Verify development and tests against Pi SDK 0.84.2 while retaining runtime compatibility with Pi 0.84.1 and newer.
|
|
16
|
+
- Reject empty saved preference fields and explicitly clamp restored thinking levels with Pi's model-capability helper.
|
|
17
|
+
- Document that the individual package and GitHub bundle must not be installed together.
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pi-set-model
|
|
2
2
|
|
|
3
|
-
Remembers Pi's selected model and thinking level for each project folder. Requires
|
|
3
|
+
Remembers Pi's selected model and thinking level for each project folder. Requires Pi 0.84.1 or newer (tested with the current Pi 0.84.2 release).
|
|
4
4
|
|
|
5
5
|
After selecting a model and thinking level, explicitly save that combination for the current working directory with `/set-model set`. New Pi sessions opened in that directory restore it, rather than retaining the model selected in another project. Later `/model` or thinking changes do not modify the saved preference unless you run `/set-model set` again.
|
|
6
6
|
|
|
@@ -8,6 +8,8 @@ Preferences are stored in the project at `.pi/set-model.json`; they are never sh
|
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
+
> **Avoid duplicate installation.** Install this npm package or the GitHub bundle, not both. Loading both copies can duplicate commands and preference-restoration handlers.
|
|
12
|
+
|
|
11
13
|
```bash
|
|
12
14
|
pi install npm:pi-set-model
|
|
13
15
|
```
|
|
@@ -31,7 +33,7 @@ Autocomplete completes `/setm...` to `/set-model` without adding a trailing spac
|
|
|
31
33
|
|
|
32
34
|
The folder is Pi's current working directory. Run Pi from the project root when you want one preference for the whole project. The setting is saved at `<cwd>/.pi/set-model.json`.
|
|
33
35
|
|
|
34
|
-
If the saved model is unavailable or has no configured API key, Pi keeps the active model and shows a warning. Thinking levels are restored after the model and
|
|
36
|
+
If the saved model is unavailable or has no configured API key, Pi keeps the active model and shows a warning. Empty or malformed preference fields are ignored. Thinking levels are restored after the model and explicitly clamped with Pi's model-capability helper; the restore notice identifies an unsupported saved level. When the session ends, the model and thinking level that were active before the project preference was applied are restored.
|
|
35
37
|
|
|
36
38
|
## Issues and feedback
|
|
37
39
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-set-model",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Pi extension that remembers model and thinking level per project folder",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
7
7
|
"keywords": ["pi-package", "pi", "extension", "model", "thinking", "project"],
|
|
8
8
|
"license": "EUPL-1.2",
|
|
9
|
-
"author":
|
|
9
|
+
"author": {
|
|
10
|
+
"name": "KAPPER NETWORK-COMMUNICATIONS GmbH",
|
|
11
|
+
"url": "https://kapper.net"
|
|
12
|
+
},
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
15
|
"url": "git+https://github.com/hknet/pi-extensions.git",
|
|
@@ -14,10 +17,25 @@
|
|
|
14
17
|
},
|
|
15
18
|
"bugs": { "url": "https://github.com/hknet/pi-extensions/issues" },
|
|
16
19
|
"homepage": "https://github.com/hknet/pi-extensions/tree/main/packages/pi-set-model#readme",
|
|
17
|
-
"files": ["set-model.ts", "README.md"],
|
|
20
|
+
"files": ["set-model.ts", "README.md", "CHANGELOG.md"],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=22.19.0"
|
|
23
|
+
},
|
|
18
24
|
"peerDependencies": {
|
|
19
|
-
"@earendil-works/pi-
|
|
20
|
-
"@earendil-works/pi-
|
|
25
|
+
"@earendil-works/pi-ai": "*",
|
|
26
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
27
|
+
"@earendil-works/pi-tui": "*"
|
|
28
|
+
},
|
|
29
|
+
"peerDependenciesMeta": {
|
|
30
|
+
"@earendil-works/pi-ai": {
|
|
31
|
+
"optional": true
|
|
32
|
+
},
|
|
33
|
+
"@earendil-works/pi-coding-agent": {
|
|
34
|
+
"optional": true
|
|
35
|
+
},
|
|
36
|
+
"@earendil-works/pi-tui": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
21
39
|
},
|
|
22
40
|
"pi": { "extensions": ["./set-model.ts"] }
|
|
23
41
|
}
|
package/set-model.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// Copyright © 2026 kapper.net - KAPPER NETWORK-COMMUNICATIONS GmbH
|
|
2
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
3
|
+
|
|
1
4
|
import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
2
5
|
import { dirname, join } from "node:path";
|
|
6
|
+
import { clampThinkingLevel } from "@earendil-works/pi-ai";
|
|
3
7
|
import { CONFIG_DIR_NAME, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
4
8
|
import type { AutocompleteItem } from "@earendil-works/pi-tui";
|
|
5
9
|
|
|
@@ -38,10 +42,13 @@ export async function loadPreference(path: string): Promise<ProjectPreference |
|
|
|
38
42
|
const preference = parsed as Partial<ProjectPreference>;
|
|
39
43
|
if (
|
|
40
44
|
typeof preference.provider !== "string" ||
|
|
45
|
+
preference.provider.trim() === "" ||
|
|
41
46
|
typeof preference.model !== "string" ||
|
|
42
|
-
|
|
47
|
+
preference.model.trim() === "" ||
|
|
48
|
+
typeof preference.thinkingLevel !== "string" ||
|
|
49
|
+
preference.thinkingLevel.trim() === ""
|
|
43
50
|
) {
|
|
44
|
-
throw new Error("expected provider, model, and thinkingLevel");
|
|
51
|
+
throw new Error("expected non-empty provider, model, and thinkingLevel strings");
|
|
45
52
|
}
|
|
46
53
|
return preference as ProjectPreference;
|
|
47
54
|
} catch (error: unknown) {
|
|
@@ -160,15 +167,19 @@ export default function setModelExtension(pi: ExtensionAPI) {
|
|
|
160
167
|
ctx.ui.notify(`No API key for project model: ${preference.provider}/${preference.model}`, "warning");
|
|
161
168
|
return;
|
|
162
169
|
}
|
|
163
|
-
|
|
170
|
+
const restoredThinkingLevel = clampThinkingLevel(model, preference.thinkingLevel);
|
|
171
|
+
pi.setThinkingLevel(restoredThinkingLevel);
|
|
164
172
|
modelBeforeProjectPreference = previousModel;
|
|
165
173
|
thinkingBeforeProjectPreference = previousThinkingLevel;
|
|
166
174
|
|
|
167
|
-
if (modelChanged) {
|
|
175
|
+
if (modelChanged || restoredThinkingLevel !== preference.thinkingLevel) {
|
|
168
176
|
ctx.ui.notify(
|
|
169
177
|
ctx.ui.theme.fg(
|
|
170
178
|
"accent",
|
|
171
|
-
`Project model restored: ${preference.provider}/${preference.model} · thinking: ${pi.getThinkingLevel()}
|
|
179
|
+
`Project model restored: ${preference.provider}/${preference.model} · thinking: ${pi.getThinkingLevel()}` +
|
|
180
|
+
(restoredThinkingLevel !== preference.thinkingLevel
|
|
181
|
+
? ` (saved level ${preference.thinkingLevel} is unsupported)`
|
|
182
|
+
: ""),
|
|
172
183
|
),
|
|
173
184
|
"info",
|
|
174
185
|
);
|