@mainwp/mcp 1.0.0-beta.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.
Files changed (49) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +1034 -0
  3. package/dist/abilities.d.ts +144 -0
  4. package/dist/abilities.d.ts.map +1 -0
  5. package/dist/abilities.js +529 -0
  6. package/dist/abilities.js.map +1 -0
  7. package/dist/config.d.ts +135 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +405 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/confirmation-responses.d.ts +44 -0
  12. package/dist/confirmation-responses.d.ts.map +1 -0
  13. package/dist/confirmation-responses.js +120 -0
  14. package/dist/confirmation-responses.js.map +1 -0
  15. package/dist/errors.d.ts +118 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +206 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/index.d.ts +17 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +506 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/logging.d.ts +34 -0
  24. package/dist/logging.d.ts.map +1 -0
  25. package/dist/logging.js +74 -0
  26. package/dist/logging.js.map +1 -0
  27. package/dist/naming.d.ts +23 -0
  28. package/dist/naming.d.ts.map +1 -0
  29. package/dist/naming.js +37 -0
  30. package/dist/naming.js.map +1 -0
  31. package/dist/prompts.d.ts +22 -0
  32. package/dist/prompts.d.ts.map +1 -0
  33. package/dist/prompts.js +414 -0
  34. package/dist/prompts.js.map +1 -0
  35. package/dist/retry.d.ts +77 -0
  36. package/dist/retry.d.ts.map +1 -0
  37. package/dist/retry.js +206 -0
  38. package/dist/retry.js.map +1 -0
  39. package/dist/security.d.ts +41 -0
  40. package/dist/security.d.ts.map +1 -0
  41. package/dist/security.js +154 -0
  42. package/dist/security.js.map +1 -0
  43. package/dist/tools.d.ts +82 -0
  44. package/dist/tools.d.ts.map +1 -0
  45. package/dist/tools.js +861 -0
  46. package/dist/tools.js.map +1 -0
  47. package/package.json +73 -0
  48. package/settings.example.json +30 -0
  49. package/settings.schema.json +129 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Name Conversion Utilities
3
+ *
4
+ * Shared functions for converting between MainWP ability names and MCP tool names.
5
+ * Extracted to avoid circular imports between abilities.ts and tools.ts.
6
+ */
7
+ /**
8
+ * Convert ability name to MCP tool name
9
+ * Strips namespace prefix since MCP server name provides context.
10
+ * e.g., "mainwp/list-sites-v1" -> "list_sites_v1"
11
+ */
12
+ export declare function abilityNameToToolName(abilityName: string): string;
13
+ /**
14
+ * Map MCP tool name back to ability name.
15
+ * Prepends the namespace since tool names don't include it.
16
+ *
17
+ * Note: This server only uses the 'mainwp' namespace. The namespace parameter
18
+ * is kept for test flexibility but is always called with 'mainwp' in production.
19
+ *
20
+ * @example toolNameToAbilityName("list_sites_v1", "mainwp") -> "mainwp/list-sites-v1"
21
+ */
22
+ export declare function toolNameToAbilityName(toolName: string, namespace: string): string;
23
+ //# sourceMappingURL=naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CASjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKjF"}
package/dist/naming.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Name Conversion Utilities
3
+ *
4
+ * Shared functions for converting between MainWP ability names and MCP tool names.
5
+ * Extracted to avoid circular imports between abilities.ts and tools.ts.
6
+ */
7
+ /**
8
+ * Convert ability name to MCP tool name
9
+ * Strips namespace prefix since MCP server name provides context.
10
+ * e.g., "mainwp/list-sites-v1" -> "list_sites_v1"
11
+ */
12
+ export function abilityNameToToolName(abilityName) {
13
+ // Strip namespace prefix: "mainwp/list-sites-v1" → "list-sites-v1"
14
+ const slashIndex = abilityName.indexOf('/');
15
+ if (slashIndex === -1) {
16
+ throw new Error(`Invalid ability name format (missing namespace): ${abilityName}`);
17
+ }
18
+ const withoutNamespace = abilityName.slice(slashIndex + 1);
19
+ // Convert hyphens to underscores: "list-sites-v1" → "list_sites_v1"
20
+ return withoutNamespace.replace(/-/g, '_');
21
+ }
22
+ /**
23
+ * Map MCP tool name back to ability name.
24
+ * Prepends the namespace since tool names don't include it.
25
+ *
26
+ * Note: This server only uses the 'mainwp' namespace. The namespace parameter
27
+ * is kept for test flexibility but is always called with 'mainwp' in production.
28
+ *
29
+ * @example toolNameToAbilityName("list_sites_v1", "mainwp") -> "mainwp/list-sites-v1"
30
+ */
31
+ export function toolNameToAbilityName(toolName, namespace) {
32
+ // Convert underscores back to hyphens: "list_sites_v1" → "list-sites-v1"
33
+ const withHyphens = toolName.replace(/_/g, '-');
34
+ // Prepend namespace: "mainwp/list-sites-v1"
35
+ return `${namespace}/${withHyphens}`;
36
+ }
37
+ //# sourceMappingURL=naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.js","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,mEAAmE;IACnE,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,oDAAoD,WAAW,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAC3D,oEAAoE;IACpE,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB,EAAE,SAAiB;IACvE,yEAAyE;IACzE,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAChD,4CAA4C;IAC5C,OAAO,GAAG,SAAS,IAAI,WAAW,EAAE,CAAC;AACvC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * MCP Prompt Templates
3
+ *
4
+ * Pre-defined workflow prompts for common MainWP operations.
5
+ * These help AI assistants guide users through complex tasks.
6
+ */
7
+ import type { Prompt, GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
8
+ /**
9
+ * Get the list of available prompts for MCP ListPrompts request
10
+ */
11
+ export declare function getPromptList(): Prompt[];
12
+ /**
13
+ * Get a specific prompt with its messages for MCP GetPrompt request
14
+ */
15
+ export declare function getPrompt(name: string, args?: Record<string, string>): GetPromptResult;
16
+ /**
17
+ * Get prompt argument values for completions
18
+ * @param _promptName - Reserved for future prompt-specific completions
19
+ * @param argumentName - The argument to get completions for
20
+ */
21
+ export declare function getPromptArgumentCompletions(_promptName: string, argumentName: string): string[];
22
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAiB,MAAM,oCAAoC,CAAC;AAuVjG;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAMxC;AAwDD;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,eAAe,CAatF;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAWhG"}
@@ -0,0 +1,414 @@
1
+ /**
2
+ * MCP Prompt Templates
3
+ *
4
+ * Pre-defined workflow prompts for common MainWP operations.
5
+ * These help AI assistants guide users through complex tasks.
6
+ */
7
+ /**
8
+ * All available prompt definitions
9
+ */
10
+ const promptDefinitions = [
11
+ // === Site Troubleshooting ===
12
+ {
13
+ name: 'troubleshoot-site',
14
+ description: 'Diagnose issues with a MainWP child site',
15
+ arguments: [
16
+ { name: 'site_id', description: 'ID of the site to troubleshoot', required: true },
17
+ {
18
+ name: 'issue_type',
19
+ description: 'Focus area: connectivity, performance, security, updates (optional)',
20
+ required: false,
21
+ },
22
+ ],
23
+ getMessages: args => [
24
+ {
25
+ role: 'user',
26
+ content: {
27
+ type: 'text',
28
+ text: `Please diagnose issues with site ID ${args?.site_id || '[site_id]'}.${args?.issue_type ? ` Focus on: ${args.issue_type}.` : ''}
29
+
30
+ Steps to follow:
31
+ 1. Use get_site_v1 to get site details and check connectivity status
32
+ 2. Check the last sync time - if stale, there may be connectivity issues
33
+ 3. Use list_updates_v1 to check for pending updates
34
+ 4. Review any error messages or warnings
35
+
36
+ Provide a summary of:
37
+ - Current site status
38
+ - Any issues found
39
+ - Recommended actions to resolve problems`,
40
+ },
41
+ },
42
+ ],
43
+ },
44
+ // === Maintenance Check ===
45
+ {
46
+ name: 'maintenance-check',
47
+ description: 'Run a comprehensive maintenance check across all managed sites',
48
+ arguments: [],
49
+ getMessages: () => [
50
+ {
51
+ role: 'user',
52
+ content: {
53
+ type: 'text',
54
+ text: `Run a comprehensive maintenance check across all managed sites.
55
+
56
+ Steps to follow:
57
+ 1. Use list_sites_v1 to get all sites
58
+ 2. Use list_updates_v1 to check for pending updates
59
+ 3. Identify sites that haven't synced recently (check last_sync timestamps)
60
+
61
+ Generate a maintenance summary including:
62
+ - Total sites managed
63
+ - Sites with pending plugin updates (list them)
64
+ - Sites with pending theme updates (list them)
65
+ - Sites with pending WordPress core updates (list them)
66
+ - Sites with connectivity issues or stale sync times
67
+ - Recommended priority order for maintenance tasks`,
68
+ },
69
+ },
70
+ ],
71
+ },
72
+ // === Update Workflow ===
73
+ {
74
+ name: 'update-workflow',
75
+ description: 'Guide through safely updating WordPress sites',
76
+ arguments: [
77
+ {
78
+ name: 'update_type',
79
+ description: 'Type of updates: plugins, themes, core, or all',
80
+ required: false,
81
+ },
82
+ {
83
+ name: 'site_ids',
84
+ description: 'Comma-separated site IDs, or "all" for all sites',
85
+ required: false,
86
+ },
87
+ ],
88
+ getMessages: args => [
89
+ {
90
+ role: 'user',
91
+ content: {
92
+ type: 'text',
93
+ text: `Help me safely update ${args?.update_type || 'all'} on ${args?.site_ids || 'all sites'}.
94
+
95
+ Guide me through this update workflow:
96
+
97
+ 1. **Pre-update Assessment**
98
+ - List all pending ${args?.update_type || ''} updates using list_updates_v1
99
+ - Identify any updates that might have compatibility issues
100
+ - Check which sites are affected
101
+
102
+ 2. **Update Strategy**
103
+ - Recommend which updates to apply first (security patches > bug fixes > features)
104
+ - Suggest testing on staging/less critical sites first
105
+ - Identify any plugins/themes that should be researched before updating
106
+
107
+ 3. **Safety Recommendations**
108
+ - Remind about backup status
109
+ - Suggest update order (core before plugins/themes)
110
+ - Note any updates that require manual intervention
111
+
112
+ Please start by checking the current update status.`,
113
+ },
114
+ },
115
+ ],
116
+ },
117
+ // === Site Report ===
118
+ {
119
+ name: 'site-report',
120
+ description: 'Generate a detailed report for a specific site',
121
+ arguments: [{ name: 'site_id', description: 'ID of the site to report on', required: true }],
122
+ getMessages: args => [
123
+ {
124
+ role: 'user',
125
+ content: {
126
+ type: 'text',
127
+ text: `Generate a detailed report for site ID ${args?.site_id || '[site_id]'}.
128
+
129
+ Gather information using available tools and create a report covering:
130
+
131
+ 1. **Site Overview**
132
+ - Site name and URL
133
+ - WordPress version
134
+ - Last sync status and time
135
+
136
+ 2. **Update Status**
137
+ - Pending plugin updates (count and list)
138
+ - Pending theme updates (count and list)
139
+ - Core update status
140
+
141
+ 3. **Health Indicators**
142
+ - Connectivity status
143
+ - Any recent errors or warnings
144
+ - Sync reliability
145
+
146
+ 4. **Recommendations**
147
+ - Prioritized action items
148
+ - Any immediate concerns
149
+
150
+ Format the report in a clear, scannable format.`,
151
+ },
152
+ },
153
+ ],
154
+ },
155
+ // === Network Summary ===
156
+ {
157
+ name: 'network-summary',
158
+ description: 'Generate a summary report of all managed sites',
159
+ arguments: [],
160
+ getMessages: () => [
161
+ {
162
+ role: 'user',
163
+ content: {
164
+ type: 'text',
165
+ text: `Generate a network-wide summary of all managed WordPress sites.
166
+
167
+ Steps to follow:
168
+ 1. Use list_sites_v1 to get all sites
169
+ 2. Aggregate statistics across the network
170
+
171
+ Create a summary report including:
172
+
173
+ **Network Overview**
174
+ - Total number of sites
175
+ - Sites by status (connected, disconnected, issues)
176
+
177
+ **Update Summary**
178
+ - Total pending plugin updates
179
+ - Total pending theme updates
180
+ - Total pending core updates
181
+ - Sites fully up-to-date vs needing updates
182
+
183
+ **Health Overview**
184
+ - Sites synced in last 24 hours
185
+ - Sites with stale sync (>24 hours)
186
+ - Any sites with errors
187
+
188
+ **Action Items**
189
+ - Most urgent maintenance tasks
190
+ - Sites requiring immediate attention
191
+
192
+ Present the data in a clear, executive-summary format.`,
193
+ },
194
+ },
195
+ ],
196
+ },
197
+ // === Security Audit ===
198
+ {
199
+ name: 'security-audit',
200
+ description: 'Perform a security-focused audit of managed sites',
201
+ arguments: [
202
+ {
203
+ name: 'site_ids',
204
+ description: 'Comma-separated site IDs to audit, or "all"',
205
+ required: false,
206
+ },
207
+ ],
208
+ getMessages: args => [
209
+ {
210
+ role: 'user',
211
+ content: {
212
+ type: 'text',
213
+ text: `Perform a security-focused audit of ${args?.site_ids || 'all managed sites'}.
214
+
215
+ Security audit checklist:
216
+
217
+ 1. **WordPress Core**
218
+ - Check for outdated WordPress versions
219
+ - Identify any sites running unsupported versions
220
+
221
+ 2. **Plugin Security**
222
+ - List plugins with available security updates
223
+ - Identify any plugins that are abandoned/not updated in 2+ years
224
+ - Flag plugins known to have security issues
225
+
226
+ 3. **Theme Security**
227
+ - Check for outdated themes
228
+ - Identify unused themes that should be removed
229
+
230
+ 4. **General Recommendations**
231
+ - Sites most urgently needing security updates
232
+ - Best practices reminders
233
+ - Priority order for security updates
234
+
235
+ Start by gathering the site and update information, then provide the security assessment.`,
236
+ },
237
+ },
238
+ ],
239
+ },
240
+ // === Backup Status ===
241
+ {
242
+ name: 'backup-status',
243
+ description: 'Check backup status across managed sites',
244
+ arguments: [
245
+ {
246
+ name: 'site_ids',
247
+ description: 'Comma-separated site IDs, or "all" (default)',
248
+ required: false,
249
+ },
250
+ ],
251
+ getMessages: args => [
252
+ {
253
+ role: 'user',
254
+ content: {
255
+ type: 'text',
256
+ text: `Check the backup status for ${args?.site_ids || 'all managed sites'}.
257
+
258
+ Please help me understand the backup situation:
259
+
260
+ 1. **Backup Overview**
261
+ - Which sites have backup plugins installed?
262
+ - When was the last backup for each site?
263
+ - Are there any sites without backup solutions?
264
+
265
+ 2. **Backup Health**
266
+ - Sites with recent backups (< 24 hours)
267
+ - Sites with aging backups (> 7 days)
268
+ - Sites with no recent backup data
269
+
270
+ 3. **Recommendations**
271
+ - Sites that need immediate backup attention
272
+ - Suggestions for backup improvements
273
+ - Best practices for backup frequency
274
+
275
+ Note: This analysis depends on the backup data available through MainWP. If backup information is limited, please indicate what additional data would be helpful.`,
276
+ },
277
+ },
278
+ ],
279
+ },
280
+ // === Performance Check ===
281
+ {
282
+ name: 'performance-check',
283
+ description: 'Analyze site performance indicators',
284
+ arguments: [
285
+ {
286
+ name: 'site_id',
287
+ description: 'Site ID to analyze, or "all" for overview',
288
+ required: false,
289
+ },
290
+ ],
291
+ getMessages: args => [
292
+ {
293
+ role: 'user',
294
+ content: {
295
+ type: 'text',
296
+ text: `Analyze performance indicators for ${args?.site_id ? `site ID ${args.site_id}` : 'all managed sites'}.
297
+
298
+ Performance analysis:
299
+
300
+ 1. **Site Health**
301
+ - Sync response times (if available)
302
+ - Connection reliability
303
+ - Any timeout or connection errors
304
+
305
+ 2. **Resource Indicators**
306
+ - Number of active plugins (more plugins = potential slowdown)
307
+ - Theme complexity indicators
308
+ - Database or storage concerns (if data available)
309
+
310
+ 3. **Optimization Opportunities**
311
+ - Sites with excessive plugins
312
+ - Outdated components that may impact performance
313
+ - Caching and optimization plugin status
314
+
315
+ 4. **Recommendations**
316
+ - Sites most likely to benefit from optimization
317
+ - Quick wins for performance improvement
318
+ - Further investigation suggestions
319
+
320
+ Gather available data and provide performance insights based on what can be determined from MainWP.`,
321
+ },
322
+ },
323
+ ],
324
+ },
325
+ ];
326
+ /**
327
+ * Get the list of available prompts for MCP ListPrompts request
328
+ */
329
+ export function getPromptList() {
330
+ return promptDefinitions.map(({ name, description, arguments: args }) => ({
331
+ name,
332
+ description,
333
+ arguments: args,
334
+ }));
335
+ }
336
+ /** Allowed values for the issue_type prompt argument */
337
+ const VALID_ISSUE_TYPES = new Set(['connectivity', 'performance', 'security', 'updates']);
338
+ /** Allowed values for the update_type prompt argument */
339
+ const VALID_UPDATE_TYPES = new Set(['plugins', 'themes', 'core', 'all']);
340
+ /**
341
+ * Validate and sanitize prompt arguments before interpolation.
342
+ * Prevents prompt injection via template arguments.
343
+ */
344
+ function validatePromptArgs(args) {
345
+ if (!args)
346
+ return args;
347
+ const sanitized = {};
348
+ for (const [key, value] of Object.entries(args)) {
349
+ if (typeof value !== 'string')
350
+ continue;
351
+ // site_id: numeric or "all"; site_ids: "all" or comma-separated numeric
352
+ if (key === 'site_id') {
353
+ if (value !== 'all' && !/^\d+$/.test(value)) {
354
+ throw new Error(`Invalid site_id: must be a numeric value or "all"`);
355
+ }
356
+ sanitized[key] = value;
357
+ }
358
+ else if (key === 'site_ids') {
359
+ // "all" or comma-separated IDs
360
+ if (value !== 'all' && !/^(\d+)(,\s*\d+)*$/.test(value)) {
361
+ throw new Error(`Invalid site_ids: must be "all" or comma-separated numeric IDs`);
362
+ }
363
+ sanitized[key] = value;
364
+ }
365
+ else if (key === 'issue_type') {
366
+ if (!VALID_ISSUE_TYPES.has(value)) {
367
+ throw new Error(`Invalid issue_type: must be one of ${[...VALID_ISSUE_TYPES].join(', ')}`);
368
+ }
369
+ sanitized[key] = value;
370
+ }
371
+ else if (key === 'update_type') {
372
+ if (!VALID_UPDATE_TYPES.has(value)) {
373
+ throw new Error(`Invalid update_type: must be one of ${[...VALID_UPDATE_TYPES].join(', ')}`);
374
+ }
375
+ sanitized[key] = value;
376
+ }
377
+ else {
378
+ // Unknown argument: truncate to reasonable length and strip control characters
379
+ // eslint-disable-next-line no-control-regex
380
+ sanitized[key] = value.slice(0, 200).replace(/[\x00-\x1f]/g, '');
381
+ }
382
+ }
383
+ return sanitized;
384
+ }
385
+ /**
386
+ * Get a specific prompt with its messages for MCP GetPrompt request
387
+ */
388
+ export function getPrompt(name, args) {
389
+ const prompt = promptDefinitions.find(p => p.name === name);
390
+ if (!prompt) {
391
+ throw new Error(`Unknown prompt: ${name}`);
392
+ }
393
+ // Validate and sanitize arguments before interpolation to prevent prompt injection
394
+ const validatedArgs = validatePromptArgs(args);
395
+ return {
396
+ messages: prompt.getMessages(validatedArgs),
397
+ };
398
+ }
399
+ /**
400
+ * Get prompt argument values for completions
401
+ * @param _promptName - Reserved for future prompt-specific completions
402
+ * @param argumentName - The argument to get completions for
403
+ */
404
+ export function getPromptArgumentCompletions(_promptName, argumentName) {
405
+ if (argumentName === 'update_type') {
406
+ return ['plugins', 'themes', 'core', 'all'];
407
+ }
408
+ if (argumentName === 'issue_type') {
409
+ return ['connectivity', 'performance', 'security', 'updates'];
410
+ }
411
+ // site_id and site_ids require dynamic data - return empty for static completions
412
+ return [];
413
+ }
414
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Retry Logic for Transient Errors
3
+ *
4
+ * Provides exponential backoff with jitter for handling transient network
5
+ * failures and server errors (HTTP 5xx, 429, network errors).
6
+ *
7
+ * Key features:
8
+ * - Only retries transient errors (5xx, 429, network errors)
9
+ * - Permanent errors (4xx except 429) fail immediately
10
+ * - Timeout budget ensures total time never exceeds requestTimeout
11
+ * - Exponential backoff with jitter prevents thundering herd
12
+ */
13
+ import type { Logger } from './logging.js';
14
+ /**
15
+ * Options for retry behavior
16
+ */
17
+ export interface RetryOptions {
18
+ /** Maximum retry attempts including initial request */
19
+ maxRetries: number;
20
+ /** Base delay between retries in milliseconds */
21
+ baseDelay: number;
22
+ /** Maximum delay between retries in milliseconds */
23
+ maxDelay: number;
24
+ /** Total time budget in milliseconds for all attempts */
25
+ timeoutBudget: number;
26
+ /** Structured logger for retry attempts */
27
+ logger?: Logger;
28
+ }
29
+ /**
30
+ * Context passed to retryable operations for timeout budget awareness
31
+ */
32
+ export interface RetryContext {
33
+ /** Remaining timeout budget in milliseconds for this attempt */
34
+ remainingBudget: number;
35
+ /** Current attempt number (0-indexed) */
36
+ attempt: number;
37
+ }
38
+ /**
39
+ * A function that returns a promise and can be retried.
40
+ * Optionally receives retry context with remaining timeout budget.
41
+ */
42
+ export type RetryableOperation<T> = (context: RetryContext) => Promise<T>;
43
+ /**
44
+ * Determine if an error is retryable (transient).
45
+ *
46
+ * Retryable errors:
47
+ * - HTTP 5xx (server errors)
48
+ * - HTTP 429 (rate limited)
49
+ * - Network errors: ECONNRESET, ECONNREFUSED, ETIMEDOUT, ENOTFOUND
50
+ *
51
+ * Non-retryable errors:
52
+ * - HTTP 4xx (except 429): client errors, auth failures, validation errors
53
+ * - AbortError: user cancellation
54
+ * - Any other errors (treat as permanent)
55
+ */
56
+ export declare function isRetryableError(error: unknown): boolean;
57
+ /**
58
+ * Calculate exponential backoff delay with jitter.
59
+ *
60
+ * Formula: min(maxDelay, baseDelay * 2^attempt + random(0, baseDelay))
61
+ *
62
+ * @param attempt - 0-indexed attempt number (0 for first retry, 1 for second, etc.)
63
+ * @param baseDelay - Base delay in milliseconds
64
+ * @param maxDelay - Maximum delay in milliseconds
65
+ * @returns Delay in milliseconds
66
+ */
67
+ export declare function calculateBackoff(attempt: number, baseDelay: number, maxDelay: number): number;
68
+ /**
69
+ * Execute an operation with retry logic.
70
+ *
71
+ * @param operation - The async operation to execute
72
+ * @param options - Retry configuration
73
+ * @returns The result of the operation
74
+ * @throws The last error if all retries are exhausted or a non-retryable error occurs
75
+ */
76
+ export declare function withRetry<T>(operation: RetryableOperation<T>, options: RetryOptions): Promise<T>;
77
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,eAAe,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AA4E1E;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAoCxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAY7F;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,CAAC,CAwEZ"}