@omnicross/subscriptions 0.1.6 → 0.1.8
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/dist/{chunk-IXGHVMZB.js → chunk-4HYDPKHR.js} +50 -21
- package/dist/chunk-6TTHLCG6.cjs +33 -0
- package/dist/chunk-75ZPJI57.cjs +9 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-TDDDW53K.js +33 -0
- package/dist/{chunk-TPW5Q25Y.cjs → chunk-UXUMAXZJ.cjs} +53 -24
- package/dist/index.cjs +21 -40
- package/dist/index.js +16 -35
- package/dist/oauth.cjs +3 -2
- package/dist/oauth.js +2 -1
- package/dist/scheduler/accountModelMap.cjs +11 -0
- package/dist/scheduler/accountModelMap.d.cts +46 -0
- package/dist/scheduler/accountModelMap.d.ts +46 -0
- package/dist/scheduler/accountModelMap.js +11 -0
- package/package.json +1 -1
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-MLKGABMK.js";
|
|
6
4
|
|
|
7
5
|
// src/oauth/flows/claude.ts
|
|
8
6
|
var claude_exports = {};
|
|
@@ -29,39 +27,70 @@ function errorMessage(error, errorDescription) {
|
|
|
29
27
|
}
|
|
30
28
|
return String(error);
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
function withStatus(message, response) {
|
|
31
|
+
return response.ok ? message : `${message} (HTTP ${response.status})`;
|
|
32
|
+
}
|
|
33
|
+
var DEFAULT_TOKEN_TIMEOUT_MS = 3e4;
|
|
34
|
+
async function fetchWithTimeout(fetchImpl, url, init, timeoutMs) {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
37
|
+
try {
|
|
38
|
+
return await fetchImpl(url, { ...init, signal: controller.signal });
|
|
39
|
+
} catch (e) {
|
|
40
|
+
if (controller.signal.aborted) {
|
|
41
|
+
throw new Error(`token endpoint timed out after ${Math.round(timeoutMs / 1e3)}s`);
|
|
42
|
+
}
|
|
43
|
+
throw e;
|
|
44
|
+
} finally {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function postForm(fetchImpl, url, params, parseErrorMessage, timeoutMs = DEFAULT_TOKEN_TIMEOUT_MS) {
|
|
49
|
+
const response = await fetchWithTimeout(
|
|
50
|
+
fetchImpl,
|
|
51
|
+
url,
|
|
52
|
+
{
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
55
|
+
body: params.toString()
|
|
56
|
+
},
|
|
57
|
+
timeoutMs
|
|
58
|
+
);
|
|
38
59
|
const responseData = await response.text();
|
|
39
60
|
let data;
|
|
40
61
|
try {
|
|
41
62
|
data = JSON.parse(responseData);
|
|
42
63
|
} catch {
|
|
43
|
-
throw new Error(parseErrorMessage);
|
|
64
|
+
throw new Error(withStatus(parseErrorMessage, response));
|
|
44
65
|
}
|
|
45
66
|
if (data.error) {
|
|
46
|
-
throw new Error(errorMessage(data.error, data.error_description));
|
|
67
|
+
throw new Error(withStatus(errorMessage(data.error, data.error_description), response));
|
|
47
68
|
}
|
|
48
69
|
return data;
|
|
49
70
|
}
|
|
50
|
-
async function postJson(fetchImpl, url, body, parseErrorMessage, extraHeaders = {}) {
|
|
51
|
-
const response = await
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
71
|
+
async function postJson(fetchImpl, url, body, parseErrorMessage, extraHeaders = {}, timeoutMs = DEFAULT_TOKEN_TIMEOUT_MS) {
|
|
72
|
+
const response = await fetchWithTimeout(
|
|
73
|
+
fetchImpl,
|
|
74
|
+
url,
|
|
75
|
+
{
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: { "Content-Type": "application/json", ...extraHeaders },
|
|
78
|
+
body: JSON.stringify(body)
|
|
79
|
+
},
|
|
80
|
+
timeoutMs
|
|
81
|
+
);
|
|
56
82
|
const responseData = await response.text();
|
|
57
83
|
let data;
|
|
58
84
|
try {
|
|
59
85
|
data = JSON.parse(responseData);
|
|
60
86
|
} catch {
|
|
61
|
-
throw new Error(parseErrorMessage);
|
|
87
|
+
throw new Error(withStatus(parseErrorMessage, response));
|
|
62
88
|
}
|
|
63
89
|
if (data.error) {
|
|
64
|
-
throw new Error(errorMessage(data.error, data.error_description));
|
|
90
|
+
throw new Error(withStatus(errorMessage(data.error, data.error_description), response));
|
|
91
|
+
}
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw new Error(withStatus("token endpoint rejected the request", response));
|
|
65
94
|
}
|
|
66
95
|
return data;
|
|
67
96
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/scheduler/accountModelMap.ts
|
|
2
|
+
function canonicalModelId(value) {
|
|
3
|
+
const idx = value.indexOf(",");
|
|
4
|
+
const bare = idx >= 0 ? value.slice(idx + 1) : value;
|
|
5
|
+
return bare.trim().toLowerCase();
|
|
6
|
+
}
|
|
7
|
+
function accountSupportsModel(supportedModels, model) {
|
|
8
|
+
if (!supportedModels) return true;
|
|
9
|
+
const target = canonicalModelId(model);
|
|
10
|
+
if (Array.isArray(supportedModels)) {
|
|
11
|
+
return supportedModels.some((m) => canonicalModelId(m) === target);
|
|
12
|
+
}
|
|
13
|
+
return Object.keys(supportedModels).some((k) => canonicalModelId(k) === target);
|
|
14
|
+
}
|
|
15
|
+
function remapForAccount(supportedModels, model) {
|
|
16
|
+
if (!supportedModels || Array.isArray(supportedModels)) return model;
|
|
17
|
+
const target = canonicalModelId(model);
|
|
18
|
+
for (const [key, actual] of Object.entries(supportedModels)) {
|
|
19
|
+
if (canonicalModelId(key) === target) return actual;
|
|
20
|
+
}
|
|
21
|
+
return model;
|
|
22
|
+
}
|
|
23
|
+
function remapReportForAccount(supportedModels, model) {
|
|
24
|
+
if (!model) return void 0;
|
|
25
|
+
const remapped = remapForAccount(supportedModels, model);
|
|
26
|
+
return remapped === model ? void 0 : remapped;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
exports.accountSupportsModel = accountSupportsModel; exports.remapForAccount = remapForAccount; exports.remapReportForAccount = remapReportForAccount;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.__export = __export;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/scheduler/accountModelMap.ts
|
|
2
|
+
function canonicalModelId(value) {
|
|
3
|
+
const idx = value.indexOf(",");
|
|
4
|
+
const bare = idx >= 0 ? value.slice(idx + 1) : value;
|
|
5
|
+
return bare.trim().toLowerCase();
|
|
6
|
+
}
|
|
7
|
+
function accountSupportsModel(supportedModels, model) {
|
|
8
|
+
if (!supportedModels) return true;
|
|
9
|
+
const target = canonicalModelId(model);
|
|
10
|
+
if (Array.isArray(supportedModels)) {
|
|
11
|
+
return supportedModels.some((m) => canonicalModelId(m) === target);
|
|
12
|
+
}
|
|
13
|
+
return Object.keys(supportedModels).some((k) => canonicalModelId(k) === target);
|
|
14
|
+
}
|
|
15
|
+
function remapForAccount(supportedModels, model) {
|
|
16
|
+
if (!supportedModels || Array.isArray(supportedModels)) return model;
|
|
17
|
+
const target = canonicalModelId(model);
|
|
18
|
+
for (const [key, actual] of Object.entries(supportedModels)) {
|
|
19
|
+
if (canonicalModelId(key) === target) return actual;
|
|
20
|
+
}
|
|
21
|
+
return model;
|
|
22
|
+
}
|
|
23
|
+
function remapReportForAccount(supportedModels, model) {
|
|
24
|
+
if (!model) return void 0;
|
|
25
|
+
const remapped = remapForAccount(supportedModels, model);
|
|
26
|
+
return remapped === model ? void 0 : remapped;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
accountSupportsModel,
|
|
31
|
+
remapForAccount,
|
|
32
|
+
remapReportForAccount
|
|
33
|
+
};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
-
};
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
var _chunk75ZPJI57cjs = require('./chunk-75ZPJI57.cjs');
|
|
6
4
|
|
|
7
5
|
// src/oauth/flows/claude.ts
|
|
8
6
|
var claude_exports = {};
|
|
9
|
-
__export(claude_exports, {
|
|
7
|
+
_chunk75ZPJI57cjs.__export.call(void 0, claude_exports, {
|
|
10
8
|
exchangeCodeForTokens: () => exchangeCodeForTokens,
|
|
11
9
|
exchangeSetupTokenCode: () => exchangeSetupTokenCode,
|
|
12
10
|
generateAuthParams: () => generateAuthParams,
|
|
@@ -29,39 +27,70 @@ function errorMessage(error, errorDescription) {
|
|
|
29
27
|
}
|
|
30
28
|
return String(error);
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
function withStatus(message, response) {
|
|
31
|
+
return response.ok ? message : `${message} (HTTP ${response.status})`;
|
|
32
|
+
}
|
|
33
|
+
var DEFAULT_TOKEN_TIMEOUT_MS = 3e4;
|
|
34
|
+
async function fetchWithTimeout(fetchImpl, url, init, timeoutMs) {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
37
|
+
try {
|
|
38
|
+
return await fetchImpl(url, { ...init, signal: controller.signal });
|
|
39
|
+
} catch (e) {
|
|
40
|
+
if (controller.signal.aborted) {
|
|
41
|
+
throw new Error(`token endpoint timed out after ${Math.round(timeoutMs / 1e3)}s`);
|
|
42
|
+
}
|
|
43
|
+
throw e;
|
|
44
|
+
} finally {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function postForm(fetchImpl, url, params, parseErrorMessage, timeoutMs = DEFAULT_TOKEN_TIMEOUT_MS) {
|
|
49
|
+
const response = await fetchWithTimeout(
|
|
50
|
+
fetchImpl,
|
|
51
|
+
url,
|
|
52
|
+
{
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
55
|
+
body: params.toString()
|
|
56
|
+
},
|
|
57
|
+
timeoutMs
|
|
58
|
+
);
|
|
38
59
|
const responseData = await response.text();
|
|
39
60
|
let data;
|
|
40
61
|
try {
|
|
41
62
|
data = JSON.parse(responseData);
|
|
42
63
|
} catch (e2) {
|
|
43
|
-
throw new Error(parseErrorMessage);
|
|
64
|
+
throw new Error(withStatus(parseErrorMessage, response));
|
|
44
65
|
}
|
|
45
66
|
if (data.error) {
|
|
46
|
-
throw new Error(errorMessage(data.error, data.error_description));
|
|
67
|
+
throw new Error(withStatus(errorMessage(data.error, data.error_description), response));
|
|
47
68
|
}
|
|
48
69
|
return data;
|
|
49
70
|
}
|
|
50
|
-
async function postJson(fetchImpl, url, body, parseErrorMessage, extraHeaders = {}) {
|
|
51
|
-
const response = await
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
71
|
+
async function postJson(fetchImpl, url, body, parseErrorMessage, extraHeaders = {}, timeoutMs = DEFAULT_TOKEN_TIMEOUT_MS) {
|
|
72
|
+
const response = await fetchWithTimeout(
|
|
73
|
+
fetchImpl,
|
|
74
|
+
url,
|
|
75
|
+
{
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: { "Content-Type": "application/json", ...extraHeaders },
|
|
78
|
+
body: JSON.stringify(body)
|
|
79
|
+
},
|
|
80
|
+
timeoutMs
|
|
81
|
+
);
|
|
56
82
|
const responseData = await response.text();
|
|
57
83
|
let data;
|
|
58
84
|
try {
|
|
59
85
|
data = JSON.parse(responseData);
|
|
60
86
|
} catch (e3) {
|
|
61
|
-
throw new Error(parseErrorMessage);
|
|
87
|
+
throw new Error(withStatus(parseErrorMessage, response));
|
|
62
88
|
}
|
|
63
89
|
if (data.error) {
|
|
64
|
-
throw new Error(errorMessage(data.error, data.error_description));
|
|
90
|
+
throw new Error(withStatus(errorMessage(data.error, data.error_description), response));
|
|
91
|
+
}
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw new Error(withStatus("token endpoint rejected the request", response));
|
|
65
94
|
}
|
|
66
95
|
return data;
|
|
67
96
|
}
|
|
@@ -204,7 +233,7 @@ async function refreshAccessToken(refreshToken, fetchImpl) {
|
|
|
204
233
|
|
|
205
234
|
// src/oauth/flows/codex.ts
|
|
206
235
|
var codex_exports = {};
|
|
207
|
-
__export(codex_exports, {
|
|
236
|
+
_chunk75ZPJI57cjs.__export.call(void 0, codex_exports, {
|
|
208
237
|
exchangeCodeForTokens: () => exchangeCodeForTokens2,
|
|
209
238
|
generateAuthParams: () => generateAuthParams2,
|
|
210
239
|
refreshAccessToken: () => refreshAccessToken2
|
|
@@ -280,7 +309,7 @@ async function refreshAccessToken2(refreshToken, fetchImpl) {
|
|
|
280
309
|
|
|
281
310
|
// src/oauth/flows/gemini.ts
|
|
282
311
|
var gemini_exports = {};
|
|
283
|
-
__export(gemini_exports, {
|
|
312
|
+
_chunk75ZPJI57cjs.__export.call(void 0, gemini_exports, {
|
|
284
313
|
exchangeCodeForTokens: () => exchangeCodeForTokens3,
|
|
285
314
|
generateAuthParams: () => generateAuthParams3,
|
|
286
315
|
refreshAccessToken: () => refreshAccessToken3
|
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkUXUMAXZJcjs = require('./chunk-UXUMAXZJ.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
var _chunk6TTHLCG6cjs = require('./chunk-6TTHLCG6.cjs');
|
|
10
|
+
require('./chunk-75ZPJI57.cjs');
|
|
6
11
|
|
|
7
12
|
// src/scheduler/SubscriptionAccountSelector.ts
|
|
8
13
|
var SESSION_AFFINITY_TTL_MS = 36e5;
|
|
@@ -61,7 +66,7 @@ var SubscriptionAccountSelector = (_class = class {constructor() { _class.protot
|
|
|
61
66
|
* conversation).
|
|
62
67
|
*/
|
|
63
68
|
evictAffinity(providerId, accountId) {
|
|
64
|
-
const prefix =
|
|
69
|
+
const prefix = scopedKey(providerId, "");
|
|
65
70
|
for (const [key, entry] of this.affinity) {
|
|
66
71
|
if (entry.accountId === accountId && key.startsWith(prefix)) {
|
|
67
72
|
this.affinity.delete(key);
|
|
@@ -116,36 +121,6 @@ var _AccountAllowanceScheduling = require('@omnicross/core/pipeline/AccountAllow
|
|
|
116
121
|
|
|
117
122
|
|
|
118
123
|
var _BoundAccountSelectionError = require('@omnicross/core/pipeline/BoundAccountSelectionError');
|
|
119
|
-
|
|
120
|
-
// src/scheduler/accountModelMap.ts
|
|
121
|
-
function canonicalModelId(value) {
|
|
122
|
-
const idx = value.indexOf(",");
|
|
123
|
-
const bare = idx >= 0 ? value.slice(idx + 1) : value;
|
|
124
|
-
return bare.trim().toLowerCase();
|
|
125
|
-
}
|
|
126
|
-
function accountSupportsModel(supportedModels, model) {
|
|
127
|
-
if (!supportedModels) return true;
|
|
128
|
-
const target = canonicalModelId(model);
|
|
129
|
-
if (Array.isArray(supportedModels)) {
|
|
130
|
-
return supportedModels.some((m) => canonicalModelId(m) === target);
|
|
131
|
-
}
|
|
132
|
-
return Object.keys(supportedModels).some((k) => canonicalModelId(k) === target);
|
|
133
|
-
}
|
|
134
|
-
function remapForAccount(supportedModels, model) {
|
|
135
|
-
if (!supportedModels || Array.isArray(supportedModels)) return model;
|
|
136
|
-
const target = canonicalModelId(model);
|
|
137
|
-
for (const [key, actual] of Object.entries(supportedModels)) {
|
|
138
|
-
if (canonicalModelId(key) === target) return actual;
|
|
139
|
-
}
|
|
140
|
-
return model;
|
|
141
|
-
}
|
|
142
|
-
function remapReportForAccount(supportedModels, model) {
|
|
143
|
-
if (!model) return void 0;
|
|
144
|
-
const remapped = remapForAccount(supportedModels, model);
|
|
145
|
-
return remapped === model ? void 0 : remapped;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// src/scheduler/accountSelection.ts
|
|
149
124
|
var ACCOUNTS_KEY = {
|
|
150
125
|
claude: "claudeAccounts",
|
|
151
126
|
codex: "codexAccounts",
|
|
@@ -162,7 +137,7 @@ function gateSchedulable(accounts, providerId, health, now, resolvedModel, suppo
|
|
|
162
137
|
if (!health && !resolvedModel || accounts.length < 2) return accounts;
|
|
163
138
|
return accounts.map((a) => {
|
|
164
139
|
const healthOk = health ? health.isSchedulable(providerId, a.id, now) : true;
|
|
165
|
-
const modelOk = resolvedModel ? accountSupportsModel(supportedModelsById.get(a.id), resolvedModel) : true;
|
|
140
|
+
const modelOk = resolvedModel ? _chunk6TTHLCG6cjs.accountSupportsModel.call(void 0, supportedModelsById.get(a.id), resolvedModel) : true;
|
|
166
141
|
return { ...a, schedulable: a.schedulable !== false && healthOk && modelOk };
|
|
167
142
|
});
|
|
168
143
|
}
|
|
@@ -172,7 +147,7 @@ function isPoolGated(accounts, health, resolvedModel) {
|
|
|
172
147
|
function hasUsableToken(token) {
|
|
173
148
|
return typeof token === "string" && token.trim() !== "";
|
|
174
149
|
}
|
|
175
|
-
async function resolveStrictPreferredToken(tokens, providerId, preferredId, activeGetter, ctx) {
|
|
150
|
+
async function resolveStrictPreferredToken(selector, tokens, providerId, preferredId, activeGetter, ctx) {
|
|
176
151
|
let config;
|
|
177
152
|
try {
|
|
178
153
|
config = await tokens.getFullConfig();
|
|
@@ -197,7 +172,7 @@ async function resolveStrictPreferredToken(tokens, providerId, preferredId, acti
|
|
|
197
172
|
if (ctx.health && !ctx.health.isSchedulable(providerId, preferredId, ctx.now)) {
|
|
198
173
|
throw new (0, _BoundAccountSelectionError.BoundAccountSelectionError)(providerId, "unhealthy");
|
|
199
174
|
}
|
|
200
|
-
if (ctx.resolvedModel && !accountSupportsModel(supportedModelsById.get(preferredId), ctx.resolvedModel)) {
|
|
175
|
+
if (ctx.resolvedModel && !_chunk6TTHLCG6cjs.accountSupportsModel.call(void 0, supportedModelsById.get(preferredId), ctx.resolvedModel)) {
|
|
201
176
|
throw new (0, _BoundAccountSelectionError.BoundAccountSelectionError)(providerId, "model-incompatible");
|
|
202
177
|
}
|
|
203
178
|
const allowance = _AccountAllowanceScheduling.getSharedAccountAllowanceScheduling.call(void 0, ).evaluate(
|
|
@@ -218,7 +193,8 @@ async function resolveStrictPreferredToken(tokens, providerId, preferredId, acti
|
|
|
218
193
|
if (!hasUsableToken(token)) {
|
|
219
194
|
throw new (0, _BoundAccountSelectionError.BoundAccountSelectionError)(providerId, "empty-token");
|
|
220
195
|
}
|
|
221
|
-
const remapped = remapReportForAccount(supportedModelsById.get(preferredId), ctx.resolvedModel);
|
|
196
|
+
const remapped = _chunk6TTHLCG6cjs.remapReportForAccount.call(void 0, supportedModelsById.get(preferredId), ctx.resolvedModel);
|
|
197
|
+
if (selector) maybeTouchLastUsed(selector, tokens, providerId, preferredId);
|
|
222
198
|
_optionalChain([ctx, 'access', _ => _.reportSelection, 'optionalCall', _2 => _2(preferredId, preferredId === activeAccountId, remapped)]);
|
|
223
199
|
return token;
|
|
224
200
|
}
|
|
@@ -284,7 +260,7 @@ async function resolveSelectedToken(selector, tokens, providerId, sessionKey, ac
|
|
|
284
260
|
const preferredId = typeof _optionalChain([ctx, 'optionalAccess', _9 => _9.preferredAccountId]) === "string" && ctx.preferredAccountId.trim() !== "" ? ctx.preferredAccountId.trim() : void 0;
|
|
285
261
|
const preferredGroup = typeof _optionalChain([ctx, 'optionalAccess', _10 => _10.preferredAccountGroup]) === "string" && ctx.preferredAccountGroup.trim() !== "" ? ctx.preferredAccountGroup.trim() : void 0;
|
|
286
262
|
if (preferredId && ctx && ctx.boundAccountFallbackPolicy !== "pool") {
|
|
287
|
-
return resolveStrictPreferredToken(tokens, providerId, preferredId, activeGetter, ctx);
|
|
263
|
+
return resolveStrictPreferredToken(selector, tokens, providerId, preferredId, activeGetter, ctx);
|
|
288
264
|
}
|
|
289
265
|
if (selector && tokens.getAccessTokenForAccount) {
|
|
290
266
|
const config = await tokens.getFullConfig();
|
|
@@ -327,7 +303,7 @@ async function resolveSelectedToken(selector, tokens, providerId, sessionKey, ac
|
|
|
327
303
|
gated = gateByAllowance(healthAndModelGated, providerId, now);
|
|
328
304
|
}
|
|
329
305
|
const poolGated = isPoolGated(candidates, health, resolvedModel) || candidates.some((account) => account.schedulable === false) || preferredGroup !== void 0;
|
|
330
|
-
const remapFor = (id) => remapReportForAccount(supportedModelsById.get(id), resolvedModel);
|
|
306
|
+
const remapFor = (id) => _chunk6TTHLCG6cjs.remapReportForAccount.call(void 0, supportedModelsById.get(id), resolvedModel);
|
|
331
307
|
if (preferredId) {
|
|
332
308
|
const preferred = gated.find((a) => a.id === preferredId);
|
|
333
309
|
if (preferred && preferred.schedulable !== false) {
|
|
@@ -375,7 +351,12 @@ async function resolveSelectedToken(selector, tokens, providerId, sessionKey, ac
|
|
|
375
351
|
if (activeAllowance.action === "pause") {
|
|
376
352
|
throw new (0, _AccountAllowanceScheduling.AccountAllowanceExhaustedError)(providerId, activeAllowance.resumeAt);
|
|
377
353
|
}
|
|
378
|
-
|
|
354
|
+
const token = await activeGetter();
|
|
355
|
+
if (hasUsableToken(token)) {
|
|
356
|
+
maybeTouchLastUsed(selector, tokens, providerId, activeAccountId);
|
|
357
|
+
_optionalChain([report, 'optionalCall', _22 => _22(activeAccountId, true, remapFor(activeAccountId))]);
|
|
358
|
+
}
|
|
359
|
+
return token;
|
|
379
360
|
}
|
|
380
361
|
return activeGetter();
|
|
381
362
|
}
|
|
@@ -1697,4 +1678,4 @@ function stripAuthHeaders(headers) {
|
|
|
1697
1678
|
|
|
1698
1679
|
|
|
1699
1680
|
|
|
1700
|
-
exports.DEFAULT_ACCOUNT_PRIORITY = DEFAULT_ACCOUNT_PRIORITY; exports.LAST_USED_PERSIST_THROTTLE_MS = LAST_USED_PERSIST_THROTTLE_MS; exports.SESSION_AFFINITY_TTL_MS = SESSION_AFFINITY_TTL_MS; exports.SubscriptionAccountSelector = SubscriptionAccountSelector; exports.SubscriptionAccountService = SubscriptionAccountService; exports.SubscriptionDispatcher = SubscriptionDispatcher; exports.SubscriptionProviderRegistry = SubscriptionProviderRegistry; exports.claudeOAuth =
|
|
1681
|
+
exports.DEFAULT_ACCOUNT_PRIORITY = DEFAULT_ACCOUNT_PRIORITY; exports.LAST_USED_PERSIST_THROTTLE_MS = LAST_USED_PERSIST_THROTTLE_MS; exports.SESSION_AFFINITY_TTL_MS = SESSION_AFFINITY_TTL_MS; exports.SubscriptionAccountSelector = SubscriptionAccountSelector; exports.SubscriptionAccountService = SubscriptionAccountService; exports.SubscriptionDispatcher = SubscriptionDispatcher; exports.SubscriptionProviderRegistry = SubscriptionProviderRegistry; exports.claudeOAuth = _chunkUXUMAXZJcjs.claude_exports; exports.codexOAuth = _chunkUXUMAXZJcjs.codex_exports; exports.geminiOAuth = _chunkUXUMAXZJcjs.gemini_exports; exports.getSubscriptionAccountService = getSubscriptionAccountService; exports.getSubscriptionProviderRegistry = getSubscriptionProviderRegistry; exports.setSubscriptionAccountService = setSubscriptionAccountService; exports.setSubscriptionProviderRegistry = setSubscriptionProviderRegistry;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,12 @@ import {
|
|
|
2
2
|
claude_exports,
|
|
3
3
|
codex_exports,
|
|
4
4
|
gemini_exports
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4HYDPKHR.js";
|
|
6
|
+
import {
|
|
7
|
+
accountSupportsModel,
|
|
8
|
+
remapReportForAccount
|
|
9
|
+
} from "./chunk-TDDDW53K.js";
|
|
10
|
+
import "./chunk-MLKGABMK.js";
|
|
6
11
|
|
|
7
12
|
// src/scheduler/SubscriptionAccountSelector.ts
|
|
8
13
|
var SESSION_AFFINITY_TTL_MS = 36e5;
|
|
@@ -61,7 +66,7 @@ var SubscriptionAccountSelector = class {
|
|
|
61
66
|
* conversation).
|
|
62
67
|
*/
|
|
63
68
|
evictAffinity(providerId, accountId) {
|
|
64
|
-
const prefix =
|
|
69
|
+
const prefix = scopedKey(providerId, "");
|
|
65
70
|
for (const [key, entry] of this.affinity) {
|
|
66
71
|
if (entry.accountId === accountId && key.startsWith(prefix)) {
|
|
67
72
|
this.affinity.delete(key);
|
|
@@ -116,36 +121,6 @@ import {
|
|
|
116
121
|
import {
|
|
117
122
|
BoundAccountSelectionError
|
|
118
123
|
} from "@omnicross/core/pipeline/BoundAccountSelectionError";
|
|
119
|
-
|
|
120
|
-
// src/scheduler/accountModelMap.ts
|
|
121
|
-
function canonicalModelId(value) {
|
|
122
|
-
const idx = value.indexOf(",");
|
|
123
|
-
const bare = idx >= 0 ? value.slice(idx + 1) : value;
|
|
124
|
-
return bare.trim().toLowerCase();
|
|
125
|
-
}
|
|
126
|
-
function accountSupportsModel(supportedModels, model) {
|
|
127
|
-
if (!supportedModels) return true;
|
|
128
|
-
const target = canonicalModelId(model);
|
|
129
|
-
if (Array.isArray(supportedModels)) {
|
|
130
|
-
return supportedModels.some((m) => canonicalModelId(m) === target);
|
|
131
|
-
}
|
|
132
|
-
return Object.keys(supportedModels).some((k) => canonicalModelId(k) === target);
|
|
133
|
-
}
|
|
134
|
-
function remapForAccount(supportedModels, model) {
|
|
135
|
-
if (!supportedModels || Array.isArray(supportedModels)) return model;
|
|
136
|
-
const target = canonicalModelId(model);
|
|
137
|
-
for (const [key, actual] of Object.entries(supportedModels)) {
|
|
138
|
-
if (canonicalModelId(key) === target) return actual;
|
|
139
|
-
}
|
|
140
|
-
return model;
|
|
141
|
-
}
|
|
142
|
-
function remapReportForAccount(supportedModels, model) {
|
|
143
|
-
if (!model) return void 0;
|
|
144
|
-
const remapped = remapForAccount(supportedModels, model);
|
|
145
|
-
return remapped === model ? void 0 : remapped;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// src/scheduler/accountSelection.ts
|
|
149
124
|
var ACCOUNTS_KEY = {
|
|
150
125
|
claude: "claudeAccounts",
|
|
151
126
|
codex: "codexAccounts",
|
|
@@ -172,7 +147,7 @@ function isPoolGated(accounts, health, resolvedModel) {
|
|
|
172
147
|
function hasUsableToken(token) {
|
|
173
148
|
return typeof token === "string" && token.trim() !== "";
|
|
174
149
|
}
|
|
175
|
-
async function resolveStrictPreferredToken(tokens, providerId, preferredId, activeGetter, ctx) {
|
|
150
|
+
async function resolveStrictPreferredToken(selector, tokens, providerId, preferredId, activeGetter, ctx) {
|
|
176
151
|
let config;
|
|
177
152
|
try {
|
|
178
153
|
config = await tokens.getFullConfig();
|
|
@@ -219,6 +194,7 @@ async function resolveStrictPreferredToken(tokens, providerId, preferredId, acti
|
|
|
219
194
|
throw new BoundAccountSelectionError(providerId, "empty-token");
|
|
220
195
|
}
|
|
221
196
|
const remapped = remapReportForAccount(supportedModelsById.get(preferredId), ctx.resolvedModel);
|
|
197
|
+
if (selector) maybeTouchLastUsed(selector, tokens, providerId, preferredId);
|
|
222
198
|
ctx.reportSelection?.(preferredId, preferredId === activeAccountId, remapped);
|
|
223
199
|
return token;
|
|
224
200
|
}
|
|
@@ -284,7 +260,7 @@ async function resolveSelectedToken(selector, tokens, providerId, sessionKey, ac
|
|
|
284
260
|
const preferredId = typeof ctx?.preferredAccountId === "string" && ctx.preferredAccountId.trim() !== "" ? ctx.preferredAccountId.trim() : void 0;
|
|
285
261
|
const preferredGroup = typeof ctx?.preferredAccountGroup === "string" && ctx.preferredAccountGroup.trim() !== "" ? ctx.preferredAccountGroup.trim() : void 0;
|
|
286
262
|
if (preferredId && ctx && ctx.boundAccountFallbackPolicy !== "pool") {
|
|
287
|
-
return resolveStrictPreferredToken(tokens, providerId, preferredId, activeGetter, ctx);
|
|
263
|
+
return resolveStrictPreferredToken(selector, tokens, providerId, preferredId, activeGetter, ctx);
|
|
288
264
|
}
|
|
289
265
|
if (selector && tokens.getAccessTokenForAccount) {
|
|
290
266
|
const config = await tokens.getFullConfig();
|
|
@@ -375,7 +351,12 @@ async function resolveSelectedToken(selector, tokens, providerId, sessionKey, ac
|
|
|
375
351
|
if (activeAllowance.action === "pause") {
|
|
376
352
|
throw new AccountAllowanceExhaustedError(providerId, activeAllowance.resumeAt);
|
|
377
353
|
}
|
|
378
|
-
|
|
354
|
+
const token = await activeGetter();
|
|
355
|
+
if (hasUsableToken(token)) {
|
|
356
|
+
maybeTouchLastUsed(selector, tokens, providerId, activeAccountId);
|
|
357
|
+
report?.(activeAccountId, true, remapFor(activeAccountId));
|
|
358
|
+
}
|
|
359
|
+
return token;
|
|
379
360
|
}
|
|
380
361
|
return activeGetter();
|
|
381
362
|
}
|
package/dist/oauth.cjs
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkUXUMAXZJcjs = require('./chunk-UXUMAXZJ.cjs');
|
|
6
|
+
require('./chunk-75ZPJI57.cjs');
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
exports.claudeOAuth =
|
|
11
|
+
exports.claudeOAuth = _chunkUXUMAXZJcjs.claude_exports; exports.codexOAuth = _chunkUXUMAXZJcjs.codex_exports; exports.geminiOAuth = _chunkUXUMAXZJcjs.gemini_exports;
|
package/dist/oauth.js
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunk6TTHLCG6cjs = require('../chunk-6TTHLCG6.cjs');
|
|
6
|
+
require('../chunk-75ZPJI57.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
exports.accountSupportsModel = _chunk6TTHLCG6cjs.accountSupportsModel; exports.remapForAccount = _chunk6TTHLCG6cjs.remapForAccount; exports.remapReportForAccount = _chunk6TTHLCG6cjs.remapReportForAccount;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* accountModelMap — pure helpers for the per-account `supportedModels` field
|
|
3
|
+
* (subscription-account-model-map, design D1).
|
|
4
|
+
*
|
|
5
|
+
* Dual-format `SubscriptionAccountEntry.supportedModels`:
|
|
6
|
+
* - **array** — an ALLOW-LIST of supported logical models; no remap.
|
|
7
|
+
* - **object** — the KEYS are the same allow-list AND each VALUE is the
|
|
8
|
+
* account's ACTUAL upstream model (a logical→actual remap).
|
|
9
|
+
* - **absent** — supports every model, no remap (zero regression).
|
|
10
|
+
*
|
|
11
|
+
* Both helpers are pure. They fold into the EXISTING `accountSelection`
|
|
12
|
+
* eligibility path (`accountSupportsModel` → `gateSchedulable`) and the outbound
|
|
13
|
+
* body-model finalize point (`remapForAccount`); they add no new mechanism.
|
|
14
|
+
*
|
|
15
|
+
* Model ids are compared on ONE canonical form — the bare, trimmed, lower-cased
|
|
16
|
+
* id (a `"providerId,modelId"` ref reduces to its `modelId`) — identical to the
|
|
17
|
+
* key-model restriction's `canonicalModelId` (#6), so membership is case- and
|
|
18
|
+
* ref-shape-insensitive and an alias cannot slip past.
|
|
19
|
+
*
|
|
20
|
+
* @module scheduler/accountModelMap
|
|
21
|
+
*/
|
|
22
|
+
/** The `supportedModels` value shape (mirrors the contract field). */
|
|
23
|
+
type SupportedModels = string[] | Record<string, string>;
|
|
24
|
+
/**
|
|
25
|
+
* Whether an account with this `supportedModels` supports the resolved model.
|
|
26
|
+
* - absent ⇒ `true` (supports everything — zero regression).
|
|
27
|
+
* - array ⇒ case-insensitive membership.
|
|
28
|
+
* - object ⇒ the model is one of the KEYS (the keys are the allow-list).
|
|
29
|
+
*/
|
|
30
|
+
declare function accountSupportsModel(supportedModels: SupportedModels | undefined, model: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The ACTUAL upstream model this account serves the logical model as. Only the
|
|
33
|
+
* OBJECT form remaps: when a key matches the resolved model its value is
|
|
34
|
+
* returned; an array form, an absent map, or a missing key ⇒ the model unchanged.
|
|
35
|
+
*/
|
|
36
|
+
declare function remapForAccount(supportedModels: SupportedModels | undefined, model: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* The remapped model to REPORT to the relay, or `undefined` when there is no
|
|
39
|
+
* actual change (array form / absent / no matching key / a remap equal to the
|
|
40
|
+
* resolved model). Returning `undefined` on a no-op keeps the outbound body
|
|
41
|
+
* byte-identical on the same-format path (the relay only rewrites `body.model`
|
|
42
|
+
* when a value is present).
|
|
43
|
+
*/
|
|
44
|
+
declare function remapReportForAccount(supportedModels: SupportedModels | undefined, model: string | undefined): string | undefined;
|
|
45
|
+
|
|
46
|
+
export { type SupportedModels, accountSupportsModel, remapForAccount, remapReportForAccount };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* accountModelMap — pure helpers for the per-account `supportedModels` field
|
|
3
|
+
* (subscription-account-model-map, design D1).
|
|
4
|
+
*
|
|
5
|
+
* Dual-format `SubscriptionAccountEntry.supportedModels`:
|
|
6
|
+
* - **array** — an ALLOW-LIST of supported logical models; no remap.
|
|
7
|
+
* - **object** — the KEYS are the same allow-list AND each VALUE is the
|
|
8
|
+
* account's ACTUAL upstream model (a logical→actual remap).
|
|
9
|
+
* - **absent** — supports every model, no remap (zero regression).
|
|
10
|
+
*
|
|
11
|
+
* Both helpers are pure. They fold into the EXISTING `accountSelection`
|
|
12
|
+
* eligibility path (`accountSupportsModel` → `gateSchedulable`) and the outbound
|
|
13
|
+
* body-model finalize point (`remapForAccount`); they add no new mechanism.
|
|
14
|
+
*
|
|
15
|
+
* Model ids are compared on ONE canonical form — the bare, trimmed, lower-cased
|
|
16
|
+
* id (a `"providerId,modelId"` ref reduces to its `modelId`) — identical to the
|
|
17
|
+
* key-model restriction's `canonicalModelId` (#6), so membership is case- and
|
|
18
|
+
* ref-shape-insensitive and an alias cannot slip past.
|
|
19
|
+
*
|
|
20
|
+
* @module scheduler/accountModelMap
|
|
21
|
+
*/
|
|
22
|
+
/** The `supportedModels` value shape (mirrors the contract field). */
|
|
23
|
+
type SupportedModels = string[] | Record<string, string>;
|
|
24
|
+
/**
|
|
25
|
+
* Whether an account with this `supportedModels` supports the resolved model.
|
|
26
|
+
* - absent ⇒ `true` (supports everything — zero regression).
|
|
27
|
+
* - array ⇒ case-insensitive membership.
|
|
28
|
+
* - object ⇒ the model is one of the KEYS (the keys are the allow-list).
|
|
29
|
+
*/
|
|
30
|
+
declare function accountSupportsModel(supportedModels: SupportedModels | undefined, model: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The ACTUAL upstream model this account serves the logical model as. Only the
|
|
33
|
+
* OBJECT form remaps: when a key matches the resolved model its value is
|
|
34
|
+
* returned; an array form, an absent map, or a missing key ⇒ the model unchanged.
|
|
35
|
+
*/
|
|
36
|
+
declare function remapForAccount(supportedModels: SupportedModels | undefined, model: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* The remapped model to REPORT to the relay, or `undefined` when there is no
|
|
39
|
+
* actual change (array form / absent / no matching key / a remap equal to the
|
|
40
|
+
* resolved model). Returning `undefined` on a no-op keeps the outbound body
|
|
41
|
+
* byte-identical on the same-format path (the relay only rewrites `body.model`
|
|
42
|
+
* when a value is present).
|
|
43
|
+
*/
|
|
44
|
+
declare function remapReportForAccount(supportedModels: SupportedModels | undefined, model: string | undefined): string | undefined;
|
|
45
|
+
|
|
46
|
+
export { type SupportedModels, accountSupportsModel, remapForAccount, remapReportForAccount };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omnicross/subscriptions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Omnicross subscription-as-provider auth strategies, OAuth flows, and the OpenCodeGo scenario dispatcher.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sayo (https://github.com/Dumoedss)",
|