@kelpi/mcp 0.1.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 (195) hide show
  1. package/README.md +312 -0
  2. package/bin/kelpi-mcp +3 -0
  3. package/dist/__tests__/integration-api/fixtures.d.ts +382 -0
  4. package/dist/__tests__/integration-api/fixtures.d.ts.map +1 -0
  5. package/dist/__tests__/integration-api/fixtures.js +478 -0
  6. package/dist/__tests__/integration-api/fixtures.js.map +1 -0
  7. package/dist/__tests__/integration-api/index.d.ts +19 -0
  8. package/dist/__tests__/integration-api/index.d.ts.map +1 -0
  9. package/dist/__tests__/integration-api/index.js +33 -0
  10. package/dist/__tests__/integration-api/index.js.map +1 -0
  11. package/dist/__tests__/integration-api/setup.d.ts +176 -0
  12. package/dist/__tests__/integration-api/setup.d.ts.map +1 -0
  13. package/dist/__tests__/integration-api/setup.js +329 -0
  14. package/dist/__tests__/integration-api/setup.js.map +1 -0
  15. package/dist/__tests__/setup.d.ts +2 -0
  16. package/dist/__tests__/setup.d.ts.map +1 -0
  17. package/dist/__tests__/setup.js +11 -0
  18. package/dist/__tests__/setup.js.map +1 -0
  19. package/dist/__tests__/unit/test-utils.d.ts +46 -0
  20. package/dist/__tests__/unit/test-utils.d.ts.map +1 -0
  21. package/dist/__tests__/unit/test-utils.js +50 -0
  22. package/dist/__tests__/unit/test-utils.js.map +1 -0
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +34 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/lib/api-client.d.ts +17 -0
  28. package/dist/lib/api-client.d.ts.map +1 -0
  29. package/dist/lib/api-client.js +169 -0
  30. package/dist/lib/api-client.js.map +1 -0
  31. package/dist/lib/auth-state.d.ts +54 -0
  32. package/dist/lib/auth-state.d.ts.map +1 -0
  33. package/dist/lib/auth-state.js +131 -0
  34. package/dist/lib/auth-state.js.map +1 -0
  35. package/dist/lib/config.d.ts +39 -0
  36. package/dist/lib/config.d.ts.map +1 -0
  37. package/dist/lib/config.js +170 -0
  38. package/dist/lib/config.js.map +1 -0
  39. package/dist/lib/error-formatter.d.ts +40 -0
  40. package/dist/lib/error-formatter.d.ts.map +1 -0
  41. package/dist/lib/error-formatter.js +149 -0
  42. package/dist/lib/error-formatter.js.map +1 -0
  43. package/dist/lib/errors.d.ts +44 -0
  44. package/dist/lib/errors.d.ts.map +1 -0
  45. package/dist/lib/errors.js +56 -0
  46. package/dist/lib/errors.js.map +1 -0
  47. package/dist/lib/tool-helpers.d.ts +49 -0
  48. package/dist/lib/tool-helpers.d.ts.map +1 -0
  49. package/dist/lib/tool-helpers.js +101 -0
  50. package/dist/lib/tool-helpers.js.map +1 -0
  51. package/dist/lib/tool-registry.d.ts +111 -0
  52. package/dist/lib/tool-registry.d.ts.map +1 -0
  53. package/dist/lib/tool-registry.js +112 -0
  54. package/dist/lib/tool-registry.js.map +1 -0
  55. package/dist/lib/version.d.ts +13 -0
  56. package/dist/lib/version.d.ts.map +1 -0
  57. package/dist/lib/version.js +13 -0
  58. package/dist/lib/version.js.map +1 -0
  59. package/dist/prompts/flow-generator.d.ts +45 -0
  60. package/dist/prompts/flow-generator.d.ts.map +1 -0
  61. package/dist/prompts/flow-generator.js +177 -0
  62. package/dist/prompts/flow-generator.js.map +1 -0
  63. package/dist/prompts/index.d.ts +7 -0
  64. package/dist/prompts/index.d.ts.map +1 -0
  65. package/dist/prompts/index.js +7 -0
  66. package/dist/prompts/index.js.map +1 -0
  67. package/dist/server.d.ts +66 -0
  68. package/dist/server.d.ts.map +1 -0
  69. package/dist/server.js +140 -0
  70. package/dist/server.js.map +1 -0
  71. package/dist/tools/auth/index.d.ts +18 -0
  72. package/dist/tools/auth/index.d.ts.map +1 -0
  73. package/dist/tools/auth/index.js +50 -0
  74. package/dist/tools/auth/index.js.map +1 -0
  75. package/dist/tools/auth/login.d.ts +37 -0
  76. package/dist/tools/auth/login.d.ts.map +1 -0
  77. package/dist/tools/auth/login.js +257 -0
  78. package/dist/tools/auth/login.js.map +1 -0
  79. package/dist/tools/auth/schemas.d.ts +69 -0
  80. package/dist/tools/auth/schemas.d.ts.map +1 -0
  81. package/dist/tools/auth/schemas.js +36 -0
  82. package/dist/tools/auth/schemas.js.map +1 -0
  83. package/dist/tools/auth/status.d.ts +11 -0
  84. package/dist/tools/auth/status.d.ts.map +1 -0
  85. package/dist/tools/auth/status.js +50 -0
  86. package/dist/tools/auth/status.js.map +1 -0
  87. package/dist/tools/contacts/create.d.ts +11 -0
  88. package/dist/tools/contacts/create.d.ts.map +1 -0
  89. package/dist/tools/contacts/create.js +47 -0
  90. package/dist/tools/contacts/create.js.map +1 -0
  91. package/dist/tools/contacts/index.d.ts +10 -0
  92. package/dist/tools/contacts/index.d.ts.map +1 -0
  93. package/dist/tools/contacts/index.js +40 -0
  94. package/dist/tools/contacts/index.js.map +1 -0
  95. package/dist/tools/contacts/schemas.d.ts +37 -0
  96. package/dist/tools/contacts/schemas.d.ts.map +1 -0
  97. package/dist/tools/contacts/schemas.js +15 -0
  98. package/dist/tools/contacts/schemas.js.map +1 -0
  99. package/dist/tools/events/index.d.ts +10 -0
  100. package/dist/tools/events/index.d.ts.map +1 -0
  101. package/dist/tools/events/index.js +42 -0
  102. package/dist/tools/events/index.js.map +1 -0
  103. package/dist/tools/events/schemas.d.ts +37 -0
  104. package/dist/tools/events/schemas.d.ts.map +1 -0
  105. package/dist/tools/events/schemas.js +17 -0
  106. package/dist/tools/events/schemas.js.map +1 -0
  107. package/dist/tools/events/track.d.ts +11 -0
  108. package/dist/tools/events/track.d.ts.map +1 -0
  109. package/dist/tools/events/track.js +41 -0
  110. package/dist/tools/events/track.js.map +1 -0
  111. package/dist/tools/flows/activate.d.ts +11 -0
  112. package/dist/tools/flows/activate.d.ts.map +1 -0
  113. package/dist/tools/flows/activate.js +46 -0
  114. package/dist/tools/flows/activate.js.map +1 -0
  115. package/dist/tools/flows/create.d.ts +11 -0
  116. package/dist/tools/flows/create.d.ts.map +1 -0
  117. package/dist/tools/flows/create.js +72 -0
  118. package/dist/tools/flows/create.js.map +1 -0
  119. package/dist/tools/flows/index.d.ts +24 -0
  120. package/dist/tools/flows/index.d.ts.map +1 -0
  121. package/dist/tools/flows/index.js +183 -0
  122. package/dist/tools/flows/index.js.map +1 -0
  123. package/dist/tools/flows/list.d.ts +11 -0
  124. package/dist/tools/flows/list.d.ts.map +1 -0
  125. package/dist/tools/flows/list.js +34 -0
  126. package/dist/tools/flows/list.js.map +1 -0
  127. package/dist/tools/flows/schemas.d.ts +621 -0
  128. package/dist/tools/flows/schemas.d.ts.map +1 -0
  129. package/dist/tools/flows/schemas.js +135 -0
  130. package/dist/tools/flows/schemas.js.map +1 -0
  131. package/dist/tools/flows/transform.d.ts +39 -0
  132. package/dist/tools/flows/transform.d.ts.map +1 -0
  133. package/dist/tools/flows/transform.js +139 -0
  134. package/dist/tools/flows/transform.js.map +1 -0
  135. package/dist/tools/index.d.ts +34 -0
  136. package/dist/tools/index.d.ts.map +1 -0
  137. package/dist/tools/index.js +46 -0
  138. package/dist/tools/index.js.map +1 -0
  139. package/dist/tools/sdk/index.d.ts +18 -0
  140. package/dist/tools/sdk/index.d.ts.map +1 -0
  141. package/dist/tools/sdk/index.js +69 -0
  142. package/dist/tools/sdk/index.js.map +1 -0
  143. package/dist/tools/sdk/public-key.d.ts +11 -0
  144. package/dist/tools/sdk/public-key.d.ts.map +1 -0
  145. package/dist/tools/sdk/public-key.js +24 -0
  146. package/dist/tools/sdk/public-key.js.map +1 -0
  147. package/dist/tools/sdk/schemas.d.ts +48 -0
  148. package/dist/tools/sdk/schemas.d.ts.map +1 -0
  149. package/dist/tools/sdk/schemas.js +35 -0
  150. package/dist/tools/sdk/schemas.js.map +1 -0
  151. package/dist/tools/sdk/snippet.d.ts +11 -0
  152. package/dist/tools/sdk/snippet.d.ts.map +1 -0
  153. package/dist/tools/sdk/snippet.js +50 -0
  154. package/dist/tools/sdk/snippet.js.map +1 -0
  155. package/dist/tools/sdk/templates/index.d.ts +5 -0
  156. package/dist/tools/sdk/templates/index.d.ts.map +1 -0
  157. package/dist/tools/sdk/templates/index.js +5 -0
  158. package/dist/tools/sdk/templates/index.js.map +1 -0
  159. package/dist/tools/sdk/templates/nextjs.d.ts +5 -0
  160. package/dist/tools/sdk/templates/nextjs.d.ts.map +1 -0
  161. package/dist/tools/sdk/templates/nextjs.js +71 -0
  162. package/dist/tools/sdk/templates/nextjs.js.map +1 -0
  163. package/dist/tools/sdk/templates/node.d.ts +9 -0
  164. package/dist/tools/sdk/templates/node.d.ts.map +1 -0
  165. package/dist/tools/sdk/templates/node.js +170 -0
  166. package/dist/tools/sdk/templates/node.js.map +1 -0
  167. package/dist/tools/sdk/templates/react.d.ts +5 -0
  168. package/dist/tools/sdk/templates/react.d.ts.map +1 -0
  169. package/dist/tools/sdk/templates/react.js +54 -0
  170. package/dist/tools/sdk/templates/react.js.map +1 -0
  171. package/dist/tools/sdk/templates/vanilla.d.ts +5 -0
  172. package/dist/tools/sdk/templates/vanilla.d.ts.map +1 -0
  173. package/dist/tools/sdk/templates/vanilla.js +61 -0
  174. package/dist/tools/sdk/templates/vanilla.js.map +1 -0
  175. package/dist/tools/templates/create.d.ts +11 -0
  176. package/dist/tools/templates/create.d.ts.map +1 -0
  177. package/dist/tools/templates/create.js +39 -0
  178. package/dist/tools/templates/create.js.map +1 -0
  179. package/dist/tools/templates/index.d.ts +17 -0
  180. package/dist/tools/templates/index.d.ts.map +1 -0
  181. package/dist/tools/templates/index.js +68 -0
  182. package/dist/tools/templates/index.js.map +1 -0
  183. package/dist/tools/templates/list.d.ts +11 -0
  184. package/dist/tools/templates/list.d.ts.map +1 -0
  185. package/dist/tools/templates/list.js +31 -0
  186. package/dist/tools/templates/list.js.map +1 -0
  187. package/dist/tools/templates/schemas.d.ts +90 -0
  188. package/dist/tools/templates/schemas.d.ts.map +1 -0
  189. package/dist/tools/templates/schemas.js +37 -0
  190. package/dist/tools/templates/schemas.js.map +1 -0
  191. package/dist/types.d.ts +55 -0
  192. package/dist/types.d.ts.map +1 -0
  193. package/dist/types.js +2 -0
  194. package/dist/types.js.map +1 -0
  195. package/package.json +76 -0
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ import { KelpiMcpServer } from './server.js';
3
+ /**
4
+ * Main entry point for the Kelpi MCP Server
5
+ *
6
+ * This starts the MCP server with stdio transport, making it available
7
+ * for use by AI assistants like Claude Desktop, Cursor, etc.
8
+ */
9
+ async function main() {
10
+ const server = new KelpiMcpServer();
11
+ // Handle graceful shutdown
12
+ const shutdown = async () => {
13
+ await server.shutdown();
14
+ process.exit(0);
15
+ };
16
+ process.on('SIGINT', shutdown);
17
+ process.on('SIGTERM', shutdown);
18
+ try {
19
+ await server.start();
20
+ }
21
+ catch (error) {
22
+ console.error('Failed to start Kelpi MCP server:', error);
23
+ process.exit(1);
24
+ }
25
+ }
26
+ main().catch((error) => {
27
+ console.error('Unhandled error:', error);
28
+ process.exit(1);
29
+ });
30
+ // Re-export public API
31
+ export { KelpiMcpServer, createServer } from './server.js';
32
+ export { ToolRegistry, ToolRegistryError } from './lib/tool-registry.js';
33
+ export { ALL_TOOLS, TOOL_DEFINITIONS, TOOL_NAMES, } from './tools/index.js';
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;GAKG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;IAEpC,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAsB,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AASzE,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,UAAU,GAEX,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { ApiClientOptions, ApiResponse } from '../types.js';
2
+ export { ApiError, AuthError, TimeoutError } from './errors.js';
3
+ /**
4
+ * API Client interface
5
+ */
6
+ export interface ApiClient {
7
+ get<T = unknown>(path: string, params?: Record<string, string>): Promise<ApiResponse<T>>;
8
+ post<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
9
+ put<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
10
+ patch<T = unknown>(path: string, body?: unknown): Promise<ApiResponse<T>>;
11
+ delete<T = unknown>(path: string): Promise<ApiResponse<T>>;
12
+ }
13
+ /**
14
+ * Create an API client with authentication and retry logic
15
+ */
16
+ export declare function createApiClient(options: ApiClientOptions): ApiClient;
17
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAC;AAGlF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA6BhE;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5D;AA2DD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAgJpE"}
@@ -0,0 +1,169 @@
1
+ // Re-export error classes from errors.ts for convenience
2
+ export { ApiError, AuthError, TimeoutError } from './errors.js';
3
+ import { ApiError, AuthError, TimeoutError } from './errors.js';
4
+ import { MCP_VERSION } from './version.js';
5
+ /**
6
+ * Default API URL for Kelpi
7
+ */
8
+ const DEFAULT_API_URL = 'https://api.kelpi.ai';
9
+ /**
10
+ * Default timeout in milliseconds (30 seconds)
11
+ */
12
+ const DEFAULT_TIMEOUT = 30000;
13
+ /**
14
+ * Default maximum retries for retryable errors
15
+ */
16
+ const DEFAULT_MAX_RETRIES = 3;
17
+ /**
18
+ * Default retry delay in milliseconds
19
+ */
20
+ const DEFAULT_RETRY_DELAY = 1000;
21
+ /**
22
+ * HTTP status codes that should trigger a retry
23
+ */
24
+ const RETRYABLE_STATUS_CODES = [429, 503];
25
+ /**
26
+ * Sleep helper for retry delay
27
+ */
28
+ function sleep(ms) {
29
+ return new Promise((resolve) => setTimeout(resolve, ms));
30
+ }
31
+ async function parseErrorBody(response) {
32
+ try {
33
+ return (await response.json());
34
+ }
35
+ catch {
36
+ return { error: response.statusText };
37
+ }
38
+ }
39
+ /**
40
+ * Format validation details from Zod's flatten() format into a readable message
41
+ */
42
+ function formatValidationDetails(details) {
43
+ if (!details)
44
+ return '';
45
+ const messages = [];
46
+ // Add form-level errors
47
+ if (details.formErrors?.length) {
48
+ messages.push(...details.formErrors);
49
+ }
50
+ // Add field-level errors
51
+ if (details.fieldErrors) {
52
+ for (const [field, errors] of Object.entries(details.fieldErrors)) {
53
+ for (const error of errors) {
54
+ messages.push(`${field}: ${error}`);
55
+ }
56
+ }
57
+ }
58
+ return messages.join('; ');
59
+ }
60
+ /**
61
+ * Create an API client with authentication and retry logic
62
+ */
63
+ export function createApiClient(options) {
64
+ const { apiKey, apiUrl = DEFAULT_API_URL, timeout = DEFAULT_TIMEOUT, maxRetries = DEFAULT_MAX_RETRIES, retryDelay = DEFAULT_RETRY_DELAY, } = options;
65
+ /**
66
+ * Build the full URL with query parameters
67
+ */
68
+ function buildUrl(path, params) {
69
+ const url = new URL(path, apiUrl);
70
+ if (params) {
71
+ Object.entries(params).forEach(([key, value]) => {
72
+ url.searchParams.set(key, value);
73
+ });
74
+ }
75
+ return url.toString();
76
+ }
77
+ /**
78
+ * Get default headers for all requests
79
+ */
80
+ function getHeaders() {
81
+ return {
82
+ Authorization: `Bearer ${apiKey}`,
83
+ 'Content-Type': 'application/json',
84
+ 'User-Agent': `kelpi-mcp/${MCP_VERSION}`,
85
+ };
86
+ }
87
+ /**
88
+ * Execute a request with timeout, error handling, and retry logic
89
+ */
90
+ async function executeRequest(method, path, body, params, retriesRemaining = maxRetries) {
91
+ const url = buildUrl(path, params);
92
+ const controller = new AbortController();
93
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
94
+ try {
95
+ const response = await fetch(url, {
96
+ method,
97
+ headers: getHeaders(),
98
+ body: body ? JSON.stringify(body) : undefined,
99
+ signal: controller.signal,
100
+ });
101
+ clearTimeout(timeoutId);
102
+ // Handle successful responses
103
+ if (response.ok) {
104
+ // Handle 204 No Content
105
+ if (response.status === 204) {
106
+ return { data: null, status: response.status };
107
+ }
108
+ const data = (await response.json());
109
+ return { data, status: response.status };
110
+ }
111
+ // Handle error responses
112
+ const errorBody = await parseErrorBody(response);
113
+ // Build error message including validation details if present
114
+ let errorMessage = errorBody.error || errorBody.message || 'Request failed';
115
+ if (errorBody.details) {
116
+ const validationDetails = formatValidationDetails(errorBody.details);
117
+ if (validationDetails) {
118
+ errorMessage = `${errorMessage}: ${validationDetails}`;
119
+ }
120
+ }
121
+ // Check if we should retry with exponential backoff
122
+ if (RETRYABLE_STATUS_CODES.includes(response.status) && retriesRemaining > 0) {
123
+ // Calculate exponential backoff with jitter
124
+ const attempt = maxRetries - retriesRemaining + 1;
125
+ const backoffDelay = retryDelay * Math.pow(2, attempt - 1);
126
+ const jitter = Math.random() * 1000;
127
+ await sleep(backoffDelay + jitter);
128
+ return executeRequest(method, path, body, params, retriesRemaining - 1);
129
+ }
130
+ // Handle 401 Unauthorized
131
+ if (response.status === 401) {
132
+ throw new AuthError(errorMessage);
133
+ }
134
+ // Throw ApiError for all other error responses
135
+ throw new ApiError(errorMessage, response.status, errorBody.errors, errorBody.details);
136
+ }
137
+ catch (error) {
138
+ clearTimeout(timeoutId);
139
+ // Re-throw our custom errors
140
+ if (error instanceof ApiError || error instanceof AuthError || error instanceof TimeoutError) {
141
+ throw error;
142
+ }
143
+ // Handle abort (timeout)
144
+ if (error instanceof Error && error.name === 'AbortError') {
145
+ throw new TimeoutError(`Request timed out after ${timeout}ms`, timeout);
146
+ }
147
+ // Handle other fetch errors
148
+ throw new ApiError(error instanceof Error ? error.message : 'Unknown error', 0);
149
+ }
150
+ }
151
+ return {
152
+ async get(path, params) {
153
+ return executeRequest('GET', path, undefined, params);
154
+ },
155
+ async post(path, body) {
156
+ return executeRequest('POST', path, body);
157
+ },
158
+ async put(path, body) {
159
+ return executeRequest('PUT', path, body);
160
+ },
161
+ async patch(path, body) {
162
+ return executeRequest('PATCH', path, body);
163
+ },
164
+ async delete(path) {
165
+ return executeRequest('DELETE', path);
166
+ },
167
+ };
168
+ }
169
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { KelpiConfig, AuthState as AuthStateType } from '../types.js';
2
+ export type AuthState = AuthStateType;
3
+ /**
4
+ * Manages authentication state for the MCP server.
5
+ * Supports caching and refresh of authentication state.
6
+ */
7
+ export declare class AuthStateManager {
8
+ private cachedState;
9
+ private config;
10
+ /**
11
+ * Create a new AuthStateManager.
12
+ * @param config - Optional config to use instead of loading from file
13
+ */
14
+ constructor(config?: KelpiConfig);
15
+ /**
16
+ * Get the current authentication state.
17
+ * Returns cached state if available, or fetches from API.
18
+ * @param fetchIfNeeded - If true (default), fetch from API if not cached
19
+ */
20
+ getState(fetchIfNeeded?: boolean): Promise<AuthState>;
21
+ /**
22
+ * Refresh the authentication state by clearing cache and re-fetching.
23
+ */
24
+ refresh(): Promise<AuthState>;
25
+ /**
26
+ * Clear the cached authentication state.
27
+ */
28
+ clearState(): void;
29
+ /**
30
+ * Get the key type from the API key prefix.
31
+ */
32
+ private getKeyType;
33
+ /**
34
+ * Fetch workspace info from the API.
35
+ */
36
+ private fetchWorkspaceInfo;
37
+ }
38
+ /**
39
+ * Get the current authentication state.
40
+ */
41
+ export declare function getAuthState(): Promise<AuthState>;
42
+ /**
43
+ * Check if currently authenticated.
44
+ */
45
+ export declare function isAuthenticated(): Promise<boolean>;
46
+ /**
47
+ * Refresh and return the authentication state.
48
+ */
49
+ export declare function refreshAuthState(): Promise<AuthState>;
50
+ /**
51
+ * Clear the cached authentication state.
52
+ */
53
+ export declare function clearAuthState(): void;
54
+ //# sourceMappingURL=auth-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-state.d.ts","sourceRoot":"","sources":["../../src/lib/auth-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,aAAa,CAAC;AAK3E,MAAM,MAAM,SAAS,GAAG,aAAa,CAAC;AAYtC;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,MAAM,CAAqB;IAEnC;;;OAGG;gBACS,MAAM,CAAC,EAAE,WAAW;IAIhC;;;;OAIG;IACG,QAAQ,CAAC,aAAa,UAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IA+CxD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;IAKnC;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;YACW,kBAAkB;CAIjC;AAYD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC,CAEvD;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,SAAS,CAAC,CAE3D;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAMrC"}
@@ -0,0 +1,131 @@
1
+ import { loadConfig } from './config.js';
2
+ import { createApiClient } from './api-client.js';
3
+ /**
4
+ * Manages authentication state for the MCP server.
5
+ * Supports caching and refresh of authentication state.
6
+ */
7
+ export class AuthStateManager {
8
+ cachedState = null;
9
+ config;
10
+ /**
11
+ * Create a new AuthStateManager.
12
+ * @param config - Optional config to use instead of loading from file
13
+ */
14
+ constructor(config) {
15
+ this.config = config || null;
16
+ }
17
+ /**
18
+ * Get the current authentication state.
19
+ * Returns cached state if available, or fetches from API.
20
+ * @param fetchIfNeeded - If true (default), fetch from API if not cached
21
+ */
22
+ async getState(fetchIfNeeded = true) {
23
+ // Return cached state if available
24
+ if (this.cachedState !== null) {
25
+ return this.cachedState;
26
+ }
27
+ // If not fetching, return unauthenticated state
28
+ if (!fetchIfNeeded) {
29
+ return { authenticated: false };
30
+ }
31
+ // Load config if not provided
32
+ const config = this.config || await loadConfig();
33
+ // If no API key, return unauthenticated state
34
+ if (!config.api_key) {
35
+ this.cachedState = { authenticated: false };
36
+ return this.cachedState;
37
+ }
38
+ // Determine key type from prefix
39
+ const keyType = this.getKeyType(config.api_key);
40
+ // Create API client and fetch workspace info
41
+ try {
42
+ const client = createApiClient({
43
+ apiKey: config.api_key,
44
+ apiUrl: config.api_url,
45
+ });
46
+ const workspaceInfo = await this.fetchWorkspaceInfo(client);
47
+ this.cachedState = {
48
+ authenticated: true,
49
+ workspace_id: workspaceInfo.workspace.id,
50
+ workspace_name: workspaceInfo.workspace.name,
51
+ key_type: keyType,
52
+ };
53
+ return this.cachedState;
54
+ }
55
+ catch {
56
+ // If API call fails, mark as unauthenticated
57
+ this.cachedState = { authenticated: false };
58
+ return this.cachedState;
59
+ }
60
+ }
61
+ /**
62
+ * Refresh the authentication state by clearing cache and re-fetching.
63
+ */
64
+ async refresh() {
65
+ this.cachedState = null;
66
+ return this.getState();
67
+ }
68
+ /**
69
+ * Clear the cached authentication state.
70
+ */
71
+ clearState() {
72
+ this.cachedState = null;
73
+ }
74
+ /**
75
+ * Get the key type from the API key prefix.
76
+ */
77
+ getKeyType(apiKey) {
78
+ if (apiKey.startsWith('klp_sk_')) {
79
+ return 'secret';
80
+ }
81
+ else if (apiKey.startsWith('klp_pk_')) {
82
+ return 'public';
83
+ }
84
+ return undefined;
85
+ }
86
+ /**
87
+ * Fetch workspace info from the API.
88
+ */
89
+ async fetchWorkspaceInfo(client) {
90
+ const response = await client.get('/api/v1/auth/me');
91
+ return response.data;
92
+ }
93
+ }
94
+ // Singleton instance for module-level functions
95
+ let defaultManager = null;
96
+ function getManager() {
97
+ if (!defaultManager) {
98
+ defaultManager = new AuthStateManager();
99
+ }
100
+ return defaultManager;
101
+ }
102
+ /**
103
+ * Get the current authentication state.
104
+ */
105
+ export async function getAuthState() {
106
+ return getManager().getState();
107
+ }
108
+ /**
109
+ * Check if currently authenticated.
110
+ */
111
+ export async function isAuthenticated() {
112
+ const state = await getAuthState();
113
+ return state.authenticated;
114
+ }
115
+ /**
116
+ * Refresh and return the authentication state.
117
+ */
118
+ export async function refreshAuthState() {
119
+ return getManager().refresh();
120
+ }
121
+ /**
122
+ * Clear the cached authentication state.
123
+ */
124
+ export function clearAuthState() {
125
+ if (defaultManager) {
126
+ defaultManager.clearState();
127
+ }
128
+ // Also reset the manager so next call creates fresh instance
129
+ defaultManager = null;
130
+ }
131
+ //# sourceMappingURL=auth-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-state.js","sourceRoot":"","sources":["../../src/lib/auth-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { KelpiConfig, ConfigValidationResult, SaveConfigOptions } from '../types.js';
2
+ export { ConfigError } from './errors.js';
3
+ export type { KelpiConfig } from '../types.js';
4
+ /**
5
+ * Returns the path to the config file.
6
+ * Uses KELPI_CONFIG_PATH env var if set, otherwise ~/.kelpi/config.json
7
+ */
8
+ export declare function getConfigPath(): string;
9
+ /**
10
+ * Loads configuration from file and merges with environment variables.
11
+ * Environment variables take precedence over file values.
12
+ */
13
+ export declare function loadConfig(): Promise<KelpiConfig>;
14
+ /**
15
+ * Returns the API key from environment variable or config file.
16
+ * Environment variable takes precedence.
17
+ */
18
+ export declare function getApiKey(): Promise<string | undefined>;
19
+ /**
20
+ * Returns the API URL from environment variable, config file, or default.
21
+ * Priority: env var > config file > default
22
+ */
23
+ export declare function getApiUrl(): Promise<string>;
24
+ /**
25
+ * Saves configuration to file.
26
+ * Creates the config directory if it doesn't exist.
27
+ *
28
+ * @param config - Configuration to save
29
+ * @param options - Save options
30
+ * @param options.merge - If true, merges with existing config.
31
+ * Warning: Not atomic. Concurrent saves may cause data loss.
32
+ */
33
+ export declare function saveConfig(config: KelpiConfig, options?: SaveConfigOptions): Promise<void>;
34
+ /**
35
+ * Validates the configuration object.
36
+ * Checks API key format and URL validity.
37
+ */
38
+ export declare function validateConfig(config: KelpiConfig): ConfigValidationResult;
39
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAG1F,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2B/C;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC,CA8BvD;AAED;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO7D;AAED;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAOjD;AAuBD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,sBAAsB,CA6B1E"}
@@ -0,0 +1,170 @@
1
+ import fsPromises from 'fs/promises';
2
+ import path from 'path';
3
+ import { homedir } from 'os';
4
+ // Re-export ConfigError from errors.ts for convenience
5
+ export { ConfigError } from './errors.js';
6
+ import { ConfigError } from './errors.js';
7
+ /**
8
+ * Default API URL for Kelpi
9
+ */
10
+ const DEFAULT_API_URL = 'https://api.kelpi.ai';
11
+ /**
12
+ * Default config directory name
13
+ */
14
+ const CONFIG_DIR = '.kelpi';
15
+ /**
16
+ * Config file name
17
+ */
18
+ const CONFIG_FILE = 'config.json';
19
+ /**
20
+ * Expands ~ to the user's home directory
21
+ */
22
+ function expandTilde(filepath) {
23
+ if (filepath.startsWith('~/')) {
24
+ return path.join(homedir(), filepath.slice(2));
25
+ }
26
+ return filepath;
27
+ }
28
+ /**
29
+ * Returns the path to the config file.
30
+ * Uses KELPI_CONFIG_PATH env var if set, otherwise ~/.kelpi/config.json
31
+ */
32
+ export function getConfigPath() {
33
+ const envPath = process.env.KELPI_CONFIG_PATH;
34
+ if (envPath) {
35
+ return expandTilde(envPath);
36
+ }
37
+ return path.join(homedir(), CONFIG_DIR, CONFIG_FILE);
38
+ }
39
+ /**
40
+ * Loads configuration from file and merges with environment variables.
41
+ * Environment variables take precedence over file values.
42
+ */
43
+ export async function loadConfig() {
44
+ const configPath = getConfigPath();
45
+ let fileConfig = {};
46
+ try {
47
+ const content = await fsPromises.readFile(configPath, 'utf8');
48
+ fileConfig = JSON.parse(content);
49
+ }
50
+ catch (error) {
51
+ if (error.code === 'ENOENT') {
52
+ // Config file doesn't exist, that's OK
53
+ fileConfig = {};
54
+ }
55
+ else if (error instanceof SyntaxError) {
56
+ throw new ConfigError('Invalid config file: malformed JSON');
57
+ }
58
+ else {
59
+ throw error;
60
+ }
61
+ }
62
+ // Merge with environment variables (env vars take precedence)
63
+ const config = { ...fileConfig };
64
+ if (process.env.KELPI_API_KEY) {
65
+ config.api_key = process.env.KELPI_API_KEY;
66
+ }
67
+ if (process.env.KELPI_API_URL) {
68
+ config.api_url = process.env.KELPI_API_URL;
69
+ }
70
+ return config;
71
+ }
72
+ /**
73
+ * Returns the API key from environment variable or config file.
74
+ * Environment variable takes precedence.
75
+ */
76
+ export async function getApiKey() {
77
+ if (process.env.KELPI_API_KEY) {
78
+ return process.env.KELPI_API_KEY;
79
+ }
80
+ const config = await loadConfig();
81
+ return config.api_key;
82
+ }
83
+ /**
84
+ * Returns the API URL from environment variable, config file, or default.
85
+ * Priority: env var > config file > default
86
+ */
87
+ export async function getApiUrl() {
88
+ if (process.env.KELPI_API_URL) {
89
+ return process.env.KELPI_API_URL;
90
+ }
91
+ const config = await loadConfig();
92
+ return config.api_url || DEFAULT_API_URL;
93
+ }
94
+ /**
95
+ * Returns the directory containing the config file
96
+ */
97
+ function getConfigDir() {
98
+ return path.dirname(getConfigPath());
99
+ }
100
+ /**
101
+ * Loads config from file only (without env var merge)
102
+ */
103
+ async function loadConfigFromFile() {
104
+ const configPath = getConfigPath();
105
+ try {
106
+ const content = await fsPromises.readFile(configPath, 'utf8');
107
+ return JSON.parse(content);
108
+ }
109
+ catch {
110
+ return {};
111
+ }
112
+ }
113
+ /**
114
+ * Saves configuration to file.
115
+ * Creates the config directory if it doesn't exist.
116
+ *
117
+ * @param config - Configuration to save
118
+ * @param options - Save options
119
+ * @param options.merge - If true, merges with existing config.
120
+ * Warning: Not atomic. Concurrent saves may cause data loss.
121
+ */
122
+ export async function saveConfig(config, options = {}) {
123
+ const configPath = getConfigPath();
124
+ const configDir = getConfigDir();
125
+ // Ensure directory exists
126
+ await fsPromises.mkdir(configDir, { recursive: true, mode: 0o700 });
127
+ let finalConfig = config;
128
+ if (options.merge) {
129
+ const existingFileConfig = await loadConfigFromFile();
130
+ finalConfig = { ...existingFileConfig, ...config };
131
+ }
132
+ // Write with restricted permissions (readable/writable only by owner)
133
+ await fsPromises.writeFile(configPath, JSON.stringify(finalConfig, null, 2) + '\n', {
134
+ mode: 0o600,
135
+ });
136
+ }
137
+ /**
138
+ * Validates the configuration object.
139
+ * Checks API key format and URL validity.
140
+ */
141
+ export function validateConfig(config) {
142
+ const errors = [];
143
+ // Validate API key if present
144
+ if (config.api_key !== undefined) {
145
+ if (!config.api_key.startsWith('klp_sk_') && !config.api_key.startsWith('klp_pk_')) {
146
+ errors.push('API key must start with klp_sk_ or klp_pk_');
147
+ }
148
+ else if (config.api_key.length <= 7) {
149
+ // klp_sk_ or klp_pk_ is 7 characters, key should be longer
150
+ errors.push('API key is too short');
151
+ }
152
+ }
153
+ // Validate API URL if present
154
+ if (config.api_url !== undefined) {
155
+ try {
156
+ const url = new URL(config.api_url);
157
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
158
+ errors.push('API URL must be a valid HTTP(S) URL');
159
+ }
160
+ }
161
+ catch {
162
+ errors.push('API URL must be a valid HTTP(S) URL');
163
+ }
164
+ }
165
+ return {
166
+ valid: errors.length === 0,
167
+ errors,
168
+ };
169
+ }
170
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAG7B,uDAAuD;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C;;GAEG;AACH,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAE/C;;GAEG;AACH,MAAM,UAAU,GAAG,QAAQ,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC;;GAEG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC9C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,UAAU,GAAgB,EAAE,CAAC;IAEjC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC9D,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,uCAAuC;YACvC,UAAU,GAAG,EAAE,CAAC;QAClB,CAAC;aAAM,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACxC,MAAM,IAAI,WAAW,CAAC,qCAAqC,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,MAAM,MAAM,GAAgB,EAAE,GAAG,UAAU,EAAE,CAAC;IAE9C,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC7C,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC7C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACnC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACnC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,OAAO,MAAM,CAAC,OAAO,IAAI,eAAe,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,SAAS,YAAY;IACnB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,kBAAkB;IAC/B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAmB,EACnB,UAA6B,EAAE;IAE/B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,0BAA0B;IAC1B,MAAM,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAEpE,IAAI,WAAW,GAAG,MAAM,CAAC;IAEzB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,kBAAkB,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACtD,WAAW,GAAG,EAAE,GAAG,kBAAkB,EAAE,GAAG,MAAM,EAAE,CAAC;IACrD,CAAC;IAED,sEAAsE;IACtE,MAAM,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;QAClF,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAmB;IAChD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,8BAA8B;IAC9B,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACnF,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC5D,CAAC;aAAM,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACtC,2DAA2D;YAC3D,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACpC,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC1D,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;KACP,CAAC;AACJ,CAAC"}