figmanage 1.2.9 → 1.3.1
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 +10 -8
- package/dist/cli/analytics.js +3 -2
- package/dist/cli/branching.js +9 -3
- package/dist/cli/comments.js +10 -4
- package/dist/cli/components.js +21 -4
- package/dist/cli/compound-commands.js +13 -12
- package/dist/cli/export.js +3 -2
- package/dist/cli/files.js +14 -8
- package/dist/cli/helpers.d.ts +1 -0
- package/dist/cli/helpers.js +10 -0
- package/dist/cli/libraries.js +2 -1
- package/dist/cli/navigate.js +11 -10
- package/dist/cli/org.js +13 -12
- package/dist/cli/permissions.js +13 -7
- package/dist/cli/projects.js +12 -6
- package/dist/cli/reading.js +3 -2
- package/dist/cli/teams.js +9 -3
- package/dist/cli/variables.js +29 -7
- package/dist/cli/versions.js +3 -2
- package/dist/cli/webhooks.js +14 -4
- package/dist/helpers.d.ts +11 -0
- package/dist/helpers.js +41 -0
- package/dist/mcp.js +18 -6
- package/dist/operations/analytics.js +1 -1
- package/dist/operations/components.d.ts +8 -2
- package/dist/operations/components.js +4 -2
- package/dist/operations/compound-manager.js +8 -9
- package/dist/operations/compound.d.ts +3 -0
- package/dist/operations/compound.js +14 -8
- package/dist/operations/files.js +1 -1
- package/dist/operations/libraries.js +1 -1
- package/dist/operations/org.js +1 -1
- package/dist/operations/reading.js +2 -0
- package/dist/operations/teams.js +1 -1
- package/dist/operations/variables.js +11 -0
- package/dist/operations/webhooks.d.ts +4 -1
- package/dist/operations/webhooks.js +2 -1
- package/dist/tools/analytics.js +6 -5
- package/dist/tools/branching.js +7 -6
- package/dist/tools/comments.js +14 -9
- package/dist/tools/components.js +24 -15
- package/dist/tools/compound-manager.js +10 -7
- package/dist/tools/compound.js +34 -22
- package/dist/tools/export.js +6 -5
- package/dist/tools/files.js +13 -12
- package/dist/tools/libraries.js +6 -3
- package/dist/tools/navigate.js +29 -18
- package/dist/tools/org.js +25 -24
- package/dist/tools/permissions.js +14 -11
- package/dist/tools/projects.js +10 -9
- package/dist/tools/reading.js +11 -7
- package/dist/tools/register.d.ts +8 -2
- package/dist/tools/register.js +9 -14
- package/dist/tools/setup.d.ts +10 -0
- package/dist/tools/setup.js +181 -0
- package/dist/tools/teams.js +7 -6
- package/dist/tools/variables.js +12 -8
- package/dist/tools/versions.js +6 -5
- package/dist/tools/webhooks.js +15 -12
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { internalClient } from '../clients/internal-api.js';
|
|
2
|
-
import { requireOrgId } from '../
|
|
2
|
+
import { requireOrgId, formatApiError } from '../helpers.js';
|
|
3
3
|
import { levelName } from './compound.js';
|
|
4
4
|
// -- Shared helpers --
|
|
5
5
|
const BATCH_SIZE = 5;
|
|
@@ -241,7 +241,7 @@ export async function offboardUser(config, params) {
|
|
|
241
241
|
actions.push({ action: 'transfer_ownership', status: 'done', detail: `${file.file_name} -> ${transfer_to}` });
|
|
242
242
|
}
|
|
243
243
|
catch (e) {
|
|
244
|
-
actions.push({ action: 'transfer_ownership', status: 'failed', detail: `${file.file_name}: ${e
|
|
244
|
+
actions.push({ action: 'transfer_ownership', status: 'failed', detail: `${file.file_name}: ${formatApiError(e)}` });
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
}
|
|
@@ -257,7 +257,7 @@ export async function offboardUser(config, params) {
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
catch (e) {
|
|
260
|
-
actions.push({ action: 'revoke_file', status: 'failed', detail: `${file.file_name}: ${e
|
|
260
|
+
actions.push({ action: 'revoke_file', status: 'failed', detail: `${file.file_name}: ${formatApiError(e)}` });
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
// Step C: Revoke project access
|
|
@@ -312,7 +312,7 @@ export async function offboardUser(config, params) {
|
|
|
312
312
|
actions.push({ action: 'downgrade_seat', status: 'done', detail: `${user.seat_type} -> viewer` });
|
|
313
313
|
}
|
|
314
314
|
catch (e) {
|
|
315
|
-
actions.push({ action: 'downgrade_seat', status: 'failed', detail: e
|
|
315
|
+
actions.push({ action: 'downgrade_seat', status: 'failed', detail: formatApiError(e) });
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
const succeeded = actions.filter(a => a.status === 'done').length;
|
|
@@ -421,7 +421,7 @@ export async function onboardUser(config, params) {
|
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
423
|
catch (e) {
|
|
424
|
-
seatChange = { status: 'failed', note: `Seat change failed: ${e
|
|
424
|
+
seatChange = { status: 'failed', note: `Seat change failed: ${formatApiError(e)}` };
|
|
425
425
|
}
|
|
426
426
|
}
|
|
427
427
|
else if (seat_type && !confirm) {
|
|
@@ -482,7 +482,7 @@ export async function quarterlyDesignOpsReport(config, params) {
|
|
|
482
482
|
}
|
|
483
483
|
catch (e) {
|
|
484
484
|
membersComplete = false;
|
|
485
|
-
errors.push(`members: pagination stopped at page ${page + 1} of ${maxPages}, fetched ${allMembers.length} members (${e
|
|
485
|
+
errors.push(`members: pagination stopped at page ${page + 1} of ${maxPages}, fetched ${allMembers.length} members (${formatApiError(e)})`);
|
|
486
486
|
break;
|
|
487
487
|
}
|
|
488
488
|
}
|
|
@@ -609,6 +609,8 @@ export async function quarterlyDesignOpsReport(config, params) {
|
|
|
609
609
|
highlights.push(`${totalInsertions} library component insertions across ${libraryAdoption.length} library/libraries.`);
|
|
610
610
|
}
|
|
611
611
|
const result = {
|
|
612
|
+
highlights,
|
|
613
|
+
...(errors.length > 0 ? { errors } : {}),
|
|
612
614
|
period: {
|
|
613
615
|
start: periodStart.toISOString().split('T')[0],
|
|
614
616
|
end: now.toISOString().split('T')[0],
|
|
@@ -628,10 +630,7 @@ export async function quarterlyDesignOpsReport(config, params) {
|
|
|
628
630
|
teams,
|
|
629
631
|
billing,
|
|
630
632
|
library_adoption: libraryAdoption,
|
|
631
|
-
highlights,
|
|
632
633
|
};
|
|
633
|
-
if (errors.length > 0)
|
|
634
|
-
result.errors = errors;
|
|
635
634
|
return result;
|
|
636
635
|
}
|
|
637
636
|
//# sourceMappingURL=compound-manager.js.map
|
|
@@ -29,7 +29,9 @@ export declare function organizeProject(config: AuthConfig, params: {
|
|
|
29
29
|
file_keys: string[];
|
|
30
30
|
target_project_id: string;
|
|
31
31
|
}): Promise<{
|
|
32
|
+
target_project_id: string;
|
|
32
33
|
moved: number;
|
|
34
|
+
moved_file_keys: string[];
|
|
33
35
|
failed: number;
|
|
34
36
|
errors: any;
|
|
35
37
|
}>;
|
|
@@ -87,6 +89,7 @@ export declare function branchCleanup(config: AuthConfig, params: {
|
|
|
87
89
|
active_branches: any[];
|
|
88
90
|
dry_run: boolean;
|
|
89
91
|
archived: boolean;
|
|
92
|
+
archived_count: number;
|
|
90
93
|
recommendations: string[];
|
|
91
94
|
}>;
|
|
92
95
|
//# sourceMappingURL=compound.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { hasPat, hasCookie } from '../auth/client.js';
|
|
2
2
|
import { publicClient } from '../clients/public-api.js';
|
|
3
3
|
import { internalClient } from '../clients/internal-api.js';
|
|
4
|
-
import { requireOrgId } from '../
|
|
4
|
+
import { requireOrgId, formatApiError } from '../helpers.js';
|
|
5
5
|
// -- Shared helpers --
|
|
6
6
|
const BATCH_SIZE = 5;
|
|
7
7
|
async function batchProcess(items, fn) {
|
|
@@ -32,7 +32,7 @@ export async function fileSummary(config, params) {
|
|
|
32
32
|
api.get(`/v1/files/${params.file_key}/comments`),
|
|
33
33
|
]);
|
|
34
34
|
if (fileResult.status === 'rejected') {
|
|
35
|
-
throw new Error(`Failed to fetch file: ${fileResult.reason
|
|
35
|
+
throw new Error(`Failed to fetch file: ${formatApiError(fileResult.reason)}`);
|
|
36
36
|
}
|
|
37
37
|
const fileData = fileResult.value.data;
|
|
38
38
|
const pages = (fileData.document?.children || []).map((c) => c.name);
|
|
@@ -78,11 +78,11 @@ export async function workspaceOverview(config, params) {
|
|
|
78
78
|
delete billing.shipping_address;
|
|
79
79
|
const errors = [];
|
|
80
80
|
if (teamsResult.status === 'rejected')
|
|
81
|
-
errors.push(`teams: ${teamsResult.reason
|
|
81
|
+
errors.push(`teams: ${formatApiError(teamsResult.reason)}`);
|
|
82
82
|
if (seatsResult.status === 'rejected')
|
|
83
|
-
errors.push(`seats: ${seatsResult.reason
|
|
83
|
+
errors.push(`seats: ${formatApiError(seatsResult.reason)}`);
|
|
84
84
|
if (billingResult.status === 'rejected')
|
|
85
|
-
errors.push(`billing: ${billingResult.reason
|
|
85
|
+
errors.push(`billing: ${formatApiError(billingResult.reason)}`);
|
|
86
86
|
const overview = { teams, seats, billing };
|
|
87
87
|
if (errors.length > 0)
|
|
88
88
|
overview.errors = errors;
|
|
@@ -104,7 +104,7 @@ export async function openComments(config, params) {
|
|
|
104
104
|
commentResults.push({ file_key: f.key, file_name: f.name, comments });
|
|
105
105
|
}
|
|
106
106
|
catch (e) {
|
|
107
|
-
commentResults.push({ file_key: f.key, file_name: f.name, comments: [], error: e
|
|
107
|
+
commentResults.push({ file_key: f.key, file_name: f.name, comments: [], error: formatApiError(e) });
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
const filesWithComments = commentResults
|
|
@@ -180,6 +180,8 @@ export async function cleanupStaleFiles(config, params) {
|
|
|
180
180
|
data: { files: staleFiles.map((f) => ({ key: f.key })), trashed: true },
|
|
181
181
|
});
|
|
182
182
|
result.trashed = true;
|
|
183
|
+
result.trashed_count = staleFiles.length;
|
|
184
|
+
result.trashed_file_keys = staleFiles.map((f) => f.key);
|
|
183
185
|
}
|
|
184
186
|
}
|
|
185
187
|
return result;
|
|
@@ -199,7 +201,9 @@ export async function organizeProject(config, params) {
|
|
|
199
201
|
const moved = Object.keys(data?.success || {}).length;
|
|
200
202
|
const failed = Object.keys(data?.errors || {}).length;
|
|
201
203
|
return {
|
|
204
|
+
target_project_id: params.target_project_id,
|
|
202
205
|
moved: moved || (failed === 0 ? params.file_keys.length : 0),
|
|
206
|
+
moved_file_keys: params.file_keys,
|
|
203
207
|
failed,
|
|
204
208
|
errors: data?.errors || {},
|
|
205
209
|
};
|
|
@@ -230,7 +234,7 @@ export async function setupProjectStructure(config, params) {
|
|
|
230
234
|
created.push({ id: folderId, name: project.name, description: project.description || null });
|
|
231
235
|
}
|
|
232
236
|
catch (e) {
|
|
233
|
-
failed.push({ name: project.name, error: e
|
|
237
|
+
failed.push({ name: project.name, error: formatApiError(e) });
|
|
234
238
|
}
|
|
235
239
|
}
|
|
236
240
|
return { created, failed };
|
|
@@ -265,7 +269,7 @@ export async function seatOptimization(config, params) {
|
|
|
265
269
|
}
|
|
266
270
|
catch (e) {
|
|
267
271
|
membersComplete = false;
|
|
268
|
-
warnings.push(`members: pagination stopped at page ${page + 1}, fetched ${allMembers.length} members (${e
|
|
272
|
+
warnings.push(`members: pagination stopped at page ${page + 1}, fetched ${allMembers.length} members (${formatApiError(e)})`);
|
|
269
273
|
break;
|
|
270
274
|
}
|
|
271
275
|
}
|
|
@@ -584,6 +588,7 @@ export async function branchCleanup(config, params) {
|
|
|
584
588
|
});
|
|
585
589
|
archived = true;
|
|
586
590
|
}
|
|
591
|
+
const archived_count = archived ? staleBranches.length : 0;
|
|
587
592
|
const recommendations = [];
|
|
588
593
|
if (staleBranches.length > 0) {
|
|
589
594
|
recommendations.push(`${staleBranches.length} branch(es) stale for ${days_stale}+ days. ${dry_run ? 'Set dry_run=false to archive.' : 'Archived.'}`);
|
|
@@ -606,6 +611,7 @@ export async function branchCleanup(config, params) {
|
|
|
606
611
|
active_branches: activeBranches,
|
|
607
612
|
dry_run,
|
|
608
613
|
archived,
|
|
614
|
+
archived_count,
|
|
609
615
|
recommendations,
|
|
610
616
|
};
|
|
611
617
|
}
|
package/dist/operations/files.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { internalClient } from '../clients/internal-api.js';
|
|
2
|
-
import { resolveOrgId } from '../
|
|
2
|
+
import { resolveOrgId } from '../helpers.js';
|
|
3
3
|
export async function createFile(config, params) {
|
|
4
4
|
const res = await internalClient(config).post('/api/files/create', {
|
|
5
5
|
folder_id: params.project_id,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { internalClient } from '../clients/internal-api.js';
|
|
2
|
-
import { requireOrgId } from '../
|
|
2
|
+
import { requireOrgId } from '../helpers.js';
|
|
3
3
|
export async function listOrgLibraries(config, params) {
|
|
4
4
|
const orgId = requireOrgId(config, params.org_id);
|
|
5
5
|
const res = await internalClient(config).get('/api/design_systems/libraries', {
|
package/dist/operations/org.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { publicClient } from '../clients/public-api.js';
|
|
2
|
+
// WARNING: Response can be very large for complex files. Callers should
|
|
3
|
+
// encourage use of depth and node_id params to limit payload size.
|
|
2
4
|
export async function getFile(config, params) {
|
|
3
5
|
const queryParams = {};
|
|
4
6
|
if (params.depth !== undefined)
|
package/dist/operations/teams.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { internalClient } from '../clients/internal-api.js';
|
|
2
|
-
import { requireOrgId } from '../
|
|
2
|
+
import { requireOrgId } from '../helpers.js';
|
|
3
3
|
export async function createTeam(config, params) {
|
|
4
4
|
const orgId = requireOrgId(config, params.org_id);
|
|
5
5
|
const res = await internalClient(config).post('/api/teams/create', { team_name: params.name, org_id: orgId, sharing_audience_control: 'org_view' });
|
|
@@ -24,6 +24,17 @@ export async function updateVariables(config, params) {
|
|
|
24
24
|
!params.variable_mode_values?.length) {
|
|
25
25
|
throw new Error('At least one operation array is required.');
|
|
26
26
|
}
|
|
27
|
+
const allOps = [
|
|
28
|
+
...(params.variable_collections || []),
|
|
29
|
+
...(params.variable_modes || []),
|
|
30
|
+
...(params.variables || []),
|
|
31
|
+
...(params.variable_mode_values || []),
|
|
32
|
+
];
|
|
33
|
+
for (const op of allOps) {
|
|
34
|
+
if (!op.action || !['CREATE', 'UPDATE', 'DELETE'].includes(op.action)) {
|
|
35
|
+
throw new Error(`Each operation must have an action field (CREATE, UPDATE, or DELETE). Got: ${JSON.stringify(op.action)}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
27
38
|
const body = {};
|
|
28
39
|
if (params.variable_collections)
|
|
29
40
|
body.variableCollections = params.variable_collections;
|
|
@@ -3,7 +3,10 @@ export type WebhookEventType = 'FILE_UPDATE' | 'FILE_DELETE' | 'FILE_VERSION_UPD
|
|
|
3
3
|
export type WebhookStatus = 'ACTIVE' | 'PAUSED';
|
|
4
4
|
export declare function listWebhooks(config: AuthConfig, params: {
|
|
5
5
|
team_id: string;
|
|
6
|
-
}): Promise<
|
|
6
|
+
}): Promise<{
|
|
7
|
+
count: number;
|
|
8
|
+
webhooks: any[];
|
|
9
|
+
}>;
|
|
7
10
|
export declare function createWebhook(config: AuthConfig, params: {
|
|
8
11
|
team_id: string;
|
|
9
12
|
event_type: WebhookEventType;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { publicClient } from '../clients/public-api.js';
|
|
2
2
|
export async function listWebhooks(config, params) {
|
|
3
3
|
const res = await publicClient(config).get(`/v2/teams/${params.team_id}/webhooks`);
|
|
4
|
-
|
|
4
|
+
const webhooks = res.data?.webhooks || [];
|
|
5
|
+
return { count: webhooks.length, webhooks };
|
|
5
6
|
}
|
|
6
7
|
export async function createWebhook(config, params) {
|
|
7
8
|
const body = {
|
package/dist/tools/analytics.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineTool,
|
|
2
|
+
import { defineTool, toolError, toolSummary, figmaId } from './register.js';
|
|
3
|
+
import { formatApiError } from '../helpers.js';
|
|
3
4
|
import { libraryUsage, componentUsage } from '../operations/analytics.js';
|
|
4
5
|
// -- library_usage --
|
|
5
6
|
defineTool({
|
|
@@ -15,10 +16,10 @@ defineTool({
|
|
|
15
16
|
}, async ({ library_file_key, days }) => {
|
|
16
17
|
try {
|
|
17
18
|
const result = await libraryUsage(config, { library_file_key, days });
|
|
18
|
-
return
|
|
19
|
+
return toolSummary('Library usage:', result);
|
|
19
20
|
}
|
|
20
21
|
catch (e) {
|
|
21
|
-
return toolError(`Failed to fetch library usage: ${e
|
|
22
|
+
return toolError(`Failed to fetch library usage: ${formatApiError(e)}`);
|
|
22
23
|
}
|
|
23
24
|
});
|
|
24
25
|
},
|
|
@@ -37,10 +38,10 @@ defineTool({
|
|
|
37
38
|
}, async ({ component_key, org_id }) => {
|
|
38
39
|
try {
|
|
39
40
|
const result = await componentUsage(config, { component_key, org_id });
|
|
40
|
-
return
|
|
41
|
+
return toolSummary('Component usage:', result);
|
|
41
42
|
}
|
|
42
43
|
catch (e) {
|
|
43
|
-
return toolError(`Failed to fetch component usage: ${e
|
|
44
|
+
return toolError(`Failed to fetch component usage: ${formatApiError(e)}`);
|
|
44
45
|
}
|
|
45
46
|
});
|
|
46
47
|
},
|
package/dist/tools/branching.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineTool, toolResult, toolError, figmaId } from './register.js';
|
|
2
|
+
import { defineTool, toolResult, toolError, toolSummary, figmaId } from './register.js';
|
|
3
|
+
import { formatApiError } from '../helpers.js';
|
|
3
4
|
import { listBranches, createBranch, deleteBranch } from '../operations/branching.js';
|
|
4
5
|
// -- list_branches --
|
|
5
6
|
defineTool({
|
|
@@ -16,10 +17,10 @@ defineTool({
|
|
|
16
17
|
const result = await listBranches(config, { file_key });
|
|
17
18
|
if (result.length === 0)
|
|
18
19
|
return toolResult('No branches found.');
|
|
19
|
-
return
|
|
20
|
+
return toolSummary(`${result.length} branch(es).`, result, 'Use create_branch to add a branch, or delete_branch to archive one.');
|
|
20
21
|
}
|
|
21
22
|
catch (e) {
|
|
22
|
-
return toolError(`Failed to list branches: ${e
|
|
23
|
+
return toolError(`Failed to list branches: ${formatApiError(e)}`);
|
|
23
24
|
}
|
|
24
25
|
});
|
|
25
26
|
},
|
|
@@ -39,10 +40,10 @@ defineTool({
|
|
|
39
40
|
}, async ({ file_key, name }) => {
|
|
40
41
|
try {
|
|
41
42
|
const result = await createBranch(config, { file_key, name });
|
|
42
|
-
return
|
|
43
|
+
return toolSummary('Created branch.', result, 'Use get_file with the branch file key to read the branch.');
|
|
43
44
|
}
|
|
44
45
|
catch (e) {
|
|
45
|
-
return toolError(`Failed to create branch: ${e
|
|
46
|
+
return toolError(`Failed to create branch: ${formatApiError(e)}`);
|
|
46
47
|
}
|
|
47
48
|
});
|
|
48
49
|
},
|
|
@@ -66,7 +67,7 @@ defineTool({
|
|
|
66
67
|
return toolResult(`Archived branch ${branch_key}`);
|
|
67
68
|
}
|
|
68
69
|
catch (e) {
|
|
69
|
-
return toolError(`Failed to delete branch: ${e
|
|
70
|
+
return toolError(`Failed to delete branch: ${formatApiError(e)}`);
|
|
70
71
|
}
|
|
71
72
|
});
|
|
72
73
|
},
|
package/dist/tools/comments.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineTool, toolResult, toolError, figmaId } from './register.js';
|
|
2
|
+
import { defineTool, toolResult, toolError, toolSummary, figmaId } from './register.js';
|
|
3
|
+
import { formatApiError } from '../helpers.js';
|
|
3
4
|
import { listComments, formatCommentsAsMarkdown, postComment, deleteComment, listCommentReactions, } from '../operations/comments.js';
|
|
4
5
|
// -- list_comments --
|
|
5
6
|
defineTool({
|
|
@@ -18,10 +19,12 @@ defineTool({
|
|
|
18
19
|
if (as_md) {
|
|
19
20
|
return toolResult(formatCommentsAsMarkdown(comments));
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
+
if (comments.length === 0)
|
|
23
|
+
return toolResult('No comments on this file.');
|
|
24
|
+
return toolSummary(`${comments.length} comment(s).`, comments, 'Use post_comment to reply, or delete_comment to remove.');
|
|
22
25
|
}
|
|
23
26
|
catch (e) {
|
|
24
|
-
return toolError(`Failed to list comments: ${e
|
|
27
|
+
return toolError(`Failed to list comments: ${formatApiError(e)}`);
|
|
25
28
|
}
|
|
26
29
|
});
|
|
27
30
|
},
|
|
@@ -43,10 +46,10 @@ defineTool({
|
|
|
43
46
|
}, async ({ file_key, message, comment_id, node_id }) => {
|
|
44
47
|
try {
|
|
45
48
|
const result = await postComment(config, { file_key, message, comment_id, node_id });
|
|
46
|
-
return
|
|
49
|
+
return toolSummary('Posted comment.', result);
|
|
47
50
|
}
|
|
48
51
|
catch (e) {
|
|
49
|
-
return toolError(`Failed to post comment: ${e
|
|
52
|
+
return toolError(`Failed to post comment: ${formatApiError(e)}`);
|
|
50
53
|
}
|
|
51
54
|
});
|
|
52
55
|
},
|
|
@@ -59,7 +62,7 @@ defineTool({
|
|
|
59
62
|
destructive: true,
|
|
60
63
|
register(server, config) {
|
|
61
64
|
server.registerTool('delete_comment', {
|
|
62
|
-
description: 'Permanently delete a comment. For top-level comments, the entire thread is removed.',
|
|
65
|
+
description: 'Permanently delete a comment. For top-level comments, the entire thread is removed. Cannot be undone.',
|
|
63
66
|
inputSchema: {
|
|
64
67
|
file_key: figmaId.describe('File key'),
|
|
65
68
|
comment_id: figmaId.describe('Comment ID to delete'),
|
|
@@ -70,7 +73,7 @@ defineTool({
|
|
|
70
73
|
return toolResult(`Deleted comment ${comment_id}`);
|
|
71
74
|
}
|
|
72
75
|
catch (e) {
|
|
73
|
-
return toolError(`Failed to delete comment: ${e
|
|
76
|
+
return toolError(`Failed to delete comment: ${formatApiError(e)}`);
|
|
74
77
|
}
|
|
75
78
|
});
|
|
76
79
|
},
|
|
@@ -89,10 +92,12 @@ defineTool({
|
|
|
89
92
|
}, async ({ file_key, comment_id }) => {
|
|
90
93
|
try {
|
|
91
94
|
const reactions = await listCommentReactions(config, { file_key, comment_id });
|
|
92
|
-
|
|
95
|
+
if (reactions.length === 0)
|
|
96
|
+
return toolResult('No reactions on this comment.');
|
|
97
|
+
return toolSummary(`${reactions.length} reaction(s).`, reactions);
|
|
93
98
|
}
|
|
94
99
|
catch (e) {
|
|
95
|
-
return toolError(`Failed to list reactions: ${e
|
|
100
|
+
return toolError(`Failed to list reactions: ${formatApiError(e)}`);
|
|
96
101
|
}
|
|
97
102
|
});
|
|
98
103
|
},
|
package/dist/tools/components.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineTool, toolResult, toolError, figmaId } from './register.js';
|
|
2
|
+
import { defineTool, toolResult, toolError, toolSummary, figmaId } from './register.js';
|
|
3
|
+
import { formatApiError } from '../helpers.js';
|
|
3
4
|
import { listFileComponents, listFileStyles, listTeamComponents, listTeamStyles, } from '../operations/components.js';
|
|
4
5
|
// -- list_file_components --
|
|
5
6
|
defineTool({
|
|
@@ -7,17 +8,19 @@ defineTool({
|
|
|
7
8
|
auth: 'pat',
|
|
8
9
|
register(server, config) {
|
|
9
10
|
server.registerTool('list_file_components', {
|
|
10
|
-
description: 'List components published from a
|
|
11
|
+
description: 'List components published from a file. Only published library components appear -- local unpublished components are not included.',
|
|
11
12
|
inputSchema: {
|
|
12
13
|
file_key: figmaId.describe('File key'),
|
|
13
14
|
},
|
|
14
15
|
}, async ({ file_key }) => {
|
|
15
16
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
17
|
+
const result = await listFileComponents(config, { file_key });
|
|
18
|
+
if (result.count === 0)
|
|
19
|
+
return toolResult('No published components in this file. Components must be published to appear.');
|
|
20
|
+
return toolSummary(`${result.count} published component(s).`, result);
|
|
18
21
|
}
|
|
19
22
|
catch (e) {
|
|
20
|
-
return toolError(`Failed to list file components: ${e
|
|
23
|
+
return toolError(`Failed to list file components: ${formatApiError(e)}`);
|
|
21
24
|
}
|
|
22
25
|
});
|
|
23
26
|
},
|
|
@@ -28,17 +31,19 @@ defineTool({
|
|
|
28
31
|
auth: 'pat',
|
|
29
32
|
register(server, config) {
|
|
30
33
|
server.registerTool('list_file_styles', {
|
|
31
|
-
description: 'List styles
|
|
34
|
+
description: 'List styles published from a file. Only published library styles appear.',
|
|
32
35
|
inputSchema: {
|
|
33
36
|
file_key: figmaId.describe('File key'),
|
|
34
37
|
},
|
|
35
38
|
}, async ({ file_key }) => {
|
|
36
39
|
try {
|
|
37
|
-
const
|
|
38
|
-
|
|
40
|
+
const result = await listFileStyles(config, { file_key });
|
|
41
|
+
if (result.count === 0)
|
|
42
|
+
return toolResult('No published styles in this file.');
|
|
43
|
+
return toolSummary(`${result.count} published style(s).`, result);
|
|
39
44
|
}
|
|
40
45
|
catch (e) {
|
|
41
|
-
return toolError(`Failed to list file styles: ${e
|
|
46
|
+
return toolError(`Failed to list file styles: ${formatApiError(e)}`);
|
|
42
47
|
}
|
|
43
48
|
});
|
|
44
49
|
},
|
|
@@ -49,7 +54,7 @@ defineTool({
|
|
|
49
54
|
auth: 'pat',
|
|
50
55
|
register(server, config) {
|
|
51
56
|
server.registerTool('list_team_components', {
|
|
52
|
-
description: 'List published components across a team.
|
|
57
|
+
description: 'List published components across a team. Pass the cursor from the response\'s pagination object to fetch the next page.',
|
|
53
58
|
inputSchema: {
|
|
54
59
|
team_id: figmaId.describe('Team ID'),
|
|
55
60
|
page_size: z.number().optional().default(30).describe('Max items per page (default: 30)'),
|
|
@@ -58,10 +63,12 @@ defineTool({
|
|
|
58
63
|
}, async ({ team_id, page_size, cursor }) => {
|
|
59
64
|
try {
|
|
60
65
|
const result = await listTeamComponents(config, { team_id, page_size, cursor });
|
|
61
|
-
|
|
66
|
+
const count = result.components?.length || 0;
|
|
67
|
+
const hasMore = !!result.pagination?.cursor;
|
|
68
|
+
return toolSummary(`${count} component(s)${hasMore ? ' (more pages available)' : ''}.`, result, hasMore ? 'Pass the cursor from pagination to fetch the next page.' : undefined);
|
|
62
69
|
}
|
|
63
70
|
catch (e) {
|
|
64
|
-
return toolError(`Failed to list team components: ${e
|
|
71
|
+
return toolError(`Failed to list team components: ${formatApiError(e)}`);
|
|
65
72
|
}
|
|
66
73
|
});
|
|
67
74
|
},
|
|
@@ -72,7 +79,7 @@ defineTool({
|
|
|
72
79
|
auth: 'pat',
|
|
73
80
|
register(server, config) {
|
|
74
81
|
server.registerTool('list_team_styles', {
|
|
75
|
-
description: 'List published styles across a team.
|
|
82
|
+
description: 'List published styles across a team. Pass the cursor from the response\'s pagination object to fetch the next page.',
|
|
76
83
|
inputSchema: {
|
|
77
84
|
team_id: figmaId.describe('Team ID'),
|
|
78
85
|
page_size: z.number().optional().default(30).describe('Max items per page (default: 30)'),
|
|
@@ -81,10 +88,12 @@ defineTool({
|
|
|
81
88
|
}, async ({ team_id, page_size, cursor }) => {
|
|
82
89
|
try {
|
|
83
90
|
const result = await listTeamStyles(config, { team_id, page_size, cursor });
|
|
84
|
-
|
|
91
|
+
const count = result.styles?.length || 0;
|
|
92
|
+
const hasMore = !!result.pagination?.cursor;
|
|
93
|
+
return toolSummary(`${count} style(s)${hasMore ? ' (more pages available)' : ''}.`, result, hasMore ? 'Pass the cursor from pagination to fetch the next page.' : undefined);
|
|
85
94
|
}
|
|
86
95
|
catch (e) {
|
|
87
|
-
return toolError(`Failed to list team styles: ${e
|
|
96
|
+
return toolError(`Failed to list team styles: ${formatApiError(e)}`);
|
|
88
97
|
}
|
|
89
98
|
});
|
|
90
99
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { defineTool,
|
|
2
|
+
import { defineTool, toolError, toolSummary, figmaId } from './register.js';
|
|
3
|
+
import { formatApiError } from '../helpers.js';
|
|
3
4
|
import { offboardUser, onboardUser, quarterlyDesignOpsReport, } from '../operations/compound-manager.js';
|
|
4
5
|
// -- offboard_user --
|
|
5
6
|
defineTool({
|
|
@@ -24,10 +25,11 @@ defineTool({
|
|
|
24
25
|
transfer_to,
|
|
25
26
|
org_id,
|
|
26
27
|
});
|
|
27
|
-
|
|
28
|
+
const mode = (execute ?? false) ? 'Offboarding complete.' : 'Offboarding audit (read-only). Set execute=true to proceed.';
|
|
29
|
+
return toolSummary(mode, result);
|
|
28
30
|
}
|
|
29
31
|
catch (e) {
|
|
30
|
-
return toolError(`Failed to audit user for offboarding: ${e
|
|
32
|
+
return toolError(`Failed to audit user for offboarding: ${formatApiError(e)}`);
|
|
31
33
|
}
|
|
32
34
|
});
|
|
33
35
|
},
|
|
@@ -60,10 +62,10 @@ defineTool({
|
|
|
60
62
|
confirm,
|
|
61
63
|
org_id,
|
|
62
64
|
});
|
|
63
|
-
return
|
|
65
|
+
return toolSummary(`Onboarding complete for ${email}.`, result);
|
|
64
66
|
}
|
|
65
67
|
catch (e) {
|
|
66
|
-
return toolError(`Failed to onboard user: ${e
|
|
68
|
+
return toolError(`Failed to onboard user: ${formatApiError(e)}`);
|
|
67
69
|
}
|
|
68
70
|
});
|
|
69
71
|
},
|
|
@@ -85,10 +87,11 @@ defineTool({
|
|
|
85
87
|
org_id,
|
|
86
88
|
days: days ?? 90,
|
|
87
89
|
});
|
|
88
|
-
|
|
90
|
+
const highlightText = result.highlights?.join(' ') || 'Report generated.';
|
|
91
|
+
return toolSummary(highlightText, result);
|
|
89
92
|
}
|
|
90
93
|
catch (e) {
|
|
91
|
-
return toolError(`Failed to generate design ops report: ${e
|
|
94
|
+
return toolError(`Failed to generate design ops report: ${formatApiError(e)}`);
|
|
92
95
|
}
|
|
93
96
|
});
|
|
94
97
|
},
|