@thenavidm/threads-mcp-cli 1.1.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/LICENSE +21 -0
- package/README.md +1019 -0
- package/SKILL.md +203 -0
- package/dist/api/client.d.ts +105 -0
- package/dist/api/client.js +305 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/errors.d.ts +92 -0
- package/dist/api/errors.js +195 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/identity.d.ts +33 -0
- package/dist/api/identity.js +52 -0
- package/dist/api/identity.js.map +1 -0
- package/dist/auth/login.d.ts +32 -0
- package/dist/auth/login.js +204 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/auth/store.d.ts +37 -0
- package/dist/auth/store.js +88 -0
- package/dist/auth/store.js.map +1 -0
- package/dist/auth/tokens.d.ts +54 -0
- package/dist/auth/tokens.js +96 -0
- package/dist/auth/tokens.js.map +1 -0
- package/dist/cli.d.ts +59 -0
- package/dist/cli.js +444 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +98 -0
- package/dist/config.js +185 -0
- package/dist/config.js.map +1 -0
- package/dist/content/containers.d.ts +89 -0
- package/dist/content/containers.js +210 -0
- package/dist/content/containers.js.map +1 -0
- package/dist/content/media.d.ts +61 -0
- package/dist/content/media.js +125 -0
- package/dist/content/media.js.map +1 -0
- package/dist/content/text.d.ts +68 -0
- package/dist/content/text.js +106 -0
- package/dist/content/text.js.map +1 -0
- package/dist/doctor.d.ts +14 -0
- package/dist/doctor.js +218 -0
- package/dist/doctor.js.map +1 -0
- package/dist/format/posts.d.ts +41 -0
- package/dist/format/posts.js +153 -0
- package/dist/format/posts.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +167 -0
- package/dist/index.js.map +1 -0
- package/dist/safety.d.ts +52 -0
- package/dist/safety.js +85 -0
- package/dist/safety.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.js +232 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/accounts.d.ts +27 -0
- package/dist/tools/accounts.js +162 -0
- package/dist/tools/accounts.js.map +1 -0
- package/dist/tools/discover.d.ts +56 -0
- package/dist/tools/discover.js +146 -0
- package/dist/tools/discover.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.js +16 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/insights.d.ts +55 -0
- package/dist/tools/insights.js +223 -0
- package/dist/tools/insights.js.map +1 -0
- package/dist/tools/kit.d.ts +90 -0
- package/dist/tools/kit.js +119 -0
- package/dist/tools/kit.js.map +1 -0
- package/dist/tools/posts.d.ts +170 -0
- package/dist/tools/posts.js +312 -0
- package/dist/tools/posts.js.map +1 -0
- package/dist/tools/read.d.ts +31 -0
- package/dist/tools/read.js +95 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/replies.d.ts +92 -0
- package/dist/tools/replies.js +218 -0
- package/dist/tools/replies.js.map +1 -0
- package/dist/transport/http.d.ts +28 -0
- package/dist/transport/http.js +103 -0
- package/dist/transport/http.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Publishing.
|
|
3
|
+
*
|
|
4
|
+
* `create_post` is the one-call path and what most work should use. The staged
|
|
5
|
+
* pair underneath it — `stage_post` and `publish_staged` — exposes the
|
|
6
|
+
* unpublished container directly, because it is the only draft state Threads
|
|
7
|
+
* has: invisible, valid for 24 hours, publishable later by id. That is exactly
|
|
8
|
+
* what an agent needs when a human wants to see something before it is public.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
export declare const createPost: import("./kit.js").ToolSpec<{
|
|
12
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
+
account: z.ZodOptional<z.ZodString>;
|
|
14
|
+
link_attachment: z.ZodOptional<z.ZodString>;
|
|
15
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
16
|
+
reply_to_id: z.ZodOptional<z.ZodString>;
|
|
17
|
+
quote_post_id: z.ZodOptional<z.ZodString>;
|
|
18
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
19
|
+
allowlisted_country_codes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
20
|
+
enable_reply_approvals: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
22
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
23
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
24
|
+
text: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}>;
|
|
26
|
+
export declare const createThread: import("./kit.js").ToolSpec<{
|
|
27
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
28
|
+
account: z.ZodOptional<z.ZodString>;
|
|
29
|
+
link_attachment: z.ZodOptional<z.ZodString>;
|
|
30
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
31
|
+
reply_to_id: z.ZodOptional<z.ZodString>;
|
|
32
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
33
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
34
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
35
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
36
|
+
posts: z.ZodArray<z.ZodString, "many">;
|
|
37
|
+
}>;
|
|
38
|
+
export declare const createCarousel: import("./kit.js").ToolSpec<{
|
|
39
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
40
|
+
account: z.ZodOptional<z.ZodString>;
|
|
41
|
+
items: z.ZodArray<z.ZodObject<{
|
|
42
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
43
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
44
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
alt_text?: string | undefined;
|
|
47
|
+
image_url?: string | undefined;
|
|
48
|
+
video_url?: string | undefined;
|
|
49
|
+
}, {
|
|
50
|
+
alt_text?: string | undefined;
|
|
51
|
+
image_url?: string | undefined;
|
|
52
|
+
video_url?: string | undefined;
|
|
53
|
+
}>, "many">;
|
|
54
|
+
text: z.ZodOptional<z.ZodString>;
|
|
55
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
56
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
57
|
+
}>;
|
|
58
|
+
export declare const stagePost: import("./kit.js").ToolSpec<{
|
|
59
|
+
account: z.ZodOptional<z.ZodString>;
|
|
60
|
+
link_attachment: z.ZodOptional<z.ZodString>;
|
|
61
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
62
|
+
reply_to_id: z.ZodOptional<z.ZodString>;
|
|
63
|
+
quote_post_id: z.ZodOptional<z.ZodString>;
|
|
64
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
65
|
+
allowlisted_country_codes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
66
|
+
enable_reply_approvals: z.ZodOptional<z.ZodBoolean>;
|
|
67
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
68
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
69
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
70
|
+
text: z.ZodOptional<z.ZodString>;
|
|
71
|
+
}>;
|
|
72
|
+
export declare const publishStaged: import("./kit.js").ToolSpec<{
|
|
73
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
74
|
+
account: z.ZodOptional<z.ZodString>;
|
|
75
|
+
container_id: z.ZodString;
|
|
76
|
+
}>;
|
|
77
|
+
export declare const getContainerStatus: import("./kit.js").ToolSpec<{
|
|
78
|
+
account: z.ZodOptional<z.ZodString>;
|
|
79
|
+
container_id: z.ZodString;
|
|
80
|
+
}>;
|
|
81
|
+
export declare const quotePost: import("./kit.js").ToolSpec<{
|
|
82
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
83
|
+
account: z.ZodOptional<z.ZodString>;
|
|
84
|
+
text: z.ZodString;
|
|
85
|
+
quoted_post_id: z.ZodString;
|
|
86
|
+
}>;
|
|
87
|
+
export declare const repost: import("./kit.js").ToolSpec<{
|
|
88
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
89
|
+
account: z.ZodOptional<z.ZodString>;
|
|
90
|
+
id: z.ZodString;
|
|
91
|
+
}>;
|
|
92
|
+
export declare const deletePost: import("./kit.js").ToolSpec<{
|
|
93
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
94
|
+
account: z.ZodOptional<z.ZodString>;
|
|
95
|
+
id: z.ZodString;
|
|
96
|
+
}>;
|
|
97
|
+
export declare const POST_TOOLS: (import("./kit.js").ToolSpec<{
|
|
98
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
99
|
+
account: z.ZodOptional<z.ZodString>;
|
|
100
|
+
link_attachment: z.ZodOptional<z.ZodString>;
|
|
101
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
102
|
+
reply_to_id: z.ZodOptional<z.ZodString>;
|
|
103
|
+
quote_post_id: z.ZodOptional<z.ZodString>;
|
|
104
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
105
|
+
allowlisted_country_codes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
106
|
+
enable_reply_approvals: z.ZodOptional<z.ZodBoolean>;
|
|
107
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
108
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
109
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
110
|
+
text: z.ZodOptional<z.ZodString>;
|
|
111
|
+
}> | import("./kit.js").ToolSpec<{
|
|
112
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
113
|
+
account: z.ZodOptional<z.ZodString>;
|
|
114
|
+
link_attachment: z.ZodOptional<z.ZodString>;
|
|
115
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
116
|
+
reply_to_id: z.ZodOptional<z.ZodString>;
|
|
117
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
118
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
119
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
120
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
121
|
+
posts: z.ZodArray<z.ZodString, "many">;
|
|
122
|
+
}> | import("./kit.js").ToolSpec<{
|
|
123
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
124
|
+
account: z.ZodOptional<z.ZodString>;
|
|
125
|
+
items: z.ZodArray<z.ZodObject<{
|
|
126
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
127
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
128
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
129
|
+
}, "strip", z.ZodTypeAny, {
|
|
130
|
+
alt_text?: string | undefined;
|
|
131
|
+
image_url?: string | undefined;
|
|
132
|
+
video_url?: string | undefined;
|
|
133
|
+
}, {
|
|
134
|
+
alt_text?: string | undefined;
|
|
135
|
+
image_url?: string | undefined;
|
|
136
|
+
video_url?: string | undefined;
|
|
137
|
+
}>, "many">;
|
|
138
|
+
text: z.ZodOptional<z.ZodString>;
|
|
139
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
140
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
141
|
+
}> | import("./kit.js").ToolSpec<{
|
|
142
|
+
account: z.ZodOptional<z.ZodString>;
|
|
143
|
+
link_attachment: z.ZodOptional<z.ZodString>;
|
|
144
|
+
topic_tag: z.ZodOptional<z.ZodString>;
|
|
145
|
+
reply_to_id: z.ZodOptional<z.ZodString>;
|
|
146
|
+
quote_post_id: z.ZodOptional<z.ZodString>;
|
|
147
|
+
reply_control: z.ZodOptional<z.ZodEnum<["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]>>;
|
|
148
|
+
allowlisted_country_codes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
149
|
+
enable_reply_approvals: z.ZodOptional<z.ZodBoolean>;
|
|
150
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
151
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
152
|
+
alt_text: z.ZodOptional<z.ZodString>;
|
|
153
|
+
text: z.ZodOptional<z.ZodString>;
|
|
154
|
+
}> | import("./kit.js").ToolSpec<{
|
|
155
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
156
|
+
account: z.ZodOptional<z.ZodString>;
|
|
157
|
+
container_id: z.ZodString;
|
|
158
|
+
}> | import("./kit.js").ToolSpec<{
|
|
159
|
+
account: z.ZodOptional<z.ZodString>;
|
|
160
|
+
container_id: z.ZodString;
|
|
161
|
+
}> | import("./kit.js").ToolSpec<{
|
|
162
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
163
|
+
account: z.ZodOptional<z.ZodString>;
|
|
164
|
+
text: z.ZodString;
|
|
165
|
+
quoted_post_id: z.ZodString;
|
|
166
|
+
}> | import("./kit.js").ToolSpec<{
|
|
167
|
+
confirm: z.ZodOptional<z.ZodBoolean>;
|
|
168
|
+
account: z.ZodOptional<z.ZodString>;
|
|
169
|
+
id: z.ZodString;
|
|
170
|
+
}>)[];
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Publishing.
|
|
3
|
+
*
|
|
4
|
+
* `create_post` is the one-call path and what most work should use. The staged
|
|
5
|
+
* pair underneath it — `stage_post` and `publish_staged` — exposes the
|
|
6
|
+
* unpublished container directly, because it is the only draft state Threads
|
|
7
|
+
* has: invisible, valid for 24 hours, publishable later by id. That is exactly
|
|
8
|
+
* what an agent needs when a human wants to see something before it is public.
|
|
9
|
+
*/
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { accountArg, confirmArg, defineTool, snippet } from "./kit.js";
|
|
12
|
+
import { createContainer, publish, publishCarousel, publishChain, publishContainer, validate, } from "../content/containers.js";
|
|
13
|
+
import { assertCarouselSize } from "../content/media.js";
|
|
14
|
+
import { deleteSucceeded } from "../api/client.js";
|
|
15
|
+
import { requireMediaId } from "../api/identity.js";
|
|
16
|
+
import { measure } from "../content/text.js";
|
|
17
|
+
const replyControl = z
|
|
18
|
+
.enum(["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"])
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Who may reply. Defaults to everyone.");
|
|
21
|
+
const mediaArgs = {
|
|
22
|
+
image_url: z
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Public HTTPS URL of a JPEG or PNG, 8MB or less. Threads fetches it itself; there is no upload endpoint."),
|
|
26
|
+
video_url: z
|
|
27
|
+
.string()
|
|
28
|
+
.optional()
|
|
29
|
+
.describe("Public HTTPS URL of an MP4 or MOV, up to 1GB and 5 minutes."),
|
|
30
|
+
alt_text: z.string().optional().describe("Alt text for the attached image or video."),
|
|
31
|
+
};
|
|
32
|
+
const composeArgs = {
|
|
33
|
+
text: z.string().optional().describe("Post body. 500 characters, and emoji count as UTF-8 bytes."),
|
|
34
|
+
...mediaArgs,
|
|
35
|
+
link_attachment: z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("A URL to render as a preview card. Text-only posts only; it cannot be combined with media."),
|
|
39
|
+
topic_tag: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe("One topic tag, without the #. 1-50 characters, no periods or ampersands."),
|
|
43
|
+
reply_to_id: z.string().optional().describe("Numeric id of the post this replies to."),
|
|
44
|
+
quote_post_id: z.string().optional().describe("Numeric id of a post to quote."),
|
|
45
|
+
reply_control: replyControl,
|
|
46
|
+
allowlisted_country_codes: z
|
|
47
|
+
.array(z.string())
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("Restrict who can see this post to these ISO 3166-1 alpha-2 country codes. Needs a profile Meta has made eligible; whoami reports whether this one is."),
|
|
50
|
+
enable_reply_approvals: z
|
|
51
|
+
.boolean()
|
|
52
|
+
.optional()
|
|
53
|
+
.describe("Hold replies for approval before they appear. Read the queue with get_pending_replies."),
|
|
54
|
+
};
|
|
55
|
+
export const createPost = defineTool({
|
|
56
|
+
name: "create_post",
|
|
57
|
+
title: "Publish a post",
|
|
58
|
+
description: "Publish one post to Threads: creates the media container, waits for it to finish processing, then publishes. Public the moment it runs, and Threads has no edit endpoint, so this needs confirm: true. For anything over 500 characters use create_thread instead.",
|
|
59
|
+
schema: { ...composeArgs, ...accountArg, ...confirmArg },
|
|
60
|
+
risk: "destructive",
|
|
61
|
+
summary: (args) => `post to Threads: "${snippet(args.text)}"`,
|
|
62
|
+
handler: async (args, ctx) => {
|
|
63
|
+
const account = ctx.account(args.account);
|
|
64
|
+
const post = await publish(ctx.client, account, {
|
|
65
|
+
text: args.text,
|
|
66
|
+
image_url: args.image_url,
|
|
67
|
+
video_url: args.video_url,
|
|
68
|
+
alt_text: args.alt_text,
|
|
69
|
+
link_attachment: args.link_attachment,
|
|
70
|
+
topic_tag: args.topic_tag,
|
|
71
|
+
reply_to_id: args.reply_to_id ? requireMediaId(args.reply_to_id) : undefined,
|
|
72
|
+
quote_post_id: args.quote_post_id ? requireMediaId(args.quote_post_id) : undefined,
|
|
73
|
+
reply_control: args.reply_control,
|
|
74
|
+
allowlisted_country_codes: args.allowlisted_country_codes,
|
|
75
|
+
enable_reply_approvals: args.enable_reply_approvals,
|
|
76
|
+
});
|
|
77
|
+
return post;
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
export const createThread = defineTool({
|
|
81
|
+
name: "create_thread",
|
|
82
|
+
title: "Publish a chain of posts",
|
|
83
|
+
description: "Publish several posts as a thread, each replying to the one before. Threads has no thread endpoint: a thread is a chain of ordinary posts, so it can half-publish. Every part is length-checked before the first one goes out, and if a later part still fails the error names exactly how far it got. Public and irreversible, so this needs confirm: true.",
|
|
84
|
+
schema: {
|
|
85
|
+
posts: z
|
|
86
|
+
.array(z.string())
|
|
87
|
+
.min(1)
|
|
88
|
+
.max(25)
|
|
89
|
+
.describe("The parts, in order. Each is capped at 500 characters and validated before anything is published."),
|
|
90
|
+
...mediaArgs,
|
|
91
|
+
link_attachment: composeArgs.link_attachment,
|
|
92
|
+
topic_tag: composeArgs.topic_tag,
|
|
93
|
+
reply_to_id: z
|
|
94
|
+
.string()
|
|
95
|
+
.optional()
|
|
96
|
+
.describe("Start the thread as a reply to this post, rather than as a new one."),
|
|
97
|
+
reply_control: replyControl,
|
|
98
|
+
...accountArg,
|
|
99
|
+
...confirmArg,
|
|
100
|
+
},
|
|
101
|
+
risk: "destructive",
|
|
102
|
+
summary: (args) => `post a ${args.posts.length}-part Threads thread starting "${snippet(args.posts[0])}"`,
|
|
103
|
+
handler: async (args, ctx) => {
|
|
104
|
+
const account = ctx.account(args.account);
|
|
105
|
+
// Media, the link card, the tag and the reply control apply to the first
|
|
106
|
+
// post only. Repeating them down the chain would attach the same image to
|
|
107
|
+
// every part, which is never what anyone means.
|
|
108
|
+
const parts = args.posts.map((text, index) => index === 0
|
|
109
|
+
? {
|
|
110
|
+
text,
|
|
111
|
+
image_url: args.image_url,
|
|
112
|
+
video_url: args.video_url,
|
|
113
|
+
alt_text: args.alt_text,
|
|
114
|
+
link_attachment: args.link_attachment,
|
|
115
|
+
topic_tag: args.topic_tag,
|
|
116
|
+
reply_control: args.reply_control,
|
|
117
|
+
}
|
|
118
|
+
: { text });
|
|
119
|
+
const { posts, warnings } = await publishChain(ctx.client, account, parts, args.reply_to_id ? requireMediaId(args.reply_to_id) : undefined);
|
|
120
|
+
return {
|
|
121
|
+
parts: posts.length,
|
|
122
|
+
root: posts[0]?.permalink ?? posts[0]?.id,
|
|
123
|
+
posts: posts.map((p, i) => ({ part: i + 1, id: p.id, permalink: p.permalink })),
|
|
124
|
+
...(warnings.length ? { warnings } : {}),
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
export const createCarousel = defineTool({
|
|
129
|
+
name: "create_carousel",
|
|
130
|
+
title: "Publish a carousel",
|
|
131
|
+
description: "Publish 2 to 20 images or videos as one carousel post. Each item is staged separately and they transcode in parallel, then a parent container binds them together. Counts as a single post against the daily quota. Public and irreversible, so this needs confirm: true.",
|
|
132
|
+
schema: {
|
|
133
|
+
items: z
|
|
134
|
+
.array(z.object({
|
|
135
|
+
image_url: z.string().optional(),
|
|
136
|
+
video_url: z.string().optional(),
|
|
137
|
+
alt_text: z.string().optional(),
|
|
138
|
+
}))
|
|
139
|
+
.min(2)
|
|
140
|
+
.max(20)
|
|
141
|
+
.describe("2 to 20 items, each with an image_url or a video_url."),
|
|
142
|
+
text: z.string().optional().describe("Caption for the carousel. 500 characters."),
|
|
143
|
+
topic_tag: composeArgs.topic_tag,
|
|
144
|
+
reply_control: replyControl,
|
|
145
|
+
...accountArg,
|
|
146
|
+
...confirmArg,
|
|
147
|
+
},
|
|
148
|
+
risk: "destructive",
|
|
149
|
+
summary: (args) => `post a ${args.items.length}-item Threads carousel: "${snippet(args.text)}"`,
|
|
150
|
+
handler: async (args, ctx) => {
|
|
151
|
+
assertCarouselSize(args.items.length);
|
|
152
|
+
const account = ctx.account(args.account);
|
|
153
|
+
return publishCarousel(ctx.client, account, args.items, {
|
|
154
|
+
text: args.text,
|
|
155
|
+
topic_tag: args.topic_tag,
|
|
156
|
+
reply_control: args.reply_control,
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
export const stagePost = defineTool({
|
|
161
|
+
name: "stage_post",
|
|
162
|
+
title: "Stage a post without publishing it",
|
|
163
|
+
description: "Build a media container without publishing. Nothing appears anywhere: the container is invisible, holds for 24 hours, and is published later with publish_staged. This is the only draft state Threads has, and the right way to show a human a post before it goes public. Nothing is public, so no confirmation is needed.",
|
|
164
|
+
schema: { ...composeArgs, ...accountArg },
|
|
165
|
+
risk: "write",
|
|
166
|
+
summary: (args) => `stage a Threads post: "${snippet(args.text)}"`,
|
|
167
|
+
handler: async (args, ctx) => {
|
|
168
|
+
const account = ctx.account(args.account);
|
|
169
|
+
const options = {
|
|
170
|
+
text: args.text,
|
|
171
|
+
image_url: args.image_url,
|
|
172
|
+
video_url: args.video_url,
|
|
173
|
+
alt_text: args.alt_text,
|
|
174
|
+
link_attachment: args.link_attachment,
|
|
175
|
+
topic_tag: args.topic_tag,
|
|
176
|
+
reply_to_id: args.reply_to_id ? requireMediaId(args.reply_to_id) : undefined,
|
|
177
|
+
quote_post_id: args.quote_post_id ? requireMediaId(args.quote_post_id) : undefined,
|
|
178
|
+
reply_control: args.reply_control,
|
|
179
|
+
allowlisted_country_codes: args.allowlisted_country_codes,
|
|
180
|
+
enable_reply_approvals: args.enable_reply_approvals,
|
|
181
|
+
};
|
|
182
|
+
const warnings = validate(options);
|
|
183
|
+
const containerId = await createContainer(ctx.client, account, options);
|
|
184
|
+
return {
|
|
185
|
+
container_id: containerId,
|
|
186
|
+
published: false,
|
|
187
|
+
expires_in_hours: 24,
|
|
188
|
+
characters: args.text ? measure(args.text).graphemes : 0,
|
|
189
|
+
next: `Call publish_staged with container_id ${containerId} to make it live.`,
|
|
190
|
+
...(warnings.length ? { warnings } : {}),
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
export const publishStaged = defineTool({
|
|
195
|
+
name: "publish_staged",
|
|
196
|
+
title: "Publish a staged container",
|
|
197
|
+
description: "Publish a container created by stage_post, waiting for processing first. This is what makes it public, so it needs confirm: true.",
|
|
198
|
+
schema: {
|
|
199
|
+
container_id: z.string().describe("The container id returned by stage_post."),
|
|
200
|
+
...accountArg,
|
|
201
|
+
...confirmArg,
|
|
202
|
+
},
|
|
203
|
+
risk: "destructive",
|
|
204
|
+
summary: (args) => `publish staged Threads container ${args.container_id}`,
|
|
205
|
+
handler: async (args, ctx) => {
|
|
206
|
+
const account = ctx.account(args.account);
|
|
207
|
+
return publishContainer(ctx.client, account, args.container_id);
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
export const getContainerStatus = defineTool({
|
|
211
|
+
name: "get_container_status",
|
|
212
|
+
title: "Check a staged container",
|
|
213
|
+
description: "The processing status of a container: IN_PROGRESS, FINISHED, ERROR or EXPIRED, with the failure reason when there is one. Useful when a video is taking a long time, or to check whether a staged post is still within its 24-hour window.",
|
|
214
|
+
schema: {
|
|
215
|
+
container_id: z.string(),
|
|
216
|
+
...accountArg,
|
|
217
|
+
},
|
|
218
|
+
risk: "read",
|
|
219
|
+
handler: async (args, ctx) => {
|
|
220
|
+
const account = ctx.account(args.account);
|
|
221
|
+
const status = (await ctx.client.call(account, `/${args.container_id}`, {
|
|
222
|
+
params: { fields: "status,error_message" },
|
|
223
|
+
}));
|
|
224
|
+
return {
|
|
225
|
+
container_id: args.container_id,
|
|
226
|
+
status: status.status ?? "UNKNOWN",
|
|
227
|
+
...(status.error_message ? { error_message: status.error_message } : {}),
|
|
228
|
+
...(status.status === "ERROR"
|
|
229
|
+
? {
|
|
230
|
+
hint: "Container errors are nearly always the media URL. It has to be publicly reachable over HTTPS, return an image or video content type, and not redirect to a login page.",
|
|
231
|
+
}
|
|
232
|
+
: {}),
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
export const quotePost = defineTool({
|
|
237
|
+
name: "quote_post",
|
|
238
|
+
title: "Quote another post",
|
|
239
|
+
description: "Publish a post that quotes an existing Threads post. Public and irreversible, so this needs confirm: true.",
|
|
240
|
+
schema: {
|
|
241
|
+
text: z.string().describe("Your commentary. 500 characters."),
|
|
242
|
+
quoted_post_id: z.string().describe("Numeric id of the post being quoted."),
|
|
243
|
+
...accountArg,
|
|
244
|
+
...confirmArg,
|
|
245
|
+
},
|
|
246
|
+
risk: "destructive",
|
|
247
|
+
summary: (args) => `quote Threads post ${args.quoted_post_id}: "${snippet(args.text)}"`,
|
|
248
|
+
handler: async (args, ctx) => {
|
|
249
|
+
const account = ctx.account(args.account);
|
|
250
|
+
return publish(ctx.client, account, {
|
|
251
|
+
text: args.text,
|
|
252
|
+
quote_post_id: requireMediaId(args.quoted_post_id),
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
export const repost = defineTool({
|
|
257
|
+
name: "repost",
|
|
258
|
+
title: "Repost a post",
|
|
259
|
+
description: "Repost an existing Threads post to your own profile. This is visible to your followers immediately and the API has no un-repost call, so it needs confirm: true.",
|
|
260
|
+
schema: {
|
|
261
|
+
id: z.string().describe("Numeric id of the post to repost."),
|
|
262
|
+
...accountArg,
|
|
263
|
+
...confirmArg,
|
|
264
|
+
},
|
|
265
|
+
risk: "destructive",
|
|
266
|
+
summary: (args) => `repost Threads post ${args.id}`,
|
|
267
|
+
handler: async (args, ctx) => {
|
|
268
|
+
const account = ctx.account(args.account);
|
|
269
|
+
const id = requireMediaId(args.id);
|
|
270
|
+
const response = (await ctx.client.call(account, `/${id}/repost`, { method: "POST" }));
|
|
271
|
+
return {
|
|
272
|
+
repost_id: response.id ?? null,
|
|
273
|
+
original: id,
|
|
274
|
+
note: "Threads has no un-repost endpoint. Undo this in the app.",
|
|
275
|
+
};
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
export const deletePost = defineTool({
|
|
279
|
+
name: "delete_post",
|
|
280
|
+
title: "Delete one of your posts",
|
|
281
|
+
description: "Permanently delete one of your own Threads posts. There is no undo, no archive, and no edit endpoint to reach for instead: replies and likes go with it. Deletions are also capped at 100 per rolling 24 hours. Needs confirm: true.",
|
|
282
|
+
schema: {
|
|
283
|
+
id: z.string().describe("Numeric id of the post to delete."),
|
|
284
|
+
...accountArg,
|
|
285
|
+
...confirmArg,
|
|
286
|
+
},
|
|
287
|
+
risk: "destructive",
|
|
288
|
+
summary: (args) => `permanently delete Threads post ${args.id}`,
|
|
289
|
+
handler: async (args, ctx) => {
|
|
290
|
+
const account = ctx.account(args.account);
|
|
291
|
+
const id = requireMediaId(args.id);
|
|
292
|
+
// Meta's delete is an HTTP DELETE. Sending POST here returns a success-
|
|
293
|
+
// shaped response for a request that deleted nothing.
|
|
294
|
+
const response = await ctx.client.call(account, `/${id}`, { method: "DELETE" });
|
|
295
|
+
return {
|
|
296
|
+
deleted: deleteSucceeded(response) ? id : null,
|
|
297
|
+
...(deleteSucceeded(response) ? {} : { warning: "Threads did not confirm the deletion.", response }),
|
|
298
|
+
};
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
export const POST_TOOLS = [
|
|
302
|
+
createPost,
|
|
303
|
+
createThread,
|
|
304
|
+
createCarousel,
|
|
305
|
+
stagePost,
|
|
306
|
+
publishStaged,
|
|
307
|
+
getContainerStatus,
|
|
308
|
+
quotePost,
|
|
309
|
+
repost,
|
|
310
|
+
deletePost,
|
|
311
|
+
];
|
|
312
|
+
//# sourceMappingURL=posts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"posts.js","sourceRoot":"","sources":["../../src/tools/posts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading your own posts.
|
|
3
|
+
*
|
|
4
|
+
* `since_hours` pages until it reaches a time window rather than a count,
|
|
5
|
+
* because "what did I post this week" is a question about time and turning it
|
|
6
|
+
* into a guess at a post count is how you end up missing half of it.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
export declare const getPosts: import("./kit.js").ToolSpec<{
|
|
10
|
+
account: z.ZodOptional<z.ZodString>;
|
|
11
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
13
|
+
since_hours: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
since: z.ZodOptional<z.ZodString>;
|
|
15
|
+
until: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}>;
|
|
17
|
+
export declare const getPost: import("./kit.js").ToolSpec<{
|
|
18
|
+
account: z.ZodOptional<z.ZodString>;
|
|
19
|
+
id: z.ZodString;
|
|
20
|
+
}>;
|
|
21
|
+
export declare const READ_TOOLS: (import("./kit.js").ToolSpec<{
|
|
22
|
+
account: z.ZodOptional<z.ZodString>;
|
|
23
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
24
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
25
|
+
since_hours: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
since: z.ZodOptional<z.ZodString>;
|
|
27
|
+
until: z.ZodOptional<z.ZodString>;
|
|
28
|
+
}> | import("./kit.js").ToolSpec<{
|
|
29
|
+
account: z.ZodOptional<z.ZodString>;
|
|
30
|
+
id: z.ZodString;
|
|
31
|
+
}>)[];
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading your own posts.
|
|
3
|
+
*
|
|
4
|
+
* `since_hours` pages until it reaches a time window rather than a count,
|
|
5
|
+
* because "what did I post this week" is a question about time and turning it
|
|
6
|
+
* into a guess at a post count is how you end up missing half of it.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { accountArg, clamp, defineTool, pageArgs } from "./kit.js";
|
|
10
|
+
import { POST_FIELDS } from "../api/client.js";
|
|
11
|
+
import { cursorOf, dataOf, renderList, renderPost } from "../format/posts.js";
|
|
12
|
+
import { requireMediaId } from "../api/identity.js";
|
|
13
|
+
export const getPosts = defineTool({
|
|
14
|
+
name: "get_posts",
|
|
15
|
+
title: "Read your recent posts",
|
|
16
|
+
description: "Your own Threads posts, newest first, with ids and permalinks. The numeric id on each result is what every other tool wants: Threads has no way to convert a permalink back into an id, so this is where ids come from.",
|
|
17
|
+
schema: {
|
|
18
|
+
since_hours: z
|
|
19
|
+
.number()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Read back this many hours, paging as needed, rather than a fixed number of posts."),
|
|
22
|
+
since: z.string().optional().describe("ISO date or Unix timestamp to start from."),
|
|
23
|
+
until: z.string().optional().describe("ISO date or Unix timestamp to stop at."),
|
|
24
|
+
...pageArgs,
|
|
25
|
+
...accountArg,
|
|
26
|
+
},
|
|
27
|
+
risk: "read",
|
|
28
|
+
handler: async (args, ctx) => {
|
|
29
|
+
const account = ctx.account(args.account);
|
|
30
|
+
const userId = await ctx.client.userId(account);
|
|
31
|
+
const pageSize = clamp(args.limit, 25);
|
|
32
|
+
const cutoff = args.since_hours ? Date.now() - args.since_hours * 3_600_000 : undefined;
|
|
33
|
+
const collected = [];
|
|
34
|
+
let cursor = args.cursor;
|
|
35
|
+
let reachedCutoff = false;
|
|
36
|
+
// Without a window this is one page. With one, page until the timestamps
|
|
37
|
+
// cross it, capped so a busy account cannot spin here forever.
|
|
38
|
+
const maxPages = cutoff ? 10 : 1;
|
|
39
|
+
for (let page = 0; page < maxPages; page++) {
|
|
40
|
+
const response = (await ctx.client.call(account, `/${userId}/threads`, {
|
|
41
|
+
params: {
|
|
42
|
+
fields: POST_FIELDS,
|
|
43
|
+
limit: cutoff ? 100 : pageSize,
|
|
44
|
+
after: cursor,
|
|
45
|
+
since: args.since,
|
|
46
|
+
until: args.until,
|
|
47
|
+
},
|
|
48
|
+
}));
|
|
49
|
+
const items = dataOf(response);
|
|
50
|
+
if (!items.length)
|
|
51
|
+
break;
|
|
52
|
+
for (const item of items) {
|
|
53
|
+
if (cutoff) {
|
|
54
|
+
const at = new Date(String(item.timestamp)).getTime();
|
|
55
|
+
if (!Number.isNaN(at) && at < cutoff) {
|
|
56
|
+
reachedCutoff = true;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
collected.push(item);
|
|
61
|
+
}
|
|
62
|
+
cursor = cursorOf(response);
|
|
63
|
+
if (reachedCutoff || !cursor)
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
return renderList(collected, {
|
|
67
|
+
source: "posts",
|
|
68
|
+
cursor: reachedCutoff ? undefined : cursor,
|
|
69
|
+
meta: {
|
|
70
|
+
account: account.username,
|
|
71
|
+
...(args.since_hours ? { since_hours: args.since_hours } : {}),
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
export const getPost = defineTool({
|
|
77
|
+
name: "get_post",
|
|
78
|
+
title: "Read one post",
|
|
79
|
+
description: "One Threads post by its numeric id, with its full field set: text, media, permalink, topic tag, link attachment, quoted post and whether it has replies.",
|
|
80
|
+
schema: {
|
|
81
|
+
id: z.string().describe("Numeric post id."),
|
|
82
|
+
...accountArg,
|
|
83
|
+
},
|
|
84
|
+
risk: "read",
|
|
85
|
+
handler: async (args, ctx) => {
|
|
86
|
+
const account = ctx.account(args.account);
|
|
87
|
+
const id = requireMediaId(args.id);
|
|
88
|
+
const post = (await ctx.client.call(account, `/${id}`, {
|
|
89
|
+
params: { fields: `${POST_FIELDS},allowlisted_country_codes` },
|
|
90
|
+
}));
|
|
91
|
+
return renderPost(post, 0);
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
export const READ_TOOLS = [getPosts, getPost];
|
|
95
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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"}
|