@oh-my-pi/pi-catalog 18.3.0 → 18.3.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 +12 -0
- package/THIRD-PARTY-NOTICES.txt +2 -2
- package/dist/types/compat/fallback-credit.d.ts +7 -0
- package/dist/types/compat/output-limits.d.ts +5 -0
- package/dist/types/compat/server-side-fallback.d.ts +7 -0
- package/dist/types/types.d.ts +13 -1
- package/package.json +4 -4
- package/src/compat/axes.ts +25 -0
- package/src/compat/fallback-credit.ts +13 -0
- package/src/compat/output-limits.ts +8 -0
- package/src/compat/resolve.ts +2 -0
- package/src/compat/rules/classes/anthropic.kdl +25 -0
- package/src/compat/rules/classes/openai.kdl +3 -0
- package/src/compat/rules/providers/anthropic.kdl +15 -0
- package/src/compat/rules/providers/yolo-auto.kdl +8 -2
- package/src/compat/rules.json +1 -1
- package/src/compat/server-side-fallback.ts +13 -0
- package/src/discovery/devin.ts +60 -1
- package/src/models.json +1 -1
- package/src/provider-models/cache-provider-id.ts +5 -0
- package/src/provider-models/openai-compat.ts +30 -7
- package/src/provider-models/special.ts +1 -0
- package/src/types.ts +13 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Model } from "../types";
|
|
2
|
+
import { resolveCatalogPolicy } from "./catalog-policy";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Ordered model ids for Anthropic's server-side refusal `fallbacks` chain,
|
|
6
|
+
* authored on the `server-side-fallback-models` catalog axis. Empty when no
|
|
7
|
+
* rule assigns a chain (the model or host does not support the feature).
|
|
8
|
+
*/
|
|
9
|
+
export function serverSideFallbackModels(model: Model): readonly string[] {
|
|
10
|
+
const value = resolveCatalogPolicy(model).serverSideFallbackModels;
|
|
11
|
+
if (!Array.isArray(value)) return [];
|
|
12
|
+
return value.filter((entry): entry is string => typeof entry === "string");
|
|
13
|
+
}
|
package/src/discovery/devin.ts
CHANGED
|
@@ -453,6 +453,51 @@ function devinModelSpec(
|
|
|
453
453
|
return spec;
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
+
/**
|
|
457
|
+
* Lead chat uid of a Fusion pairing `fusion-<lead>[-fast]-sidekick-<sidekick>`.
|
|
458
|
+
* An exact live lead uid wins, so leads whose own uid ends in `-fast`
|
|
459
|
+
* (`swe-1-6-fast`) route as written. Otherwise `-fast` selects the lead's
|
|
460
|
+
* priority lane when the server lists one, then the standard lane.
|
|
461
|
+
*
|
|
462
|
+
* Returns `undefined` for uids that are not pairings and `null` for pairings
|
|
463
|
+
* whose lead is not live: the composite uid itself is never servable.
|
|
464
|
+
*/
|
|
465
|
+
function devinFusionLeadUid(uid: string, liveUids: ReadonlyMap<string, unknown>): string | null | undefined {
|
|
466
|
+
if (!uid.startsWith("fusion-")) return undefined;
|
|
467
|
+
const cut = uid.indexOf("-sidekick-");
|
|
468
|
+
if (cut <= "fusion-".length) return undefined;
|
|
469
|
+
const lead = uid.slice("fusion-".length, cut);
|
|
470
|
+
if (liveUids.has(lead)) return lead;
|
|
471
|
+
if (lead.endsWith("-fast")) {
|
|
472
|
+
const base = lead.slice(0, -"-fast".length);
|
|
473
|
+
if (liveUids.has(`${base}-priority`)) return `${base}-priority`;
|
|
474
|
+
if (liveUids.has(base)) return base;
|
|
475
|
+
}
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Point a Fusion pairing at its lead. omp runs only the lead (the sidekick is
|
|
481
|
+
* paired by the native client), so the limits and pricing a caller budgets
|
|
482
|
+
* against are the lead's, not the composite card's.
|
|
483
|
+
*/
|
|
484
|
+
function routeDevinFusionLead(spec: ModelSpec<"devin-agent">, lead: ModelSpec<"devin-agent">): void {
|
|
485
|
+
spec.requestModelId = lead.id;
|
|
486
|
+
spec.reasoning = lead.reasoning;
|
|
487
|
+
spec.input = lead.input;
|
|
488
|
+
spec.supportsTools = lead.supportsTools;
|
|
489
|
+
spec.cost = lead.cost;
|
|
490
|
+
spec.contextWindow = lead.contextWindow;
|
|
491
|
+
spec.maxTokens = lead.maxTokens;
|
|
492
|
+
if (lead.compat?.supportsParallelToolCalls) {
|
|
493
|
+
spec.compat = { ...spec.compat, supportsParallelToolCalls: true };
|
|
494
|
+
} else if (spec.compat?.supportsParallelToolCalls) {
|
|
495
|
+
const { supportsParallelToolCalls: _, ...rest } = spec.compat;
|
|
496
|
+
if (Object.keys(rest).length > 0) spec.compat = rest;
|
|
497
|
+
else delete spec.compat;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
456
501
|
function normalizeDevinModels(
|
|
457
502
|
configs: readonly ClientModelConfig[],
|
|
458
503
|
baseUrlOverride: string | undefined,
|
|
@@ -461,6 +506,11 @@ function normalizeDevinModels(
|
|
|
461
506
|
const specs: ModelSpec<"devin-agent">[] = [];
|
|
462
507
|
const seen = new Set<string>();
|
|
463
508
|
const lanes = new Map<string, DevinFamilyLane>();
|
|
509
|
+
const liveConfigs = new Map<string, ClientModelConfig>();
|
|
510
|
+
for (const config of configs) {
|
|
511
|
+
const uid = config.modelUid.trim();
|
|
512
|
+
if (!config.disabled && uid && !liveConfigs.has(uid)) liveConfigs.set(uid, config);
|
|
513
|
+
}
|
|
464
514
|
|
|
465
515
|
for (const config of configs) {
|
|
466
516
|
if (config.disabled) {
|
|
@@ -482,7 +532,16 @@ function normalizeDevinModels(
|
|
|
482
532
|
// `fusion-sidekick-*`) that are themselves valid chat uids. Only the
|
|
483
533
|
// former take the `AssignModel` path — sending a composite uid there 404s.
|
|
484
534
|
const isAssignModelRouter = isRouter && (config.modelInfo?.harnessUids.length ?? 0) === 0;
|
|
485
|
-
|
|
535
|
+
// Fusion pairings are orchestrated by the native client: it runs the lead
|
|
536
|
+
// model as an ordinary chat uid and pairs a sidekick locally. The server
|
|
537
|
+
// has no provider for the composite uid itself (`permission_denied: no API
|
|
538
|
+
// providers are available`), so the chat request carries the lead uid and
|
|
539
|
+
// a pairing without a live lead is not listed.
|
|
540
|
+
const lead = devinFusionLeadUid(uid, liveConfigs);
|
|
541
|
+
if (lead === null) continue;
|
|
542
|
+
const spec = devinModelSpec(config, uid, baseUrl, isAssignModelRouter);
|
|
543
|
+
if (lead !== undefined) routeDevinFusionLead(spec, devinModelSpec(liveConfigs.get(lead)!, lead, baseUrl, false));
|
|
544
|
+
specs.push(spec);
|
|
486
545
|
// A router is a server-side dispatcher, not an effort tier: it stays a
|
|
487
546
|
// standalone model even when upstream files it under a family.
|
|
488
547
|
if (!isRouter) {
|