intentkit 0.6.11.dev3__py3-none-any.whl → 0.6.11.dev4__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.6.11-dev3"
6
+ __version__ = "0.6.11-dev4"
7
7
  __author__ = "hyacinthus"
8
8
  __email__ = "hyacinthus@gmail.com"
9
9
 
intentkit/clients/cdp.py CHANGED
@@ -17,6 +17,7 @@ from intentkit.models.agent import Agent
17
17
  from intentkit.models.agent_data import AgentData
18
18
 
19
19
  _clients: Dict[str, "CdpClient"] = {}
20
+ _origin_cdp_client: Optional[OriginCdpClient] = None
20
21
 
21
22
  logger = logging.getLogger(__name__)
22
23
 
@@ -56,6 +57,24 @@ def bip39_seed_to_eth_keys(seed_hex: str) -> Dict[str, str]:
56
57
  }
57
58
 
58
59
 
60
+ def get_origin_cdp_client(skill_store: SkillStoreABC) -> OriginCdpClient:
61
+ global _origin_cdp_client
62
+ if _origin_cdp_client:
63
+ return _origin_cdp_client
64
+
65
+ # Get credentials from skill store system config
66
+ api_key_id = skill_store.get_system_config("cdp_api_key_id")
67
+ api_key_secret = skill_store.get_system_config("cdp_api_key_secret")
68
+ wallet_secret = skill_store.get_system_config("cdp_wallet_secret")
69
+
70
+ _origin_cdp_client = OriginCdpClient(
71
+ api_key_id=api_key_id,
72
+ api_key_secret=api_key_secret,
73
+ wallet_secret=wallet_secret,
74
+ )
75
+ return _origin_cdp_client
76
+
77
+
59
78
  class CdpClient:
60
79
  def __init__(self, agent_id: str, skill_store: SkillStoreABC) -> None:
61
80
  self._agent_id = agent_id
@@ -81,11 +100,7 @@ class CdpClient:
81
100
  # new agent or address not migrated yet
82
101
  if not address:
83
102
  # create cdp client for later use
84
- cdp_client = OriginCdpClient(
85
- api_key_id=api_key_id,
86
- api_key_secret=api_key_secret,
87
- wallet_secret=wallet_secret,
88
- )
103
+ cdp_client = get_origin_cdp_client(self._skill_store)
89
104
  # try migrating from v1 cdp_wallet_data
90
105
  if agent_data.cdp_wallet_data:
91
106
  wallet_data = json.loads(agent_data.cdp_wallet_data)
@@ -115,8 +130,7 @@ class CdpClient:
115
130
  address = new_account.address
116
131
  logger.info("Created new wallet: %s", address)
117
132
 
118
- # close client
119
- await cdp_client.close()
133
+ # do not close cached global client
120
134
  # now it should be created or migrated, store it
121
135
  agent_data.evm_wallet_address = address
122
136
  await agent_data.save()
intentkit/models/llm.py CHANGED
@@ -628,9 +628,10 @@ class DeepseekLLM(LLMModel):
628
628
  info = await self.model_info()
629
629
 
630
630
  kwargs = {
631
- "model_name": self.model_name,
632
- "openai_api_key": config.deepseek_api_key,
631
+ "model": self.model_name,
632
+ "api_key": config.deepseek_api_key,
633
633
  "timeout": info.timeout,
634
+ "max_retries": 3,
634
635
  }
635
636
 
636
637
  # Add optional parameters based on model support
@@ -644,7 +645,7 @@ class DeepseekLLM(LLMModel):
644
645
  kwargs["presence_penalty"] = self.presence_penalty
645
646
 
646
647
  if info.api_base:
647
- kwargs["openai_api_base"] = info.api_base
648
+ kwargs["api_base"] = info.api_base
648
649
 
649
650
  return ChatDeepSeek(**kwargs)
650
651
 
@@ -6,6 +6,8 @@ from typing import TypedDict
6
6
  from intentkit.abstracts.skill import SkillStoreABC
7
7
  from intentkit.skills.base import SkillConfig, SkillState
8
8
  from intentkit.skills.xmtp.base import XmtpBaseTool
9
+ from intentkit.skills.xmtp.price import XmtpGetSwapPrice
10
+ from intentkit.skills.xmtp.swap import XmtpSwap
9
11
  from intentkit.skills.xmtp.transfer import XmtpTransfer
10
12
 
11
13
  # Cache skills at the module level, because they are stateless
@@ -16,6 +18,8 @@ logger = logging.getLogger(__name__)
16
18
 
17
19
  class SkillStates(TypedDict):
18
20
  xmtp_transfer: SkillState
21
+ xmtp_swap: SkillState
22
+ xmtp_get_swap_price: SkillState
19
23
 
20
24
 
21
25
  class Config(SkillConfig):
@@ -77,6 +81,18 @@ def get_xmtp_skill(
77
81
  skill_store=store,
78
82
  )
79
83
  return _cache[name]
84
+ elif name == "xmtp_swap":
85
+ if name not in _cache:
86
+ _cache[name] = XmtpSwap(
87
+ skill_store=store,
88
+ )
89
+ return _cache[name]
90
+ elif name == "xmtp_get_swap_price":
91
+ if name not in _cache:
92
+ _cache[name] = XmtpGetSwapPrice(
93
+ skill_store=store,
94
+ )
95
+ return _cache[name]
80
96
  else:
81
97
  logger.warning(f"Unknown XMTP skill: {name}")
82
98
  return None
@@ -0,0 +1,72 @@
1
+ from typing import Literal, Type
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from intentkit.clients.cdp import get_origin_cdp_client
6
+ from intentkit.skills.xmtp.base import XmtpBaseTool
7
+
8
+
9
+ class SwapPriceInput(BaseModel):
10
+ """Input for querying swap price via CDP."""
11
+
12
+ from_token: str = Field(description="The contract address to swap from")
13
+ to_token: str = Field(description="The contract address to swap to")
14
+ from_amount: str = Field(description="Input amount in smallest units (as string)")
15
+ from_address: str = Field(
16
+ description="The address where the from_token balance is located"
17
+ )
18
+
19
+
20
+ class XmtpGetSwapPrice(XmtpBaseTool):
21
+ """Skill for fetching indicative swap price using CDP SDK."""
22
+
23
+ name: str = "xmtp_get_swap_price"
24
+ description: str = "Get an indicative swap price/quote for token pair and amount on Base networks using CDP."
25
+ response_format: Literal["content", "content_and_artifact"] = "content"
26
+ args_schema: Type[BaseModel] = SwapPriceInput
27
+
28
+ async def _arun(
29
+ self,
30
+ from_token: str,
31
+ to_token: str,
32
+ from_amount: str,
33
+ from_address: str,
34
+ ) -> str:
35
+ context = self.get_context()
36
+ agent = context.agent
37
+
38
+ if agent.network_id not in ("base-mainnet", "base-sepolia"):
39
+ raise ValueError(
40
+ f"Swap price only supported on base-mainnet or base-sepolia. Current: {agent.network_id}"
41
+ )
42
+
43
+ network_for_cdp = {
44
+ "base-mainnet": "base",
45
+ "base-sepolia": "base-sepolia",
46
+ }[agent.network_id]
47
+
48
+ cdp_client = get_origin_cdp_client(self.skill_store)
49
+ # Note: Don't use async with context manager as get_origin_cdp_client returns a managed global client
50
+ price = await cdp_client.evm.get_swap_price(
51
+ from_token=from_token,
52
+ to_token=to_token,
53
+ from_amount=str(from_amount),
54
+ network=network_for_cdp,
55
+ taker=from_address,
56
+ )
57
+
58
+ # Try to format a readable message from typical fields
59
+ try:
60
+ amount_out = getattr(price, "to_amount", None) or (
61
+ price.get("to_amount") if isinstance(price, dict) else None
62
+ )
63
+ route = getattr(price, "route", None) or (
64
+ price.get("route") if isinstance(price, dict) else None
65
+ )
66
+ route_str = f" via {route}" if route else ""
67
+ if amount_out:
68
+ return f"Estimated output: {amount_out} units of {to_token}{route_str} on {agent.network_id}."
69
+ except Exception:
70
+ pass
71
+
72
+ return f"Swap price result (raw): {price}"
@@ -0,0 +1,204 @@
1
+ from typing import List, Tuple, Type
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from intentkit.clients.cdp import get_origin_cdp_client
6
+ from intentkit.models.chat import ChatMessageAttachment, ChatMessageAttachmentType
7
+ from intentkit.skills.xmtp.base import XmtpBaseTool
8
+
9
+
10
+ class SwapInput(BaseModel):
11
+ """Input for XMTP swap skill.
12
+
13
+ This creates an unsigned swap transaction attachment using CDP swap quote
14
+ that a user can review and sign via XMTP wallet_sendCalls.
15
+ """
16
+
17
+ from_address: str = Field(description="The sender address for the swap")
18
+ from_token: str = Field(
19
+ description="The contract address of the token to swap from"
20
+ )
21
+ to_token: str = Field(description="The contract address of the token to swap to")
22
+ from_amount: str = Field(
23
+ description="The input amount in the smallest unit of from_token (as string)"
24
+ )
25
+ slippage_bps: int = Field(
26
+ default=100,
27
+ description="Maximum slippage in basis points (100 = 1%). Defaults to 100.",
28
+ )
29
+
30
+
31
+ class XmtpSwap(XmtpBaseTool):
32
+ """Skill for creating XMTP swap transactions using CDP swap quote.
33
+
34
+ Generates a wallet_sendCalls transaction request to perform a token swap.
35
+ May include an ERC20 approval call followed by the router swap call.
36
+ Supports Base mainnet and Base Sepolia testnet.
37
+ """
38
+
39
+ name: str = "xmtp_swap"
40
+ description: str = (
41
+ "Create an XMTP transaction request for swapping tokens on Base using CDP swap quote. "
42
+ "Returns a wallet_sendCalls payload that can include an optional approval call and the swap call. "
43
+ "Only supports base-mainnet and base-sepolia."
44
+ )
45
+ args_schema: Type[BaseModel] = SwapInput
46
+
47
+ async def _arun(
48
+ self,
49
+ from_address: str,
50
+ from_token: str,
51
+ to_token: str,
52
+ from_amount: str,
53
+ slippage_bps: int = 100,
54
+ ) -> Tuple[str, List[ChatMessageAttachment]]:
55
+ # Resolve agent context and target network
56
+ context = self.get_context()
57
+ agent = context.agent
58
+
59
+ # ChainId mapping for XMTP wallet_sendCalls
60
+ chain_id_hex_by_network = {
61
+ "base-mainnet": "0x2105", # 8453
62
+ "base-sepolia": "0x14A34", # 84532
63
+ }
64
+
65
+ if agent.network_id not in chain_id_hex_by_network:
66
+ raise ValueError(
67
+ f"XMTP swap only supports base-mainnet or base-sepolia. Current agent network: {agent.network_id}"
68
+ )
69
+
70
+ chain_id_hex = chain_id_hex_by_network[agent.network_id]
71
+
72
+ # CDP network mapping for swap quote API
73
+ # Reference: CDP SDK examples for swap quote and price
74
+ # https://github.com/coinbase/cdp-sdk/blob/main/examples/python/evm/swaps/create_swap_quote.py
75
+ network_for_cdp = {
76
+ "base-mainnet": "base",
77
+ "base-sepolia": "base-sepolia",
78
+ }[agent.network_id]
79
+
80
+ # Get CDP client from global origin helper (server-side credentials)
81
+ cdp_client = get_origin_cdp_client(self.skill_store)
82
+
83
+ # Call CDP to create swap quote and extract call datas
84
+ # Be permissive with response shape across SDK versions
85
+ try:
86
+ # Attempt the canonical method per CDP SDK examples
87
+ # create_swap_quote(from_token, to_token, from_amount, network, taker, slippage_bps, signer_address)
88
+ # Note: Don't use async with context manager as get_origin_cdp_client returns a managed global client
89
+ quote = await cdp_client.evm.create_swap_quote(
90
+ from_token=from_token,
91
+ to_token=to_token,
92
+ from_amount=str(from_amount),
93
+ network=network_for_cdp,
94
+ taker=from_address,
95
+ slippage_bps=slippage_bps,
96
+ signer_address=from_address,
97
+ )
98
+ except Exception as e: # pragma: no cover - defensive
99
+ raise ValueError(f"Failed to create swap quote via CDP: {e!s}")
100
+
101
+ # Extract approval and swap calls if present (prefer QuoteSwapResult canonical fields)
102
+ calls: list[dict] = []
103
+
104
+ def to_xmtp_call(call_like, description: str) -> dict | None:
105
+ if not call_like:
106
+ return None
107
+ # Attributes on QuoteSwapResult call-like objects
108
+ to_value = getattr(call_like, "to", None) or getattr(
109
+ call_like, "target", None
110
+ )
111
+ data_value = getattr(call_like, "data", None) or getattr(
112
+ call_like, "calldata", None
113
+ )
114
+ value_value = getattr(call_like, "value", None)
115
+ # Dict fallback
116
+ if isinstance(call_like, dict):
117
+ to_value = to_value or call_like.get("to") or call_like.get("target")
118
+ data_value = (
119
+ data_value or call_like.get("data") or call_like.get("calldata")
120
+ )
121
+ value_value = value_value or call_like.get("value")
122
+ if not to_value or not data_value:
123
+ return None
124
+ value_hex = (
125
+ value_value
126
+ if isinstance(value_value, str) and value_value.startswith("0x")
127
+ else (hex(int(value_value)) if value_value is not None else "0x0")
128
+ )
129
+ data_hex = (
130
+ data_value if str(data_value).startswith("0x") else f"0x{data_value}"
131
+ )
132
+ return {
133
+ "to": to_value,
134
+ "value": value_hex,
135
+ "data": data_hex,
136
+ "metadata": {
137
+ "description": description,
138
+ "transactionType": "swap_step",
139
+ "fromToken": from_token,
140
+ "toToken": to_token,
141
+ "amountIn": from_amount,
142
+ "slippageBps": slippage_bps,
143
+ },
144
+ }
145
+
146
+ # Heuristics for various response shapes
147
+ approval = (
148
+ getattr(quote, "approval", None)
149
+ or getattr(quote, "approval_call_data", None)
150
+ or (quote.get("approval") if isinstance(quote, dict) else None)
151
+ or (quote.get("approval_call_data") if isinstance(quote, dict) else None)
152
+ )
153
+ approval_xmtp = to_xmtp_call(approval, "Approve token spending if required")
154
+ if approval_xmtp:
155
+ calls.append(approval_xmtp)
156
+
157
+ swap_call = (
158
+ getattr(quote, "swap", None)
159
+ or getattr(quote, "swap_call_data", None)
160
+ or (quote.get("swap") if isinstance(quote, dict) else None)
161
+ or (quote.get("swap_call_data") if isinstance(quote, dict) else None)
162
+ )
163
+ swap_xmtp = to_xmtp_call(swap_call, "Execute token swap")
164
+ if swap_xmtp:
165
+ calls.append(swap_xmtp)
166
+
167
+ if not calls:
168
+ # As a final fallback, some responses may provide a generic 'calls' list
169
+ raw_calls = getattr(quote, "calls", None) or (
170
+ quote.get("calls") if isinstance(quote, dict) else None
171
+ )
172
+ if isinstance(raw_calls, list):
173
+ for idx, c in enumerate(raw_calls):
174
+ x = to_xmtp_call(c, f"Swap step {idx + 1}")
175
+ if x:
176
+ calls.append(x)
177
+
178
+ if not calls:
179
+ raise ValueError(
180
+ "CDP swap quote did not return callable steps compatible with wallet_sendCalls"
181
+ )
182
+
183
+ # Build XMTP wallet_sendCalls payload
184
+ wallet_send_calls = {
185
+ "version": "1.0",
186
+ "from": from_address,
187
+ "chainId": chain_id_hex,
188
+ "calls": calls,
189
+ }
190
+
191
+ # Attachment for chat
192
+ attachment: ChatMessageAttachment = {
193
+ "type": ChatMessageAttachmentType.XMTP,
194
+ "url": None,
195
+ "json": wallet_send_calls,
196
+ }
197
+
198
+ # Human-friendly message
199
+ content_message = (
200
+ f"I created a swap transaction request to exchange {from_amount} units of {from_token} "
201
+ f"for {to_token} on {agent.network_id}. Review and sign to execute."
202
+ )
203
+
204
+ return content_message, [attachment]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: intentkit
3
- Version: 0.6.11.dev3
3
+ Version: 0.6.11.dev4
4
4
  Summary: Intent-based AI Agent Platform - Core Package
5
5
  Project-URL: Homepage, https://github.com/crestal-network/intentkit
6
6
  Project-URL: Repository, https://github.com/crestal-network/intentkit
@@ -1,4 +1,4 @@
1
- intentkit/__init__.py,sha256=L3MeNqTVKVhtQpOK1Tq4ZEIq_bUh-6E7orxvxP36kA4,384
1
+ intentkit/__init__.py,sha256=-53Aff4TSlAzOvvA-Mqb5kjEZiXmV8lAoboQ8zJCUm0,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
@@ -8,7 +8,7 @@ intentkit/abstracts/graph.py,sha256=8jkQnm6pnUAyiU7w5dpe2RuSLvpXBN17NGqZGEuc0ys,
8
8
  intentkit/abstracts/skill.py,sha256=cIJ6BkASD31U1IEkE8rdAawq99w_xsg0lt3oalqa1ZA,5071
9
9
  intentkit/abstracts/twitter.py,sha256=cEtP7ygR_b-pHdc9i8kBuyooz1cPoGUGwsBHDpowJyY,1262
10
10
  intentkit/clients/__init__.py,sha256=sQ_6_bRC2MPWLPH-skQ3qsEe8ce-dUGL7i8VJOautHg,298
11
- intentkit/clients/cdp.py,sha256=_CkvnBkzdq7-sFMGct4lz85FpaOoHxOGstWubhClzrA,5921
11
+ intentkit/clients/cdp.py,sha256=VaIFzgfqpq5H4bHbFBe8UPabhkwe8s5pge_P5FssGqU,6453
12
12
  intentkit/clients/twitter.py,sha256=Lfa7srHOFnY96SXcElW0jfg7XKS_WliWnXjPZEe6SQc,18976
13
13
  intentkit/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  intentkit/config/config.py,sha256=Q3xsxRvn0RxcPpAOHbHcPumTRlJQMcE_pfnPfAl6aXw,8553
@@ -32,7 +32,7 @@ intentkit/models/credit.py,sha256=bcasHyrCwforLGrH8ZWEvN6y6ml7NeAFrGl8cfqvqbI,42
32
32
  intentkit/models/db.py,sha256=nuDX6NEtnfD5YLr2iVpAAXsgHbSpG5diqfLC-PkHsA4,4406
33
33
  intentkit/models/db_mig.py,sha256=vT6Tanm-BHC2T7dTztuB1UG494EFBAlHADKsNzR6xaQ,3577
34
34
  intentkit/models/generator.py,sha256=lyZu9U9rZUGkqd_QT5SAhay9DY358JJY8EhDSpN8I1M,10298
35
- intentkit/models/llm.py,sha256=VCSeK_AfyQDbkYO2ZjcF0A2JxxheqmW1T92Ow08lLCk,26917
35
+ intentkit/models/llm.py,sha256=BgmtW6Vq7ZLZN33HG37VWGg_e8YlF8GxrO9WEvKCE-A,26928
36
36
  intentkit/models/redis.py,sha256=UoN8jqLREO1VO9_w6m-JhldpP19iEHj4TiGVCMutQW4,3702
37
37
  intentkit/models/skill.py,sha256=h_2wtKEbYE29TLsMdaSnjfOv6vXY6GwMU_abw-ONX28,16374
38
38
  intentkit/models/user.py,sha256=P7l6LOsZmXZ5tDPTczTbqDtDB_MKc_9_ddZkAB2npPk,9288
@@ -388,9 +388,11 @@ intentkit/skills/web_scraper/scrape_and_index.py,sha256=Xi1BmUd-LgmJXnQOgSz82baq
388
388
  intentkit/skills/web_scraper/utils.py,sha256=feGBTMWqpkoY7RFy2xDHVs5y8c2h8-XZ111jRo6cC3k,23349
389
389
  intentkit/skills/web_scraper/website_indexer.py,sha256=rTqCx-XzJtMlZnyGImPGWRdLpS13_exXc3lQu9EDjQM,17925
390
390
  intentkit/skills/xmtp/README.md,sha256=7y3ny77l5WUI758Q3xip1akFEgBdbibkwZjeJDu5MwE,2963
391
- intentkit/skills/xmtp/__init__.py,sha256=pG56rMjtC85x_R_YadlKyTnWYJe-jgwW4xolilcVCkA,2003
391
+ intentkit/skills/xmtp/__init__.py,sha256=inpuVqA9i98g8VIqqfC28PbfveozSukbEHOLbOMYv14,2538
392
392
  intentkit/skills/xmtp/base.py,sha256=85ZEuNLJmI_NmBPkbvDXQrNvJNG8dp9MbcbQYQQ3QZ8,430
393
+ intentkit/skills/xmtp/price.py,sha256=LqM3tWiW42bYIRqfvsZUvYpG5H5ife3WUhR-pxiS9I8,2648
393
394
  intentkit/skills/xmtp/schema.json,sha256=p8lPnzAzsW4yrPcuEv48Tv6qj3ouSNEFjw7YSxDZ3ok,1558
395
+ intentkit/skills/xmtp/swap.py,sha256=f_cl8NMAWJ3q1t8_y1Bs8P6o78MzWb7Z85sIqLfAz-A,8082
394
396
  intentkit/skills/xmtp/transfer.py,sha256=hlkUu2UkTKx1Y7mUrBT4OjkWuzDK8DwfNpxYEwdOFhc,5860
395
397
  intentkit/skills/xmtp/xmtp.png,sha256=vQzT-71zIb8aPodg-GkGSQbBnjGAPczWGm3es2ZkJe8,6681
396
398
  intentkit/utils/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
@@ -401,7 +403,7 @@ intentkit/utils/random.py,sha256=DymMxu9g0kuQLgJUqalvgksnIeLdS-v0aRk5nQU0mLI,452
401
403
  intentkit/utils/s3.py,sha256=9trQNkKQ5VgxWsewVsV8Y0q_pXzGRvsCYP8xauyUYkg,8549
402
404
  intentkit/utils/slack_alert.py,sha256=s7UpRgyzLW7Pbmt8cKzTJgMA9bm4EP-1rQ5KXayHu6E,2264
403
405
  intentkit/utils/tx.py,sha256=2yLLGuhvfBEY5n_GJ8wmIWLCzn0FsYKv5kRNzw_sLUI,1454
404
- intentkit-0.6.11.dev3.dist-info/METADATA,sha256=h3k4XpLhiazptmdImgGO9vWD0JB920dPjVDEInDonHc,6414
405
- intentkit-0.6.11.dev3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
406
- intentkit-0.6.11.dev3.dist-info/licenses/LICENSE,sha256=Bln6DhK-LtcO4aXy-PBcdZv2f24MlJFm_qn222biJtE,1071
407
- intentkit-0.6.11.dev3.dist-info/RECORD,,
406
+ intentkit-0.6.11.dev4.dist-info/METADATA,sha256=-KB_L3wx69B4fvZdiDdpS3adppof0sR-G8-xDU_m6kM,6414
407
+ intentkit-0.6.11.dev4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
408
+ intentkit-0.6.11.dev4.dist-info/licenses/LICENSE,sha256=Bln6DhK-LtcO4aXy-PBcdZv2f24MlJFm_qn222biJtE,1071
409
+ intentkit-0.6.11.dev4.dist-info/RECORD,,