postfast-mcp 0.8.3 → 0.10.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.
Files changed (37) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/dist/core/app.d.ts +42 -0
  4. package/dist/core/app.js +107 -0
  5. package/dist/core/app.js.map +1 -0
  6. package/dist/core/backend-port.d.ts +25 -1
  7. package/dist/core/build-tools.d.ts +20 -5
  8. package/dist/core/build-tools.js +50 -15
  9. package/dist/core/build-tools.js.map +1 -1
  10. package/dist/core/index.d.ts +2 -1
  11. package/dist/core/index.js +1 -0
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/core/instructions.d.ts +6 -1
  14. package/dist/core/instructions.js +46 -57
  15. package/dist/core/instructions.js.map +1 -1
  16. package/dist/core/tool-def.d.ts +29 -13
  17. package/dist/core/tools/accounts.js +12 -4
  18. package/dist/core/tools/accounts.js.map +1 -1
  19. package/dist/core/tools/app.d.ts +7 -0
  20. package/dist/core/tools/app.js +323 -0
  21. package/dist/core/tools/app.js.map +1 -0
  22. package/dist/core/tools/inbox-confirm.d.ts +2 -3
  23. package/dist/core/tools/inbox-confirm.js +5 -6
  24. package/dist/core/tools/inbox-confirm.js.map +1 -1
  25. package/dist/core/tools/inbox.js +12 -12
  26. package/dist/core/tools/inbox.js.map +1 -1
  27. package/dist/core/tools/index.js +2 -0
  28. package/dist/core/tools/index.js.map +1 -1
  29. package/dist/core/tools/posts.js +14 -12
  30. package/dist/core/tools/posts.js.map +1 -1
  31. package/dist/core/tools/uploads.js +6 -12
  32. package/dist/core/tools/uploads.js.map +1 -1
  33. package/dist/core/types.d.ts +128 -0
  34. package/dist/stdio/index.js +1 -1
  35. package/dist/stdio/index.js.map +1 -1
  36. package/dist/view/index.html +125 -0
  37. package/package.json +8 -3
@@ -1,4 +1,6 @@
1
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
1
2
  import type { ZodRawShape } from 'zod';
3
+ import type { AppOptions } from './app.js';
2
4
  import type { BackendPort } from './backend-port.js';
3
5
  /** The two deployments a catalog tool can ship in. */
4
6
  export type Binding = 'stdio' | 'remote';
@@ -22,32 +24,42 @@ export interface ToolAnnotations {
22
24
  export type ResolvedToolAnnotations = ToolAnnotations & {
23
25
  title: string;
24
26
  };
27
+ /** An icon listed on a tool in tools/list. */
28
+ export interface ToolIcon {
29
+ src: string;
30
+ mimeType?: string;
31
+ sizes?: string[];
32
+ }
25
33
  /**
26
34
  * One tool as authored in the catalog. `description`/`inputSchema` may be a
27
35
  * function of the binding for the few spots where the surfaces genuinely
28
- * differ (upload-tool references — stdio uploads local files, the remote
29
- * uploads conversation media/URLs). Everything else is binding-invariant.
30
- * The functions also receive `gated`: true only on a remote build with the
31
- * confirm gate on (BuildToolsOptions.confirmGate).
36
+ * differ: upload-tool references (stdio uploads local files, the remote
37
+ * uploads conversation media/URLs), and the remote binding's rule that every
38
+ * post and comment reply waits for the user's yes. Everything else is
39
+ * binding-invariant.
32
40
  */
33
41
  export interface ToolDef {
34
42
  name: string;
35
43
  /** Which binding(s) expose the tool. */
36
44
  binding: Binding | 'both';
37
45
  title: string;
38
- description: string | ((binding: Binding, gated?: boolean) => string);
39
- inputSchema: ZodRawShape | ((binding: Binding, gated?: boolean) => ZodRawShape);
46
+ description: string | ((binding: Binding) => string);
47
+ inputSchema: ZodRawShape | ((binding: Binding) => ZodRawShape);
40
48
  annotations: ToolAnnotations;
41
- /** Replaces `annotations` when the confirm gate is on. */
42
- gatedAnnotations?: ToolAnnotations;
49
+ /** Replaces `annotations` on the remote binding. */
50
+ remoteAnnotations?: ToolAnnotations;
43
51
  /** Extra tool metadata, e.g. the ChatGPT file-param marker on upload_media. */
44
52
  _meta?: Record<string, unknown>;
45
53
  /** False only for tools that are not scoped to a workspace (list_workspaces). */
46
54
  workspaceScoped?: boolean;
47
- /** The tool exists only when the confirm gate is on. */
48
- gatedOnly?: boolean;
49
- /** The tool is dropped when the confirm gate is on. */
50
- hiddenWhenGated?: boolean;
55
+ /** The tool signs confirm tokens, so it exists only with BuildToolsOptions.confirmGate. */
56
+ needsConfirmSecret?: boolean;
57
+ /** The tool exists only when the host turns the app on (BuildToolsOptions.app). */
58
+ appOnly?: boolean;
59
+ /** Icons for tools/list. Only app tools carry them. */
60
+ icons?: ToolIcon[];
61
+ /** Turns run()'s data into the call result; toolResult() when absent. */
62
+ toResult?: (data: unknown) => CallToolResult;
51
63
  /**
52
64
  * The BackendPort method this tool's run() dispatches to. When set and the
53
65
  * port instance lacks the method (an older adapter running a newer catalog),
@@ -59,10 +71,12 @@ export interface ToolDef {
59
71
  * Dispatch to the backend. `args` are the validated tool arguments minus
60
72
  * `workspaceId`, which is split off by the registrar and passed separately
61
73
  * (always undefined on stdio — the pf-api-key is already workspace-scoped).
62
- * `ctx.confirmSecret` is set by buildTools() when the confirm gate is on.
74
+ * `ctx.confirmSecret` is set by buildTools() when the host passes
75
+ * confirmGate, `ctx.app` when the app is on.
63
76
  */
64
77
  run: (port: BackendPort, args: Record<string, unknown>, workspaceId?: string, ctx?: {
65
78
  confirmSecret?: string;
79
+ app?: AppOptions;
66
80
  }) => Promise<unknown>;
67
81
  }
68
82
  /** A ToolDef with binding-dependent fields resolved for one concrete binding. */
@@ -73,6 +87,8 @@ export interface ResolvedTool {
73
87
  inputSchema: ZodRawShape;
74
88
  annotations: ResolvedToolAnnotations;
75
89
  _meta?: Record<string, unknown>;
90
+ icons?: ToolIcon[];
76
91
  portMethod?: keyof BackendPort;
77
92
  run: ToolDef['run'];
93
+ toResult?: ToolDef['toResult'];
78
94
  }
@@ -80,8 +80,11 @@ export const accountTools = [
80
80
  name: 'generate_connect_link',
81
81
  binding: 'both',
82
82
  title: 'Generate Connect Link',
83
- description: 'Generate a shareable link for external clients to connect their social accounts to the workspace. Can be scoped to specific platforms and return the user to your own app when done.',
84
- inputSchema: {
83
+ description: (binding) => 'Generate a shareable link for external clients to connect their social accounts to the workspace. Can be scoped to specific platforms and return the user to your own app when done.' +
84
+ (binding === 'remote'
85
+ ? ' Email the link (sendEmail) only when the user asks you to and gives the address.'
86
+ : ''),
87
+ inputSchema: (binding) => ({
85
88
  expiryDays: z
86
89
  .number()
87
90
  .int()
@@ -89,7 +92,12 @@ export const accountTools = [
89
92
  .max(30)
90
93
  .default(7)
91
94
  .describe('Link expiry in days (1-30, default 7)'),
92
- sendEmail: z.boolean().default(false).describe('Send the link via email'),
95
+ sendEmail: z
96
+ .boolean()
97
+ .default(false)
98
+ .describe(binding === 'remote'
99
+ ? 'Send the link via email. Set it only when the user asks you to and gives the address.'
100
+ : 'Send the link via email'),
93
101
  email: z
94
102
  .email()
95
103
  .optional()
@@ -109,7 +117,7 @@ export const accountTools = [
109
117
  .max(128)
110
118
  .optional()
111
119
  .describe('Your own reference for this link, echoed back unchanged on the return URL. Letters, digits and - . _ ~ : @ only.'),
112
- },
120
+ }),
113
121
  // destructive: sendEmail delivers a real email that cannot be recalled, and the
114
122
  // minted link grants account-connect access until it expires.
115
123
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
@@ -1 +1 @@
1
- {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../src/core/tools/accounts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../src/core/tools/accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ToolDef } from '../tool-def.js';
2
+ /**
3
+ * The calendar app: a sidebar entrypoint, a conversation-tab entrypoint, the
4
+ * view's post details and its analytics call. Present only when the host passes
5
+ * BuildToolsOptions.app; every tool is hidden from the model.
6
+ */
7
+ export declare const appTools: ToolDef[];
@@ -0,0 +1,323 @@
1
+ import { z } from 'zod';
2
+ import { APP_ICON, appToolMeta } from '../app.js';
3
+ const DAY_MS = 24 * 60 * 60 * 1000;
4
+ // The view shows 2 days back to 14 ahead in the viewer's time zone and trims
5
+ // to local days; one extra day each side covers every time zone.
6
+ const WINDOW_BACK_DAYS = 3;
7
+ const WINDOW_AHEAD_DAYS = 15;
8
+ const POSTS_LIMIT = 100;
9
+ const DRAFTS_LIMIT = 20;
10
+ /** Captions are cut here; the view clamps them to three lines. */
11
+ const CAPTION_CHARS = 280;
12
+ /** An opened post shows its full text up to here (Facebook allows about 63,000). */
13
+ const FULL_TEXT_CHARS = 20_000;
14
+ /** Result size ceiling, far below the 150,000-character limit (see fitBudget). */
15
+ const RESULT_BUDGET_CHARS = 100_000;
16
+ /** The switcher's list is a convenience: cap it, and never wait long for it. */
17
+ const MAX_WORKSPACES = 100;
18
+ const WORKSPACE_NAME_CHARS = 120;
19
+ const WORKSPACES_TIMEOUT_MS = 5_000;
20
+ const APP_ACTIONS = [
21
+ 'open_in_postfast',
22
+ 'review_in_chat',
23
+ 'reconnect',
24
+ 'connect_account',
25
+ 'new_post_started',
26
+ ];
27
+ /** The posts page tab that lists each status; everything else is on "scheduled". */
28
+ const POSTS_TAB = {
29
+ DRAFT: 'draft',
30
+ FAILED: 'failed',
31
+ PUBLISHED: 'published',
32
+ };
33
+ function postsUrl(app, params) {
34
+ return `${app.webAppUrl}/dashboard/posts?${new URLSearchParams(params)}`;
35
+ }
36
+ function toAccount(account) {
37
+ return {
38
+ id: account.id,
39
+ platform: account.platform,
40
+ handle: account.platformUsername || account.displayName || null,
41
+ connectionStatus: account.connectionStatus,
42
+ disabledReason: account.disabledReason ?? null,
43
+ avatarUrl: account.avatarUrl ?? null,
44
+ };
45
+ }
46
+ /** The text cut to `max` characters, ending in an ellipsis when cut. */
47
+ function shorten(text, max) {
48
+ const value = text ?? '';
49
+ return value.length > max
50
+ ? { text: `${value.slice(0, max - 1).trimEnd()}…`, truncated: true }
51
+ : { text: value, truncated: false };
52
+ }
53
+ function openUrlFor(app, post, workspaceId) {
54
+ return postsUrl(app, {
55
+ tab: POSTS_TAB[post.status] ?? 'scheduled',
56
+ editPostId: post.id,
57
+ ...(workspaceId ? { workspaceId } : {}),
58
+ });
59
+ }
60
+ function toPost(post, app, workspaceId) {
61
+ const { text, truncated } = shorten(post.content, CAPTION_CHARS);
62
+ return {
63
+ ...post,
64
+ content: text,
65
+ contentTruncated: truncated,
66
+ openUrl: openUrlFor(app, post, workspaceId),
67
+ };
68
+ }
69
+ const overBudget = (view) => JSON.stringify(view).length > RESULT_BUDGET_CHARS;
70
+ /**
71
+ * Keeps the view under the budget, giving up the least useful data first:
72
+ * avatars of accounts without a listed post, then every avatar, then posts
73
+ * from the far end (the latest dated post or the oldest draft) with hasMore set.
74
+ */
75
+ function fitBudget(view) {
76
+ if (!overBudget(view))
77
+ return view;
78
+ const listed = new Set([...view.posts, ...view.drafts].map((p) => p.socialMediaId));
79
+ for (const account of view.accounts)
80
+ if (!listed.has(account.id))
81
+ account.avatarUrl = null;
82
+ if (!overBudget(view))
83
+ return view;
84
+ for (const account of view.accounts)
85
+ account.avatarUrl = null;
86
+ while (overBudget(view) && (view.posts.length || view.drafts.length)) {
87
+ if (view.posts.length >= view.drafts.length) {
88
+ view.posts.pop();
89
+ view.hasMore = true;
90
+ }
91
+ else {
92
+ view.drafts.pop();
93
+ view.draftsHasMore = true;
94
+ }
95
+ }
96
+ return view;
97
+ }
98
+ /**
99
+ * The connection's workspaces for the view's switcher, from list_workspaces'
100
+ * `{ data: [{ id, name, isPersonal }] }`. A failed, slow or unexpected answer
101
+ * gives [] (no switcher) and never fails the calendar.
102
+ */
103
+ async function loadWorkspaces(port) {
104
+ let raw;
105
+ let timer;
106
+ try {
107
+ raw = await Promise.race([
108
+ port.listWorkspaces(),
109
+ new Promise((resolve) => {
110
+ timer = setTimeout(resolve, WORKSPACES_TIMEOUT_MS, undefined);
111
+ }),
112
+ ]);
113
+ }
114
+ catch {
115
+ return [];
116
+ }
117
+ finally {
118
+ clearTimeout(timer);
119
+ }
120
+ const rows = Array.isArray(raw) ? raw : raw?.data;
121
+ if (!Array.isArray(rows))
122
+ return [];
123
+ const seen = new Set();
124
+ const list = [];
125
+ for (const row of rows) {
126
+ const { id, name, isPersonal } = (row ?? {});
127
+ if (typeof id !== 'string' || !id || seen.has(id))
128
+ continue;
129
+ seen.add(id);
130
+ const label = typeof name === 'string' ? name.trim() : '';
131
+ list.push({
132
+ id,
133
+ name: shorten(label || 'Untitled workspace', WORKSPACE_NAME_CHARS).text,
134
+ personal: isPersonal === true,
135
+ });
136
+ if (list.length === MAX_WORKSPACES)
137
+ break;
138
+ }
139
+ return list;
140
+ }
141
+ /** Personal first, then by name; the workspace on screen is always in the list. */
142
+ function switcherList(workspaces, current) {
143
+ if (!workspaces.length)
144
+ return [];
145
+ const list = workspaces.some((w) => w.id === current.id)
146
+ ? workspaces
147
+ : [...workspaces, { ...current, personal: false }];
148
+ return list
149
+ .sort((a, b) => Number(b.personal) - Number(a.personal) ||
150
+ a.name.localeCompare(b.name, 'en', { sensitivity: 'base' }) ||
151
+ a.id.localeCompare(b.id))
152
+ .map(({ id, name }) => ({ id, name }));
153
+ }
154
+ /** Fails loudly on a payload the view could not render, instead of showing an empty calendar. */
155
+ function assertCalendar(calendar) {
156
+ const ok = calendar &&
157
+ typeof calendar.workspace?.id === 'string' &&
158
+ Array.isArray(calendar.accounts) &&
159
+ Array.isArray(calendar.posts) &&
160
+ Array.isArray(calendar.drafts);
161
+ if (!ok)
162
+ throw new Error('The calendar could not be loaded: unexpected response from PostFast.');
163
+ }
164
+ async function loadCalendar(port, entrypoint, args, workspaceId, app) {
165
+ if (!app || !port.getAppCalendar) {
166
+ throw new Error('The PostFast calendar is not available on this connection.');
167
+ }
168
+ const now = Date.now();
169
+ const window = {
170
+ from: new Date(now - WINDOW_BACK_DAYS * DAY_MS).toISOString(),
171
+ to: new Date(now + WINDOW_AHEAD_DAYS * DAY_MS).toISOString(),
172
+ };
173
+ const [calendar, workspaces] = await Promise.all([
174
+ port.getAppCalendar({
175
+ ...window,
176
+ limit: POSTS_LIMIT,
177
+ draftsLimit: DRAFTS_LIMIT,
178
+ entrypoint,
179
+ refresh: args.refresh === true,
180
+ }, workspaceId),
181
+ loadWorkspaces(port),
182
+ ]);
183
+ assertCalendar(calendar);
184
+ const ws = calendar.workspace;
185
+ return fitBudget({
186
+ version: 1,
187
+ entrypoint,
188
+ generatedAt: new Date(now).toISOString(),
189
+ window,
190
+ workspace: { id: ws.id, name: ws.name },
191
+ workspaces: switcherList(workspaces, { id: ws.id, name: ws.name }),
192
+ accounts: calendar.accounts.map(toAccount),
193
+ posts: calendar.posts.map((post) => toPost(post, app, ws.id)),
194
+ drafts: calendar.drafts.map((post) => toPost(post, app, ws.id)),
195
+ hasMore: calendar.hasMore === true,
196
+ draftsHasMore: calendar.draftsHasMore === true,
197
+ links: {
198
+ posts: postsUrl(app, { workspaceId: ws.id }),
199
+ accounts: `${app.webAppUrl}/dashboard/accounts?${new URLSearchParams({ workspaceId: ws.id })}`,
200
+ },
201
+ });
202
+ }
203
+ /**
204
+ * The view gets everything in `_meta`, which stays out of the model's context,
205
+ * so the signed media URLs never reach it. The text and structuredContent
206
+ * carry counts only.
207
+ */
208
+ function calendarResult(data) {
209
+ const view = data;
210
+ const counts = {
211
+ posts: view.posts.length,
212
+ drafts: view.drafts.length,
213
+ failed: view.posts.filter((p) => p.status === 'FAILED').length,
214
+ pendingApproval: [...view.posts, ...view.drafts].filter((p) => p.approvalStatus === 'PENDING_APPROVAL' && p.status !== 'PUBLISHED').length,
215
+ };
216
+ return {
217
+ content: [
218
+ {
219
+ type: 'text',
220
+ text: `Opened the PostFast calendar for ${view.workspace.name}: ${counts.posts} posts from ${view.window.from.slice(0, 10)} to ${view.window.to.slice(0, 10)} and ${counts.drafts} drafts without a date.`,
221
+ },
222
+ ],
223
+ structuredContent: { window: view.window, ...counts, hasMore: view.hasMore },
224
+ _meta: { 'postfast/calendar': view },
225
+ };
226
+ }
227
+ async function loadPost(port, args, workspaceId, app) {
228
+ if (!app || !port.getAppPost) {
229
+ throw new Error('Post details are not available on this connection.');
230
+ }
231
+ const post = await port.getAppPost(args, workspaceId);
232
+ if (!post || typeof post.id !== 'string' || !Array.isArray(post.mediaItems)) {
233
+ throw new Error('The post could not be loaded: unexpected response from PostFast.');
234
+ }
235
+ const { text, truncated } = shorten(post.content, FULL_TEXT_CHARS);
236
+ return {
237
+ ...post,
238
+ content: text,
239
+ contentTruncated: truncated,
240
+ openUrl: openUrlFor(app, post, post.workspaceId),
241
+ };
242
+ }
243
+ /** Like the calendar: the post goes to the view in `_meta`; the model sees ids only. */
244
+ function postResult(data) {
245
+ const post = data;
246
+ return {
247
+ content: [{ type: 'text', text: `Opened post ${post.id} in the PostFast calendar.` }],
248
+ structuredContent: { postId: post.id, mediaCount: post.mediaItems.length },
249
+ _meta: { 'postfast/post': post },
250
+ };
251
+ }
252
+ const refreshField = z
253
+ .boolean()
254
+ .optional()
255
+ .describe('True when the open calendar reloads its data; omitted when it opens.');
256
+ const calendarTool = (name, title, entrypoint, description) => ({
257
+ name,
258
+ binding: 'remote',
259
+ appOnly: true,
260
+ title,
261
+ description,
262
+ inputSchema: { refresh: refreshField },
263
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
264
+ icons: [APP_ICON],
265
+ _meta: appToolMeta(entrypoint),
266
+ portMethod: 'getAppCalendar',
267
+ run: (port, args, workspaceId, ctx) => loadCalendar(port, entrypoint, args, workspaceId, ctx?.app),
268
+ toResult: calendarResult,
269
+ });
270
+ const READ_ONLY_NOTE = 'Read-only: the calendar never approves, publishes, replies to or deletes anything; those go through the conversation.';
271
+ /**
272
+ * The calendar app: a sidebar entrypoint, a conversation-tab entrypoint, the
273
+ * view's post details and its analytics call. Present only when the host passes
274
+ * BuildToolsOptions.app; every tool is hidden from the model.
275
+ */
276
+ export const appTools = [
277
+ calendarTool('open_postfast', 'Content Calendar', 'global', `Opens the PostFast content calendar: posts from the last 2 days through the next 14, grouped by day, drafts without a date, and a filter by account. ${READ_ONLY_NOTE}`),
278
+ calendarTool('postfast_tab', 'PostFast Calendar', 'thread', `Opens the PostFast calendar in a tab beside this conversation: the same posts, drafts and account filter as the sidebar calendar. ${READ_ONLY_NOTE}`),
279
+ {
280
+ name: 'get_calendar_post',
281
+ binding: 'remote',
282
+ appOnly: true,
283
+ title: 'Calendar Post Details',
284
+ description: 'Called by the PostFast calendar when a post is opened: its full text, first comment and every image or video. Read-only.',
285
+ inputSchema: {
286
+ postId: z.uuid().describe('The post to open, from the calendar.'),
287
+ },
288
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
289
+ _meta: appToolMeta(),
290
+ portMethod: 'getAppPost',
291
+ run: (port, args, workspaceId, ctx) => loadPost(port, args, workspaceId, ctx?.app),
292
+ toResult: postResult,
293
+ },
294
+ {
295
+ name: 'record_app_action',
296
+ binding: 'remote',
297
+ appOnly: true,
298
+ title: 'Record Calendar Action',
299
+ description: 'Called by the PostFast calendar to record which of its buttons was used (open in PostFast, review in chat, reconnect, connect an account, new post), for product analytics. Changes no posts, accounts or settings.',
300
+ inputSchema: {
301
+ action: z.enum(APP_ACTIONS).describe('The button that was used.'),
302
+ entrypoint: z
303
+ .enum(['global', 'thread'])
304
+ .optional()
305
+ .describe('Where the calendar was opened: the sidebar (global) or a conversation tab (thread).'),
306
+ },
307
+ annotations: {
308
+ readOnlyHint: false,
309
+ destructiveHint: false,
310
+ idempotentHint: false,
311
+ openWorldHint: false,
312
+ },
313
+ _meta: appToolMeta(),
314
+ portMethod: 'recordAppAction',
315
+ run: async (port, args, workspaceId) => {
316
+ if (!port.recordAppAction)
317
+ throw new Error('Not available on this connection.');
318
+ await port.recordAppAction(args, workspaceId);
319
+ return { recorded: true };
320
+ },
321
+ },
322
+ ];
323
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/core/tools/app.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,8 @@
1
1
  import type { ToolDef } from '../tool-def.js';
2
2
  /**
3
3
  * Comment replies, Instagram private replies and comment deletions in two
4
- * steps, for hosts with the confirm gate on (there they replace
5
- * reply_to_inbox_item, send_inbox_private_reply and set_inbox_item_state
6
- * DELETE). prepare returns a preview and a signed token and calls nothing.
4
+ * steps, on the remote binding (where they replace reply_to_inbox_item,
5
+ * send_inbox_private_reply and set_inbox_item_state DELETE). prepare returns a preview and a signed token and calls nothing.
7
6
  * confirm repeats the same values, so the client's approval prompt for the
8
7
  * destructive call shows the real reply text, and any change fails the
9
8
  * signature. The token is not tied to a user: confirm runs with the caller's
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { redeem, sign } from '../confirm-token.js';
3
3
  const CONFIRM_ACTIONS = ['REPLY', 'PRIVATE_REPLY', 'DELETE'];
4
- /** The confirm-gate secret, handed to run() by buildTools() when the gate is on. */
4
+ /** The confirm secret, handed to run() by buildTools() when the host passes confirmGate. */
5
5
  function secretOf(ctx) {
6
6
  if (!ctx?.confirmSecret) {
7
7
  throw new Error('The confirm gate is not configured on this server.');
@@ -10,9 +10,8 @@ function secretOf(ctx) {
10
10
  }
11
11
  /**
12
12
  * Comment replies, Instagram private replies and comment deletions in two
13
- * steps, for hosts with the confirm gate on (there they replace
14
- * reply_to_inbox_item, send_inbox_private_reply and set_inbox_item_state
15
- * DELETE). prepare returns a preview and a signed token and calls nothing.
13
+ * steps, on the remote binding (where they replace reply_to_inbox_item,
14
+ * send_inbox_private_reply and set_inbox_item_state DELETE). prepare returns a preview and a signed token and calls nothing.
16
15
  * confirm repeats the same values, so the client's approval prompt for the
17
16
  * destructive call shows the real reply text, and any change fails the
18
17
  * signature. The token is not tied to a user: confirm runs with the caller's
@@ -22,7 +21,7 @@ export const inboxConfirmTools = [
22
21
  {
23
22
  name: 'prepare_inbox_action',
24
23
  binding: 'remote',
25
- gatedOnly: true,
24
+ needsConfirmSecret: true,
26
25
  title: 'Prepare Comment Reply or Deletion',
27
26
  description: "Prepare a reply to a comment, an Instagram private reply, or a comment deletion WITHOUT doing it. REPLY posts publicly under the comment; PRIVATE_REPLY sends an Instagram private reply that arrives as a direct message (one per comment, within 7 days; check the item's canPrivateReply); DELETE removes the comment on the platform permanently (not supported on Threads). Before a reply, check the conversation's canReply and maxReplyLength. Returns a preview and a confirmToken. Then show the user which comment it is (its author and text) and exactly what will happen, and wait for their yes in the conversation before calling confirm_inbox_action, even if they already told you what to write. Nothing reaches the platform in this step.",
28
27
  inputSchema: {
@@ -62,7 +61,7 @@ export const inboxConfirmTools = [
62
61
  {
63
62
  name: 'confirm_inbox_action',
64
63
  binding: 'remote',
65
- gatedOnly: true,
64
+ needsConfirmSecret: true,
66
65
  title: 'Confirm Comment Reply or Deletion',
67
66
  description: 'Carry out a reply or deletion prepared with prepare_inbox_action. Pass its confirmToken with the same itemId, action and text (and workspaceId, if you used one); anything different is rejected. Call it only after the user has seen the preview and said yes in the conversation. Replies on Threads cannot be removed through PostFast, private replies cannot be unsent, and deletions cannot be undone. A token expires 15 minutes after it was prepared and works once. Failures return the underlying inbox.* codes (for example replyTooLong, privateReplyAlreadySent, deleteNotSupported).',
68
67
  inputSchema: {
@@ -1 +1 @@
1
- {"version":3,"file":"inbox-confirm.js","sourceRoot":"","sources":["../../../src/core/tools/inbox-confirm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inbox-confirm.js","sourceRoot":"","sources":["../../../src/core/tools/inbox-confirm.ts"],"names":[],"mappings":"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"}
@@ -63,8 +63,8 @@ export const inboxTools = [
63
63
  name: 'list_inbox_items',
64
64
  binding: 'both',
65
65
  title: 'List Inbox Items',
66
- description: (_binding, gated) => 'List the items of one inbox conversation — the comments and the replies sent to them — oldest first by default (order=DESC for newest first). Items carry direction (INBOUND | OUTBOUND), state (VISIBLE | HIDDEN | DELETED), author info, and on Instagram comments canPrivateReply (eligibility for ' +
67
- (gated ? 'a PRIVATE_REPLY through prepare_inbox_action' : 'send_inbox_private_reply') +
66
+ description: (binding) => 'List the items of one inbox conversation — the comments and the replies sent to them — oldest first by default (order=DESC for newest first). Items carry direction (INBOUND | OUTBOUND), state (VISIBLE | HIDDEN | DELETED), author info, and on Instagram comments canPrivateReply (eligibility for ' +
67
+ (binding === 'remote' ? 'a PRIVATE_REPLY through prepare_inbox_action' : 'send_inbox_private_reply') +
68
68
  '). Replies sent from PostFast appear exactly once — no duplicates when the platform reports them back.',
69
69
  inputSchema: {
70
70
  conversationId: z
@@ -93,7 +93,8 @@ export const inboxTools = [
93
93
  },
94
94
  {
95
95
  name: 'reply_to_inbox_item',
96
- binding: 'both',
96
+ // stdio only: the remote binding replies through prepare/confirm_inbox_action.
97
+ binding: 'stdio',
97
98
  title: 'Reply to Inbox Comment',
98
99
  description: "Reply publicly UNDER a specific comment — pass the comment item's id (from list_inbox_items), not the conversation id. BEFORE replying, check the conversation's canReply and maxReplyLength and stay within them; the caps are per platform (TikTok 1,200, Instagram 2,200, Facebook 8,000, Threads 500 characters) but the server-computed fields are authoritative — never assume. Failures return inbox.* codes (e.g. replyTooLong, replyNotSupported, rateLimited).",
99
100
  inputSchema: {
@@ -103,13 +104,13 @@ export const inboxTools = [
103
104
  // destructive: publishes a public comment; Threads exposes no delete verb, so a
104
105
  // reply there cannot be removed through our API.
105
106
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
106
- hiddenWhenGated: true,
107
107
  portMethod: 'replyToInboxItem',
108
108
  run: (port, args, workspaceId) => port.replyToInboxItem(args, workspaceId),
109
109
  },
110
110
  {
111
111
  name: 'send_inbox_private_reply',
112
- binding: 'both',
112
+ // stdio only: the remote binding replies through prepare/confirm_inbox_action.
113
+ binding: 'stdio',
113
114
  title: 'Send Instagram Private Reply',
114
115
  description: "Instagram only: send ONE private reply to a comment — it arrives as a direct message to the commenter and may land in their Message Requests folder. Allowed once per comment, within 7 days of the comment, up to 1,000 bytes (emoji and non-Latin text count multi-byte — roughly 1,000 characters, less with emoji). Check the item's canPrivateReply first (from list_inbox_items). A second attempt on the same comment fails with inbox.privateReplyAlreadySent; other failures include privateReplyWindowExpired and privateReplyNotSupported.",
115
116
  inputSchema: {
@@ -121,7 +122,6 @@ export const inboxTools = [
121
122
  // destructive: sends a real direct message with no unsend path, and the
122
123
  // once-per-comment guard means the attempt cannot be repeated.
123
124
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
124
- hiddenWhenGated: true,
125
125
  portMethod: 'sendInboxPrivateReply',
126
126
  run: (port, args, workspaceId) => port.sendInboxPrivateReply(args, workspaceId),
127
127
  },
@@ -129,21 +129,21 @@ export const inboxTools = [
129
129
  name: 'set_inbox_item_state',
130
130
  binding: 'both',
131
131
  title: 'Moderate Inbox Comment',
132
- description: (_binding, gated) => gated
133
- ? 'Hide a comment from the public on the platform (HIDE) or restore it (UNHIDE). Works on TikTok, Instagram, Facebook and Threads and can be reversed. To delete a comment permanently, use prepare_inbox_action with action DELETE. State changes made on the platform itself sync back to the inbox automatically.'
132
+ description: (binding) => binding === 'remote'
133
+ ? 'Hide a comment from the public on the platform (HIDE) or restore it (UNHIDE). Works on TikTok, Instagram, Facebook and Threads and can be reversed. To delete a comment permanently, use prepare_inbox_action with action DELETE. State changes made on the platform itself sync back to the inbox automatically. Hide or unhide a comment only when the user asks.'
134
134
  : 'Moderate a comment on the platform: HIDE hides it from the public, UNHIDE restores it, DELETE removes the comment on the platform — cannot be undone. HIDE/UNHIDE work on TikTok, Instagram, Facebook, and Threads; DELETE is not supported on Threads (inbox.deleteNotSupported). State changes made on the platform itself sync back to the inbox automatically.',
135
- inputSchema: (_binding, gated) => ({
135
+ inputSchema: (binding) => ({
136
136
  itemId: z.uuid().describe('The comment item id (from list_inbox_items)'),
137
- action: gated
137
+ action: binding === 'remote'
138
138
  ? z.enum(['HIDE', 'UNHIDE']).describe('HIDE or UNHIDE')
139
139
  : z
140
140
  .enum(INBOX_ITEM_STATE_ACTIONS)
141
141
  .describe('HIDE, UNHIDE, or DELETE (DELETE is irreversible)'),
142
142
  }),
143
143
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
144
- // Gated, DELETE moves to prepare/confirm_inbox_action, leaving only
144
+ // Remote, DELETE moves to prepare/confirm_inbox_action, leaving only
145
145
  // reversible HIDE/UNHIDE here.
146
- gatedAnnotations: {
146
+ remoteAnnotations: {
147
147
  readOnlyHint: false,
148
148
  destructiveHint: false,
149
149
  idempotentHint: true,