posterly-mcp-server 0.19.6 → 0.19.7
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/README.md +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/format.d.ts +11 -0
- package/dist/lib/format.js +51 -0
- package/dist/tools/create-connect-session.d.ts +4 -0
- package/dist/tools/create-connect-session.js +17 -8
- package/dist/tools/create-post.d.ts +39 -39
- package/dist/tools/create-post.js +8 -4
- package/dist/tools/create-posts-batch.d.ts +29 -29
- package/dist/tools/create-posts-batch.js +7 -1
- package/dist/tools/delete-post.js +8 -1
- package/dist/tools/get-agent-signup-info.js +5 -0
- package/dist/tools/get-connect-link.d.ts +4 -0
- package/dist/tools/get-connect-link.js +7 -2
- package/dist/tools/get-connect-session.d.ts +4 -0
- package/dist/tools/get-connect-session.js +33 -5
- package/dist/tools/get-post.js +3 -1
- package/dist/tools/get-signup-session.d.ts +4 -0
- package/dist/tools/get-signup-session.js +8 -5
- package/dist/tools/list-posts.js +11 -4
- package/dist/tools/start-signup.d.ts +4 -0
- package/dist/tools/start-signup.js +8 -5
- package/dist/tools/update-post.d.ts +20 -20
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/lib/format.ts +56 -0
- package/src/tools/create-connect-session.ts +18 -9
- package/src/tools/create-post.ts +11 -4
- package/src/tools/create-posts-batch.ts +11 -1
- package/src/tools/delete-post.ts +8 -1
- package/src/tools/get-agent-signup-info.ts +5 -0
- package/src/tools/get-connect-link.ts +8 -3
- package/src/tools/get-connect-session.ts +35 -6
- package/src/tools/get-post.ts +3 -1
- package/src/tools/get-signup-session.ts +9 -6
- package/src/tools/list-posts.ts +11 -5
- package/src/tools/start-signup.ts +9 -5
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ Add the same server definition to your Cursor MCP settings:
|
|
|
103
103
|
|
|
104
104
|
## Available tools
|
|
105
105
|
|
|
106
|
-
`posterly-mcp-server@0.19.
|
|
106
|
+
`posterly-mcp-server@0.19.7` exposes 54 tools.
|
|
107
107
|
|
|
108
108
|
Public signup tools work before `POSTERLY_API_KEY` exists:
|
|
109
109
|
|
package/dist/index.js
CHANGED
|
@@ -58,7 +58,7 @@ import { updateOAuthClientTool } from './tools/update-oauth-client.js';
|
|
|
58
58
|
import { deleteOAuthClientTool } from './tools/delete-oauth-client.js';
|
|
59
59
|
const server = new McpServer({
|
|
60
60
|
name: 'posterly',
|
|
61
|
-
version: '0.19.
|
|
61
|
+
version: '0.19.7',
|
|
62
62
|
});
|
|
63
63
|
const client = new PosterlyClient();
|
|
64
64
|
// Register tools
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Account, Post } from './api-client.js';
|
|
2
|
+
export declare const DASHBOARD_CALENDAR_URL: string;
|
|
3
|
+
export declare const DASHBOARD_TABLE_URL: string;
|
|
4
|
+
export declare const DASHBOARD_CONNECT_URL: string;
|
|
5
|
+
export declare function formatLocalDateTime(value?: string | null): string;
|
|
6
|
+
export declare function dashboardUrlForPost(post: Pick<Post, 'id' | 'scheduled_at'>): string;
|
|
7
|
+
export declare function dashboardUrlForPosts(): string;
|
|
8
|
+
export declare function dashboardUrlForPostList(posts: Array<Pick<Post, 'scheduled_at'>>): string;
|
|
9
|
+
export declare function truncateText(value: string | null | undefined, max?: number): string;
|
|
10
|
+
export declare function formatAccountLabel(account: Account): string;
|
|
11
|
+
export declare function formatConnectedAccounts(accounts?: Account[]): string;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const POSTERLY_APP_URL = (process.env.POSTERLY_URL || 'https://www.poster.ly').replace(/\/$/, '');
|
|
2
|
+
export const DASHBOARD_CALENDAR_URL = `${POSTERLY_APP_URL}/dashboard/calendar`;
|
|
3
|
+
export const DASHBOARD_TABLE_URL = `${POSTERLY_APP_URL}/dashboard/table`;
|
|
4
|
+
export const DASHBOARD_CONNECT_URL = `${POSTERLY_APP_URL}/dashboard/connect`;
|
|
5
|
+
export function formatLocalDateTime(value) {
|
|
6
|
+
if (!value)
|
|
7
|
+
return 'N/A';
|
|
8
|
+
const date = new Date(value);
|
|
9
|
+
if (Number.isNaN(date.getTime()))
|
|
10
|
+
return value;
|
|
11
|
+
return date.toLocaleString();
|
|
12
|
+
}
|
|
13
|
+
export function dashboardUrlForPost(post) {
|
|
14
|
+
const baseUrl = isInCurrentMonth(post.scheduled_at) ? DASHBOARD_CALENDAR_URL : DASHBOARD_TABLE_URL;
|
|
15
|
+
const url = new URL(baseUrl);
|
|
16
|
+
url.searchParams.set('post_id', String(post.id));
|
|
17
|
+
return url.toString();
|
|
18
|
+
}
|
|
19
|
+
export function dashboardUrlForPosts() {
|
|
20
|
+
return DASHBOARD_TABLE_URL;
|
|
21
|
+
}
|
|
22
|
+
export function dashboardUrlForPostList(posts) {
|
|
23
|
+
if (posts.length > 0 && posts.every((post) => isInCurrentMonth(post.scheduled_at))) {
|
|
24
|
+
return DASHBOARD_CALENDAR_URL;
|
|
25
|
+
}
|
|
26
|
+
return DASHBOARD_TABLE_URL;
|
|
27
|
+
}
|
|
28
|
+
export function truncateText(value, max = 80) {
|
|
29
|
+
const text = value?.trim() || '';
|
|
30
|
+
if (!text)
|
|
31
|
+
return '(empty)';
|
|
32
|
+
return text.length > max ? `${text.slice(0, max - 1)}...` : text;
|
|
33
|
+
}
|
|
34
|
+
export function formatAccountLabel(account) {
|
|
35
|
+
const username = account.username ? `@${account.username}` : `account ${account.id}`;
|
|
36
|
+
return `${account.platform} ${username}`;
|
|
37
|
+
}
|
|
38
|
+
export function formatConnectedAccounts(accounts) {
|
|
39
|
+
if (!accounts?.length)
|
|
40
|
+
return 'none yet';
|
|
41
|
+
return accounts.map(formatAccountLabel).join(', ');
|
|
42
|
+
}
|
|
43
|
+
function isInCurrentMonth(value) {
|
|
44
|
+
if (!value)
|
|
45
|
+
return false;
|
|
46
|
+
const date = new Date(value);
|
|
47
|
+
if (Number.isNaN(date.getTime()))
|
|
48
|
+
return false;
|
|
49
|
+
const now = new Date();
|
|
50
|
+
return date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth();
|
|
51
|
+
}
|
|
@@ -7,18 +7,22 @@ export declare const createConnectSessionTool: {
|
|
|
7
7
|
platform: z.ZodEnum<["bluesky", "devto", "discord", "facebook", "facebook_instagram", "facebook_pages", "gmb", "google-business", "google_business", "google_business_profile", "hashnode", "instagram", "instagram-standalone", "instagram_direct", "linkedin", "linkedin-company", "linkedin-page", "linkedin_company", "linkedin_page", "linkedin_personal", "mastodon", "medium", "meta", "meta_business", "pinterest", "reddit", "skool", "slack", "telegram", "threads", "tiktok", "twitter", "whop", "wordpress", "x", "x_twitter", "youtube"]>;
|
|
8
8
|
workspace_id: z.ZodOptional<z.ZodString>;
|
|
9
9
|
auto_start: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
+
debug: z.ZodOptional<z.ZodBoolean>;
|
|
10
11
|
}, "strip", z.ZodTypeAny, {
|
|
11
12
|
platform: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "reddit" | "wordpress" | "mastodon" | "medium" | "devto" | "hashnode" | "discord" | "slack" | "skool" | "whop" | "gmb" | "google-business" | "google_business_profile" | "x" | "meta" | "linkedin_page" | "facebook_instagram" | "facebook_pages" | "instagram_direct" | "linkedin-company" | "linkedin-page" | "linkedin_company" | "linkedin_personal" | "meta_business" | "x_twitter";
|
|
12
13
|
workspace_id?: string | undefined;
|
|
13
14
|
auto_start?: boolean | undefined;
|
|
15
|
+
debug?: boolean | undefined;
|
|
14
16
|
}, {
|
|
15
17
|
platform: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "reddit" | "wordpress" | "mastodon" | "medium" | "devto" | "hashnode" | "discord" | "slack" | "skool" | "whop" | "gmb" | "google-business" | "google_business_profile" | "x" | "meta" | "linkedin_page" | "facebook_instagram" | "facebook_pages" | "instagram_direct" | "linkedin-company" | "linkedin-page" | "linkedin_company" | "linkedin_personal" | "meta_business" | "x_twitter";
|
|
16
18
|
workspace_id?: string | undefined;
|
|
17
19
|
auto_start?: boolean | undefined;
|
|
20
|
+
debug?: boolean | undefined;
|
|
18
21
|
}>;
|
|
19
22
|
execute(client: PosterlyClient, input: {
|
|
20
23
|
platform: string;
|
|
21
24
|
workspace_id?: string;
|
|
22
25
|
auto_start?: boolean;
|
|
26
|
+
debug?: boolean;
|
|
23
27
|
}): Promise<string>;
|
|
24
28
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { DASHBOARD_CONNECT_URL, formatConnectedAccounts, formatLocalDateTime } from '../lib/format.js';
|
|
2
3
|
import { CONNECT_INPUTS } from '../generated/platform-manifest.js';
|
|
3
4
|
export const createConnectSessionTool = {
|
|
4
5
|
name: 'create_connect_session',
|
|
5
|
-
description: 'Create a short-lived Posterly dashboard handoff session for connecting a social account.
|
|
6
|
+
description: 'Create a short-lived Posterly dashboard handoff session for connecting a social account. Send the secure connection URL to the user, then poll get_connect_session to narrate progress. Do not ask for social media passwords or OAuth codes; Posterly handles those browser steps.',
|
|
6
7
|
inputSchema: z.object({
|
|
7
8
|
platform: z
|
|
8
9
|
.enum(CONNECT_INPUTS)
|
|
@@ -15,24 +16,32 @@ export const createConnectSessionTool = {
|
|
|
15
16
|
.boolean()
|
|
16
17
|
.optional()
|
|
17
18
|
.describe('When true, the dashboard starts the provider flow after the user opens the URL. Defaults to true.'),
|
|
19
|
+
debug: z
|
|
20
|
+
.boolean()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('When true, include the raw connect session JSON for debugging. Keep false for normal user-facing agent flows.'),
|
|
18
23
|
}),
|
|
19
24
|
async execute(client, input) {
|
|
20
|
-
const
|
|
21
|
-
|
|
25
|
+
const { debug, ...payload } = input;
|
|
26
|
+
const result = await client.createConnectSession(payload);
|
|
27
|
+
return formatConnectSession(result.connect_session, Boolean(debug));
|
|
22
28
|
},
|
|
23
29
|
};
|
|
24
30
|
function formatConnectSession(session, includeRaw) {
|
|
31
|
+
const connected = session.connected_count ?? session.connected_accounts?.length ?? 0;
|
|
25
32
|
return [
|
|
26
|
-
`Posterly connect session: ${session.id}`,
|
|
33
|
+
`Posterly connect session created: ${session.id}`,
|
|
27
34
|
`Platform: ${session.platform}`,
|
|
28
35
|
`Status: ${session.status}`,
|
|
29
36
|
`Message: ${session.status_message}`,
|
|
30
|
-
`
|
|
37
|
+
`Secure connection URL: ${session.connect_url}`,
|
|
31
38
|
`Poll URL: ${session.poll_url}`,
|
|
32
|
-
`Connected accounts: ${
|
|
33
|
-
`
|
|
39
|
+
`Connected accounts: ${connected}`,
|
|
40
|
+
`Accounts: ${formatConnectedAccounts(session.connected_accounts)}`,
|
|
41
|
+
`Expires: ${formatLocalDateTime(session.expires_at)}`,
|
|
42
|
+
`Dashboard connect page: ${DASHBOARD_CONNECT_URL}`,
|
|
34
43
|
'',
|
|
35
|
-
'Next step:
|
|
44
|
+
'Next step for the AI agent: send the secure connection URL to the user, explain that Posterly will handle the browser OAuth step, then poll get_connect_session until the account is connected or the session ends.',
|
|
36
45
|
includeRaw ? `\nRaw connect session:\n${JSON.stringify(session, null, 2)}` : '',
|
|
37
46
|
].filter(Boolean).join('\n');
|
|
38
47
|
}
|
|
@@ -36,8 +36,10 @@ export declare const instagramSettingsSchema: z.ZodObject<{
|
|
|
36
36
|
reel_cover_url: z.ZodOptional<z.ZodString>;
|
|
37
37
|
reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
|
|
38
38
|
}, "strip", z.ZodTypeAny, {
|
|
39
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
40
39
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
40
|
+
reel_cover_url?: string | undefined;
|
|
41
|
+
reel_thumb_offset?: number | undefined;
|
|
42
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
41
43
|
is_trial_reel?: boolean | undefined;
|
|
42
44
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
43
45
|
collaborators?: (string | {
|
|
@@ -52,11 +54,11 @@ export declare const instagramSettingsSchema: z.ZodObject<{
|
|
|
52
54
|
})[] | undefined;
|
|
53
55
|
first_comment?: string | undefined;
|
|
54
56
|
media_alt_texts?: Record<string, string> | undefined;
|
|
57
|
+
}, {
|
|
58
|
+
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
55
59
|
reel_cover_url?: string | undefined;
|
|
56
60
|
reel_thumb_offset?: number | undefined;
|
|
57
|
-
}, {
|
|
58
61
|
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
59
|
-
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
60
62
|
is_trial_reel?: boolean | undefined;
|
|
61
63
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
62
64
|
collaborators?: (string | {
|
|
@@ -71,8 +73,6 @@ export declare const instagramSettingsSchema: z.ZodObject<{
|
|
|
71
73
|
})[] | undefined;
|
|
72
74
|
first_comment?: string | undefined;
|
|
73
75
|
media_alt_texts?: Record<string, string> | undefined;
|
|
74
|
-
reel_cover_url?: string | undefined;
|
|
75
|
-
reel_thumb_offset?: number | undefined;
|
|
76
76
|
}>;
|
|
77
77
|
export declare const platformSettingsSchema: z.ZodObject<{
|
|
78
78
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -265,8 +265,10 @@ export declare const createPostInputSchema: z.ZodObject<{
|
|
|
265
265
|
reel_cover_url: z.ZodOptional<z.ZodString>;
|
|
266
266
|
reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
|
|
267
267
|
}, "strip", z.ZodTypeAny, {
|
|
268
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
269
268
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
269
|
+
reel_cover_url?: string | undefined;
|
|
270
|
+
reel_thumb_offset?: number | undefined;
|
|
271
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
270
272
|
is_trial_reel?: boolean | undefined;
|
|
271
273
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
272
274
|
collaborators?: (string | {
|
|
@@ -281,11 +283,11 @@ export declare const createPostInputSchema: z.ZodObject<{
|
|
|
281
283
|
})[] | undefined;
|
|
282
284
|
first_comment?: string | undefined;
|
|
283
285
|
media_alt_texts?: Record<string, string> | undefined;
|
|
286
|
+
}, {
|
|
287
|
+
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
284
288
|
reel_cover_url?: string | undefined;
|
|
285
289
|
reel_thumb_offset?: number | undefined;
|
|
286
|
-
}, {
|
|
287
290
|
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
288
|
-
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
289
291
|
is_trial_reel?: boolean | undefined;
|
|
290
292
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
291
293
|
collaborators?: (string | {
|
|
@@ -300,8 +302,6 @@ export declare const createPostInputSchema: z.ZodObject<{
|
|
|
300
302
|
})[] | undefined;
|
|
301
303
|
first_comment?: string | undefined;
|
|
302
304
|
media_alt_texts?: Record<string, string> | undefined;
|
|
303
|
-
reel_cover_url?: string | undefined;
|
|
304
|
-
reel_thumb_offset?: number | undefined;
|
|
305
305
|
}>>;
|
|
306
306
|
platform_settings: z.ZodOptional<z.ZodObject<{
|
|
307
307
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -453,16 +453,18 @@ export declare const createPostInputSchema: z.ZodObject<{
|
|
|
453
453
|
workspace_id?: string | undefined;
|
|
454
454
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
455
455
|
account_id?: string | undefined;
|
|
456
|
-
post_type?: string | undefined;
|
|
457
|
-
username?: string | undefined;
|
|
458
|
-
caption?: string | undefined;
|
|
459
456
|
scheduled_at?: string | undefined;
|
|
460
457
|
media_url?: string | undefined;
|
|
461
458
|
media_urls?: string[] | undefined;
|
|
459
|
+
post_type?: string | undefined;
|
|
460
|
+
username?: string | undefined;
|
|
461
|
+
caption?: string | undefined;
|
|
462
462
|
thread_posts?: string[] | undefined;
|
|
463
463
|
instagram_settings?: {
|
|
464
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
465
464
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
465
|
+
reel_cover_url?: string | undefined;
|
|
466
|
+
reel_thumb_offset?: number | undefined;
|
|
467
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
466
468
|
is_trial_reel?: boolean | undefined;
|
|
467
469
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
468
470
|
collaborators?: (string | {
|
|
@@ -477,8 +479,6 @@ export declare const createPostInputSchema: z.ZodObject<{
|
|
|
477
479
|
})[] | undefined;
|
|
478
480
|
first_comment?: string | undefined;
|
|
479
481
|
media_alt_texts?: Record<string, string> | undefined;
|
|
480
|
-
reel_cover_url?: string | undefined;
|
|
481
|
-
reel_thumb_offset?: number | undefined;
|
|
482
482
|
} | undefined;
|
|
483
483
|
platform_settings?: z.objectOutputType<{
|
|
484
484
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -533,16 +533,18 @@ export declare const createPostInputSchema: z.ZodObject<{
|
|
|
533
533
|
workspace_id?: string | undefined;
|
|
534
534
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
535
535
|
account_id?: string | undefined;
|
|
536
|
-
post_type?: string | undefined;
|
|
537
|
-
username?: string | undefined;
|
|
538
|
-
caption?: string | undefined;
|
|
539
536
|
scheduled_at?: string | undefined;
|
|
540
537
|
media_url?: string | undefined;
|
|
541
538
|
media_urls?: string[] | undefined;
|
|
539
|
+
post_type?: string | undefined;
|
|
540
|
+
username?: string | undefined;
|
|
541
|
+
caption?: string | undefined;
|
|
542
542
|
thread_posts?: string[] | undefined;
|
|
543
543
|
instagram_settings?: {
|
|
544
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
545
544
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
545
|
+
reel_cover_url?: string | undefined;
|
|
546
|
+
reel_thumb_offset?: number | undefined;
|
|
547
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
546
548
|
is_trial_reel?: boolean | undefined;
|
|
547
549
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
548
550
|
collaborators?: (string | {
|
|
@@ -557,8 +559,6 @@ export declare const createPostInputSchema: z.ZodObject<{
|
|
|
557
559
|
})[] | undefined;
|
|
558
560
|
first_comment?: string | undefined;
|
|
559
561
|
media_alt_texts?: Record<string, string> | undefined;
|
|
560
|
-
reel_cover_url?: string | undefined;
|
|
561
|
-
reel_thumb_offset?: number | undefined;
|
|
562
562
|
} | undefined;
|
|
563
563
|
platform_settings?: z.objectInputType<{
|
|
564
564
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -661,8 +661,10 @@ export declare const createPostTool: {
|
|
|
661
661
|
reel_cover_url: z.ZodOptional<z.ZodString>;
|
|
662
662
|
reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
|
|
663
663
|
}, "strip", z.ZodTypeAny, {
|
|
664
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
665
664
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
665
|
+
reel_cover_url?: string | undefined;
|
|
666
|
+
reel_thumb_offset?: number | undefined;
|
|
667
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
666
668
|
is_trial_reel?: boolean | undefined;
|
|
667
669
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
668
670
|
collaborators?: (string | {
|
|
@@ -677,11 +679,11 @@ export declare const createPostTool: {
|
|
|
677
679
|
})[] | undefined;
|
|
678
680
|
first_comment?: string | undefined;
|
|
679
681
|
media_alt_texts?: Record<string, string> | undefined;
|
|
682
|
+
}, {
|
|
683
|
+
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
680
684
|
reel_cover_url?: string | undefined;
|
|
681
685
|
reel_thumb_offset?: number | undefined;
|
|
682
|
-
}, {
|
|
683
686
|
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
684
|
-
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
685
687
|
is_trial_reel?: boolean | undefined;
|
|
686
688
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
687
689
|
collaborators?: (string | {
|
|
@@ -696,8 +698,6 @@ export declare const createPostTool: {
|
|
|
696
698
|
})[] | undefined;
|
|
697
699
|
first_comment?: string | undefined;
|
|
698
700
|
media_alt_texts?: Record<string, string> | undefined;
|
|
699
|
-
reel_cover_url?: string | undefined;
|
|
700
|
-
reel_thumb_offset?: number | undefined;
|
|
701
701
|
}>>;
|
|
702
702
|
platform_settings: z.ZodOptional<z.ZodObject<{
|
|
703
703
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -849,16 +849,18 @@ export declare const createPostTool: {
|
|
|
849
849
|
workspace_id?: string | undefined;
|
|
850
850
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
851
851
|
account_id?: string | undefined;
|
|
852
|
-
post_type?: string | undefined;
|
|
853
|
-
username?: string | undefined;
|
|
854
|
-
caption?: string | undefined;
|
|
855
852
|
scheduled_at?: string | undefined;
|
|
856
853
|
media_url?: string | undefined;
|
|
857
854
|
media_urls?: string[] | undefined;
|
|
855
|
+
post_type?: string | undefined;
|
|
856
|
+
username?: string | undefined;
|
|
857
|
+
caption?: string | undefined;
|
|
858
858
|
thread_posts?: string[] | undefined;
|
|
859
859
|
instagram_settings?: {
|
|
860
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
861
860
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
861
|
+
reel_cover_url?: string | undefined;
|
|
862
|
+
reel_thumb_offset?: number | undefined;
|
|
863
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
862
864
|
is_trial_reel?: boolean | undefined;
|
|
863
865
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
864
866
|
collaborators?: (string | {
|
|
@@ -873,8 +875,6 @@ export declare const createPostTool: {
|
|
|
873
875
|
})[] | undefined;
|
|
874
876
|
first_comment?: string | undefined;
|
|
875
877
|
media_alt_texts?: Record<string, string> | undefined;
|
|
876
|
-
reel_cover_url?: string | undefined;
|
|
877
|
-
reel_thumb_offset?: number | undefined;
|
|
878
878
|
} | undefined;
|
|
879
879
|
platform_settings?: z.objectOutputType<{
|
|
880
880
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -929,16 +929,18 @@ export declare const createPostTool: {
|
|
|
929
929
|
workspace_id?: string | undefined;
|
|
930
930
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
931
931
|
account_id?: string | undefined;
|
|
932
|
-
post_type?: string | undefined;
|
|
933
|
-
username?: string | undefined;
|
|
934
|
-
caption?: string | undefined;
|
|
935
932
|
scheduled_at?: string | undefined;
|
|
936
933
|
media_url?: string | undefined;
|
|
937
934
|
media_urls?: string[] | undefined;
|
|
935
|
+
post_type?: string | undefined;
|
|
936
|
+
username?: string | undefined;
|
|
937
|
+
caption?: string | undefined;
|
|
938
938
|
thread_posts?: string[] | undefined;
|
|
939
939
|
instagram_settings?: {
|
|
940
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
941
940
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
941
|
+
reel_cover_url?: string | undefined;
|
|
942
|
+
reel_thumb_offset?: number | undefined;
|
|
943
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
942
944
|
is_trial_reel?: boolean | undefined;
|
|
943
945
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
944
946
|
collaborators?: (string | {
|
|
@@ -953,8 +955,6 @@ export declare const createPostTool: {
|
|
|
953
955
|
})[] | undefined;
|
|
954
956
|
first_comment?: string | undefined;
|
|
955
957
|
media_alt_texts?: Record<string, string> | undefined;
|
|
956
|
-
reel_cover_url?: string | undefined;
|
|
957
|
-
reel_thumb_offset?: number | undefined;
|
|
958
958
|
} | undefined;
|
|
959
959
|
platform_settings?: z.objectInputType<{
|
|
960
960
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { dashboardUrlForPost, formatLocalDateTime } from '../lib/format.js';
|
|
2
3
|
import { SUPPORTED_PLATFORM_INPUTS, SUPPORTED_PLATFORM_IDS } from '../generated/platform-manifest.js';
|
|
3
4
|
export const instagramSettingsSchema = z.object({
|
|
4
5
|
__type: z.enum(['instagram', 'instagram-standalone']).optional(),
|
|
@@ -149,6 +150,7 @@ export const createPostTool = {
|
|
|
149
150
|
'2. Show the user a preview containing ALL of: account(s) and platform(s), final caption text, scheduled time (in the user\'s timezone), media attached (if any), and workspace name.\n' +
|
|
150
151
|
'3. Get explicit confirmation from the user (e.g. "post it", "yes schedule that", "looks good") BEFORE calling this tool. Do NOT infer consent from earlier instructions like "post about X every Monday" — confirm each individual post or the entire batch.\n' +
|
|
151
152
|
'4. If scheduling multiple posts in one turn, list every post first and confirm the batch as a whole, then prefer `create_posts_batch` so they are created in one API request.\n\n' +
|
|
153
|
+
'AFTER CALLING: Tell the user the post was created, include the Posterly dashboard link returned by the tool, and offer the next natural action. Do not narrate raw HTTP, curl, or API plumbing.\n\n' +
|
|
152
154
|
'Provide either account_id OR username+platform to identify the account. If scheduled_at is omitted, the post publishes immediately. If workspace_id is omitted, the server resolves one from the social account, falling back to the caller\'s default (personal) workspace — pass workspace_id explicitly if the user has more than one workspace.\n\n' +
|
|
153
155
|
'THREADS: Pass `thread_posts` (an array of 2+ strings) to schedule a multi-post thread on X (Twitter) or Threads (Meta). The first entry is the lead post; the rest are published as replies in the same chain. X entries are capped at 280 characters each (4000 for verified, 25000 for organization accounts); Threads entries are capped at 500 characters each. When `thread_posts` is set, `caption` is ignored.\n\n' +
|
|
154
156
|
'PLATFORM SETTINGS: Pass `platform_settings` for composer-equivalent controls: Facebook story/reel/backgrounds, YouTube title/privacy/thumbnail/playlist, LinkedIn document titles/mentions/video thumbnails, TikTok direct-post privacy/toggles/commercial disclosure, Pinterest post_type (image/video/carousel), board (from pinterest.boards helper), title, link, and cover_image_url (video Pins), GBP event/offer/CTA, X reply settings/polls, Threads reply controls/text attachments, Bluesky languages/alt text, and Instagram feed/story/reel/carousel/collaborators/first comments/trial Reels. `instagram_settings` remains as a backwards-compatible alias.',
|
|
@@ -159,16 +161,17 @@ export const createPostTool = {
|
|
|
159
161
|
const result = await client.createPost(payload);
|
|
160
162
|
const p = result.post;
|
|
161
163
|
const ws = result.workspace;
|
|
162
|
-
const when = p.scheduled_at
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
const when = p.scheduled_at ? formatLocalDateTime(p.scheduled_at) : 'now';
|
|
165
|
+
const dashboardUrl = dashboardUrlForPost({ id: p.id, scheduled_at: p.scheduled_at });
|
|
166
|
+
const createdLine = p.scheduled_at ? 'Post scheduled successfully.' : 'Post created successfully.';
|
|
165
167
|
const lines = [
|
|
166
|
-
|
|
168
|
+
createdLine,
|
|
167
169
|
`• ID: ${p.id}`,
|
|
168
170
|
`• Platform: ${p.platform || input.platform || 'unknown'}`,
|
|
169
171
|
`• Type: ${p.post_type}`,
|
|
170
172
|
`• Status: ${p.status}`,
|
|
171
173
|
`• Scheduled: ${when}`,
|
|
174
|
+
`• View in Posterly: ${dashboardUrl}`,
|
|
172
175
|
];
|
|
173
176
|
if (thread_posts) {
|
|
174
177
|
lines.push(`• Thread: ${thread_posts.length} posts`);
|
|
@@ -185,6 +188,7 @@ export const createPostTool = {
|
|
|
185
188
|
if (ws) {
|
|
186
189
|
lines.push(`• Workspace: ${ws.name} (${ws.id}) — resolved from ${ws.resolved_from}`);
|
|
187
190
|
}
|
|
191
|
+
lines.push('', 'Next step for the AI agent: tell the user the post is in Posterly, share the dashboard link above, then ask whether they want to create another post, adjust this one, or connect another account.');
|
|
188
192
|
return lines.join('\n');
|
|
189
193
|
},
|
|
190
194
|
};
|
|
@@ -51,8 +51,10 @@ export declare const createPostsBatchTool: {
|
|
|
51
51
|
reel_cover_url: z.ZodOptional<z.ZodString>;
|
|
52
52
|
reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
|
|
53
53
|
}, "strip", z.ZodTypeAny, {
|
|
54
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
55
54
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
55
|
+
reel_cover_url?: string | undefined;
|
|
56
|
+
reel_thumb_offset?: number | undefined;
|
|
57
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
56
58
|
is_trial_reel?: boolean | undefined;
|
|
57
59
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
58
60
|
collaborators?: (string | {
|
|
@@ -67,11 +69,11 @@ export declare const createPostsBatchTool: {
|
|
|
67
69
|
})[] | undefined;
|
|
68
70
|
first_comment?: string | undefined;
|
|
69
71
|
media_alt_texts?: Record<string, string> | undefined;
|
|
72
|
+
}, {
|
|
73
|
+
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
70
74
|
reel_cover_url?: string | undefined;
|
|
71
75
|
reel_thumb_offset?: number | undefined;
|
|
72
|
-
}, {
|
|
73
76
|
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
74
|
-
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
75
77
|
is_trial_reel?: boolean | undefined;
|
|
76
78
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
77
79
|
collaborators?: (string | {
|
|
@@ -86,8 +88,6 @@ export declare const createPostsBatchTool: {
|
|
|
86
88
|
})[] | undefined;
|
|
87
89
|
first_comment?: string | undefined;
|
|
88
90
|
media_alt_texts?: Record<string, string> | undefined;
|
|
89
|
-
reel_cover_url?: string | undefined;
|
|
90
|
-
reel_thumb_offset?: number | undefined;
|
|
91
91
|
}>>;
|
|
92
92
|
platform_settings: z.ZodOptional<z.ZodObject<{
|
|
93
93
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -239,16 +239,18 @@ export declare const createPostsBatchTool: {
|
|
|
239
239
|
workspace_id?: string | undefined;
|
|
240
240
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
241
241
|
account_id?: string | undefined;
|
|
242
|
-
post_type?: string | undefined;
|
|
243
|
-
username?: string | undefined;
|
|
244
|
-
caption?: string | undefined;
|
|
245
242
|
scheduled_at?: string | undefined;
|
|
246
243
|
media_url?: string | undefined;
|
|
247
244
|
media_urls?: string[] | undefined;
|
|
245
|
+
post_type?: string | undefined;
|
|
246
|
+
username?: string | undefined;
|
|
247
|
+
caption?: string | undefined;
|
|
248
248
|
thread_posts?: string[] | undefined;
|
|
249
249
|
instagram_settings?: {
|
|
250
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
251
250
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
251
|
+
reel_cover_url?: string | undefined;
|
|
252
|
+
reel_thumb_offset?: number | undefined;
|
|
253
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
252
254
|
is_trial_reel?: boolean | undefined;
|
|
253
255
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
254
256
|
collaborators?: (string | {
|
|
@@ -263,8 +265,6 @@ export declare const createPostsBatchTool: {
|
|
|
263
265
|
})[] | undefined;
|
|
264
266
|
first_comment?: string | undefined;
|
|
265
267
|
media_alt_texts?: Record<string, string> | undefined;
|
|
266
|
-
reel_cover_url?: string | undefined;
|
|
267
|
-
reel_thumb_offset?: number | undefined;
|
|
268
268
|
} | undefined;
|
|
269
269
|
platform_settings?: z.objectOutputType<{
|
|
270
270
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -319,16 +319,18 @@ export declare const createPostsBatchTool: {
|
|
|
319
319
|
workspace_id?: string | undefined;
|
|
320
320
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
321
321
|
account_id?: string | undefined;
|
|
322
|
-
post_type?: string | undefined;
|
|
323
|
-
username?: string | undefined;
|
|
324
|
-
caption?: string | undefined;
|
|
325
322
|
scheduled_at?: string | undefined;
|
|
326
323
|
media_url?: string | undefined;
|
|
327
324
|
media_urls?: string[] | undefined;
|
|
325
|
+
post_type?: string | undefined;
|
|
326
|
+
username?: string | undefined;
|
|
327
|
+
caption?: string | undefined;
|
|
328
328
|
thread_posts?: string[] | undefined;
|
|
329
329
|
instagram_settings?: {
|
|
330
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
331
330
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
331
|
+
reel_cover_url?: string | undefined;
|
|
332
|
+
reel_thumb_offset?: number | undefined;
|
|
333
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
332
334
|
is_trial_reel?: boolean | undefined;
|
|
333
335
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
334
336
|
collaborators?: (string | {
|
|
@@ -343,8 +345,6 @@ export declare const createPostsBatchTool: {
|
|
|
343
345
|
})[] | undefined;
|
|
344
346
|
first_comment?: string | undefined;
|
|
345
347
|
media_alt_texts?: Record<string, string> | undefined;
|
|
346
|
-
reel_cover_url?: string | undefined;
|
|
347
|
-
reel_thumb_offset?: number | undefined;
|
|
348
348
|
} | undefined;
|
|
349
349
|
platform_settings?: z.objectInputType<{
|
|
350
350
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -401,16 +401,18 @@ export declare const createPostsBatchTool: {
|
|
|
401
401
|
workspace_id?: string | undefined;
|
|
402
402
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
403
403
|
account_id?: string | undefined;
|
|
404
|
-
post_type?: string | undefined;
|
|
405
|
-
username?: string | undefined;
|
|
406
|
-
caption?: string | undefined;
|
|
407
404
|
scheduled_at?: string | undefined;
|
|
408
405
|
media_url?: string | undefined;
|
|
409
406
|
media_urls?: string[] | undefined;
|
|
407
|
+
post_type?: string | undefined;
|
|
408
|
+
username?: string | undefined;
|
|
409
|
+
caption?: string | undefined;
|
|
410
410
|
thread_posts?: string[] | undefined;
|
|
411
411
|
instagram_settings?: {
|
|
412
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
413
412
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
413
|
+
reel_cover_url?: string | undefined;
|
|
414
|
+
reel_thumb_offset?: number | undefined;
|
|
415
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
414
416
|
is_trial_reel?: boolean | undefined;
|
|
415
417
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
416
418
|
collaborators?: (string | {
|
|
@@ -425,8 +427,6 @@ export declare const createPostsBatchTool: {
|
|
|
425
427
|
})[] | undefined;
|
|
426
428
|
first_comment?: string | undefined;
|
|
427
429
|
media_alt_texts?: Record<string, string> | undefined;
|
|
428
|
-
reel_cover_url?: string | undefined;
|
|
429
|
-
reel_thumb_offset?: number | undefined;
|
|
430
430
|
} | undefined;
|
|
431
431
|
platform_settings?: z.objectOutputType<{
|
|
432
432
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -483,16 +483,18 @@ export declare const createPostsBatchTool: {
|
|
|
483
483
|
workspace_id?: string | undefined;
|
|
484
484
|
platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "linkedin" | "youtube" | "pinterest" | "threads" | "google_business" | "telegram" | "bluesky" | "gmb" | "google-business" | "google_business_profile" | "x" | undefined;
|
|
485
485
|
account_id?: string | undefined;
|
|
486
|
-
post_type?: string | undefined;
|
|
487
|
-
username?: string | undefined;
|
|
488
|
-
caption?: string | undefined;
|
|
489
486
|
scheduled_at?: string | undefined;
|
|
490
487
|
media_url?: string | undefined;
|
|
491
488
|
media_urls?: string[] | undefined;
|
|
489
|
+
post_type?: string | undefined;
|
|
490
|
+
username?: string | undefined;
|
|
491
|
+
caption?: string | undefined;
|
|
492
492
|
thread_posts?: string[] | undefined;
|
|
493
493
|
instagram_settings?: {
|
|
494
|
-
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
495
494
|
post_type?: "post" | "feed" | "story" | "reel" | "carousel" | undefined;
|
|
495
|
+
reel_cover_url?: string | undefined;
|
|
496
|
+
reel_thumb_offset?: number | undefined;
|
|
497
|
+
__type?: "instagram" | "instagram-standalone" | undefined;
|
|
496
498
|
is_trial_reel?: boolean | undefined;
|
|
497
499
|
graduation_strategy?: "MANUAL" | "SS_PERFORMANCE" | undefined;
|
|
498
500
|
collaborators?: (string | {
|
|
@@ -507,8 +509,6 @@ export declare const createPostsBatchTool: {
|
|
|
507
509
|
})[] | undefined;
|
|
508
510
|
first_comment?: string | undefined;
|
|
509
511
|
media_alt_texts?: Record<string, string> | undefined;
|
|
510
|
-
reel_cover_url?: string | undefined;
|
|
511
|
-
reel_thumb_offset?: number | undefined;
|
|
512
512
|
} | undefined;
|
|
513
513
|
platform_settings?: z.objectInputType<{
|
|
514
514
|
__type: z.ZodOptional<z.ZodString>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { dashboardUrlForPostList, formatLocalDateTime } from '../lib/format.js';
|
|
2
3
|
import { buildCreatePostPayload, createPostInputSchema } from './create-post.js';
|
|
3
4
|
export const createPostsBatchTool = {
|
|
4
5
|
name: 'create_posts_batch',
|
|
@@ -7,6 +8,7 @@ export const createPostsBatchTool = {
|
|
|
7
8
|
'1. Call `whoami` at the start of any new session to confirm which workspace and user you are acting for.\n' +
|
|
8
9
|
'2. Show the user a preview of EVERY post: account/platform, final caption or thread text, scheduled time in their timezone, media, platform settings, and workspace.\n' +
|
|
9
10
|
'3. Get explicit confirmation for the whole batch before calling. Do not infer consent from an earlier content plan.\n\n' +
|
|
11
|
+
'AFTER CALLING: Summarize the batch result in natural language, include the Posterly dashboard link returned by the tool, and avoid narrating raw HTTP, curl, or API plumbing.\n\n' +
|
|
10
12
|
'Each item accepts the same fields as `create_post`, including `thread_posts`, `platform_settings`, `instagram_settings`, media URLs, and workspace_id. The endpoint may partially succeed; failed items are returned with their index.',
|
|
11
13
|
inputSchema: z.object({
|
|
12
14
|
posts: z
|
|
@@ -18,21 +20,25 @@ export const createPostsBatchTool = {
|
|
|
18
20
|
async execute(client, input) {
|
|
19
21
|
const payloads = input.posts.map((post) => buildCreatePostPayload(post));
|
|
20
22
|
const result = await client.createPostsBatch({ posts: payloads });
|
|
23
|
+
const createdPosts = result.posts.map((item) => item.post);
|
|
24
|
+
const dashboardUrl = dashboardUrlForPostList(createdPosts);
|
|
21
25
|
const lines = [
|
|
22
26
|
'Batch create completed.',
|
|
23
27
|
`• Total: ${result.total}`,
|
|
24
28
|
`• Created: ${result.created}`,
|
|
25
29
|
`• Replayed: ${result.replayed}`,
|
|
26
30
|
`• Failed: ${result.failed}`,
|
|
31
|
+
`• View in Posterly: ${dashboardUrl}`,
|
|
27
32
|
];
|
|
28
33
|
for (const item of result.posts.slice(0, 25)) {
|
|
29
34
|
const post = item.post;
|
|
30
|
-
const when = post.scheduled_at ?
|
|
35
|
+
const when = post.scheduled_at ? formatLocalDateTime(post.scheduled_at) : 'now';
|
|
31
36
|
lines.push(`• [${item.index}] ID ${post.id} ${post.platform || 'unknown'} ${post.post_type || 'post'} ${post.status || 'created'} at ${when}${item.replayed ? ' (replayed)' : ''}`);
|
|
32
37
|
}
|
|
33
38
|
for (const error of result.errors.slice(0, 25)) {
|
|
34
39
|
lines.push(`• [${error.index}] ERROR ${error.status}: ${error.error}`);
|
|
35
40
|
}
|
|
41
|
+
lines.push('', 'Next step for the AI agent: tell the user which posts were created, share the dashboard link above, and ask whether they want to review the queue, adjust anything, or create the next post.');
|
|
36
42
|
return lines.join('\n');
|
|
37
43
|
},
|
|
38
44
|
};
|