@outfitter/contracts 0.4.1 → 0.5.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 (100) hide show
  1. package/README.md +18 -15
  2. package/dist/actions.d.ts +8 -3
  3. package/dist/actions.js +25 -6
  4. package/dist/assert/index.d.ts +7 -3
  5. package/dist/assert/index.js +59 -6
  6. package/dist/capabilities.js +57 -8
  7. package/dist/context.d.ts +8 -3
  8. package/dist/context.js +1 -1
  9. package/dist/envelope.d.ts +6 -2
  10. package/dist/envelope.js +49 -7
  11. package/dist/errors.d.ts +6 -2
  12. package/dist/errors.js +7 -1
  13. package/dist/from-fetch.d.ts +7 -0
  14. package/dist/from-fetch.js +110 -0
  15. package/dist/handler.d.ts +7 -2
  16. package/dist/hints.d.ts +2 -0
  17. package/dist/index.d.ts +25 -14
  18. package/dist/index.js +17 -153
  19. package/dist/internal/error-base.d.ts +2 -0
  20. package/dist/internal/error-base.js +31 -0
  21. package/dist/internal/error-operational.d.ts +3 -0
  22. package/dist/internal/error-operational.js +125 -0
  23. package/dist/internal/error-serialization.d.ts +7 -0
  24. package/dist/{shared/@outfitter/contracts-3wj7xghe.js → internal/error-serialization.js} +28 -67
  25. package/dist/internal/error-taxonomy.d.ts +2 -0
  26. package/dist/internal/error-taxonomy.js +21 -0
  27. package/dist/internal/error-validation.d.ts +3 -0
  28. package/dist/internal/error-validation.js +121 -0
  29. package/dist/internal/safe-json.d.ts +7 -0
  30. package/dist/internal/safe-json.js +66 -0
  31. package/dist/internal/schema-converters.d.ts +26 -0
  32. package/dist/internal/schema-converters.js +12 -0
  33. package/dist/internal/schema-primitives.d.ts +10 -0
  34. package/dist/internal/schema-primitives.js +9 -0
  35. package/dist/internal/schema-types.d.ts +2 -0
  36. package/dist/internal/schema-types.js +9 -0
  37. package/dist/logging.js +11 -3
  38. package/dist/recovery.d.ts +6 -2
  39. package/dist/recovery.js +49 -6
  40. package/dist/resilience.d.ts +6 -2
  41. package/dist/resilience.js +80 -4
  42. package/dist/result/index.js +1 -16
  43. package/dist/result/utilities.js +29 -7
  44. package/dist/schema.d.ts +2 -1
  45. package/dist/schema.js +165 -2
  46. package/dist/serialization.d.ts +8 -2
  47. package/dist/serialization.js +1 -3
  48. package/dist/shared/@outfitter/{contracts-k71jqd1m.d.ts → contracts-10p5q75w.d.ts} +1 -1
  49. package/dist/shared/@outfitter/contracts-1zzcpfyg.d.ts +40 -0
  50. package/dist/shared/@outfitter/contracts-3f5k5tg5.d.ts +28 -0
  51. package/dist/shared/@outfitter/contracts-3qmyq81n.d.ts +78 -0
  52. package/dist/shared/@outfitter/contracts-3re9d4bp.js +114 -0
  53. package/dist/shared/@outfitter/contracts-735ecmbq.d.ts +107 -0
  54. package/dist/shared/@outfitter/contracts-7a0xmwbg.d.ts +11 -0
  55. package/dist/shared/@outfitter/contracts-8cmkh2db.d.ts +31 -0
  56. package/dist/shared/@outfitter/{contracts-agmt8915.js → contracts-c3qfce25.js} +3 -0
  57. package/dist/shared/@outfitter/{contracts-1waabxbk.d.ts → contracts-drwd9ywk.d.ts} +4 -1
  58. package/dist/shared/@outfitter/{contracts-0snpmkdt.js → contracts-hgh47193.js} +10 -4
  59. package/dist/shared/@outfitter/contracts-hrepwwne.js +62 -0
  60. package/dist/shared/@outfitter/contracts-jtn6b927.js +18 -0
  61. package/dist/shared/@outfitter/contracts-jtt6dnmg.js +2 -0
  62. package/dist/shared/@outfitter/contracts-jyhqr766.js +25 -0
  63. package/dist/shared/@outfitter/contracts-mehpmvwp.d.ts +164 -0
  64. package/dist/shared/@outfitter/contracts-msxdg52h.d.ts +125 -0
  65. package/dist/shared/@outfitter/{contracts-95cc3y06.d.ts → contracts-mt027fqj.d.ts} +2 -1
  66. package/dist/shared/@outfitter/contracts-njb2art4.d.ts +174 -0
  67. package/dist/shared/@outfitter/contracts-p77yjs4g.d.ts +46 -0
  68. package/dist/shared/@outfitter/contracts-qpbv29bg.d.ts +59 -0
  69. package/dist/shared/@outfitter/contracts-sawwfgb5.js +111 -0
  70. package/dist/shared/@outfitter/{contracts-e4m948m7.d.ts → contracts-t4txv24h.d.ts} +2 -1
  71. package/dist/shared/@outfitter/contracts-vbgt9rfn.d.ts +74 -0
  72. package/dist/shared/@outfitter/{contracts-56pcsavx.d.ts → contracts-vhajx4gg.d.ts} +8 -2
  73. package/dist/shared/@outfitter/contracts-vhr2ep6b.js +3 -0
  74. package/dist/shared/@outfitter/contracts-w7nvcwrp.d.ts +44 -0
  75. package/dist/shared/@outfitter/contracts-x0ppyt7e.d.ts +76 -0
  76. package/dist/shared/@outfitter/{contracts-0akf2sm6.d.ts → contracts-zma4mscd.d.ts} +16 -1
  77. package/dist/shared/@outfitter/contracts-zsgxsa91.d.ts +84 -0
  78. package/dist/stream.d.ts +2 -0
  79. package/dist/stream.js +1 -0
  80. package/dist/validation.d.ts +7 -3
  81. package/dist/validation.js +6 -2
  82. package/dist/wrap-error.d.ts +7 -0
  83. package/dist/wrap-error.js +71 -0
  84. package/package.json +44 -20
  85. package/dist/shared/@outfitter/contracts-31penhwa.d.ts +0 -81
  86. package/dist/shared/@outfitter/contracts-3gswmhb1.d.ts +0 -446
  87. package/dist/shared/@outfitter/contracts-4zaj7ejb.js +0 -52
  88. package/dist/shared/@outfitter/contracts-85nd53s9.js +0 -53
  89. package/dist/shared/@outfitter/contracts-9wtm5nsw.d.ts +0 -42
  90. package/dist/shared/@outfitter/contracts-cp5c6dws.js +0 -32
  91. package/dist/shared/@outfitter/contracts-d0tq2adf.js +0 -60
  92. package/dist/shared/@outfitter/contracts-mmg0npfk.d.ts +0 -30
  93. package/dist/shared/@outfitter/contracts-phjhz5q3.js +0 -293
  94. package/dist/shared/@outfitter/contracts-q0v44kef.js +0 -28
  95. package/dist/shared/@outfitter/contracts-r21yet6j.js +0 -80
  96. package/dist/shared/@outfitter/contracts-sm6vak1a.js +0 -14
  97. package/dist/shared/@outfitter/contracts-t79engf9.d.ts +0 -60
  98. package/dist/shared/@outfitter/contracts-wfht4q2b.js +0 -341
  99. package/dist/shared/@outfitter/contracts-zx72gyh1.js +0 -32
  100. /package/dist/{shared/@outfitter/contracts-37gpc56f.js → hints.js} +0 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Transport-agnostic streaming types for handler progress reporting.
3
+ *
4
+ * {@link StreamEvent} is a discriminated union of events that handlers emit
5
+ * via {@link ProgressCallback} to report progress. Transport adapters (CLI NDJSON,
6
+ * MCP notifications) consume these events without the handler knowing the transport.
7
+ *
8
+ * - {@link StreamStartEvent} — Emitted once at the beginning of a streaming operation
9
+ * - {@link StreamStepEvent} — Emitted when a named phase completes
10
+ * - {@link StreamProgressEvent} — Emitted for incremental progress updates
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+ /**
15
+ * Emitted once at the beginning of a streaming operation.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * ctx.progress?.({
20
+ * type: "start",
21
+ * command: "check tsdoc",
22
+ * ts: new Date().toISOString(),
23
+ * });
24
+ * ```
25
+ */
26
+ interface StreamStartEvent {
27
+ /** Discriminator — always `"start"`. */
28
+ type: "start";
29
+ /** The command or operation being executed. */
30
+ command: string;
31
+ /** ISO-8601 timestamp of when the operation started. */
32
+ ts: string;
33
+ }
34
+ /**
35
+ * Emitted when a named phase or step completes.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * ctx.progress?.({
40
+ * type: "step",
41
+ * name: "scanning files",
42
+ * status: "complete",
43
+ * duration_ms: 42,
44
+ * });
45
+ * ```
46
+ */
47
+ interface StreamStepEvent {
48
+ /** Discriminator — always `"step"`. */
49
+ type: "step";
50
+ /** Name of the phase or step. */
51
+ name: string;
52
+ /**
53
+ * Status of the step.
54
+ *
55
+ * Common values are `"running"`, `"complete"`, and `"failed"`.
56
+ * Custom values are still allowed for forward compatibility.
57
+ */
58
+ status: "running" | "complete" | "failed" | (string & {});
59
+ /** Optional duration of the step in milliseconds. */
60
+ duration_ms?: number;
61
+ }
62
+ /**
63
+ * Emitted for incremental progress updates (e.g., processing N of M items).
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * ctx.progress?.({
68
+ * type: "progress",
69
+ * current: 5,
70
+ * total: 10,
71
+ * message: "Processing file 5 of 10",
72
+ * });
73
+ * ```
74
+ */
75
+ interface StreamProgressEvent {
76
+ /** Discriminator — always `"progress"`. */
77
+ type: "progress";
78
+ /** Current progress count. */
79
+ current: number;
80
+ /** Total expected count. */
81
+ total: number;
82
+ /** Optional human-readable progress message. */
83
+ message?: string;
84
+ }
85
+ /**
86
+ * Discriminated union of all stream event types.
87
+ *
88
+ * Handlers emit these events via `ctx.progress?.()` to report progress
89
+ * without coupling to any specific transport. The `type` field serves
90
+ * as the discriminator for narrowing.
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * function handleEvent(event: StreamEvent) {
95
+ * switch (event.type) {
96
+ * case "start":
97
+ * console.log(`Starting: ${event.command}`);
98
+ * break;
99
+ * case "step":
100
+ * console.log(`Step: ${event.name} — ${event.status}`);
101
+ * break;
102
+ * case "progress":
103
+ * console.log(`${event.current}/${event.total}`);
104
+ * break;
105
+ * }
106
+ * }
107
+ * ```
108
+ */
109
+ type StreamEvent = StreamStartEvent | StreamStepEvent | StreamProgressEvent;
110
+ /**
111
+ * Callback type for reporting streaming progress events.
112
+ *
113
+ * Transport adapters provide this callback to handlers via `ctx.progress`.
114
+ * When `progress` is `undefined` on {@link HandlerContext}, the handler
115
+ * does not stream — it simply returns its final result.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const progress: ProgressCallback = (event) => {
120
+ * process.stdout.write(JSON.stringify(event) + "\n");
121
+ * };
122
+ * ```
123
+ */
124
+ type ProgressCallback = (event: StreamEvent) => void;
125
+ export { StreamStartEvent, StreamStepEvent, StreamProgressEvent, StreamEvent, ProgressCallback };
@@ -1,4 +1,5 @@
1
- import { OutfitterError, TimeoutError } from "./contracts-3gswmhb1.js";
1
+ import { OutfitterError } from "./contracts-7a0xmwbg.js";
2
+ import { TimeoutError } from "./contracts-735ecmbq.js";
2
3
  import { Result } from "better-result";
3
4
  /**
4
5
  * Options for retry behavior.
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Error taxonomy: categories, code maps, metadata, and lookup functions.
3
+ *
4
+ * @internal
5
+ */
6
+ /**
7
+ * Error categories for classification, exit codes, and HTTP status mapping.
8
+ *
9
+ * Used for:
10
+ * - CLI exit code determination
11
+ * - HTTP status code mapping
12
+ * - Error grouping in logs and metrics
13
+ * - Client retry decisions (transient vs permanent)
14
+ */
15
+ type ErrorCategory = "validation" | "not_found" | "conflict" | "permission" | "timeout" | "rate_limit" | "network" | "internal" | "auth" | "cancelled";
16
+ /**
17
+ * Maps error category to CLI exit code.
18
+ * Non-zero exit indicates error; specific values for script automation.
19
+ */
20
+ declare const exitCodeMap: Record<ErrorCategory, number>;
21
+ /**
22
+ * Maps error category to HTTP status code.
23
+ * Used by MCP servers and API responses.
24
+ */
25
+ declare const statusCodeMap: Record<ErrorCategory, number>;
26
+ /**
27
+ * Maps error category to JSON-RPC 2.0 error code (for MCP protocol compliance).
28
+ *
29
+ * Standard protocol codes (-32600 series) for direct mappings:
30
+ * - validation -> -32602 (Invalid params)
31
+ * - internal -> -32603 (Internal error)
32
+ *
33
+ * Implementation-defined server error codes (-32000 to -32099) for domain categories:
34
+ * - auth -> -32000
35
+ * - timeout -> -32001
36
+ * - conflict -> -32002
37
+ * - permission -> -32003
38
+ * - rate_limit -> -32004
39
+ * - network -> -32005
40
+ * - cancelled -> -32006
41
+ * - not_found -> -32007
42
+ */
43
+ declare const jsonRpcCodeMap: Record<ErrorCategory, number>;
44
+ /**
45
+ * Maps error category to whether the error is safe to retry (for agent safety).
46
+ *
47
+ * Transient errors (timeout, rate_limit, network) are retryable — they may
48
+ * succeed on a subsequent attempt. Permanent errors require human intervention
49
+ * or input correction before retrying would help.
50
+ */
51
+ declare const retryableMap: Record<ErrorCategory, boolean>;
52
+ /**
53
+ * Unified metadata for an error category.
54
+ *
55
+ * Combines exit code, HTTP status, JSON-RPC code, and retryable flag
56
+ * into a single lookup for transport adapters and agent tooling.
57
+ */
58
+ interface ErrorCategoryMeta {
59
+ exitCode: number;
60
+ statusCode: number;
61
+ jsonRpcCode: number;
62
+ retryable: boolean;
63
+ }
64
+ /**
65
+ * Get unified metadata for an error category.
66
+ *
67
+ * Returns exit code, HTTP status code, JSON-RPC error code, and retryable
68
+ * flag in a single object. Useful for transport adapters that need all
69
+ * metadata at once.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const meta = errorCategoryMeta("validation");
74
+ * // { exitCode: 1, statusCode: 400, jsonRpcCode: -32602, retryable: false }
75
+ *
76
+ * const meta = errorCategoryMeta("timeout");
77
+ * // { exitCode: 5, statusCode: 504, jsonRpcCode: -32001, retryable: true }
78
+ * ```
79
+ */
80
+ declare function errorCategoryMeta(category: ErrorCategory): ErrorCategoryMeta;
81
+ /**
82
+ * Numeric error codes for granular error identification.
83
+ *
84
+ * Ranges by category:
85
+ * - validation: 1000-1999
86
+ * - not_found: 2000-2999
87
+ * - conflict: 3000-3999
88
+ * - permission: 4000-4999
89
+ * - timeout: 5000-5999
90
+ * - rate_limit: 6000-6999
91
+ * - network: 7000-7999
92
+ * - internal: 8000-8999
93
+ * - auth: 9000-9999
94
+ * - cancelled: 10000-10999
95
+ */
96
+ declare const ERROR_CODES: {
97
+ readonly validation: {
98
+ readonly FIELD_REQUIRED: 1001;
99
+ readonly INVALID_FORMAT: 1002;
100
+ readonly OUT_OF_RANGE: 1003;
101
+ readonly TYPE_MISMATCH: 1004;
102
+ readonly AMBIGUOUS_MATCH: 1005;
103
+ };
104
+ readonly not_found: {
105
+ readonly RESOURCE_NOT_FOUND: 2001;
106
+ readonly FILE_NOT_FOUND: 2002;
107
+ };
108
+ readonly conflict: {
109
+ readonly ALREADY_EXISTS: 3001;
110
+ readonly VERSION_MISMATCH: 3002;
111
+ };
112
+ readonly permission: {
113
+ readonly FORBIDDEN: 4001;
114
+ readonly INSUFFICIENT_RIGHTS: 4002;
115
+ };
116
+ readonly timeout: {
117
+ readonly OPERATION_TIMEOUT: 5001;
118
+ readonly CONNECTION_TIMEOUT: 5002;
119
+ };
120
+ readonly rate_limit: {
121
+ readonly QUOTA_EXCEEDED: 6001;
122
+ readonly THROTTLED: 6002;
123
+ };
124
+ readonly network: {
125
+ readonly CONNECTION_REFUSED: 7001;
126
+ readonly DNS_FAILED: 7002;
127
+ };
128
+ readonly internal: {
129
+ readonly UNEXPECTED_STATE: 8001;
130
+ readonly ASSERTION_FAILED: 8002;
131
+ };
132
+ readonly auth: {
133
+ readonly INVALID_TOKEN: 9001;
134
+ readonly EXPIRED_TOKEN: 9002;
135
+ };
136
+ readonly cancelled: {
137
+ readonly USER_CANCELLED: 10_001;
138
+ readonly SIGNAL_RECEIVED: 10_002;
139
+ };
140
+ };
141
+ /**
142
+ * Union type of all numeric error codes.
143
+ * Useful for type-safe error code handling.
144
+ */
145
+ type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES][keyof (typeof ERROR_CODES)[keyof typeof ERROR_CODES]];
146
+ /**
147
+ * Serialized error format for JSON transport.
148
+ */
149
+ interface SerializedError {
150
+ _tag: string;
151
+ category: ErrorCategory;
152
+ context?: Record<string, unknown>;
153
+ message: string;
154
+ }
155
+ /**
156
+ * Base interface for OutfitterError properties.
157
+ * All concrete error classes must include these fields.
158
+ *
159
+ * @deprecated Use `OutfitterError` (or concrete error class constructor props) instead. This alias will be removed in v1.0.
160
+ */
161
+ interface KitErrorProps {
162
+ category: ErrorCategory;
163
+ context?: Record<string, unknown>;
164
+ message: string;
165
+ }
166
+ /**
167
+ * Get CLI exit code for an error category.
168
+ */
169
+ declare function getExitCode(category: ErrorCategory): number;
170
+ /**
171
+ * Get HTTP status code for an error category.
172
+ */
173
+ declare function getStatusCode(category: ErrorCategory): number;
174
+ export { ErrorCategory, exitCodeMap, statusCodeMap, jsonRpcCodeMap, retryableMap, ErrorCategoryMeta, errorCategoryMeta, ERROR_CODES, ErrorCode, SerializedError, KitErrorProps, getExitCode, getStatusCode };
@@ -0,0 +1,46 @@
1
+ import { OutfitterError } from "./contracts-7a0xmwbg.js";
2
+ import { SerializedError } from "./contracts-njb2art4.js";
3
+ /**
4
+ * Options for error serialization.
5
+ */
6
+ interface SerializeErrorOptions {
7
+ /** Include stack trace (default: false in production, true otherwise). */
8
+ includeStack?: boolean;
9
+ }
10
+ /**
11
+ * Serialize a OutfitterError to JSON-safe format.
12
+ *
13
+ * Strips stack traces in production, preserves in development.
14
+ * Automatically redacts sensitive values from context.
15
+ *
16
+ * @param error - The error to serialize
17
+ * @param options - Serialization options
18
+ * @param isProduction - Whether the environment is production. When omitted, falls back to
19
+ * `process.env["NODE_ENV"] === "production"` for safe-by-default stack stripping.
20
+ * @returns JSON-safe serialized error
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const serialized = serializeError(new NotFoundError("note", "abc123"));
25
+ * // { _tag: "NotFoundError", category: "not_found", message: "note not found: abc123", context: { resourceType: "note", resourceId: "abc123" } }
26
+ * ```
27
+ */
28
+ declare function serializeError(error: OutfitterError, options?: SerializeErrorOptions, isProduction?: boolean): SerializedError;
29
+ /**
30
+ * Deserialize error from JSON (e.g., from MCP response).
31
+ *
32
+ * Returns a typed OutfitterError subclass based on _tag.
33
+ *
34
+ * @param data - Serialized error data
35
+ * @returns Reconstructed OutfitterError instance
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const error = deserializeError(jsonData);
40
+ * if (error._tag === "NotFoundError") {
41
+ * // TypeScript knows error.resourceType exists
42
+ * }
43
+ * ```
44
+ */
45
+ declare function deserializeError(data: SerializedError): OutfitterError;
46
+ export { SerializeErrorOptions, serializeError, deserializeError };
@@ -0,0 +1,59 @@
1
+ import { TaggedErrorClass } from "better-result";
2
+ declare const ValidationErrorBase: TaggedErrorClass<"ValidationError", {
3
+ message: string;
4
+ field?: string;
5
+ context?: Record<string, unknown>;
6
+ }>;
7
+ declare const AmbiguousErrorBase: TaggedErrorClass<"AmbiguousError", {
8
+ message: string;
9
+ candidates: string[];
10
+ context?: Record<string, unknown>;
11
+ }>;
12
+ declare const AssertionErrorBase: TaggedErrorClass<"AssertionError", {
13
+ message: string;
14
+ }>;
15
+ declare const NotFoundErrorBase: TaggedErrorClass<"NotFoundError", {
16
+ message: string;
17
+ resourceType: string;
18
+ resourceId: string;
19
+ context?: Record<string, unknown>;
20
+ }>;
21
+ declare const AlreadyExistsErrorBase: TaggedErrorClass<"AlreadyExistsError", {
22
+ message: string;
23
+ resourceType: string;
24
+ resourceId: string;
25
+ context?: Record<string, unknown>;
26
+ }>;
27
+ declare const ConflictErrorBase: TaggedErrorClass<"ConflictError", {
28
+ message: string;
29
+ context?: Record<string, unknown>;
30
+ }>;
31
+ declare const PermissionErrorBase: TaggedErrorClass<"PermissionError", {
32
+ message: string;
33
+ context?: Record<string, unknown>;
34
+ }>;
35
+ declare const TimeoutErrorBase: TaggedErrorClass<"TimeoutError", {
36
+ message: string;
37
+ operation: string;
38
+ timeoutMs: number;
39
+ }>;
40
+ declare const RateLimitErrorBase: TaggedErrorClass<"RateLimitError", {
41
+ message: string;
42
+ retryAfterSeconds?: number;
43
+ }>;
44
+ declare const NetworkErrorBase: TaggedErrorClass<"NetworkError", {
45
+ message: string;
46
+ context?: Record<string, unknown>;
47
+ }>;
48
+ declare const InternalErrorBase: TaggedErrorClass<"InternalError", {
49
+ message: string;
50
+ context?: Record<string, unknown>;
51
+ }>;
52
+ declare const AuthErrorBase: TaggedErrorClass<"AuthError", {
53
+ message: string;
54
+ reason?: "missing" | "invalid" | "expired";
55
+ }>;
56
+ declare const CancelledErrorBase: TaggedErrorClass<"CancelledError", {
57
+ message: string;
58
+ }>;
59
+ export { ValidationErrorBase, AmbiguousErrorBase, AssertionErrorBase, NotFoundErrorBase, AlreadyExistsErrorBase, ConflictErrorBase, PermissionErrorBase, TimeoutErrorBase, RateLimitErrorBase, NetworkErrorBase, InternalErrorBase, AuthErrorBase, CancelledErrorBase };
@@ -0,0 +1,111 @@
1
+ // @bun
2
+ // packages/contracts/src/internal/error-taxonomy.ts
3
+ var exitCodeMap = {
4
+ validation: 1,
5
+ not_found: 2,
6
+ conflict: 3,
7
+ permission: 4,
8
+ timeout: 5,
9
+ rate_limit: 6,
10
+ network: 7,
11
+ internal: 8,
12
+ auth: 9,
13
+ cancelled: 130
14
+ };
15
+ var statusCodeMap = {
16
+ validation: 400,
17
+ not_found: 404,
18
+ conflict: 409,
19
+ permission: 403,
20
+ timeout: 504,
21
+ rate_limit: 429,
22
+ network: 502,
23
+ internal: 500,
24
+ auth: 401,
25
+ cancelled: 499
26
+ };
27
+ var jsonRpcCodeMap = {
28
+ validation: -32602,
29
+ not_found: -32007,
30
+ internal: -32603,
31
+ auth: -32000,
32
+ timeout: -32001,
33
+ conflict: -32002,
34
+ permission: -32003,
35
+ rate_limit: -32004,
36
+ network: -32005,
37
+ cancelled: -32006
38
+ };
39
+ var retryableMap = {
40
+ validation: false,
41
+ not_found: false,
42
+ conflict: false,
43
+ permission: false,
44
+ timeout: true,
45
+ rate_limit: true,
46
+ network: true,
47
+ internal: false,
48
+ auth: false,
49
+ cancelled: false
50
+ };
51
+ function errorCategoryMeta(category) {
52
+ return {
53
+ exitCode: exitCodeMap[category],
54
+ statusCode: statusCodeMap[category],
55
+ jsonRpcCode: jsonRpcCodeMap[category],
56
+ retryable: retryableMap[category]
57
+ };
58
+ }
59
+ var ERROR_CODES = {
60
+ validation: {
61
+ FIELD_REQUIRED: 1001,
62
+ INVALID_FORMAT: 1002,
63
+ OUT_OF_RANGE: 1003,
64
+ TYPE_MISMATCH: 1004,
65
+ AMBIGUOUS_MATCH: 1005
66
+ },
67
+ not_found: {
68
+ RESOURCE_NOT_FOUND: 2001,
69
+ FILE_NOT_FOUND: 2002
70
+ },
71
+ conflict: {
72
+ ALREADY_EXISTS: 3001,
73
+ VERSION_MISMATCH: 3002
74
+ },
75
+ permission: {
76
+ FORBIDDEN: 4001,
77
+ INSUFFICIENT_RIGHTS: 4002
78
+ },
79
+ timeout: {
80
+ OPERATION_TIMEOUT: 5001,
81
+ CONNECTION_TIMEOUT: 5002
82
+ },
83
+ rate_limit: {
84
+ QUOTA_EXCEEDED: 6001,
85
+ THROTTLED: 6002
86
+ },
87
+ network: {
88
+ CONNECTION_REFUSED: 7001,
89
+ DNS_FAILED: 7002
90
+ },
91
+ internal: {
92
+ UNEXPECTED_STATE: 8001,
93
+ ASSERTION_FAILED: 8002
94
+ },
95
+ auth: {
96
+ INVALID_TOKEN: 9001,
97
+ EXPIRED_TOKEN: 9002
98
+ },
99
+ cancelled: {
100
+ USER_CANCELLED: 10001,
101
+ SIGNAL_RECEIVED: 10002
102
+ }
103
+ };
104
+ function getExitCode(category) {
105
+ return exitCodeMap[category];
106
+ }
107
+ function getStatusCode(category) {
108
+ return statusCodeMap[category];
109
+ }
110
+
111
+ export { exitCodeMap, statusCodeMap, jsonRpcCodeMap, retryableMap, errorCategoryMeta, ERROR_CODES, getExitCode, getStatusCode };
@@ -1,4 +1,5 @@
1
- import { OutfitterError, SerializedError } from "./contracts-3gswmhb1.js";
1
+ import { OutfitterError } from "./contracts-7a0xmwbg.js";
2
+ import { SerializedError } from "./contracts-njb2art4.js";
2
3
  import { Result } from "better-result";
3
4
  /**
4
5
  * Metadata attached to every response envelope.
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Hint types for agent-navigable responses.
3
+ *
4
+ * Hints are transport-local suggestions attached to command/tool responses.
5
+ * They guide agents (and humans) toward next actions without coupling
6
+ * handler logic to any specific transport.
7
+ *
8
+ * - {@link ActionHint} — Base hint with description and optional params
9
+ * - {@link CLIHint} — CLI-specific hint with a runnable command
10
+ * - {@link MCPHint} — MCP-specific hint with tool name and optional input
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+ /**
15
+ * Base hint type for action responses.
16
+ *
17
+ * Describes a suggested next action with optional structured parameters.
18
+ * Transport-specific hints ({@link CLIHint}, {@link MCPHint}) extend this
19
+ * with transport-appropriate fields.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const hint: ActionHint = {
24
+ * description: "Retry the operation with a longer timeout",
25
+ * params: { timeoutMs: 10_000 },
26
+ * };
27
+ * ```
28
+ */
29
+ interface ActionHint {
30
+ /** Human-readable description of the suggested action. */
31
+ readonly description: string;
32
+ /** Optional structured parameters for the suggested action. */
33
+ readonly params?: Record<string, unknown>;
34
+ }
35
+ /**
36
+ * CLI-specific hint with a runnable command string.
37
+ *
38
+ * Extends {@link ActionHint} with a `command` field that agents or users
39
+ * can execute directly in the terminal.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const hint: CLIHint = {
44
+ * description: "Fix lint issues automatically",
45
+ * command: "outfitter lint --fix",
46
+ * };
47
+ * ```
48
+ */
49
+ interface CLIHint extends ActionHint {
50
+ /** CLI command string that can be executed to perform the suggested action. */
51
+ readonly command: string;
52
+ }
53
+ /**
54
+ * MCP-specific hint with a tool name and optional input.
55
+ *
56
+ * Extends {@link ActionHint} with a `tool` field identifying the MCP tool
57
+ * to invoke, and an optional `input` payload for that tool.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const hint: MCPHint = {
62
+ * description: "Search for related notes",
63
+ * tool: "search-notes",
64
+ * input: { query: "architecture patterns", limit: 5 },
65
+ * };
66
+ * ```
67
+ */
68
+ interface MCPHint extends ActionHint {
69
+ /** MCP tool name to invoke for the suggested action. */
70
+ readonly tool: string;
71
+ /** Optional input payload for the MCP tool. */
72
+ readonly input?: unknown;
73
+ }
74
+ export { ActionHint, CLIHint, MCPHint };
@@ -1,5 +1,5 @@
1
- import { Handler, SyncHandler } from "./contracts-0akf2sm6.js";
2
- import { OutfitterError } from "./contracts-3gswmhb1.js";
1
+ import { Handler, SyncHandler } from "./contracts-zma4mscd.js";
2
+ import { OutfitterError } from "./contracts-7a0xmwbg.js";
3
3
  import { z } from "zod";
4
4
  declare const ACTION_SURFACES: readonly ["cli", "mcp", "api", "server"];
5
5
  type ActionSurface = (typeof ACTION_SURFACES)[number];
@@ -25,7 +25,13 @@ interface ActionCliSpec<TInput = unknown> {
25
25
  interface ActionMcpSpec<TInput = unknown> {
26
26
  readonly deferLoading?: boolean;
27
27
  readonly description?: string;
28
+ /** When true, the action modifies or deletes data */
29
+ readonly destructive?: boolean;
30
+ /** When true, calling the action multiple times with the same input has the same effect */
31
+ readonly idempotent?: boolean;
28
32
  readonly mapInput?: (input: unknown) => TInput;
33
+ /** When true, the action does not modify any state */
34
+ readonly readOnly?: boolean;
29
35
  readonly tool?: string;
30
36
  }
31
37
  type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
@@ -0,0 +1,3 @@
1
+ export { ERROR_CODES, errorCategoryMeta, exitCodeMap, getExitCode, getStatusCode, jsonRpcCodeMap, retryableMap, statusCodeMap } from "../../internal/error-taxonomy.js";
2
+ export { AlreadyExistsError, AmbiguousError, AssertionError, ConflictError, NotFoundError, ValidationError } from "../../internal/error-validation.js";
3
+ export { AuthError, CancelledError, InternalError, NetworkError, PermissionError, RateLimitError, TimeoutError } from "../../internal/error-operational.js";
@@ -0,0 +1,44 @@
1
+ /**
2
+ * JSON Schema type definitions and Zod introspection helpers.
3
+ *
4
+ * @internal
5
+ */
6
+ /**
7
+ * JSON Schema representation.
8
+ */
9
+ interface JsonSchema {
10
+ $defs?: Record<string, JsonSchema>;
11
+ $ref?: string;
12
+ $schema?: string;
13
+ additionalProperties?: boolean | JsonSchema;
14
+ allOf?: JsonSchema[];
15
+ anyOf?: JsonSchema[];
16
+ const?: unknown;
17
+ default?: unknown;
18
+ definitions?: Record<string, JsonSchema>;
19
+ description?: string;
20
+ enum?: unknown[];
21
+ exclusiveMaximum?: number;
22
+ exclusiveMinimum?: number;
23
+ format?: string;
24
+ items?: JsonSchema | JsonSchema[];
25
+ maximum?: number;
26
+ maxLength?: number;
27
+ minimum?: number;
28
+ minLength?: number;
29
+ not?: JsonSchema | Record<string, never>;
30
+ oneOf?: JsonSchema[];
31
+ pattern?: string;
32
+ properties?: Record<string, JsonSchema>;
33
+ required?: string[];
34
+ type?: string;
35
+ }
36
+ /**
37
+ * Extract the internal _def object from a Zod schema or def.
38
+ */
39
+ declare function getDef(schemaOrDef: any): any;
40
+ /**
41
+ * Extract description from a Zod schema or its def.
42
+ */
43
+ declare function getDescription(schema: any, def: any): string | undefined;
44
+ export { JsonSchema, getDef, getDescription };