@exagent/agent 0.1.19 → 0.1.21

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/dist/cli.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  loadConfig,
7
7
  loadSecureEnv,
8
8
  validateConfig
9
- } from "./chunk-ZLDWYPBF.mjs";
9
+ } from "./chunk-U6YJHCO3.mjs";
10
10
 
11
11
  // src/cli.ts
12
12
  import { Command } from "commander";
package/dist/index.d.mts CHANGED
@@ -2,6 +2,80 @@ import { z } from 'zod';
2
2
  import { Address, Hash, WalletClient } from 'viem';
3
3
  import { ExagentClient } from '@exagent/sdk';
4
4
 
5
+ /** Risk state persisted across restarts */
6
+ interface RiskState {
7
+ dailyPnL: number;
8
+ dailyFees: number;
9
+ lastResetDate: string;
10
+ }
11
+ /**
12
+ * PositionTracker — automatic position tracking with persistence.
13
+ *
14
+ * Wraps StrategyStore with domain-specific logic for tracking spot positions,
15
+ * trade history, and risk state. Used by the runtime to give strategies
16
+ * intelligent memory across restarts.
17
+ *
18
+ * - Entry prices tracked via cost-basis weighted average
19
+ * - Realized PnL calculated on sells
20
+ * - Balances synced from on-chain each cycle
21
+ * - Risk state (daily PnL/fees) persisted for circuit breaker continuity
22
+ */
23
+ declare class PositionTracker {
24
+ private store;
25
+ private positions;
26
+ private tradeHistory;
27
+ private maxTradeHistory;
28
+ constructor(store: StrategyStore, options?: {
29
+ maxTradeHistory?: number;
30
+ });
31
+ /**
32
+ * Record a trade result. On buy: creates/updates position with cost-basis
33
+ * weighted average. On sell: calculates realized PnL and removes if fully sold.
34
+ */
35
+ recordTrade(params: {
36
+ action: 'buy' | 'sell';
37
+ tokenIn: string;
38
+ tokenOut: string;
39
+ amountIn: bigint;
40
+ priceIn: number;
41
+ priceOut: number;
42
+ txHash?: string;
43
+ reasoning?: string;
44
+ success: boolean;
45
+ }): void;
46
+ /**
47
+ * Handle a buy: create or update position with cost-basis weighted average.
48
+ */
49
+ private handleBuy;
50
+ /**
51
+ * Handle a sell: calculate realized PnL and remove position if fully sold.
52
+ * Returns the realized PnL in USD.
53
+ */
54
+ private handleSell;
55
+ /**
56
+ * Sync tracked positions with on-chain balances.
57
+ * Updates currentAmount, detects new tokens (airdrops), removes zeroed positions.
58
+ */
59
+ syncBalances(balances: Record<string, bigint>, prices: Record<string, number>): void;
60
+ /** Get all tracked positions */
61
+ getPositions(): TrackedPosition[];
62
+ /** Get a single position by token address */
63
+ getPosition(token: string): TrackedPosition | undefined;
64
+ /** Get trade history (newest first) */
65
+ getTradeHistory(limit?: number): TradeRecord[];
66
+ /** Get unrealized PnL per position given current prices */
67
+ getUnrealizedPnL(prices: Record<string, number>): Record<string, number>;
68
+ /** Get total unrealized PnL across all positions */
69
+ getTotalUnrealizedPnL(prices: Record<string, number>): number;
70
+ /** Load persisted risk state */
71
+ getRiskState(): RiskState;
72
+ /** Save risk state to persistent store */
73
+ saveRiskState(state: RiskState): void;
74
+ /** Get a compact summary for relay heartbeats */
75
+ getPositionSummary(prices: Record<string, number>): PositionSummary;
76
+ private persist;
77
+ }
78
+
5
79
  declare const LLMProviderSchema: z.ZodEnum<["openai", "anthropic", "google", "deepseek", "mistral", "groq", "together", "ollama", "custom"]>;
6
80
  type LLMProvider = z.infer<typeof LLMProviderSchema>;
7
81
  declare const LLMConfigSchema: z.ZodObject<{
@@ -265,9 +339,9 @@ declare const AgentConfigSchema: z.ZodObject<{
265
339
  }>>;
266
340
  allowedTokens: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
267
341
  }, "strip", z.ZodTypeAny, {
268
- agentId: string | number;
269
342
  name: string;
270
343
  network: "mainnet";
344
+ agentId: string | number;
271
345
  llm: {
272
346
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
273
347
  temperature: number;
@@ -314,8 +388,8 @@ declare const AgentConfigSchema: z.ZodObject<{
314
388
  } | undefined;
315
389
  allowedTokens?: string[] | undefined;
316
390
  }, {
317
- agentId: string | number;
318
391
  name: string;
392
+ agentId: string | number;
319
393
  llm: {
320
394
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
321
395
  model?: string | undefined;
@@ -404,7 +478,99 @@ interface LLMResponse {
404
478
  totalTokens: number;
405
479
  };
406
480
  }
407
- type StrategyFunction = (marketData: MarketData, llm: LLMAdapter, config: AgentConfig) => Promise<TradeSignal[]>;
481
+ /**
482
+ * Persistent key-value store for strategies.
483
+ * Data survives restarts (backed by a JSON file in the agent's data directory).
484
+ * Use this to store entry prices, position metadata, PnL tracking, etc.
485
+ */
486
+ interface StrategyStore {
487
+ get<T = unknown>(key: string): T | undefined;
488
+ set<T = unknown>(key: string, value: T): void;
489
+ delete(key: string): void;
490
+ /** Get all keys in the store */
491
+ keys(): string[];
492
+ }
493
+ /**
494
+ * A tracked spot position with entry price and cost basis.
495
+ * Automatically managed by the runtime's PositionTracker.
496
+ */
497
+ interface TrackedPosition {
498
+ /** Lowercase token address */
499
+ token: string;
500
+ /** Human-readable symbol (e.g., "AERO") — best-effort, may be missing */
501
+ symbol?: string;
502
+ /** USD price at time of first buy */
503
+ entryPrice: number;
504
+ /** Cost-basis weighted average entry price */
505
+ averageEntryPrice: number;
506
+ /** Total USD spent buying this token */
507
+ totalCostBasis: number;
508
+ /** Total token amount ever acquired (in token units, not wei) */
509
+ totalAmountAcquired: number;
510
+ /** Latest known token amount held (in token units, from on-chain balance) */
511
+ currentAmount: number;
512
+ /** Timestamp of first buy (ms) */
513
+ entryTimestamp: number;
514
+ /** Timestamp of last update (ms) */
515
+ lastUpdateTimestamp: number;
516
+ /** Transaction hashes from buy trades (last 10) */
517
+ txHashes: string[];
518
+ }
519
+ /**
520
+ * A recorded trade with metadata and optional realized PnL.
521
+ */
522
+ interface TradeRecord {
523
+ timestamp: number;
524
+ action: 'buy' | 'sell';
525
+ tokenIn: string;
526
+ tokenOut: string;
527
+ /** Serialized bigint (JSON can't encode bigint) */
528
+ amountIn: string;
529
+ /** Estimated USD value of the trade */
530
+ priceUSD: number;
531
+ txHash?: string;
532
+ reasoning?: string;
533
+ /** Realized PnL in USD (only for sells) */
534
+ realizedPnL?: number;
535
+ success: boolean;
536
+ }
537
+ /**
538
+ * Compact position summary for relay heartbeats.
539
+ */
540
+ interface PositionSummary {
541
+ openPositions: number;
542
+ totalUnrealizedPnL: number;
543
+ topPositions: Array<{
544
+ token: string;
545
+ symbol?: string;
546
+ unrealizedPnL: number;
547
+ holdingDuration: number;
548
+ }>;
549
+ recentTrades: number;
550
+ totalRealizedPnL: number;
551
+ }
552
+ /**
553
+ * Context passed to strategies with persistent storage, positions, and trade history.
554
+ */
555
+ interface StrategyContext {
556
+ /** Persistent key-value store (survives restarts) */
557
+ store: StrategyStore;
558
+ /** Agent ID on-chain */
559
+ agentId: number;
560
+ /** Agent wallet address */
561
+ walletAddress: string;
562
+ /** Current open positions with entry prices (auto-populated by runtime) */
563
+ positions?: TrackedPosition[];
564
+ /** Recent trade history, newest first (auto-populated by runtime) */
565
+ tradeHistory?: TradeRecord[];
566
+ /** Position tracker instance for advanced queries (e.g., getUnrealizedPnL) */
567
+ positionTracker?: PositionTracker;
568
+ }
569
+ /**
570
+ * Strategy function signature (user implements this).
571
+ * The 4th parameter (context) is optional for backward compatibility.
572
+ */
573
+ type StrategyFunction = (marketData: MarketData, llm: LLMAdapter, config: AgentConfig, context?: StrategyContext) => Promise<TradeSignal[]>;
408
574
  interface LLMAdapter {
409
575
  chat(messages: LLMMessage[]): Promise<LLMResponse>;
410
576
  getMetadata(): LLMMetadata;
@@ -529,6 +695,8 @@ interface AgentStatusPayload {
529
695
  mode: AgentMode;
530
696
  agentId: string;
531
697
  wallet?: string;
698
+ /** @exagent/agent package version (e.g., "0.1.20") */
699
+ sdkVersion?: string;
532
700
  cycleCount?: number;
533
701
  lastCycleAt?: number;
534
702
  tradingIntervalMs?: number;
@@ -558,6 +726,19 @@ interface AgentStatusPayload {
558
726
  effectiveLeverage: number;
559
727
  pendingRecords: number;
560
728
  };
729
+ /** Spot position tracking summary (auto-populated by PositionTracker) */
730
+ positions?: {
731
+ openPositions: number;
732
+ totalUnrealizedPnL: number;
733
+ topPositions: Array<{
734
+ token: string;
735
+ symbol?: string;
736
+ unrealizedPnL: number;
737
+ holdingDuration: number;
738
+ }>;
739
+ recentTrades: number;
740
+ totalRealizedPnL: number;
741
+ };
561
742
  }
562
743
  interface RelayConfig {
563
744
  enabled: boolean;
@@ -593,9 +774,12 @@ declare class AgentRuntime {
593
774
  private lastCycleAt;
594
775
  private lastPortfolioValue;
595
776
  private lastEthBalance;
777
+ private lastPrices;
596
778
  private processAlive;
597
779
  private riskUniverse;
598
780
  private allowedTokens;
781
+ private strategyContext;
782
+ private positionTracker;
599
783
  private perpClient;
600
784
  private perpSigner;
601
785
  private perpOrders;
@@ -746,6 +930,22 @@ declare function validateConfig(config: RuntimeConfig): void;
746
930
  */
747
931
  declare function createSampleConfig(agentId: number, name: string): AgentConfig;
748
932
 
933
+ /**
934
+ * File-backed persistent key-value store for strategies.
935
+ * Data is saved as JSON in the agent's data directory and survives restarts.
936
+ */
937
+ declare class FileStore implements StrategyStore {
938
+ private data;
939
+ private filePath;
940
+ private dirty;
941
+ constructor(dataDir?: string);
942
+ get<T = unknown>(key: string): T | undefined;
943
+ set<T = unknown>(key: string, value: T): void;
944
+ delete(key: string): void;
945
+ keys(): string[];
946
+ private flush;
947
+ }
948
+
749
949
  /**
750
950
  * Base adapter class with common functionality
751
951
  */
@@ -1116,7 +1316,9 @@ declare class RiskManager {
1116
1316
  */
1117
1317
  filterSignals(signals: TradeSignal[], marketData: MarketData): TradeSignal[];
1118
1318
  /**
1119
- * Validate individual signal against risk limits
1319
+ * Validate individual signal against risk limits.
1320
+ * Sell signals are exempt from position size and minimum value checks —
1321
+ * those guardrails prevent oversized/dust buys, but blocking exits traps capital.
1120
1322
  */
1121
1323
  private validateSignal;
1122
1324
  /**
@@ -1141,6 +1343,23 @@ declare class RiskManager {
1141
1343
  * This prevents protocol fees from triggering circuit breakers.
1142
1344
  */
1143
1345
  updateFees(fees: number): void;
1346
+ /**
1347
+ * Export current risk state for persistence across restarts.
1348
+ */
1349
+ exportState(): {
1350
+ dailyPnL: number;
1351
+ dailyFees: number;
1352
+ lastResetDate: string;
1353
+ };
1354
+ /**
1355
+ * Restore risk state from persistence (called on startup).
1356
+ * Only restores if the saved state is from today — expired state is ignored.
1357
+ */
1358
+ restoreState(state: {
1359
+ dailyPnL: number;
1360
+ dailyFees: number;
1361
+ lastResetDate: string;
1362
+ }): void;
1144
1363
  /**
1145
1364
  * Get current risk status
1146
1365
  * @param portfolioValue - Current portfolio value in USD (needed for accurate loss limit)
@@ -1861,4 +2080,7 @@ declare function decryptEnvFile(encPath: string, passphrase: string): Record<str
1861
2080
  */
1862
2081
  declare function loadSecureEnv(basePath: string, passphrase?: string): boolean;
1863
2082
 
1864
- export { type AccountSummary, type AgentConfig, AgentConfigSchema, type AgentMode, AgentRuntime, type AgentStatusPayload, AnthropicAdapter, BaseLLMAdapter, type CommandType, DeepSeekAdapter, type FillCallback, type FundingCallback, type FundingPayment, GoogleAdapter, GroqAdapter, HYPERLIQUID_DOMAIN, HyperliquidClient, HyperliquidSigner, HyperliquidWebSocket, type LLMAdapter, type LLMConfig, LLMConfigSchema, type LLMMessage, type LLMMetadata, type LLMProvider, LLMProviderSchema, type LLMResponse, type LiquidationCallback, type MarketData, MarketDataService, type MessageLevel, type MessageType, MistralAdapter, OllamaAdapter, type OnboardingStatus, OpenAIAdapter, OrderManager, type OrderResult, type PerpAction, type PerpConfig$1 as PerpConfig, PerpConfigSchema, type PerpFill, type PerpMarketData, PerpOnboarding, type PerpPosition, type PerpStrategyFunction, PerpTradeRecorder, type PerpTradeSignal, type PerpConfig as PerpTradingConfig, PositionManager, type RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyFunction, type StrategyTemplate, TogetherAdapter, TradeExecutor, type TradeSignal, type TradingConfig, TradingConfigSchema, type VaultConfig, VaultConfigSchema, VaultManager, type VaultManagerConfig, type VaultPolicy, VaultPolicySchema, type VaultStatus, createLLMAdapter, createSampleConfig, decryptEnvFile, encryptEnvFile, fillHashToBytes32, fillOidToBytes32, getAllStrategyTemplates, getNextNonce, getStrategyTemplate, loadConfig, loadSecureEnv, loadStrategy, validateConfig, validateStrategy };
2083
+ /** @exagent/agent package version update alongside package.json */
2084
+ declare const AGENT_VERSION = "0.1.21";
2085
+
2086
+ export { AGENT_VERSION, type AccountSummary, type AgentConfig, AgentConfigSchema, type AgentMode, AgentRuntime, type AgentStatusPayload, AnthropicAdapter, BaseLLMAdapter, type CommandType, DeepSeekAdapter, FileStore, type FillCallback, type FundingCallback, type FundingPayment, GoogleAdapter, GroqAdapter, HYPERLIQUID_DOMAIN, HyperliquidClient, HyperliquidSigner, HyperliquidWebSocket, type LLMAdapter, type LLMConfig, LLMConfigSchema, type LLMMessage, type LLMMetadata, type LLMProvider, LLMProviderSchema, type LLMResponse, type LiquidationCallback, type MarketData, MarketDataService, type MessageLevel, type MessageType, MistralAdapter, OllamaAdapter, type OnboardingStatus, OpenAIAdapter, OrderManager, type OrderResult, type PerpAction, type PerpConfig$1 as PerpConfig, PerpConfigSchema, type PerpFill, type PerpMarketData, PerpOnboarding, type PerpPosition, type PerpStrategyFunction, PerpTradeRecorder, type PerpTradeSignal, type PerpConfig as PerpTradingConfig, PositionManager, type PositionSummary, PositionTracker, type RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskState, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyContext, type StrategyFunction, type StrategyStore, type StrategyTemplate, TogetherAdapter, type TrackedPosition, TradeExecutor, type TradeRecord, type TradeSignal, type TradingConfig, TradingConfigSchema, type VaultConfig, VaultConfigSchema, VaultManager, type VaultManagerConfig, type VaultPolicy, VaultPolicySchema, type VaultStatus, createLLMAdapter, createSampleConfig, decryptEnvFile, encryptEnvFile, fillHashToBytes32, fillOidToBytes32, getAllStrategyTemplates, getNextNonce, getStrategyTemplate, loadConfig, loadSecureEnv, loadStrategy, validateConfig, validateStrategy };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,80 @@ import { z } from 'zod';
2
2
  import { Address, Hash, WalletClient } from 'viem';
3
3
  import { ExagentClient } from '@exagent/sdk';
4
4
 
5
+ /** Risk state persisted across restarts */
6
+ interface RiskState {
7
+ dailyPnL: number;
8
+ dailyFees: number;
9
+ lastResetDate: string;
10
+ }
11
+ /**
12
+ * PositionTracker — automatic position tracking with persistence.
13
+ *
14
+ * Wraps StrategyStore with domain-specific logic for tracking spot positions,
15
+ * trade history, and risk state. Used by the runtime to give strategies
16
+ * intelligent memory across restarts.
17
+ *
18
+ * - Entry prices tracked via cost-basis weighted average
19
+ * - Realized PnL calculated on sells
20
+ * - Balances synced from on-chain each cycle
21
+ * - Risk state (daily PnL/fees) persisted for circuit breaker continuity
22
+ */
23
+ declare class PositionTracker {
24
+ private store;
25
+ private positions;
26
+ private tradeHistory;
27
+ private maxTradeHistory;
28
+ constructor(store: StrategyStore, options?: {
29
+ maxTradeHistory?: number;
30
+ });
31
+ /**
32
+ * Record a trade result. On buy: creates/updates position with cost-basis
33
+ * weighted average. On sell: calculates realized PnL and removes if fully sold.
34
+ */
35
+ recordTrade(params: {
36
+ action: 'buy' | 'sell';
37
+ tokenIn: string;
38
+ tokenOut: string;
39
+ amountIn: bigint;
40
+ priceIn: number;
41
+ priceOut: number;
42
+ txHash?: string;
43
+ reasoning?: string;
44
+ success: boolean;
45
+ }): void;
46
+ /**
47
+ * Handle a buy: create or update position with cost-basis weighted average.
48
+ */
49
+ private handleBuy;
50
+ /**
51
+ * Handle a sell: calculate realized PnL and remove position if fully sold.
52
+ * Returns the realized PnL in USD.
53
+ */
54
+ private handleSell;
55
+ /**
56
+ * Sync tracked positions with on-chain balances.
57
+ * Updates currentAmount, detects new tokens (airdrops), removes zeroed positions.
58
+ */
59
+ syncBalances(balances: Record<string, bigint>, prices: Record<string, number>): void;
60
+ /** Get all tracked positions */
61
+ getPositions(): TrackedPosition[];
62
+ /** Get a single position by token address */
63
+ getPosition(token: string): TrackedPosition | undefined;
64
+ /** Get trade history (newest first) */
65
+ getTradeHistory(limit?: number): TradeRecord[];
66
+ /** Get unrealized PnL per position given current prices */
67
+ getUnrealizedPnL(prices: Record<string, number>): Record<string, number>;
68
+ /** Get total unrealized PnL across all positions */
69
+ getTotalUnrealizedPnL(prices: Record<string, number>): number;
70
+ /** Load persisted risk state */
71
+ getRiskState(): RiskState;
72
+ /** Save risk state to persistent store */
73
+ saveRiskState(state: RiskState): void;
74
+ /** Get a compact summary for relay heartbeats */
75
+ getPositionSummary(prices: Record<string, number>): PositionSummary;
76
+ private persist;
77
+ }
78
+
5
79
  declare const LLMProviderSchema: z.ZodEnum<["openai", "anthropic", "google", "deepseek", "mistral", "groq", "together", "ollama", "custom"]>;
6
80
  type LLMProvider = z.infer<typeof LLMProviderSchema>;
7
81
  declare const LLMConfigSchema: z.ZodObject<{
@@ -265,9 +339,9 @@ declare const AgentConfigSchema: z.ZodObject<{
265
339
  }>>;
266
340
  allowedTokens: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
267
341
  }, "strip", z.ZodTypeAny, {
268
- agentId: string | number;
269
342
  name: string;
270
343
  network: "mainnet";
344
+ agentId: string | number;
271
345
  llm: {
272
346
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
273
347
  temperature: number;
@@ -314,8 +388,8 @@ declare const AgentConfigSchema: z.ZodObject<{
314
388
  } | undefined;
315
389
  allowedTokens?: string[] | undefined;
316
390
  }, {
317
- agentId: string | number;
318
391
  name: string;
392
+ agentId: string | number;
319
393
  llm: {
320
394
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
321
395
  model?: string | undefined;
@@ -404,7 +478,99 @@ interface LLMResponse {
404
478
  totalTokens: number;
405
479
  };
406
480
  }
407
- type StrategyFunction = (marketData: MarketData, llm: LLMAdapter, config: AgentConfig) => Promise<TradeSignal[]>;
481
+ /**
482
+ * Persistent key-value store for strategies.
483
+ * Data survives restarts (backed by a JSON file in the agent's data directory).
484
+ * Use this to store entry prices, position metadata, PnL tracking, etc.
485
+ */
486
+ interface StrategyStore {
487
+ get<T = unknown>(key: string): T | undefined;
488
+ set<T = unknown>(key: string, value: T): void;
489
+ delete(key: string): void;
490
+ /** Get all keys in the store */
491
+ keys(): string[];
492
+ }
493
+ /**
494
+ * A tracked spot position with entry price and cost basis.
495
+ * Automatically managed by the runtime's PositionTracker.
496
+ */
497
+ interface TrackedPosition {
498
+ /** Lowercase token address */
499
+ token: string;
500
+ /** Human-readable symbol (e.g., "AERO") — best-effort, may be missing */
501
+ symbol?: string;
502
+ /** USD price at time of first buy */
503
+ entryPrice: number;
504
+ /** Cost-basis weighted average entry price */
505
+ averageEntryPrice: number;
506
+ /** Total USD spent buying this token */
507
+ totalCostBasis: number;
508
+ /** Total token amount ever acquired (in token units, not wei) */
509
+ totalAmountAcquired: number;
510
+ /** Latest known token amount held (in token units, from on-chain balance) */
511
+ currentAmount: number;
512
+ /** Timestamp of first buy (ms) */
513
+ entryTimestamp: number;
514
+ /** Timestamp of last update (ms) */
515
+ lastUpdateTimestamp: number;
516
+ /** Transaction hashes from buy trades (last 10) */
517
+ txHashes: string[];
518
+ }
519
+ /**
520
+ * A recorded trade with metadata and optional realized PnL.
521
+ */
522
+ interface TradeRecord {
523
+ timestamp: number;
524
+ action: 'buy' | 'sell';
525
+ tokenIn: string;
526
+ tokenOut: string;
527
+ /** Serialized bigint (JSON can't encode bigint) */
528
+ amountIn: string;
529
+ /** Estimated USD value of the trade */
530
+ priceUSD: number;
531
+ txHash?: string;
532
+ reasoning?: string;
533
+ /** Realized PnL in USD (only for sells) */
534
+ realizedPnL?: number;
535
+ success: boolean;
536
+ }
537
+ /**
538
+ * Compact position summary for relay heartbeats.
539
+ */
540
+ interface PositionSummary {
541
+ openPositions: number;
542
+ totalUnrealizedPnL: number;
543
+ topPositions: Array<{
544
+ token: string;
545
+ symbol?: string;
546
+ unrealizedPnL: number;
547
+ holdingDuration: number;
548
+ }>;
549
+ recentTrades: number;
550
+ totalRealizedPnL: number;
551
+ }
552
+ /**
553
+ * Context passed to strategies with persistent storage, positions, and trade history.
554
+ */
555
+ interface StrategyContext {
556
+ /** Persistent key-value store (survives restarts) */
557
+ store: StrategyStore;
558
+ /** Agent ID on-chain */
559
+ agentId: number;
560
+ /** Agent wallet address */
561
+ walletAddress: string;
562
+ /** Current open positions with entry prices (auto-populated by runtime) */
563
+ positions?: TrackedPosition[];
564
+ /** Recent trade history, newest first (auto-populated by runtime) */
565
+ tradeHistory?: TradeRecord[];
566
+ /** Position tracker instance for advanced queries (e.g., getUnrealizedPnL) */
567
+ positionTracker?: PositionTracker;
568
+ }
569
+ /**
570
+ * Strategy function signature (user implements this).
571
+ * The 4th parameter (context) is optional for backward compatibility.
572
+ */
573
+ type StrategyFunction = (marketData: MarketData, llm: LLMAdapter, config: AgentConfig, context?: StrategyContext) => Promise<TradeSignal[]>;
408
574
  interface LLMAdapter {
409
575
  chat(messages: LLMMessage[]): Promise<LLMResponse>;
410
576
  getMetadata(): LLMMetadata;
@@ -529,6 +695,8 @@ interface AgentStatusPayload {
529
695
  mode: AgentMode;
530
696
  agentId: string;
531
697
  wallet?: string;
698
+ /** @exagent/agent package version (e.g., "0.1.20") */
699
+ sdkVersion?: string;
532
700
  cycleCount?: number;
533
701
  lastCycleAt?: number;
534
702
  tradingIntervalMs?: number;
@@ -558,6 +726,19 @@ interface AgentStatusPayload {
558
726
  effectiveLeverage: number;
559
727
  pendingRecords: number;
560
728
  };
729
+ /** Spot position tracking summary (auto-populated by PositionTracker) */
730
+ positions?: {
731
+ openPositions: number;
732
+ totalUnrealizedPnL: number;
733
+ topPositions: Array<{
734
+ token: string;
735
+ symbol?: string;
736
+ unrealizedPnL: number;
737
+ holdingDuration: number;
738
+ }>;
739
+ recentTrades: number;
740
+ totalRealizedPnL: number;
741
+ };
561
742
  }
562
743
  interface RelayConfig {
563
744
  enabled: boolean;
@@ -593,9 +774,12 @@ declare class AgentRuntime {
593
774
  private lastCycleAt;
594
775
  private lastPortfolioValue;
595
776
  private lastEthBalance;
777
+ private lastPrices;
596
778
  private processAlive;
597
779
  private riskUniverse;
598
780
  private allowedTokens;
781
+ private strategyContext;
782
+ private positionTracker;
599
783
  private perpClient;
600
784
  private perpSigner;
601
785
  private perpOrders;
@@ -746,6 +930,22 @@ declare function validateConfig(config: RuntimeConfig): void;
746
930
  */
747
931
  declare function createSampleConfig(agentId: number, name: string): AgentConfig;
748
932
 
933
+ /**
934
+ * File-backed persistent key-value store for strategies.
935
+ * Data is saved as JSON in the agent's data directory and survives restarts.
936
+ */
937
+ declare class FileStore implements StrategyStore {
938
+ private data;
939
+ private filePath;
940
+ private dirty;
941
+ constructor(dataDir?: string);
942
+ get<T = unknown>(key: string): T | undefined;
943
+ set<T = unknown>(key: string, value: T): void;
944
+ delete(key: string): void;
945
+ keys(): string[];
946
+ private flush;
947
+ }
948
+
749
949
  /**
750
950
  * Base adapter class with common functionality
751
951
  */
@@ -1116,7 +1316,9 @@ declare class RiskManager {
1116
1316
  */
1117
1317
  filterSignals(signals: TradeSignal[], marketData: MarketData): TradeSignal[];
1118
1318
  /**
1119
- * Validate individual signal against risk limits
1319
+ * Validate individual signal against risk limits.
1320
+ * Sell signals are exempt from position size and minimum value checks —
1321
+ * those guardrails prevent oversized/dust buys, but blocking exits traps capital.
1120
1322
  */
1121
1323
  private validateSignal;
1122
1324
  /**
@@ -1141,6 +1343,23 @@ declare class RiskManager {
1141
1343
  * This prevents protocol fees from triggering circuit breakers.
1142
1344
  */
1143
1345
  updateFees(fees: number): void;
1346
+ /**
1347
+ * Export current risk state for persistence across restarts.
1348
+ */
1349
+ exportState(): {
1350
+ dailyPnL: number;
1351
+ dailyFees: number;
1352
+ lastResetDate: string;
1353
+ };
1354
+ /**
1355
+ * Restore risk state from persistence (called on startup).
1356
+ * Only restores if the saved state is from today — expired state is ignored.
1357
+ */
1358
+ restoreState(state: {
1359
+ dailyPnL: number;
1360
+ dailyFees: number;
1361
+ lastResetDate: string;
1362
+ }): void;
1144
1363
  /**
1145
1364
  * Get current risk status
1146
1365
  * @param portfolioValue - Current portfolio value in USD (needed for accurate loss limit)
@@ -1861,4 +2080,7 @@ declare function decryptEnvFile(encPath: string, passphrase: string): Record<str
1861
2080
  */
1862
2081
  declare function loadSecureEnv(basePath: string, passphrase?: string): boolean;
1863
2082
 
1864
- export { type AccountSummary, type AgentConfig, AgentConfigSchema, type AgentMode, AgentRuntime, type AgentStatusPayload, AnthropicAdapter, BaseLLMAdapter, type CommandType, DeepSeekAdapter, type FillCallback, type FundingCallback, type FundingPayment, GoogleAdapter, GroqAdapter, HYPERLIQUID_DOMAIN, HyperliquidClient, HyperliquidSigner, HyperliquidWebSocket, type LLMAdapter, type LLMConfig, LLMConfigSchema, type LLMMessage, type LLMMetadata, type LLMProvider, LLMProviderSchema, type LLMResponse, type LiquidationCallback, type MarketData, MarketDataService, type MessageLevel, type MessageType, MistralAdapter, OllamaAdapter, type OnboardingStatus, OpenAIAdapter, OrderManager, type OrderResult, type PerpAction, type PerpConfig$1 as PerpConfig, PerpConfigSchema, type PerpFill, type PerpMarketData, PerpOnboarding, type PerpPosition, type PerpStrategyFunction, PerpTradeRecorder, type PerpTradeSignal, type PerpConfig as PerpTradingConfig, PositionManager, type RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyFunction, type StrategyTemplate, TogetherAdapter, TradeExecutor, type TradeSignal, type TradingConfig, TradingConfigSchema, type VaultConfig, VaultConfigSchema, VaultManager, type VaultManagerConfig, type VaultPolicy, VaultPolicySchema, type VaultStatus, createLLMAdapter, createSampleConfig, decryptEnvFile, encryptEnvFile, fillHashToBytes32, fillOidToBytes32, getAllStrategyTemplates, getNextNonce, getStrategyTemplate, loadConfig, loadSecureEnv, loadStrategy, validateConfig, validateStrategy };
2083
+ /** @exagent/agent package version update alongside package.json */
2084
+ declare const AGENT_VERSION = "0.1.21";
2085
+
2086
+ export { AGENT_VERSION, type AccountSummary, type AgentConfig, AgentConfigSchema, type AgentMode, AgentRuntime, type AgentStatusPayload, AnthropicAdapter, BaseLLMAdapter, type CommandType, DeepSeekAdapter, FileStore, type FillCallback, type FundingCallback, type FundingPayment, GoogleAdapter, GroqAdapter, HYPERLIQUID_DOMAIN, HyperliquidClient, HyperliquidSigner, HyperliquidWebSocket, type LLMAdapter, type LLMConfig, LLMConfigSchema, type LLMMessage, type LLMMetadata, type LLMProvider, LLMProviderSchema, type LLMResponse, type LiquidationCallback, type MarketData, MarketDataService, type MessageLevel, type MessageType, MistralAdapter, OllamaAdapter, type OnboardingStatus, OpenAIAdapter, OrderManager, type OrderResult, type PerpAction, type PerpConfig$1 as PerpConfig, PerpConfigSchema, type PerpFill, type PerpMarketData, PerpOnboarding, type PerpPosition, type PerpStrategyFunction, PerpTradeRecorder, type PerpTradeSignal, type PerpConfig as PerpTradingConfig, PositionManager, type PositionSummary, PositionTracker, type RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskState, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyContext, type StrategyFunction, type StrategyStore, type StrategyTemplate, TogetherAdapter, type TrackedPosition, TradeExecutor, type TradeRecord, type TradeSignal, type TradingConfig, TradingConfigSchema, type VaultConfig, VaultConfigSchema, VaultManager, type VaultManagerConfig, type VaultPolicy, VaultPolicySchema, type VaultStatus, createLLMAdapter, createSampleConfig, decryptEnvFile, encryptEnvFile, fillHashToBytes32, fillOidToBytes32, getAllStrategyTemplates, getNextNonce, getStrategyTemplate, loadConfig, loadSecureEnv, loadStrategy, validateConfig, validateStrategy };