@xiaoso/dsh-tool-plus 0.1.16 → 0.1.17-beta.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/lib/{abort-DZ54CaKU.mjs → abort-BTblp0Rt.mjs} +2 -2
- package/lib/{alibaba-coding-plan-DODpkcqi.mjs → alibaba-coding-plan-t3R4YKCB.mjs} +3 -3
- package/lib/{alibaba-token-plan-C6lpKCda.mjs → alibaba-token-plan-CO4djG1y.mjs} +4 -4
- package/lib/{alibaba-token-plan-CHGyWOfX.mjs → alibaba-token-plan-CUjYJX0-.mjs} +1 -1
- package/lib/{anthropic-Dv_GGX6g.mjs → anthropic-nf7w6so1.mjs} +48 -21
- package/lib/{api-key-validation-MnMf_ihX.mjs → api-key-validation-C_tZ7Y9a.mjs} +2 -2
- package/lib/behavior-BwvTUtag.mjs +111 -0
- package/lib/{browser-render-BZXt548F.mjs → browser-render-BQaEVK_n.mjs} +4 -4
- package/lib/{reference-CtvM4zLU.mjs → bundled-references-CrQ4dQcT.mjs} +57 -4
- package/lib/cascade-BWjRTD1q.mjs +30265 -0
- package/lib/{cline-pass-BT9CBEOj.mjs → cline-pass-Bjm-O8GG.mjs} +2 -2
- package/lib/cloudflare-CKXRJ0l9.mjs +37 -0
- package/lib/{cloudflare-ai-gateway-DReN6ohJ.mjs → cloudflare-ai-gateway-BpnBSjwV.mjs} +8 -4
- package/lib/cloudflare-workers-ai-odj9XswL.mjs +32 -0
- package/lib/collapse-_nkb2dn7.mjs +1945 -0
- package/lib/{coreweave-C82HrLpb.mjs → coreweave-CGDZOD8-.mjs} +1 -1
- package/lib/{coreweave-C68UgRQO.mjs → coreweave-DwffcgW5.mjs} +4 -4
- package/lib/cursor-BgOuV7Qf.mjs +794 -0
- package/lib/{cursor-_gHHq-Dq.mjs → cursor-CF1iHHbv.mjs} +68 -19
- package/lib/{cursor-proto-Cr_WEMuv.mjs → cursor-proto-BuNTjX3L.mjs} +823 -23
- package/lib/{devin-QpfTSl9H.mjs → devin-7OEeEb80.mjs} +112 -31
- package/lib/{devin-proto-DYhp4Ty6.mjs → devin-proto-C-QreeAv.mjs} +71 -5
- package/lib/{dom-DG3sPESc.mjs → dom-BmbZv4v9.mjs} +598 -182
- package/lib/{error-O63pC8zg.mjs → error-8LVo7tug.mjs} +725 -104
- package/lib/factory-droid-ChhmsGWb.mjs +71 -0
- package/lib/{fs-promises-shim-B2YFWkcd.mjs → fs-promises-shim-CANAxFWh.mjs} +10 -1
- package/lib/{github-copilot-BMEcw8N1.mjs → github-copilot-QwevdT30.mjs} +4 -4
- package/lib/{github-copilot-headers-DnjGEbko.mjs → github-copilot-headers-CAUZ0rUD.mjs} +138 -26
- package/lib/{gitlab-duo-DnHqJjFY.mjs → gitlab-duo-DigV7k_o.mjs} +2 -2
- package/lib/{google-antigravity-B1mSckrK.mjs → google-antigravity-D-oe0r8A.mjs} +6 -7
- package/lib/{google-gemini-cli-DJwThCCn.mjs → google-gemini-cli-CQBHgGJT.mjs} +5 -6
- package/lib/{google-oauth-shared-BctLpVUN.mjs → google-oauth-shared-CvgVIUwJ.mjs} +2 -2
- package/lib/google-validation-CdvRj4ec.mjs +126 -0
- package/lib/id-EJwVLDHE.mjs +2548 -0
- package/lib/index.mjs +248 -258
- package/lib/{kilo-BEgEwMJQ.mjs → kilo-5r6OffCa.mjs} +2 -2
- package/lib/{kimi-T9NldEIJ.mjs → kimi-DOOtbXmm.mjs} +9 -10
- package/lib/{launch-BIWNyrBB.mjs → launch-DkAjib7h.mjs} +1 -1
- package/lib/{markit-Dvp2JPdT.mjs → markit-CCcyeAds.mjs} +359 -140
- package/lib/{models-DnXMYGcJ.mjs → models-DCpDT_im.mjs} +199203 -112275
- package/lib/{muse-code-CNvqqAp6.mjs → muse-code-CYf8zj_B.mjs} +5 -5
- package/lib/{openai-codex-D5-CyTxa.mjs → openai-codex-Cj-TvSFh.mjs} +13 -10
- package/lib/{perplexity-A2PEoGaC.mjs → perplexity-Dh_Qgsmx.mjs} +68 -25
- package/lib/{pkce-BYjmugmw.mjs → pkce-DO-jBJLV.mjs} +1 -1
- package/lib/pricing-DusBEhwm.mjs +593 -0
- package/lib/{readability-uGhqb4GC.mjs → readability-XHK0o3bv.mjs} +287 -27
- package/lib/{scrapers-C1ujjV8k.mjs → scrapers-B6PADOVm.mjs} +13 -13
- package/lib/slugify-ynYWBIA5.mjs +11 -0
- package/lib/snowflake-B_jap6lz.mjs +666 -0
- package/lib/snowflake-Cu1ZyOp6.mjs +151 -0
- package/lib/{src-AELUUb5U.mjs → src-BhinCSpi.mjs} +1172 -458
- package/lib/{stream-AVOoe5Hj.mjs → stream-D2ivg3GH.mjs} +3740 -5311
- package/lib/{turndown-D6fof1OX.mjs → turndown-Vya8SavL.mjs} +82 -30
- package/lib/types/tools/hashline/native/index.d.ts +2 -2
- package/lib/types/tools/hashline/native/policy.d.ts +19 -21
- package/lib/types/tools/omp/session/agent-storage.d.ts +3 -3
- package/lib/types/tools/shared/bun-named-shim.d.ts +5 -0
- package/lib/{types-BLrLohwK.mjs → types-tH1v9uRm.mjs} +2 -2
- package/lib/{utils-cZX3f_Ls.mjs → utils-C_Ncya1r.mjs} +1737 -509
- package/lib/utils-D2tK38xq.mjs +34006 -0
- package/lib/{utils-I4I8azHN.mjs → utils-DrDwmNtu.mjs} +8 -3
- package/lib/{xai-oauth-CbeldUSV.mjs → xai-oauth-DLLzX6my.mjs} +4 -4
- package/lib/{xiaomi-Dl3VSs04.mjs → xiaomi-CqK-KivK.mjs} +2 -2
- package/lib/{zai-FyjGSypr.mjs → zai-DoJ2xPIH.mjs} +2 -2
- package/lib/{zip-DRrycScC.mjs → zip-DG1mUV6X.mjs} +1 -1
- package/package.json +8 -8
- package/lib/amazon-bedrock-Dx0rr9dY.mjs +0 -996
- package/lib/anthropic-ClCw0PV_.mjs +0 -3624
- package/lib/anthropic-wire-lbGAFzYb.mjs +0 -927
- package/lib/azure-openai-responses-WE_bgFWp.mjs +0 -285
- package/lib/bundled-references-DY3EJxZV.mjs +0 -56
- package/lib/cloudflare-ai-gateway-CrMa97Ap.mjs +0 -44
- package/lib/collapse-CkMNRNr7.mjs +0 -2304
- package/lib/cursor-C6jaIJDg.mjs +0 -283
- package/lib/cursor-D-XZYDf_.mjs +0 -4544
- package/lib/deterministic-id-CUEIMSqR.mjs +0 -17
- package/lib/devin-ExGIghmx.mjs +0 -69
- package/lib/devin-u0ljw5P6.mjs +0 -628
- package/lib/effort-BdtQMN-_.mjs +0 -23
- package/lib/event-stream-BKEtb45Y.mjs +0 -167
- package/lib/gemini-headers-Co9cVvex.mjs +0 -54
- package/lib/google-auth-qAN-6DMW.mjs +0 -232
- package/lib/google-gemini-cli-B2Aw1S5w.mjs +0 -844
- package/lib/google-lTxuq28n.mjs +0 -38
- package/lib/google-shared-Y01j9xOr.mjs +0 -856
- package/lib/google-validation-BEkNs-Bx.mjs +0 -18
- package/lib/google-vertex-DcM-FRC5.mjs +0 -99
- package/lib/hosts-00rjRzUD.mjs +0 -203
- package/lib/id-AL5obQzR.mjs +0 -71
- package/lib/idle-iterator-D0ZXEcUq.mjs +0 -366
- package/lib/ollama-6R0oXZks.mjs +0 -574
- package/lib/openai-codex-responses-C8bnBWOe.mjs +0 -3232
- package/lib/openai-completions-DNr3mUsn.mjs +0 -1430
- package/lib/openai-configuration-update-xMYUjaK_.mjs +0 -150
- package/lib/openai-reasoning-fallback-Ju-5pSR8.mjs +0 -380
- package/lib/openai-responses-CjpafAEr.mjs +0 -861
- package/lib/protobuf-BMgDYu_U.mjs +0 -717
- package/lib/provider-response-SqKSkkUc.mjs +0 -22
- package/lib/proxy-DxvCQOCA.mjs +0 -230
- package/lib/request-debug-BwPOqN_j.mjs +0 -183
- package/lib/sanitize-text-BCf5KmCf.mjs +0 -33
- package/lib/sse-debug-B-tkLCPW.mjs +0 -11
- package/lib/stream-markup-healing-CN3RsqG9.mjs +0 -267
- package/lib/strict-tool-validation-CBTz1dAA.mjs +0 -105
- package/lib/taxonomy-DSIM99rS.mjs +0 -15392
- package/lib/thinking-ngMwf_1Y.mjs +0 -336
- package/lib/type-guards-CttAANEx.mjs +0 -11
- package/lib/utils-CE3DSebh.mjs +0 -11763
- package/lib/vision-guard-BCpXWUj3.mjs +0 -77
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { p as LRUCache } from "./src-BhinCSpi.mjs";
|
|
4
|
+
import { f as parseRevisionPrefix, h as isRecord, l as formatRevision, s as taxonomy, t as globMatch } from "./cascade-BWjRTD1q.mjs";
|
|
5
|
+
import "./utils-DrDwmNtu.mjs";
|
|
6
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.12.6/node_modules/@oh-my-pi/pi-catalog/src/compat/taxonomy.ts
|
|
7
|
+
/**
|
|
8
|
+
* Runtime model-identity taxonomy: classifies wire model ids into
|
|
9
|
+
* `(class, family, revision)` ranks, applies reviewed identity overrides, and
|
|
10
|
+
* exposes the collapse/discovery vocabularies.
|
|
11
|
+
*
|
|
12
|
+
* Faithful port of the o2 reference (`taxonomy.rs` / `classify.rs`):
|
|
13
|
+
* matchers rank `exact(4) > bounded(3) > namespace(2) > prefix(1) > glob(0)`
|
|
14
|
+
* with token byte length as tiebreak; equal cross-class or cross-family ranks
|
|
15
|
+
* throw unless classification is `lenient` (discovery normalization).
|
|
16
|
+
*/
|
|
17
|
+
/** Two classes, families, or reviewed override patterns tie for one model id. */
|
|
18
|
+
var AmbiguousIdentityError = class extends Error {
|
|
19
|
+
model;
|
|
20
|
+
first;
|
|
21
|
+
second;
|
|
22
|
+
constructor(model, first, second, kind) {
|
|
23
|
+
super(`ambiguous ${kind} for \`${model}\`: \`${first}\` and \`${second}\` tie`);
|
|
24
|
+
this.model = model;
|
|
25
|
+
this.first = first;
|
|
26
|
+
this.second = second;
|
|
27
|
+
this.name = "AmbiguousIdentityError";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const MATCHER_RANK = {
|
|
31
|
+
exact: 4,
|
|
32
|
+
bounded: 3,
|
|
33
|
+
namespace: 2,
|
|
34
|
+
prefix: 1,
|
|
35
|
+
glob: 0
|
|
36
|
+
};
|
|
37
|
+
function bareOf(id) {
|
|
38
|
+
const slash = id.lastIndexOf("/");
|
|
39
|
+
return slash === -1 ? id : id.slice(slash + 1);
|
|
40
|
+
}
|
|
41
|
+
function boundedMatch(value, token) {
|
|
42
|
+
if (value === token) return true;
|
|
43
|
+
if (!value.startsWith(token)) return false;
|
|
44
|
+
const next = value.charCodeAt(token.length);
|
|
45
|
+
return next === 45 || next === 95 || next === 46 || next === 58 || next >= 48 && next <= 57;
|
|
46
|
+
}
|
|
47
|
+
function matcherMatches(matcher, lower, bare) {
|
|
48
|
+
switch (matcher.kind) {
|
|
49
|
+
case "exact": return bare === matcher.token;
|
|
50
|
+
case "bounded": return boundedMatch(bare, matcher.token);
|
|
51
|
+
case "namespace": {
|
|
52
|
+
const parts = matcher.bounded ? lower.split(/[/.:]/) : lower.split("/");
|
|
53
|
+
for (const part of parts) {
|
|
54
|
+
if (!part) continue;
|
|
55
|
+
if (matcher.bounded ? boundedMatch(part, matcher.token) : part === matcher.token) return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
case "prefix": return bare.startsWith(matcher.token);
|
|
60
|
+
case "glob": return globMatch(matcher.token, bare);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function nonWildcardBytes(glob) {
|
|
64
|
+
let count = 0;
|
|
65
|
+
for (let i = 0; i < glob.length; i++) if (glob[i] !== "*") count++;
|
|
66
|
+
return count;
|
|
67
|
+
}
|
|
68
|
+
function rankFamilies(cls, subject) {
|
|
69
|
+
let winner;
|
|
70
|
+
let tied;
|
|
71
|
+
for (const family of cls.families) {
|
|
72
|
+
if (!globMatch(family.glob, subject)) continue;
|
|
73
|
+
const rank = [family.priority, nonWildcardBytes(family.glob)];
|
|
74
|
+
if (winner && winner.rank[0] === rank[0] && winner.rank[1] === rank[1] && winner.id !== family.id) tied = [winner.id, family.id];
|
|
75
|
+
else if (!winner || winner.rank[0] < rank[0] || winner.rank[0] === rank[0] && winner.rank[1] < rank[1]) {
|
|
76
|
+
winner = {
|
|
77
|
+
rank,
|
|
78
|
+
id: family.id
|
|
79
|
+
};
|
|
80
|
+
tied = void 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
winner,
|
|
85
|
+
tied
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function stripClassNamespace(cls, bare) {
|
|
89
|
+
const separator = bare.search(/[.:]/);
|
|
90
|
+
if (separator <= 0 || separator === bare.length - 1) return void 0;
|
|
91
|
+
const namespace = bare.slice(0, separator);
|
|
92
|
+
if (!cls.matchers.some((matcher) => matcher.token === namespace)) return void 0;
|
|
93
|
+
return bare.slice(separator + 1);
|
|
94
|
+
}
|
|
95
|
+
function classifyFamily(cls, bare, model, lenient) {
|
|
96
|
+
const initial = rankFamilies(cls, bare);
|
|
97
|
+
const tied = initial.tied;
|
|
98
|
+
if (!tied) return initial.winner?.id;
|
|
99
|
+
const scoped = stripClassNamespace(cls, bare);
|
|
100
|
+
if (scoped !== void 0) {
|
|
101
|
+
const rescored = rankFamilies(cls, scoped);
|
|
102
|
+
if (rescored.winner && !rescored.tied) return rescored.winner.id;
|
|
103
|
+
}
|
|
104
|
+
if (lenient) return void 0;
|
|
105
|
+
throw new AmbiguousIdentityError(model, tied[0], tied[1], "family");
|
|
106
|
+
}
|
|
107
|
+
function extractRevision(cls, bare) {
|
|
108
|
+
if (cls.skipBare.includes(bare)) return void 0;
|
|
109
|
+
for (const rule of cls.revisionPrefixes) {
|
|
110
|
+
let tail;
|
|
111
|
+
if (rule.anywhere) {
|
|
112
|
+
const start = bare.indexOf(rule.prefix);
|
|
113
|
+
if (start !== -1) tail = bare.slice(start + rule.prefix.length);
|
|
114
|
+
} else if (bare.startsWith(rule.prefix)) tail = bare.slice(rule.prefix.length);
|
|
115
|
+
if (tail === void 0) continue;
|
|
116
|
+
const digit = tail.search(/[0-9]/);
|
|
117
|
+
if (digit === -1) return void 0;
|
|
118
|
+
const revision = parseRevisionPrefix(tail.slice(digit));
|
|
119
|
+
return revision ? formatRevision(revision) : void 0;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function classifyRanks(model, lenient) {
|
|
123
|
+
const lower = model.trim().toLowerCase();
|
|
124
|
+
const bare = bareOf(lower);
|
|
125
|
+
let winner;
|
|
126
|
+
let tied;
|
|
127
|
+
for (const cls of taxonomy.classes) for (const matcher of cls.matchers) {
|
|
128
|
+
if (!matcherMatches(matcher, lower, bare)) continue;
|
|
129
|
+
const rank = [MATCHER_RANK[matcher.kind], matcher.token.length];
|
|
130
|
+
if (winner && winner.rank[0] === rank[0] && winner.rank[1] === rank[1] && winner.cls.id !== cls.id) tied = [winner.cls.id, cls.id];
|
|
131
|
+
else if (!winner || winner.rank[0] < rank[0] || winner.rank[0] === rank[0] && winner.rank[1] < rank[1]) {
|
|
132
|
+
winner = {
|
|
133
|
+
rank,
|
|
134
|
+
cls
|
|
135
|
+
};
|
|
136
|
+
tied = void 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (tied) {
|
|
140
|
+
if (lenient) return { class: "unknown" };
|
|
141
|
+
throw new AmbiguousIdentityError(lower, tied[0], tied[1], "class");
|
|
142
|
+
}
|
|
143
|
+
if (!winner) return { class: "unknown" };
|
|
144
|
+
const ranks = { class: winner.cls.id };
|
|
145
|
+
const family = classifyFamily(winner.cls, bare, lower, lenient);
|
|
146
|
+
if (family !== void 0) ranks.family = family;
|
|
147
|
+
const revision = extractRevision(winner.cls, bare);
|
|
148
|
+
if (revision !== void 0) ranks.revision = revision;
|
|
149
|
+
return ranks;
|
|
150
|
+
}
|
|
151
|
+
function ranksInClass(classId, model, lenient) {
|
|
152
|
+
const cls = taxonomy.classes.find((candidate) => candidate.id === classId);
|
|
153
|
+
if (!cls) return {};
|
|
154
|
+
const lower = model.trim().toLowerCase();
|
|
155
|
+
const bare = bareOf(lower);
|
|
156
|
+
const out = {};
|
|
157
|
+
const family = classifyFamily(cls, bare, lower, lenient);
|
|
158
|
+
if (family !== void 0) out.family = family;
|
|
159
|
+
const revision = extractRevision(cls, bare);
|
|
160
|
+
if (revision !== void 0) out.revision = revision;
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
let overrideIndexes;
|
|
164
|
+
function getOverrideIndexes() {
|
|
165
|
+
if (overrideIndexes !== void 0) return overrideIndexes;
|
|
166
|
+
const exact = /* @__PURE__ */ new Map();
|
|
167
|
+
const patterns = [];
|
|
168
|
+
const classes = taxonomy.classes;
|
|
169
|
+
for (const cls of classes) for (const override of cls.overrides) {
|
|
170
|
+
if (override.model === void 0) {
|
|
171
|
+
if (override.glob !== void 0) patterns.push({
|
|
172
|
+
override,
|
|
173
|
+
glob: override.glob,
|
|
174
|
+
provider: override.provider?.toLowerCase(),
|
|
175
|
+
specificity: nonWildcardBytes(override.glob)
|
|
176
|
+
});
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const key = override.model.toLowerCase();
|
|
180
|
+
let bucket = exact.get(key);
|
|
181
|
+
if (bucket === void 0) {
|
|
182
|
+
bucket = {
|
|
183
|
+
byProvider: /* @__PURE__ */ new Map(),
|
|
184
|
+
agnostic: void 0
|
|
185
|
+
};
|
|
186
|
+
exact.set(key, bucket);
|
|
187
|
+
}
|
|
188
|
+
if (override.provider !== void 0) {
|
|
189
|
+
const providerKey = override.provider.toLowerCase();
|
|
190
|
+
if (!bucket.byProvider.has(providerKey)) bucket.byProvider.set(providerKey, override);
|
|
191
|
+
} else bucket.agnostic ??= override;
|
|
192
|
+
}
|
|
193
|
+
overrideIndexes = {
|
|
194
|
+
exact,
|
|
195
|
+
patterns
|
|
196
|
+
};
|
|
197
|
+
return overrideIndexes;
|
|
198
|
+
}
|
|
199
|
+
function overrideIsActive(override, observedAtMs) {
|
|
200
|
+
return override.expiresAtMs === void 0 || observedAtMs === void 0 || observedAtMs < override.expiresAtMs;
|
|
201
|
+
}
|
|
202
|
+
function rankPatternOverrides(patterns, provider, bareModel, observedAtMs) {
|
|
203
|
+
let winner;
|
|
204
|
+
let tied;
|
|
205
|
+
for (const pattern of patterns) {
|
|
206
|
+
const { override, specificity } = pattern;
|
|
207
|
+
if (pattern.provider !== provider || !overrideIsActive(override, observedAtMs)) continue;
|
|
208
|
+
if (!globMatch(pattern.glob, bareModel)) continue;
|
|
209
|
+
if (winner?.specificity === specificity) tied = [winner.override, override];
|
|
210
|
+
else if (winner === void 0 || winner.specificity < specificity) {
|
|
211
|
+
winner = {
|
|
212
|
+
specificity,
|
|
213
|
+
override
|
|
214
|
+
};
|
|
215
|
+
tied = void 0;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
winner,
|
|
220
|
+
tied
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function findIdentityOverride(provider, bareModel, observedAtMs, lenient) {
|
|
224
|
+
const lowerProvider = provider.toLowerCase();
|
|
225
|
+
const lowerBareModel = bareModel.toLowerCase();
|
|
226
|
+
const indexes = getOverrideIndexes();
|
|
227
|
+
const bucket = indexes.exact.get(lowerBareModel);
|
|
228
|
+
if (bucket !== void 0) {
|
|
229
|
+
const scoped = bucket.byProvider.get(lowerProvider);
|
|
230
|
+
if (scoped !== void 0 && overrideIsActive(scoped, observedAtMs)) return scoped;
|
|
231
|
+
const agnostic = bucket.agnostic;
|
|
232
|
+
if (agnostic !== void 0 && overrideIsActive(agnostic, observedAtMs)) return agnostic;
|
|
233
|
+
}
|
|
234
|
+
const scoped = rankPatternOverrides(indexes.patterns, lowerProvider, lowerBareModel, observedAtMs);
|
|
235
|
+
const ranked = scoped.winner === void 0 && scoped.tied === void 0 ? rankPatternOverrides(indexes.patterns, void 0, lowerBareModel, observedAtMs) : scoped;
|
|
236
|
+
if (ranked.tied !== void 0) {
|
|
237
|
+
if (lenient) return void 0;
|
|
238
|
+
throw new AmbiguousIdentityError(lowerBareModel, ranked.tied[0].id, ranked.tied[1].id, "override");
|
|
239
|
+
}
|
|
240
|
+
return ranked.winner?.override;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Collapses a declared thinking or effort suffix from a model identifier.
|
|
244
|
+
* Exact `effort-family` aliases collapse to the family's logical model
|
|
245
|
+
* without assigning an effort; provider-scoped effort lanes additionally
|
|
246
|
+
* collapse an effort suffix wedged before the lane token.
|
|
247
|
+
*/
|
|
248
|
+
function collapseVariantId(provider, model) {
|
|
249
|
+
const { collapse } = taxonomy;
|
|
250
|
+
const lower = model.toLowerCase();
|
|
251
|
+
for (const family of collapse.effortFamilies) if (family.provider === provider.toLowerCase() && family.aliases.includes(lower)) return {
|
|
252
|
+
logicalId: family.logical,
|
|
253
|
+
thinkingVariant: false
|
|
254
|
+
};
|
|
255
|
+
const bare = bareOf(lower);
|
|
256
|
+
let winner;
|
|
257
|
+
for (const rule of collapse.suffixes) {
|
|
258
|
+
if (!lower.endsWith(rule.suffix)) continue;
|
|
259
|
+
if (rule.exceptBarePrefix !== void 0 && bare.startsWith(rule.exceptBarePrefix)) continue;
|
|
260
|
+
if (!winner || rule.suffix.length > winner.suffix.length) winner = rule;
|
|
261
|
+
}
|
|
262
|
+
if (winner) {
|
|
263
|
+
const collapsed = {
|
|
264
|
+
logicalId: model.slice(0, model.length - winner.suffix.length),
|
|
265
|
+
thinkingVariant: winner.thinking === true
|
|
266
|
+
};
|
|
267
|
+
if (winner.effort !== void 0) collapsed.effort = winner.effort;
|
|
268
|
+
return collapsed;
|
|
269
|
+
}
|
|
270
|
+
for (const lane of collapse.lanes) {
|
|
271
|
+
if (!lane.providers.some((candidate) => candidate === provider.toLowerCase()) || !lower.endsWith(lane.suffix)) continue;
|
|
272
|
+
const trimmed = lower.slice(0, lower.length - lane.suffix.length);
|
|
273
|
+
const trimmedBare = bareOf(trimmed);
|
|
274
|
+
if (lane.barePrefix !== void 0 && !trimmedBare.startsWith(lane.barePrefix)) continue;
|
|
275
|
+
let effortRule;
|
|
276
|
+
for (const rule of collapse.suffixes) {
|
|
277
|
+
if (rule.effort === void 0 || !trimmed.endsWith(rule.suffix)) continue;
|
|
278
|
+
if (rule.exceptBarePrefix !== void 0 && trimmedBare.startsWith(rule.exceptBarePrefix)) continue;
|
|
279
|
+
if (!effortRule || rule.suffix.length > effortRule.suffix.length) effortRule = rule;
|
|
280
|
+
}
|
|
281
|
+
if (!effortRule) continue;
|
|
282
|
+
const base = model.slice(0, trimmed.length - effortRule.suffix.length);
|
|
283
|
+
if (!base || base.endsWith("/")) continue;
|
|
284
|
+
return {
|
|
285
|
+
logicalId: `${base}${model.slice(trimmed.length)}`,
|
|
286
|
+
effort: effortRule.effort,
|
|
287
|
+
thinkingVariant: false
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
logicalId: model,
|
|
292
|
+
thinkingVariant: false
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Removes the first declared thinking-variant suffix token from a model id.
|
|
297
|
+
*
|
|
298
|
+
* Unlike {@link collapseVariantId}, this vocabulary-only helper also handles an
|
|
299
|
+
* infix token used to pair live discovery siblings. Negated forms such as
|
|
300
|
+
* `non-thinking` and `no-thinking` are not variants.
|
|
301
|
+
*/
|
|
302
|
+
function stripThinkingVariantSuffix(model) {
|
|
303
|
+
const lower = model.toLowerCase();
|
|
304
|
+
for (const token of taxonomy.collapse.pairTokens) {
|
|
305
|
+
const needle = `-${token}`;
|
|
306
|
+
let searchFrom = 0;
|
|
307
|
+
while (searchFrom < lower.length) {
|
|
308
|
+
const index = lower.indexOf(needle, searchFrom);
|
|
309
|
+
if (index === -1) break;
|
|
310
|
+
const end = index + needle.length;
|
|
311
|
+
const next = lower.charCodeAt(end);
|
|
312
|
+
const followedByTokenCharacter = next >= 48 && next <= 57 || next >= 97 && next <= 122;
|
|
313
|
+
let wordStart = index;
|
|
314
|
+
while (wordStart > 0) {
|
|
315
|
+
const code = lower.charCodeAt(wordStart - 1);
|
|
316
|
+
if (!(code >= 48 && code <= 57 || code >= 97 && code <= 122)) break;
|
|
317
|
+
wordStart--;
|
|
318
|
+
}
|
|
319
|
+
const preceding = lower.slice(wordStart, index);
|
|
320
|
+
if (!followedByTokenCharacter && preceding !== "non" && preceding !== "no") {
|
|
321
|
+
const stripped = model.slice(0, index) + model.slice(end);
|
|
322
|
+
return stripped.length > 0 ? stripped : void 0;
|
|
323
|
+
}
|
|
324
|
+
searchFrom = index + 1;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Classifies a model into its structured identity: reviewed override first,
|
|
330
|
+
* then suffix collapse, then class/family/revision ranks over the logical id.
|
|
331
|
+
*
|
|
332
|
+
* Results are memoized per (provider, model, lenient) — the rule tree is
|
|
333
|
+
* static per process. Cached identities are frozen and each caller receives
|
|
334
|
+
* a shallow copy, so a consumer that mutates its copy (e.g. `buildModel`
|
|
335
|
+
* storing `policy.identity` on the model) cannot poison the cache or any
|
|
336
|
+
* other model classified under the same key. Calls with an explicit
|
|
337
|
+
* observedAtMs skip the memo so override expiry stays exact.
|
|
338
|
+
*
|
|
339
|
+
* @throws AmbiguousIdentityError on equal-rank cross-class, cross-family, or
|
|
340
|
+
* reviewed-pattern matches unless `opts.lenient`.
|
|
341
|
+
*/
|
|
342
|
+
const classifyMemo = new LRUCache({ max: 16384 });
|
|
343
|
+
function classifyMemoKey(provider, modelId, lenient) {
|
|
344
|
+
return `${provider.length}:${provider}${modelId.length}:${modelId}${lenient ? 1 : 0}`;
|
|
345
|
+
}
|
|
346
|
+
function classifyModel(provider, modelId, opts) {
|
|
347
|
+
if (opts?.observedAtMs === void 0) {
|
|
348
|
+
const key = classifyMemoKey(provider, modelId, opts?.lenient === true);
|
|
349
|
+
const cached = classifyMemo.get(key);
|
|
350
|
+
if (cached !== void 0) return { ...cached };
|
|
351
|
+
const identity = classifyModelUncached(provider, modelId, opts);
|
|
352
|
+
classifyMemo.set(key, Object.freeze(identity));
|
|
353
|
+
return { ...identity };
|
|
354
|
+
}
|
|
355
|
+
return classifyModelUncached(provider, modelId, opts);
|
|
356
|
+
}
|
|
357
|
+
function classifyModelUncached(provider, modelId, opts) {
|
|
358
|
+
const lenient = opts?.lenient === true;
|
|
359
|
+
const trimmed = modelId.trim();
|
|
360
|
+
const override = findIdentityOverride(provider, bareOf(trimmed), opts?.observedAtMs, lenient);
|
|
361
|
+
if (override) {
|
|
362
|
+
const logical = override.logical ?? trimmed;
|
|
363
|
+
const cls = override.class ?? classifyRanks(logical, lenient).class;
|
|
364
|
+
const inferred = ranksInClass(cls, logical, lenient);
|
|
365
|
+
const identity = { class: cls };
|
|
366
|
+
const family = override.family ?? inferred.family;
|
|
367
|
+
if (family !== void 0) identity.family = family;
|
|
368
|
+
const revision = override.revision ?? inferred.revision;
|
|
369
|
+
if (revision !== void 0) identity.revision = revision;
|
|
370
|
+
if (override.effort !== void 0) identity.effort = override.effort;
|
|
371
|
+
if (override.thinkingVariant) identity.thinkingVariant = true;
|
|
372
|
+
if (logical !== trimmed) identity.logicalId = logical;
|
|
373
|
+
return identity;
|
|
374
|
+
}
|
|
375
|
+
const collapsed = trimmed.length === modelId.length ? collapseVariantId(provider, trimmed) : {
|
|
376
|
+
logicalId: trimmed,
|
|
377
|
+
thinkingVariant: false
|
|
378
|
+
};
|
|
379
|
+
const ranks = classifyRanks(collapsed.logicalId, lenient);
|
|
380
|
+
const identity = { class: ranks.class };
|
|
381
|
+
if (ranks.family !== void 0) identity.family = ranks.family;
|
|
382
|
+
if (ranks.revision !== void 0) identity.revision = ranks.revision;
|
|
383
|
+
if (collapsed.effort !== void 0) identity.effort = collapsed.effort;
|
|
384
|
+
if (collapsed.thinkingVariant) identity.thinkingVariant = true;
|
|
385
|
+
if (collapsed.logicalId !== trimmed) identity.logicalId = collapsed.logicalId;
|
|
386
|
+
return identity;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Strips a declared billing-variant suffix (`-free`, `-contributor`) from a
|
|
390
|
+
* wire identifier, returning the base id it shares a transport with.
|
|
391
|
+
*/
|
|
392
|
+
function billingVariantPlain(wireModel) {
|
|
393
|
+
for (const suffix of taxonomy.discovery.billingVariantSuffixes) {
|
|
394
|
+
const split = wireModel.length - suffix.length;
|
|
395
|
+
if (split <= 0) continue;
|
|
396
|
+
if (wireModel.slice(split).toLowerCase() === suffix) return wireModel.slice(0, split);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
/** The declared collapse suffix vocabulary (read-only view for collapse logic). */
|
|
400
|
+
function collapseVocabulary() {
|
|
401
|
+
return taxonomy.collapse;
|
|
402
|
+
}
|
|
403
|
+
/** The declared discovery vocabulary (read-only view). */
|
|
404
|
+
function discoveryVocabulary() {
|
|
405
|
+
return taxonomy.discovery;
|
|
406
|
+
}
|
|
407
|
+
//#endregion
|
|
408
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.12.6/node_modules/@oh-my-pi/pi-catalog/src/pricing.ts
|
|
409
|
+
function nonnegative(value) {
|
|
410
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
411
|
+
}
|
|
412
|
+
function isRates(value) {
|
|
413
|
+
return isRecord(value) && nonnegative(value.input) && nonnegative(value.output) && nonnegative(value.cacheRead) && nonnegative(value.cacheWrite);
|
|
414
|
+
}
|
|
415
|
+
function isLongContext(value) {
|
|
416
|
+
return isRecord(value) && isRates(value) && typeof value.inputThreshold === "number" && Number.isFinite(value.inputThreshold) && value.inputThreshold > 0 && (value.inputThresholdInclusive === void 0 || typeof value.inputThresholdInclusive === "boolean");
|
|
417
|
+
}
|
|
418
|
+
function isPeakWindow(value) {
|
|
419
|
+
return isRecord(value) && Array.isArray(value.weekdays) && value.weekdays.length > 0 && value.weekdays.every((day) => Number.isInteger(day) && day >= 0 && day <= 6) && new Set(value.weekdays).size === value.weekdays.length && typeof value.startMinute === "number" && Number.isInteger(value.startMinute) && typeof value.endMinute === "number" && Number.isInteger(value.endMinute) && value.startMinute >= 0 && value.endMinute <= 1440 && value.startMinute < value.endMinute;
|
|
420
|
+
}
|
|
421
|
+
function isEffectiveRate(value) {
|
|
422
|
+
return isRecord(value) && isRates(value) && typeof value.effectiveFrom === "number" && Number.isSafeInteger(value.effectiveFrom) && Math.abs(value.effectiveFrom) <= 864e13 && (value.longContext === void 0 || isLongContext(value.longContext));
|
|
423
|
+
}
|
|
424
|
+
/** Validate serialized schedules before admitting cached model rows. */
|
|
425
|
+
function isTimeBasedCost(value) {
|
|
426
|
+
if (!isRecord(value) || !nonnegative(value.offPeakMultiplier) || !Array.isArray(value.peakWindows) || !value.peakWindows.every(isPeakWindow)) return false;
|
|
427
|
+
if (value.effectiveRates === void 0) return true;
|
|
428
|
+
if (!Array.isArray(value.effectiveRates) || !value.effectiveRates.every(isEffectiveRate)) return false;
|
|
429
|
+
const dates = /* @__PURE__ */ new Set();
|
|
430
|
+
for (const rate of value.effectiveRates) {
|
|
431
|
+
if (dates.has(rate.effectiveFrom)) return false;
|
|
432
|
+
dates.add(rate.effectiveFrom);
|
|
433
|
+
}
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
function payload(value, keys, field) {
|
|
437
|
+
if (!isRecord(value) || Object.keys(value).some((key) => !keys.includes(key))) throw new Error(`Invalid time-based-cost ${field}`);
|
|
438
|
+
return value;
|
|
439
|
+
}
|
|
440
|
+
function namedEntries(value, field) {
|
|
441
|
+
if (!isRecord(value)) throw new Error(`Invalid time-based-cost ${field}: expected named objects`);
|
|
442
|
+
return Object.values(value);
|
|
443
|
+
}
|
|
444
|
+
/** Parse a KDL ISO UTC instant (`YYYY-MM-DDTHH:mm:ssZ`, optional milliseconds) to Unix ms. */
|
|
445
|
+
function parseUtcInstant(date, axis) {
|
|
446
|
+
if (typeof date !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/.test(date)) throw new Error(`Invalid ${axis} effective-from: expected an ISO UTC timestamp`);
|
|
447
|
+
const instant = Date.parse(date);
|
|
448
|
+
if (!Number.isFinite(instant) || new Date(instant).toISOString() !== (date.includes(".") ? date : date.replace("Z", ".000Z"))) throw new Error(`Invalid ${axis} effective-from: invalid UTC date`);
|
|
449
|
+
return instant;
|
|
450
|
+
}
|
|
451
|
+
/** KDL object children are named records; normalize them once while constructing the model. */
|
|
452
|
+
function materializeTimeBasedCost(value) {
|
|
453
|
+
const source = payload(value, [
|
|
454
|
+
"offPeakMultiplier",
|
|
455
|
+
"peakWindows",
|
|
456
|
+
"effectiveRates"
|
|
457
|
+
], "schedule");
|
|
458
|
+
const peakWindows = namedEntries(source.peakWindows, "peak-windows").map((entry) => {
|
|
459
|
+
const window = payload(entry, [
|
|
460
|
+
"weekdays",
|
|
461
|
+
"startMinute",
|
|
462
|
+
"endMinute"
|
|
463
|
+
], "peak-window");
|
|
464
|
+
if (typeof window.weekdays !== "string" || !/^[0-6](,[0-6])*$/.test(window.weekdays)) throw new Error("Invalid time-based-cost weekdays: expected comma-separated UTC weekday numbers");
|
|
465
|
+
return {
|
|
466
|
+
...window,
|
|
467
|
+
weekdays: window.weekdays.split(",").map(Number)
|
|
468
|
+
};
|
|
469
|
+
});
|
|
470
|
+
const effectiveRates = source.effectiveRates === void 0 ? void 0 : namedEntries(source.effectiveRates, "effective-rates").map((entry) => {
|
|
471
|
+
const rate = payload(entry, [
|
|
472
|
+
"effectiveFrom",
|
|
473
|
+
"input",
|
|
474
|
+
"output",
|
|
475
|
+
"cacheRead",
|
|
476
|
+
"cacheWrite",
|
|
477
|
+
"longContext"
|
|
478
|
+
], "effective-rate");
|
|
479
|
+
const effectiveFrom = parseUtcInstant(rate.effectiveFrom, "time-based-cost");
|
|
480
|
+
if (rate.longContext !== void 0) payload(rate.longContext, [
|
|
481
|
+
"inputThreshold",
|
|
482
|
+
"inputThresholdInclusive",
|
|
483
|
+
"input",
|
|
484
|
+
"output",
|
|
485
|
+
"cacheRead",
|
|
486
|
+
"cacheWrite"
|
|
487
|
+
], "long-context");
|
|
488
|
+
return {
|
|
489
|
+
...rate,
|
|
490
|
+
effectiveFrom
|
|
491
|
+
};
|
|
492
|
+
});
|
|
493
|
+
const schedule = {
|
|
494
|
+
offPeakMultiplier: source.offPeakMultiplier,
|
|
495
|
+
peakWindows,
|
|
496
|
+
...effectiveRates && { effectiveRates }
|
|
497
|
+
};
|
|
498
|
+
if (!isTimeBasedCost(schedule)) throw new Error("Invalid time-based-cost schedule: invalid windows, rates, or multiplier");
|
|
499
|
+
return schedule;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* The latest `effectiveRates` card of a materialized schedule due at
|
|
503
|
+
* `timestamp`, or undefined before the first one (or without a schedule).
|
|
504
|
+
*/
|
|
505
|
+
function dueEffectiveRate(schedule, timestamp) {
|
|
506
|
+
let due;
|
|
507
|
+
for (const candidate of schedule?.effectiveRates ?? []) if (candidate.effectiveFrom <= timestamp && (due === void 0 || candidate.effectiveFrom > due.effectiveFrom)) due = candidate;
|
|
508
|
+
return due;
|
|
509
|
+
}
|
|
510
|
+
const TOKEN_COST_LEGS = [
|
|
511
|
+
"input",
|
|
512
|
+
"output",
|
|
513
|
+
"cacheRead",
|
|
514
|
+
"cacheWrite"
|
|
515
|
+
];
|
|
516
|
+
const DATED_CARD_KEYS = ["effectiveFrom", ...TOKEN_COST_LEGS];
|
|
517
|
+
/**
|
|
518
|
+
* Parse the compiled `effective-rates` block of a `cost-patch` or
|
|
519
|
+
* `cost-fallback` payload into dated cards, ascending by date. Throws on a
|
|
520
|
+
* malformed card, so a typo in a rule fails the build instead of silently
|
|
521
|
+
* leaving the old price in force.
|
|
522
|
+
*/
|
|
523
|
+
function parseDatedCostCards(costAxis, axis) {
|
|
524
|
+
const effectiveRates = isRecord(costAxis) ? costAxis.effectiveRates : void 0;
|
|
525
|
+
if (effectiveRates === void 0) return [];
|
|
526
|
+
if (!isRecord(effectiveRates)) throw new Error(`Invalid ${axis} effective-rates: expected named objects`);
|
|
527
|
+
const cards = Object.values(effectiveRates).map((entry) => {
|
|
528
|
+
if (!isRecord(entry) || Object.keys(entry).some((key) => !DATED_CARD_KEYS.includes(key))) throw new Error(`Invalid ${axis} effective-rate: unknown or malformed fields`);
|
|
529
|
+
const card = { effectiveFrom: parseUtcInstant(entry.effectiveFrom, axis) };
|
|
530
|
+
for (const leg of TOKEN_COST_LEGS) {
|
|
531
|
+
const value = entry[leg];
|
|
532
|
+
if (value === void 0) continue;
|
|
533
|
+
if (!nonnegative(value)) throw new Error(`Invalid ${axis} effective-rate ${leg}: expected a nonnegative number`);
|
|
534
|
+
card[leg] = value;
|
|
535
|
+
}
|
|
536
|
+
return card;
|
|
537
|
+
});
|
|
538
|
+
cards.sort((a, b) => a.effectiveFrom - b.effectiveFrom);
|
|
539
|
+
for (let index = 1; index < cards.length; index++) if (cards[index].effectiveFrom === cards[index - 1].effectiveFrom) throw new Error(`Invalid ${axis} effective-rates: duplicate effective-from`);
|
|
540
|
+
return cards;
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Earliest instant a rate card can name (the `Date` range minimum). A leading
|
|
544
|
+
* card from here holds the price in force before the first dated change.
|
|
545
|
+
*/
|
|
546
|
+
const EARLIEST_EFFECTIVE_FROM = -864e13;
|
|
547
|
+
/** A schedule of dated rate cards alone: no peak windows, no off-peak discount. */
|
|
548
|
+
const NO_RECURRING_TARIFF = {
|
|
549
|
+
offPeakMultiplier: 1,
|
|
550
|
+
peakWindows: []
|
|
551
|
+
};
|
|
552
|
+
/**
|
|
553
|
+
* A flat card plus its dated overrides as a request-time `ModelCost`: the
|
|
554
|
+
* card due at `now` in the scalar legs, and every period (a leading card for
|
|
555
|
+
* the base price, then each dated card over the previous one) in a
|
|
556
|
+
* `timeBased` schedule without a recurring tariff. The plain card when no
|
|
557
|
+
* dated card exists.
|
|
558
|
+
*/
|
|
559
|
+
function datedCost(base, cards, now = Date.now()) {
|
|
560
|
+
if (cards.length === 0) return base;
|
|
561
|
+
const effectiveRates = [{
|
|
562
|
+
effectiveFrom: EARLIEST_EFFECTIVE_FROM,
|
|
563
|
+
...base
|
|
564
|
+
}];
|
|
565
|
+
for (const card of cards) effectiveRates.push({
|
|
566
|
+
...effectiveRates.at(-1),
|
|
567
|
+
...card
|
|
568
|
+
});
|
|
569
|
+
const timeBased = {
|
|
570
|
+
...NO_RECURRING_TARIFF,
|
|
571
|
+
effectiveRates
|
|
572
|
+
};
|
|
573
|
+
const { effectiveFrom: _effectiveFrom, ...due } = dueEffectiveRate(timeBased, now);
|
|
574
|
+
return {
|
|
575
|
+
...due,
|
|
576
|
+
timeBased
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Overwrite `cost` legs with the latest dated card due at `now`. Leaves
|
|
581
|
+
* `cost` unchanged before the first card.
|
|
582
|
+
*/
|
|
583
|
+
function applyDueDatedCostCard(cost, cards, now = Date.now()) {
|
|
584
|
+
let due;
|
|
585
|
+
for (const card of cards) if (card.effectiveFrom <= now) due = card;
|
|
586
|
+
if (due === void 0) return;
|
|
587
|
+
for (const leg of TOKEN_COST_LEGS) {
|
|
588
|
+
const value = due[leg];
|
|
589
|
+
if (value !== void 0) cost[leg] = value;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
//#endregion
|
|
593
|
+
export { dueEffectiveRate as a, billingVariantPlain as c, collapseVocabulary as d, discoveryVocabulary as f, datedCost as i, classifyModel as l, NO_RECURRING_TARIFF as n, materializeTimeBasedCost as o, stripThinkingVariantSuffix as p, applyDueDatedCostCard as r, parseDatedCostCards as s, EARLIEST_EFFECTIVE_FROM as t, collapseVariantId as u };
|