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 +1 -1
- intentkit/models/agent_schema.json +4 -0
- intentkit/skills/base.py +4 -18
- intentkit/skills/casino/README.md +254 -0
- intentkit/skills/casino/__init__.py +97 -0
- intentkit/skills/casino/base.py +23 -0
- intentkit/skills/casino/casino.png +0 -0
- intentkit/skills/casino/deck_draw.py +130 -0
- intentkit/skills/casino/deck_shuffle.py +118 -0
- intentkit/skills/casino/dice_roll.py +102 -0
- intentkit/skills/casino/schema.json +78 -0
- intentkit/skills/casino/utils.py +107 -0
- intentkit/skills/skills.toml +4 -0
- intentkit/skills/twitter/follow_user.py +1 -1
- intentkit/skills/twitter/get_mentions.py +1 -1
- intentkit/skills/twitter/get_timeline.py +1 -1
- intentkit/skills/twitter/get_user_by_username.py +1 -1
- intentkit/skills/twitter/get_user_tweets.py +1 -1
- intentkit/skills/twitter/like_tweet.py +1 -1
- intentkit/skills/twitter/post_tweet.py +20 -4
- intentkit/skills/twitter/reply_tweet.py +18 -4
- intentkit/skills/twitter/retweet.py +1 -1
- intentkit/skills/twitter/search_tweets.py +1 -1
- {intentkit-0.6.17.dev2.dist-info → intentkit-0.6.18.dist-info}/METADATA +1 -1
- {intentkit-0.6.17.dev2.dist-info → intentkit-0.6.18.dist-info}/RECORD +27 -18
- {intentkit-0.6.17.dev2.dist-info → intentkit-0.6.18.dist-info}/WHEEL +0 -0
- {intentkit-0.6.17.dev2.dist-info → intentkit-0.6.18.dist-info}/licenses/LICENSE +0 -0
intentkit/__init__.py
CHANGED
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
|
-
|
|
184
|
-
|
|
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
|
+
}
|
intentkit/skills/skills.toml
CHANGED
|
@@ -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
|
-
#
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
75
|
-
|
|
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
|
-
|
|
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.
|
|
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=
|
|
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=
|
|
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=
|
|
40
|
-
intentkit/skills/skills.toml,sha256=
|
|
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=
|
|
324
|
-
intentkit/skills/twitter/get_mentions.py,sha256=
|
|
325
|
-
intentkit/skills/twitter/get_timeline.py,sha256=
|
|
326
|
-
intentkit/skills/twitter/get_user_by_username.py,sha256=
|
|
327
|
-
intentkit/skills/twitter/get_user_tweets.py,sha256=
|
|
328
|
-
intentkit/skills/twitter/like_tweet.py,sha256=
|
|
329
|
-
intentkit/skills/twitter/post_tweet.py,sha256=
|
|
330
|
-
intentkit/skills/twitter/reply_tweet.py,sha256=
|
|
331
|
-
intentkit/skills/twitter/retweet.py,sha256=
|
|
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=
|
|
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.
|
|
406
|
-
intentkit-0.6.
|
|
407
|
-
intentkit-0.6.
|
|
408
|
-
intentkit-0.6.
|
|
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,,
|
|
File without changes
|
|
File without changes
|