• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apowers313 / prompt-tool / 17061363984

19 Aug 2025 06:22AM UTC coverage: 86.862% (-1.4%) from 88.256%
17061363984

push

github

apowers313
ci: fix build, take 7

1101 of 1266 branches covered (86.97%)

Branch coverage included in aggregate %.

4 of 4 new or added lines in 1 file covered. (100.0%)

196 existing lines in 12 files now uncovered.

3719 of 4283 relevant lines covered (86.83%)

13.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.59
/src/utils/errors.ts
1
import chalk from 'chalk';
1✔
2
import { logger } from './logger.js';
1✔
3

4
export enum ErrorCategory {
1✔
5
  USER_ERROR = 'USER_ERROR',
1✔
6
  CONFIG_ERROR = 'CONFIG_ERROR',
1✔
7
  FILE_SYSTEM_ERROR = 'FILE_SYSTEM_ERROR',
1✔
8
  NETWORK_ERROR = 'NETWORK_ERROR',
1✔
9
  EXTERNAL_TOOL_ERROR = 'EXTERNAL_TOOL_ERROR',
1✔
10
  SYSTEM_ERROR = 'SYSTEM_ERROR',
1✔
11
  UNKNOWN = 'UNKNOWN'
1✔
12
}
13

14
export enum ErrorSeverity {
1✔
15
  WARNING = 'WARNING',
1✔
16
  ERROR = 'ERROR',
1✔
17
  FATAL = 'FATAL'
1✔
18
}
19

20
export interface ErrorSuggestion {
21
  text: string;
22
  command?: string;
23
}
24

25
export class PromptToolError extends Error {
1✔
26
  constructor(
1✔
27
    message: string,
54✔
28
    public code: string,
54✔
29
    public category: ErrorCategory = ErrorCategory.UNKNOWN,
54✔
30
    public severity: ErrorSeverity = ErrorSeverity.ERROR,
54✔
31
    public suggestions: ErrorSuggestion[] = [],
54✔
32
    public icon: string = '❌'
54✔
33
  ) {
54✔
34
    super(message);
54✔
35
    this.name = 'PromptToolError';
54✔
36
  }
54✔
37
}
1✔
38

39
export interface ErrorOptions {
40
  message: string;
41
  code: string;
42
  category?: ErrorCategory;
43
  severity?: ErrorSeverity;
44
  suggestions?: ErrorSuggestion[];
45
  icon?: string;
46
}
47

48
export function createError(options: ErrorOptions): PromptToolError {
1✔
49
  return new PromptToolError(
50✔
50
    options.message,
50✔
51
    options.code,
50✔
52
    options.category ?? ErrorCategory.UNKNOWN,
50✔
53
    options.severity ?? ErrorSeverity.ERROR,
50✔
54
    options.suggestions ?? [],
50✔
55
    options.icon ?? '❌'
50✔
56
  );
50✔
57
}
50✔
58

59
export function isRecoverableError(error: unknown): boolean {
1✔
60
  if (!(error instanceof PromptToolError)) {
4!
61
    return false;
×
UNCOV
62
  }
×
63
  
64
  if (error.severity === ErrorSeverity.FATAL) {
4✔
65
    return false;
1✔
66
  }
1✔
67
  
68
  const recoverableCategories = [
3✔
69
    ErrorCategory.USER_ERROR,
3✔
70
    ErrorCategory.CONFIG_ERROR,
3✔
71
    ErrorCategory.NETWORK_ERROR,
3✔
72
    ErrorCategory.EXTERNAL_TOOL_ERROR
3✔
73
  ];
3✔
74
  
75
  return recoverableCategories.includes(error.category);
3✔
76
}
3✔
77

78
export function getErrorCategory(error: unknown): ErrorCategory {
1✔
79
  if (error instanceof PromptToolError) {
3✔
80
    return error.category;
2✔
81
  }
2✔
82
  return ErrorCategory.UNKNOWN;
1✔
83
}
1✔
84

85
export function displayError(error: PromptToolError | Error): void {
1✔
86
  if (error instanceof PromptToolError) {
5✔
87
    const prefix = error.severity === ErrorSeverity.FATAL 
3✔
88
      ? chalk.bgRed.white(' FATAL ERROR: ')
1✔
89
      : error.severity === ErrorSeverity.WARNING
2✔
90
      ? chalk.yellow('Warning:')
1✔
91
      : chalk.red('Error:');
1✔
92
    
93
    const displayFn = error.severity === ErrorSeverity.WARNING ? logger.warn.bind(logger) : logger.error.bind(logger);
3✔
94
    
95
    displayFn(`${error.icon} ${prefix} ${error.message}`);
3✔
96
    
97
    if (error.suggestions.length > 0) {
3✔
98
      displayFn(chalk.yellow('\n💡 Suggestions:'));
2✔
99
      error.suggestions.forEach(suggestion => {
2✔
100
        displayFn(chalk.dim(`   • ${suggestion.text}`));
3✔
101
        if (suggestion.command) {
3✔
102
          displayFn(chalk.green(`     ▶️  ${suggestion.command}`));
1✔
103
        }
1✔
104
      });
2✔
105
    }
2✔
106
  } else {
5✔
107
    logger.error(chalk.red('Error:'), error.message);
2✔
108
  }
2✔
109
  
110
  if (process.env.DEBUG === 'true') {
5✔
111
    logger.error(chalk.dim('\nStack trace:'));
1✔
112
    logger.error(chalk.dim(error.stack || 'No stack trace available'));
1!
113
  }
1✔
114
}
5✔
115

116
// Common error creators
117
export const errors = {
1✔
118
  // File System Errors
119
  fileNotFound: (path: string) => createError({
1✔
120
    message: `File not found: ${path}`,
3✔
121
    code: 'FILE_NOT_FOUND',
3✔
122
    category: ErrorCategory.FILE_SYSTEM_ERROR,
3✔
123
    suggestions: [
3✔
124
      { text: 'Check if the file exists', command: `ls -la "${path}"` },
3✔
125
      { text: 'Verify the path is correct' },
3✔
126
      { text: 'Use absolute paths to avoid confusion' }
3✔
127
    ],
3✔
128
    icon: '📄'
3✔
129
  }),
3✔
130

131
  permissionDenied: (path: string) => createError({
1✔
132
    message: `Permission denied: ${path}`,
2✔
133
    code: 'PERMISSION_DENIED',
2✔
134
    category: ErrorCategory.FILE_SYSTEM_ERROR,
2✔
135
    suggestions: [
2✔
136
      { text: 'Check directory permissions', command: `ls -la "${path}"` },
2✔
137
      { text: 'Fix permissions', command: `chmod 755 "${path}"` },
2✔
138
      { text: 'Ensure directory exists', command: `mkdir -p "${path}"` }
2✔
139
    ],
2✔
140
    icon: '🔒'
2✔
141
  }),
2✔
142

143
  // User Errors
144
  noPromptsFound: (dirs: string[]) => createError({
1✔
145
    message: `No prompts found in: ${dirs.join(', ')}`,
5✔
146
    code: 'NO_PROMPTS',
5✔
147
    category: ErrorCategory.USER_ERROR,
5✔
148
    suggestions: [
5✔
149
      { text: 'Create a new prompt interactively', command: 'pt add' },
5✔
150
      { text: 'Generate a sample prompt', command: 'pt example' },
5✔
151
      { text: `Create a .md file in one of the directories` }
5✔
152
    ],
5✔
153
    icon: '🔍'
5✔
154
  }),
5✔
155

156
  validationError: (field: string, format: string, example: string) => createError({
1✔
157
    message: `Invalid ${field}`,
7✔
158
    code: 'VALIDATION_ERROR',
7✔
159
    category: ErrorCategory.USER_ERROR,
7✔
160
    severity: ErrorSeverity.WARNING,
7✔
161
    suggestions: [
7✔
162
      { text: `Expected format: ${format}` },
7✔
163
      { text: `Example: ${example}` }
7✔
164
    ],
7✔
165
    icon: '✏️'
7✔
166
  }),
7✔
167

168
  templateError: (template: string, details: string) => createError({
1✔
169
    message: `Template error in "${template}": ${details}`,
1✔
170
    code: 'TEMPLATE_ERROR',
1✔
171
    category: ErrorCategory.USER_ERROR,
1✔
172
    suggestions: [
1✔
173
      { text: 'Check template syntax' },
1✔
174
      { text: 'Ensure all helpers are closed properly' },
1✔
175
      { text: 'Verify variable names are correct' }
1✔
176
    ],
1✔
177
    icon: '📝'
1✔
178
  }),
1✔
179

180
  // Configuration Errors
181
  configMissing: () => createError({
1✔
182
    message: 'No configuration found',
4✔
183
    code: 'NO_CONFIG',
4✔
184
    category: ErrorCategory.CONFIG_ERROR,
4✔
185
    suggestions: [
4✔
186
      { text: 'Initialize configuration', command: 'pt init' }
4✔
187
    ],
4✔
188
    icon: '⚙️'
4✔
189
  }),
4✔
190

191
  invalidConfig: (field: string, expected: string, actual: unknown) => createError({
1✔
192
    message: `Configuration error: '${field}' must be ${expected} (found: ${typeof actual})`,
7✔
193
    code: 'INVALID_CONFIG',
7✔
194
    category: ErrorCategory.CONFIG_ERROR,
7✔
195
    suggestions: [
7✔
196
      { text: `Edit .pt-config.json and fix the '${field}' value` },
7✔
197
      { text: `Expected format: ${expected}` }
7✔
198
    ],
7✔
199
    icon: '⚙️'
7✔
200
  }),
7✔
201

202
  featureNotEnabled: (feature: string, benefits: string[]) => createError({
1✔
203
    message: `${feature} is not enabled`,
4✔
204
    code: 'FEATURE_DISABLED',
4✔
205
    category: ErrorCategory.CONFIG_ERROR,
4✔
206
    severity: ErrorSeverity.WARNING,
4✔
207
    suggestions: [
4✔
208
      { text: 'Enable it by running:', command: 'pt init' },
4✔
209
      { text: `Benefits: ${benefits.join(', ')}` }
4✔
210
    ],
4✔
211
    icon: '🎯'
4✔
212
  }),
4✔
213

214
  // External Tool Errors
215
  toolNotFound: (tool: string, suggestions: string[] = []) => createError({
1✔
216
    message: `Tool '${tool}' not found`,
2✔
217
    code: 'TOOL_NOT_FOUND',
2✔
218
    category: ErrorCategory.EXTERNAL_TOOL_ERROR,
2✔
219
    suggestions: [
2✔
220
      ...suggestions.map(s => ({ text: `Did you mean '${s}'?` })),
2✔
221
      { text: 'Check if installed', command: `which ${tool}` },
2✔
222
      { text: 'Install if needed', command: `npm install -g ${tool}` }
2✔
223
    ],
2✔
224
    icon: '🔧'
2✔
225
  }),
2✔
226

227
  noEditor: () => createError({
1✔
228
    message: 'No editor configured',
3✔
229
    code: 'NO_EDITOR',
3✔
230
    category: ErrorCategory.EXTERNAL_TOOL_ERROR,
3✔
231
    suggestions: [
3✔
232
      { text: 'Set your editor:', command: 'export EDITOR=vim' },
3✔
233
      { text: 'For VS Code:', command: 'export EDITOR="code --wait"' },
3✔
234
      { text: 'Add to your shell profile to make permanent' }
3✔
235
    ],
3✔
236
    icon: '✏️'
3✔
237
  }),
3✔
238

239
  gitError: (details: string) => createError({
1✔
240
    message: `Git error: ${details}`,
3✔
241
    code: 'GIT_ERROR',
3✔
242
    category: ErrorCategory.EXTERNAL_TOOL_ERROR,
3✔
243
    suggestions: [
3✔
244
      { text: 'Check git status', command: 'git status' },
3✔
245
      { text: 'View git log', command: 'git log --oneline -5' },
3✔
246
      { text: 'Ensure you\'re in a git repository' }
3✔
247
    ],
3✔
248
    icon: '🔗'
3✔
249
  }),
3✔
250

251
  gitNotInstalled: () => createError({
1✔
252
    message: 'Git is not installed',
1✔
253
    code: 'GIT_NOT_INSTALLED',
1✔
254
    category: ErrorCategory.EXTERNAL_TOOL_ERROR,
1✔
255
    suggestions: [
1✔
256
      { text: 'Install git for your platform' },
1✔
257
      { text: 'macOS:', command: 'brew install git' },
1✔
258
      { text: 'Ubuntu/Debian:', command: 'sudo apt-get install git' },
1✔
259
      { text: 'Visit https://git-scm.com/downloads for more options' }
1✔
260
    ],
1✔
261
    icon: '🔗'
1✔
262
  }),
1✔
263

264
  // Network Errors
265
  networkError: (url: string, details: string) => createError({
1✔
266
    message: `Network error accessing ${url}: ${details}`,
2✔
267
    code: 'NETWORK_ERROR',
2✔
268
    category: ErrorCategory.NETWORK_ERROR,
2✔
269
    suggestions: [
2✔
270
      { text: 'Check your internet connection' },
2✔
271
      { text: 'Verify the URL is correct' },
2✔
272
      { text: 'Try again in a few moments' },
2✔
273
      { text: 'Check if you need to configure a proxy' }
2✔
274
    ],
2✔
275
    icon: '🌐'
2✔
276
  }),
2✔
277

278
  // History Errors  
279
  historyNotFound: (index: number, total: number) => createError({
1✔
280
    message: `History entry #${index} not found`,
2✔
281
    code: 'HISTORY_NOT_FOUND',
2✔
282
    category: ErrorCategory.USER_ERROR,
2✔
283
    severity: ErrorSeverity.WARNING,
2✔
284
    suggestions: [
2✔
285
      { text: `Available entries: 1-${total}` },
2✔
286
      { text: 'View all entries', command: 'pt history' }
2✔
287
    ],
2✔
288
    icon: '📋'
2✔
289
  })
2✔
290
};
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc