@alavida/agentpack 0.1.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.
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Structured error codes matching the CLI design reference exit code map.
3
+ */
4
+ export const EXIT_CODES = {
5
+ SUCCESS: 0,
6
+ GENERAL: 1,
7
+ VALIDATION: 2,
8
+ NETWORK: 3,
9
+ NOT_FOUND: 4,
10
+ };
11
+
12
+ /**
13
+ * Base error class for all agentpack CLI errors.
14
+ * Carries a machine-readable code and mapped exit code.
15
+ */
16
+ export class AgentpackError extends Error {
17
+ constructor(message, { code, exitCode = EXIT_CODES.GENERAL, suggestion } = {}) {
18
+ super(message);
19
+ this.name = 'AgentpackError';
20
+ this.code = code || 'general_error';
21
+ this.exitCode = exitCode;
22
+ this.suggestion = suggestion;
23
+ }
24
+
25
+ toJSON() {
26
+ return {
27
+ error: this.code,
28
+ message: this.message,
29
+ ...(this.suggestion && { suggestion: this.suggestion }),
30
+ };
31
+ }
32
+ }
33
+
34
+ export class ValidationError extends AgentpackError {
35
+ constructor(message, opts = {}) {
36
+ super(message, { code: 'validation_error', exitCode: EXIT_CODES.VALIDATION, ...opts });
37
+ this.name = 'ValidationError';
38
+ }
39
+ }
40
+
41
+ export class NetworkError extends AgentpackError {
42
+ constructor(message, opts = {}) {
43
+ super(message, { code: 'network_error', exitCode: EXIT_CODES.NETWORK, ...opts });
44
+ this.name = 'NetworkError';
45
+ }
46
+ }
47
+
48
+ export class NotFoundError extends AgentpackError {
49
+ constructor(message, opts = {}) {
50
+ super(message, { code: 'not_found', exitCode: EXIT_CODES.NOT_FOUND, ...opts });
51
+ this.name = 'NotFoundError';
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Format an error for human-readable stderr output.
57
+ */
58
+ export function formatError(err) {
59
+ if (err instanceof AgentpackError) {
60
+ let msg = `Error: ${err.message}`;
61
+ if (err.suggestion) {
62
+ msg += `\n\nSuggestion: ${err.suggestion}`;
63
+ }
64
+ return msg;
65
+ }
66
+ return `Error: ${err.message || err}`;
67
+ }
@@ -0,0 +1,61 @@
1
+ import { stdout, stderr } from 'node:process';
2
+
3
+ /**
4
+ * TTY detection: humans get formatted output, agents get JSON.
5
+ * --json flag overrides TTY detection (always JSON).
6
+ * --quiet suppresses non-essential stderr.
7
+ */
8
+
9
+ const isTTY = stdout.isTTY === true;
10
+ const supportsColor = isTTY && !process.env.NO_COLOR;
11
+
12
+ export const output = {
13
+ /**
14
+ * Write primary results to stdout.
15
+ */
16
+ write(text) {
17
+ stdout.write(text + '\n');
18
+ },
19
+
20
+ /**
21
+ * Write JSON to stdout. Used when --json flag is set or piping.
22
+ */
23
+ json(data) {
24
+ stdout.write(JSON.stringify(data, null, 2) + '\n');
25
+ },
26
+
27
+ /**
28
+ * Write status/progress to stderr (visible to humans, invisible to pipes).
29
+ */
30
+ status(text) {
31
+ stderr.write(text + '\n');
32
+ },
33
+
34
+ /**
35
+ * Write error to stderr.
36
+ */
37
+ error(text) {
38
+ stderr.write(text + '\n');
39
+ },
40
+
41
+ /**
42
+ * Write a table to stdout for human-readable output.
43
+ */
44
+ table(headers, rows) {
45
+ const widths = headers.map((h, i) =>
46
+ Math.max(h.length, ...rows.map((r) => String(r[i] || '').length))
47
+ );
48
+
49
+ const pad = (str, width) => String(str).padEnd(width);
50
+ const sep = widths.map((w) => '-'.repeat(w)).join(' ');
51
+
52
+ stdout.write(headers.map((h, i) => pad(h, widths[i])).join(' ') + '\n');
53
+ stdout.write(sep + '\n');
54
+ for (const row of rows) {
55
+ stdout.write(row.map((c, i) => pad(c || '', widths[i])).join(' ') + '\n');
56
+ }
57
+ },
58
+
59
+ isTTY,
60
+ supportsColor,
61
+ };