developer-ai 1.0.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 (105) hide show
  1. package/README.md +241 -0
  2. package/bin/developer-ai.js +2 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +219 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config/index.d.ts +7 -0
  8. package/dist/config/index.d.ts.map +1 -0
  9. package/dist/config/index.js +82 -0
  10. package/dist/config/index.js.map +1 -0
  11. package/dist/config/schema.d.ts +115 -0
  12. package/dist/config/schema.d.ts.map +1 -0
  13. package/dist/config/schema.js +29 -0
  14. package/dist/config/schema.js.map +1 -0
  15. package/dist/constants.d.ts +8 -0
  16. package/dist/constants.d.ts.map +1 -0
  17. package/dist/constants.js +8 -0
  18. package/dist/constants.js.map +1 -0
  19. package/dist/core/agent.d.ts +38 -0
  20. package/dist/core/agent.d.ts.map +1 -0
  21. package/dist/core/agent.js +155 -0
  22. package/dist/core/agent.js.map +1 -0
  23. package/dist/core/system-prompt.d.ts +6 -0
  24. package/dist/core/system-prompt.d.ts.map +1 -0
  25. package/dist/core/system-prompt.js +44 -0
  26. package/dist/core/system-prompt.js.map +1 -0
  27. package/dist/core/types.d.ts +42 -0
  28. package/dist/core/types.d.ts.map +1 -0
  29. package/dist/core/types.js +6 -0
  30. package/dist/core/types.js.map +1 -0
  31. package/dist/index.d.ts +15 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +12 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/mcp/client.d.ts +13 -0
  36. package/dist/mcp/client.d.ts.map +1 -0
  37. package/dist/mcp/client.js +202 -0
  38. package/dist/mcp/client.js.map +1 -0
  39. package/dist/providers/ollama.d.ts +13 -0
  40. package/dist/providers/ollama.d.ts.map +1 -0
  41. package/dist/providers/ollama.js +60 -0
  42. package/dist/providers/ollama.js.map +1 -0
  43. package/dist/providers/openai.d.ts +9 -0
  44. package/dist/providers/openai.d.ts.map +1 -0
  45. package/dist/providers/openai.js +40 -0
  46. package/dist/providers/openai.js.map +1 -0
  47. package/dist/skills/loader.d.ts +25 -0
  48. package/dist/skills/loader.d.ts.map +1 -0
  49. package/dist/skills/loader.js +93 -0
  50. package/dist/skills/loader.js.map +1 -0
  51. package/dist/tests/tools.test.d.ts +2 -0
  52. package/dist/tests/tools.test.d.ts.map +1 -0
  53. package/dist/tests/tools.test.js +170 -0
  54. package/dist/tests/tools.test.js.map +1 -0
  55. package/dist/tools/index.d.ts +5 -0
  56. package/dist/tools/index.d.ts.map +1 -0
  57. package/dist/tools/index.js +19 -0
  58. package/dist/tools/index.js.map +1 -0
  59. package/dist/tools/list-files.d.ts +3 -0
  60. package/dist/tools/list-files.d.ts.map +1 -0
  61. package/dist/tools/list-files.js +60 -0
  62. package/dist/tools/list-files.js.map +1 -0
  63. package/dist/tools/read-file.d.ts +3 -0
  64. package/dist/tools/read-file.d.ts.map +1 -0
  65. package/dist/tools/read-file.js +46 -0
  66. package/dist/tools/read-file.js.map +1 -0
  67. package/dist/tools/registry.d.ts +24 -0
  68. package/dist/tools/registry.d.ts.map +1 -0
  69. package/dist/tools/registry.js +37 -0
  70. package/dist/tools/registry.js.map +1 -0
  71. package/dist/tools/run-command.d.ts +3 -0
  72. package/dist/tools/run-command.d.ts.map +1 -0
  73. package/dist/tools/run-command.js +114 -0
  74. package/dist/tools/run-command.js.map +1 -0
  75. package/dist/tools/search-text.d.ts +3 -0
  76. package/dist/tools/search-text.d.ts.map +1 -0
  77. package/dist/tools/search-text.js +103 -0
  78. package/dist/tools/search-text.js.map +1 -0
  79. package/dist/tools/utils.d.ts +6 -0
  80. package/dist/tools/utils.d.ts.map +1 -0
  81. package/dist/tools/utils.js +14 -0
  82. package/dist/tools/utils.js.map +1 -0
  83. package/dist/tools/web-search.d.ts +3 -0
  84. package/dist/tools/web-search.d.ts.map +1 -0
  85. package/dist/tools/web-search.js +80 -0
  86. package/dist/tools/web-search.js.map +1 -0
  87. package/dist/tools/write-file.d.ts +3 -0
  88. package/dist/tools/write-file.d.ts.map +1 -0
  89. package/dist/tools/write-file.js +66 -0
  90. package/dist/tools/write-file.js.map +1 -0
  91. package/package.json +54 -0
  92. package/skills/accessibility/SKILL.md +496 -0
  93. package/skills/api-design/SKILL.md +419 -0
  94. package/skills/code-review/SKILL.md +267 -0
  95. package/skills/debugging/SKILL.md +332 -0
  96. package/skills/documentation/SKILL.md +496 -0
  97. package/skills/error-handling/SKILL.md +504 -0
  98. package/skills/git-workflow/SKILL.md +448 -0
  99. package/skills/human-like-coding/SKILL.md +400 -0
  100. package/skills/performance-optimization/SKILL.md +412 -0
  101. package/skills/prompt-engineering/SKILL.md +362 -0
  102. package/skills/refactoring/SKILL.md +457 -0
  103. package/skills/security-audit/SKILL.md +453 -0
  104. package/skills/testing-strategy/SKILL.md +501 -0
  105. package/skills/webapp-testing/SKILL.md +309 -0
@@ -0,0 +1,504 @@
1
+ ---
2
+ name: error-handling
3
+ description: Guide for implementing robust error handling. Use when designing error handling strategies, creating custom errors, implementing retry logic, or improving error messages. Covers error types, try-catch patterns, async error handling, and user-facing errors.
4
+ ---
5
+
6
+ # Error Handling Skill
7
+
8
+ This skill provides guidance for implementing robust, user-friendly error handling in applications.
9
+
10
+ ## Overview
11
+
12
+ Good error handling improves debugging, user experience, and system reliability. This skill covers patterns for catching, processing, and communicating errors effectively.
13
+
14
+ ## Error Hierarchy
15
+
16
+ ### Custom Error Classes
17
+
18
+ ```javascript
19
+ // Base application error
20
+ class AppError extends Error {
21
+ constructor(message, statusCode = 500, code = 'INTERNAL_ERROR') {
22
+ super(message);
23
+ this.name = this.constructor.name;
24
+ this.statusCode = statusCode;
25
+ this.code = code;
26
+ this.isOperational = true;
27
+ Error.captureStackTrace(this, this.constructor);
28
+ }
29
+ }
30
+
31
+ // Specific error types
32
+ class ValidationError extends AppError {
33
+ constructor(message, details = []) {
34
+ super(message, 400, 'VALIDATION_ERROR');
35
+ this.details = details;
36
+ }
37
+ }
38
+
39
+ class NotFoundError extends AppError {
40
+ constructor(resource = 'Resource') {
41
+ super(`${resource} not found`, 404, 'NOT_FOUND');
42
+ }
43
+ }
44
+
45
+ class UnauthorizedError extends AppError {
46
+ constructor(message = 'Authentication required') {
47
+ super(message, 401, 'UNAUTHORIZED');
48
+ }
49
+ }
50
+
51
+ class ForbiddenError extends AppError {
52
+ constructor(message = 'Access denied') {
53
+ super(message, 403, 'FORBIDDEN');
54
+ }
55
+ }
56
+
57
+ class ConflictError extends AppError {
58
+ constructor(message = 'Resource conflict') {
59
+ super(message, 409, 'CONFLICT');
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### Usage
65
+
66
+ ```javascript
67
+ function getUser(id) {
68
+ const user = users.find(u => u.id === id);
69
+ if (!user) {
70
+ throw new NotFoundError('User');
71
+ }
72
+ return user;
73
+ }
74
+
75
+ function validateEmail(email) {
76
+ if (!email.includes('@')) {
77
+ throw new ValidationError('Invalid email format', [
78
+ { field: 'email', message: 'Must contain @' }
79
+ ]);
80
+ }
81
+ }
82
+ ```
83
+
84
+ ## Try-Catch Patterns
85
+
86
+ ### Basic Try-Catch
87
+
88
+ ```javascript
89
+ try {
90
+ const result = riskyOperation();
91
+ return result;
92
+ } catch (error) {
93
+ // Handle specific errors differently
94
+ if (error instanceof ValidationError) {
95
+ return { error: error.details };
96
+ }
97
+ if (error instanceof NotFoundError) {
98
+ return { error: 'Item not found' };
99
+ }
100
+ // Re-throw unexpected errors
101
+ throw error;
102
+ }
103
+ ```
104
+
105
+ ### With Finally
106
+
107
+ ```javascript
108
+ let connection;
109
+ try {
110
+ connection = await database.connect();
111
+ const result = await connection.query(sql);
112
+ return result;
113
+ } catch (error) {
114
+ logger.error('Database query failed', { error, sql });
115
+ throw new AppError('Database operation failed');
116
+ } finally {
117
+ // Always cleanup
118
+ if (connection) {
119
+ await connection.release();
120
+ }
121
+ }
122
+ ```
123
+
124
+ ### Wrapping Errors
125
+
126
+ ```javascript
127
+ async function fetchUserData(userId) {
128
+ try {
129
+ const response = await fetch(`/api/users/${userId}`);
130
+ if (!response.ok) {
131
+ throw new Error(`HTTP ${response.status}`);
132
+ }
133
+ return await response.json();
134
+ } catch (error) {
135
+ // Wrap with context
136
+ throw new AppError(
137
+ `Failed to fetch user ${userId}: ${error.message}`,
138
+ 500,
139
+ 'FETCH_ERROR'
140
+ );
141
+ }
142
+ }
143
+ ```
144
+
145
+ ## Async Error Handling
146
+
147
+ ### Async/Await
148
+
149
+ ```javascript
150
+ // With try-catch
151
+ async function processOrder(orderId) {
152
+ try {
153
+ const order = await getOrder(orderId);
154
+ const payment = await processPayment(order);
155
+ await updateInventory(order.items);
156
+ await sendConfirmation(order);
157
+ return { success: true, payment };
158
+ } catch (error) {
159
+ logger.error('Order processing failed', { orderId, error });
160
+ throw error;
161
+ }
162
+ }
163
+
164
+ // Express async wrapper
165
+ const asyncHandler = (fn) => (req, res, next) => {
166
+ Promise.resolve(fn(req, res, next)).catch(next);
167
+ };
168
+
169
+ app.get('/orders/:id', asyncHandler(async (req, res) => {
170
+ const order = await getOrder(req.params.id);
171
+ res.json(order);
172
+ }));
173
+ ```
174
+
175
+ ### Promise Error Handling
176
+
177
+ ```javascript
178
+ // Chain with catch
179
+ fetchData()
180
+ .then(processData)
181
+ .then(saveResult)
182
+ .catch(handleError);
183
+
184
+ // Multiple promises
185
+ const results = await Promise.allSettled([
186
+ fetchUsers(),
187
+ fetchOrders(),
188
+ fetchProducts(),
189
+ ]);
190
+
191
+ const errors = results
192
+ .filter(r => r.status === 'rejected')
193
+ .map(r => r.reason);
194
+
195
+ if (errors.length) {
196
+ logger.warn('Some operations failed', { errors });
197
+ }
198
+ ```
199
+
200
+ ### Timeout Handling
201
+
202
+ ```javascript
203
+ function withTimeout(promise, ms) {
204
+ const timeout = new Promise((_, reject) => {
205
+ setTimeout(() => reject(new Error('Operation timed out')), ms);
206
+ });
207
+ return Promise.race([promise, timeout]);
208
+ }
209
+
210
+ try {
211
+ const result = await withTimeout(fetchData(), 5000);
212
+ } catch (error) {
213
+ if (error.message === 'Operation timed out') {
214
+ // Handle timeout specifically
215
+ }
216
+ throw error;
217
+ }
218
+ ```
219
+
220
+ ## Express Error Handling
221
+
222
+ ### Error Middleware
223
+
224
+ ```javascript
225
+ // Error handler middleware (must have 4 parameters)
226
+ function errorHandler(err, req, res, next) {
227
+ // Log error
228
+ logger.error({
229
+ message: err.message,
230
+ stack: err.stack,
231
+ path: req.path,
232
+ method: req.method,
233
+ body: req.body,
234
+ });
235
+
236
+ // Operational errors - safe to send to client
237
+ if (err.isOperational) {
238
+ return res.status(err.statusCode).json({
239
+ error: {
240
+ code: err.code,
241
+ message: err.message,
242
+ ...(err.details && { details: err.details }),
243
+ },
244
+ });
245
+ }
246
+
247
+ // Programming errors - don't leak details
248
+ res.status(500).json({
249
+ error: {
250
+ code: 'INTERNAL_ERROR',
251
+ message: 'Something went wrong',
252
+ },
253
+ });
254
+ }
255
+
256
+ // 404 handler
257
+ function notFoundHandler(req, res) {
258
+ res.status(404).json({
259
+ error: {
260
+ code: 'NOT_FOUND',
261
+ message: `Route ${req.method} ${req.path} not found`,
262
+ },
263
+ });
264
+ }
265
+
266
+ // Apply middleware
267
+ app.use(notFoundHandler);
268
+ app.use(errorHandler);
269
+ ```
270
+
271
+ ### Validation Error Handling
272
+
273
+ ```javascript
274
+ const { validationResult } = require('express-validator');
275
+
276
+ function handleValidationErrors(req, res, next) {
277
+ const errors = validationResult(req);
278
+
279
+ if (!errors.isEmpty()) {
280
+ throw new ValidationError('Validation failed',
281
+ errors.array().map(e => ({
282
+ field: e.path,
283
+ message: e.msg,
284
+ }))
285
+ );
286
+ }
287
+
288
+ next();
289
+ }
290
+ ```
291
+
292
+ ## React Error Handling
293
+
294
+ ### Error Boundaries
295
+
296
+ ```jsx
297
+ class ErrorBoundary extends React.Component {
298
+ constructor(props) {
299
+ super(props);
300
+ this.state = { hasError: false, error: null };
301
+ }
302
+
303
+ static getDerivedStateFromError(error) {
304
+ return { hasError: true, error };
305
+ }
306
+
307
+ componentDidCatch(error, errorInfo) {
308
+ // Log to error reporting service
309
+ logErrorToService(error, errorInfo);
310
+ }
311
+
312
+ render() {
313
+ if (this.state.hasError) {
314
+ return this.props.fallback || <ErrorFallback error={this.state.error} />;
315
+ }
316
+
317
+ return this.props.children;
318
+ }
319
+ }
320
+
321
+ // Usage
322
+ <ErrorBoundary fallback={<div>Something went wrong</div>}>
323
+ <MyComponent />
324
+ </ErrorBoundary>
325
+ ```
326
+
327
+ ### Async Error Handling in React
328
+
329
+ ```jsx
330
+ function useAsync(asyncFn, dependencies = []) {
331
+ const [state, setState] = useState({
332
+ data: null,
333
+ error: null,
334
+ loading: true,
335
+ });
336
+
337
+ useEffect(() => {
338
+ setState(s => ({ ...s, loading: true }));
339
+
340
+ asyncFn()
341
+ .then(data => setState({ data, error: null, loading: false }))
342
+ .catch(error => setState({ data: null, error, loading: false }));
343
+ }, dependencies);
344
+
345
+ return state;
346
+ }
347
+
348
+ // Usage
349
+ function UserProfile({ userId }) {
350
+ const { data: user, error, loading } = useAsync(
351
+ () => fetchUser(userId),
352
+ [userId]
353
+ );
354
+
355
+ if (loading) return <Loading />;
356
+ if (error) return <ErrorMessage error={error} />;
357
+ return <Profile user={user} />;
358
+ }
359
+ ```
360
+
361
+ ## Retry Logic
362
+
363
+ ### Exponential Backoff
364
+
365
+ ```javascript
366
+ async function withRetry(fn, options = {}) {
367
+ const {
368
+ maxAttempts = 3,
369
+ baseDelay = 1000,
370
+ maxDelay = 10000,
371
+ shouldRetry = () => true,
372
+ } = options;
373
+
374
+ let lastError;
375
+
376
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
377
+ try {
378
+ return await fn();
379
+ } catch (error) {
380
+ lastError = error;
381
+
382
+ if (attempt === maxAttempts || !shouldRetry(error)) {
383
+ throw error;
384
+ }
385
+
386
+ const delay = Math.min(
387
+ baseDelay * Math.pow(2, attempt - 1),
388
+ maxDelay
389
+ );
390
+
391
+ await new Promise(resolve => setTimeout(resolve, delay));
392
+ }
393
+ }
394
+
395
+ throw lastError;
396
+ }
397
+
398
+ // Usage
399
+ const data = await withRetry(
400
+ () => fetchFromAPI('/data'),
401
+ {
402
+ maxAttempts: 3,
403
+ shouldRetry: (error) => error.status >= 500,
404
+ }
405
+ );
406
+ ```
407
+
408
+ ## Error Messages
409
+
410
+ ### User-Facing Messages
411
+
412
+ ```javascript
413
+ const UserMessages = {
414
+ VALIDATION_ERROR: 'Please check your input and try again.',
415
+ NOT_FOUND: 'The requested item could not be found.',
416
+ UNAUTHORIZED: 'Please log in to continue.',
417
+ FORBIDDEN: 'You don\'t have permission to do this.',
418
+ CONFLICT: 'This item already exists.',
419
+ NETWORK_ERROR: 'Unable to connect. Please check your internet.',
420
+ INTERNAL_ERROR: 'Something went wrong. Please try again later.',
421
+ };
422
+
423
+ function getUserMessage(error) {
424
+ return UserMessages[error.code] || UserMessages.INTERNAL_ERROR;
425
+ }
426
+ ```
427
+
428
+ ### Developer-Facing Messages
429
+
430
+ ```javascript
431
+ // Include context for debugging
432
+ throw new AppError(
433
+ `Failed to process order ${orderId}: Payment declined for user ${userId}`,
434
+ 400,
435
+ 'PAYMENT_DECLINED'
436
+ );
437
+
438
+ // Structured logging
439
+ logger.error('Order processing failed', {
440
+ orderId,
441
+ userId,
442
+ amount,
443
+ paymentMethod,
444
+ error: error.message,
445
+ stack: error.stack,
446
+ });
447
+ ```
448
+
449
+ ## Error Logging
450
+
451
+ ### Structured Logging
452
+
453
+ ```javascript
454
+ const winston = require('winston');
455
+
456
+ const logger = winston.createLogger({
457
+ level: 'info',
458
+ format: winston.format.combine(
459
+ winston.format.timestamp(),
460
+ winston.format.json()
461
+ ),
462
+ defaultMeta: { service: 'api' },
463
+ transports: [
464
+ new winston.transports.File({ filename: 'error.log', level: 'error' }),
465
+ new winston.transports.File({ filename: 'combined.log' }),
466
+ ],
467
+ });
468
+
469
+ // Log with context
470
+ function logError(error, context = {}) {
471
+ logger.error({
472
+ message: error.message,
473
+ code: error.code,
474
+ stack: error.stack,
475
+ ...context,
476
+ });
477
+ }
478
+ ```
479
+
480
+ ## Error Handling Checklist
481
+
482
+ ### Implementation
483
+ - [ ] Custom error classes created
484
+ - [ ] Error middleware configured
485
+ - [ ] Async errors handled
486
+ - [ ] Error boundaries in React
487
+
488
+ ### Logging
489
+ - [ ] Errors logged with context
490
+ - [ ] Stack traces captured
491
+ - [ ] No sensitive data in logs
492
+ - [ ] Log levels appropriate
493
+
494
+ ### User Experience
495
+ - [ ] User-friendly error messages
496
+ - [ ] Actionable feedback provided
497
+ - [ ] Recovery options available
498
+ - [ ] Loading/error states handled
499
+
500
+ ### Monitoring
501
+ - [ ] Error tracking configured
502
+ - [ ] Alerts for critical errors
503
+ - [ ] Error trends monitored
504
+ - [ ] Resolution time tracked