pi-ollama-cloud 0.2.1 → 0.3.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/CHANGELOG.md +5 -0
- package/models.ts +57 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.3.0] - 2026-05-04
|
|
6
|
+
|
|
7
|
+
- Derive `thinkingLevelMap` from pi's built-in model definitions instead of hardcoding model-family mappings. The extension now picks up thinking level metadata automatically when pi-mono adds or updates it for any model.
|
|
8
|
+
- Add family-based fallback matching: when an Ollama Cloud model ID doesn't match a pi model ID exactly, the extension now tries matching by model family (via Ollama's `details.family` field). For example, `gemma4:31b` correctly picks up Gemma 4's thinking level map from pi.
|
|
9
|
+
|
|
5
10
|
## [0.2.1] - 2026-04-29
|
|
6
11
|
|
|
7
12
|
- Fix API key retrieval by using `AuthStorage` instead of `ctx.modelRegistry.getApiKeyForProvider`. The provider-level API key lookup was failing, causing auth to only work when an environment variable was set. Now reads from `auth.json` directly via the pi `AuthStorage` class.
|
package/models.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { type ExtensionCommandContext, getAgentDir, type ProviderModelConfig } from "@mariozechner/pi-coding-agent";
|
|
4
4
|
import { AuthStorage } from "@mariozechner/pi-coding-agent";
|
|
5
|
+
import { getModels, getProviders } from "@mariozechner/pi-ai";
|
|
5
6
|
|
|
6
7
|
// --- Constants ---
|
|
7
8
|
const CACHE_DIR = join(getAgentDir(), "cache");
|
|
@@ -46,6 +47,52 @@ function getContextLength(modelInfo: Record<string, unknown>): number {
|
|
|
46
47
|
return 128000;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
// --- Built-in model knowledge index ---
|
|
51
|
+
// Build a lookup of model ID -> thinkingLevelMap from pi's built-in models.
|
|
52
|
+
// This avoids hardcoding model-family mappings: when pi-mono updates its
|
|
53
|
+
// model definitions (e.g. DeepSeek V4's thinking levels), the extension
|
|
54
|
+
// picks up the changes automatically.
|
|
55
|
+
const BUILTIN_THINKING_MAP: Record<string, ProviderModelConfig["thinkingLevelMap"]> = {};
|
|
56
|
+
// Fallback: family stem -> [stem, thinkingLevelMap] pairs for models whose Ollama Cloud
|
|
57
|
+
// ID doesn't match exactly. The stem is derived by stripping provider prefixes and
|
|
58
|
+
// non-alphanumeric characters (e.g. "gemma-4-31b-it" -> "gemma431bit").
|
|
59
|
+
// When looking up an Ollama model by its details.family field, we search for a pi stem
|
|
60
|
+
// that starts with the family stem (e.g. family "gemma4" -> pi "gemma431bit").
|
|
61
|
+
// Entries are sorted longest-first so the most specific match wins.
|
|
62
|
+
const BUILTIN_FAMILY_ENTRIES: [string, NonNullable<ProviderModelConfig["thinkingLevelMap"]>][] = [];
|
|
63
|
+
for (const provider of getProviders()) {
|
|
64
|
+
for (const model of getModels(provider as any)) {
|
|
65
|
+
if (model.thinkingLevelMap) {
|
|
66
|
+
BUILTIN_THINKING_MAP[model.id] = model.thinkingLevelMap;
|
|
67
|
+
const stem = model.id
|
|
68
|
+
.replace(/^[a-z0-9-]+\//, "") // strip provider prefix (e.g. "zai/", "deepseek/")
|
|
69
|
+
.replace(/[^a-zA-Z0-9]/g, "") // strip non-alphanumeric
|
|
70
|
+
.toLowerCase();
|
|
71
|
+
BUILTIN_FAMILY_ENTRIES.push([stem, model.thinkingLevelMap]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Longest stems first so a more specific match (e.g. "gemma431bit") wins over a generic one (e.g. "gemma4").
|
|
76
|
+
BUILTIN_FAMILY_ENTRIES.sort((a, b) => b[0].length - a[0].length);
|
|
77
|
+
|
|
78
|
+
function resolveThinkingLevelMap(modelId: string, data: OllamaShowResponse): ProviderModelConfig["thinkingLevelMap"] {
|
|
79
|
+
// 1. Exact ID match (e.g. "deepseek-v4-pro")
|
|
80
|
+
const exact = BUILTIN_THINKING_MAP[modelId];
|
|
81
|
+
if (exact) return exact;
|
|
82
|
+
|
|
83
|
+
// 2. Family-based fallback: match Ollama's details.family against pi model stems
|
|
84
|
+
if (data.capabilities?.includes("thinking")) {
|
|
85
|
+
const familyStem = data.details.family.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
|
86
|
+
for (const [stem, tlm] of BUILTIN_FAMILY_ENTRIES) {
|
|
87
|
+
if (stem.startsWith(familyStem)) {
|
|
88
|
+
return tlm;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
|
|
49
96
|
export function assembleModels(raw: Record<string, OllamaShowResponse>): ProviderModelConfig[] {
|
|
50
97
|
return Object.entries(raw)
|
|
51
98
|
.filter(([, data]) => data.capabilities?.includes("tools"))
|
|
@@ -53,6 +100,7 @@ export function assembleModels(raw: Record<string, OllamaShowResponse>): Provide
|
|
|
53
100
|
id,
|
|
54
101
|
name: id,
|
|
55
102
|
reasoning: data.capabilities?.includes("thinking") ?? false,
|
|
103
|
+
thinkingLevelMap: resolveThinkingLevelMap(id, data),
|
|
56
104
|
input: (data.capabilities?.includes("vision") ? ["text", "image"] : ["text"]) as ("text" | "image")[],
|
|
57
105
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
58
106
|
contextWindow: getContextLength(data.model_info ?? {}),
|
|
@@ -106,16 +154,17 @@ export function writeCache(models: Record<string, OllamaShowResponse>): void {
|
|
|
106
154
|
// --- Fetch Models ---
|
|
107
155
|
export async function fetchModels(ctx: ExtensionCommandContext): Promise<Record<string, OllamaShowResponse> | null> {
|
|
108
156
|
const apiKey = await authStorage.getApiKey("ollama-cloud");
|
|
109
|
-
|
|
157
|
+
|
|
110
158
|
if (!apiKey) {
|
|
111
159
|
ctx.ui.notify(
|
|
112
160
|
"No Ollama Cloud API key found. \n" +
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
161
|
+
"Please ensure your API key is set in: \n" +
|
|
162
|
+
"- auth.json file (at ~/.pi/agent/auth.json) under 'ollama-cloud' key,\n" +
|
|
163
|
+
"- or via the CLI --api-key flag.\n" +
|
|
164
|
+
"Example auth.json entry: \n" +
|
|
165
|
+
'{ \"ollama-cloud\": { \"type\": \"api_key\", \"key\": \"YOUR_API_KEY\" } }',
|
|
166
|
+
"error",
|
|
167
|
+
);
|
|
119
168
|
return null;
|
|
120
169
|
}
|
|
121
170
|
|
|
@@ -176,4 +225,4 @@ export async function fetchModels(ctx: ExtensionCommandContext): Promise<Record<
|
|
|
176
225
|
ctx.ui.notify(`Fetched ${succeeded} model details${failed ? ` (${failed} failed)` : ""}`, "info");
|
|
177
226
|
|
|
178
227
|
return results;
|
|
179
|
-
}
|
|
228
|
+
}
|