@ottocode/ai-sdk 0.1.5 → 0.1.7
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 +1 -1
- package/src/auth.ts +3 -4
- package/src/fetch.ts +34 -24
- package/src/index.ts +0 -1
- package/src/payment.ts +45 -21
- package/src/setu.ts +1 -0
- package/src/types.ts +2 -7
package/package.json
CHANGED
package/src/auth.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { Keypair } from '@solana/web3.js';
|
|
2
2
|
import bs58 from 'bs58';
|
|
3
3
|
import nacl from 'tweetnacl';
|
|
4
|
-
import type { SetuAuth
|
|
5
|
-
import type { TransactionSigner } from '@solana/kit';
|
|
4
|
+
import type { SetuAuth } from './types.ts';
|
|
6
5
|
|
|
7
6
|
export interface WalletContext {
|
|
8
7
|
walletAddress: string;
|
|
9
8
|
buildHeaders: () => Promise<Record<string, string>> | Record<string, string>;
|
|
10
9
|
keypair?: Keypair;
|
|
11
10
|
privateKeyBytes?: Uint8Array;
|
|
12
|
-
|
|
11
|
+
signTransaction?: (transaction: Uint8Array) => Promise<Uint8Array>;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
export function createWalletContext(auth: SetuAuth): WalletContext {
|
|
@@ -21,7 +20,7 @@ export function createWalletContext(auth: SetuAuth): WalletContext {
|
|
|
21
20
|
} = auth.signer;
|
|
22
21
|
return {
|
|
23
22
|
walletAddress,
|
|
24
|
-
|
|
23
|
+
signTransaction,
|
|
25
24
|
buildHeaders: async () => {
|
|
26
25
|
const nonce = Date.now().toString();
|
|
27
26
|
const signature = await customSignNonce(nonce);
|
package/src/fetch.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
PaymentOptions,
|
|
5
5
|
CacheOptions,
|
|
6
6
|
BalanceUpdate,
|
|
7
|
+
FetchFunction,
|
|
7
8
|
} from './types.ts';
|
|
8
9
|
import { pickPaymentRequirement, handlePayment } from './payment.ts';
|
|
9
10
|
import { addAnthropicCacheControl } from './cache.ts';
|
|
@@ -80,34 +81,41 @@ function wrapResponseWithBalanceSniffing(
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
if (!response.body) return response;
|
|
84
|
+
if (typeof TransformStream === 'undefined') return response;
|
|
85
|
+
if (typeof response.body.pipeThrough !== 'function') return response;
|
|
83
86
|
|
|
84
87
|
const onBalanceUpdate = callbacks.onBalanceUpdate;
|
|
85
88
|
let partial = '';
|
|
86
89
|
const decoder = new TextDecoder();
|
|
87
|
-
const transform = new TransformStream<Uint8Array, Uint8Array>({
|
|
88
|
-
transform(chunk, controller) {
|
|
89
|
-
controller.enqueue(chunk);
|
|
90
|
-
partial += decoder.decode(chunk, { stream: true });
|
|
91
|
-
let nlIndex = partial.indexOf('\n');
|
|
92
|
-
while (nlIndex !== -1) {
|
|
93
|
-
const line = partial.slice(0, nlIndex);
|
|
94
|
-
partial = partial.slice(nlIndex + 1);
|
|
95
|
-
tryParseSetuComment(line, onBalanceUpdate);
|
|
96
|
-
nlIndex = partial.indexOf('\n');
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
flush() {
|
|
100
|
-
if (partial.trim()) {
|
|
101
|
-
tryParseSetuComment(partial, onBalanceUpdate);
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
90
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
91
|
+
try {
|
|
92
|
+
const transform = new TransformStream<Uint8Array, Uint8Array>({
|
|
93
|
+
transform(chunk, controller) {
|
|
94
|
+
controller.enqueue(chunk);
|
|
95
|
+
partial += decoder.decode(chunk, { stream: true });
|
|
96
|
+
let nlIndex = partial.indexOf('\n');
|
|
97
|
+
while (nlIndex !== -1) {
|
|
98
|
+
const line = partial.slice(0, nlIndex);
|
|
99
|
+
partial = partial.slice(nlIndex + 1);
|
|
100
|
+
tryParseSetuComment(line, onBalanceUpdate);
|
|
101
|
+
nlIndex = partial.indexOf('\n');
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
flush() {
|
|
105
|
+
if (partial.trim()) {
|
|
106
|
+
tryParseSetuComment(partial, onBalanceUpdate);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return new Response(response.body.pipeThrough(transform), {
|
|
112
|
+
status: response.status,
|
|
113
|
+
statusText: response.statusText,
|
|
114
|
+
headers: response.headers,
|
|
115
|
+
});
|
|
116
|
+
} catch {
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
async function getWalletUsdcBalance(
|
|
@@ -154,6 +162,7 @@ async function getWalletUsdcBalance(
|
|
|
154
162
|
export interface CreateSetuFetchOptions {
|
|
155
163
|
wallet: WalletContext;
|
|
156
164
|
baseURL: string;
|
|
165
|
+
fetch?: FetchFunction;
|
|
157
166
|
rpcURL?: string;
|
|
158
167
|
callbacks?: PaymentCallbacks;
|
|
159
168
|
cache?: CacheOptions;
|
|
@@ -164,6 +173,7 @@ export function createSetuFetch(options: CreateSetuFetchOptions) {
|
|
|
164
173
|
const {
|
|
165
174
|
wallet,
|
|
166
175
|
baseURL,
|
|
176
|
+
fetch: customFetch,
|
|
167
177
|
rpcURL = DEFAULT_RPC_URL,
|
|
168
178
|
callbacks = {},
|
|
169
179
|
cache,
|
|
@@ -175,7 +185,7 @@ export function createSetuFetch(options: CreateSetuFetchOptions) {
|
|
|
175
185
|
payment?.maxPaymentAttempts ?? DEFAULT_MAX_PAYMENT_ATTEMPTS;
|
|
176
186
|
const topupApprovalMode = payment?.topupApprovalMode ?? 'auto';
|
|
177
187
|
const autoPayThresholdUsd = payment?.autoPayThresholdUsd ?? 0;
|
|
178
|
-
const baseFetch = globalThis.fetch.bind(globalThis);
|
|
188
|
+
const baseFetch = customFetch ?? globalThis.fetch.bind(globalThis);
|
|
179
189
|
|
|
180
190
|
return async (
|
|
181
191
|
input: Parameters<typeof fetch>[0],
|
package/src/index.ts
CHANGED
package/src/payment.ts
CHANGED
|
@@ -7,8 +7,16 @@ import type {
|
|
|
7
7
|
ExactPaymentRequirement,
|
|
8
8
|
PaymentPayload,
|
|
9
9
|
PaymentCallbacks,
|
|
10
|
-
|
|
10
|
+
FetchFunction,
|
|
11
11
|
} from './types.ts';
|
|
12
|
+
import {
|
|
13
|
+
address,
|
|
14
|
+
getTransactionEncoder,
|
|
15
|
+
getTransactionDecoder,
|
|
16
|
+
type Transaction,
|
|
17
|
+
type TransactionWithLifetime,
|
|
18
|
+
type TransactionWithinSizeLimit,
|
|
19
|
+
} from '@solana/kit';
|
|
12
20
|
|
|
13
21
|
function simplifyPaymentError(errMsg: string): string {
|
|
14
22
|
const lower = errMsg.toLowerCase();
|
|
@@ -45,27 +53,43 @@ export function pickPaymentRequirement(
|
|
|
45
53
|
return accepts.find((opt) => opt && opt.scheme === 'exact') ?? null;
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
function wrapCallbackAsSigner(
|
|
57
|
+
walletAddress: string,
|
|
58
|
+
callback: (transaction: Uint8Array) => Promise<Uint8Array>,
|
|
59
|
+
) {
|
|
60
|
+
const encoder = getTransactionEncoder();
|
|
61
|
+
const decoder = getTransactionDecoder();
|
|
62
|
+
return {
|
|
63
|
+
address: address(walletAddress),
|
|
64
|
+
modifyAndSignTransactions: async (
|
|
65
|
+
transactions: readonly (
|
|
66
|
+
| Transaction
|
|
67
|
+
| (Transaction & TransactionWithLifetime)
|
|
68
|
+
)[],
|
|
69
|
+
): Promise<
|
|
70
|
+
readonly (Transaction &
|
|
71
|
+
TransactionWithinSizeLimit &
|
|
72
|
+
TransactionWithLifetime)[]
|
|
73
|
+
> => {
|
|
74
|
+
const results = [];
|
|
75
|
+
for (const tx of transactions) {
|
|
76
|
+
const bytes = new Uint8Array(encoder.encode(tx));
|
|
77
|
+
const signedBytes = await callback(bytes);
|
|
78
|
+
const signed = decoder.decode(signedBytes);
|
|
79
|
+
results.push(
|
|
80
|
+
signed as Transaction &
|
|
81
|
+
TransactionWithinSizeLimit &
|
|
82
|
+
TransactionWithLifetime,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return results;
|
|
86
|
+
},
|
|
87
|
+
};
|
|
57
88
|
}
|
|
58
89
|
|
|
59
90
|
async function resolvePaymentSigner(wallet: WalletContext) {
|
|
60
|
-
if (wallet.
|
|
61
|
-
|
|
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
|
-
>;
|
|
91
|
+
if (wallet.signTransaction) {
|
|
92
|
+
return wrapCallbackAsSigner(wallet.walletAddress, wallet.signTransaction);
|
|
69
93
|
}
|
|
70
94
|
if (wallet.keypair) {
|
|
71
95
|
const privateKeyBase58 = bs58.encode(wallet.keypair.secretKey);
|
|
@@ -113,7 +137,7 @@ export async function processSinglePayment(args: {
|
|
|
113
137
|
wallet: WalletContext;
|
|
114
138
|
rpcURL: string;
|
|
115
139
|
baseURL: string;
|
|
116
|
-
baseFetch:
|
|
140
|
+
baseFetch: FetchFunction;
|
|
117
141
|
callbacks: PaymentCallbacks;
|
|
118
142
|
}): Promise<{ attempts: number; balance?: number | string }> {
|
|
119
143
|
args.callbacks.onPaymentSigning?.();
|
|
@@ -185,7 +209,7 @@ export async function handlePayment(args: {
|
|
|
185
209
|
wallet: WalletContext;
|
|
186
210
|
rpcURL: string;
|
|
187
211
|
baseURL: string;
|
|
188
|
-
baseFetch:
|
|
212
|
+
baseFetch: FetchFunction;
|
|
189
213
|
maxAttempts: number;
|
|
190
214
|
callbacks: PaymentCallbacks;
|
|
191
215
|
}): Promise<{ attemptsUsed: number }> {
|
package/src/setu.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { LanguageModelV3Middleware } from '@ai-sdk/provider';
|
|
2
|
-
import type { TransactionSigner } from '@solana/kit';
|
|
3
2
|
|
|
4
3
|
export type ProviderId =
|
|
5
4
|
| 'openai'
|
|
@@ -28,15 +27,10 @@ export interface ProviderConfig {
|
|
|
28
27
|
modelPrefix?: string;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
export interface LegacySigner {
|
|
32
|
-
publicKey: { toBase58(): string };
|
|
33
|
-
secretKey: Uint8Array;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
30
|
export interface ExternalSigner {
|
|
37
31
|
walletAddress: string;
|
|
38
32
|
signNonce: (nonce: string) => Promise<string> | string;
|
|
39
|
-
signTransaction?:
|
|
33
|
+
signTransaction?: (transaction: Uint8Array) => Promise<Uint8Array>;
|
|
40
34
|
}
|
|
41
35
|
|
|
42
36
|
export interface SetuAuth {
|
|
@@ -97,6 +91,7 @@ export interface PaymentOptions {
|
|
|
97
91
|
export interface SetuConfig {
|
|
98
92
|
auth: SetuAuth;
|
|
99
93
|
baseURL?: string;
|
|
94
|
+
fetch?: FetchFunction;
|
|
100
95
|
rpcURL?: string;
|
|
101
96
|
providers?: ProviderConfig[];
|
|
102
97
|
modelMap?: Record<string, ProviderId>;
|