@aisa-one/cli 0.1.8 → 0.2.0
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.
- package/dist/commands/configCmd.js +1 -1
- package/dist/commands/twitter.d.ts +127 -3
- package/dist/commands/twitter.js +296 -36
- package/dist/config.js +2 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/index.js +204 -5
- package/dist/types.d.ts +0 -16
- package/dist/utils/file.d.ts +0 -4
- package/dist/utils/file.js +1 -26
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { getConfig, setConfig, listConfig, resetConfig } from "../config.js";
|
|
3
3
|
import { success, info } from "../utils/display.js";
|
|
4
|
-
const VALID_KEYS = ["defaultModel", "baseUrl", "outputFormat"];
|
|
4
|
+
const VALID_KEYS = ["defaultModel", "baseUrl", "outputFormat", "twitterCookies", "twitterProxy"];
|
|
5
5
|
export function configSetAction(key, value) {
|
|
6
6
|
if (!VALID_KEYS.includes(key)) {
|
|
7
7
|
console.error(`Unknown config key: ${key}`);
|
|
@@ -1,14 +1,138 @@
|
|
|
1
|
-
export declare function
|
|
2
|
-
|
|
1
|
+
export declare function twitterUserAction(username: string, options: {
|
|
2
|
+
raw?: boolean;
|
|
3
|
+
}): Promise<void>;
|
|
4
|
+
export declare function twitterUserAboutAction(username: string, options: {
|
|
5
|
+
raw?: boolean;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
export declare function twitterBatchUsersAction(ids: string, options: {
|
|
8
|
+
raw?: boolean;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
export declare function twitterUserTweetsAction(username: string, options: {
|
|
3
11
|
raw?: boolean;
|
|
12
|
+
cursor?: string;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
export declare function twitterMentionsAction(username: string, options: {
|
|
15
|
+
raw?: boolean;
|
|
16
|
+
cursor?: string;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export declare function twitterFollowersAction(username: string, options: {
|
|
19
|
+
raw?: boolean;
|
|
20
|
+
cursor?: string;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
export declare function twitterFollowingAction(username: string, options: {
|
|
23
|
+
raw?: boolean;
|
|
24
|
+
cursor?: string;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
export declare function twitterVerifiedFollowersAction(userId: string, options: {
|
|
27
|
+
raw?: boolean;
|
|
28
|
+
cursor?: string;
|
|
29
|
+
}): Promise<void>;
|
|
30
|
+
export declare function twitterCheckFollowAction(source: string, target: string, options: {
|
|
31
|
+
raw?: boolean;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
export declare function twitterUserSearchAction(query: string, options: {
|
|
34
|
+
raw?: boolean;
|
|
35
|
+
cursor?: string;
|
|
4
36
|
}): Promise<void>;
|
|
5
37
|
export declare function twitterSearchAction(query: string, options: {
|
|
6
38
|
limit?: string;
|
|
39
|
+
type?: string;
|
|
7
40
|
raw?: boolean;
|
|
41
|
+
cursor?: string;
|
|
8
42
|
}): Promise<void>;
|
|
9
|
-
export declare function
|
|
43
|
+
export declare function twitterDetailAction(ids: string, options: {
|
|
44
|
+
raw?: boolean;
|
|
45
|
+
}): Promise<void>;
|
|
46
|
+
export declare function twitterRepliesAction(tweetId: string, options: {
|
|
47
|
+
raw?: boolean;
|
|
48
|
+
cursor?: string;
|
|
49
|
+
}): Promise<void>;
|
|
50
|
+
export declare function twitterQuotesAction(tweetId: string, options: {
|
|
51
|
+
raw?: boolean;
|
|
52
|
+
cursor?: string;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
export declare function twitterRetweetersAction(tweetId: string, options: {
|
|
55
|
+
raw?: boolean;
|
|
56
|
+
cursor?: string;
|
|
57
|
+
}): Promise<void>;
|
|
58
|
+
export declare function twitterThreadAction(tweetId: string, options: {
|
|
59
|
+
raw?: boolean;
|
|
60
|
+
cursor?: string;
|
|
61
|
+
}): Promise<void>;
|
|
62
|
+
export declare function twitterArticleAction(tweetId: string, options: {
|
|
10
63
|
raw?: boolean;
|
|
11
64
|
}): Promise<void>;
|
|
12
65
|
export declare function twitterTrendsAction(options: {
|
|
66
|
+
woeid?: string;
|
|
67
|
+
count?: string;
|
|
68
|
+
raw?: boolean;
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
export declare function twitterListMembersAction(listId: string, options: {
|
|
71
|
+
raw?: boolean;
|
|
72
|
+
cursor?: string;
|
|
73
|
+
}): Promise<void>;
|
|
74
|
+
export declare function twitterListFollowersAction(listId: string, options: {
|
|
75
|
+
raw?: boolean;
|
|
76
|
+
cursor?: string;
|
|
77
|
+
}): Promise<void>;
|
|
78
|
+
export declare function twitterCommunityInfoAction(communityId: string, options: {
|
|
79
|
+
raw?: boolean;
|
|
80
|
+
}): Promise<void>;
|
|
81
|
+
export declare function twitterCommunityMembersAction(communityId: string, options: {
|
|
82
|
+
raw?: boolean;
|
|
83
|
+
cursor?: string;
|
|
84
|
+
}): Promise<void>;
|
|
85
|
+
export declare function twitterCommunityModsAction(communityId: string, options: {
|
|
86
|
+
raw?: boolean;
|
|
87
|
+
cursor?: string;
|
|
88
|
+
}): Promise<void>;
|
|
89
|
+
export declare function twitterCommunityTweetsAction(communityId: string, options: {
|
|
90
|
+
raw?: boolean;
|
|
91
|
+
cursor?: string;
|
|
92
|
+
}): Promise<void>;
|
|
93
|
+
export declare function twitterCommunitySearchAction(query: string, options: {
|
|
94
|
+
raw?: boolean;
|
|
95
|
+
cursor?: string;
|
|
96
|
+
}): Promise<void>;
|
|
97
|
+
export declare function twitterSpaceAction(spaceId: string, options: {
|
|
98
|
+
raw?: boolean;
|
|
99
|
+
}): Promise<void>;
|
|
100
|
+
export declare function twitterLoginAction(options: {
|
|
101
|
+
username?: string;
|
|
102
|
+
email?: string;
|
|
103
|
+
password?: string;
|
|
104
|
+
proxy?: string;
|
|
105
|
+
totp?: string;
|
|
106
|
+
cookies?: string;
|
|
107
|
+
raw?: boolean;
|
|
108
|
+
}): Promise<void>;
|
|
109
|
+
export declare function twitterLogoutAction(): void;
|
|
110
|
+
export declare function tweetAction(text: string, options: {
|
|
111
|
+
replyTo?: string;
|
|
112
|
+
mediaIds?: string;
|
|
113
|
+
raw?: boolean;
|
|
114
|
+
}): Promise<void>;
|
|
115
|
+
export declare function twitterLikeAction(tweetId: string, options: {
|
|
116
|
+
raw?: boolean;
|
|
117
|
+
}): Promise<void>;
|
|
118
|
+
export declare function twitterUnlikeAction(tweetId: string, options: {
|
|
119
|
+
raw?: boolean;
|
|
120
|
+
}): Promise<void>;
|
|
121
|
+
export declare function twitterRetweetAction(tweetId: string, options: {
|
|
122
|
+
raw?: boolean;
|
|
123
|
+
}): Promise<void>;
|
|
124
|
+
export declare function twitterDeleteAction(tweetId: string, options: {
|
|
125
|
+
raw?: boolean;
|
|
126
|
+
}): Promise<void>;
|
|
127
|
+
export declare function twitterFollowAction(userId: string, options: {
|
|
128
|
+
raw?: boolean;
|
|
129
|
+
}): Promise<void>;
|
|
130
|
+
export declare function twitterUnfollowAction(userId: string, options: {
|
|
131
|
+
raw?: boolean;
|
|
132
|
+
}): Promise<void>;
|
|
133
|
+
export declare function twitterUploadMediaAction(filePath: string, options: {
|
|
134
|
+
raw?: boolean;
|
|
135
|
+
}): Promise<void>;
|
|
136
|
+
export declare function twitterDmAction(userId: string, text: string, options: {
|
|
13
137
|
raw?: boolean;
|
|
14
138
|
}): Promise<void>;
|
package/dist/commands/twitter.js
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
import ora from "ora";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import
|
|
3
|
+
import fetch from "node-fetch";
|
|
4
|
+
import { requireApiKey, getConfig, setConfig } from "../config.js";
|
|
4
5
|
import { apiRequest } from "../api.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
6
|
+
import { APIS_BASE_URL } from "../constants.js";
|
|
7
|
+
import { error, success, formatJson } from "../utils/display.js";
|
|
8
|
+
function requireCookies() {
|
|
9
|
+
const cookies = getConfig("twitterCookies");
|
|
10
|
+
const proxy = getConfig("twitterProxy");
|
|
11
|
+
if (!cookies) {
|
|
12
|
+
error('No Twitter cookies configured. Run "aisa twitter login" or "aisa config set twitterCookies <value>".');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
if (!proxy) {
|
|
16
|
+
error('No Twitter proxy configured. Run "aisa config set twitterProxy <value>".');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
return { login_cookies: cookies, proxy };
|
|
20
|
+
}
|
|
21
|
+
/** Simple GET against a twitter read endpoint. */
|
|
22
|
+
async function twitterGet(endpoint, query, label, options) {
|
|
7
23
|
const key = requireApiKey();
|
|
8
|
-
const spinner = ora(
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
body.reply_to_tweet_id = options.replyTo;
|
|
12
|
-
// Note: create_tweet_v2 requires login_cookies and proxy
|
|
13
|
-
// This will fail without those - provide a helpful message
|
|
14
|
-
const res = await apiRequest(key, "twitter/create_tweet_v2", {
|
|
15
|
-
method: "POST",
|
|
16
|
-
body,
|
|
24
|
+
const spinner = ora(label).start();
|
|
25
|
+
const res = await apiRequest(key, endpoint, {
|
|
26
|
+
query,
|
|
17
27
|
domain: true,
|
|
18
28
|
});
|
|
19
29
|
if (!res.success) {
|
|
20
|
-
spinner.fail("
|
|
21
|
-
|
|
22
|
-
error("Tweet creation requires Twitter login cookies. See: https://docs.aisa.one");
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
error(res.error || "Unknown error");
|
|
26
|
-
}
|
|
30
|
+
spinner.fail(label.replace(/\.{3}$/, " failed"));
|
|
31
|
+
error(res.error || "Unknown error");
|
|
27
32
|
return;
|
|
28
33
|
}
|
|
29
34
|
spinner.stop();
|
|
@@ -31,22 +36,21 @@ export async function tweetAction(text, options) {
|
|
|
31
36
|
console.log(JSON.stringify(res.data));
|
|
32
37
|
}
|
|
33
38
|
else {
|
|
34
|
-
console.log(chalk.green("Tweet posted!"));
|
|
35
39
|
console.log(formatJson(res.data));
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
|
-
|
|
42
|
+
/** POST against a twitter write endpoint (auto-injects cookies/proxy). */
|
|
43
|
+
async function twitterWrite(endpoint, body, label, options) {
|
|
39
44
|
const key = requireApiKey();
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
query: q,
|
|
45
|
+
const auth = requireCookies();
|
|
46
|
+
const spinner = ora(label).start();
|
|
47
|
+
const res = await apiRequest(key, endpoint, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
body: { ...auth, ...body },
|
|
46
50
|
domain: true,
|
|
47
51
|
});
|
|
48
52
|
if (!res.success) {
|
|
49
|
-
spinner.fail("
|
|
53
|
+
spinner.fail(label.replace(/\.{3}$/, " failed"));
|
|
50
54
|
error(res.error || "Unknown error");
|
|
51
55
|
return;
|
|
52
56
|
}
|
|
@@ -58,6 +62,7 @@ export async function twitterSearchAction(query, options) {
|
|
|
58
62
|
console.log(formatJson(res.data));
|
|
59
63
|
}
|
|
60
64
|
}
|
|
65
|
+
// ── Read: User Endpoints ─────────────────────────────────────────────────────
|
|
61
66
|
export async function twitterUserAction(username, options) {
|
|
62
67
|
const key = requireApiKey();
|
|
63
68
|
const spinner = ora(`Fetching @${username}...`).start();
|
|
@@ -92,24 +97,279 @@ export async function twitterUserAction(username, options) {
|
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
}
|
|
100
|
+
export async function twitterUserAboutAction(username, options) {
|
|
101
|
+
return twitterGet("twitter/user_about", { userName: username }, `Fetching about @${username}...`, options);
|
|
102
|
+
}
|
|
103
|
+
export async function twitterBatchUsersAction(ids, options) {
|
|
104
|
+
return twitterGet("twitter/user/batch_info_by_ids", { userIds: ids }, "Fetching users...", options);
|
|
105
|
+
}
|
|
106
|
+
export async function twitterUserTweetsAction(username, options) {
|
|
107
|
+
const q = { userName: username };
|
|
108
|
+
if (options.cursor)
|
|
109
|
+
q.cursor = options.cursor;
|
|
110
|
+
return twitterGet("twitter/user/last_tweets", q, `Fetching tweets by @${username}...`, options);
|
|
111
|
+
}
|
|
112
|
+
export async function twitterMentionsAction(username, options) {
|
|
113
|
+
const q = { userName: username };
|
|
114
|
+
if (options.cursor)
|
|
115
|
+
q.cursor = options.cursor;
|
|
116
|
+
return twitterGet("twitter/user/mentions", q, `Fetching mentions of @${username}...`, options);
|
|
117
|
+
}
|
|
118
|
+
export async function twitterFollowersAction(username, options) {
|
|
119
|
+
const q = { userName: username };
|
|
120
|
+
if (options.cursor)
|
|
121
|
+
q.cursor = options.cursor;
|
|
122
|
+
return twitterGet("twitter/user/followers", q, `Fetching followers of @${username}...`, options);
|
|
123
|
+
}
|
|
124
|
+
export async function twitterFollowingAction(username, options) {
|
|
125
|
+
const q = { userName: username };
|
|
126
|
+
if (options.cursor)
|
|
127
|
+
q.cursor = options.cursor;
|
|
128
|
+
return twitterGet("twitter/user/followings", q, `Fetching following of @${username}...`, options);
|
|
129
|
+
}
|
|
130
|
+
export async function twitterVerifiedFollowersAction(userId, options) {
|
|
131
|
+
const q = { user_id: userId };
|
|
132
|
+
if (options.cursor)
|
|
133
|
+
q.cursor = options.cursor;
|
|
134
|
+
return twitterGet("twitter/user/verifiedFollowers", q, "Fetching verified followers...", options);
|
|
135
|
+
}
|
|
136
|
+
export async function twitterCheckFollowAction(source, target, options) {
|
|
137
|
+
return twitterGet("twitter/user/check_follow_relationship", { source_user_name: source, target_user_name: target }, `Checking follow relationship @${source} → @${target}...`, options);
|
|
138
|
+
}
|
|
139
|
+
export async function twitterUserSearchAction(query, options) {
|
|
140
|
+
const q = { query };
|
|
141
|
+
if (options.cursor)
|
|
142
|
+
q.cursor = options.cursor;
|
|
143
|
+
return twitterGet("twitter/user/search", q, `Searching users: "${query}"...`, options);
|
|
144
|
+
}
|
|
145
|
+
// ── Read: Tweet Endpoints ────────────────────────────────────────────────────
|
|
146
|
+
export async function twitterSearchAction(query, options) {
|
|
147
|
+
const q = {
|
|
148
|
+
query,
|
|
149
|
+
queryType: options.type === "top" ? "Top" : "Latest",
|
|
150
|
+
};
|
|
151
|
+
if (options.cursor)
|
|
152
|
+
q.cursor = options.cursor;
|
|
153
|
+
if (options.limit)
|
|
154
|
+
q.count = options.limit;
|
|
155
|
+
return twitterGet("twitter/tweet/advanced_search", q, `Searching tweets: "${query}"...`, options);
|
|
156
|
+
}
|
|
157
|
+
export async function twitterDetailAction(ids, options) {
|
|
158
|
+
return twitterGet("twitter/tweets", { tweet_ids: ids }, "Fetching tweet details...", options);
|
|
159
|
+
}
|
|
160
|
+
export async function twitterRepliesAction(tweetId, options) {
|
|
161
|
+
const q = { tweetId };
|
|
162
|
+
if (options.cursor)
|
|
163
|
+
q.cursor = options.cursor;
|
|
164
|
+
return twitterGet("twitter/tweet/replies", q, "Fetching replies...", options);
|
|
165
|
+
}
|
|
166
|
+
export async function twitterQuotesAction(tweetId, options) {
|
|
167
|
+
const q = { tweetId };
|
|
168
|
+
if (options.cursor)
|
|
169
|
+
q.cursor = options.cursor;
|
|
170
|
+
return twitterGet("twitter/tweet/quotes", q, "Fetching quotes...", options);
|
|
171
|
+
}
|
|
172
|
+
export async function twitterRetweetersAction(tweetId, options) {
|
|
173
|
+
const q = { tweetId };
|
|
174
|
+
if (options.cursor)
|
|
175
|
+
q.cursor = options.cursor;
|
|
176
|
+
return twitterGet("twitter/tweet/retweeters", q, "Fetching retweeters...", options);
|
|
177
|
+
}
|
|
178
|
+
export async function twitterThreadAction(tweetId, options) {
|
|
179
|
+
const q = { tweetId };
|
|
180
|
+
if (options.cursor)
|
|
181
|
+
q.cursor = options.cursor;
|
|
182
|
+
return twitterGet("twitter/tweet/thread_context", q, "Fetching thread...", options);
|
|
183
|
+
}
|
|
184
|
+
export async function twitterArticleAction(tweetId, options) {
|
|
185
|
+
return twitterGet("twitter/article", { tweet_id: tweetId }, "Fetching article...", options);
|
|
186
|
+
}
|
|
187
|
+
// ── Read: Trends ─────────────────────────────────────────────────────────────
|
|
95
188
|
export async function twitterTrendsAction(options) {
|
|
189
|
+
const q = {
|
|
190
|
+
woeid: options.woeid || "1",
|
|
191
|
+
count: options.count || "30",
|
|
192
|
+
};
|
|
193
|
+
return twitterGet("twitter/trends", q, "Fetching trends...", options);
|
|
194
|
+
}
|
|
195
|
+
// ── Read: Lists ──────────────────────────────────────────────────────────────
|
|
196
|
+
export async function twitterListMembersAction(listId, options) {
|
|
197
|
+
const q = { list_id: listId };
|
|
198
|
+
if (options.cursor)
|
|
199
|
+
q.cursor = options.cursor;
|
|
200
|
+
return twitterGet("twitter/list/members", q, "Fetching list members...", options);
|
|
201
|
+
}
|
|
202
|
+
export async function twitterListFollowersAction(listId, options) {
|
|
203
|
+
const q = { list_id: listId };
|
|
204
|
+
if (options.cursor)
|
|
205
|
+
q.cursor = options.cursor;
|
|
206
|
+
return twitterGet("twitter/list/followers", q, "Fetching list followers...", options);
|
|
207
|
+
}
|
|
208
|
+
// ── Read: Communities ────────────────────────────────────────────────────────
|
|
209
|
+
export async function twitterCommunityInfoAction(communityId, options) {
|
|
210
|
+
return twitterGet("twitter/community/info", { community_id: communityId }, "Fetching community info...", options);
|
|
211
|
+
}
|
|
212
|
+
export async function twitterCommunityMembersAction(communityId, options) {
|
|
213
|
+
const q = { community_id: communityId };
|
|
214
|
+
if (options.cursor)
|
|
215
|
+
q.cursor = options.cursor;
|
|
216
|
+
return twitterGet("twitter/community/members", q, "Fetching community members...", options);
|
|
217
|
+
}
|
|
218
|
+
export async function twitterCommunityModsAction(communityId, options) {
|
|
219
|
+
const q = { community_id: communityId };
|
|
220
|
+
if (options.cursor)
|
|
221
|
+
q.cursor = options.cursor;
|
|
222
|
+
return twitterGet("twitter/community/moderators", q, "Fetching community moderators...", options);
|
|
223
|
+
}
|
|
224
|
+
export async function twitterCommunityTweetsAction(communityId, options) {
|
|
225
|
+
const q = { community_id: communityId };
|
|
226
|
+
if (options.cursor)
|
|
227
|
+
q.cursor = options.cursor;
|
|
228
|
+
return twitterGet("twitter/community/tweets", q, "Fetching community tweets...", options);
|
|
229
|
+
}
|
|
230
|
+
export async function twitterCommunitySearchAction(query, options) {
|
|
231
|
+
const q = { query };
|
|
232
|
+
if (options.cursor)
|
|
233
|
+
q.cursor = options.cursor;
|
|
234
|
+
return twitterGet("twitter/community/get_tweets_from_all_community", q, `Searching community tweets: "${query}"...`, options);
|
|
235
|
+
}
|
|
236
|
+
// ── Read: Spaces ─────────────────────────────────────────────────────────────
|
|
237
|
+
export async function twitterSpaceAction(spaceId, options) {
|
|
238
|
+
return twitterGet("twitter/spaces/detail", { space_id: spaceId }, "Fetching space details...", options);
|
|
239
|
+
}
|
|
240
|
+
// ── Write: Login / Logout ────────────────────────────────────────────────────
|
|
241
|
+
export async function twitterLoginAction(options) {
|
|
242
|
+
// Direct cookie import mode
|
|
243
|
+
if (options.cookies) {
|
|
244
|
+
if (!options.proxy) {
|
|
245
|
+
error("--proxy is required when setting cookies directly.");
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
setConfig("twitterCookies", options.cookies);
|
|
249
|
+
setConfig("twitterProxy", options.proxy);
|
|
250
|
+
success("Twitter cookies and proxy saved.");
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
// Login via API
|
|
254
|
+
if (!options.username || !options.password || !options.proxy) {
|
|
255
|
+
error("Required: --username, --password, --proxy (and optionally --email, --totp)");
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
96
258
|
const key = requireApiKey();
|
|
97
|
-
const spinner = ora("
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
259
|
+
const spinner = ora("Logging in to Twitter...").start();
|
|
260
|
+
const body = {
|
|
261
|
+
user_name: options.username,
|
|
262
|
+
password: options.password,
|
|
263
|
+
proxy: options.proxy,
|
|
264
|
+
};
|
|
265
|
+
if (options.email)
|
|
266
|
+
body.email = options.email;
|
|
267
|
+
if (options.totp)
|
|
268
|
+
body.totp_secret = options.totp;
|
|
269
|
+
const res = await apiRequest(key, "twitter/user_login_v2", { method: "POST", body, domain: true });
|
|
103
270
|
if (!res.success) {
|
|
104
|
-
spinner.fail("
|
|
271
|
+
spinner.fail("Twitter login failed");
|
|
105
272
|
error(res.error || "Unknown error");
|
|
106
273
|
return;
|
|
107
274
|
}
|
|
108
275
|
spinner.stop();
|
|
276
|
+
// Extract and store cookies
|
|
277
|
+
const data = res.data;
|
|
278
|
+
const cookies = data?.login_cookies ||
|
|
279
|
+
data?.data?.login_cookies;
|
|
280
|
+
if (cookies) {
|
|
281
|
+
setConfig("twitterCookies", cookies);
|
|
282
|
+
setConfig("twitterProxy", options.proxy);
|
|
283
|
+
success("Logged in! Cookies and proxy saved.");
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
console.log(chalk.yellow("Login response did not contain login_cookies. Raw response:"));
|
|
287
|
+
console.log(formatJson(res.data));
|
|
288
|
+
}
|
|
109
289
|
if (options.raw) {
|
|
110
290
|
console.log(JSON.stringify(res.data));
|
|
111
291
|
}
|
|
292
|
+
}
|
|
293
|
+
export function twitterLogoutAction() {
|
|
294
|
+
setConfig("twitterCookies", "");
|
|
295
|
+
setConfig("twitterProxy", "");
|
|
296
|
+
success("Twitter cookies and proxy cleared.");
|
|
297
|
+
}
|
|
298
|
+
// ── Write: Tweet ─────────────────────────────────────────────────────────────
|
|
299
|
+
export async function tweetAction(text, options) {
|
|
300
|
+
const body = { tweet_text: text };
|
|
301
|
+
if (options.replyTo)
|
|
302
|
+
body.reply_to_tweet_id = options.replyTo;
|
|
303
|
+
if (options.mediaIds)
|
|
304
|
+
body.media_ids = options.mediaIds.split(",");
|
|
305
|
+
return twitterWrite("twitter/create_tweet_v2", body, "Posting tweet...", options);
|
|
306
|
+
}
|
|
307
|
+
// ── Write: Like / Unlike ─────────────────────────────────────────────────────
|
|
308
|
+
export async function twitterLikeAction(tweetId, options) {
|
|
309
|
+
return twitterWrite("twitter/like_tweet_v2", { tweet_id: tweetId }, "Liking tweet...", options);
|
|
310
|
+
}
|
|
311
|
+
export async function twitterUnlikeAction(tweetId, options) {
|
|
312
|
+
return twitterWrite("twitter/unlike_tweet_v2", { tweet_id: tweetId }, "Unliking tweet...", options);
|
|
313
|
+
}
|
|
314
|
+
// ── Write: Retweet ───────────────────────────────────────────────────────────
|
|
315
|
+
export async function twitterRetweetAction(tweetId, options) {
|
|
316
|
+
return twitterWrite("twitter/retweet_tweet_v2", { tweet_id: tweetId }, "Retweeting...", options);
|
|
317
|
+
}
|
|
318
|
+
// ── Write: Delete ────────────────────────────────────────────────────────────
|
|
319
|
+
export async function twitterDeleteAction(tweetId, options) {
|
|
320
|
+
return twitterWrite("twitter/delete_tweet_v2", { tweet_id: tweetId }, "Deleting tweet...", options);
|
|
321
|
+
}
|
|
322
|
+
// ── Write: Follow / Unfollow ─────────────────────────────────────────────────
|
|
323
|
+
export async function twitterFollowAction(userId, options) {
|
|
324
|
+
return twitterWrite("twitter/follow_user_v2", { user_id: userId }, "Following user...", options);
|
|
325
|
+
}
|
|
326
|
+
export async function twitterUnfollowAction(userId, options) {
|
|
327
|
+
return twitterWrite("twitter/unfollow_user_v2", { user_id: userId }, "Unfollowing user...", options);
|
|
328
|
+
}
|
|
329
|
+
// ── Write: Upload Media ──────────────────────────────────────────────────────
|
|
330
|
+
export async function twitterUploadMediaAction(filePath, options) {
|
|
331
|
+
const key = requireApiKey();
|
|
332
|
+
const auth = requireCookies();
|
|
333
|
+
const spinner = ora("Uploading media...").start();
|
|
334
|
+
let formData;
|
|
335
|
+
try {
|
|
336
|
+
const { FormData: NFFormData, fileFromSync } = await import("node-fetch");
|
|
337
|
+
formData = new NFFormData();
|
|
338
|
+
formData.append("file", fileFromSync(filePath));
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
spinner.fail("Failed to read file");
|
|
342
|
+
error(`Could not read file: ${filePath}`);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
formData.append("login_cookies", auth.login_cookies);
|
|
346
|
+
formData.append("proxy", auth.proxy);
|
|
347
|
+
const url = `${APIS_BASE_URL}/twitter/upload_media_v2`;
|
|
348
|
+
const res = await fetch(url, {
|
|
349
|
+
method: "POST",
|
|
350
|
+
headers: {
|
|
351
|
+
Authorization: `Bearer ${key}`,
|
|
352
|
+
"x-aisa-source": "cli",
|
|
353
|
+
},
|
|
354
|
+
body: formData,
|
|
355
|
+
});
|
|
356
|
+
if (!res.ok) {
|
|
357
|
+
spinner.fail("Upload failed");
|
|
358
|
+
const text = await res.text();
|
|
359
|
+
error(`${res.status}: ${text}`);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const data = await res.json();
|
|
363
|
+
spinner.stop();
|
|
364
|
+
if (options.raw) {
|
|
365
|
+
console.log(JSON.stringify(data));
|
|
366
|
+
}
|
|
112
367
|
else {
|
|
113
|
-
|
|
368
|
+
success("Media uploaded!");
|
|
369
|
+
console.log(formatJson(data));
|
|
114
370
|
}
|
|
115
371
|
}
|
|
372
|
+
// ── Write: Direct Message ────────────────────────────────────────────────────
|
|
373
|
+
export async function twitterDmAction(userId, text, options) {
|
|
374
|
+
return twitterWrite("twitter/send_dm_to_user", { user_id: userId, text }, "Sending DM...", options);
|
|
375
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -7,6 +7,8 @@ const config = new Conf({
|
|
|
7
7
|
defaultModel: { type: "string", default: "gpt-4.1" },
|
|
8
8
|
baseUrl: { type: "string", default: "https://api.aisa.one/v1" },
|
|
9
9
|
outputFormat: { type: "string", default: "text" },
|
|
10
|
+
twitterCookies: { type: "string", default: "" },
|
|
11
|
+
twitterProxy: { type: "string", default: "" },
|
|
10
12
|
},
|
|
11
13
|
});
|
|
12
14
|
export function getApiKey() {
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.2.0";
|
|
2
2
|
export declare const BASE_URL = "https://api.aisa.one";
|
|
3
3
|
export declare const CLI_BASE_URL = "https://api.aisa.one/v1";
|
|
4
4
|
export declare const APIS_BASE_URL = "https://api.aisa.one/apis/v1";
|
package/dist/constants.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { webSearchAction, scholarAction } from "./commands/search.js";
|
|
|
18
18
|
// Finance
|
|
19
19
|
import { stockAction, cryptoAction, screenerAction } from "./commands/finance.js";
|
|
20
20
|
// Twitter
|
|
21
|
-
import { tweetAction, twitterSearchAction, twitterUserAction, twitterTrendsAction } from "./commands/twitter.js";
|
|
21
|
+
import { tweetAction, twitterSearchAction, twitterUserAction, twitterTrendsAction, twitterUserAboutAction, twitterBatchUsersAction, twitterUserTweetsAction, twitterMentionsAction, twitterFollowersAction, twitterFollowingAction, twitterVerifiedFollowersAction, twitterCheckFollowAction, twitterUserSearchAction, twitterDetailAction, twitterRepliesAction, twitterQuotesAction, twitterRetweetersAction, twitterThreadAction, twitterArticleAction, twitterListMembersAction, twitterListFollowersAction, twitterCommunityInfoAction, twitterCommunityMembersAction, twitterCommunityModsAction, twitterCommunityTweetsAction, twitterCommunitySearchAction, twitterSpaceAction, twitterLoginAction, twitterLogoutAction, twitterLikeAction, twitterUnlikeAction, twitterRetweetAction, twitterDeleteAction, twitterFollowAction, twitterUnfollowAction, twitterUploadMediaAction, twitterDmAction, } from "./commands/twitter.js";
|
|
22
22
|
// Video
|
|
23
23
|
import { videoCreateAction, videoStatusAction } from "./commands/video.js";
|
|
24
24
|
// Skills
|
|
@@ -162,27 +162,226 @@ program
|
|
|
162
162
|
// ── Twitter shortcuts ──
|
|
163
163
|
program
|
|
164
164
|
.command("tweet <text>")
|
|
165
|
-
.description("Post a tweet")
|
|
165
|
+
.description("Post a tweet (requires twitter login)")
|
|
166
166
|
.option("--reply-to <id>", "Reply to tweet ID")
|
|
167
|
+
.option("--media-ids <ids>", "Comma-separated media IDs")
|
|
167
168
|
.option("--raw", "Raw JSON output")
|
|
168
169
|
.action(wrap(tweetAction));
|
|
169
170
|
const twitter = program.command("twitter").description("Twitter/X operations");
|
|
171
|
+
// Auth
|
|
172
|
+
twitter
|
|
173
|
+
.command("login")
|
|
174
|
+
.description("Login to Twitter or import cookies")
|
|
175
|
+
.option("--username <name>", "Twitter username")
|
|
176
|
+
.option("--email <email>", "Account email")
|
|
177
|
+
.option("--password <pass>", "Account password")
|
|
178
|
+
.option("--proxy <url>", "Proxy URL (required)")
|
|
179
|
+
.option("--totp <secret>", "2FA TOTP secret")
|
|
180
|
+
.option("--cookies <cookies>", "Import login_cookies directly")
|
|
181
|
+
.option("--raw", "Raw JSON output")
|
|
182
|
+
.action(wrap(twitterLoginAction));
|
|
183
|
+
twitter
|
|
184
|
+
.command("logout")
|
|
185
|
+
.description("Clear stored Twitter cookies")
|
|
186
|
+
.action(twitterLogoutAction);
|
|
187
|
+
// User read
|
|
188
|
+
twitter
|
|
189
|
+
.command("user <username>")
|
|
190
|
+
.description("Get user profile")
|
|
191
|
+
.option("--raw", "Raw JSON output")
|
|
192
|
+
.action(wrap(twitterUserAction));
|
|
193
|
+
twitter
|
|
194
|
+
.command("user-about <username>")
|
|
195
|
+
.description("Get user profile details (country, verification, name history)")
|
|
196
|
+
.option("--raw", "Raw JSON output")
|
|
197
|
+
.action(wrap(twitterUserAboutAction));
|
|
198
|
+
twitter
|
|
199
|
+
.command("batch-users <ids>")
|
|
200
|
+
.description("Get multiple users by comma-separated IDs")
|
|
201
|
+
.option("--raw", "Raw JSON output")
|
|
202
|
+
.action(wrap(twitterBatchUsersAction));
|
|
203
|
+
twitter
|
|
204
|
+
.command("user-tweets <username>")
|
|
205
|
+
.description("Get user's recent tweets")
|
|
206
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
207
|
+
.option("--raw", "Raw JSON output")
|
|
208
|
+
.action(wrap(twitterUserTweetsAction));
|
|
209
|
+
twitter
|
|
210
|
+
.command("mentions <username>")
|
|
211
|
+
.description("Get user mentions")
|
|
212
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
213
|
+
.option("--raw", "Raw JSON output")
|
|
214
|
+
.action(wrap(twitterMentionsAction));
|
|
215
|
+
twitter
|
|
216
|
+
.command("followers <username>")
|
|
217
|
+
.description("Get user followers")
|
|
218
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
219
|
+
.option("--raw", "Raw JSON output")
|
|
220
|
+
.action(wrap(twitterFollowersAction));
|
|
221
|
+
twitter
|
|
222
|
+
.command("following <username>")
|
|
223
|
+
.description("Get user followings")
|
|
224
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
225
|
+
.option("--raw", "Raw JSON output")
|
|
226
|
+
.action(wrap(twitterFollowingAction));
|
|
227
|
+
twitter
|
|
228
|
+
.command("verified-followers <user-id>")
|
|
229
|
+
.description("Get verified followers (requires user ID)")
|
|
230
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
231
|
+
.option("--raw", "Raw JSON output")
|
|
232
|
+
.action(wrap(twitterVerifiedFollowersAction));
|
|
233
|
+
twitter
|
|
234
|
+
.command("check-follow <source> <target>")
|
|
235
|
+
.description("Check follow relationship between two usernames")
|
|
236
|
+
.option("--raw", "Raw JSON output")
|
|
237
|
+
.action(wrap(twitterCheckFollowAction));
|
|
238
|
+
twitter
|
|
239
|
+
.command("user-search <query>")
|
|
240
|
+
.description("Search users by keyword")
|
|
241
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
242
|
+
.option("--raw", "Raw JSON output")
|
|
243
|
+
.action(wrap(twitterUserSearchAction));
|
|
244
|
+
// Tweet read
|
|
170
245
|
twitter
|
|
171
246
|
.command("search <query>")
|
|
172
247
|
.description("Search tweets")
|
|
248
|
+
.option("--type <type>", "Query type: latest or top", "latest")
|
|
173
249
|
.option("--limit <n>", "Max results")
|
|
250
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
174
251
|
.option("--raw", "Raw JSON output")
|
|
175
252
|
.action(wrap(twitterSearchAction));
|
|
176
253
|
twitter
|
|
177
|
-
.command("
|
|
178
|
-
.description("Get
|
|
254
|
+
.command("detail <ids>")
|
|
255
|
+
.description("Get tweets by comma-separated IDs")
|
|
179
256
|
.option("--raw", "Raw JSON output")
|
|
180
|
-
.action(wrap(
|
|
257
|
+
.action(wrap(twitterDetailAction));
|
|
258
|
+
twitter
|
|
259
|
+
.command("replies <tweet-id>")
|
|
260
|
+
.description("Get tweet replies")
|
|
261
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
262
|
+
.option("--raw", "Raw JSON output")
|
|
263
|
+
.action(wrap(twitterRepliesAction));
|
|
264
|
+
twitter
|
|
265
|
+
.command("quotes <tweet-id>")
|
|
266
|
+
.description("Get tweet quotes")
|
|
267
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
268
|
+
.option("--raw", "Raw JSON output")
|
|
269
|
+
.action(wrap(twitterQuotesAction));
|
|
270
|
+
twitter
|
|
271
|
+
.command("retweeters <tweet-id>")
|
|
272
|
+
.description("Get tweet retweeters")
|
|
273
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
274
|
+
.option("--raw", "Raw JSON output")
|
|
275
|
+
.action(wrap(twitterRetweetersAction));
|
|
276
|
+
twitter
|
|
277
|
+
.command("thread <tweet-id>")
|
|
278
|
+
.description("Get full conversation thread")
|
|
279
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
280
|
+
.option("--raw", "Raw JSON output")
|
|
281
|
+
.action(wrap(twitterThreadAction));
|
|
282
|
+
twitter
|
|
283
|
+
.command("article <tweet-id>")
|
|
284
|
+
.description("Get article content by tweet ID")
|
|
285
|
+
.option("--raw", "Raw JSON output")
|
|
286
|
+
.action(wrap(twitterArticleAction));
|
|
287
|
+
// Trends
|
|
181
288
|
twitter
|
|
182
289
|
.command("trends")
|
|
183
290
|
.description("Get trending topics")
|
|
291
|
+
.option("--woeid <id>", "Location WOEID (1 = worldwide)", "1")
|
|
292
|
+
.option("--count <n>", "Number of trends")
|
|
184
293
|
.option("--raw", "Raw JSON output")
|
|
185
294
|
.action(wrap(twitterTrendsAction));
|
|
295
|
+
// Lists
|
|
296
|
+
twitter
|
|
297
|
+
.command("list-members <list-id>")
|
|
298
|
+
.description("Get list members")
|
|
299
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
300
|
+
.option("--raw", "Raw JSON output")
|
|
301
|
+
.action(wrap(twitterListMembersAction));
|
|
302
|
+
twitter
|
|
303
|
+
.command("list-followers <list-id>")
|
|
304
|
+
.description("Get list followers")
|
|
305
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
306
|
+
.option("--raw", "Raw JSON output")
|
|
307
|
+
.action(wrap(twitterListFollowersAction));
|
|
308
|
+
// Communities
|
|
309
|
+
twitter
|
|
310
|
+
.command("community-info <community-id>")
|
|
311
|
+
.description("Get community info")
|
|
312
|
+
.option("--raw", "Raw JSON output")
|
|
313
|
+
.action(wrap(twitterCommunityInfoAction));
|
|
314
|
+
twitter
|
|
315
|
+
.command("community-members <community-id>")
|
|
316
|
+
.description("Get community members")
|
|
317
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
318
|
+
.option("--raw", "Raw JSON output")
|
|
319
|
+
.action(wrap(twitterCommunityMembersAction));
|
|
320
|
+
twitter
|
|
321
|
+
.command("community-mods <community-id>")
|
|
322
|
+
.description("Get community moderators")
|
|
323
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
324
|
+
.option("--raw", "Raw JSON output")
|
|
325
|
+
.action(wrap(twitterCommunityModsAction));
|
|
326
|
+
twitter
|
|
327
|
+
.command("community-tweets <community-id>")
|
|
328
|
+
.description("Get community tweets")
|
|
329
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
330
|
+
.option("--raw", "Raw JSON output")
|
|
331
|
+
.action(wrap(twitterCommunityTweetsAction));
|
|
332
|
+
twitter
|
|
333
|
+
.command("community-search <query>")
|
|
334
|
+
.description("Search tweets across all communities")
|
|
335
|
+
.option("--cursor <cursor>", "Pagination cursor")
|
|
336
|
+
.option("--raw", "Raw JSON output")
|
|
337
|
+
.action(wrap(twitterCommunitySearchAction));
|
|
338
|
+
// Spaces
|
|
339
|
+
twitter
|
|
340
|
+
.command("space <space-id>")
|
|
341
|
+
.description("Get Space details")
|
|
342
|
+
.option("--raw", "Raw JSON output")
|
|
343
|
+
.action(wrap(twitterSpaceAction));
|
|
344
|
+
// Write operations
|
|
345
|
+
twitter
|
|
346
|
+
.command("like <tweet-id>")
|
|
347
|
+
.description("Like a tweet")
|
|
348
|
+
.option("--raw", "Raw JSON output")
|
|
349
|
+
.action(wrap(twitterLikeAction));
|
|
350
|
+
twitter
|
|
351
|
+
.command("unlike <tweet-id>")
|
|
352
|
+
.description("Unlike a tweet")
|
|
353
|
+
.option("--raw", "Raw JSON output")
|
|
354
|
+
.action(wrap(twitterUnlikeAction));
|
|
355
|
+
twitter
|
|
356
|
+
.command("retweet <tweet-id>")
|
|
357
|
+
.description("Retweet a tweet")
|
|
358
|
+
.option("--raw", "Raw JSON output")
|
|
359
|
+
.action(wrap(twitterRetweetAction));
|
|
360
|
+
twitter
|
|
361
|
+
.command("delete <tweet-id>")
|
|
362
|
+
.description("Delete a tweet")
|
|
363
|
+
.option("--raw", "Raw JSON output")
|
|
364
|
+
.action(wrap(twitterDeleteAction));
|
|
365
|
+
twitter
|
|
366
|
+
.command("follow <user-id>")
|
|
367
|
+
.description("Follow a user (requires user ID)")
|
|
368
|
+
.option("--raw", "Raw JSON output")
|
|
369
|
+
.action(wrap(twitterFollowAction));
|
|
370
|
+
twitter
|
|
371
|
+
.command("unfollow <user-id>")
|
|
372
|
+
.description("Unfollow a user (requires user ID)")
|
|
373
|
+
.option("--raw", "Raw JSON output")
|
|
374
|
+
.action(wrap(twitterUnfollowAction));
|
|
375
|
+
twitter
|
|
376
|
+
.command("upload-media <file-path>")
|
|
377
|
+
.description("Upload media file for tweets")
|
|
378
|
+
.option("--raw", "Raw JSON output")
|
|
379
|
+
.action(wrap(twitterUploadMediaAction));
|
|
380
|
+
twitter
|
|
381
|
+
.command("dm <user-id> <text>")
|
|
382
|
+
.description("Send a direct message")
|
|
383
|
+
.option("--raw", "Raw JSON output")
|
|
384
|
+
.action(wrap(twitterDmAction));
|
|
186
385
|
// ── Video shortcuts ──
|
|
187
386
|
const video = program.command("video").description("AI video generation");
|
|
188
387
|
video
|
package/dist/types.d.ts
CHANGED
|
@@ -25,22 +25,6 @@ export interface Model {
|
|
|
25
25
|
owned_by: string;
|
|
26
26
|
supported_endpoint_types?: string[] | null;
|
|
27
27
|
}
|
|
28
|
-
export interface SkillMeta {
|
|
29
|
-
name: string;
|
|
30
|
-
description: string;
|
|
31
|
-
owner: string;
|
|
32
|
-
slug: string;
|
|
33
|
-
tags: string[];
|
|
34
|
-
category: string;
|
|
35
|
-
verified: boolean;
|
|
36
|
-
installs: number;
|
|
37
|
-
}
|
|
38
|
-
export interface SkillDetail extends SkillMeta {
|
|
39
|
-
files: Array<{
|
|
40
|
-
path: string;
|
|
41
|
-
content: string;
|
|
42
|
-
}>;
|
|
43
|
-
}
|
|
44
28
|
export interface BalanceResponse {
|
|
45
29
|
balance: number;
|
|
46
30
|
currency: string;
|
package/dist/utils/file.d.ts
CHANGED
|
@@ -4,9 +4,5 @@ export declare function writeSkillFiles(targetDir: string, files: Array<{
|
|
|
4
4
|
path: string;
|
|
5
5
|
content: string;
|
|
6
6
|
}>): void;
|
|
7
|
-
export declare function readSkillDir(dirPath: string): Array<{
|
|
8
|
-
path: string;
|
|
9
|
-
content: string;
|
|
10
|
-
}>;
|
|
11
7
|
export declare function removeDir(dirPath: string): void;
|
|
12
8
|
export declare function detectAgents(agentDirs: Record<string, string>): string[];
|
package/dist/utils/file.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync,
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
2
2
|
import { join, resolve, relative, sep } from "node:path";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
export function expandHome(p) {
|
|
@@ -20,31 +20,6 @@ export function writeSkillFiles(targetDir, files) {
|
|
|
20
20
|
writeFileSync(fullPath, file.content, "utf-8");
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
export function readSkillDir(dirPath) {
|
|
24
|
-
const files = [];
|
|
25
|
-
function walk(dir) {
|
|
26
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
27
|
-
const fullPath = join(dir, entry.name);
|
|
28
|
-
if (entry.isDirectory()) {
|
|
29
|
-
if (entry.name === "node_modules" || entry.name === ".git")
|
|
30
|
-
continue;
|
|
31
|
-
walk(fullPath);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
const relPath = relative(dirPath, fullPath);
|
|
35
|
-
const stat = statSync(fullPath);
|
|
36
|
-
if (stat.size > 1024 * 1024)
|
|
37
|
-
continue; // skip files > 1MB
|
|
38
|
-
files.push({
|
|
39
|
-
path: relPath,
|
|
40
|
-
content: readFileSync(fullPath, "utf-8"),
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
walk(dirPath);
|
|
46
|
-
return files;
|
|
47
|
-
}
|
|
48
23
|
export function removeDir(dirPath) {
|
|
49
24
|
if (existsSync(dirPath)) {
|
|
50
25
|
rmSync(dirPath, { recursive: true, force: true });
|
package/package.json
CHANGED