@circuitorg/agent-sdk 1.2.0 → 1.2.3

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/README.md CHANGED
@@ -13,6 +13,7 @@ A simplified TypeScript SDK for building automated agents to deploy on Circuit.
13
13
  - [🚀 Quick Start](#-quick-start)
14
14
  - [Install the SDK](#install-the-sdk)
15
15
  - [Create Your First Agent](#create-your-first-agent)
16
+ - [Required Asset setup](#required-asset-setup)
16
17
  - [🎯 Core Concepts](#-core-concepts)
17
18
  - [The AgentContext Object](#the-agentcontext-object)
18
19
  - [Run/Stop Function Requirements](#runstop-function-requirements)
@@ -23,6 +24,7 @@ A simplified TypeScript SDK for building automated agents to deploy on Circuit.
23
24
  - [📈 Polymarket Prediction Markets](#-polymarket-prediction-markets)
24
25
  - [Place Market Orders](#place-market-orders)
25
26
  - [Redeem Positions](#redeem-positions)
27
+ - [📊 Transaction History](#-transaction-history)
26
28
  - [🚀 Sign \& Send Transactions](#-sign--send-transactions)
27
29
  - [Ethereum (any EVM chain)](#ethereum-any-evm-chain)
28
30
  - [Solana](#solana)
@@ -65,9 +67,27 @@ Every agent receives a single `AgentContext` object that provides:
65
67
  - `agent.swidge` - Cross-chain swaps and bridges (`.quote()`, `.execute()`)
66
68
  - `agent.signAndSend()` - Execute custom built transactions on any supported chain
67
69
  - `agent.signMessage()` - Sign messages (EVM only)
70
+ - `agent.transactions()` - Get transaction history with asset changes
68
71
 
69
72
  **Important:** `currentPositions` reflects your allocated assets at the **start** of each execution. To avoid failed transactions, you should be tracking intra-run position changes based on transactions the agent makes during the execution. Circuit will provide updated positions on the next execution request.
70
73
 
74
+
75
+ #### Required Asset setup
76
+ > Note: For native tokens, use the following null addresses for solana/ethereum
77
+ ```toml
78
+ // Requiring 1 SOL
79
+ [[requiredAssets]]
80
+ network = "solana"
81
+ address = "11111111111111111111111111111111"
82
+ minimumAmount = "1000000000"
83
+
84
+ // Requiring 1 ETH
85
+ [[requiredAssets]]
86
+ network = "ethereum:<chainId>"
87
+ address = "0x0000000000000000000000000000000000000000"
88
+ minimumAmount = "1000000000000000000"
89
+ ```
90
+
71
91
  ```typescript
72
92
  import { Agent, AgentContext } from "@circuitorg/agent-sdk";
73
93
 
@@ -121,6 +141,7 @@ Every agent function receives a single `AgentContext` object that contains:
121
141
  - `agent.swidge` - Cross-chain swap operations
122
142
  - `agent.signAndSend()` - Sign and broadcast transactions
123
143
  - `agent.signMessage()` - Sign messages on EVM
144
+ - `agent.transactions()` - Get transaction history with asset changes
124
145
 
125
146
  ### Run/Stop Function Requirements
126
147
 
@@ -215,6 +236,8 @@ Built-in Swidge integration for seamless cross-chain token swaps and bridges.
215
236
  ### Get and execute a quote
216
237
  > Note: It is important to always validate quotes before executing. Circuit will always do its best to return a quote, and as of now, will only filter out quotes with price impacts exceeding 100% to ensure maximum flexibility. It is on the agent to makes sure a quote is valid, given its own parameters
217
238
 
239
+ > **Bulk Execution:** `execute()` accepts both single quotes and arrays. Pass an array to execute multiple swaps in parallel: `await agent.swidge.execute([quote1.data, quote2.data])` returns an array of results.
240
+
218
241
  ```typescript
219
242
  async function run(agent: AgentContext): Promise<void> {
220
243
  // 1. Get quote
@@ -224,7 +247,6 @@ async function run(agent: AgentContext): Promise<void> {
224
247
  amount: "1000000000000000", // 0.001 ETH
225
248
  toToken: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
226
249
  slippage: "2.0",
227
- priceImpact: "100.0"
228
250
  });
229
251
 
230
252
  if (!quote.success) {
@@ -306,6 +328,66 @@ async function stop(agent: AgentContext): Promise<void> {
306
328
  }
307
329
  ```
308
330
 
331
+ ## 📊 Transaction History
332
+
333
+ Get a list of asset changes for all confirmed transactions during your session. This is useful for tracking what assets have moved in and out of the agent's wallet.
334
+
335
+ > **Note:** The system needs to index new transactions, so there may be a slight delay between when you execute a transaction and when the resulting asset changes are returned in this method. Make sure you are taking that into consideration if dealing with assets the agent just transacted with.
336
+
337
+ ```typescript
338
+ async function run(agent: AgentContext): Promise<void> {
339
+ // Get all transaction history for this session
340
+ const result = await agent.transactions();
341
+
342
+ if (result.success && result.data) {
343
+ await agent.log(`Found ${result.data.length} asset changes`);
344
+
345
+ // Filter for outgoing transfers
346
+ const outgoing = result.data.filter(
347
+ (change) => change.from === agent.sessionWalletAddress
348
+ );
349
+ await agent.log(`Outgoing transfers: ${outgoing.length}`);
350
+
351
+ // Calculate total USD value (where price data is available)
352
+ const totalUsd = result.data
353
+ .filter((c) => c.tokenUsdPrice)
354
+ .reduce((sum, c) => {
355
+ const amount = parseFloat(c.amount);
356
+ const price = parseFloat(c.tokenUsdPrice!);
357
+ return sum + amount * price;
358
+ }, 0);
359
+ await agent.log(`Total USD value: $${totalUsd.toFixed(2)}`);
360
+
361
+ // View specific transaction details
362
+ for (const change of result.data) {
363
+ await agent.log(`${change.network}: ${change.from} → ${change.to}`);
364
+ await agent.log(` Amount: ${change.amount} ${change.tokenType}`);
365
+ if (change.token) {
366
+ await agent.log(` Token: ${change.token}`);
367
+ }
368
+ await agent.log(` Tx: ${change.transactionHash}`);
369
+ await agent.log(` Time: ${change.timestamp}`);
370
+ }
371
+ } else {
372
+ await agent.log(result.error || "Failed to fetch transactions", { error: true });
373
+ }
374
+ }
375
+ ```
376
+
377
+ **AssetChange Structure:**
378
+
379
+ Each asset change in the response contains:
380
+ - `network` - Network identifier (e.g., `"ethereum:1"`, `"solana"`)
381
+ - `transactionHash` - Transaction hash
382
+ - `from` - Sender address
383
+ - `to` - Recipient address
384
+ - `amount` - Amount transferred (as string to preserve precision)
385
+ - `token` - Token contract address (`null` for native tokens)
386
+ - `tokenId` - Token ID for NFTs (`null` for fungible tokens)
387
+ - `tokenType` - Token type (e.g., `"native"`, `"ERC20"`, `"ERC721"`)
388
+ - `tokenUsdPrice` - Token price in USD at time of transaction (`null` if unavailable)
389
+ - `timestamp` - Transaction timestamp
390
+
309
391
  ## 🚀 Sign & Send Transactions
310
392
 
311
393
  ### Ethereum (any EVM chain)
@@ -0,0 +1 @@
1
+ import{existsSync as t,readFileSync as r}from"fs";import{homedir as o}from"os";import{join as n}from"path";function i(){try{if("undefined"==typeof process)return;const i=o();let c=n(i,".config","circuit","auth.json");if(!t(c)&&(c=n(i,".circuit","auth.json"),!t(c)))return;const f=r(c,"utf-8");return JSON.parse(f)}catch{return}}export{i as loadAuthFromFileSystem};
package/index.d.ts CHANGED
@@ -139,6 +139,137 @@ type SignMessageResponse = {
139
139
  statusText?: string;
140
140
  };
141
141
  };
142
+ /**
143
+ * Asset change representing a token transfer in a confirmed transaction
144
+ */
145
+ type AssetChange = {
146
+ /** Network identifier (e.g., "ethereum:1", "solana") */
147
+ network: string;
148
+ /** Transaction hash */
149
+ transactionHash: string;
150
+ /** Sender address */
151
+ from: string;
152
+ /** Recipient address */
153
+ to: string;
154
+ /** Amount transferred (as string to preserve precision) */
155
+ amount: string;
156
+ /** Token contract address (null for native tokens) */
157
+ token: string | null;
158
+ /** Token ID for NFTs (null for fungible tokens) */
159
+ tokenId: string | null;
160
+ /** Token type (e.g., "native", "ERC20", "ERC721") */
161
+ tokenType: string;
162
+ /** Token price in USD at time of transaction (null if unavailable) */
163
+ tokenUsdPrice: string | null;
164
+ /** Timestamp of the transaction */
165
+ timestamp: string;
166
+ };
167
+ /**
168
+ * Response from transactions() method
169
+ */
170
+ type TransactionsResponse = {
171
+ /** Whether the operation was successful */
172
+ success: boolean;
173
+ /** Array of asset changes (only present on success) */
174
+ data?: AssetChange[];
175
+ /** Error message (only present on failure) */
176
+ error?: string;
177
+ /** Detailed error message (only present on failure) */
178
+ errorMessage?: string;
179
+ /** Detailed error information (only present on failure) */
180
+ errorDetails?: {
181
+ message?: string;
182
+ status?: number;
183
+ };
184
+ };
185
+ /**
186
+ * Current position with optional Polymarket metadata enrichment
187
+ */
188
+ type EnrichedPosition = {
189
+ /** Network identifier (e.g., "ethereum:1", "solana") */
190
+ network: string;
191
+ /** Asset contract address */
192
+ assetAddress: string;
193
+ /** Token ID for NFTs/ERC1155 (null for fungible tokens) */
194
+ tokenId: string | null;
195
+ /** Average unit cost in USD */
196
+ avgUnitCost: string;
197
+ /** Current quantity held (raw amount) */
198
+ currentQty: string;
199
+ /** Optional Polymarket metadata (only present for ERC1155 positions) */
200
+ polymarketMetadata?: {
201
+ /** ERC1155 contract address for the market */
202
+ contractAddress: string;
203
+ /** Token ID for the specific outcome */
204
+ tokenId: string | null;
205
+ /** Token decimals (typically 6) */
206
+ decimals: number;
207
+ /** Unique condition identifier */
208
+ conditionId: string;
209
+ /** Human-readable share count */
210
+ formattedShares: string;
211
+ /** Raw share count in smallest unit */
212
+ shares: string;
213
+ /** Current position value in USD */
214
+ valueUsd: string;
215
+ /** Market question text */
216
+ question: string;
217
+ /** Outcome name (e.g., "Yes", "No") */
218
+ outcome: string;
219
+ /** Current price per share in USD */
220
+ priceUsd: string;
221
+ /** Average purchase price per share in USD */
222
+ averagePriceUsd: string;
223
+ /** Whether position can be redeemed */
224
+ isRedeemable: boolean;
225
+ /** Whether position uses negative risk collateral */
226
+ isNegativeRisk: boolean;
227
+ /** Market image URL */
228
+ imageUrl: string;
229
+ /** Initial position value in USD */
230
+ initialValue: string;
231
+ /** Unrealized profit/loss in USD */
232
+ pnlUsd: string;
233
+ /** Unrealized profit/loss percentage */
234
+ pnlPercent: string;
235
+ /** Realized profit/loss in USD */
236
+ pnlRealizedUsd: string;
237
+ /** Realized profit/loss percentage */
238
+ pnlRealizedPercent: string;
239
+ /** Market end date (ISO 8601 string) */
240
+ endDate: string;
241
+ };
242
+ };
243
+ /**
244
+ * Data returned from getCurrentPositions() method
245
+ */
246
+ type CurrentPositionsData = {
247
+ /** Array of current positions with optional Polymarket metadata */
248
+ positions: EnrichedPosition[];
249
+ /** Whether there are pending transactions that may affect position balances */
250
+ hasPendingTxs: boolean;
251
+ };
252
+ /**
253
+ * Response from getCurrentPositions() method
254
+ *
255
+ * Returns the current live positions for the session with optional Polymarket
256
+ * metadata enrichment for ERC1155 positions.
257
+ */
258
+ type CurrentPositionsResponse = {
259
+ /** Whether the operation was successful */
260
+ success: boolean;
261
+ /** Current positions data (only present on success) */
262
+ data?: CurrentPositionsData;
263
+ /** Error message (only present on failure) */
264
+ error?: string;
265
+ /** Detailed error message (only present on failure) */
266
+ errorMessage?: string;
267
+ /** Detailed error information (only present on failure) */
268
+ errorDetails?: {
269
+ message?: string;
270
+ status?: number;
271
+ };
272
+ };
142
273
 
143
274
  /**
144
275
  * Agent log type definitions for agent communication
@@ -182,6 +313,8 @@ interface SDKConfig {
182
313
  sessionId: number;
183
314
  /** Optional base URL (auto-detected if omitted - internal use only) */
184
315
  baseUrl?: string;
316
+ /** Optional Authorization header from incoming request */
317
+ authorizationHeader?: string;
185
318
  }
186
319
 
187
320
  /**
@@ -477,6 +610,7 @@ declare const SwidgeExecuteResponseWrapperSchema: z.ZodObject<{
477
610
  txs: z.ZodArray<z.ZodString>;
478
611
  }, z.core.$strip>;
479
612
  lastUpdated: z.ZodNumber;
613
+ error: z.ZodOptional<z.ZodString>;
480
614
  }, z.core.$strip>>;
481
615
  error: z.ZodOptional<z.ZodString>;
482
616
  errorMessage: z.ZodOptional<z.ZodString>;
@@ -866,7 +1000,6 @@ declare class AgentSdk {
866
1000
  * fromToken: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDC on Polygon
867
1001
  * toToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
868
1002
  * slippage: "2.0", // 2% slippage for cross-chain (default: 0.5%)
869
- * priceImpact: "1.0" // 1% max price impact (default: 0.5%)
870
1003
  * });
871
1004
  *
872
1005
  * // 🔄 Swap USDC → ETH on same chain (using defaults)
@@ -876,7 +1009,6 @@ declare class AgentSdk {
876
1009
  * amount: "100000000", // $100 USDC (6 decimals)
877
1010
  * fromToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC
878
1011
  * // toToken omitted = native ETH (default behavior)
879
- * // slippage defaults to "0.5", priceImpact defaults to "0.5"
880
1012
  * });
881
1013
  *
882
1014
  * if (quote.success && quote.data) {
@@ -896,6 +1028,10 @@ declare class AgentSdk {
896
1028
  * `sdk.swidge.quote()` and let the magic happen. Signs transactions, broadcasts them,
897
1029
  * and waits for completion.
898
1030
  *
1031
+ * Supports both single and bulk execution:
1032
+ * - Pass a single quote → get a single response
1033
+ * - Pass an array of quotes → get an array of responses
1034
+ *
899
1035
  * ⚠️ **What happens:**
900
1036
  * - Signs transactions using your wallet's policy engine
901
1037
  * - Broadcasts to the blockchain(s)
@@ -904,8 +1040,8 @@ declare class AgentSdk {
904
1040
  *
905
1041
  * 💡 **Pro tip**: The backend handles all the complexity - you just pass the quote!
906
1042
  *
907
- * @param quote Complete quote object from `sdk.swidge.quote()` (the entire `data` field from the quote response)
908
- * @returns SwidgeExecuteResponse with transaction status and details
1043
+ * @param quote Complete quote object(s) from `sdk.swidge.quote()` (the entire `data` field from the quote response)
1044
+ * @returns SwidgeExecuteResponse or array of responses (matching input type) with transaction status and details
909
1045
  * - `success` (boolean): Whether the execution was successful
910
1046
  * - `data` (SwidgeExecuteData | undefined): Execution result containing:
911
1047
  * - `status`: "success" | "failure" | "refund" | "delayed" - Final transaction status
@@ -924,10 +1060,9 @@ declare class AgentSdk {
924
1060
  * amount: "50000000", // $50 USDC
925
1061
  * fromToken: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
926
1062
  * toToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
927
- * slippage: "2.0", // priceImpact defaults to "0.5"
928
1063
  * });
929
1064
  *
930
- * // 2️⃣ Execute the swap
1065
+ * // 2️⃣ Execute the swap (single)
931
1066
  * if (quote.success && quote.data) {
932
1067
  * const result = await sdk.swidge.execute(quote.data);
933
1068
  *
@@ -949,9 +1084,18 @@ declare class AgentSdk {
949
1084
  * console.log(`❌ Execute failed: ${result.error}`);
950
1085
  * }
951
1086
  * }
1087
+ *
1088
+ * // 3️⃣ Bulk execution (multiple quotes)
1089
+ * const results = await sdk.swidge.execute([quote.data, quote.data]);
1090
+ * results.forEach((result, index) => {
1091
+ * console.log(`Swap ${index + 1}: ${result.success ? result.data?.status : result.error}`);
1092
+ * });
952
1093
  * ```
953
1094
  */
954
- execute: (executeQuote: SwidgeExecuteRequest) => Promise<SwidgeExecuteResponse>;
1095
+ execute: {
1096
+ (executeQuote: SwidgeExecuteRequest): Promise<SwidgeExecuteResponse>;
1097
+ (executeQuotes: SwidgeExecuteRequest[]): Promise<SwidgeExecuteResponse[]>;
1098
+ };
955
1099
  };
956
1100
  /**
957
1101
  * 💾 Memory: Session-scoped key-value storage
@@ -1314,7 +1458,7 @@ declare class AgentSdk {
1314
1458
  */
1315
1459
  private handleSwidgeQuote;
1316
1460
  /**
1317
- * Handle swidge execute requests
1461
+ * Handle swidge execute requests (single or bulk)
1318
1462
  */
1319
1463
  private handleSwidgeExecute;
1320
1464
  private handlePolymarketMarketOrder;
@@ -1335,6 +1479,146 @@ declare class AgentSdk {
1335
1479
  * Handle memory list requests
1336
1480
  */
1337
1481
  private handleMemoryList;
1482
+ /**
1483
+ * 📊 Get transaction ledger with asset changes
1484
+ *
1485
+ * Retrieves all confirmed transaction asset changes for the current session.
1486
+ * Returns both EVM and Solana transactions with their asset transfers.
1487
+ *
1488
+ * **Returns**: `TransactionsResponse`
1489
+ * - `success` (boolean): Whether the operation succeeded
1490
+ * - `data` (AssetChange[] | undefined): Array of asset changes on success
1491
+ * - Each `AssetChange` contains:
1492
+ * - `network` (string): Network identifier (e.g., "ethereum:1", "solana")
1493
+ * - `transactionHash` (string): Transaction hash
1494
+ * - `from` (string): Sender address
1495
+ * - `to` (string): Recipient address
1496
+ * - `amount` (string): Amount transferred (as string to preserve precision)
1497
+ * - `token` (string | null): Token contract address (null for native tokens)
1498
+ * - `tokenId` (string | null): Token ID for NFTs (null for fungible tokens)
1499
+ * - `tokenType` (string): Token type (e.g., "native", "ERC20", "ERC721")
1500
+ * - `tokenUsdPrice` (string | null): Token price in USD at time of transaction
1501
+ * - `timestamp` (string): Transaction timestamp
1502
+ * - `error` (string | undefined): Error message on failure
1503
+ * - `errorMessage` (string | undefined): Detailed error message on failure
1504
+ *
1505
+ * @returns Promise resolving to TransactionsResponse with array of asset changes
1506
+ *
1507
+ * @example
1508
+ * ```ts
1509
+ * const result = await sdk.transactions();
1510
+ *
1511
+ * if (result.success && result.data) {
1512
+ * console.log(`Found ${result.data.length} asset changes`);
1513
+ * result.data.forEach(change => {
1514
+ * console.log(`${change.from} → ${change.to}: ${change.amount} (${change.tokenType})`);
1515
+ * console.log(`Token: ${change.token || 'native'}, USD Price: ${change.tokenUsdPrice || 'N/A'}`);
1516
+ * });
1517
+ * }
1518
+ * ```
1519
+ */
1520
+ transactions(): Promise<TransactionsResponse>;
1521
+ /**
1522
+ * 💼 Get current live positions for the session
1523
+ *
1524
+ * Retrieves all current positions held by the session wallet with live balance data.
1525
+ * For ERC1155 positions (e.g., Polymarket), optionally enriches the response with
1526
+ * detailed market metadata including PNL, current prices, and redeemability status.
1527
+ *
1528
+ * **Key Features**:
1529
+ * - Live balance data from the analytics service
1530
+ * - Automatic Polymarket metadata enrichment for ERC1155 positions
1531
+ * - Pending transaction detection to warn of potentially stale balances
1532
+ *
1533
+ * **Returns**: `CurrentPositionsResponse`
1534
+ * - `success` (boolean): Whether the operation succeeded
1535
+ * - `data` (CurrentPositionsData | undefined): Current positions data on success
1536
+ * - `positions` (EnrichedPosition[]): Array of current positions
1537
+ * - `network` (string): Network identifier (e.g., "ethereum:137")
1538
+ * - `assetAddress` (string): Token/asset contract address
1539
+ * - `tokenId` (string | null): Token ID for NFTs/ERC1155 (null for fungible)
1540
+ * - `avgUnitCost` (string): Average unit cost in USD
1541
+ * - `currentQty` (string): Current quantity held (raw amount)
1542
+ * - `polymarketMetadata` (optional): Detailed Polymarket position data
1543
+ * - `question` (string): Market question text
1544
+ * - `outcome` (string): Outcome name (e.g., "Yes", "No")
1545
+ * - `formattedShares` (string): Human-readable share count
1546
+ * - `valueUsd` (string): Current position value in USD
1547
+ * - `priceUsd` (string): Current price per share
1548
+ * - `averagePriceUsd` (string): Average purchase price
1549
+ * - `pnlUsd` (string): Unrealized profit/loss in USD
1550
+ * - `pnlPercent` (string): Unrealized profit/loss percentage
1551
+ * - `isRedeemable` (boolean): Whether position can be redeemed
1552
+ * - `endDate` (string): Market end date
1553
+ * - Plus additional market details
1554
+ * - `hasPendingTxs` (boolean): Whether there are pending transactions
1555
+ * - `error` (string | undefined): Error message on failure
1556
+ * - `errorMessage` (string | undefined): Detailed error message on failure
1557
+ *
1558
+ * @returns Promise resolving to CurrentPositionsResponse with enriched positions
1559
+ *
1560
+ * @example
1561
+ * ```ts
1562
+ * const result = await sdk.getCurrentPositions();
1563
+ *
1564
+ * if (result.success && result.data) {
1565
+ * console.log(`Found ${result.data.positions.length} positions`);
1566
+ *
1567
+ * if (result.data.hasPendingTxs) {
1568
+ * console.log('⚠️ Warning: Pending transactions may affect balances');
1569
+ * }
1570
+ *
1571
+ * result.data.positions.forEach(position => {
1572
+ * console.log(`${position.assetAddress}: ${position.currentQty} units`);
1573
+ * console.log(` Average cost: $${position.avgUnitCost}`);
1574
+ *
1575
+ * // Check for Polymarket enrichment
1576
+ * if (position.polymarketMetadata) {
1577
+ * const pm = position.polymarketMetadata;
1578
+ * console.log(` 📈 ${pm.question}`);
1579
+ * console.log(` Outcome: ${pm.outcome}`);
1580
+ * console.log(` Shares: ${pm.formattedShares}`);
1581
+ * console.log(` Value: $${pm.valueUsd}`);
1582
+ * console.log(` PNL: $${pm.pnlUsd} (${pm.pnlPercent}%)`);
1583
+ * console.log(` Redeemable: ${pm.isRedeemable ? 'Yes' : 'No'}`);
1584
+ * }
1585
+ * });
1586
+ * } else {
1587
+ * console.error(`Failed to get positions: ${result.error}`);
1588
+ * }
1589
+ * ```
1590
+ *
1591
+ * **Success Response Example**:
1592
+ * ```json
1593
+ * {
1594
+ * "success": true,
1595
+ * "data": {
1596
+ * "positions": [
1597
+ * {
1598
+ * "network": "ethereum:137",
1599
+ * "assetAddress": "0x4d97dcd97eC945f40cF65F87097ACe5EA0476045",
1600
+ * "tokenId": "123456",
1601
+ * "avgUnitCost": "0.52",
1602
+ * "currentQty": "10.5",
1603
+ * "polymarketMetadata": {
1604
+ * "question": "Will event X happen?",
1605
+ * "outcome": "Yes",
1606
+ * "formattedShares": "10.5",
1607
+ * "valueUsd": "5.46",
1608
+ * "priceUsd": "0.52",
1609
+ * "averagePriceUsd": "0.50",
1610
+ * "pnlUsd": "0.21",
1611
+ * "pnlPercent": "4.00",
1612
+ * "isRedeemable": false
1613
+ * }
1614
+ * }
1615
+ * ],
1616
+ * "hasPendingTxs": false
1617
+ * }
1618
+ * }
1619
+ * ```
1620
+ */
1621
+ getCurrentPositions(): Promise<CurrentPositionsResponse>;
1338
1622
  }
1339
1623
 
1340
1624
  /**
@@ -1352,6 +1636,7 @@ declare class AgentSdk {
1352
1636
  declare class APIClient {
1353
1637
  private config;
1354
1638
  private baseUrl;
1639
+ private authorizationHeader?;
1355
1640
  private isCloudflareWorker;
1356
1641
  private hasServiceBinding;
1357
1642
  /**
@@ -1512,6 +1797,7 @@ declare class AgentContext {
1512
1797
  * @param config.sessionWalletAddress - Wallet address for this session
1513
1798
  * @param config.currentPositions - Current positions allocated to this agent
1514
1799
  * @param config.baseUrl - Override API base URL (detected automatically otherwise)
1800
+ * @param config.authorizationHeader - Optional Authorization header from incoming request
1515
1801
  *
1516
1802
  * @example
1517
1803
  * ```typescript
@@ -1529,6 +1815,7 @@ declare class AgentContext {
1529
1815
  sessionWalletAddress: string;
1530
1816
  currentPositions: CurrentPosition[];
1531
1817
  baseUrl?: string;
1818
+ authorizationHeader?: string;
1532
1819
  });
1533
1820
  /**
1534
1821
  * Unified logging method that handles console output and backend messaging.
@@ -1937,7 +2224,6 @@ declare class AgentContext {
1937
2224
  * - `fromToken` (optional): Source token address (omit for native tokens)
1938
2225
  * - `toToken` (optional): Destination token address (omit for native tokens)
1939
2226
  * - `slippage` (optional): Slippage tolerance % as string (default: "0.5")
1940
- * - `priceImpact` (optional): Max price impact % as string (default: "0.5")
1941
2227
  *
1942
2228
  * **Output**: `SwidgeQuoteResponse`
1943
2229
  * - `success`: Whether the quote was retrieved successfully
@@ -1967,18 +2253,23 @@ declare class AgentContext {
1967
2253
  *
1968
2254
  * Takes your quote and signs/broadcasts transactions automatically.
1969
2255
  *
1970
- * **Input**: `SwidgeQuoteData` - Complete quote object from agent.swidge.quote()
2256
+ * Supports both single and bulk execution:
2257
+ * - Pass a single quote → get a single response
2258
+ * - Pass an array of quotes → get an array of responses
2259
+ *
2260
+ * **Input**: `SwidgeQuoteData | SwidgeQuoteData[]` - Complete quote object(s) from agent.swidge.quote()
1971
2261
  *
1972
- * **Output**: `SwidgeExecuteResponse`
2262
+ * **Output**: `SwidgeExecuteResponse | SwidgeExecuteResponse[]` (matching input type)
1973
2263
  * - `success`: Whether the execution was successful
1974
2264
  * - `data`: Execution result with status ("success", "failure", "refund", "delayed") and transaction hashes
1975
2265
  * - `error`: Error message if execution failed
1976
2266
  *
1977
- * @param quoteData - Complete quote object from agent.swidge.quote()
2267
+ * @param quoteData - Complete quote object(s) from agent.swidge.quote()
1978
2268
  * @returns Promise resolving to SwidgeExecuteResponse with transaction status
1979
2269
  *
1980
2270
  * @example
1981
2271
  * ```typescript
2272
+ * // Single execution
1982
2273
  * const quote = await agent.swidge.quote({...});
1983
2274
  * if (quote.success && quote.data) {
1984
2275
  * const result = await agent.swidge.execute(quote.data);
@@ -1989,10 +2280,140 @@ declare class AgentContext {
1989
2280
  * }
1990
2281
  * }
1991
2282
  * }
2283
+ *
2284
+ * // Bulk execution
2285
+ * const results = await agent.swidge.execute([quote.data, quote2.data]);
2286
+ * results.forEach((result, index) => {
2287
+ * if (result.success && result.data) {
2288
+ * console.log(`Swap ${index + 1} status: ${result.data.status}`);
2289
+ * }
2290
+ * });
1992
2291
  * ```
1993
2292
  */
1994
- execute: (quoteData: SwidgeQuoteData) => Promise<SwidgeExecuteResponse>;
2293
+ execute: {
2294
+ (quoteData: SwidgeQuoteData): Promise<SwidgeExecuteResponse>;
2295
+ (quoteData: SwidgeQuoteData[]): Promise<SwidgeExecuteResponse[]>;
2296
+ };
1995
2297
  };
2298
+ /**
2299
+ * Get transaction ledger with asset changes.
2300
+ *
2301
+ * Fetches all confirmed transaction asset changes for this session, including
2302
+ * both EVM and Solana transactions.
2303
+ *
2304
+ * **Output**: `TransactionsResponse`
2305
+ * - `success` (boolean): Whether the operation succeeded
2306
+ * - `data` (AssetChange[] | undefined): Array of asset changes on success
2307
+ * - Each `AssetChange` contains:
2308
+ * - `network` (string): Network identifier (e.g., "ethereum:1", "solana")
2309
+ * - `transactionHash` (string): Transaction hash
2310
+ * - `from` (string): Sender address
2311
+ * - `to` (string): Recipient address
2312
+ * - `amount` (string): Amount transferred (as string to preserve precision)
2313
+ * - `token` (string | null): Token contract address (null for native tokens)
2314
+ * - `tokenId` (string | null): Token ID for NFTs (null for fungible tokens)
2315
+ * - `tokenType` (string): Token type (e.g., "native", "ERC20", "ERC721")
2316
+ * - `tokenUsdPrice` (string | null): Token price in USD at time of transaction
2317
+ * - `timestamp` (string): Transaction timestamp
2318
+ * - `error` (string | undefined): Error message on failure
2319
+ * - `errorMessage` (string | undefined): Detailed error message on failure
2320
+ *
2321
+ * @returns Promise resolving to TransactionsResponse with asset changes
2322
+ *
2323
+ * @example
2324
+ * ```typescript
2325
+ * const result = await agent.transactions();
2326
+ *
2327
+ * if (result.success && result.data) {
2328
+ * await agent.log(`Found ${result.data.length} transactions`);
2329
+ *
2330
+ * // Filter for outgoing transfers
2331
+ * const outgoing = result.data.filter(
2332
+ * change => change.from === agent.sessionWalletAddress
2333
+ * );
2334
+ *
2335
+ * // Calculate total USD value
2336
+ * const totalUsd = result.data
2337
+ * .filter(c => c.tokenUsdPrice)
2338
+ * .reduce((sum, c) => sum + parseFloat(c.amount) * parseFloat(c.tokenUsdPrice!), 0);
2339
+ *
2340
+ * await agent.log(`Total USD value: $${totalUsd.toFixed(2)}`);
2341
+ * } else {
2342
+ * await agent.log(result.error || 'Failed to fetch transactions', { error: true });
2343
+ * }
2344
+ * ```
2345
+ */
2346
+ transactions(): Promise<TransactionsResponse>;
2347
+ /**
2348
+ * Get current live positions for the session.
2349
+ *
2350
+ * Retrieves all current positions held by the session wallet with live balance data.
2351
+ * For ERC1155 positions (e.g., Polymarket), automatically enriches the response with
2352
+ * detailed market metadata including PNL, current prices, and redeemability status.
2353
+ *
2354
+ * **Output**: `CurrentPositionsResponse`
2355
+ * - `success` (boolean): Whether the operation succeeded
2356
+ * - `data` (CurrentPositionsData | undefined): Current positions data on success
2357
+ * - `hasPendingTxs` (boolean): Whether there are pending transactions
2358
+ * - `positions` (EnrichedPosition[]): Array of current positions
2359
+ * - `network` (string): Network identifier (e.g., "ethereum:137")
2360
+ * - `assetAddress` (string): Token/asset contract address
2361
+ * - `tokenId` (string | null): Token ID for NFTs/ERC1155 (null for fungible)
2362
+ * - `avgUnitCost` (string): Average unit cost in USD
2363
+ * - `currentQty` (string): Current quantity held (raw amount)
2364
+ * - `polymarketMetadata` (optional): Detailed Polymarket position data
2365
+ * - `question` (string): Market question text
2366
+ * - `outcome` (string): Outcome name (e.g., "Yes", "No")
2367
+ * - `formattedShares` (string): Human-readable share count
2368
+ * - `valueUsd` (string): Current position value in USD
2369
+ * - `priceUsd` (string): Current price per share
2370
+ * - `averagePriceUsd` (string): Average purchase price
2371
+ * - `pnlUsd` (string): Unrealized profit/loss in USD
2372
+ * - `pnlPercent` (string): Unrealized profit/loss percentage
2373
+ * - `isRedeemable` (boolean): Whether position can be redeemed
2374
+ * - `endDate` (string): Market end date
2375
+ * - Plus additional market details
2376
+ * - `error` (string | undefined): Error message on failure
2377
+ * - `errorMessage` (string | undefined): Detailed error message on failure
2378
+ *
2379
+ * @returns Promise resolving to CurrentPositionsResponse with enriched positions
2380
+ *
2381
+ * @example
2382
+ * ```typescript
2383
+ * const result = await agent.getCurrentPositions();
2384
+ *
2385
+ * if (result.success && result.data) {
2386
+ * await agent.log(`Managing ${result.data.positions.length} positions`);
2387
+ *
2388
+ * if (result.data.hasPendingTxs) {
2389
+ * await agent.log('⚠️ Warning: Pending transactions may affect balances');
2390
+ * }
2391
+ *
2392
+ * // Iterate through positions
2393
+ * for (const position of result.data.positions) {
2394
+ * await agent.log(`Position: ${position.assetAddress}`);
2395
+ * await agent.log(` Quantity: ${position.currentQty}`);
2396
+ * await agent.log(` Avg Cost: $${position.avgUnitCost}`);
2397
+ *
2398
+ * // Check for Polymarket enrichment
2399
+ * if (position.polymarketMetadata) {
2400
+ * const pm = position.polymarketMetadata;
2401
+ * await agent.log(` Market: ${pm.question}`);
2402
+ * await agent.log(` Outcome: ${pm.outcome}`);
2403
+ * await agent.log(` Value: $${pm.valueUsd}`);
2404
+ * await agent.log(` PNL: $${pm.pnlUsd} (${pm.pnlPercent}%)`);
2405
+ *
2406
+ * if (pm.isRedeemable) {
2407
+ * await agent.log(' ✅ This position is redeemable!');
2408
+ * }
2409
+ * }
2410
+ * }
2411
+ * } else {
2412
+ * await agent.log(result.error || 'Failed to fetch positions', { error: true });
2413
+ * }
2414
+ * ```
2415
+ */
2416
+ getCurrentPositions(): Promise<CurrentPositionsResponse>;
1996
2417
  }
1997
2418
 
1998
2419
  /**
@@ -2063,7 +2484,8 @@ interface AgentConfig {
2063
2484
  * HTTP server wrapper for agent functions.
2064
2485
  *
2065
2486
  * Exposes the following endpoints:
2066
- * - `POST /execute` — required, calls your execution function
2487
+ * - `POST /run` — required, calls your execution function
2488
+ * - `POST /execute` — backward compatibility, maps to run function
2067
2489
  * - `POST /stop` — always available, uses provided or default stop function
2068
2490
  * - `GET /health` — always available, uses default health check
2069
2491
  */
@@ -2106,9 +2528,9 @@ declare class Agent {
2106
2528
  private updateJobStatus;
2107
2529
  private setupRoutes;
2108
2530
  private getPortFromPackageJson;
2109
- run(port?: number): {
2531
+ run(port?: number): Promise<{
2110
2532
  fetch: (request: Request, env: any, ctx: any) => Promise<Response>;
2111
- } | undefined;
2533
+ } | undefined>;
2112
2534
  /** Get the worker export for Cloudflare Workers environments. */
2113
2535
  getExport(): {
2114
2536
  fetch: (request: Request, env: any, ctx: any) => Promise<Response>;
@@ -2138,4 +2560,4 @@ declare function isSolanaNetwork(network: Network): network is "solana";
2138
2560
  */
2139
2561
  declare function getChainIdFromNetwork(network: `ethereum:${number}`): number;
2140
2562
 
2141
- export { APIClient, Agent, AgentContext, AgentSdk, type CurrentPosition, type LogResponse, type MemoryDeleteResponse, type MemoryGetResponse, type MemoryListResponse, type MemorySetResponse, type Network, type PolymarketMarketOrderRequest, type PolymarketMarketOrderResponse, type PolymarketRedeemPositionsRequest, type PolymarketRedeemPositionsResponse, QUOTE_RESULT, type SDKConfig, type SignAndSendRequest, type SignAndSendResponse, type SignMessageRequest, type SignMessageResponse, type StopFunctionContract, type SwidgeExecuteResponse, type SwidgeQuoteRequest, type SwidgeQuoteResponse, type SwidgeQuoteResult, getChainIdFromNetwork, isEthereumNetwork, isSolanaNetwork, type runFunctionContract };
2563
+ export { APIClient, Agent, AgentContext, AgentSdk, type AssetChange, type CurrentPosition, type CurrentPositionsData, type CurrentPositionsResponse, type EnrichedPosition, type LogResponse, type MemoryDeleteResponse, type MemoryGetResponse, type MemoryListResponse, type MemorySetResponse, type Network, type PolymarketMarketOrderRequest, type PolymarketMarketOrderResponse, type PolymarketRedeemPositionsRequest, type PolymarketRedeemPositionsResponse, QUOTE_RESULT, type SDKConfig, type SignAndSendRequest, type SignAndSendResponse, type SignMessageRequest, type SignMessageResponse, type StopFunctionContract, type SwidgeExecuteResponse, type SwidgeQuoteRequest, type SwidgeQuoteResponse, type SwidgeQuoteResult, type TransactionsResponse, getChainIdFromNetwork, isEthereumNetwork, isSolanaNetwork, type runFunctionContract };
package/index.js CHANGED
@@ -1 +1 @@
1
- var __getOwnPropNames=Object.getOwnPropertyNames,__require=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("undefined"!=typeof require)return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')}),__commonJS=(e,t)=>function(){return t||(0,e[__getOwnPropNames(e)[0]])((t={exports:{}}).exports,t),t.exports},require_auth_loader=__commonJS({"src/utils/auth-loader.cjs"(exports,module){function loadAuthFromFileSystem(){try{if("undefined"==typeof process)return;const fs=eval("require")("fs"),path=eval("require")("path"),os=eval("require")("os"),homeDir=os.homedir();let authPath=path.join(homeDir,".config","circuit","auth.json");if(!fs.existsSync(authPath)&&(authPath=path.join(homeDir,".circuit","auth.json"),!fs.existsSync(authPath)))return;const authContent=fs.readFileSync(authPath,"utf-8");return JSON.parse(authContent)}catch(e){return}}module.exports={loadAuthFromFileSystem:loadAuthFromFileSystem}}}),API_BASE_URL_LOCAL="https://agents.circuit.org",APIClient=class{config;baseUrl;isCloudflareWorker(){return"undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare}hasServiceBinding(){let e=!1;return this.isCloudflareWorker()&&(void 0!==globalThis.AGENTS_TO_API_PROXY||void 0!==globalThis.__AGENT_ENV__&&globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)&&(e=!0),e}constructor(e){this.config=e,this.baseUrl=e.baseUrl||API_BASE_URL_LOCAL}getAgentSlug(){return"undefined"!=typeof process&&process.env?.CIRCUIT_AGENT_SLUG?process.env.CIRCUIT_AGENT_SLUG:void 0!==globalThis.CIRCUIT_AGENT_SLUG?globalThis.CIRCUIT_AGENT_SLUG:void 0}getAuthHeaders(){const e={};e["X-Session-Id"]=this.config.sessionId.toString();const t=this.getAgentSlug();if(t&&(e["X-Agent-Slug"]=t),!this.hasServiceBinding())try{const t=this.loadAuthConfig();t?.sessionToken&&(e.Authorization=`Bearer ${t.sessionToken}`)}catch(e){}return e}loadAuthConfig(){try{const{loadAuthFromFileSystem:e}=require_auth_loader();return e()}catch(e){}}async makeRequest(e,t={}){const r={...{"Content-Type":"application/json",...this.getAuthHeaders()},...t.headers};let s;if(this.hasServiceBinding()){let o;if(void 0!==globalThis.AGENTS_TO_API_PROXY)o=globalThis.AGENTS_TO_API_PROXY;else{if(void 0===globalThis.__AGENT_ENV__||!globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)throw new Error("Service binding detected but not accessible");o=globalThis.__AGENT_ENV__.AGENTS_TO_API_PROXY}const a={...t,headers:r},n=`https://agents-to-api-proxy.circuit-0bc.workers.dev${e}`;s=await o.fetch(n,a)}else{const o=`${this.baseUrl}${e}`,a={...t,headers:r};s=await fetch(o,a)}if(!s.ok){const e=await s.json().catch(()=>({})),t=e.message||e.error||`HTTP ${s.status}: ${s.statusText}`,r=new Error(t);throw r.error=e.error,r.errorMessage=e.message,r.errorDetails=e,r.statusCode=s.status,r}return await s.json()}async get(e){return this.makeRequest(e,{method:"GET"})}async post(e,t){return this.makeRequest(e,{method:"POST",body:t?JSON.stringify(t):void 0})}async delete(e){return this.makeRequest(e,{method:"DELETE"})}};function isEthereumNetwork(e){return e.startsWith("ethereum:")}function isSolanaNetwork(e){return"solana"===e}function getChainIdFromNetwork(e){return Number(e.split(":")[1])}var AgentSdk=class{client;config;constructor(e){this.config=e,this.client=new APIClient(e)}async _sendLog(e){await this.client.post("/v1/logs",e)}async signAndSend(e){try{if(isEthereumNetwork(e.network)){const t=getChainIdFromNetwork(e.network);if("toAddress"in e.request)return await this.handleEvmTransaction({chainId:t,toAddress:e.request.toAddress,data:e.request.data,valueWei:e.request.value,message:e.message})}if(isSolanaNetwork(e.network)&&"hexTransaction"in e.request)return await this.handleSolanaTransaction({hexTransaction:e.request.hexTransaction,message:e.message});const t=`Unsupported network: ${e.network}`;return{success:!1,error:"Unsupported Network",errorMessage:t,errorDetails:{message:t}}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{};return t||r?{success:!1,error:t,errorMessage:r,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async signMessage(e){try{if(isEthereumNetwork(e.network))return await this.handleEvmSignMessage(e);const t=`Unsupported network: ${e.network}`;return{success:!1,error:"Unsupported Network",errorMessage:t,errorDetails:{message:t}}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{};return t||r?{success:!1,error:t,errorMessage:r,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}swidge={quote:async e=>this.handleSwidgeQuote(e),execute:async e=>this.handleSwidgeExecute(e)};memory={set:async(e,t)=>this.handleMemorySet(e,t),get:async e=>this.handleMemoryGet(e),delete:async e=>this.handleMemoryDelete(e),list:async()=>this.handleMemoryList()};platforms={polymarket:{marketOrder:async e=>this.handlePolymarketMarketOrder(e),redeemPositions:async e=>this.handlePolymarketRedeemPositions(e||{tokenIds:[]})}};async handleEvmTransaction(e){try{const t=await this.client.post("/v1/transactions/evm",e),r=await this.client.post(`/v1/transactions/evm/${t.internalTransactionId}/broadcast`);return{success:!0,data:{internalTransactionId:t.internalTransactionId,txHash:r.txHash,transactionUrl:r.transactionUrl}}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{};return t||r?{success:!1,error:t,errorMessage:r,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async handleSolanaTransaction(e){try{const t=await this.client.post("/v1/transactions/solana",e),r=await this.client.post(`/v1/transactions/solana/${t.internalTransactionId}/broadcast`);return{success:!0,data:{internalTransactionId:t.internalTransactionId,txHash:r.txHash,transactionUrl:r.transactionUrl}}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{};return t||r?{success:!1,error:t,errorMessage:r,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async handleEvmSignMessage(e){try{return{success:!0,data:await this.client.post("/v1/messages/evm",{messageType:e.request.messageType,data:e.request.data,chainId:e.request.chainId})}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{};return t||r?{success:!1,error:t,errorMessage:r,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async _updateJobStatus(e){try{return await this.client.post(`/v1/jobs/${e.jobId}/status`,e)}catch(e){return{status:400,message:`Failed to update job status: ${e instanceof Error?e.message:"Unknown error"}`}}}async handleSwidgeQuote(e){try{return{success:!0,data:await this.client.post("/v1/swidge/quote",e)}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to get swidge quote";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}async handleSwidgeExecute(e){try{return{success:!0,data:await this.client.post("/v1/swidge/execute",e)}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to execute swidge swap";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}async handlePolymarketMarketOrder(e){try{return{success:!0,data:await this.client.post("/v1/platforms/polymarket/market-order",e)}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to execute polymarket market order";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}async handlePolymarketRedeemPositions(e){try{return{success:!0,data:await this.client.post("/v1/platforms/polymarket/redeem-positions",e)}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to redeem polymarket positions";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}async handleMemorySet(e,t){try{return{success:!0,data:await this.client.post(`/v1/memory/${e}`,{value:t})}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to set memory";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}async handleMemoryGet(e){try{return{success:!0,data:await this.client.get(`/v1/memory/${e}`)}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to get memory";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}async handleMemoryDelete(e){try{return{success:!0,data:await this.client.delete(`/v1/memory/${e}`)}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to delete memory";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}async handleMemoryList(){try{return{success:!0,data:await this.client.get("/v1/memory/list")}}catch(e){const t=e.error,r=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to list memory keys";return{success:!1,error:t||"SDK Error",errorMessage:r||o,errorDetails:s}}}};import{zValidator}from"@hono/zod-validator";import{Hono}from"hono";import{cors}from"hono/cors";import{z}from"zod";var AgentContext=class{sessionId;sessionWalletAddress;currentPositions;t;constructor(e){this.sessionId=e.sessionId,this.sessionWalletAddress=e.sessionWalletAddress,this.currentPositions=e.currentPositions,this.t=new AgentSdk({sessionId:e.sessionId,baseUrl:e.baseUrl})}async log(e,t){const{error:r=!1,debug:s=!1}=t||{};let o,a;const n=(e,t)=>{if("bigint"==typeof t)return t.toString();if("function"==typeof t)return`[Function: ${t.name||"anonymous"}]`;if(void 0===t)return"[undefined]";if(null===t)return null;if("object"==typeof t&&!Array.isArray(t)&&t.toString!==Object.prototype.toString)try{const e=t.toString();if("[object Object]"!==e)return e}catch(e){}return t};if("object"==typeof e&&null!==e?(o=JSON.stringify(e,n,2),a=JSON.stringify(e,n)):(o=String(e),a=String(e)),r?console.log(`[ERROR] ${o}`):console.log(o),s)return{success:!0};const i=r?"error":"observe";try{const e=a.length>250?a.slice(0,250):a;return await this.t._sendLog([{type:i,shortMessage:e}]),{success:!0}}catch(e){const t=e instanceof Error?e.message:"Failed to send log";return console.error(`Failed to send log to backend: ${t}`),{success:!1,error:"Log Error",errorMessage:t,errorDetails:{message:t,type:e instanceof Error?e.constructor.name:"UnknownError"}}}}async signAndSend(e){return this.t.signAndSend(e)}async signMessage(e){return this.t.signMessage(e)}memory={set:async(e,t)=>this.t.memory.set(e,t),get:async e=>this.t.memory.get(e),delete:async e=>this.t.memory.delete(e),list:async()=>this.t.memory.list()};platforms={polymarket:{marketOrder:async e=>this.t.platforms.polymarket.marketOrder(e),redeemPositions:async e=>this.t.platforms.polymarket.redeemPositions(e)}};swidge={quote:async e=>this.t.swidge.quote(e),execute:async e=>this.t.swidge.execute(e)}},CurrentPositionSchema=z.object({network:z.string(),assetAddress:z.string(),tokenId:z.string().nullable(),avgUnitCost:z.string(),currentQty:z.string()}),AgentRequestSchema=z.object({sessionId:z.number(),sessionWalletAddress:z.string(),jobId:z.string().optional(),currentPositions:z.array(CurrentPositionSchema)}),HealthResponseSchema=z.object({status:z.string()}),Agent=class{app;runFunction;stopFunction;healthCheckFunction=async()=>({status:"healthy",timestamp:(new Date).toISOString()});constructor(e){this.app=new Hono,this.runFunction=e.runFunction,this.stopFunction=e.stopFunction,this.app.use("*",cors()),this.setupRoutes()}defaultStopFunction=async e=>{await e.log(`Agent stopped for session ${e.sessionId}`)};async executeWithJobTracking(e,t){let r,s=!1;try{const r=new AgentContext({sessionId:e.sessionId,sessionWalletAddress:e.sessionWalletAddress,currentPositions:e.currentPositions});await t(r),s=!0}catch(e){r=this.getErrorMessage(e),s=!1,console.error("Agent function error:",r)}finally{e.jobId&&await this.updateJobStatus(e.sessionId,e.jobId,s?"success":"failed",r)}}getErrorMessage(e){if(null==e)return"Unknown error";try{const t=e?.constructor?.name||"Error";let r="";r=e instanceof Error&&e.message||String(e),r=r.replace(/[^\x20-\x7E\n\t]/g,"");const s=`${t}: ${r}`;return s.length>1e3?`${s.substring(0,997)}...`:s}catch{return"Unknown error (message extraction failed)"}}async updateJobStatus(e,t,r,s){const o=new AgentSdk({sessionId:e});for(let e=1;e<=3;e++)try{return await o._updateJobStatus({jobId:t,status:r,errorMessage:s}),void console.log(`Job status updated to '${r}' (attempt ${e})`)}catch(t){console.error(`Status update attempt ${e}/3 failed:`,t),e<3&&await new Promise(t=>setTimeout(t,100*2**(e-1)))}if("failed"===r)try{return await o._updateJobStatus({jobId:t,status:r,errorMessage:void 0}),void console.warn(`Job status updated to '${r}' without error message`)}catch(e){console.error(`CRITICAL: Failed to update job ${t} status. Likely API connectivity issue:`,e)}else console.error(`CRITICAL: Failed to update job ${t} status to success after 3 attempts`)}setupRoutes(){this.app.post("/execute",zValidator("json",AgentRequestSchema),async e=>{const t=e.req.valid("json");return await this.executeWithJobTracking(t,this.runFunction),e.json({success:!0,message:"Execution completed"})}),this.app.post("/stop",zValidator("json",AgentRequestSchema),async e=>{const t=e.req.valid("json"),r=this.stopFunction||this.defaultStopFunction;return await this.executeWithJobTracking(t,r),e.json({success:!0,message:"Stop completed"})}),this.app.get("/health",async e=>{try{const t=await this.healthCheckFunction();return e.json(t)}catch(t){return console.error("Agent health check error:",t),e.json({status:"unhealthy",error:t instanceof Error?t.message:"Unknown error",timestamp:(new Date).toISOString()},500)}})}getPortFromPackageJson(){try{const e=__require("fs"),t=__require("path").join(process.cwd(),"package.json");if(e.existsSync(t)){const r=JSON.parse(e.readFileSync(t,"utf-8"));if(r.circuit?.port)return console.log("⚠️ Warning: circuit.port in package.json is deprecated. Use AGENT_PORT environment variable instead."),Number.parseInt(r.circuit.port,10)}}catch(e){console.log("Could not read package.json for port configuration")}return null}run(port){const isCloudflareWorker="undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare;if(isCloudflareWorker)return this.getExport();const bunEnv=globalThis.Bun?.env,envPort=process.env.AGENT_PORT||bunEnv?.AGENT_PORT,packageJsonPort=this.getPortFromPackageJson();let finalPort=port;!finalPort&&envPort&&(finalPort=Number.parseInt(envPort,10)),!finalPort&&packageJsonPort&&(finalPort=packageJsonPort),finalPort||(finalPort=3e3),console.log("🔧 Agent configuration:"),console.log(` Explicit port parameter: ${port||"not set"}`),console.log(` process.env.AGENT_PORT: ${process.env.AGENT_PORT||"not set"}`),console.log(` Bun.env.AGENT_PORT: ${bunEnv?.AGENT_PORT||"not set"}`),console.log(` package.json circuit.port: ${packageJsonPort||"not set"} (deprecated)`),console.log(` Final port: ${finalPort}`);try{const req=eval("require"),{serve:serve}=req("@hono/node-server");console.log(`🚀 Server is running on port ${finalPort}`),serve({fetch:this.app.fetch,port:finalPort})}catch(e){console.error("Failed to start local server. @hono/node-server is not available."),console.error("For local development, install @hono/node-server: npm install @hono/node-server"),process.exit(1)}}getExport(){return{fetch:async(e,t,r)=>(t&&"undefined"!=typeof globalThis&&(globalThis.__AGENT_ENV__=t),this.app.fetch(e,t,r))}}};function createAgentHandler(e,t){return new Agent({runFunction:e,stopFunction:t})}import{z as z2}from"zod";var zEthereumNetwork=z2.templateLiteral(["ethereum:",z2.coerce.number().int().nonnegative()]),SwidgeNetworkSchema=z2.union([z2.literal("solana"),zEthereumNetwork]),SwidgeWalletSchema=z2.object({address:z2.string(),network:SwidgeNetworkSchema}),SwidgeQuoteRequestSchema=z2.object({from:SwidgeWalletSchema,to:SwidgeWalletSchema,fromToken:z2.string().optional(),toToken:z2.string().optional(),amount:z2.string(),slippage:z2.string().optional()}),SwidgeQuoteAssetSchema=z2.object({network:SwidgeNetworkSchema,address:z2.string(),token:z2.string().nullable(),name:z2.string().optional(),symbol:z2.string().optional(),decimals:z2.number().optional(),amount:z2.string().optional(),minimumAmount:z2.string().optional(),amountFormatted:z2.string().optional(),amountUsd:z2.string().optional()}),SwidgePriceImpactSchema=z2.object({usd:z2.string().optional(),percentage:z2.string().optional()}),SwidgeFeeSchema=z2.object({name:z2.string(),amount:z2.string().optional(),amountFormatted:z2.string().optional(),amountUsd:z2.string().optional()}),SwidgeSolanaInstructionSchema=z2.object({programId:z2.string(),keys:z2.array(z2.object({pubkey:z2.string(),isSigner:z2.boolean(),isWritable:z2.boolean()})),data:z2.union([z2.string(),z2.instanceof(Buffer)])}),SwidgeEvmTransactionDetailsSchema=z2.object({type:z2.literal("evm"),from:z2.string().regex(/^0x[a-fA-F0-9]{40}$/),to:z2.string().regex(/^0x[a-fA-F0-9]{40}$/),chainId:z2.number(),value:z2.number(),data:z2.string().regex(/^0x[a-fA-F0-9]*$/),gas:z2.number().nullish(),maxFeePerGas:z2.number().nullish(),maxPriorityFeePerGas:z2.number().nullish()}),SwidgeSolanaTransactionDetailsSchema=z2.object({type:z2.literal("solana"),instructions:z2.array(SwidgeSolanaInstructionSchema),addressLookupTableAddresses:z2.array(z2.string())}),zTransactionStep=z2.object({type:z2.literal("transaction"),description:z2.string(),transactionDetails:z2.union([SwidgeEvmTransactionDetailsSchema,SwidgeSolanaTransactionDetailsSchema]),metadata:z2.record(z2.string(),z2.string())}),zUnsignedSignatureStep=z2.object({type:z2.literal("signature"),description:z2.string(),signatureData:z2.string(),metadata:z2.record(z2.string(),z2.string())}),SwidgeUnsignedStepSchema=z2.discriminatedUnion("type",[zTransactionStep,zUnsignedSignatureStep]),SwidgeQuoteDataSchema=z2.object({engine:z2.literal("relay"),assetSend:SwidgeQuoteAssetSchema,assetReceive:SwidgeQuoteAssetSchema,priceImpact:SwidgePriceImpactSchema,fees:z2.array(SwidgeFeeSchema),steps:z2.array(SwidgeUnsignedStepSchema)}),SwidgeStatusInfoSchema=z2.object({network:z2.string(),txs:z2.array(z2.string())}),SwidgeExecuteResponseSchema=z2.object({status:z2.union([z2.literal("success"),z2.literal("failure"),z2.literal("refund"),z2.literal("delayed")]),in:SwidgeStatusInfoSchema,out:SwidgeStatusInfoSchema,lastUpdated:z2.number()}),QUOTE_RESULT={FOUND:"QUOTE_FOUND",NO_QUOTE_PROVIDED:"No quote provided",WALLET_NOT_FOUND:"Wallet not found",WALLET_MISMATCH:"From wallet does not match session wallet",PRICE_IMPACT_TOO_HIGH:"Failed to get quote. Error: Price impact is too high",NO_ROUTES_FOUND:"Failed to get quote. Error: no routes found",AMOUNT_TOO_SMALL:"Failed to get quote. APIError: Swap output amount is too small to cover fees required to execute swap"},SwidgeSDKResponseSchema=e=>z2.object({success:z2.boolean(),data:e.optional(),error:z2.string().optional(),errorMessage:z2.string().optional(),errorDetails:z2.object({message:z2.string().optional(),error:z2.string().optional(),status:z2.number().optional(),statusText:z2.string().optional()}).optional()}),SwidgeQuoteResponseWrapperSchema=SwidgeSDKResponseSchema(SwidgeQuoteDataSchema),SwidgeExecuteResponseWrapperSchema=SwidgeSDKResponseSchema(SwidgeExecuteResponseSchema);export{APIClient,Agent,AgentContext,AgentSdk,QUOTE_RESULT,getChainIdFromNetwork,isEthereumNetwork,isSolanaNetwork};
1
+ import{loadAuthFromFileSystem as e}from"./chunk-4I3A6QAK.js";var r=class{config;baseUrl;authorizationHeader;isCloudflareWorker(){return"undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare}hasServiceBinding(){if(this.isCloudflareWorker()){if(void 0!==globalThis.AGENTS_TO_API_PROXY)return!0;if(void 0!==globalThis.__AGENT_ENV__&&globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)return!0}return!1}constructor(e){this.config=e,this.baseUrl=e.baseUrl||"https://agents.circuit.org",this.authorizationHeader=e.authorizationHeader}getAgentSlug(){return"undefined"!=typeof process&&process.env?.CIRCUIT_AGENT_SLUG?process.env.CIRCUIT_AGENT_SLUG:void 0!==globalThis.CIRCUIT_AGENT_SLUG?globalThis.CIRCUIT_AGENT_SLUG:void 0}getAuthHeaders(){const e={};e["X-Session-Id"]=this.config.sessionId.toString();const r=this.getAgentSlug();if(r&&(e["X-Agent-Slug"]=r),this.isCloudflareWorker())return e;if(this.authorizationHeader)return e.Authorization=this.authorizationHeader,e;try{const r=this.loadAuthConfig();r?.sessionToken&&(e.Authorization=`Bearer ${r.sessionToken}`)}catch{}return e}loadAuthConfig(){try{return e()}catch{}}async makeRequest(e,r={}){const t={...{"Content-Type":"application/json",...this.getAuthHeaders()},...r.headers};let s;if(this.hasServiceBinding()){let o;if(void 0!==globalThis.AGENTS_TO_API_PROXY)o=globalThis.AGENTS_TO_API_PROXY;else{if(void 0===globalThis.__AGENT_ENV__||!globalThis.__AGENT_ENV__?.AGENTS_TO_API_PROXY)throw new Error("Service binding detected but not accessible");o=globalThis.__AGENT_ENV__.AGENTS_TO_API_PROXY}const a={...r,headers:t},n=`https://agents-to-api-proxy.circuit-0bc.workers.dev${e}`;s=await o.fetch(n,a)}else{const o=`${this.baseUrl}${e}`,a={...r,headers:t};s=await fetch(o,a)}if(!s.ok){const e=await s.json().catch(()=>({})),r=e.message||e.error||`HTTP ${s.status}: ${s.statusText}`,t=new Error(r);throw t.error=e.error,t.errorMessage=e.message,t.errorDetails=e,t.statusCode=s.status,t}return await s.json()}async get(e){return this.makeRequest(e,{method:"GET"})}async post(e,r){return this.makeRequest(e,{method:"POST",body:r?JSON.stringify(r):void 0})}async delete(e){return this.makeRequest(e,{method:"DELETE"})}};function t(e){return e.startsWith("ethereum:")}function s(e){return"solana"===e}function o(e){return Number(e.split(":")[1])}var a=class{client;config;constructor(e){this.config=e,this.client=new r(e)}async _sendLog(e){await this.client.post("/v1/logs",e)}async signAndSend(e){try{if(t(e.network)){const r=o(e.network);if("toAddress"in e.request)return await this.handleEvmTransaction({chainId:r,toAddress:e.request.toAddress,data:e.request.data,valueWei:e.request.value,message:e.message})}if(s(e.network)&&"hexTransaction"in e.request)return await this.handleSolanaTransaction({hexTransaction:e.request.hexTransaction,message:e.message});const r=`Unsupported network: ${e.network}`;return{success:!1,error:"Unsupported Network",errorMessage:r,errorDetails:{message:r}}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{};return r||t?{success:!1,error:r,errorMessage:t,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async signMessage(e){try{if(t(e.network))return await this.handleEvmSignMessage(e);const r=`Unsupported network: ${e.network}`;return{success:!1,error:"Unsupported Network",errorMessage:r,errorDetails:{message:r}}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{};return r||t?{success:!1,error:r,errorMessage:t,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}swidge={quote:async e=>this.handleSwidgeQuote(e),execute:function(e){return this.handleSwidgeExecute(e)}.bind(this)};memory={set:async(e,r)=>this.handleMemorySet(e,r),get:async e=>this.handleMemoryGet(e),delete:async e=>this.handleMemoryDelete(e),list:async()=>this.handleMemoryList()};platforms={polymarket:{marketOrder:async e=>this.handlePolymarketMarketOrder(e),redeemPositions:async e=>this.handlePolymarketRedeemPositions(e||{tokenIds:[]})}};async handleEvmTransaction(e){try{const r=await this.client.post("/v1/transactions/evm",e),t=await this.client.post(`/v1/transactions/evm/${r.internalTransactionId}/broadcast`);return{success:!0,data:{internalTransactionId:r.internalTransactionId,txHash:t.txHash,transactionUrl:t.transactionUrl}}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{};return r||t?{success:!1,error:r,errorMessage:t,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async handleSolanaTransaction(e){try{const r=await this.client.post("/v1/transactions/solana",e),t=await this.client.post(`/v1/transactions/solana/${r.internalTransactionId}/broadcast`);return{success:!0,data:{internalTransactionId:r.internalTransactionId,txHash:t.txHash,transactionUrl:t.transactionUrl}}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{};return r||t?{success:!1,error:r,errorMessage:t,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async handleEvmSignMessage(e){try{return{success:!0,data:await this.client.post("/v1/messages/evm",{messageType:e.request.messageType,data:e.request.data,chainId:e.request.chainId})}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{};return r||t?{success:!1,error:r,errorMessage:t,errorDetails:s}:{success:!1,error:"SDK Error",errorMessage:e instanceof Error?e.message:"Unknown error",errorDetails:{}}}}async _updateJobStatus(e){try{return await this.client.post(`/v1/jobs/${e.jobId}/status`,e)}catch(e){return{status:400,message:`Failed to update job status: ${e instanceof Error?e.message:"Unknown error"}`}}}async handleSwidgeQuote(e){try{return{success:!0,data:await this.client.post("/v1/swidge/quote",e)}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to get swidge quote";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async handleSwidgeExecute(e){try{const r=await this.client.post("/v1/swidge/execute",e);if(Array.isArray(r))return r.map(e=>{const r="success"===e.status;return{success:r,data:e,error:r?void 0:e.error}});const t="success"===r.status;return{success:t,data:r,error:t?void 0:r.error}}catch(r){const t=r.error,s=r.errorMessage,o=r.errorDetails||{},a=r instanceof Error?r.message:"Failed to execute swidge swap";return Array.isArray(e)?[{success:!1,error:t||"SDK Error",errorMessage:s||a,errorDetails:o}]:{success:!1,error:t||"SDK Error",errorMessage:s||a,errorDetails:o}}}async handlePolymarketMarketOrder(e){try{return{success:!0,data:await this.client.post("/v1/platforms/polymarket/market-order",e)}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to execute polymarket market order";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async handlePolymarketRedeemPositions(e){try{return{success:!0,data:await this.client.post("/v1/platforms/polymarket/redeem-positions",e)}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to redeem polymarket positions";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async handleMemorySet(e,r){try{return{success:!0,data:await this.client.post(`/v1/memory/${e}`,{value:r})}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to set memory";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async handleMemoryGet(e){try{return{success:!0,data:await this.client.get(`/v1/memory/${e}`)}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to get memory";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async handleMemoryDelete(e){try{return{success:!0,data:await this.client.delete(`/v1/memory/${e}`)}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to delete memory";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async handleMemoryList(){try{return{success:!0,data:await this.client.get("/v1/memory/list")}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to list memory keys";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async transactions(){try{return{success:!0,data:await this.client.get("/v1/transactions/ledger")}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to fetch transactions";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}async getCurrentPositions(){try{return{success:!0,data:await this.client.get("/v1/positions/current")}}catch(e){const r=e.error,t=e.errorMessage,s=e.errorDetails||{},o=e instanceof Error?e.message:"Failed to fetch current positions";return{success:!1,error:r||"SDK Error",errorMessage:t||o,errorDetails:s}}}};import{existsSync as n,readFileSync as i}from"fs";import{join as c}from"path";import{zValidator as u}from"@hono/zod-validator";import{Hono as l}from"hono";import{cors as d}from"hono/cors";import*as h from"zod";var m=class{sessionId;sessionWalletAddress;currentPositions;t;constructor(e){this.sessionId=e.sessionId,this.sessionWalletAddress=e.sessionWalletAddress,this.currentPositions=e.currentPositions,this.t=new a({sessionId:e.sessionId,baseUrl:e.baseUrl,authorizationHeader:e.authorizationHeader})}async log(e,r){const{error:t=!1,debug:s=!1}=r||{};let o,a;const n=(e,r)=>{if("bigint"==typeof r)return r.toString();if("function"==typeof r)return`[Function: ${r.name||"anonymous"}]`;if(void 0===r)return"[undefined]";if(null===r)return null;if("object"==typeof r&&!Array.isArray(r)&&r.toString!==Object.prototype.toString)try{const e=r.toString();if("[object Object]"!==e)return e}catch(e){}return r};if("object"==typeof e&&null!==e?(o=JSON.stringify(e,n,2),a=JSON.stringify(e,n)):(o=String(e),a=String(e)),t?console.error(o):console.log(o),s)return{success:!0};const i=t?"error":"observe";try{const e=a.length>250?a.slice(0,250):a;return await this.t._sendLog([{type:i,shortMessage:e}]),{success:!0}}catch(e){const r=e instanceof Error?e.message:"Failed to send log";return console.error(`Failed to send log to backend: ${r}`),{success:!1,error:"Log Error",errorMessage:r,errorDetails:{message:r,type:e instanceof Error?e.constructor.name:"UnknownError"}}}}async signAndSend(e){return this.t.signAndSend(e)}async signMessage(e){return this.t.signMessage(e)}memory={set:async(e,r)=>this.t.memory.set(e,r),get:async e=>this.t.memory.get(e),delete:async e=>this.t.memory.delete(e),list:async()=>this.t.memory.list()};platforms={polymarket:{marketOrder:async e=>this.t.platforms.polymarket.marketOrder(e),redeemPositions:async e=>this.t.platforms.polymarket.redeemPositions(e)}};swidge={quote:async e=>this.t.swidge.quote(e),execute:function(e){return this.t.swidge.execute(e)}.bind(this)};async transactions(){return this.t.transactions()}async getCurrentPositions(){return this.t.getCurrentPositions()}},g=h.object({network:h.string(),assetAddress:h.string(),tokenId:h.string().nullable(),avgUnitCost:h.string(),currentQty:h.string()}),y=h.object({sessionId:h.number(),sessionWalletAddress:h.string(),jobId:h.string().optional(),currentPositions:h.array(g)}),p=(h.object({status:h.string()}),class{app;runFunction;stopFunction;healthCheckFunction=async()=>({status:"healthy",timestamp:(new Date).toISOString()});constructor(e){this.app=new l,this.runFunction=e.runFunction,this.stopFunction=e.stopFunction,this.app.use("*",d()),this.setupRoutes()}defaultStopFunction=async e=>{await e.log(`Agent stopped for session ${e.sessionId}`)};async executeWithJobTracking(e,r,t){let s,o=!1;try{const s=new m({sessionId:e.sessionId,sessionWalletAddress:e.sessionWalletAddress,currentPositions:e.currentPositions,authorizationHeader:t});await r(s),o=!0}catch(e){s=this.getErrorMessage(e),o=!1,console.error("Agent function error:",s)}finally{e.jobId&&await this.updateJobStatus(e.sessionId,e.jobId,o?"success":"failed",s,t)}}getErrorMessage(e){if(null==e)return"Unknown error";try{const r=e?.constructor?.name||"Error";let t="";t=e instanceof Error&&e.message||String(e),t=t.replace(/[^\x20-\x7E\n\t]/g,"");const s=`${r}: ${t}`;return s.length>1e3?`${s.substring(0,997)}...`:s}catch{return"Unknown error (message extraction failed)"}}async updateJobStatus(e,r,t,s,o){const n=new a({sessionId:e,authorizationHeader:o});for(let e=1;e<=3;e++)try{return void await n._updateJobStatus({jobId:r,status:t,errorMessage:s})}catch(r){console.error(`Status update attempt ${e}/3 failed:`,r),e<3&&await new Promise(r=>setTimeout(r,100*2**(e-1)))}if("failed"===t)try{return console.warn(`Issue updating job status to '${t}' with error message, attempting to update status without error message`),void await n._updateJobStatus({jobId:r,status:t,errorMessage:void 0})}catch(e){console.error(`CRITICAL: Failed to update job ${r} status. Likely API connectivity issue:`,e)}else console.error(`CRITICAL: Failed to update job ${r} status to success after 3 attempts`)}setupRoutes(){this.app.post("/run",u("json",y),async e=>{const r=e.req.valid("json"),t=e.req.header("Authorization");return await this.executeWithJobTracking(r,this.runFunction,t),e.json({success:!0,message:"Execution completed"})}),this.app.post("/execute",u("json",y),async e=>{const r=e.req.valid("json"),t=e.req.header("Authorization");return await this.executeWithJobTracking(r,this.runFunction,t),e.json({success:!0,message:"Execution completed"})}),this.app.post("/stop",u("json",y),async e=>{const r=e.req.valid("json"),t=e.req.header("Authorization"),s=this.stopFunction||this.defaultStopFunction;return await this.executeWithJobTracking(r,s,t),e.json({success:!0,message:"Stop completed"})}),this.app.get("/health",async e=>{try{const r=await this.healthCheckFunction();return e.json(r)}catch(r){return console.error("Agent health check error:",r),e.json({status:"unhealthy",error:r instanceof Error?r.message:"Unknown error",timestamp:(new Date).toISOString()},500)}})}getPortFromPackageJson(){try{const e=c(process.cwd(),"package.json");if(n(e)){const r=JSON.parse(i(e,"utf-8"));if(r.circuit?.port)return console.log("⚠️ Warning: circuit.port in package.json is deprecated. Use AGENT_PORT environment variable instead."),Number.parseInt(r.circuit.port,10)}}catch(e){console.log("Could not read package.json for port configuration")}return null}async run(e){if("undefined"!=typeof globalThis&&void 0!==globalThis.Cloudflare)return this.getExport();const r=globalThis.Bun?.env,t=process.env.AGENT_PORT||r?.AGENT_PORT,s=this.getPortFromPackageJson();let o=e;!o&&t&&(o=Number.parseInt(t,10)),!o&&s&&(o=s),o||(o=3e3),console.log("🔧 Agent configuration:"),console.log(` Explicit port parameter: ${e||"not set"}`),console.log(` process.env.AGENT_PORT: ${process.env.AGENT_PORT||"not set"}`),console.log(` Bun.env.AGENT_PORT: ${r?.AGENT_PORT||"not set"}`),console.log(` package.json circuit.port: ${s||"not set"} (deprecated)`),console.log(` Final port: ${o}`);try{const{serve:e}=await import("@hono/node-server");console.log(`🚀 Server is running on port ${o}`),console.log("📍 Available endpoints: GET /health, POST /run, POST /execute (backward compat), POST /stop"),e({fetch:this.app.fetch,port:o})}catch(e){console.error("Failed to start local server. @hono/node-server is not available."),console.error("For local development, install @hono/node-server: npm install @hono/node-server"),process.exit(1)}}getExport(){return{fetch:async(e,r,t)=>(r&&"undefined"!=typeof globalThis&&(globalThis.__AGENT_ENV__=r),this.app.fetch(e,r,t))}}});import{z as f}from"zod";var w=f.templateLiteral(["ethereum:",f.coerce.number().int().nonnegative()]),v=f.union([f.literal("solana"),w]),E=f.object({address:f.string(),network:v}),T=(f.object({from:E,to:E,fromToken:f.string().optional(),toToken:f.string().optional(),amount:f.string(),slippage:f.string().optional()}),f.object({network:v,address:f.string(),token:f.string().nullable(),name:f.string().optional(),symbol:f.string().optional(),decimals:f.number().optional(),amount:f.string().optional(),minimumAmount:f.string().optional(),amountFormatted:f.string().optional(),amountUsd:f.string().optional()})),b=f.object({usd:f.string().optional(),percentage:f.string().optional()}),k=f.object({name:f.string(),amount:f.string().optional(),amountFormatted:f.string().optional(),amountUsd:f.string().optional()}),D=f.object({programId:f.string(),keys:f.array(f.object({pubkey:f.string(),isSigner:f.boolean(),isWritable:f.boolean()})),data:f.union([f.string(),f.instanceof(Buffer)])}),S=f.object({type:f.literal("evm"),from:f.string().regex(/^0x[a-fA-F0-9]{40}$/),to:f.string().regex(/^0x[a-fA-F0-9]{40}$/),chainId:f.number(),value:f.number(),data:f.string().regex(/^0x[a-fA-F0-9]*$/),gas:f.number().nullish(),maxFeePerGas:f.number().nullish(),maxPriorityFeePerGas:f.number().nullish()}),A=f.object({type:f.literal("solana"),instructions:f.array(D),addressLookupTableAddresses:f.array(f.string())}),M=f.object({type:f.literal("transaction"),description:f.string(),transactionDetails:f.union([S,A]),metadata:f.record(f.string(),f.string())}),F=f.object({type:f.literal("signature"),description:f.string(),signatureData:f.string(),metadata:f.record(f.string(),f.string())}),$=f.discriminatedUnion("type",[M,F]),O=f.object({engine:f.literal("relay"),assetSend:T,assetReceive:T,priceImpact:b,fees:f.array(k),steps:f.array($)}),U=f.object({network:f.string(),txs:f.array(f.string())}),x=f.object({status:f.union([f.literal("success"),f.literal("failure"),f.literal("refund"),f.literal("delayed")]),in:U,out:U,lastUpdated:f.number(),error:f.string().optional()}),I={FOUND:"QUOTE_FOUND",NO_QUOTE_PROVIDED:"No quote provided",WALLET_NOT_FOUND:"Wallet not found",WALLET_MISMATCH:"From wallet does not match session wallet",PRICE_IMPACT_TOO_HIGH:"Failed to get quote. Error: Price impact is too high",NO_ROUTES_FOUND:"Failed to get quote. Error: no routes found",AMOUNT_TOO_SMALL:"Failed to get quote. APIError: Swap output amount is too small to cover fees required to execute swap"},P=e=>f.object({success:f.boolean(),data:e.optional(),error:f.string().optional(),errorMessage:f.string().optional(),errorDetails:f.object({message:f.string().optional(),error:f.string().optional(),status:f.number().optional(),statusText:f.string().optional()}).optional()});P(O),P(x);export{r as APIClient,p as Agent,m as AgentContext,a as AgentSdk,I as QUOTE_RESULT,o as getChainIdFromNetwork,t as isEthereumNetwork,s as isSolanaNetwork};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@circuitorg/agent-sdk",
3
- "version": "1.2.0",
3
+ "version": "1.2.3",
4
4
  "description": "typescript sdk for the Agent Toolset Service",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -0,0 +1,6 @@
1
+ interface AuthConfig {
2
+ sessionToken: string;
3
+ }
4
+ declare function loadAuthFromFileSystem(): AuthConfig | undefined;
5
+
6
+ export { loadAuthFromFileSystem };
@@ -0,0 +1 @@
1
+ import{loadAuthFromFileSystem as o}from"../chunk-4I3A6QAK.js";export{o as loadAuthFromFileSystem};
@@ -1,39 +0,0 @@
1
- // This file is intentionally in JavaScript to avoid TypeScript/bundler transformations
2
- // It provides a way to load auth config from the file system in Node.js environments
3
-
4
- function loadAuthFromFileSystem() {
5
- try {
6
- // Check if we're in a Node.js environment
7
- if (typeof process === 'undefined') {
8
- return undefined;
9
- }
10
-
11
- // Use dynamic require to avoid bundler processing
12
- const fs = eval("require")('fs');
13
- const path = eval("require")('path');
14
- const os = eval("require")('os');
15
-
16
- // Use os.homedir() for cross-platform compatibility (works on Windows, Mac, Linux)
17
- const homeDir = os.homedir();
18
-
19
- // Try main config directory first (matches CLI behavior)
20
- let authPath = path.join(homeDir, '.config', 'circuit', 'auth.json');
21
-
22
- if (!fs.existsSync(authPath)) {
23
- // Try fallback directory (matches CLI fallback behavior)
24
- authPath = path.join(homeDir, '.circuit', 'auth.json');
25
-
26
- if (!fs.existsSync(authPath)) {
27
- return undefined;
28
- }
29
- }
30
-
31
- const authContent = fs.readFileSync(authPath, 'utf-8');
32
- return JSON.parse(authContent);
33
- } catch (error) {
34
- // Silently fail if we can't read the auth config
35
- return undefined;
36
- }
37
- }
38
-
39
- module.exports = { loadAuthFromFileSystem };