@ottocode/ai-sdk 0.1.4 → 0.1.5
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/package.json +2 -2
- package/src/auth.ts +64 -28
- package/src/balance.ts +104 -90
- package/src/cache.ts +154 -132
- package/src/catalog.ts +1242 -1487
- package/src/fetch.ts +275 -254
- package/src/index.ts +19 -17
- package/src/payment.ts +176 -136
- package/src/providers/factory.ts +53 -53
- package/src/providers/registry.ts +59 -94
- package/src/setu.ts +119 -75
- package/src/types.ts +98 -78
- package/src/wallet.ts +20 -20
package/src/payment.ts
CHANGED
|
@@ -1,171 +1,211 @@
|
|
|
1
|
-
import { Buffer } from 'node:buffer';
|
|
2
1
|
import bs58 from 'bs58';
|
|
3
2
|
import { createPaymentHeader } from 'x402/client';
|
|
4
3
|
import { svm } from 'x402/shared';
|
|
5
4
|
import type { PaymentRequirements } from 'x402/types';
|
|
6
5
|
import type { WalletContext } from './auth.ts';
|
|
7
6
|
import type {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
ExactPaymentRequirement,
|
|
8
|
+
PaymentPayload,
|
|
9
|
+
PaymentCallbacks,
|
|
10
|
+
LegacySigner,
|
|
11
11
|
} from './types.ts';
|
|
12
|
-
import { buildWalletHeaders } from './auth.ts';
|
|
13
12
|
|
|
14
13
|
function simplifyPaymentError(errMsg: string): string {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
const lower = errMsg.toLowerCase();
|
|
15
|
+
if (
|
|
16
|
+
lower.includes('insufficient') ||
|
|
17
|
+
lower.includes('not enough') ||
|
|
18
|
+
lower.includes('balance')
|
|
19
|
+
)
|
|
20
|
+
return 'Insufficient USDC balance';
|
|
21
|
+
if (lower.includes('simulation') || lower.includes('compute unit'))
|
|
22
|
+
return 'Transaction simulation failed';
|
|
23
|
+
if (lower.includes('blockhash') || lower.includes('expired'))
|
|
24
|
+
return 'Transaction expired, please retry';
|
|
25
|
+
if (lower.includes('timeout') || lower.includes('timed out'))
|
|
26
|
+
return 'Transaction timed out';
|
|
27
|
+
if (lower.includes('rejected') || lower.includes('cancelled'))
|
|
28
|
+
return 'Transaction rejected';
|
|
29
|
+
if (lower.includes('network') || lower.includes('connection'))
|
|
30
|
+
return 'Network error';
|
|
31
|
+
const short = (errMsg.split('.')[0] ?? errMsg).slice(0, 80);
|
|
32
|
+
return short.length < errMsg.length ? `${short}...` : errMsg;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
export function pickPaymentRequirement(
|
|
33
|
-
|
|
36
|
+
payload: unknown,
|
|
34
37
|
): ExactPaymentRequirement | null {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
const acceptsValue =
|
|
39
|
+
typeof payload === 'object' && payload !== null
|
|
40
|
+
? (payload as { accepts?: unknown }).accepts
|
|
41
|
+
: undefined;
|
|
42
|
+
const accepts = Array.isArray(acceptsValue)
|
|
43
|
+
? (acceptsValue as ExactPaymentRequirement[])
|
|
44
|
+
: [];
|
|
45
|
+
return accepts.find((opt) => opt && opt.scheme === 'exact') ?? null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isLegacySigner(signer: unknown): signer is LegacySigner {
|
|
49
|
+
return (
|
|
50
|
+
typeof signer === 'object' &&
|
|
51
|
+
signer !== null &&
|
|
52
|
+
'secretKey' in signer &&
|
|
53
|
+
signer.secretKey instanceof Uint8Array &&
|
|
54
|
+
'publicKey' in signer &&
|
|
55
|
+
typeof (signer as LegacySigner).publicKey?.toBase58 === 'function'
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function resolvePaymentSigner(wallet: WalletContext) {
|
|
60
|
+
if (wallet.transactionSigner) {
|
|
61
|
+
if (isLegacySigner(wallet.transactionSigner)) {
|
|
62
|
+
const privateKeyBase58 = bs58.encode(wallet.transactionSigner.secretKey);
|
|
63
|
+
return svm.createSignerFromBase58(privateKeyBase58);
|
|
64
|
+
}
|
|
65
|
+
return wallet.transactionSigner as Exclude<
|
|
66
|
+
typeof wallet.transactionSigner,
|
|
67
|
+
LegacySigner
|
|
68
|
+
>;
|
|
69
|
+
}
|
|
70
|
+
if (wallet.keypair) {
|
|
71
|
+
const privateKeyBase58 = bs58.encode(wallet.keypair.secretKey);
|
|
72
|
+
return svm.createSignerFromBase58(privateKeyBase58);
|
|
73
|
+
}
|
|
74
|
+
throw new Error(
|
|
75
|
+
'Setu: payments require either a privateKey or signer.signTransaction.',
|
|
76
|
+
);
|
|
43
77
|
}
|
|
44
78
|
|
|
45
79
|
export async function createPaymentPayload(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
80
|
+
requirement: ExactPaymentRequirement,
|
|
81
|
+
wallet: WalletContext,
|
|
82
|
+
rpcURL: string,
|
|
49
83
|
): Promise<PaymentPayload> {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
) as { payload: { transaction: string } };
|
|
84
|
+
const signer = await resolvePaymentSigner(wallet);
|
|
85
|
+
const header = await createPaymentHeader(
|
|
86
|
+
signer,
|
|
87
|
+
1,
|
|
88
|
+
requirement as PaymentRequirements,
|
|
89
|
+
{ svmConfig: { rpcUrl: rpcURL } },
|
|
90
|
+
);
|
|
91
|
+
const decoded = JSON.parse(atob(header)) as {
|
|
92
|
+
payload: { transaction: string };
|
|
93
|
+
};
|
|
61
94
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
95
|
+
return {
|
|
96
|
+
x402Version: 1,
|
|
97
|
+
scheme: 'exact',
|
|
98
|
+
network: requirement.network,
|
|
99
|
+
payload: { transaction: decoded.payload.transaction },
|
|
100
|
+
};
|
|
68
101
|
}
|
|
69
102
|
|
|
70
103
|
interface PaymentResponse {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
104
|
+
amount_usd?: number | string;
|
|
105
|
+
new_balance?: number | string;
|
|
106
|
+
amount?: number;
|
|
107
|
+
balance?: number;
|
|
108
|
+
transaction?: string;
|
|
76
109
|
}
|
|
77
110
|
|
|
78
111
|
export async function processSinglePayment(args: {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
112
|
+
requirement: ExactPaymentRequirement;
|
|
113
|
+
wallet: WalletContext;
|
|
114
|
+
rpcURL: string;
|
|
115
|
+
baseURL: string;
|
|
116
|
+
baseFetch: typeof fetch;
|
|
117
|
+
callbacks: PaymentCallbacks;
|
|
85
118
|
}): Promise<{ attempts: number; balance?: number | string }> {
|
|
86
|
-
|
|
119
|
+
args.callbacks.onPaymentSigning?.();
|
|
87
120
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
121
|
+
let paymentPayload: PaymentPayload;
|
|
122
|
+
try {
|
|
123
|
+
paymentPayload = await createPaymentPayload(
|
|
124
|
+
args.requirement,
|
|
125
|
+
args.wallet,
|
|
126
|
+
args.rpcURL,
|
|
127
|
+
);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
130
|
+
const userMsg = `Payment failed: ${simplifyPaymentError(errMsg)}`;
|
|
131
|
+
args.callbacks.onPaymentError?.(userMsg);
|
|
132
|
+
throw new Error(`Setu: ${userMsg}`);
|
|
133
|
+
}
|
|
101
134
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
135
|
+
const walletHeaders = await args.wallet.buildHeaders();
|
|
136
|
+
const response = await args.baseFetch(`${args.baseURL}/v1/topup`, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: { 'Content-Type': 'application/json', ...walletHeaders },
|
|
139
|
+
body: JSON.stringify({
|
|
140
|
+
paymentPayload,
|
|
141
|
+
paymentRequirement: args.requirement,
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
111
144
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
145
|
+
const rawBody = await response.text().catch(() => '');
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
if (
|
|
148
|
+
response.status === 400 &&
|
|
149
|
+
rawBody.toLowerCase().includes('already processed')
|
|
150
|
+
) {
|
|
151
|
+
return { attempts: 1 };
|
|
152
|
+
}
|
|
153
|
+
args.callbacks.onPaymentError?.(`Topup failed: ${response.status}`);
|
|
154
|
+
throw new Error(`Setu topup failed (${response.status}): ${rawBody}`);
|
|
155
|
+
}
|
|
120
156
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
157
|
+
let parsed: PaymentResponse | undefined;
|
|
158
|
+
try {
|
|
159
|
+
parsed = rawBody ? (JSON.parse(rawBody) as PaymentResponse) : undefined;
|
|
160
|
+
} catch {
|
|
161
|
+
parsed = undefined;
|
|
162
|
+
}
|
|
127
163
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
164
|
+
if (parsed) {
|
|
165
|
+
const amountUsd =
|
|
166
|
+
typeof parsed.amount_usd === 'string'
|
|
167
|
+
? parseFloat(parsed.amount_usd)
|
|
168
|
+
: (parsed.amount_usd ?? parsed.amount ?? 0);
|
|
169
|
+
const newBalance =
|
|
170
|
+
typeof parsed.new_balance === 'string'
|
|
171
|
+
? parseFloat(parsed.new_balance)
|
|
172
|
+
: (parsed.new_balance ?? parsed.balance ?? 0);
|
|
173
|
+
args.callbacks.onPaymentComplete?.({
|
|
174
|
+
amountUsd,
|
|
175
|
+
newBalance,
|
|
176
|
+
transactionId: parsed.transaction,
|
|
177
|
+
});
|
|
178
|
+
return { attempts: 1, balance: newBalance };
|
|
179
|
+
}
|
|
180
|
+
return { attempts: 1 };
|
|
145
181
|
}
|
|
146
182
|
|
|
147
183
|
export async function handlePayment(args: {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
184
|
+
requirement: ExactPaymentRequirement;
|
|
185
|
+
wallet: WalletContext;
|
|
186
|
+
rpcURL: string;
|
|
187
|
+
baseURL: string;
|
|
188
|
+
baseFetch: typeof fetch;
|
|
189
|
+
maxAttempts: number;
|
|
190
|
+
callbacks: PaymentCallbacks;
|
|
155
191
|
}): Promise<{ attemptsUsed: number }> {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
192
|
+
let attempts = 0;
|
|
193
|
+
while (attempts < args.maxAttempts) {
|
|
194
|
+
const result = await processSinglePayment(args);
|
|
195
|
+
attempts += result.attempts;
|
|
196
|
+
const balanceValue =
|
|
197
|
+
typeof result.balance === 'number'
|
|
198
|
+
? result.balance
|
|
199
|
+
: result.balance != null
|
|
200
|
+
? Number(result.balance)
|
|
201
|
+
: undefined;
|
|
202
|
+
if (
|
|
203
|
+
balanceValue == null ||
|
|
204
|
+
Number.isNaN(balanceValue) ||
|
|
205
|
+
balanceValue >= 0
|
|
206
|
+
) {
|
|
207
|
+
return { attemptsUsed: attempts };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
throw new Error(`Setu: payment failed after ${attempts} additional top-ups.`);
|
|
171
211
|
}
|
package/src/providers/factory.ts
CHANGED
|
@@ -7,64 +7,64 @@ import type { LanguageModelV3Middleware } from '@ai-sdk/provider';
|
|
|
7
7
|
import type { ProviderApiFormat, ProviderId, FetchFunction } from '../types.ts';
|
|
8
8
|
|
|
9
9
|
export function createModel(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
modelId: string,
|
|
11
|
+
apiFormat: ProviderApiFormat,
|
|
12
|
+
providerId: ProviderId,
|
|
13
|
+
baseURL: string,
|
|
14
|
+
customFetch: FetchFunction,
|
|
15
|
+
middleware?: LanguageModelV3Middleware | LanguageModelV3Middleware[],
|
|
16
16
|
) {
|
|
17
|
-
|
|
17
|
+
const fetchFn = customFetch as unknown as typeof globalThis.fetch;
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
let model:
|
|
20
|
+
| ReturnType<ReturnType<typeof createOpenAI>['responses']>
|
|
21
|
+
| ReturnType<ReturnType<typeof createAnthropic>>;
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
switch (apiFormat) {
|
|
24
|
+
case 'anthropic-messages': {
|
|
25
|
+
const provider = createAnthropic({
|
|
26
|
+
baseURL,
|
|
27
|
+
apiKey: 'setu-wallet-auth',
|
|
28
|
+
fetch: fetchFn,
|
|
29
|
+
});
|
|
30
|
+
model = provider(modelId);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
case 'google-native': {
|
|
35
|
+
const provider = createGoogleGenerativeAI({
|
|
36
|
+
baseURL,
|
|
37
|
+
apiKey: 'setu-wallet-auth',
|
|
38
|
+
fetch: fetchFn,
|
|
39
|
+
});
|
|
40
|
+
model = provider(modelId);
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
case 'openai-chat': {
|
|
45
|
+
const provider = createOpenAICompatible({
|
|
46
|
+
name: `setu-${providerId}`,
|
|
47
|
+
baseURL,
|
|
48
|
+
headers: { Authorization: 'Bearer setu-wallet-auth' },
|
|
49
|
+
fetch: fetchFn,
|
|
50
|
+
});
|
|
51
|
+
model = provider(modelId);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
default: {
|
|
55
|
+
const provider = createOpenAI({
|
|
56
|
+
baseURL,
|
|
57
|
+
apiKey: 'setu-wallet-auth',
|
|
58
|
+
fetch: fetchFn,
|
|
59
|
+
});
|
|
60
|
+
model = provider.responses(modelId);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
52
64
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
baseURL,
|
|
57
|
-
apiKey: 'setu-wallet-auth',
|
|
58
|
-
fetch: fetchFn,
|
|
59
|
-
});
|
|
60
|
-
model = provider.responses(modelId);
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
65
|
+
if (middleware) {
|
|
66
|
+
return wrapLanguageModel({ model, middleware });
|
|
67
|
+
}
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
return wrapLanguageModel({ model, middleware });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return model;
|
|
69
|
+
return model;
|
|
70
70
|
}
|
|
@@ -1,105 +1,70 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ProviderId,
|
|
3
|
+
ProviderConfig,
|
|
4
|
+
ProviderApiFormat,
|
|
5
|
+
} from '../types.ts';
|
|
6
|
+
import { setuCatalog } from '../catalog.ts';
|
|
2
7
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
apiFormat: 'openai-responses',
|
|
12
|
-
modelPrefix: 'o1',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
id: 'openai',
|
|
16
|
-
apiFormat: 'openai-responses',
|
|
17
|
-
modelPrefix: 'o3',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
id: 'openai',
|
|
21
|
-
apiFormat: 'openai-responses',
|
|
22
|
-
modelPrefix: 'o4',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'openai',
|
|
26
|
-
apiFormat: 'openai-responses',
|
|
27
|
-
modelPrefix: 'codex-',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
id: 'anthropic',
|
|
31
|
-
apiFormat: 'anthropic-messages',
|
|
32
|
-
modelPrefix: 'claude-',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
id: 'google',
|
|
36
|
-
apiFormat: 'google-native',
|
|
37
|
-
modelPrefix: 'gemini-',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
id: 'moonshot',
|
|
41
|
-
apiFormat: 'openai-chat',
|
|
42
|
-
modelPrefix: 'kimi-',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
id: 'minimax',
|
|
46
|
-
apiFormat: 'anthropic-messages',
|
|
47
|
-
modelPrefix: 'MiniMax-',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
id: 'zai',
|
|
51
|
-
apiFormat: 'openai-chat',
|
|
52
|
-
modelPrefix: 'glm-',
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
id: 'zai',
|
|
56
|
-
apiFormat: 'openai-chat',
|
|
57
|
-
modelPrefix: 'z1-',
|
|
58
|
-
},
|
|
59
|
-
];
|
|
8
|
+
const OWNER_API_FORMAT: Record<string, ProviderApiFormat> = {
|
|
9
|
+
openai: 'openai-responses',
|
|
10
|
+
anthropic: 'anthropic-messages',
|
|
11
|
+
google: 'google-native',
|
|
12
|
+
minimax: 'anthropic-messages',
|
|
13
|
+
moonshot: 'openai-chat',
|
|
14
|
+
zai: 'openai-chat',
|
|
15
|
+
};
|
|
60
16
|
|
|
61
17
|
export class ProviderRegistry {
|
|
62
|
-
|
|
63
|
-
|
|
18
|
+
private configs: ProviderConfig[];
|
|
19
|
+
private modelMap: Record<string, ProviderId>;
|
|
64
20
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
21
|
+
constructor(
|
|
22
|
+
customProviders?: ProviderConfig[],
|
|
23
|
+
modelMap?: Record<string, ProviderId>,
|
|
24
|
+
) {
|
|
25
|
+
this.configs = [...(customProviders ?? [])];
|
|
26
|
+
this.modelMap = modelMap ?? {};
|
|
27
|
+
}
|
|
72
28
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
29
|
+
resolve(
|
|
30
|
+
modelId: string,
|
|
31
|
+
): { providerId: ProviderId; apiFormat: ProviderApiFormat } | null {
|
|
32
|
+
if (this.modelMap[modelId]) {
|
|
33
|
+
const providerId = this.modelMap[modelId];
|
|
34
|
+
const config = this.configs.find((c) => c.id === providerId);
|
|
35
|
+
return {
|
|
36
|
+
providerId,
|
|
37
|
+
apiFormat: config?.apiFormat ?? 'openai-chat',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
82
40
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
41
|
+
for (const config of this.configs) {
|
|
42
|
+
if (config.models?.includes(modelId)) {
|
|
43
|
+
return { providerId: config.id, apiFormat: config.apiFormat };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
88
46
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
47
|
+
for (const config of this.configs) {
|
|
48
|
+
if (config.modelPrefix && modelId.startsWith(config.modelPrefix)) {
|
|
49
|
+
return { providerId: config.id, apiFormat: config.apiFormat };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
94
52
|
|
|
95
|
-
|
|
96
|
-
|
|
53
|
+
const entry = setuCatalog.models.find((m) => m.id === modelId);
|
|
54
|
+
if (entry) {
|
|
55
|
+
const providerId = entry.owned_by as ProviderId;
|
|
56
|
+
const apiFormat = OWNER_API_FORMAT[providerId] ?? 'openai-chat';
|
|
57
|
+
return { providerId, apiFormat };
|
|
58
|
+
}
|
|
97
59
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
101
62
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
63
|
+
register(config: ProviderConfig): void {
|
|
64
|
+
this.configs.push(config);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
mapModel(modelId: string, providerId: ProviderId): void {
|
|
68
|
+
this.modelMap[modelId] = providerId;
|
|
69
|
+
}
|
|
105
70
|
}
|