@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ottocode/ai-sdk",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts",
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, LegacySigner } from './types.ts';
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
- transactionSigner?: TransactionSigner | LegacySigner;
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
- transactionSigner: signTransaction,
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
- return new Response(response.body.pipeThrough(transform), {
107
- status: response.status,
108
- statusText: response.statusText,
109
- headers: response.headers,
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
@@ -5,7 +5,6 @@ export type {
5
5
  SetuConfig,
6
6
  SetuAuth,
7
7
  ExternalSigner,
8
- LegacySigner,
9
8
  ProviderId,
10
9
  ProviderApiFormat,
11
10
  ProviderConfig,
package/src/payment.ts CHANGED
@@ -7,8 +7,16 @@ import type {
7
7
  ExactPaymentRequirement,
8
8
  PaymentPayload,
9
9
  PaymentCallbacks,
10
- LegacySigner,
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 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
- );
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.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
- >;
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: typeof fetch;
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: typeof fetch;
212
+ baseFetch: FetchFunction;
189
213
  maxAttempts: number;
190
214
  callbacks: PaymentCallbacks;
191
215
  }): Promise<{ attemptsUsed: number }> {
package/src/setu.ts CHANGED
@@ -62,6 +62,7 @@ export function createSetu(config: SetuConfig): SetuInstance {
62
62
  const setuFetch = createSetuFetch({
63
63
  wallet,
64
64
  baseURL,
65
+ fetch: config.fetch,
65
66
  rpcURL: config.rpcURL,
66
67
  callbacks: config.callbacks,
67
68
  cache: config.cache,
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?: TransactionSigner | LegacySigner;
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>;