@oh-my-pi/pi-catalog 18.4.0 → 18.4.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.
- package/CHANGELOG.md +21 -0
- package/dist/types/compat/resolve.d.ts +6 -0
- package/dist/types/compat/types.d.ts +2 -0
- package/dist/types/wire/devin.d.ts +15 -4
- package/package.json +4 -4
- package/src/compat/behavior.ts +1 -1
- package/src/compat/catalog-policy.ts +2 -2
- package/src/compat/context-window.ts +3 -3
- package/src/compat/resolve.ts +9 -0
- package/src/compat/rules/providers/amazon-bedrock.kdl +16 -5
- package/src/compat/rules/providers/cursor.kdl +593 -2
- package/src/compat/rules/providers/github-copilot.kdl +14 -0
- package/src/compat/rules/runtime/behavior.kdl +8 -0
- package/src/compat/rules/taxonomy/xai.kdl +4 -2
- package/src/compat/rules.json +1 -1
- package/src/compat/types.ts +2 -0
- package/src/model-cache.ts +87 -48
- package/src/models.json +1 -1
- package/src/wire/devin.ts +13 -9
package/src/compat/types.ts
CHANGED
|
@@ -270,6 +270,8 @@ export interface CompiledCursorParameter {
|
|
|
270
270
|
/** One provider quota-scope table. */
|
|
271
271
|
export interface CompiledQuotaRule {
|
|
272
272
|
provider: string;
|
|
273
|
+
/** Tier used when no exact or fallback membership matches. */
|
|
274
|
+
defaultTier?: string;
|
|
273
275
|
tiers: { label: string; models: string[] }[];
|
|
274
276
|
fallbacks: { label: string; substring: string }[];
|
|
275
277
|
}
|
package/src/model-cache.ts
CHANGED
|
@@ -94,7 +94,15 @@ export interface CacheEntry<TApi extends Api = Api> {
|
|
|
94
94
|
let sharedDb: Database | null = null;
|
|
95
95
|
let sharedDbPath: string | null = null;
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
interface ReadRowCacheEntry {
|
|
98
|
+
/** `PRAGMA data_version` of the shared connection when validated; null for per-call connections. */
|
|
99
|
+
dataVersion: number | null;
|
|
100
|
+
/** Raw row the entry was parsed from; null when the row was absent or rejected. */
|
|
101
|
+
row: CacheRow | null;
|
|
102
|
+
entry: CacheEntry<Api> | null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const readRowCache = new Map<string, ReadRowCacheEntry>();
|
|
98
106
|
const READ_ROW_CACHE_MAX = 64;
|
|
99
107
|
|
|
100
108
|
function readCacheKey(resolvedPath: string, providerId: string): string {
|
|
@@ -329,67 +337,98 @@ export function readModelCache<TApi extends Api>(
|
|
|
329
337
|
// Monotonic change signal: same-shaped WAL overwrites after checkpoint
|
|
330
338
|
// can leave every size:mtime pair identical, so file metadata alone
|
|
331
339
|
// cannot invalidate. PRAGMA data_version increments on each committed
|
|
332
|
-
// write transaction visible to a new reader.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
// write transaction visible to a new reader. It is only comparable
|
|
341
|
+
// across calls on the same connection, so it gates the no-query fast
|
|
342
|
+
// path for the shared handle only.
|
|
343
|
+
const shared = dbPath === undefined;
|
|
344
|
+
return runModelCacheDb(resolvedPath, shared, db => {
|
|
345
|
+
const dataVersion = shared ? dbDataVersion(db) : null;
|
|
346
|
+
const cached = readRowCache.get(key);
|
|
347
|
+
if (dataVersion !== null && cached?.dataVersion === dataVersion) {
|
|
348
|
+
// Freshness is time-relative: recompute per call from the
|
|
349
|
+
// cached row's updatedAt so a long-lived process goes stale.
|
|
350
|
+
return withFreshness(cached.entry as CacheEntry<TApi> | null, ttlMs, now);
|
|
342
351
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
352
|
+
// Any commit (to any provider's row) bumps data_version. Re-read this
|
|
353
|
+
// row, but reuse the parsed entry when its bytes are unchanged.
|
|
354
|
+
const stmt = db.query<CacheRow, [string]>("SELECT * FROM model_cache WHERE provider_id = ?");
|
|
355
|
+
let row: CacheRow | null;
|
|
356
|
+
try {
|
|
357
|
+
row = stmt.get(providerId);
|
|
358
|
+
} finally {
|
|
359
|
+
stmt.finalize();
|
|
360
|
+
}
|
|
361
|
+
let entry: CacheEntry<TApi> | null;
|
|
362
|
+
if (
|
|
363
|
+
cached?.entry &&
|
|
364
|
+
cached.row &&
|
|
365
|
+
row &&
|
|
366
|
+
row.materialization_policy === materializationPolicy() &&
|
|
367
|
+
cacheRowsEqual(cached.row, row)
|
|
368
|
+
) {
|
|
369
|
+
entry = withFreshness(cached.entry as CacheEntry<TApi>, ttlMs, now);
|
|
370
|
+
} else {
|
|
371
|
+
entry = parseCacheRow<TApi>(db, providerId, row, ttlMs, now);
|
|
347
372
|
}
|
|
348
|
-
|
|
373
|
+
if (readRowCache.size >= READ_ROW_CACHE_MAX) readRowCache.clear();
|
|
374
|
+
readRowCache.set(key, {
|
|
375
|
+
dataVersion,
|
|
376
|
+
row: entry === null ? null : row,
|
|
377
|
+
entry: entry as CacheEntry<Api> | null,
|
|
378
|
+
});
|
|
379
|
+
return entry;
|
|
349
380
|
});
|
|
350
|
-
return entry.entry;
|
|
351
381
|
} catch {
|
|
352
382
|
return null;
|
|
353
383
|
}
|
|
354
384
|
}
|
|
355
385
|
|
|
356
|
-
function
|
|
386
|
+
function cacheRowsEqual(left: CacheRow, right: CacheRow): boolean {
|
|
387
|
+
return (
|
|
388
|
+
left.version === right.version &&
|
|
389
|
+
left.materialization_policy === right.materialization_policy &&
|
|
390
|
+
left.updated_at === right.updated_at &&
|
|
391
|
+
left.authoritative === right.authoritative &&
|
|
392
|
+
left.static_fingerprint === right.static_fingerprint &&
|
|
393
|
+
left.header_omitted_model_ids === right.header_omitted_model_ids &&
|
|
394
|
+
left.unrestorable_header_model_ids === right.unrestorable_header_model_ids &&
|
|
395
|
+
left.header_restore_version === right.header_restore_version &&
|
|
396
|
+
left.models === right.models
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function parseCacheRow<TApi extends Api>(
|
|
357
401
|
db: Database,
|
|
358
402
|
providerId: string,
|
|
403
|
+
row: CacheRow | null,
|
|
359
404
|
ttlMs: number,
|
|
360
405
|
now: () => number,
|
|
361
406
|
): CacheEntry<TApi> | null {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const row = stmt.get(providerId);
|
|
365
|
-
if (!row || row.version !== CACHE_SCHEMA_VERSION || row.materialization_policy !== materializationPolicy()) {
|
|
366
|
-
return null;
|
|
367
|
-
}
|
|
368
|
-
const models = parseMaterializedModels<TApi>(row.models);
|
|
369
|
-
const headerOmittedModelIds = parseModelIds(row.header_omitted_model_ids);
|
|
370
|
-
const unrestorableHeaderModelIds = parseModelIds(row.unrestorable_header_model_ids);
|
|
371
|
-
if (models === null || headerOmittedModelIds === null || unrestorableHeaderModelIds === null) {
|
|
372
|
-
// Fail closed on corrupt header provenance: treating malformed
|
|
373
|
-
// markers as empty could return a model with required credentials
|
|
374
|
-
// silently absent. secure_delete scrubs the rejected payload.
|
|
375
|
-
db.run("DELETE FROM model_cache WHERE provider_id = ?", [providerId]);
|
|
376
|
-
return null;
|
|
377
|
-
}
|
|
378
|
-
const ageMs = now() - row.updated_at;
|
|
379
|
-
const fresh = Number.isFinite(ageMs) && ageMs >= 0 && ageMs <= ttlMs;
|
|
380
|
-
return {
|
|
381
|
-
models,
|
|
382
|
-
fresh,
|
|
383
|
-
authoritative: row.authoritative === 1,
|
|
384
|
-
updatedAt: row.updated_at,
|
|
385
|
-
headerOmittedModelIds,
|
|
386
|
-
unrestorableHeaderModelIds,
|
|
387
|
-
legacyHeaderRestoreMarkers: row.header_restore_version < HEADER_RESTORE_VERSION,
|
|
388
|
-
staticFingerprint: row.static_fingerprint ?? "",
|
|
389
|
-
};
|
|
390
|
-
} finally {
|
|
391
|
-
stmt.finalize();
|
|
407
|
+
if (!row || row.version !== CACHE_SCHEMA_VERSION || row.materialization_policy !== materializationPolicy()) {
|
|
408
|
+
return null;
|
|
392
409
|
}
|
|
410
|
+
const models = parseMaterializedModels<TApi>(row.models);
|
|
411
|
+
const headerOmittedModelIds = parseModelIds(row.header_omitted_model_ids);
|
|
412
|
+
const unrestorableHeaderModelIds = parseModelIds(row.unrestorable_header_model_ids);
|
|
413
|
+
if (models === null || headerOmittedModelIds === null || unrestorableHeaderModelIds === null) {
|
|
414
|
+
// Fail closed on corrupt header provenance: treating malformed
|
|
415
|
+
// markers as empty could return a model with required credentials
|
|
416
|
+
// silently absent. secure_delete scrubs the rejected payload.
|
|
417
|
+
db.run("DELETE FROM model_cache WHERE provider_id = ?", [providerId]);
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
const ageMs = now() - row.updated_at;
|
|
421
|
+
const fresh = Number.isFinite(ageMs) && ageMs >= 0 && ageMs <= ttlMs;
|
|
422
|
+
return {
|
|
423
|
+
models,
|
|
424
|
+
fresh,
|
|
425
|
+
authoritative: row.authoritative === 1,
|
|
426
|
+
updatedAt: row.updated_at,
|
|
427
|
+
headerOmittedModelIds,
|
|
428
|
+
unrestorableHeaderModelIds,
|
|
429
|
+
legacyHeaderRestoreMarkers: row.header_restore_version < HEADER_RESTORE_VERSION,
|
|
430
|
+
staticFingerprint: row.static_fingerprint ?? "",
|
|
431
|
+
};
|
|
393
432
|
}
|
|
394
433
|
|
|
395
434
|
/** Whether a live model carries at least one request header. */
|