arcade-x 1.0.0__py3-none-any.whl → 1.1.1__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.
- arcade_x/tools/tweets.py +60 -7
- arcade_x/tools/utils.py +11 -0
- {arcade_x-1.0.0.dist-info → arcade_x-1.1.1.dist-info}/METADATA +4 -4
- arcade_x-1.1.1.dist-info/RECORD +10 -0
- arcade_x-1.0.0.dist-info/RECORD +0 -10
- {arcade_x-1.0.0.dist-info → arcade_x-1.1.1.dist-info}/WHEEL +0 -0
- {arcade_x-1.0.0.dist-info → arcade_x-1.1.1.dist-info}/licenses/LICENSE +0 -0
arcade_x/tools/tweets.py
CHANGED
|
@@ -14,12 +14,22 @@ from arcade_x.tools.utils import (
|
|
|
14
14
|
get_tweet_url,
|
|
15
15
|
parse_search_recent_tweets_response,
|
|
16
16
|
remove_none_values,
|
|
17
|
+
validate_tweet_id,
|
|
17
18
|
)
|
|
18
19
|
|
|
19
20
|
# Manage Tweets Tools. See developer docs for additional available parameters:
|
|
20
21
|
# https://developer.x.com/en/docs/x-api/tweets/manage-tweets/api-reference
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
async def _post_tweet(context: ToolContext, payload: dict) -> str:
|
|
25
|
+
headers = get_headers_with_token(context)
|
|
26
|
+
async with httpx.AsyncClient() as client:
|
|
27
|
+
response = await client.post(TWEETS_URL, headers=headers, json=payload, timeout=10)
|
|
28
|
+
response.raise_for_status()
|
|
29
|
+
tweet_id = response.json()["data"]["id"]
|
|
30
|
+
return f"Tweet with id {tweet_id} posted successfully. URL: {get_tweet_url(tweet_id)}"
|
|
31
|
+
|
|
32
|
+
|
|
23
33
|
@tool(
|
|
24
34
|
requires_auth=X(
|
|
25
35
|
scopes=["tweet.read", "tweet.write", "users.read"],
|
|
@@ -28,18 +38,59 @@ from arcade_x.tools.utils import (
|
|
|
28
38
|
async def post_tweet(
|
|
29
39
|
context: ToolContext,
|
|
30
40
|
tweet_text: Annotated[str, "The text content of the tweet you want to post"],
|
|
41
|
+
quote_tweet_id: Annotated[
|
|
42
|
+
str | None,
|
|
43
|
+
"The ID of the tweet you want to quote."
|
|
44
|
+
" It must be a valid integer as a string. Optional.",
|
|
45
|
+
] = None,
|
|
31
46
|
) -> Annotated[str, "Success string and the URL of the tweet"]:
|
|
32
|
-
"""Post a tweet to X (Twitter).
|
|
47
|
+
"""Post a tweet to X (Twitter).
|
|
33
48
|
|
|
34
|
-
|
|
49
|
+
IMPORTANT NOTE:
|
|
50
|
+
Use this tool ONLY when posting a tweet that is not a reply.
|
|
51
|
+
If you need to reply to a tweet, use the ReplyToTweet tool instead.
|
|
52
|
+
If you need to quote a tweet, you must include the quote_tweet_id parameter."""
|
|
35
53
|
payload = {"text": tweet_text}
|
|
54
|
+
if quote_tweet_id:
|
|
55
|
+
validate_tweet_id(quote_tweet_id)
|
|
56
|
+
payload["quote_tweet_id"] = quote_tweet_id
|
|
57
|
+
return await _post_tweet(context, payload)
|
|
36
58
|
|
|
37
|
-
async with httpx.AsyncClient() as client:
|
|
38
|
-
response = await client.post(TWEETS_URL, headers=headers, json=payload, timeout=10)
|
|
39
|
-
response.raise_for_status()
|
|
40
59
|
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
@tool(
|
|
61
|
+
requires_auth=X(
|
|
62
|
+
scopes=["tweet.read", "tweet.write", "users.read"],
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
async def reply_to_tweet(
|
|
66
|
+
context: ToolContext,
|
|
67
|
+
tweet_id: Annotated[
|
|
68
|
+
str, "The ID of the tweet you want to reply to. It must be a valid integer as a string."
|
|
69
|
+
],
|
|
70
|
+
tweet_text: Annotated[str, "The text content of the tweet you want to post"],
|
|
71
|
+
quote_tweet_id: Annotated[
|
|
72
|
+
str | None,
|
|
73
|
+
"The ID of the tweet you want to quote. It must be a valid integer as a string. Optional.",
|
|
74
|
+
] = None,
|
|
75
|
+
) -> Annotated[str, "Success string and the URL of the tweet"]:
|
|
76
|
+
"""Reply to a tweet on X (Twitter).
|
|
77
|
+
|
|
78
|
+
IMPORTANT NOTE:
|
|
79
|
+
Use this tool ONLY when replying to a tweet directly.
|
|
80
|
+
If you need to post a tweet that is not a reply, use the PostTweet tool instead.
|
|
81
|
+
If you need to quote a tweet on your reply, you must include the quote_tweet_id parameter.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
payload = {
|
|
85
|
+
"text": tweet_text,
|
|
86
|
+
"reply": {
|
|
87
|
+
"in_reply_to_tweet_id": tweet_id,
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
if quote_tweet_id:
|
|
91
|
+
validate_tweet_id(quote_tweet_id)
|
|
92
|
+
payload["quote_tweet_id"] = quote_tweet_id
|
|
93
|
+
return await _post_tweet(context, payload)
|
|
43
94
|
|
|
44
95
|
|
|
45
96
|
@tool(requires_auth=X(scopes=["tweet.read", "tweet.write", "users.read"]))
|
|
@@ -49,6 +100,7 @@ async def delete_tweet_by_id(
|
|
|
49
100
|
) -> Annotated[str, "Success string confirming the tweet deletion"]:
|
|
50
101
|
"""Delete a tweet on X (Twitter)."""
|
|
51
102
|
|
|
103
|
+
validate_tweet_id(tweet_id)
|
|
52
104
|
headers = get_headers_with_token(context)
|
|
53
105
|
url = f"{TWEETS_URL}/{tweet_id}"
|
|
54
106
|
|
|
@@ -185,6 +237,7 @@ async def lookup_tweet_by_id(
|
|
|
185
237
|
) -> Annotated[dict[str, Any], "Dictionary containing the tweet data"]:
|
|
186
238
|
"""Look up a tweet on X (Twitter) by tweet ID."""
|
|
187
239
|
|
|
240
|
+
validate_tweet_id(tweet_id)
|
|
188
241
|
headers = get_headers_with_token(context)
|
|
189
242
|
params = {
|
|
190
243
|
"expansions": "author_id",
|
arcade_x/tools/utils.py
CHANGED
|
@@ -161,3 +161,14 @@ def expand_attached_media(params: dict) -> dict:
|
|
|
161
161
|
"public_metrics",
|
|
162
162
|
])
|
|
163
163
|
return params
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def validate_tweet_id(tweet_id: str) -> None:
|
|
167
|
+
"""
|
|
168
|
+
Validate a tweet ID.
|
|
169
|
+
"""
|
|
170
|
+
if not tweet_id.isdigit():
|
|
171
|
+
raise ToolExecutionError(
|
|
172
|
+
"Invalid tweet ID",
|
|
173
|
+
developer_message="Tweet ID must be a valid integer",
|
|
174
|
+
)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arcade_x
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Arcade.dev LLM tools for X (Twitter)
|
|
5
5
|
Author-email: Arcade <dev@arcade.dev>
|
|
6
6
|
License: Proprietary - Arcade Software License Agreement v1.0
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Python: >=3.10
|
|
9
|
-
Requires-Dist: arcade-tdk<
|
|
9
|
+
Requires-Dist: arcade-tdk<4.0.0,>=3.0.0
|
|
10
10
|
Requires-Dist: httpx<1.0.0,>=0.27.2
|
|
11
11
|
Provides-Extra: dev
|
|
12
|
-
Requires-Dist: arcade-
|
|
13
|
-
Requires-Dist: arcade-serve<
|
|
12
|
+
Requires-Dist: arcade-mcp[evals]<2.0.0,>=1.1.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: arcade-serve<4.0.0,>=3.0.0; extra == 'dev'
|
|
14
14
|
Requires-Dist: mypy<1.6.0,>=1.5.1; extra == 'dev'
|
|
15
15
|
Requires-Dist: pre-commit<3.5.0,>=3.4.0; extra == 'dev'
|
|
16
16
|
Requires-Dist: pytest-asyncio<0.25.0,>=0.24.0; extra == 'dev'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
arcade_x/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
arcade_x/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
arcade_x/tools/constants.py,sha256=d-OJK5Qx05JRUcpK5G1DcYB91wT37hFSzGmIYfwlEtA,42
|
|
4
|
+
arcade_x/tools/tweets.py,sha256=xfg31_Jh7sUuBfFjRIY_TwbUFCcYbm_xyUE_s35HB-8,9416
|
|
5
|
+
arcade_x/tools/users.py,sha256=gopYKTBOwbZAeVdL_T3vwkepbpv1bdPbqcU_2oPC3SY,2132
|
|
6
|
+
arcade_x/tools/utils.py,sha256=lR_shws08LWQD-4XU9r3xYmasZ2j2i-cUaCCDnuN8UE,5723
|
|
7
|
+
arcade_x-1.1.1.dist-info/METADATA,sha256=Sy3KedtCp4On90A6gekRMTaOoeSp3G7wvLXxj9UlR4Y,897
|
|
8
|
+
arcade_x-1.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
+
arcade_x-1.1.1.dist-info/licenses/LICENSE,sha256=ixeE7aL9b2B-_ZYHTY1vQcJB4NufKeo-LWwKNObGDN0,1960
|
|
10
|
+
arcade_x-1.1.1.dist-info/RECORD,,
|
arcade_x-1.0.0.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
arcade_x/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
arcade_x/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
arcade_x/tools/constants.py,sha256=d-OJK5Qx05JRUcpK5G1DcYB91wT37hFSzGmIYfwlEtA,42
|
|
4
|
-
arcade_x/tools/tweets.py,sha256=S1Psv-gFePz-8ibnp7rY-GCdogkAm-hJQZpHf7hUusk,7498
|
|
5
|
-
arcade_x/tools/users.py,sha256=gopYKTBOwbZAeVdL_T3vwkepbpv1bdPbqcU_2oPC3SY,2132
|
|
6
|
-
arcade_x/tools/utils.py,sha256=wxPdp3JDG-gEDM7XUNiZSgL61isVE3SRqaLiwYP-K40,5461
|
|
7
|
-
arcade_x-1.0.0.dist-info/METADATA,sha256=0_sk7qdtG0g4jZ_BYI5ewed2hVDwCA2VcqLCRnBzEoA,896
|
|
8
|
-
arcade_x-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
-
arcade_x-1.0.0.dist-info/licenses/LICENSE,sha256=ixeE7aL9b2B-_ZYHTY1vQcJB4NufKeo-LWwKNObGDN0,1960
|
|
10
|
-
arcade_x-1.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|