intentkit 0.7.5.dev16__py3-none-any.whl → 0.7.5.dev17__py3-none-any.whl

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.

Potentially problematic release.


This version of intentkit might be problematic. Click here for more details.

intentkit/__init__.py CHANGED
@@ -3,7 +3,7 @@
3
3
  A powerful platform for building AI agents with blockchain and cryptocurrency capabilities.
4
4
  """
5
5
 
6
- __version__ = "0.7.5-dev16"
6
+ __version__ = "0.7.5-dev17"
7
7
  __author__ = "hyacinthus"
8
8
  __email__ = "hyacinthus@gmail.com"
9
9
 
intentkit/models/agent.py CHANGED
@@ -142,7 +142,7 @@ class AgentExample(BaseModel):
142
142
  description="Name of the example",
143
143
  max_length=50,
144
144
  json_schema_extra={
145
- "x-group": "examples",
145
+ "x-placeholder": "Add a name for the example",
146
146
  },
147
147
  ),
148
148
  ]
@@ -152,7 +152,7 @@ class AgentExample(BaseModel):
152
152
  description="Description of the example",
153
153
  max_length=200,
154
154
  json_schema_extra={
155
- "x-group": "examples",
155
+ "x-placeholder": "Add a short description for the example",
156
156
  },
157
157
  ),
158
158
  ]
@@ -162,7 +162,7 @@ class AgentExample(BaseModel):
162
162
  description="Example prompt",
163
163
  max_length=2000,
164
164
  json_schema_extra={
165
- "x-group": "examples",
165
+ "x-placeholder": "The prompt will be sent to the agent",
166
166
  },
167
167
  ),
168
168
  ]
@@ -394,6 +394,21 @@ class AgentTable(Base, AgentUserInputColumns):
394
394
  nullable=True,
395
395
  comment="List of example interactions for the agent",
396
396
  )
397
+ public_extra = Column(
398
+ JSON().with_variant(JSONB(), "postgresql"),
399
+ nullable=True,
400
+ comment="Public extra data of the agent",
401
+ )
402
+ deployed_at = Column(
403
+ DateTime(timezone=True),
404
+ nullable=True,
405
+ comment="Timestamp when the agent was deployed",
406
+ )
407
+ public_info_updated_at = Column(
408
+ DateTime(timezone=True),
409
+ nullable=True,
410
+ comment="Timestamp when the agent public info was last updated",
411
+ )
397
412
 
398
413
  # auto timestamp
399
414
  created_at = Column(
@@ -881,6 +896,8 @@ class AgentUpdate(AgentUserInput):
881
896
  # update
882
897
  for key, value in self.model_dump(exclude_unset=True).items():
883
898
  setattr(db_agent, key, value)
899
+ db_agent.version = self.hash()
900
+ db_agent.deployed_at = func.now()
884
901
  await db.commit()
885
902
  await db.refresh(db_agent)
886
903
  return Agent.model_validate(db_agent)
@@ -903,6 +920,7 @@ class AgentUpdate(AgentUserInput):
903
920
  setattr(db_agent, key, value)
904
921
  # version
905
922
  db_agent.version = self.hash()
923
+ db_agent.deployed_at = func.now()
906
924
  await db.commit()
907
925
  await db.refresh(db_agent)
908
926
  return Agent.model_validate(db_agent)
@@ -964,6 +982,7 @@ class AgentCreate(AgentUpdate):
964
982
  try:
965
983
  db_agent = AgentTable(**self.model_dump())
966
984
  db_agent.version = self.hash()
985
+ db_agent.deployed_at = func.now()
967
986
  db.add(db_agent)
968
987
  await db.commit()
969
988
  await db.refresh(db_agent)
@@ -991,7 +1010,6 @@ class AgentPublicInfo(BaseModel):
991
1010
  default=None,
992
1011
  description="Description of the agent, for public view, not contained in prompt",
993
1012
  json_schema_extra={
994
- "x-group": "basic",
995
1013
  "x-placeholder": "Introduce your agent",
996
1014
  },
997
1015
  ),
@@ -1002,7 +1020,6 @@ class AgentPublicInfo(BaseModel):
1002
1020
  default=None,
1003
1021
  description="Link of external website of the agent, if you have one",
1004
1022
  json_schema_extra={
1005
- "x-group": "basic",
1006
1023
  "x-placeholder": "Enter agent external website url",
1007
1024
  "format": "uri",
1008
1025
  },
@@ -1016,7 +1033,6 @@ class AgentPublicInfo(BaseModel):
1016
1033
  max_length=10,
1017
1034
  min_length=1,
1018
1035
  json_schema_extra={
1019
- "x-group": "basic",
1020
1036
  "x-placeholder": "If one day, your agent has it's own token, what will it be?",
1021
1037
  },
1022
1038
  ),
@@ -1028,8 +1044,7 @@ class AgentPublicInfo(BaseModel):
1028
1044
  description="Token address of the agent",
1029
1045
  max_length=42,
1030
1046
  json_schema_extra={
1031
- "x-group": "internal",
1032
- "readOnly": True,
1047
+ "x-placeholder": "The contract address of the agent token",
1033
1048
  },
1034
1049
  ),
1035
1050
  ]
@@ -1040,8 +1055,7 @@ class AgentPublicInfo(BaseModel):
1040
1055
  description="Pool of the agent token",
1041
1056
  max_length=42,
1042
1057
  json_schema_extra={
1043
- "x-group": "internal",
1044
- "readOnly": True,
1058
+ "x-placeholder": "The contract address of the agent token pool",
1045
1059
  },
1046
1060
  ),
1047
1061
  ]
@@ -1052,7 +1066,7 @@ class AgentPublicInfo(BaseModel):
1052
1066
  description="Fee percentage of the agent",
1053
1067
  ge=Decimal("0.0"),
1054
1068
  json_schema_extra={
1055
- "x-group": "basic",
1069
+ "x-placeholder": "Agent will charge service fee according to this ratio.",
1056
1070
  },
1057
1071
  ),
1058
1072
  ]
@@ -1063,7 +1077,7 @@ class AgentPublicInfo(BaseModel):
1063
1077
  description="Introduction of the example",
1064
1078
  max_length=2000,
1065
1079
  json_schema_extra={
1066
- "x-group": "examples",
1080
+ "x-placeholder": "Add a short introduction in new chat",
1067
1081
  },
1068
1082
  ),
1069
1083
  ]
@@ -1074,11 +1088,51 @@ class AgentPublicInfo(BaseModel):
1074
1088
  description="List of example prompts for the agent",
1075
1089
  max_length=6,
1076
1090
  json_schema_extra={
1077
- "x-group": "examples",
1078
1091
  "x-inline": True,
1079
1092
  },
1080
1093
  ),
1081
1094
  ]
1095
+ public_extra: Annotated[
1096
+ Optional[Dict[str, Any]],
1097
+ PydanticField(
1098
+ default=None,
1099
+ description="Public extra data of the agent",
1100
+ ),
1101
+ ]
1102
+
1103
+ async def override(self, agent_id: str) -> "Agent":
1104
+ """Override agent public info with all fields from this instance.
1105
+
1106
+ Args:
1107
+ agent_id: The ID of the agent to override
1108
+
1109
+ Returns:
1110
+ The updated Agent instance
1111
+ """
1112
+ async with get_session() as session:
1113
+ # Get the agent from database
1114
+ result = await session.execute(
1115
+ select(AgentTable).where(AgentTable.id == agent_id)
1116
+ )
1117
+ db_agent = result.scalar_one_or_none()
1118
+
1119
+ if not db_agent:
1120
+ raise IntentKitAPIError(404, "NotFound", f"Agent {agent_id} not found")
1121
+
1122
+ # Update public info fields
1123
+ update_data = self.model_dump()
1124
+ for key, value in update_data.items():
1125
+ if hasattr(db_agent, key):
1126
+ setattr(db_agent, key, value)
1127
+
1128
+ # Update public_info_updated_at timestamp
1129
+ db_agent.public_info_updated_at = func.now()
1130
+
1131
+ # Commit changes
1132
+ await session.commit()
1133
+ await session.refresh(db_agent)
1134
+
1135
+ return Agent.model_validate(db_agent)
1082
1136
 
1083
1137
 
1084
1138
  class Agent(AgentCreate, AgentPublicInfo):
@@ -1124,6 +1178,21 @@ class Agent(AgentCreate, AgentPublicInfo):
1124
1178
  description="Other helper data fields for query, come from agent and agent data"
1125
1179
  ),
1126
1180
  ]
1181
+ deployed_at: Annotated[
1182
+ Optional[datetime],
1183
+ PydanticField(
1184
+ default=None,
1185
+ description="Timestamp when the agent was deployed",
1186
+ ),
1187
+ ]
1188
+ public_info_updated_at: Annotated[
1189
+ Optional[datetime],
1190
+ PydanticField(
1191
+ default=None,
1192
+ description="Timestamp when the agent public info was last updated",
1193
+ ),
1194
+ ]
1195
+
1127
1196
  # auto timestamp
1128
1197
  created_at: Annotated[
1129
1198
  datetime,
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import List, Optional, TypedDict
2
+ from typing import Any, List, Optional, TypedDict
3
3
 
4
4
  from intentkit.abstracts.skill import SkillStoreABC
5
5
  from intentkit.skills.base import SkillConfig, SkillState
@@ -32,10 +32,10 @@ async def get_skills(
32
32
  config: "Config",
33
33
  is_private: bool,
34
34
  store: SkillStoreABC,
35
- **_,
35
+ **_: Any,
36
36
  ) -> list[LiFiBaseTool]:
37
37
  """Get all LiFi skills."""
38
- available_skills = []
38
+ available_skills: list[str] = []
39
39
 
40
40
  # Log configuration
41
41
  logger.info(f"[LiFi_Skills] Initializing with config: {config}")
@@ -57,7 +57,7 @@ async def get_skills(
57
57
  logger.info(f"[LiFi_Skills] Available skills: {available_skills}")
58
58
 
59
59
  # Get each skill using the cached getter
60
- skills = []
60
+ skills: list[LiFiBaseTool] = []
61
61
  for name in available_skills:
62
62
  try:
63
63
  skill = get_lifi_skill(name, store, config)
@@ -2,11 +2,12 @@ import asyncio
2
2
  from typing import Any, Dict, List, Optional, Type
3
3
 
4
4
  import httpx
5
+ from coinbase_agentkit import CdpEvmWalletProvider
5
6
  from pydantic import BaseModel, Field
6
7
  from web3 import Web3
7
8
 
8
9
  from intentkit.abstracts.skill import SkillStoreABC
9
- from intentkit.clients import get_cdp_client
10
+ from intentkit.clients import CdpClient, get_cdp_client
10
11
  from intentkit.skills.lifi.base import LiFiBaseTool
11
12
  from intentkit.skills.lifi.token_quote import TokenQuote
12
13
  from intentkit.skills.lifi.utils import (
@@ -69,7 +70,7 @@ class TokenExecute(LiFiBaseTool):
69
70
  default_slippage: float = 0.03
70
71
  allowed_chains: Optional[List[str]] = None
71
72
  max_execution_time: int = 300
72
- quote_tool: TokenQuote = Field(default=None, exclude=True)
73
+ quote_tool: Optional[TokenQuote] = Field(default=None, exclude=True)
73
74
 
74
75
  def __init__(
75
76
  self,
@@ -77,7 +78,7 @@ class TokenExecute(LiFiBaseTool):
77
78
  default_slippage: float = 0.03,
78
79
  allowed_chains: Optional[List[str]] = None,
79
80
  max_execution_time: int = 300,
80
- ):
81
+ ) -> None:
81
82
  """Initialize the TokenExecute skill with configuration options."""
82
83
  super().__init__(skill_store=skill_store)
83
84
  self.default_slippage = default_slippage
@@ -93,6 +94,8 @@ class TokenExecute(LiFiBaseTool):
93
94
 
94
95
  def _format_quote_result(self, data: Dict[str, Any]) -> str:
95
96
  """Format the quote result in a readable format."""
97
+ if self.quote_tool is None:
98
+ raise RuntimeError("Quote tool is not initialized")
96
99
  # Use the same formatting as token_quote
97
100
  return self.quote_tool._format_quote_result(data)
98
101
 
@@ -103,7 +106,7 @@ class TokenExecute(LiFiBaseTool):
103
106
  from_token: str,
104
107
  to_token: str,
105
108
  from_amount: str,
106
- slippage: float = None,
109
+ slippage: Optional[float] = None,
107
110
  **kwargs,
108
111
  ) -> str:
109
112
  """Execute a token transfer."""
@@ -168,7 +171,9 @@ class TokenExecute(LiFiBaseTool):
168
171
 
169
172
  # Step 3: Execute transaction
170
173
  tx_hash = await self._execute_transfer_transaction(
171
- cdp_wallet_provider, quote_data
174
+ cdp_wallet_provider,
175
+ quote_data,
176
+ from_address,
172
177
  )
173
178
 
174
179
  # Step 4: Monitor status and return result
@@ -180,10 +185,12 @@ class TokenExecute(LiFiBaseTool):
180
185
  self.logger.error("LiFi_Error: %s", str(e))
181
186
  return f"An unexpected error occurred: {str(e)}"
182
187
 
183
- async def _get_cdp_wallet_provider(self, agent_id: str):
188
+ async def _get_cdp_wallet_provider(
189
+ self, agent_id: str
190
+ ) -> CdpEvmWalletProvider | str:
184
191
  """Get CDP wallet provider with error handling."""
185
192
  try:
186
- cdp_client = await get_cdp_client(agent_id, self.skill_store)
193
+ cdp_client: CdpClient = await get_cdp_client(agent_id, self.skill_store)
187
194
  if not cdp_client:
188
195
  return "CDP client not available. Please ensure your agent has CDP wallet configuration."
189
196
 
@@ -207,7 +214,7 @@ class TokenExecute(LiFiBaseTool):
207
214
  from_amount: str,
208
215
  slippage: float,
209
216
  from_address: str,
210
- ) -> Dict[str, Any]:
217
+ ) -> Dict[str, Any] | str:
211
218
  """Get quote from LiFi API."""
212
219
  api_params = build_quote_params(
213
220
  from_chain,
@@ -249,7 +256,7 @@ class TokenExecute(LiFiBaseTool):
249
256
  return data
250
257
 
251
258
  async def _handle_token_approval(
252
- self, wallet_provider, quote_data: Dict[str, Any]
259
+ self, wallet_provider: CdpEvmWalletProvider, quote_data: Dict[str, Any]
253
260
  ) -> Optional[str]:
254
261
  """Handle ERC20 token approval if needed."""
255
262
  estimate = quote_data.get("estimate", {})
@@ -273,13 +280,18 @@ class TokenExecute(LiFiBaseTool):
273
280
  raise Exception(f"Failed to approve token: {str(e)}")
274
281
 
275
282
  async def _execute_transfer_transaction(
276
- self, wallet_provider, quote_data: Dict[str, Any]
283
+ self,
284
+ wallet_provider: CdpEvmWalletProvider,
285
+ quote_data: Dict[str, Any],
286
+ from_address: str,
277
287
  ) -> str:
278
288
  """Execute the main transfer transaction."""
279
289
  transaction_request = quote_data.get("transactionRequest")
280
290
 
281
291
  try:
282
- tx_params = prepare_transaction_params(transaction_request)
292
+ tx_params = prepare_transaction_params(
293
+ transaction_request, wallet_address=from_address
294
+ )
283
295
  self.logger.info(
284
296
  f"Sending transaction to {tx_params['to']} with value {tx_params['value']}"
285
297
  )
@@ -407,7 +419,7 @@ class TokenExecute(LiFiBaseTool):
407
419
 
408
420
  async def _check_and_set_allowance(
409
421
  self,
410
- wallet_provider,
422
+ wallet_provider: CdpEvmWalletProvider,
411
423
  token_address: str,
412
424
  approval_address: str,
413
425
  amount: str,
@@ -65,7 +65,7 @@ class TokenQuote(LiFiBaseTool):
65
65
  skill_store: SkillStoreABC,
66
66
  default_slippage: float = 0.03,
67
67
  allowed_chains: Optional[List[str]] = None,
68
- ):
68
+ ) -> None:
69
69
  """Initialize the TokenQuote skill with configuration options."""
70
70
  super().__init__(skill_store=skill_store)
71
71
  self.default_slippage = default_slippage
@@ -78,7 +78,7 @@ class TokenQuote(LiFiBaseTool):
78
78
  from_token: str,
79
79
  to_token: str,
80
80
  from_amount: str,
81
- slippage: float = None,
81
+ slippage: Optional[float] = None,
82
82
  **kwargs,
83
83
  ) -> str:
84
84
  """Get a quote for token transfer."""
@@ -4,6 +4,7 @@ LiFi Skills Utilities
4
4
  Common utilities and helper functions for LiFi token transfer skills.
5
5
  """
6
6
 
7
+ from decimal import ROUND_DOWN, Decimal, InvalidOperation
7
8
  from typing import Any, Dict, List, Optional, Tuple
8
9
 
9
10
  import httpx
@@ -179,7 +180,7 @@ def handle_api_response(
179
180
  from_chain: str,
180
181
  to_token: str,
181
182
  to_chain: str,
182
- ) -> Tuple[Optional[Dict], Optional[str]]:
183
+ ) -> Tuple[Optional[Dict[str, Any]], Optional[str]]:
183
184
  """
184
185
  Handle LiFi API response and return data or error message.
185
186
 
@@ -293,17 +294,20 @@ def convert_chain_to_id(chain: str) -> int:
293
294
 
294
295
 
295
296
  def convert_amount_to_wei(amount: str, token_symbol: str = "ETH") -> str:
296
- """
297
- Convert human-readable amount to wei format for LiFi API.
297
+ """Convert a token amount into the smallest denomination expected by LiFi."""
298
298
 
299
- Args:
300
- amount: Amount in human readable format (e.g., "0.0015")
301
- token_symbol: Token symbol to determine decimals
299
+ if amount is None:
300
+ raise ValueError("Amount is required")
301
+
302
+ normalized_amount = amount.strip()
303
+ if not normalized_amount:
304
+ raise ValueError("Amount cannot be empty")
305
+
306
+ # If the user already provided an integer amount without a decimal point,
307
+ # assume it is already in the token's smallest denomination.
308
+ if normalized_amount.isdigit():
309
+ return normalized_amount
302
310
 
303
- Returns:
304
- Amount in wei format as string
305
- """
306
- # Default decimals for common tokens
307
311
  token_decimals = {
308
312
  "ETH": 18,
309
313
  "USDC": 6,
@@ -318,13 +322,16 @@ def convert_amount_to_wei(amount: str, token_symbol: str = "ETH") -> str:
318
322
  decimals = token_decimals.get(token_symbol.upper(), 18)
319
323
 
320
324
  try:
321
- # Convert string to float, then to wei
322
- amount_float = float(amount)
323
- amount_wei = int(amount_float * (10**decimals))
324
- return str(amount_wei)
325
- except (ValueError, TypeError):
326
- # If conversion fails, return original amount
327
- return amount
325
+ decimal_amount = Decimal(normalized_amount)
326
+ scaled_amount = (decimal_amount * (Decimal(10) ** decimals)).quantize(
327
+ Decimal("1"),
328
+ rounding=ROUND_DOWN,
329
+ )
330
+ return str(int(scaled_amount))
331
+ except (InvalidOperation, ValueError, TypeError):
332
+ # If conversion fails, fall back to the original value to avoid
333
+ # accidentally submitting an incorrect amount.
334
+ return normalized_amount
328
335
 
329
336
 
330
337
  def build_quote_params(
@@ -350,15 +357,12 @@ def build_quote_params(
350
357
  Raises:
351
358
  ValueError: If chain identifiers are not recognized
352
359
  """
353
- # Convert amount to wei format for API
354
- wei_amount = convert_amount_to_wei(from_amount, from_token)
355
-
356
360
  return {
357
361
  "fromChain": convert_chain_to_id(from_chain),
358
362
  "toChain": convert_chain_to_id(to_chain),
359
363
  "fromToken": from_token,
360
364
  "toToken": to_token,
361
- "fromAmount": wei_amount,
365
+ "fromAmount": convert_amount_to_wei(from_amount, from_token),
362
366
  "fromAddress": from_address or DUMMY_ADDRESS,
363
367
  "slippage": slippage,
364
368
  }
@@ -381,36 +385,85 @@ def is_native_token(token_address: str) -> bool:
381
385
  )
382
386
 
383
387
 
384
- def prepare_transaction_params(transaction_request: Dict[str, Any]) -> Dict[str, Any]:
385
- """
386
- Prepare transaction parameters for CDP wallet provider.
388
+ def _convert_hex_or_decimal(value: Any) -> Optional[int]:
389
+ """Convert LiFi transaction numeric values into integers."""
387
390
 
388
- Args:
389
- transaction_request: Transaction request from LiFi API
391
+ if value is None:
392
+ return None
390
393
 
391
- Returns:
392
- Formatted transaction parameters
394
+ if isinstance(value, int):
395
+ return value
396
+
397
+ if isinstance(value, str):
398
+ stripped = value.strip()
399
+ if not stripped:
400
+ return None
401
+ if stripped.startswith("0x"):
402
+ return int(stripped, 16)
403
+ try:
404
+ return int(Decimal(stripped))
405
+ except (InvalidOperation, ValueError):
406
+ return None
407
+
408
+ return None
409
+
410
+
411
+ def prepare_transaction_params(
412
+ transaction_request: Dict[str, Any],
413
+ wallet_address: Optional[str] = None,
414
+ ) -> Dict[str, Any]:
415
+ """Prepare transaction parameters for the CDP wallet provider."""
393
416
 
394
- Raises:
395
- Exception: If required parameters are missing
396
- """
397
417
  to_address = transaction_request.get("to")
398
- value = transaction_request.get("value", "0")
418
+ value = transaction_request.get("value", "0x0")
399
419
  data = transaction_request.get("data", "0x")
400
420
 
401
421
  if not to_address:
402
- raise Exception("No destination address in transaction request")
422
+ raise Exception("Transaction request is missing destination address")
403
423
 
404
- # Convert value to integer if it's a string
405
- if isinstance(value, str):
406
- value = int(value, 16) if value.startswith("0x") else int(value)
407
-
408
- return {
424
+ tx_params: Dict[str, Any] = {
409
425
  "to": Web3.to_checksum_address(to_address),
410
- "value": value,
411
426
  "data": data,
412
427
  }
413
428
 
429
+ int_value = _convert_hex_or_decimal(value)
430
+ if int_value is not None:
431
+ tx_params["value"] = int_value
432
+
433
+ chain_id = _convert_hex_or_decimal(transaction_request.get("chainId"))
434
+ if chain_id is not None:
435
+ tx_params["chainId"] = chain_id
436
+
437
+ gas_limit = _convert_hex_or_decimal(
438
+ transaction_request.get("gasLimit") or transaction_request.get("gas")
439
+ )
440
+ if gas_limit is not None:
441
+ tx_params["gas"] = gas_limit
442
+
443
+ gas_price = _convert_hex_or_decimal(transaction_request.get("gasPrice"))
444
+ if gas_price is not None:
445
+ tx_params["gasPrice"] = gas_price
446
+
447
+ max_fee_per_gas = _convert_hex_or_decimal(transaction_request.get("maxFeePerGas"))
448
+ if max_fee_per_gas is not None:
449
+ tx_params["maxFeePerGas"] = max_fee_per_gas
450
+
451
+ max_priority_fee_per_gas = _convert_hex_or_decimal(
452
+ transaction_request.get("maxPriorityFeePerGas")
453
+ )
454
+ if max_priority_fee_per_gas is not None:
455
+ tx_params["maxPriorityFeePerGas"] = max_priority_fee_per_gas
456
+
457
+ nonce = _convert_hex_or_decimal(transaction_request.get("nonce"))
458
+ if nonce is not None:
459
+ tx_params["nonce"] = nonce
460
+
461
+ from_address = transaction_request.get("from") or wallet_address
462
+ if from_address:
463
+ tx_params["from"] = Web3.to_checksum_address(from_address)
464
+
465
+ return tx_params
466
+
414
467
 
415
468
  def format_quote_basic_info(data: Dict[str, Any]) -> Dict[str, Any]:
416
469
  """
@@ -464,7 +517,7 @@ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
464
517
 
465
518
  # Extract gas and fee costs
466
519
  gas_costs = estimate.get("gasCosts", [])
467
- fee_costs = []
520
+ fee_costs: List[Dict[str, Any]] = []
468
521
 
469
522
  # Collect fee information from included steps
470
523
  for step in data.get("includedSteps", []):
@@ -476,7 +529,7 @@ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
476
529
  fees_text = ""
477
530
  if fee_costs:
478
531
  fees_text = "**Fees:**\n"
479
- total_fee_usd = 0
532
+ total_fee_usd = 0.0
480
533
  for fee in fee_costs:
481
534
  fee_name = fee.get("name", "Unknown fee")
482
535
  fee_amount = fee.get("amount", "0")
@@ -508,7 +561,7 @@ def format_fees_and_gas(data: Dict[str, Any]) -> Tuple[str, str]:
508
561
  gas_text = ""
509
562
  if gas_costs:
510
563
  gas_text = "**Gas Cost:**\n"
511
- total_gas_usd = 0
564
+ total_gas_usd = 0.0
512
565
  for gas in gas_costs:
513
566
  gas_amount = gas.get("amount", "0")
514
567
  gas_token = gas.get("token", {}).get("symbol", "ETH")
@@ -628,7 +681,7 @@ def get_explorer_url(chain_id: int, tx_hash: str) -> str:
628
681
 
629
682
 
630
683
  def format_transaction_result(
631
- tx_hash: str, chain_id: int, token_info: dict = None
684
+ tx_hash: str, chain_id: int, token_info: Optional[Dict[str, str]] = None
632
685
  ) -> str:
633
686
  """
634
687
  Format transaction result with explorer link.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: intentkit
3
- Version: 0.7.5.dev16
3
+ Version: 0.7.5.dev17
4
4
  Summary: Intent-based AI Agent Platform - Core Package
5
5
  Project-URL: Homepage, https://github.com/crestalnetwork/intentkit
6
6
  Project-URL: Repository, https://github.com/crestalnetwork/intentkit
@@ -1,4 +1,4 @@
1
- intentkit/__init__.py,sha256=nCq4_D7vaKCADBGRl2MWoWd3YHhRu1YKO3bVXKPL618,384
1
+ intentkit/__init__.py,sha256=zzYPe38hldbmSqiTWyKK_F_D4FWBcbvtkt2-n4h0zDU,384
2
2
  intentkit/abstracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  intentkit/abstracts/agent.py,sha256=108gb5W8Q1Sy4G55F2_ZFv2-_CnY76qrBtpIr0Oxxqk,1489
4
4
  intentkit/abstracts/api.py,sha256=ZUc24vaQvQVbbjznx7bV0lbbQxdQPfEV8ZxM2R6wZWo,166
@@ -21,7 +21,7 @@ intentkit/core/credit.py,sha256=b4f4T6G6eeBTMe0L_r8awWtXgUnqiog4IUaymDPYym0,7558
21
21
  intentkit/core/engine.py,sha256=Ecwt-ZuPrJmFcN69P6dsEs_NeCyp52HJ9TL_8X2cP34,36086
22
22
  intentkit/core/node.py,sha256=7h9zgDSd928bzUi3m3EZnKkhbwqlbRAQUr_uz7gKB5Y,8880
23
23
  intentkit/core/prompt.py,sha256=idNx1ono4Maz2i6IBKfaKOBBbEQiWbaSxr2Eb1vZTI4,15482
24
- intentkit/models/agent.py,sha256=pZUbIRd56Ti1irCTH6yOf7SXskqoeBENe8aWG98sZ5k,65133
24
+ intentkit/models/agent.py,sha256=yXulE5vlOOku6DSiid_Jp6OCfqy3-XN47rmKax5xX1w,67582
25
25
  intentkit/models/agent_data.py,sha256=5zq3EPKnygT2P1OHc2IfEmL8hXkjeBND6sJ0JJsvQJg,28370
26
26
  intentkit/models/agent_public.json,sha256=0X8Bd2WOobDJLsok8avWNzmzu4uvKSGEyy6Myn53eT4,2802
27
27
  intentkit/models/agent_schema.json,sha256=hFGUE57JIiN8V4olgLf2LBXPejA2QLiQoFc6riM1UFo,17139
@@ -253,13 +253,13 @@ intentkit/skills/http/post.py,sha256=Rh3Zclvri_s1gSpCFzjXOoQQns2Clp4JWEcDb4E_FFc
253
253
  intentkit/skills/http/put.py,sha256=PKe7XuQcomsBrh8XgpkltQpOH-KGO1hJeIo0pKGaVpw,4161
254
254
  intentkit/skills/http/schema.json,sha256=zryLRzGm4_BpBZmzlmNlyHmWrPFu3bdv0yx0sqrCwa4,2074
255
255
  intentkit/skills/lifi/README.md,sha256=7Cjn6-VDzXIeNNlt8aXrwErEOk22ofPzk4hCubyT3vQ,8355
256
- intentkit/skills/lifi/__init__.py,sha256=m7fim2BabigaWsv1VNr0TtVlvkNbHwvFvohPZTQHw_8,4944
256
+ intentkit/skills/lifi/__init__.py,sha256=U2zOLqnMNS9q-5lDhVOOU2_mch0JowLor5ktneaTa0k,4985
257
257
  intentkit/skills/lifi/base.py,sha256=8MrF3vJmh0ZmVHoGZ51K73u0o9AljVV1bch6ji9rS5E,584
258
258
  intentkit/skills/lifi/lifi.png,sha256=CtFw-pbaD51BqduIOu5zNeGGBigw0e_OQLsZJe3XnsE,7311
259
259
  intentkit/skills/lifi/schema.json,sha256=Hzy4s8LOoI-JOMyo-JAVWqylFFbS6SRAaL7hOmA2_4k,2579
260
- intentkit/skills/lifi/token_execute.py,sha256=lnoRfo17vSXF6-0bfzLliGt_xfkeuCgknCMafjC1Fog,17179
261
- intentkit/skills/lifi/token_quote.py,sha256=p6QrzbxHmKtSMxat_9x3BYu2YP3US1I24HyXjeVaLQs,6874
262
- intentkit/skills/lifi/utils.py,sha256=bGefOONC_FtdQ8EGLGwfyBOE0l0TGkFzoWZ_hBgom04,19084
260
+ intentkit/skills/lifi/token_execute.py,sha256=cqaMjKebatW6VjTsegald97LIj88MMIhxg44rTfToWM,17654
261
+ intentkit/skills/lifi/token_quote.py,sha256=OyuRhNrjU0QbDfzyrmU6mEBtBed0xfwldv1R1AoeQvA,6892
262
+ intentkit/skills/lifi/utils.py,sha256=gYd7quenIyqwPl7FOvgGnehmtz4dcf_IiHPWGORPAMM,21057
263
263
  intentkit/skills/moralis/README.md,sha256=zrXuTBBruB4XmQln3ELFagsO1eDnaZnCKqvEdvZPl94,13253
264
264
  intentkit/skills/moralis/__init__.py,sha256=n72KfGiehQ1HSQiOrMcNIUwnaFpwg2TwKeN9zxCkaaE,3301
265
265
  intentkit/skills/moralis/api.py,sha256=48MGdHYF29Q77OQOGdAVWFogyuZQ3SbmfrJW6mUxoT0,7935
@@ -450,7 +450,7 @@ intentkit/utils/random.py,sha256=DymMxu9g0kuQLgJUqalvgksnIeLdS-v0aRk5nQU0mLI,452
450
450
  intentkit/utils/s3.py,sha256=A8Nsx5QJyLsxhj9g7oHNy2-m24tjQUhC9URm8Qb1jFw,10057
451
451
  intentkit/utils/slack_alert.py,sha256=s7UpRgyzLW7Pbmt8cKzTJgMA9bm4EP-1rQ5KXayHu6E,2264
452
452
  intentkit/utils/tx.py,sha256=2yLLGuhvfBEY5n_GJ8wmIWLCzn0FsYKv5kRNzw_sLUI,1454
453
- intentkit-0.7.5.dev16.dist-info/METADATA,sha256=X35JNufFbTXZDWVHPidXBIuQ5jSwEkSIHt2IiUlEwHg,6360
454
- intentkit-0.7.5.dev16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
455
- intentkit-0.7.5.dev16.dist-info/licenses/LICENSE,sha256=Bln6DhK-LtcO4aXy-PBcdZv2f24MlJFm_qn222biJtE,1071
456
- intentkit-0.7.5.dev16.dist-info/RECORD,,
453
+ intentkit-0.7.5.dev17.dist-info/METADATA,sha256=hm_zrcP_dUGiGA9ezniXpGahyR9Io4Aj4YHW_9Mtnrs,6360
454
+ intentkit-0.7.5.dev17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
455
+ intentkit-0.7.5.dev17.dist-info/licenses/LICENSE,sha256=Bln6DhK-LtcO4aXy-PBcdZv2f24MlJFm_qn222biJtE,1071
456
+ intentkit-0.7.5.dev17.dist-info/RECORD,,