@ottocode/ai-sdk 0.1.4 → 0.1.6

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