pi-set-model 0.1.3 → 0.1.4

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 ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 0.1.4 - 2026-08-23
4
+
5
+ ### Changed
6
+
7
+ - Mark Pi's host-provided SDK packages as optional wildcard peers so npm does not install a redundant Pi SDK dependency tree.
8
+ - Verify development and tests against Pi SDK 0.84.2 while retaining runtime compatibility with Pi 0.84.1 and newer.
9
+ - Reject empty saved preference fields and explicitly clamp restored thinking levels with Pi's model-capability helper.
10
+ - Document that the individual package and GitHub bundle must not be installed together.
package/LICENSE CHANGED
File without changes
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 pi `>=0.84.1`.
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 are clamped to that model's supported levels by Pi. When the session ends, the model and thinking level that were active before the project preference was applied are restored.
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,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-set-model",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Pi extension that remembers model and thinking level per project folder",
5
5
  "type": "module",
6
6
  "private": false,
@@ -14,10 +14,25 @@
14
14
  },
15
15
  "bugs": { "url": "https://github.com/hknet/pi-extensions/issues" },
16
16
  "homepage": "https://github.com/hknet/pi-extensions/tree/main/packages/pi-set-model#readme",
17
- "files": ["set-model.ts", "README.md"],
17
+ "files": ["set-model.ts", "README.md", "CHANGELOG.md"],
18
+ "engines": {
19
+ "node": ">=22.19.0"
20
+ },
18
21
  "peerDependencies": {
19
- "@earendil-works/pi-coding-agent": ">=0.84.1",
20
- "@earendil-works/pi-tui": ">=0.84.1"
22
+ "@earendil-works/pi-ai": "*",
23
+ "@earendil-works/pi-coding-agent": "*",
24
+ "@earendil-works/pi-tui": "*"
25
+ },
26
+ "peerDependenciesMeta": {
27
+ "@earendil-works/pi-ai": {
28
+ "optional": true
29
+ },
30
+ "@earendil-works/pi-coding-agent": {
31
+ "optional": true
32
+ },
33
+ "@earendil-works/pi-tui": {
34
+ "optional": true
35
+ }
21
36
  },
22
37
  "pi": { "extensions": ["./set-model.ts"] }
23
38
  }
package/set-model.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
2
2
  import { dirname, join } from "node:path";
3
+ import { clampThinkingLevel } from "@earendil-works/pi-ai";
3
4
  import { CONFIG_DIR_NAME, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
4
5
  import type { AutocompleteItem } from "@earendil-works/pi-tui";
5
6
 
@@ -38,10 +39,13 @@ export async function loadPreference(path: string): Promise<ProjectPreference |
38
39
  const preference = parsed as Partial<ProjectPreference>;
39
40
  if (
40
41
  typeof preference.provider !== "string" ||
42
+ preference.provider.trim() === "" ||
41
43
  typeof preference.model !== "string" ||
42
- typeof preference.thinkingLevel !== "string"
44
+ preference.model.trim() === "" ||
45
+ typeof preference.thinkingLevel !== "string" ||
46
+ preference.thinkingLevel.trim() === ""
43
47
  ) {
44
- throw new Error("expected provider, model, and thinkingLevel");
48
+ throw new Error("expected non-empty provider, model, and thinkingLevel strings");
45
49
  }
46
50
  return preference as ProjectPreference;
47
51
  } catch (error: unknown) {
@@ -160,15 +164,19 @@ export default function setModelExtension(pi: ExtensionAPI) {
160
164
  ctx.ui.notify(`No API key for project model: ${preference.provider}/${preference.model}`, "warning");
161
165
  return;
162
166
  }
163
- pi.setThinkingLevel(preference.thinkingLevel);
167
+ const restoredThinkingLevel = clampThinkingLevel(model, preference.thinkingLevel);
168
+ pi.setThinkingLevel(restoredThinkingLevel);
164
169
  modelBeforeProjectPreference = previousModel;
165
170
  thinkingBeforeProjectPreference = previousThinkingLevel;
166
171
 
167
- if (modelChanged) {
172
+ if (modelChanged || restoredThinkingLevel !== preference.thinkingLevel) {
168
173
  ctx.ui.notify(
169
174
  ctx.ui.theme.fg(
170
175
  "accent",
171
- `Project model restored: ${preference.provider}/${preference.model} · thinking: ${pi.getThinkingLevel()}`,
176
+ `Project model restored: ${preference.provider}/${preference.model} · thinking: ${pi.getThinkingLevel()}` +
177
+ (restoredThinkingLevel !== preference.thinkingLevel
178
+ ? ` (saved level ${preference.thinkingLevel} is unsupported)`
179
+ : ""),
172
180
  ),
173
181
  "info",
174
182
  );