@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/setu.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
SetuConfig,
|
|
3
|
+
ProviderId,
|
|
4
|
+
ProviderApiFormat,
|
|
5
|
+
FetchFunction,
|
|
6
|
+
BalanceResponse,
|
|
7
|
+
WalletUsdcBalance,
|
|
8
|
+
SetuAuth,
|
|
9
|
+
} from './types.ts';
|
|
10
|
+
import { createWalletContext } from './auth.ts';
|
|
11
|
+
import type { WalletContext } from './auth.ts';
|
|
3
12
|
import { createSetuFetch } from './fetch.ts';
|
|
4
13
|
import { ProviderRegistry } from './providers/registry.ts';
|
|
5
14
|
import { createModel } from './providers/factory.ts';
|
|
@@ -8,86 +17,121 @@ import { fetchBalance, fetchWalletUsdcBalance } from './balance.ts';
|
|
|
8
17
|
const DEFAULT_BASE_URL = 'https://api.setu.ottocode.io';
|
|
9
18
|
|
|
10
19
|
function trimTrailingSlash(url: string) {
|
|
11
|
-
|
|
20
|
+
return url.endsWith('/') ? url.slice(0, -1) : url;
|
|
12
21
|
}
|
|
13
22
|
|
|
14
23
|
export interface SetuProvider {
|
|
15
|
-
|
|
24
|
+
model(modelId: string): ReturnType<typeof createModel>;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
export interface SetuInstance {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
model(modelId: string): ReturnType<typeof createModel>;
|
|
29
|
+
provider(providerId: ProviderId, apiFormat?: ProviderApiFormat): SetuProvider;
|
|
30
|
+
fetch(): FetchFunction;
|
|
31
|
+
balance(): Promise<BalanceResponse | null>;
|
|
32
|
+
walletBalance(
|
|
33
|
+
network?: 'mainnet' | 'devnet',
|
|
34
|
+
): Promise<WalletUsdcBalance | null>;
|
|
35
|
+
walletAddress: string | null;
|
|
36
|
+
registry: ProviderRegistry;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function resolveAuth(auth: SetuAuth): {
|
|
40
|
+
auth: SetuAuth;
|
|
41
|
+
wallet: WalletContext;
|
|
42
|
+
} {
|
|
43
|
+
if (auth.signer) {
|
|
44
|
+
return { auth, wallet: createWalletContext(auth) };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const privateKey = auth.privateKey || process.env.SETU_PRIVATE_KEY;
|
|
48
|
+
if (!privateKey) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
'Setu: either privateKey (or SETU_PRIVATE_KEY env) or signer is required.',
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const resolvedAuth = { ...auth, privateKey };
|
|
54
|
+
return { auth: resolvedAuth, wallet: createWalletContext(resolvedAuth) };
|
|
26
55
|
}
|
|
27
56
|
|
|
28
57
|
export function createSetu(config: SetuConfig): SetuInstance {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
58
|
+
const baseURL = trimTrailingSlash(config.baseURL ?? DEFAULT_BASE_URL);
|
|
59
|
+
const { auth: resolvedAuth, wallet } = resolveAuth(config.auth);
|
|
60
|
+
const registry = new ProviderRegistry(config.providers, config.modelMap);
|
|
61
|
+
|
|
62
|
+
const setuFetch = createSetuFetch({
|
|
63
|
+
wallet,
|
|
64
|
+
baseURL,
|
|
65
|
+
rpcURL: config.rpcURL,
|
|
66
|
+
callbacks: config.callbacks,
|
|
67
|
+
cache: config.cache,
|
|
68
|
+
payment: config.payment,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const modelBaseURL = `${baseURL}/v1`;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
model(modelId: string) {
|
|
75
|
+
const resolved = registry.resolve(modelId);
|
|
76
|
+
if (!resolved) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Setu: unknown model "${modelId}". Register it via providers or modelMap config.`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return createModel(
|
|
82
|
+
modelId,
|
|
83
|
+
resolved.apiFormat,
|
|
84
|
+
resolved.providerId,
|
|
85
|
+
modelBaseURL,
|
|
86
|
+
setuFetch,
|
|
87
|
+
config.middleware,
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
provider(
|
|
92
|
+
providerId: ProviderId,
|
|
93
|
+
apiFormat?: ProviderApiFormat,
|
|
94
|
+
): SetuProvider {
|
|
95
|
+
return {
|
|
96
|
+
model(modelId: string) {
|
|
97
|
+
const resolved = registry.resolve(modelId);
|
|
98
|
+
const format = apiFormat ?? resolved?.apiFormat ?? 'openai-chat';
|
|
99
|
+
return createModel(
|
|
100
|
+
modelId,
|
|
101
|
+
format,
|
|
102
|
+
providerId,
|
|
103
|
+
modelBaseURL,
|
|
104
|
+
setuFetch,
|
|
105
|
+
config.middleware,
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
fetch(): FetchFunction {
|
|
112
|
+
return setuFetch;
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
async balance() {
|
|
116
|
+
return fetchBalance(wallet, baseURL);
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
async walletBalance(network?: 'mainnet' | 'devnet') {
|
|
120
|
+
const walletAddr = wallet.walletAddress;
|
|
121
|
+
if (!resolvedAuth.privateKey && !walletAddr) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
if (resolvedAuth.privateKey) {
|
|
125
|
+
return fetchWalletUsdcBalance(
|
|
126
|
+
resolvedAuth as Required<Pick<SetuAuth, 'privateKey'>>,
|
|
127
|
+
network,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return fetchWalletUsdcBalance({ walletAddress: walletAddr }, network);
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
walletAddress: wallet.walletAddress,
|
|
134
|
+
|
|
135
|
+
registry,
|
|
136
|
+
};
|
|
93
137
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,50 +1,70 @@
|
|
|
1
1
|
import type { LanguageModelV3Middleware } from '@ai-sdk/provider';
|
|
2
|
+
import type { TransactionSigner } from '@solana/kit';
|
|
2
3
|
|
|
3
4
|
export type ProviderId =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
| 'openai'
|
|
6
|
+
| 'anthropic'
|
|
7
|
+
| 'google'
|
|
8
|
+
| 'moonshot'
|
|
9
|
+
| 'zai'
|
|
10
|
+
| 'minimax'
|
|
11
|
+
| (string & {});
|
|
12
|
+
|
|
13
|
+
export type ProviderApiFormat =
|
|
14
|
+
| 'openai-responses'
|
|
15
|
+
| 'anthropic-messages'
|
|
16
|
+
| 'openai-chat'
|
|
17
|
+
| 'google-native';
|
|
18
|
+
|
|
19
|
+
export type FetchFunction = (
|
|
20
|
+
input: string | URL | Request,
|
|
21
|
+
init?: RequestInit,
|
|
22
|
+
) => Promise<Response>;
|
|
11
23
|
|
|
12
|
-
export
|
|
24
|
+
export interface ProviderConfig {
|
|
25
|
+
id: ProviderId;
|
|
26
|
+
apiFormat: ProviderApiFormat;
|
|
27
|
+
models?: string[];
|
|
28
|
+
modelPrefix?: string;
|
|
29
|
+
}
|
|
13
30
|
|
|
14
|
-
export
|
|
31
|
+
export interface LegacySigner {
|
|
32
|
+
publicKey: { toBase58(): string };
|
|
33
|
+
secretKey: Uint8Array;
|
|
34
|
+
}
|
|
15
35
|
|
|
16
|
-
export interface
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
modelPrefix?: string;
|
|
36
|
+
export interface ExternalSigner {
|
|
37
|
+
walletAddress: string;
|
|
38
|
+
signNonce: (nonce: string) => Promise<string> | string;
|
|
39
|
+
signTransaction?: TransactionSigner | LegacySigner;
|
|
21
40
|
}
|
|
22
41
|
|
|
23
42
|
export interface SetuAuth {
|
|
24
|
-
|
|
43
|
+
privateKey?: string;
|
|
44
|
+
signer?: ExternalSigner;
|
|
25
45
|
}
|
|
26
46
|
|
|
27
47
|
export interface BalanceUpdate {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
48
|
+
costUsd: number;
|
|
49
|
+
balanceRemaining: number;
|
|
50
|
+
inputTokens?: number;
|
|
51
|
+
outputTokens?: number;
|
|
32
52
|
}
|
|
33
53
|
|
|
34
54
|
export interface PaymentCallbacks {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
onPaymentRequired?: (amountUsd: number, currentBalance?: number) => void;
|
|
56
|
+
onPaymentSigning?: () => void;
|
|
57
|
+
onPaymentComplete?: (data: {
|
|
58
|
+
amountUsd: number;
|
|
59
|
+
newBalance: number;
|
|
60
|
+
transactionId?: string;
|
|
61
|
+
}) => void;
|
|
62
|
+
onPaymentError?: (error: string) => void;
|
|
63
|
+
onPaymentApproval?: (info: {
|
|
64
|
+
amountUsd: number;
|
|
65
|
+
currentBalance: number;
|
|
66
|
+
}) => Promise<'crypto' | 'fiat' | 'cancel'>;
|
|
67
|
+
onBalanceUpdate?: (update: BalanceUpdate) => void;
|
|
48
68
|
}
|
|
49
69
|
|
|
50
70
|
export type AnthropicCacheStrategy = 'auto' | 'manual' | 'custom' | false;
|
|
@@ -52,71 +72,71 @@ export type AnthropicCacheStrategy = 'auto' | 'manual' | 'custom' | false;
|
|
|
52
72
|
export type AnthropicCachePlacement = 'first' | 'last' | 'all';
|
|
53
73
|
|
|
54
74
|
export interface AnthropicCacheConfig {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
strategy?: AnthropicCacheStrategy;
|
|
76
|
+
systemBreakpoints?: number;
|
|
77
|
+
messageBreakpoints?: number;
|
|
78
|
+
systemPlacement?: AnthropicCachePlacement;
|
|
79
|
+
messagePlacement?: AnthropicCachePlacement;
|
|
80
|
+
cacheType?: 'ephemeral';
|
|
81
|
+
transform?: (body: Record<string, unknown>) => Record<string, unknown>;
|
|
62
82
|
}
|
|
63
83
|
|
|
64
84
|
export interface CacheOptions {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
85
|
+
promptCacheKey?: string;
|
|
86
|
+
promptCacheRetention?: 'in_memory' | '24h';
|
|
87
|
+
anthropicCaching?: boolean | AnthropicCacheConfig;
|
|
68
88
|
}
|
|
69
89
|
|
|
70
90
|
export interface PaymentOptions {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
topupApprovalMode?: 'auto' | 'approval';
|
|
92
|
+
autoPayThresholdUsd?: number;
|
|
93
|
+
maxRequestAttempts?: number;
|
|
94
|
+
maxPaymentAttempts?: number;
|
|
75
95
|
}
|
|
76
96
|
|
|
77
97
|
export interface SetuConfig {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
auth: SetuAuth;
|
|
99
|
+
baseURL?: string;
|
|
100
|
+
rpcURL?: string;
|
|
101
|
+
providers?: ProviderConfig[];
|
|
102
|
+
modelMap?: Record<string, ProviderId>;
|
|
103
|
+
callbacks?: PaymentCallbacks;
|
|
104
|
+
cache?: CacheOptions;
|
|
105
|
+
payment?: PaymentOptions;
|
|
106
|
+
middleware?: LanguageModelV3Middleware | LanguageModelV3Middleware[];
|
|
87
107
|
}
|
|
88
108
|
|
|
89
109
|
export interface ExactPaymentRequirement {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
110
|
+
scheme: 'exact';
|
|
111
|
+
network: string;
|
|
112
|
+
maxAmountRequired: string;
|
|
113
|
+
asset: string;
|
|
114
|
+
payTo: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
resource?: string;
|
|
117
|
+
extra?: Record<string, unknown>;
|
|
118
|
+
maxTimeoutSeconds?: number;
|
|
99
119
|
}
|
|
100
120
|
|
|
101
121
|
export interface PaymentPayload {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
122
|
+
x402Version: 1;
|
|
123
|
+
scheme: 'exact';
|
|
124
|
+
network: string;
|
|
125
|
+
payload: { transaction: string };
|
|
106
126
|
}
|
|
107
127
|
|
|
108
128
|
export interface BalanceResponse {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
walletAddress: string;
|
|
130
|
+
balance: number;
|
|
131
|
+
totalSpent: number;
|
|
132
|
+
totalTopups: number;
|
|
133
|
+
requestCount: number;
|
|
134
|
+
createdAt?: string;
|
|
135
|
+
lastRequest?: string;
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
export interface WalletUsdcBalance {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
139
|
+
walletAddress: string;
|
|
140
|
+
usdcBalance: number;
|
|
141
|
+
network: 'mainnet' | 'devnet';
|
|
122
142
|
}
|
package/src/wallet.ts
CHANGED
|
@@ -2,33 +2,33 @@ import { Keypair } from '@solana/web3.js';
|
|
|
2
2
|
import bs58 from 'bs58';
|
|
3
3
|
|
|
4
4
|
export interface WalletInfo {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
publicKey: string;
|
|
6
|
+
privateKey: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function generateWallet(): WalletInfo {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const keypair = Keypair.generate();
|
|
11
|
+
return {
|
|
12
|
+
privateKey: bs58.encode(keypair.secretKey),
|
|
13
|
+
publicKey: keypair.publicKey.toBase58(),
|
|
14
|
+
};
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function importWallet(privateKey: string): WalletInfo {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
const privateKeyBytes = bs58.decode(privateKey);
|
|
19
|
+
const keypair = Keypair.fromSecretKey(privateKeyBytes);
|
|
20
|
+
return {
|
|
21
|
+
privateKey,
|
|
22
|
+
publicKey: keypair.publicKey.toBase58(),
|
|
23
|
+
};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function isValidPrivateKey(privateKey: string): boolean {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
try {
|
|
28
|
+
const bytes = bs58.decode(privateKey);
|
|
29
|
+
Keypair.fromSecretKey(bytes);
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
34
|
}
|