intentkit 0.6.17.dev2__py3-none-any.whl → 0.6.18__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.17-dev2"
6
+ __version__ = "0.6.18"
7
7
  __author__ = "hyacinthus"
8
8
  __email__ = "hyacinthus@gmail.com"
9
9
 
@@ -547,6 +547,10 @@
547
547
  "lifi": {
548
548
  "title": "LiFi",
549
549
  "$ref": "../skills/lifi/schema.json"
550
+ },
551
+ "casino": {
552
+ "title": "Casino",
553
+ "$ref": "../skills/casino/schema.json"
550
554
  }
551
555
  }
552
556
  },
intentkit/skills/base.py CHANGED
@@ -2,7 +2,6 @@ import asyncio
2
2
  import logging
3
3
  from typing import Any, Callable, Dict, Literal, NotRequired, Optional, TypedDict, Union
4
4
 
5
- from langchain_core.runnables import RunnableConfig
6
5
  from langchain_core.tools import BaseTool
7
6
  from langchain_core.tools.base import ToolException
8
7
  from langgraph.runtime import get_runtime
@@ -180,22 +179,9 @@ class IntentKitSkill(BaseTool):
180
179
  "Use _arun instead, IntentKit only supports synchronous skill calls"
181
180
  )
182
181
 
183
- def context_from_config(self, runner_config: RunnableConfig) -> SkillContext:
184
- if "configurable" not in runner_config:
185
- raise ValueError("configurable not in runner_config")
186
- configurable = runner_config["configurable"]
187
- if not configurable:
188
- raise ValueError("configurable in runnable config is empty")
189
- return SkillContext(
190
- skill_category=self.category,
191
- agent_id=configurable.get("agent_id"),
192
- user_id=configurable.get("user_id"),
193
- app_id=configurable.get("app_id"),
194
- chat_id=configurable.get("chat_id"),
195
- entrypoint=configurable.get("entrypoint"),
196
- is_private=configurable.get("is_private"),
197
- )
198
-
199
- def get_context(self) -> AgentContext:
182
+ @staticmethod
183
+ def get_context() -> AgentContext:
200
184
  runtime = get_runtime(AgentContext)
185
+ if runtime.context is None or not isinstance(runtime.context, AgentContext):
186
+ raise ValueError("No AgentContext found")
201
187
  return runtime.context
@@ -0,0 +1,254 @@
1
+ # Casino Skills for IntentKit
2
+
3
+ The Casino skills provide comprehensive gambling and gaming capabilities for AI agents, enabling interactive card games, dice games, and casino-style entertainment.
4
+
5
+ ## 🎯 Overview
6
+
7
+ This skill set includes three main functions:
8
+ - **Deck Shuffling**: Create and shuffle card decks with customizable options
9
+ - **Card Drawing**: Draw cards with visual PNG/SVG images
10
+ - **Quantum Dice Rolling**: True random dice using quantum number generation
11
+
12
+ ## 🛠️ Available Skills
13
+
14
+ ### 1. `casino_deck_shuffle`
15
+ Creates and shuffles new card decks with options for multiple decks and jokers.
16
+
17
+ **Parameters:**
18
+ - `deck_count` (int): Number of decks (1-6, default: 1)
19
+ - `jokers_enabled` (bool): Include jokers (default: false)
20
+
21
+ ### 2. `casino_deck_draw`
22
+ Draws cards from the current deck with detailed information and images.
23
+
24
+ **Parameters:**
25
+ - `count` (int): Number of cards to draw (1-10, default: 1)
26
+
27
+ ### 3. `casino_dice_roll`
28
+ Rolls quantum random dice with visual representation.
29
+
30
+ **Parameters:**
31
+ - `dice_count` (int): Number of dice to roll (1-10, default: 1)
32
+
33
+ ## 🎮 Game Examples
34
+
35
+ ### 🃏 Blackjack (21)
36
+
37
+ **Setup:**
38
+ ```
39
+ Agent: I'll set up a Blackjack game for you! Let me shuffle a fresh deck.
40
+ [Calls casino_deck_shuffle with deck_count=1]
41
+ ```
42
+
43
+ **Dealing Cards:**
44
+ ```
45
+ Agent: Dealing your cards...
46
+ [Calls casino_deck_draw with count=2 for player]
47
+ [Calls casino_deck_draw with count=1 for dealer, 1 face down]
48
+
49
+ Result: You have: King♠️ (image) + 7♥️ (image) = 17
50
+ Dealer shows: Ace♣️ (image) + [hidden card]
51
+ ```
52
+
53
+ **Player Actions:**
54
+ ```
55
+ User: "Hit me"
56
+ Agent: [Calls casino_deck_draw with count=1]
57
+ Result: You drew 3♦️ (image). Total: 20
58
+
59
+ User: "Stand"
60
+ Agent: Revealing dealer's hidden card...
61
+ [Calls casino_deck_draw for dealer's hidden card and additional cards as needed]
62
+ ```
63
+
64
+ ### 🎲 Craps
65
+
66
+ **Come Out Roll:**
67
+ ```
68
+ Agent: Welcome to the Craps table! Place your bets and let's roll!
69
+ [Calls casino_dice_roll with dice_count=2]
70
+
71
+ Result: 🎲 Rolled: ⚂ ⚃ (3 + 4 = 7) - WINNER!
72
+ The shooter made their point on the come out roll!
73
+ ```
74
+
75
+ **Point Phase:**
76
+ ```
77
+ Agent: Point is 6. Rolling again...
78
+ [Calls casino_dice_roll with dice_count=2]
79
+
80
+ Result: 🎲 Rolled: ⚁ ⚄ (2 + 5 = 7) - Seven out!
81
+ New shooter coming up.
82
+ ```
83
+
84
+ ### 🃏 Texas Hold'em Poker
85
+
86
+ **Pre-flop:**
87
+ ```
88
+ Agent: Dealing pocket cards...
89
+ [Calls casino_deck_shuffle with deck_count=1]
90
+ [Calls casino_deck_draw with count=2 for each player]
91
+
92
+ Your cards: A♠️ (image) K♠️ (image) - Ace-King suited!
93
+ ```
94
+
95
+ **The Flop:**
96
+ ```
97
+ Agent: Dealing the flop...
98
+ [Calls casino_deck_draw with count=3]
99
+
100
+ Flop: A♦️ (image) K♣️ (image) 7♠️ (image)
101
+ You have two pair - Aces and Kings!
102
+ ```
103
+
104
+ **Turn and River:**
105
+ ```
106
+ Agent: Turn card...
107
+ [Calls casino_deck_draw with count=1]
108
+ Turn: Q♠️ (image)
109
+
110
+ River card...
111
+ [Calls casino_deck_draw with count=1]
112
+ River: J♠️ (image)
113
+
114
+ Final board: A♦️ K♣️ 7♠️ Q♠️ J♠️
115
+ You have a straight! A-K-Q-J-10
116
+ ```
117
+
118
+ ### 🎯 Yahtzee
119
+
120
+ **First Roll:**
121
+ ```
122
+ Agent: Rolling all 5 dice for Yahtzee!
123
+ [Calls casino_dice_roll with dice_count=5]
124
+
125
+ Result: ⚀ ⚃ ⚃ ⚄ ⚅ (1, 4, 4, 5, 6)
126
+ Which dice would you like to keep?
127
+ ```
128
+
129
+ **Rerolls:**
130
+ ```
131
+ User: "Keep the two 4s"
132
+ Agent: Rerolling 3 dice...
133
+ [Calls casino_dice_roll with dice_count=3]
134
+
135
+ Result: ⚃ ⚃ ⚃ (4, 4, 4) - Combined with your kept dice: ⚃ ⚃ ⚃ ⚃ ⚃
136
+ YAHTZEE! Five of a kind - 4s! 🎉
137
+ ```
138
+
139
+ ### 🎲 Liar's Dice
140
+
141
+ **Round Start:**
142
+ ```
143
+ Agent: Everyone roll your dice under the cup!
144
+ [Each player calls casino_dice_roll with dice_count=5]
145
+
146
+ Your dice (hidden): ⚁ ⚁ ⚂ ⚄ ⚅ (2, 2, 3, 5, 6)
147
+ ```
148
+
149
+ **Bidding:**
150
+ ```
151
+ User: "I bid three 2s"
152
+ Agent: Player 2 bids four 3s...
153
+ Player 3 calls "Liar!" on Player 2.
154
+
155
+ Revealing all dice...
156
+ [Shows all dice rolled by each player]
157
+ Total 3s on table: 2 dice
158
+ Player 2 bid four 3s but there were only 2. Player 2 loses a die!
159
+ ```
160
+
161
+ ### 🃏 War (Card Game)
162
+
163
+ **Battle:**
164
+ ```
165
+ Agent: Time for War! Each player draws one card.
166
+ [Calls casino_deck_draw with count=1 for each player]
167
+
168
+ You: Q♦️ (image) - Queen of Diamonds
169
+ Opponent: 8♣️ (image) - Eight of Clubs
170
+
171
+ Queen beats 8 - You win this round!
172
+ ```
173
+
174
+ **War Declaration:**
175
+ ```
176
+ Agent: Both players drew Kings! It's WAR!
177
+ [Calls casino_deck_draw with count=4 for each player - 3 face down, 1 face up]
178
+
179
+ Your war card: A♠️ (image) - Ace of Spades
180
+ Opponent's war card: 10♥️ (image) - Ten of Hearts
181
+
182
+ Ace beats 10 - You win the entire war pile!
183
+ ```
184
+
185
+ ## 🎨 Visual Features
186
+
187
+ ### Card Images
188
+ Each card comes with both PNG and SVG images:
189
+ ```json
190
+ {
191
+ "value": "ACE",
192
+ "suit": "SPADES",
193
+ "code": "AS",
194
+ "image": "https://deckofcardsapi.com/static/img/AS.png",
195
+ "svg_image": "https://deckofcardsapi.com/static/img/AS.svg"
196
+ }
197
+ ```
198
+
199
+ ### Dice Visualization
200
+ Dice results include emoji representation:
201
+ - ⚀ (1) ⚁ (2) ⚂ (3) ⚃ (4) ⚄ (5) ⚅ (6)
202
+
203
+ ### Game State Persistence
204
+ - Deck state maintained between draws
205
+ - Remaining cards tracked automatically
206
+ - Each agent has independent game sessions
207
+
208
+ ## 🛡️ Built-in Features
209
+
210
+ ### Rate Limiting
211
+ - **Deck Shuffle**: 20 requests/minute
212
+ - **Card Draw**: 30 requests/minute
213
+ - **Dice Roll**: 15 requests/minute
214
+
215
+ ### Error Handling
216
+ - Automatic deck creation if none exists
217
+ - Graceful API failure handling
218
+ - Input validation and sanitization
219
+
220
+ ### Quantum Randomness
221
+ Dice rolling uses true quantum random number generation from QRandom.io for authentic unpredictability, complete with quantum signatures for verification.
222
+
223
+ ## 🚀 Getting Started
224
+
225
+ 1. Enable Casino skills in your agent configuration
226
+ 2. Set skill states (public/private/disabled) for each function
227
+ 3. Start gaming! The agent will automatically manage decks and game state
228
+
229
+ ## 🎪 Advanced Gaming Scenarios
230
+
231
+ ### Multi-Table Casino
232
+ ```
233
+ Agent: Welcome to the Nation Casino! I'm managing 3 tables:
234
+ - Table 1: Blackjack (6-deck shoe)
235
+ - Table 2: Poker Tournament
236
+ - Table 3: Craps with side bets
237
+
238
+ Which table interests you?
239
+ ```
240
+
241
+ ### Tournament Mode
242
+ ```
243
+ Agent: Poker Tournament - Round 1 of 3
244
+ Blinds: 50/100 chips
245
+ [Manages multiple hands, tracks chip counts, advances rounds]
246
+ ```
247
+
248
+ ### Live Dealer Experience
249
+ ```
250
+ Agent: 🎭 Good evening! I'm your live dealer tonight.
251
+ [Maintains casino atmosphere, explains rules, manages multiple players]
252
+ ```
253
+
254
+ The Casino skills transform your AI agent into a comprehensive gaming companion capable of hosting authentic casino experiences with visual cards, quantum dice, and persistent game management! 🎰🎲🃏
@@ -0,0 +1,97 @@
1
+ """Casino skills for card games and dice rolling."""
2
+
3
+ import logging
4
+ from typing import TypedDict
5
+
6
+ from intentkit.abstracts.skill import SkillStoreABC
7
+ from intentkit.skills.base import SkillConfig, SkillState
8
+ from intentkit.skills.casino.base import CasinoBaseTool
9
+ from intentkit.skills.casino.deck_draw import CasinoDeckDraw
10
+ from intentkit.skills.casino.deck_shuffle import CasinoDeckShuffle
11
+ from intentkit.skills.casino.dice_roll import CasinoDiceRoll
12
+
13
+ # Cache skills at the system level, because they are stateless
14
+ _cache: dict[str, CasinoBaseTool] = {}
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class SkillStates(TypedDict):
20
+ deck_shuffle: SkillState
21
+ deck_draw: SkillState
22
+ dice_roll: SkillState
23
+
24
+
25
+ class Config(SkillConfig):
26
+ """Configuration for Casino skills."""
27
+
28
+ states: SkillStates
29
+
30
+
31
+ async def get_skills(
32
+ config: "Config",
33
+ is_private: bool,
34
+ store: SkillStoreABC,
35
+ **_,
36
+ ) -> list[CasinoBaseTool]:
37
+ """Get all Casino skills.
38
+
39
+ Args:
40
+ config: The configuration for Casino skills.
41
+ is_private: Whether to include private skills.
42
+ store: The skill store for persisting data.
43
+
44
+ Returns:
45
+ A list of Casino skills.
46
+ """
47
+ available_skills = []
48
+
49
+ # Include skills based on their state
50
+ for skill_name, state in config["states"].items():
51
+ if state == "disabled":
52
+ continue
53
+ elif state == "public" or (state == "private" and is_private):
54
+ available_skills.append(skill_name)
55
+
56
+ # Get each skill using the cached getter
57
+ result = []
58
+ for name in available_skills:
59
+ skill = get_casino_skill(name, store)
60
+ if skill:
61
+ result.append(skill)
62
+ return result
63
+
64
+
65
+ def get_casino_skill(
66
+ name: str,
67
+ store: SkillStoreABC,
68
+ ) -> CasinoBaseTool:
69
+ """Get a Casino skill by name.
70
+
71
+ Args:
72
+ name: The name of the skill to get
73
+ store: The skill store for persisting data
74
+
75
+ Returns:
76
+ The requested Casino skill
77
+ """
78
+ if name == "deck_shuffle":
79
+ if name not in _cache:
80
+ _cache[name] = CasinoDeckShuffle(
81
+ skill_store=store,
82
+ )
83
+ return _cache[name]
84
+ elif name == "deck_draw":
85
+ if name not in _cache:
86
+ _cache[name] = CasinoDeckDraw(
87
+ skill_store=store,
88
+ )
89
+ return _cache[name]
90
+ elif name == "dice_roll":
91
+ if name not in _cache:
92
+ _cache[name] = CasinoDiceRoll(
93
+ skill_store=store,
94
+ )
95
+ return _cache[name]
96
+ else:
97
+ raise ValueError(f"Unknown Casino skill: {name}")
@@ -0,0 +1,23 @@
1
+ """Base class for Casino tools."""
2
+
3
+ from typing import Type
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from intentkit.abstracts.skill import SkillStoreABC
8
+ from intentkit.skills.base import IntentKitSkill
9
+
10
+
11
+ class CasinoBaseTool(IntentKitSkill):
12
+ """Base class for Casino tools."""
13
+
14
+ name: str = Field(description="The name of the tool")
15
+ description: str = Field(description="A description of what the tool does")
16
+ args_schema: Type[BaseModel]
17
+ skill_store: SkillStoreABC = Field(
18
+ description="The skill store for persisting data"
19
+ )
20
+
21
+ @property
22
+ def category(self) -> str:
23
+ return "casino"
Binary file
@@ -0,0 +1,130 @@
1
+ """Card drawing skill using Deck of Cards API."""
2
+
3
+ import logging
4
+ from typing import Type
5
+
6
+ try:
7
+ import httpx
8
+ except ImportError:
9
+ raise ImportError(
10
+ "httpx is required for Casino skills. Install it with: pip install httpx"
11
+ )
12
+ from pydantic import BaseModel, Field
13
+
14
+ from intentkit.skills.casino.base import CasinoBaseTool
15
+ from intentkit.skills.casino.utils import (
16
+ CURRENT_DECK_KEY,
17
+ DECK_STORAGE_KEY,
18
+ ENDPOINTS,
19
+ RATE_LIMITS,
20
+ format_card_info,
21
+ validate_card_count,
22
+ )
23
+
24
+ NAME = "casino_deck_draw"
25
+ PROMPT = (
26
+ "Draw cards from the current deck. If no deck exists, a new one will be created. "
27
+ "Returns detailed card information including images."
28
+ )
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ class CasinoDeckDrawInput(BaseModel):
34
+ """Input for CasinoDeckDraw tool."""
35
+
36
+ count: int = Field(default=1, description="Number of cards to draw (1-10)")
37
+
38
+
39
+ class CasinoDeckDraw(CasinoBaseTool):
40
+ """Tool for drawing cards from a deck.
41
+
42
+ This tool uses the Deck of Cards API to draw cards from the current deck.
43
+
44
+ Attributes:
45
+ name: The name of the tool.
46
+ description: A description of what the tool does.
47
+ args_schema: The schema for the tool's input arguments.
48
+ """
49
+
50
+ name: str = NAME
51
+ description: str = PROMPT
52
+ args_schema: Type[BaseModel] = CasinoDeckDrawInput
53
+
54
+ async def _arun(self, count: int = 1, **kwargs) -> dict:
55
+ try:
56
+ context = self.get_context()
57
+
58
+ # Apply rate limit using built-in user_rate_limit method
59
+ rate_config = RATE_LIMITS["deck_draw"]
60
+ await self.user_rate_limit(
61
+ context.user_id or context.agent_id,
62
+ rate_config["max_requests"],
63
+ rate_config["interval"] // 60, # Convert to minutes
64
+ "deck_draw",
65
+ )
66
+
67
+ # Validate count
68
+ count = validate_card_count(count)
69
+
70
+ # Get current deck info
71
+ deck_info = await self.skill_store.get_agent_skill_data(
72
+ context.agent_id, DECK_STORAGE_KEY, CURRENT_DECK_KEY
73
+ )
74
+
75
+ deck_id = "new" # Default to new deck
76
+ if deck_info and deck_info.get("deck_id"):
77
+ deck_id = deck_info["deck_id"]
78
+
79
+ # Build API URL
80
+ url = ENDPOINTS["deck_draw"].format(deck_id=deck_id)
81
+ params = {"count": count}
82
+
83
+ async with httpx.AsyncClient() as client:
84
+ response = await client.get(url, params=params)
85
+
86
+ if response.status_code == 200:
87
+ data = response.json()
88
+
89
+ if data.get("success"):
90
+ # Update deck info
91
+ if deck_id == "new":
92
+ deck_info = {
93
+ "deck_id": data["deck_id"],
94
+ "deck_count": 1,
95
+ "jokers_enabled": False,
96
+ "remaining": data["remaining"],
97
+ "shuffled": True,
98
+ }
99
+ else:
100
+ deck_info["remaining"] = data["remaining"]
101
+
102
+ await self.skill_store.save_agent_skill_data(
103
+ context.agent_id,
104
+ DECK_STORAGE_KEY,
105
+ CURRENT_DECK_KEY,
106
+ deck_info,
107
+ )
108
+
109
+ # Format card information with images
110
+ cards = [
111
+ format_card_info(card) for card in data.get("cards", [])
112
+ ]
113
+
114
+ return {
115
+ "success": True,
116
+ "cards_drawn": cards,
117
+ "remaining_cards": data["remaining"],
118
+ "deck_id": data["deck_id"],
119
+ "message": f"Drew {len(cards)} card{'s' if len(cards) > 1 else ''} "
120
+ f"({data['remaining']} remaining)",
121
+ }
122
+ else:
123
+ return {"success": False, "error": "Failed to draw cards"}
124
+ else:
125
+ logger.error(f"Deck API error: {response.status_code}")
126
+ return {"success": False, "error": "Failed to draw cards"}
127
+
128
+ except Exception as e:
129
+ logger.error(f"Error drawing cards: {str(e)}")
130
+ raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
@@ -0,0 +1,118 @@
1
+ """Deck shuffling skill using Deck of Cards API."""
2
+
3
+ import logging
4
+ from typing import Type
5
+
6
+ try:
7
+ import httpx
8
+ except ImportError:
9
+ raise ImportError(
10
+ "httpx is required for Casino skills. Install it with: pip install httpx"
11
+ )
12
+ from pydantic import BaseModel, Field
13
+
14
+ from intentkit.skills.casino.base import CasinoBaseTool
15
+ from intentkit.skills.casino.utils import (
16
+ CURRENT_DECK_KEY,
17
+ DECK_STORAGE_KEY,
18
+ ENDPOINTS,
19
+ RATE_LIMITS,
20
+ validate_deck_count,
21
+ )
22
+
23
+ NAME = "casino_deck_shuffle"
24
+ PROMPT = (
25
+ "Create and shuffle a new deck of cards. You can specify the number of decks "
26
+ "to use (default is 1) and optionally include jokers."
27
+ )
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class CasinoDeckShuffleInput(BaseModel):
33
+ """Input for CasinoDeckShuffle tool."""
34
+
35
+ deck_count: int = Field(
36
+ default=1, description="Number of decks to use (1-6, default 1)"
37
+ )
38
+ jokers_enabled: bool = Field(
39
+ default=False, description="Whether to include jokers in the deck"
40
+ )
41
+
42
+
43
+ class CasinoDeckShuffle(CasinoBaseTool):
44
+ """Tool for creating and shuffling card decks.
45
+
46
+ This tool uses the Deck of Cards API to create new shuffled decks.
47
+
48
+ Attributes:
49
+ name: The name of the tool.
50
+ description: A description of what the tool does.
51
+ args_schema: The schema for the tool's input arguments.
52
+ """
53
+
54
+ name: str = NAME
55
+ description: str = PROMPT
56
+ args_schema: Type[BaseModel] = CasinoDeckShuffleInput
57
+
58
+ async def _arun(
59
+ self, deck_count: int = 1, jokers_enabled: bool = False, **kwargs
60
+ ) -> dict:
61
+ try:
62
+ context = self.get_context()
63
+
64
+ # Apply rate limit using built-in user_rate_limit method
65
+ rate_config = RATE_LIMITS["deck_shuffle"]
66
+ await self.user_rate_limit(
67
+ context.user_id or context.agent_id,
68
+ rate_config["max_requests"],
69
+ rate_config["interval"] // 60, # Convert to minutes
70
+ "deck_shuffle",
71
+ )
72
+
73
+ # Validate deck count
74
+ deck_count = validate_deck_count(deck_count)
75
+
76
+ # Build API URL and parameters
77
+ url = ENDPOINTS["deck_new_shuffle"]
78
+ params = {"deck_count": deck_count}
79
+
80
+ if jokers_enabled:
81
+ params["jokers_enabled"] = "true"
82
+
83
+ async with httpx.AsyncClient() as client:
84
+ response = await client.get(url, params=params)
85
+
86
+ if response.status_code == 200:
87
+ data = response.json()
88
+
89
+ # Store deck info for the agent
90
+ deck_info = {
91
+ "deck_id": data["deck_id"],
92
+ "deck_count": deck_count,
93
+ "jokers_enabled": jokers_enabled,
94
+ "remaining": data["remaining"],
95
+ "shuffled": data["shuffled"],
96
+ }
97
+
98
+ await self.skill_store.save_agent_skill_data(
99
+ context.agent_id, DECK_STORAGE_KEY, CURRENT_DECK_KEY, deck_info
100
+ )
101
+
102
+ return {
103
+ "success": True,
104
+ "deck_id": data["deck_id"],
105
+ "deck_count": deck_count,
106
+ "jokers_enabled": jokers_enabled,
107
+ "remaining_cards": data["remaining"],
108
+ "message": f"Created and shuffled {'a new deck' if deck_count == 1 else f'{deck_count} decks'} "
109
+ f"with {data['remaining']} cards"
110
+ + (" (including jokers)" if jokers_enabled else ""),
111
+ }
112
+ else:
113
+ logger.error(f"Deck API error: {response.status_code}")
114
+ return {"success": False, "error": "Failed to create deck"}
115
+
116
+ except Exception as e:
117
+ logger.error(f"Error shuffling deck: {str(e)}")
118
+ raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
@@ -0,0 +1,102 @@
1
+ """Quantum dice rolling skill using QRandom API."""
2
+
3
+ import logging
4
+ from typing import Type
5
+
6
+ try:
7
+ import httpx
8
+ except ImportError:
9
+ raise ImportError(
10
+ "httpx is required for Casino skills. Install it with: pip install httpx"
11
+ )
12
+ from pydantic import BaseModel, Field
13
+
14
+ from intentkit.skills.casino.base import CasinoBaseTool
15
+ from intentkit.skills.casino.utils import (
16
+ ENDPOINTS,
17
+ RATE_LIMITS,
18
+ get_dice_visual,
19
+ validate_dice_count,
20
+ )
21
+
22
+ NAME = "casino_dice_roll"
23
+ PROMPT = (
24
+ "Roll quantum random dice using true quantum randomness. "
25
+ "Can roll multiple 6-sided dice at once for games."
26
+ )
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class CasinoDiceRollInput(BaseModel):
32
+ """Input for CasinoDiceRoll tool."""
33
+
34
+ dice_count: int = Field(default=1, description="Number of dice to roll (1-10)")
35
+
36
+
37
+ class CasinoDiceRoll(CasinoBaseTool):
38
+ """Tool for rolling quantum random dice.
39
+
40
+ This tool uses the QRandom API to generate truly random dice rolls
41
+ using quantum randomness.
42
+
43
+ Attributes:
44
+ name: The name of the tool.
45
+ description: A description of what the tool does.
46
+ args_schema: The schema for the tool's input arguments.
47
+ """
48
+
49
+ name: str = NAME
50
+ description: str = PROMPT
51
+ args_schema: Type[BaseModel] = CasinoDiceRollInput
52
+
53
+ async def _arun(self, dice_count: int = 1, **kwargs) -> dict:
54
+ try:
55
+ context = self.get_context()
56
+
57
+ # Apply rate limit using built-in user_rate_limit method
58
+ rate_config = RATE_LIMITS["dice_roll"]
59
+ await self.user_rate_limit(
60
+ context.user_id or context.agent_id,
61
+ rate_config["max_requests"],
62
+ rate_config["interval"] // 60, # Convert to minutes
63
+ "dice_roll",
64
+ )
65
+
66
+ # Validate dice count
67
+ dice_count = validate_dice_count(dice_count)
68
+
69
+ # Build API URL
70
+ url = ENDPOINTS["dice_roll"]
71
+ params = {"n": dice_count}
72
+
73
+ async with httpx.AsyncClient() as client:
74
+ response = await client.get(url, params=params)
75
+
76
+ if response.status_code == 200:
77
+ data = response.json()
78
+
79
+ dice_results = data.get("dice", [])
80
+ total = sum(dice_results)
81
+
82
+ # Generate dice emoji representation
83
+ dice_visual = get_dice_visual(dice_results)
84
+
85
+ return {
86
+ "success": True,
87
+ "dice_results": dice_results,
88
+ "dice_visual": dice_visual,
89
+ "total": total,
90
+ "dice_count": len(dice_results),
91
+ "quantum_signature": data.get("signature", ""),
92
+ "quantum_id": data.get("id", ""),
93
+ "message": f"Rolled {len(dice_results)} dice: {' '.join(dice_visual)} "
94
+ f"(Total: {total})",
95
+ }
96
+ else:
97
+ logger.error(f"QRandom API error: {response.status_code}")
98
+ return {"success": False, "error": "Failed to roll dice"}
99
+
100
+ except Exception as e:
101
+ logger.error(f"Error rolling dice: {str(e)}")
102
+ raise type(e)(f"[agent:{context.agent_id}]: {e}") from e
@@ -0,0 +1,78 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "title": "Casino",
5
+ "description": "Casino gaming skills including card decks and quantum dice rolling for interactive games with users",
6
+ "x-icon": "https://ai.service.crestal.dev/skills/casino/casino.png",
7
+ "x-tags": [
8
+ "Gaming",
9
+ "Entertainment"
10
+ ],
11
+ "properties": {
12
+ "enabled": {
13
+ "type": "boolean",
14
+ "title": "Enabled",
15
+ "description": "Whether this skill is enabled",
16
+ "default": false
17
+ },
18
+ "states": {
19
+ "type": "object",
20
+ "properties": {
21
+ "deck_shuffle": {
22
+ "type": "string",
23
+ "title": "Shuffle Card Deck",
24
+ "enum": [
25
+ "disabled",
26
+ "public",
27
+ "private"
28
+ ],
29
+ "x-enum-title": [
30
+ "Disabled",
31
+ "Agent Owner + All Users",
32
+ "Agent Owner Only"
33
+ ],
34
+ "description": "Create and shuffle new card decks with customizable options",
35
+ "default": "disabled"
36
+ },
37
+ "deck_draw": {
38
+ "type": "string",
39
+ "title": "Draw Cards",
40
+ "enum": [
41
+ "disabled",
42
+ "public",
43
+ "private"
44
+ ],
45
+ "x-enum-title": [
46
+ "Disabled",
47
+ "Agent Owner + All Users",
48
+ "Agent Owner Only"
49
+ ],
50
+ "description": "Draw cards from the current deck with detailed card information and images",
51
+ "default": "disabled"
52
+ },
53
+ "dice_roll": {
54
+ "type": "string",
55
+ "title": "Roll Quantum Dice",
56
+ "enum": [
57
+ "disabled",
58
+ "public",
59
+ "private"
60
+ ],
61
+ "x-enum-title": [
62
+ "Disabled",
63
+ "Agent Owner + All Users",
64
+ "Agent Owner Only"
65
+ ],
66
+ "description": "Roll dice using quantum random number generation for true randomness",
67
+ "default": "disabled"
68
+ }
69
+ },
70
+ "description": "States for each Casino skill"
71
+ }
72
+ },
73
+ "required": [
74
+ "states",
75
+ "enabled"
76
+ ],
77
+ "additionalProperties": true
78
+ }
@@ -0,0 +1,107 @@
1
+ """
2
+ Casino Skills Utilities
3
+
4
+ Common constants, URLs, and helper functions for Casino skills.
5
+ """
6
+
7
+ # API URLs
8
+ DECK_OF_CARDS_API_BASE = "https://www.deckofcardsapi.com/api/deck"
9
+ QRANDOM_API_BASE = "https://qrandom.io/api/random"
10
+
11
+ # API Endpoints
12
+ ENDPOINTS = {
13
+ "deck_new_shuffle": f"{DECK_OF_CARDS_API_BASE}/new/shuffle/",
14
+ "deck_draw": f"{DECK_OF_CARDS_API_BASE}/{{deck_id}}/draw/",
15
+ "dice_roll": f"{QRANDOM_API_BASE}/dice",
16
+ }
17
+
18
+ # Rate Limits (requests per minute)
19
+ RATE_LIMITS = {
20
+ "deck_shuffle": {"max_requests": 20, "interval": 60},
21
+ "deck_draw": {"max_requests": 30, "interval": 60},
22
+ "dice_roll": {"max_requests": 15, "interval": 60},
23
+ }
24
+
25
+ # Storage Keys
26
+ DECK_STORAGE_KEY = "casino_deck"
27
+ CURRENT_DECK_KEY = "current_deck"
28
+
29
+ # Dice visual representation
30
+ DICE_EMOJI = ["⚀", "⚁", "⚂", "⚃", "⚄", "⚅"]
31
+
32
+ # Card back image URL for display
33
+ CARD_BACK_IMAGE = "https://www.deckofcardsapi.com/static/img/back.png"
34
+
35
+ # Validation limits
36
+ MAX_DECK_COUNT = 6
37
+ MIN_DECK_COUNT = 1
38
+ MAX_CARDS_DRAW = 10
39
+ MIN_CARDS_DRAW = 1
40
+ MAX_DICE_COUNT = 10
41
+ MIN_DICE_COUNT = 1
42
+
43
+
44
+ def get_dice_visual(dice_results: list[int]) -> list[str]:
45
+ """Convert dice numbers to emoji representation.
46
+
47
+ Args:
48
+ dice_results: List of dice roll results (1-6)
49
+
50
+ Returns:
51
+ List of dice emoji strings
52
+ """
53
+ return [DICE_EMOJI[result - 1] for result in dice_results if 1 <= result <= 6]
54
+
55
+
56
+ def validate_deck_count(count: int) -> int:
57
+ """Validate and normalize deck count.
58
+
59
+ Args:
60
+ count: Requested deck count
61
+
62
+ Returns:
63
+ Normalized deck count within valid range
64
+ """
65
+ return max(MIN_DECK_COUNT, min(MAX_DECK_COUNT, count))
66
+
67
+
68
+ def validate_card_count(count: int) -> int:
69
+ """Validate and normalize card draw count.
70
+
71
+ Args:
72
+ count: Requested card count
73
+
74
+ Returns:
75
+ Normalized card count within valid range
76
+ """
77
+ return max(MIN_CARDS_DRAW, min(MAX_CARDS_DRAW, count))
78
+
79
+
80
+ def validate_dice_count(count: int) -> int:
81
+ """Validate and normalize dice count.
82
+
83
+ Args:
84
+ count: Requested dice count
85
+
86
+ Returns:
87
+ Normalized dice count within valid range
88
+ """
89
+ return max(MIN_DICE_COUNT, min(MAX_DICE_COUNT, count))
90
+
91
+
92
+ def format_card_info(card: dict) -> dict:
93
+ """Format card information for consistent output.
94
+
95
+ Args:
96
+ card: Raw card data from Deck of Cards API
97
+
98
+ Returns:
99
+ Formatted card information
100
+ """
101
+ return {
102
+ "value": card["value"],
103
+ "suit": card["suit"],
104
+ "code": card["code"],
105
+ "image": card["image"],
106
+ "svg_image": card["images"]["svg"],
107
+ }
@@ -14,6 +14,10 @@ author_wallet = "0x2Bd32A312280bF5A01140e68ca630fB76cE8A3De"
14
14
  author_github = "hyacinthus"
15
15
  author_wallet = "0x445750026A4a1906b61302442E085f9cbAfe206a"
16
16
 
17
+ [casino]
18
+ author_github = "bluntbrain"
19
+ author_wallet = "0x3cdd051eeC909f94965F9c1c657f5b70a172B2C0"
20
+
17
21
  [chainlist]
18
22
  author_github = "bluntbrain"
19
23
  author_wallet = "0x3cdd051eeC909f94965F9c1c657f5b70a172B2C0"
@@ -37,8 +37,8 @@ class TwitterFollowUser(TwitterBaseTool):
37
37
  args_schema: Type[BaseModel] = TwitterFollowUserInput
38
38
 
39
39
  async def _arun(self, user_id: str, **kwargs) -> bool:
40
+ context = self.get_context()
40
41
  try:
41
- context = self.get_context()
42
42
  skill_config = context.agent.skill_config(self.category)
43
43
  twitter = get_twitter_client(
44
44
  agent_id=context.agent_id,
@@ -41,8 +41,8 @@ class TwitterGetMentions(TwitterBaseTool):
41
41
  args_schema: Type[BaseModel] = TwitterGetMentionsInput
42
42
 
43
43
  async def _arun(self, **kwargs) -> list[Tweet]:
44
+ context = self.get_context()
44
45
  try:
45
- context = self.get_context()
46
46
  skill_config = context.agent.skill_config(self.category)
47
47
  twitter = get_twitter_client(
48
48
  agent_id=context.agent_id,
@@ -37,11 +37,11 @@ class TwitterGetTimeline(TwitterBaseTool):
37
37
  args_schema: Type[BaseModel] = TwitterGetTimelineInput
38
38
 
39
39
  async def _arun(self, **kwargs):
40
+ context = self.get_context()
40
41
  try:
41
42
  # Ensure max_results is an integer
42
43
  max_results = 10
43
44
 
44
- context = self.get_context()
45
45
  skill_config = context.agent.skill_config(self.category)
46
46
  twitter = get_twitter_client(
47
47
  agent_id=context.agent_id,
@@ -38,8 +38,8 @@ class TwitterGetUserByUsername(TwitterBaseTool):
38
38
  args_schema: Type[BaseModel] = TwitterGetUserByUsernameInput
39
39
 
40
40
  async def _arun(self, username: str, **kwargs):
41
+ context = self.get_context()
41
42
  try:
42
- context = self.get_context()
43
43
  skill_config = context.agent.skill_config(self.category)
44
44
  twitter = get_twitter_client(
45
45
  agent_id=context.agent_id,
@@ -44,6 +44,7 @@ class TwitterGetUserTweets(TwitterBaseTool):
44
44
  args_schema: Type[BaseModel] = TwitterGetUserTweetsInput
45
45
 
46
46
  async def _arun(self, **kwargs):
47
+ context = self.get_context()
47
48
  try:
48
49
  user_id = kwargs.get("user_id")
49
50
  if not user_id:
@@ -55,7 +56,6 @@ class TwitterGetUserTweets(TwitterBaseTool):
55
56
  # Get exclude parameter with default
56
57
  exclude = kwargs.get("exclude", ["replies", "retweets"])
57
58
 
58
- context = self.get_context()
59
59
  skill_config = context.agent.skill_config(self.category)
60
60
  twitter = get_twitter_client(
61
61
  agent_id=context.agent_id,
@@ -35,8 +35,8 @@ class TwitterLikeTweet(TwitterBaseTool):
35
35
  args_schema: Type[BaseModel] = TwitterLikeTweetInput
36
36
 
37
37
  async def _arun(self, tweet_id: str, **kwargs):
38
+ context = self.get_context()
38
39
  try:
39
- context = self.get_context()
40
40
  skill_config = context.agent.skill_config(self.category)
41
41
  twitter = get_twitter_client(
42
42
  agent_id=context.agent_id,
@@ -49,8 +49,8 @@ class TwitterPostTweet(TwitterBaseTool):
49
49
  image: Optional[str] = None,
50
50
  **kwargs,
51
51
  ):
52
+ context = self.get_context()
52
53
  try:
53
- context = self.get_context()
54
54
  skill_config = context.agent.skill_config(self.category)
55
55
  twitter = get_twitter_client(
56
56
  agent_id=context.agent_id,
@@ -66,11 +66,23 @@ class TwitterPostTweet(TwitterBaseTool):
66
66
  )
67
67
 
68
68
  media_ids = []
69
+ image_warning = ""
69
70
 
70
71
  # Handle image upload if provided
71
72
  if image:
72
- # Use the TwitterClient method to upload the image
73
- media_ids = await twitter.upload_media(context.agent_id, image)
73
+ # Validate image URL - must be from system's S3 CDN
74
+ aws_s3_cdn_url = await self.skill_store.get_system_config(
75
+ "aws_s3_cdn_url"
76
+ )
77
+ if aws_s3_cdn_url and image.startswith(aws_s3_cdn_url):
78
+ # Use the TwitterClient method to upload the image
79
+ media_ids = await twitter.upload_media(context.agent_id, image)
80
+ else:
81
+ # Image is not from system's S3 CDN, skip upload but warn
82
+ image_warning = "Warning: The provided image URL is not from the system's S3 CDN and has been ignored. "
83
+ logger.warning(
84
+ f"Image URL validation failed for agent {context.agent_id}: {image}"
85
+ )
74
86
 
75
87
  # Post tweet using tweepy client
76
88
  tweet_params = {"text": text, "user_auth": twitter.use_key}
@@ -79,7 +91,11 @@ class TwitterPostTweet(TwitterBaseTool):
79
91
 
80
92
  response = await client.create_tweet(**tweet_params)
81
93
  if "data" in response and "id" in response["data"]:
82
- return response
94
+ # Return response with warning if image was ignored
95
+ result = (
96
+ f"{image_warning}Tweet posted successfully. Response: {response}"
97
+ )
98
+ return result
83
99
  else:
84
100
  logger.error(f"Error posting tweet: {str(response)}")
85
101
  raise ToolException("Failed to post tweet.")
@@ -51,8 +51,8 @@ class TwitterReplyTweet(TwitterBaseTool):
51
51
  image: Optional[str] = None,
52
52
  **kwargs,
53
53
  ):
54
+ context = self.get_context()
54
55
  try:
55
- context = self.get_context()
56
56
  skill_config = context.agent.skill_config(self.category)
57
57
  twitter = get_twitter_client(
58
58
  agent_id=context.agent_id,
@@ -68,11 +68,23 @@ class TwitterReplyTweet(TwitterBaseTool):
68
68
  )
69
69
 
70
70
  media_ids = []
71
+ image_warning = ""
71
72
 
72
73
  # Handle image upload if provided
73
74
  if image:
74
- # Use the TwitterClient method to upload the image
75
- media_ids = await twitter.upload_media(context.agent_id, image)
75
+ # Validate image URL - must be from system's S3 CDN
76
+ aws_s3_cdn_url = await self.skill_store.get_system_config(
77
+ "aws_s3_cdn_url"
78
+ )
79
+ if aws_s3_cdn_url and image.startswith(aws_s3_cdn_url):
80
+ # Use the TwitterClient method to upload the image
81
+ media_ids = await twitter.upload_media(context.agent_id, image)
82
+ else:
83
+ # Image is not from system's S3 CDN, skip upload but warn
84
+ image_warning = "Warning: The provided image URL is not from the system's S3 CDN and has been ignored. "
85
+ logger.warning(
86
+ f"Image URL validation failed for agent {context.agent_id}: {image}"
87
+ )
76
88
 
77
89
  # Post reply tweet using tweepy client
78
90
  tweet_params = {
@@ -87,7 +99,9 @@ class TwitterReplyTweet(TwitterBaseTool):
87
99
  response = await client.create_tweet(**tweet_params)
88
100
 
89
101
  if "data" in response and "id" in response["data"]:
90
- return response
102
+ # Return response with warning if image was ignored
103
+ result = f"{image_warning}Reply tweet posted successfully. Response: {response}"
104
+ return result
91
105
  else:
92
106
  logger.error(f"Error replying to tweet: {str(response)}")
93
107
  raise ToolException("Failed to post reply tweet.")
@@ -35,8 +35,8 @@ class TwitterRetweet(TwitterBaseTool):
35
35
  args_schema: Type[BaseModel] = TwitterRetweetInput
36
36
 
37
37
  async def _arun(self, tweet_id: str, **kwargs):
38
+ context = self.get_context()
38
39
  try:
39
- context = self.get_context()
40
40
  skill_config = context.agent.skill_config(self.category)
41
41
  twitter = get_twitter_client(
42
42
  agent_id=context.agent_id,
@@ -36,9 +36,9 @@ class TwitterSearchTweets(TwitterBaseTool):
36
36
  args_schema: Type[BaseModel] = TwitterSearchTweetsInput
37
37
 
38
38
  async def _arun(self, query: str, **kwargs):
39
+ context = self.get_context()
39
40
  max_results = 10
40
41
  try:
41
- context = self.get_context()
42
42
  skill_config = context.agent.skill_config(self.category)
43
43
  twitter = get_twitter_client(
44
44
  agent_id=context.agent_id,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: intentkit
3
- Version: 0.6.17.dev2
3
+ Version: 0.6.18
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=agNEqMMXaSE-jLk4FIPwautZ6GtAZycW7W_NZwXm7SQ,384
1
+ intentkit/__init__.py,sha256=Z4n7a5ePiJyvI9QNN3MRw8J3AcCVN2sptnOSIgzmtM4,379
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
@@ -22,7 +22,7 @@ intentkit/core/prompt.py,sha256=a6nogIGZuDt2u2EuDd29DAv73OjCBOn-bZnuqYRvY7A,1580
22
22
  intentkit/core/skill.py,sha256=vPK37sDRT9kzkMBymPwqZ5uEdxTTRtb_DfREIeyz-Xw,5788
23
23
  intentkit/models/agent.py,sha256=uC5AErdVucaEajKCXAcF6C3VwYRVIhXTIfOBp-n-Xhg,66310
24
24
  intentkit/models/agent_data.py,sha256=mVsiK8TziYa1W1ujU1KwI9osIVIeSM7XJEogGRL1WVU,28263
25
- intentkit/models/agent_schema.json,sha256=_AaLP2fWsmx7psAYvumj1F_v9XzIPfHL7lpBvr1Y1QU,20890
25
+ intentkit/models/agent_schema.json,sha256=vhW6k9sPAU7Wx0VQjhNc-v9-pu0q6JsRK0z3Mgo5W6w,20999
26
26
  intentkit/models/app_setting.py,sha256=iYbW63QD91bt4oEYV3wOXHuRFav2b4VXLwb_StgUQtQ,8230
27
27
  intentkit/models/base.py,sha256=o-zRjVrak-f5Jokdvj8BjLm8gcC3yYiYMCTLegwT2lA,185
28
28
  intentkit/models/chat.py,sha256=4z5y0Q77XsVABeGMRXnxlY2Ol6gnivTxeMrlO04IB-Q,20494
@@ -36,8 +36,8 @@ intentkit/models/redis.py,sha256=UoN8jqLREO1VO9_w6m-JhldpP19iEHj4TiGVCMutQW4,370
36
36
  intentkit/models/skill.py,sha256=h_2wtKEbYE29TLsMdaSnjfOv6vXY6GwMU_abw-ONX28,16374
37
37
  intentkit/models/user.py,sha256=P7l6LOsZmXZ5tDPTczTbqDtDB_MKc_9_ddZkAB2npPk,9288
38
38
  intentkit/skills/__init__.py,sha256=WkjmKB4xvy36zyXMroPMf_DTPgQloNS3L73nVnBmuQI,303
39
- intentkit/skills/base.py,sha256=9WZ7Q6M1mUSFvFO5ak9MEbiAqjMBVqdyEiVQV5YHTzg,6954
40
- intentkit/skills/skills.toml,sha256=iFMn_UmdFFCk4HTHolpSv6Ve6O-iRckJtxVcZ5EjxQM,2634
39
+ intentkit/skills/base.py,sha256=T02h8M9xZAekLPQdqEefmGQhhwdq6OlMf4IuAcdHngs,6316
40
+ intentkit/skills/skills.toml,sha256=BCqO6nQVaU3wSpY0Js1xjakLzfttsq6hcHcJbw7q958,2734
41
41
  intentkit/skills/acolyt/__init__.py,sha256=qHQXFlqyyx4deRxC0rts_ZEEpDVV-vWXPncqI_ZMOi4,2074
42
42
  intentkit/skills/acolyt/acolyt.jpg,sha256=CwrrouzXzYvnHi1rprYruvZqPopG06ppMczEZmZ7D2s,11559
43
43
  intentkit/skills/acolyt/ask.py,sha256=UuTdjF5961MLDMzDChnD7OGAqi0UYTTFgwGvuAIUDkQ,5871
@@ -62,6 +62,15 @@ intentkit/skills/carv/fetch_news.py,sha256=jqi9IwFM99dT8z_RqK9b0FXFLHQfhaqdMlaqn
62
62
  intentkit/skills/carv/onchain_query.py,sha256=mPFpyNPMp55fIlENwqi1M9mhAXcw7uDshX3Lxo6K2x8,6102
63
63
  intentkit/skills/carv/schema.json,sha256=oSReeG50ZJTOxSRniQBJW6KfilscZfp66PiBVOjphS4,5021
64
64
  intentkit/skills/carv/token_info_and_price.py,sha256=B2Xcr3l8EPoHLAVAq0qP3m05ue7xxHgNXBu_W0XjZTI,4060
65
+ intentkit/skills/casino/README.md,sha256=VfJoeiuBVERcCiKQReF7xZ52gVc_IjV-56fqXDeJvXA,6453
66
+ intentkit/skills/casino/__init__.py,sha256=T65XUCWxyxTt4KYWJSb0VxrwbhN3XREi8yVgOUM3VMY,2596
67
+ intentkit/skills/casino/base.py,sha256=Qwb7YU4XiPvufOeT-Nmv-G2UtkxRfGzVHcfTzs-hBMQ,626
68
+ intentkit/skills/casino/casino.png,sha256=P5fU1J7otDPvXcxcug9KFZuuv2sBun7iwr6dv9GU4NQ,472437
69
+ intentkit/skills/casino/deck_draw.py,sha256=JFFqlSYr2l06h5IbIlBhMd0QGi9yko6RCbvqqNaN0DQ,4547
70
+ intentkit/skills/casino/deck_shuffle.py,sha256=bJvo6BdHhfdgnDWuFE1FA0m3kCd131Q72vXVnDi3WwI,4014
71
+ intentkit/skills/casino/dice_roll.py,sha256=-exkBlN0V7ocFTCO4mmT7aUied9tavJIPlFal3WLbl4,3339
72
+ intentkit/skills/casino/schema.json,sha256=7VtA2VZA7Y7pSA-W4wCkLy8xCCN21GX839Pd1Yzg8fo,2122
73
+ intentkit/skills/casino/utils.py,sha256=b5fPwACH_tHgXD-V646weDDEvd4giRGPNfd9f7RRXc0,2593
65
74
  intentkit/skills/cdp/__init__.py,sha256=0OAYGSW_8u1kzV7mPxdyLVSlYWv_cQeQ87pVZPgwTsk,4772
66
75
  intentkit/skills/cdp/base.py,sha256=BcleKSXm0oNcHYky4uUPCJ3roXxMeTJs2OUS-8MkfMI,581
67
76
  intentkit/skills/cdp/cdp.png,sha256=dxPF6jPbKVfxJNMvbGTmBhXM-rSDvweF06txoX1cIM4,4425
@@ -320,17 +329,17 @@ intentkit/skills/token/token_price.py,sha256=fTvfVtQA5N4QG22C66SzZUn_XlnpDVeojPe
320
329
  intentkit/skills/token/token_search.py,sha256=blbtJ-0lQlhrjWLJHB8uMg5offJCbghuaTLRpm8vewE,4205
321
330
  intentkit/skills/twitter/__init__.py,sha256=VPww1hJOw3wetWAZp4HfsdPkbpe4zjJ5JbKTkqDz1ME,4484
322
331
  intentkit/skills/twitter/base.py,sha256=D2Ib0SAXMzydPfTW5g55mwZAVDscQ-rRIcrmT_J5ZE0,3932
323
- intentkit/skills/twitter/follow_user.py,sha256=fb5ferc428o-ykGqoJNRrKmpl8tKRlThZmtMOkN7Gk8,2267
324
- intentkit/skills/twitter/get_mentions.py,sha256=C-4pOrWiqmuv5IpmUy2sYjNj8sZGeXo_cJdomWuDpN0,4132
325
- intentkit/skills/twitter/get_timeline.py,sha256=xWWITCGBbj98C14E7E-NC6tbAsfR6zatNni9tJgU-CI,3729
326
- intentkit/skills/twitter/get_user_by_username.py,sha256=OBZcNIi5OHwMHroCJuGAClbV-zl4vHWNOn4D13brHMM,2596
327
- intentkit/skills/twitter/get_user_tweets.py,sha256=Bm-Lk7WMQ8QalabuUyqSmDQ_lo-qfL18njyqXLZGtkc,4178
328
- intentkit/skills/twitter/like_tweet.py,sha256=LM3sAT-m8kRU9B_9BuRJWaZcetNon1xvUlKjDahFE0k,2110
329
- intentkit/skills/twitter/post_tweet.py,sha256=2pkIminZwP2qqEgn033zO7kA0HlnEr0hcg8_Y56ApKY,2878
330
- intentkit/skills/twitter/reply_tweet.py,sha256=XHvIa39S4yyo9bT1BCS13rlqYsi6nm6t4Op-Y4PYRdM,3154
331
- intentkit/skills/twitter/retweet.py,sha256=onqOnvD_lE_lXqkq8R-Yu-8thPXUZuh63S6zRXvXnuU,2421
332
+ intentkit/skills/twitter/follow_user.py,sha256=QXZNeZ6UE1K-42i1AjZq8QpJPFYqXS8sBURE_EQLO6s,2263
333
+ intentkit/skills/twitter/get_mentions.py,sha256=zdD6DtSpKFBCVOP3f14pb0MCLIduIEdnEknquOxNYSI,4128
334
+ intentkit/skills/twitter/get_timeline.py,sha256=IA5OuaquqRdgrjAsNEb_dcoTw1EkuhHGXseYEex7LvU,3725
335
+ intentkit/skills/twitter/get_user_by_username.py,sha256=Vl1S3eUPtX7xr6eg6zp0my0uVyumoe9g9FV2zhDXnP4,2592
336
+ intentkit/skills/twitter/get_user_tweets.py,sha256=w9bE0PsGcMmHKyvr6SgI1elhWnRmcSjXjQUEl31Nfm0,4174
337
+ intentkit/skills/twitter/like_tweet.py,sha256=KWX4rh1s_Y9gx_JMCKt3ew7HsIQhRlVyPDUQWldUxbw,2106
338
+ intentkit/skills/twitter/post_tweet.py,sha256=XBAgHrib9eqZa3Z07zGyfYaEe0DYwTX-DEEwfx80eTk,3756
339
+ intentkit/skills/twitter/reply_tweet.py,sha256=Irkr043SmZvO97RdA-lwWfSQ7PkiGk3pteix5o9qjFo,3998
340
+ intentkit/skills/twitter/retweet.py,sha256=vyQgFutLrLqjo43YDZrEW-uKsZMZ6gTrPf0MHCXttnU,2417
332
341
  intentkit/skills/twitter/schema.json,sha256=uSSl-dhOs_qrSoOlxFAsTbst0_POWPRZo9YAF_qhho8,6977
333
- intentkit/skills/twitter/search_tweets.py,sha256=sPYgGbz3vJD-y-Fr07qg4B7CPXiY9sjGMoWtyWuNVsQ,4002
342
+ intentkit/skills/twitter/search_tweets.py,sha256=oR-dF3oIPDGjZKy1LN6ifG7GqJ9Ef5YYSuYlBalE9hY,3998
334
343
  intentkit/skills/twitter/twitter.png,sha256=MggF-4UC40K2mf1K0hqsIFzCmw-n_2yMSH50MjxvZso,23879
335
344
  intentkit/skills/unrealspeech/__init__.py,sha256=1A8084j67jltD4njAsCJVTP7IsPYxTghz2IbtuNS4O8,1588
336
345
  intentkit/skills/unrealspeech/base.py,sha256=YQ2SG_KdCW-c8ryQLUL2Mu5yUzKoLb1WymCGnpP6k1Y,1301
@@ -402,7 +411,7 @@ intentkit/utils/random.py,sha256=DymMxu9g0kuQLgJUqalvgksnIeLdS-v0aRk5nQU0mLI,452
402
411
  intentkit/utils/s3.py,sha256=9trQNkKQ5VgxWsewVsV8Y0q_pXzGRvsCYP8xauyUYkg,8549
403
412
  intentkit/utils/slack_alert.py,sha256=s7UpRgyzLW7Pbmt8cKzTJgMA9bm4EP-1rQ5KXayHu6E,2264
404
413
  intentkit/utils/tx.py,sha256=2yLLGuhvfBEY5n_GJ8wmIWLCzn0FsYKv5kRNzw_sLUI,1454
405
- intentkit-0.6.17.dev2.dist-info/METADATA,sha256=jdAPouDo4HCfaCDoR67Q0kvXf0-IwhocF2pRpQxOqtQ,6414
406
- intentkit-0.6.17.dev2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
407
- intentkit-0.6.17.dev2.dist-info/licenses/LICENSE,sha256=Bln6DhK-LtcO4aXy-PBcdZv2f24MlJFm_qn222biJtE,1071
408
- intentkit-0.6.17.dev2.dist-info/RECORD,,
414
+ intentkit-0.6.18.dist-info/METADATA,sha256=tDm7cKBdeXPfEOcHmduYqv3tJZDsafdz4cGPJiPOvdM,6409
415
+ intentkit-0.6.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
416
+ intentkit-0.6.18.dist-info/licenses/LICENSE,sha256=Bln6DhK-LtcO4aXy-PBcdZv2f24MlJFm_qn222biJtE,1071
417
+ intentkit-0.6.18.dist-info/RECORD,,