@oh-my-pi/pi-coding-agent 13.12.5 → 13.12.6
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 +11 -0
- package/package.json +7 -7
- package/src/config/model-registry.ts +72 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [13.12.6] - 2026-03-15
|
|
6
|
+
### Changed
|
|
7
|
+
|
|
8
|
+
- Updated llama.cpp model discovery to read context window from the `/props` endpoint's `default_generation_settings.n_ctx` field instead of using hardcoded 128000 default
|
|
9
|
+
- Updated llama.cpp model discovery to detect vision capabilities from the `/props` endpoint's `modalities.vision` field instead of defaulting to text-only input
|
|
10
|
+
- Changed llama.cpp `maxTokens` calculation to respect discovered context window limits, capping at 8192 or the server's context window, whichever is smaller
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fixed llama.cpp auto-discovery to read context window and vision support from the native `/props` endpoint instead of relying on hardcoded defaults
|
|
15
|
+
|
|
5
16
|
## [13.12.5] - 2026-03-15
|
|
6
17
|
|
|
7
18
|
### Added
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
4
|
-
"version": "13.12.
|
|
4
|
+
"version": "13.12.6",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/can1357/oh-my-pi",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@mozilla/readability": "^0.6",
|
|
44
|
-
"@oh-my-pi/omp-stats": "13.12.
|
|
45
|
-
"@oh-my-pi/pi-agent-core": "13.12.
|
|
46
|
-
"@oh-my-pi/pi-ai": "13.12.
|
|
47
|
-
"@oh-my-pi/pi-natives": "13.12.
|
|
48
|
-
"@oh-my-pi/pi-tui": "13.12.
|
|
49
|
-
"@oh-my-pi/pi-utils": "13.12.
|
|
44
|
+
"@oh-my-pi/omp-stats": "13.12.6",
|
|
45
|
+
"@oh-my-pi/pi-agent-core": "13.12.6",
|
|
46
|
+
"@oh-my-pi/pi-ai": "13.12.6",
|
|
47
|
+
"@oh-my-pi/pi-natives": "13.12.6",
|
|
48
|
+
"@oh-my-pi/pi-tui": "13.12.6",
|
|
49
|
+
"@oh-my-pi/pi-utils": "13.12.6",
|
|
50
50
|
"@sinclair/typebox": "^0.34",
|
|
51
51
|
"@xterm/headless": "^6.0",
|
|
52
52
|
"ajv": "^8.18",
|
|
@@ -372,6 +372,11 @@ type OllamaDiscoveredModelMetadata = {
|
|
|
372
372
|
contextWindow?: number;
|
|
373
373
|
};
|
|
374
374
|
|
|
375
|
+
type LlamaCppDiscoveredServerMetadata = {
|
|
376
|
+
contextWindow?: number;
|
|
377
|
+
input?: ("text" | "image")[];
|
|
378
|
+
};
|
|
379
|
+
|
|
375
380
|
/**
|
|
376
381
|
* Resolve an API key config value to an actual key.
|
|
377
382
|
* Checks environment variable first, then treats as literal.
|
|
@@ -416,6 +421,25 @@ function extractOllamaContextWindow(payload: Record<string, unknown>): number |
|
|
|
416
421
|
return match ? toPositiveNumberOrUndefined(match[1]) : undefined;
|
|
417
422
|
}
|
|
418
423
|
|
|
424
|
+
function extractLlamaCppContextWindow(payload: Record<string, unknown>): number | undefined {
|
|
425
|
+
const generationSettings = payload.default_generation_settings;
|
|
426
|
+
if (isRecord(generationSettings)) {
|
|
427
|
+
const contextWindow = toPositiveNumberOrUndefined(generationSettings.n_ctx);
|
|
428
|
+
if (contextWindow !== undefined) {
|
|
429
|
+
return contextWindow;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return toPositiveNumberOrUndefined(payload.n_ctx);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function extractLlamaCppInputCapabilities(payload: Record<string, unknown>): ("text" | "image")[] | undefined {
|
|
436
|
+
const modalities = payload.modalities;
|
|
437
|
+
if (!isRecord(modalities)) {
|
|
438
|
+
return undefined;
|
|
439
|
+
}
|
|
440
|
+
return modalities.vision === true ? ["text", "image"] : ["text"];
|
|
441
|
+
}
|
|
442
|
+
|
|
419
443
|
function extractGoogleOAuthToken(value: string | undefined): string | undefined {
|
|
420
444
|
if (!isAuthenticated(value)) return undefined;
|
|
421
445
|
try {
|
|
@@ -1225,6 +1249,32 @@ export class ModelRegistry {
|
|
|
1225
1249
|
return this.#applyProviderModelOverrides(providerConfig.provider, discovered);
|
|
1226
1250
|
}
|
|
1227
1251
|
|
|
1252
|
+
async #discoverLlamaCppServerMetadata(
|
|
1253
|
+
baseUrl: string,
|
|
1254
|
+
headers: Record<string, string> | undefined,
|
|
1255
|
+
): Promise<LlamaCppDiscoveredServerMetadata | null> {
|
|
1256
|
+
const propsUrl = `${this.#toLlamaCppNativeBaseUrl(baseUrl)}/props`;
|
|
1257
|
+
try {
|
|
1258
|
+
const response = await fetch(propsUrl, {
|
|
1259
|
+
headers,
|
|
1260
|
+
signal: AbortSignal.timeout(150),
|
|
1261
|
+
});
|
|
1262
|
+
if (!response.ok) {
|
|
1263
|
+
return null;
|
|
1264
|
+
}
|
|
1265
|
+
const payload = (await response.json()) as unknown;
|
|
1266
|
+
if (!isRecord(payload)) {
|
|
1267
|
+
return null;
|
|
1268
|
+
}
|
|
1269
|
+
return {
|
|
1270
|
+
contextWindow: extractLlamaCppContextWindow(payload),
|
|
1271
|
+
input: extractLlamaCppInputCapabilities(payload),
|
|
1272
|
+
};
|
|
1273
|
+
} catch {
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1228
1278
|
async #discoverLlamaCppModels(providerConfig: DiscoveryProviderConfig): Promise<Model<Api>[]> {
|
|
1229
1279
|
const baseUrl = this.#normalizeLlamaCppBaseUrl(providerConfig.baseUrl);
|
|
1230
1280
|
const modelsUrl = `${baseUrl}/models`;
|
|
@@ -1235,10 +1285,13 @@ export class ModelRegistry {
|
|
|
1235
1285
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
1236
1286
|
}
|
|
1237
1287
|
|
|
1238
|
-
const response = await
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1288
|
+
const [response, serverMetadata] = await Promise.all([
|
|
1289
|
+
fetch(modelsUrl, {
|
|
1290
|
+
headers,
|
|
1291
|
+
signal: AbortSignal.timeout(250),
|
|
1292
|
+
}),
|
|
1293
|
+
this.#discoverLlamaCppServerMetadata(baseUrl, headers),
|
|
1294
|
+
]);
|
|
1242
1295
|
if (!response.ok) {
|
|
1243
1296
|
throw new Error(`HTTP ${response.status} from ${modelsUrl}`);
|
|
1244
1297
|
}
|
|
@@ -1256,10 +1309,10 @@ export class ModelRegistry {
|
|
|
1256
1309
|
provider: providerConfig.provider,
|
|
1257
1310
|
baseUrl,
|
|
1258
1311
|
reasoning: false,
|
|
1259
|
-
input: ["text"],
|
|
1312
|
+
input: serverMetadata?.input ?? ["text"],
|
|
1260
1313
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1261
|
-
contextWindow: 128000,
|
|
1262
|
-
maxTokens: 8192,
|
|
1314
|
+
contextWindow: serverMetadata?.contextWindow ?? 128000,
|
|
1315
|
+
maxTokens: Math.min(serverMetadata?.contextWindow ?? Number.POSITIVE_INFINITY, 8192),
|
|
1263
1316
|
headers,
|
|
1264
1317
|
compat: {
|
|
1265
1318
|
supportsStore: false,
|
|
@@ -1331,6 +1384,18 @@ export class ModelRegistry {
|
|
|
1331
1384
|
}
|
|
1332
1385
|
}
|
|
1333
1386
|
|
|
1387
|
+
#toLlamaCppNativeBaseUrl(baseUrl: string): string {
|
|
1388
|
+
try {
|
|
1389
|
+
const parsed = new URL(baseUrl);
|
|
1390
|
+
const trimmedPath = parsed.pathname.replace(/\/+$/g, "");
|
|
1391
|
+
parsed.pathname = trimmedPath.endsWith("/v1") ? trimmedPath.slice(0, -3) || "/" : trimmedPath || "/";
|
|
1392
|
+
const normalized = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
|
|
1393
|
+
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
1394
|
+
} catch {
|
|
1395
|
+
return baseUrl.endsWith("/v1") ? baseUrl.slice(0, -3) : baseUrl;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1334
1399
|
#normalizeLmStudioBaseUrl(baseUrl?: string): string {
|
|
1335
1400
|
const defaultBaseUrl = "http://127.0.0.1:1234/v1";
|
|
1336
1401
|
const raw = baseUrl || defaultBaseUrl;
|