@exagent/agent 0.1.20 → 0.1.22

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-Z4N6G5XT.mjs";
9
+ } from "./chunk-EJHDRG5Y.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;
@@ -417,7 +491,66 @@ interface StrategyStore {
417
491
  keys(): string[];
418
492
  }
419
493
  /**
420
- * Context passed to strategies with persistent storage and trade history.
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.
421
554
  */
422
555
  interface StrategyContext {
423
556
  /** Persistent key-value store (survives restarts) */
@@ -426,6 +559,12 @@ interface StrategyContext {
426
559
  agentId: number;
427
560
  /** Agent wallet address */
428
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;
429
568
  }
430
569
  /**
431
570
  * Strategy function signature (user implements this).
@@ -556,6 +695,8 @@ interface AgentStatusPayload {
556
695
  mode: AgentMode;
557
696
  agentId: string;
558
697
  wallet?: string;
698
+ /** @exagent/agent package version (e.g., "0.1.20") */
699
+ sdkVersion?: string;
559
700
  cycleCount?: number;
560
701
  lastCycleAt?: number;
561
702
  tradingIntervalMs?: number;
@@ -585,6 +726,23 @@ interface AgentStatusPayload {
585
726
  effectiveLeverage: number;
586
727
  pendingRecords: number;
587
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
+ };
742
+ /** Current on-chain config hash (for epoch tracking) */
743
+ configHash?: string;
744
+ /** Config hash awaiting owner approval — null/undefined means no pending verification */
745
+ pendingConfigHash?: string | null;
588
746
  }
589
747
  interface RelayConfig {
590
748
  enabled: boolean;
@@ -616,14 +774,18 @@ declare class AgentRuntime {
616
774
  private isRunning;
617
775
  private mode;
618
776
  private configHash;
777
+ private pendingConfigHash;
778
+ private lastConfigCheckAt;
619
779
  private cycleCount;
620
780
  private lastCycleAt;
621
781
  private lastPortfolioValue;
622
782
  private lastEthBalance;
783
+ private lastPrices;
623
784
  private processAlive;
624
785
  private riskUniverse;
625
786
  private allowedTokens;
626
787
  private strategyContext;
788
+ private positionTracker;
627
789
  private perpClient;
628
790
  private perpSigner;
629
791
  private perpOrders;
@@ -634,6 +796,11 @@ declare class AgentRuntime {
634
796
  private perpStrategy;
635
797
  private perpConnected;
636
798
  private perpTradingActive;
799
+ private cachedPerpEquity;
800
+ private cachedPerpUnrealizedPnl;
801
+ private cachedPerpMarginUsed;
802
+ private cachedPerpLeverage;
803
+ private cachedPerpOpenPositions;
637
804
  constructor(config: RuntimeConfig);
638
805
  /**
639
806
  * Initialize the agent runtime
@@ -665,8 +832,14 @@ declare class AgentRuntime {
665
832
  private loadTradingRestrictions;
666
833
  /**
667
834
  * Sync the LLM config hash to chain for epoch tracking.
668
- * If the wallet has insufficient gas, enters a recovery loop
669
- * that waits for the user to fund the wallet.
835
+ *
836
+ * If the trading wallet is NOT the agent owner, the on-chain setConfig
837
+ * call would revert with AgentNotOwner. Instead, we set a pending state
838
+ * and send a message to the command center so the owner can approve it
839
+ * from the website with one click.
840
+ *
841
+ * Until the config is verified on-chain, the agent won't appear on the
842
+ * leaderboard (trades still execute normally).
670
843
  */
671
844
  private syncConfigHash;
672
845
  /**
@@ -685,6 +858,11 @@ declare class AgentRuntime {
685
858
  * Handle a command from the command center
686
859
  */
687
860
  private handleCommand;
861
+ /**
862
+ * Periodically check if the owner has approved the pending config hash.
863
+ * Called from sendRelayStatus at most every 2.5 minutes (timestamp-throttled).
864
+ */
865
+ private checkPendingConfigApproval;
688
866
  /**
689
867
  * Send current status to the relay
690
868
  */
@@ -1187,6 +1365,23 @@ declare class RiskManager {
1187
1365
  * This prevents protocol fees from triggering circuit breakers.
1188
1366
  */
1189
1367
  updateFees(fees: number): void;
1368
+ /**
1369
+ * Export current risk state for persistence across restarts.
1370
+ */
1371
+ exportState(): {
1372
+ dailyPnL: number;
1373
+ dailyFees: number;
1374
+ lastResetDate: string;
1375
+ };
1376
+ /**
1377
+ * Restore risk state from persistence (called on startup).
1378
+ * Only restores if the saved state is from today — expired state is ignored.
1379
+ */
1380
+ restoreState(state: {
1381
+ dailyPnL: number;
1382
+ dailyFees: number;
1383
+ lastResetDate: string;
1384
+ }): void;
1190
1385
  /**
1191
1386
  * Get current risk status
1192
1387
  * @param portfolioValue - Current portfolio value in USD (needed for accurate loss limit)
@@ -1907,4 +2102,7 @@ declare function decryptEnvFile(encPath: string, passphrase: string): Record<str
1907
2102
  */
1908
2103
  declare function loadSecureEnv(basePath: string, passphrase?: string): boolean;
1909
2104
 
1910
- export { 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 RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyContext, type StrategyFunction, type StrategyStore, 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 };
2105
+ /** @exagent/agent package version update alongside package.json */
2106
+ declare const AGENT_VERSION = "0.1.22";
2107
+
2108
+ 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;
@@ -417,7 +491,66 @@ interface StrategyStore {
417
491
  keys(): string[];
418
492
  }
419
493
  /**
420
- * Context passed to strategies with persistent storage and trade history.
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.
421
554
  */
422
555
  interface StrategyContext {
423
556
  /** Persistent key-value store (survives restarts) */
@@ -426,6 +559,12 @@ interface StrategyContext {
426
559
  agentId: number;
427
560
  /** Agent wallet address */
428
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;
429
568
  }
430
569
  /**
431
570
  * Strategy function signature (user implements this).
@@ -556,6 +695,8 @@ interface AgentStatusPayload {
556
695
  mode: AgentMode;
557
696
  agentId: string;
558
697
  wallet?: string;
698
+ /** @exagent/agent package version (e.g., "0.1.20") */
699
+ sdkVersion?: string;
559
700
  cycleCount?: number;
560
701
  lastCycleAt?: number;
561
702
  tradingIntervalMs?: number;
@@ -585,6 +726,23 @@ interface AgentStatusPayload {
585
726
  effectiveLeverage: number;
586
727
  pendingRecords: number;
587
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
+ };
742
+ /** Current on-chain config hash (for epoch tracking) */
743
+ configHash?: string;
744
+ /** Config hash awaiting owner approval — null/undefined means no pending verification */
745
+ pendingConfigHash?: string | null;
588
746
  }
589
747
  interface RelayConfig {
590
748
  enabled: boolean;
@@ -616,14 +774,18 @@ declare class AgentRuntime {
616
774
  private isRunning;
617
775
  private mode;
618
776
  private configHash;
777
+ private pendingConfigHash;
778
+ private lastConfigCheckAt;
619
779
  private cycleCount;
620
780
  private lastCycleAt;
621
781
  private lastPortfolioValue;
622
782
  private lastEthBalance;
783
+ private lastPrices;
623
784
  private processAlive;
624
785
  private riskUniverse;
625
786
  private allowedTokens;
626
787
  private strategyContext;
788
+ private positionTracker;
627
789
  private perpClient;
628
790
  private perpSigner;
629
791
  private perpOrders;
@@ -634,6 +796,11 @@ declare class AgentRuntime {
634
796
  private perpStrategy;
635
797
  private perpConnected;
636
798
  private perpTradingActive;
799
+ private cachedPerpEquity;
800
+ private cachedPerpUnrealizedPnl;
801
+ private cachedPerpMarginUsed;
802
+ private cachedPerpLeverage;
803
+ private cachedPerpOpenPositions;
637
804
  constructor(config: RuntimeConfig);
638
805
  /**
639
806
  * Initialize the agent runtime
@@ -665,8 +832,14 @@ declare class AgentRuntime {
665
832
  private loadTradingRestrictions;
666
833
  /**
667
834
  * Sync the LLM config hash to chain for epoch tracking.
668
- * If the wallet has insufficient gas, enters a recovery loop
669
- * that waits for the user to fund the wallet.
835
+ *
836
+ * If the trading wallet is NOT the agent owner, the on-chain setConfig
837
+ * call would revert with AgentNotOwner. Instead, we set a pending state
838
+ * and send a message to the command center so the owner can approve it
839
+ * from the website with one click.
840
+ *
841
+ * Until the config is verified on-chain, the agent won't appear on the
842
+ * leaderboard (trades still execute normally).
670
843
  */
671
844
  private syncConfigHash;
672
845
  /**
@@ -685,6 +858,11 @@ declare class AgentRuntime {
685
858
  * Handle a command from the command center
686
859
  */
687
860
  private handleCommand;
861
+ /**
862
+ * Periodically check if the owner has approved the pending config hash.
863
+ * Called from sendRelayStatus at most every 2.5 minutes (timestamp-throttled).
864
+ */
865
+ private checkPendingConfigApproval;
688
866
  /**
689
867
  * Send current status to the relay
690
868
  */
@@ -1187,6 +1365,23 @@ declare class RiskManager {
1187
1365
  * This prevents protocol fees from triggering circuit breakers.
1188
1366
  */
1189
1367
  updateFees(fees: number): void;
1368
+ /**
1369
+ * Export current risk state for persistence across restarts.
1370
+ */
1371
+ exportState(): {
1372
+ dailyPnL: number;
1373
+ dailyFees: number;
1374
+ lastResetDate: string;
1375
+ };
1376
+ /**
1377
+ * Restore risk state from persistence (called on startup).
1378
+ * Only restores if the saved state is from today — expired state is ignored.
1379
+ */
1380
+ restoreState(state: {
1381
+ dailyPnL: number;
1382
+ dailyFees: number;
1383
+ lastResetDate: string;
1384
+ }): void;
1190
1385
  /**
1191
1386
  * Get current risk status
1192
1387
  * @param portfolioValue - Current portfolio value in USD (needed for accurate loss limit)
@@ -1907,4 +2102,7 @@ declare function decryptEnvFile(encPath: string, passphrase: string): Record<str
1907
2102
  */
1908
2103
  declare function loadSecureEnv(basePath: string, passphrase?: string): boolean;
1909
2104
 
1910
- export { 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 RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyContext, type StrategyFunction, type StrategyStore, 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 };
2105
+ /** @exagent/agent package version update alongside package.json */
2106
+ declare const AGENT_VERSION = "0.1.22";
2107
+
2108
+ 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 };