@elliotding/ai-agent-mcp 0.1.25 → 0.1.26

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 (237) hide show
  1. package/package.json +4 -1
  2. package/.prompt-cache/cmd-cmd-client-sdk-ai-hub-generate-testcase.md +0 -101
  3. package/.prompt-cache/cmd-cmd-client-sdk-ai-hub-submit_zct_job.md +0 -158
  4. package/.prompt-cache/skill-skill-client-sdk-ai-hub-analyze-conf-status.md +0 -311
  5. package/.prompt-cache/skill-skill-client-sdk-ai-hub-analyze-sdk-log.md +0 -64
  6. package/.prompt-cache/skill-skill-client-sdk-ai-hub-analyze-zmb-log-errors.md +0 -84
  7. package/ai-resource-telemetry.json +0 -40
  8. package/dist/api/cached-client.d.ts +0 -48
  9. package/dist/api/cached-client.d.ts.map +0 -1
  10. package/dist/api/cached-client.js +0 -126
  11. package/dist/api/cached-client.js.map +0 -1
  12. package/dist/api/client.d.ts +0 -281
  13. package/dist/api/client.d.ts.map +0 -1
  14. package/dist/api/client.js +0 -371
  15. package/dist/api/client.js.map +0 -1
  16. package/dist/auth/index.d.ts +0 -8
  17. package/dist/auth/index.d.ts.map +0 -1
  18. package/dist/auth/index.js +0 -26
  19. package/dist/auth/index.js.map +0 -1
  20. package/dist/auth/middleware.d.ts +0 -36
  21. package/dist/auth/middleware.d.ts.map +0 -1
  22. package/dist/auth/middleware.js +0 -194
  23. package/dist/auth/middleware.js.map +0 -1
  24. package/dist/auth/permissions.d.ts +0 -60
  25. package/dist/auth/permissions.d.ts.map +0 -1
  26. package/dist/auth/permissions.js +0 -262
  27. package/dist/auth/permissions.js.map +0 -1
  28. package/dist/auth/token-validator.d.ts +0 -52
  29. package/dist/auth/token-validator.d.ts.map +0 -1
  30. package/dist/auth/token-validator.js +0 -215
  31. package/dist/auth/token-validator.js.map +0 -1
  32. package/dist/cache/cache-manager.d.ts +0 -49
  33. package/dist/cache/cache-manager.d.ts.map +0 -1
  34. package/dist/cache/cache-manager.js +0 -191
  35. package/dist/cache/cache-manager.js.map +0 -1
  36. package/dist/cache/index.d.ts +0 -6
  37. package/dist/cache/index.d.ts.map +0 -1
  38. package/dist/cache/index.js +0 -12
  39. package/dist/cache/index.js.map +0 -1
  40. package/dist/cache/redis-client.d.ts +0 -45
  41. package/dist/cache/redis-client.d.ts.map +0 -1
  42. package/dist/cache/redis-client.js +0 -210
  43. package/dist/cache/redis-client.js.map +0 -1
  44. package/dist/config/constants.d.ts +0 -28
  45. package/dist/config/constants.d.ts.map +0 -1
  46. package/dist/config/constants.js +0 -31
  47. package/dist/config/constants.js.map +0 -1
  48. package/dist/config/index.d.ts +0 -71
  49. package/dist/config/index.d.ts.map +0 -1
  50. package/dist/config/index.js +0 -190
  51. package/dist/config/index.js.map +0 -1
  52. package/dist/filesystem/manager.d.ts +0 -45
  53. package/dist/filesystem/manager.d.ts.map +0 -1
  54. package/dist/filesystem/manager.js +0 -246
  55. package/dist/filesystem/manager.js.map +0 -1
  56. package/dist/git/multi-source-manager.d.ts +0 -78
  57. package/dist/git/multi-source-manager.d.ts.map +0 -1
  58. package/dist/git/multi-source-manager.js +0 -577
  59. package/dist/git/multi-source-manager.js.map +0 -1
  60. package/dist/git/operations.d.ts +0 -27
  61. package/dist/git/operations.d.ts.map +0 -1
  62. package/dist/git/operations.js +0 -83
  63. package/dist/git/operations.js.map +0 -1
  64. package/dist/index.d.ts +0 -6
  65. package/dist/index.d.ts.map +0 -1
  66. package/dist/index.js +0 -122
  67. package/dist/index.js.map +0 -1
  68. package/dist/monitoring/health.d.ts +0 -35
  69. package/dist/monitoring/health.d.ts.map +0 -1
  70. package/dist/monitoring/health.js +0 -105
  71. package/dist/monitoring/health.js.map +0 -1
  72. package/dist/prompts/cache.d.ts +0 -69
  73. package/dist/prompts/cache.d.ts.map +0 -1
  74. package/dist/prompts/cache.js +0 -163
  75. package/dist/prompts/cache.js.map +0 -1
  76. package/dist/prompts/generator.d.ts +0 -49
  77. package/dist/prompts/generator.d.ts.map +0 -1
  78. package/dist/prompts/generator.js +0 -160
  79. package/dist/prompts/generator.js.map +0 -1
  80. package/dist/prompts/index.d.ts +0 -13
  81. package/dist/prompts/index.d.ts.map +0 -1
  82. package/dist/prompts/index.js +0 -24
  83. package/dist/prompts/index.js.map +0 -1
  84. package/dist/prompts/manager.d.ts +0 -207
  85. package/dist/prompts/manager.d.ts.map +0 -1
  86. package/dist/prompts/manager.js +0 -566
  87. package/dist/prompts/manager.js.map +0 -1
  88. package/dist/resources/index.d.ts +0 -6
  89. package/dist/resources/index.d.ts.map +0 -1
  90. package/dist/resources/index.js +0 -10
  91. package/dist/resources/index.js.map +0 -1
  92. package/dist/resources/loader.d.ts +0 -88
  93. package/dist/resources/loader.d.ts.map +0 -1
  94. package/dist/resources/loader.js +0 -492
  95. package/dist/resources/loader.js.map +0 -1
  96. package/dist/server/http.d.ts +0 -57
  97. package/dist/server/http.d.ts.map +0 -1
  98. package/dist/server/http.js +0 -435
  99. package/dist/server/http.js.map +0 -1
  100. package/dist/server.d.ts +0 -13
  101. package/dist/server.d.ts.map +0 -1
  102. package/dist/server.js +0 -201
  103. package/dist/server.js.map +0 -1
  104. package/dist/session/manager.d.ts +0 -91
  105. package/dist/session/manager.d.ts.map +0 -1
  106. package/dist/session/manager.js +0 -251
  107. package/dist/session/manager.js.map +0 -1
  108. package/dist/telemetry/index.d.ts +0 -3
  109. package/dist/telemetry/index.d.ts.map +0 -1
  110. package/dist/telemetry/index.js +0 -7
  111. package/dist/telemetry/index.js.map +0 -1
  112. package/dist/telemetry/manager.d.ts +0 -151
  113. package/dist/telemetry/manager.d.ts.map +0 -1
  114. package/dist/telemetry/manager.js +0 -367
  115. package/dist/telemetry/manager.js.map +0 -1
  116. package/dist/tools/index.d.ts +0 -13
  117. package/dist/tools/index.d.ts.map +0 -1
  118. package/dist/tools/index.js +0 -29
  119. package/dist/tools/index.js.map +0 -1
  120. package/dist/tools/manage-subscription.d.ts +0 -47
  121. package/dist/tools/manage-subscription.d.ts.map +0 -1
  122. package/dist/tools/manage-subscription.js +0 -317
  123. package/dist/tools/manage-subscription.js.map +0 -1
  124. package/dist/tools/registry.d.ts +0 -40
  125. package/dist/tools/registry.d.ts.map +0 -1
  126. package/dist/tools/registry.js +0 -85
  127. package/dist/tools/registry.js.map +0 -1
  128. package/dist/tools/resolve-prompt-content.d.ts +0 -35
  129. package/dist/tools/resolve-prompt-content.d.ts.map +0 -1
  130. package/dist/tools/resolve-prompt-content.js +0 -99
  131. package/dist/tools/resolve-prompt-content.js.map +0 -1
  132. package/dist/tools/search-resources.d.ts +0 -35
  133. package/dist/tools/search-resources.d.ts.map +0 -1
  134. package/dist/tools/search-resources.js +0 -159
  135. package/dist/tools/search-resources.js.map +0 -1
  136. package/dist/tools/sync-resources.d.ts +0 -54
  137. package/dist/tools/sync-resources.d.ts.map +0 -1
  138. package/dist/tools/sync-resources.js +0 -735
  139. package/dist/tools/sync-resources.js.map +0 -1
  140. package/dist/tools/track-usage.d.ts +0 -63
  141. package/dist/tools/track-usage.d.ts.map +0 -1
  142. package/dist/tools/track-usage.js +0 -90
  143. package/dist/tools/track-usage.js.map +0 -1
  144. package/dist/tools/uninstall-resource.d.ts +0 -30
  145. package/dist/tools/uninstall-resource.d.ts.map +0 -1
  146. package/dist/tools/uninstall-resource.js +0 -174
  147. package/dist/tools/uninstall-resource.js.map +0 -1
  148. package/dist/tools/upload-resource.d.ts +0 -81
  149. package/dist/tools/upload-resource.d.ts.map +0 -1
  150. package/dist/tools/upload-resource.js +0 -393
  151. package/dist/tools/upload-resource.js.map +0 -1
  152. package/dist/transport/sse.d.ts +0 -29
  153. package/dist/transport/sse.d.ts.map +0 -1
  154. package/dist/transport/sse.js +0 -271
  155. package/dist/transport/sse.js.map +0 -1
  156. package/dist/types/errors.d.ts +0 -60
  157. package/dist/types/errors.d.ts.map +0 -1
  158. package/dist/types/errors.js +0 -112
  159. package/dist/types/errors.js.map +0 -1
  160. package/dist/types/index.d.ts +0 -7
  161. package/dist/types/index.d.ts.map +0 -1
  162. package/dist/types/index.js +0 -23
  163. package/dist/types/index.js.map +0 -1
  164. package/dist/types/mcp.d.ts +0 -50
  165. package/dist/types/mcp.d.ts.map +0 -1
  166. package/dist/types/mcp.js +0 -6
  167. package/dist/types/mcp.js.map +0 -1
  168. package/dist/types/resources.d.ts +0 -109
  169. package/dist/types/resources.d.ts.map +0 -1
  170. package/dist/types/resources.js +0 -7
  171. package/dist/types/resources.js.map +0 -1
  172. package/dist/types/tools.d.ts +0 -253
  173. package/dist/types/tools.d.ts.map +0 -1
  174. package/dist/types/tools.js +0 -6
  175. package/dist/types/tools.js.map +0 -1
  176. package/dist/utils/cursor-paths.d.ts +0 -84
  177. package/dist/utils/cursor-paths.d.ts.map +0 -1
  178. package/dist/utils/cursor-paths.js +0 -166
  179. package/dist/utils/cursor-paths.js.map +0 -1
  180. package/dist/utils/log-cleaner.d.ts +0 -18
  181. package/dist/utils/log-cleaner.d.ts.map +0 -1
  182. package/dist/utils/log-cleaner.js +0 -112
  183. package/dist/utils/log-cleaner.js.map +0 -1
  184. package/dist/utils/logger.d.ts +0 -59
  185. package/dist/utils/logger.d.ts.map +0 -1
  186. package/dist/utils/logger.js +0 -292
  187. package/dist/utils/logger.js.map +0 -1
  188. package/dist/utils/validation.d.ts +0 -58
  189. package/dist/utils/validation.d.ts.map +0 -1
  190. package/dist/utils/validation.js +0 -214
  191. package/dist/utils/validation.js.map +0 -1
  192. package/src/api/cached-client.ts +0 -144
  193. package/src/api/client.ts +0 -697
  194. package/src/auth/index.ts +0 -11
  195. package/src/auth/middleware.ts +0 -244
  196. package/src/auth/permissions.ts +0 -323
  197. package/src/auth/token-validator.ts +0 -292
  198. package/src/cache/cache-manager.ts +0 -243
  199. package/src/cache/index.ts +0 -6
  200. package/src/cache/redis-client.ts +0 -249
  201. package/src/config/constants.ts +0 -33
  202. package/src/config/index.ts +0 -269
  203. package/src/filesystem/manager.ts +0 -235
  204. package/src/git/multi-source-manager.ts +0 -654
  205. package/src/git/operations.ts +0 -93
  206. package/src/index.ts +0 -157
  207. package/src/monitoring/health.ts +0 -132
  208. package/src/prompts/cache.ts +0 -140
  209. package/src/prompts/generator.ts +0 -143
  210. package/src/prompts/index.ts +0 -20
  211. package/src/prompts/manager.ts +0 -718
  212. package/src/resources/index.ts +0 -13
  213. package/src/resources/loader.ts +0 -563
  214. package/src/server/http.ts +0 -549
  215. package/src/server.ts +0 -206
  216. package/src/session/manager.ts +0 -296
  217. package/src/telemetry/index.ts +0 -10
  218. package/src/telemetry/manager.ts +0 -419
  219. package/src/tools/index.ts +0 -13
  220. package/src/tools/manage-subscription.ts +0 -388
  221. package/src/tools/registry.ts +0 -97
  222. package/src/tools/resolve-prompt-content.ts +0 -113
  223. package/src/tools/search-resources.ts +0 -185
  224. package/src/tools/sync-resources.ts +0 -829
  225. package/src/tools/track-usage.ts +0 -113
  226. package/src/tools/uninstall-resource.ts +0 -199
  227. package/src/tools/upload-resource.ts +0 -431
  228. package/src/transport/sse.ts +0 -308
  229. package/src/types/errors.ts +0 -146
  230. package/src/types/index.ts +0 -7
  231. package/src/types/mcp.ts +0 -61
  232. package/src/types/resources.ts +0 -141
  233. package/src/types/tools.ts +0 -305
  234. package/src/utils/cursor-paths.ts +0 -135
  235. package/src/utils/log-cleaner.ts +0 -92
  236. package/src/utils/logger.ts +0 -333
  237. package/src/utils/validation.ts +0 -262
@@ -1,93 +0,0 @@
1
- /**
2
- * Git Operations Module
3
- * Per-repo git helpers used by upload_resource to target a specific source repo.
4
- * All repo URLs and branches come from AI-Resources/ai-resources-config.json —
5
- * not from environment variables.
6
- */
7
-
8
- import simpleGit from 'simple-git';
9
- import { config } from '../config';
10
- import { logger } from '../utils/logger';
11
- import { createGitError } from '../types/errors';
12
-
13
- class GitOperations {
14
- // ---- Per-repo helpers (used by upload_resource to target a specific source) ----
15
-
16
- /**
17
- * Check whether a git repository exists at an arbitrary local path
18
- */
19
- async repositoryExistsAt(repoPath: string): Promise<boolean> {
20
- try {
21
- const git = simpleGit({ baseDir: repoPath, binary: 'git', maxConcurrentProcesses: 6 });
22
- await git.status();
23
- return true;
24
- } catch {
25
- return false;
26
- }
27
- }
28
-
29
- /**
30
- * Get current branch of an arbitrary local repo
31
- */
32
- async getCurrentBranchAt(repoPath: string): Promise<string> {
33
- try {
34
- const git = simpleGit({ baseDir: repoPath, binary: 'git', maxConcurrentProcesses: 6 });
35
- const branchSummary = await git.branch();
36
- return branchSummary.current;
37
- } catch (error) {
38
- throw createGitError('get-branch', error as Error);
39
- }
40
- }
41
-
42
- /**
43
- * Commit and push to a specific repo / remote url / branch.
44
- * Creates a unique remote testing branch and returns a PR URL.
45
- */
46
- async commitAndPushRepo(
47
- repoPath: string,
48
- remoteUrl: string,
49
- baseBranch: string,
50
- message: string,
51
- files?: string[]
52
- ): Promise<{ commitHash: string; prUrl?: string }> {
53
- try {
54
- const git = simpleGit({ baseDir: repoPath, binary: 'git', maxConcurrentProcesses: 6 });
55
-
56
- logger.info({ repoPath, remoteUrl, message, fileCount: files?.length }, 'Committing and pushing to source repo...');
57
-
58
- await git.addConfig('user.name', config.git.userName);
59
- await git.addConfig('user.email', config.git.userEmail);
60
-
61
- const branchSummary = await git.branch();
62
- const currentBranch = branchSummary.current;
63
-
64
- const timestamp = Date.now();
65
- const randomSuffix = Math.random().toString(36).substring(2, 8);
66
- const remoteBranchName = `dev-${currentBranch}-testing-${timestamp}-${randomSuffix}`;
67
- logger.info({ remoteBranchName }, 'Generated remote branch name for PR');
68
-
69
- if (files && files.length > 0) {
70
- await git.add(files);
71
- } else {
72
- await git.add('.');
73
- }
74
-
75
- const commitResult = await git.commit(message);
76
- const commitHash = commitResult.commit;
77
- logger.info({ commitHash }, 'Git commit created');
78
-
79
- await git.push(remoteUrl, `${currentBranch}:${remoteBranchName}`);
80
- logger.info({ remoteBranchName }, 'Git push completed');
81
-
82
- const repoBaseUrl = remoteUrl.replace(/\.git$/, '');
83
- const prUrl = `${repoBaseUrl}/compare/${baseBranch}...${remoteBranchName}`;
84
- logger.info({ prUrl, commitHash }, 'PR URL generated');
85
-
86
- return { commitHash, prUrl };
87
- } catch (error) {
88
- throw createGitError('commit-push', error as Error, remoteUrl);
89
- }
90
- }
91
- }
92
-
93
- export const gitOperations = new GitOperations();
package/src/index.ts DELETED
@@ -1,157 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * CSP AI Agent MCP Server - Main Entry Point
5
- */
6
-
7
- import { config } from './config';
8
- import { logger } from './utils/logger';
9
- import { startLogCleanupSchedule, stopLogCleanupSchedule } from './utils/log-cleaner';
10
- import { startServer, stopServer } from './server';
11
- import { stopCacheCleanup } from './auth/token-validator';
12
- import { sessionManager } from './session/manager';
13
- import { telemetry } from './telemetry/index.js';
14
- import { apiClient } from './api/client.js';
15
-
16
- // Global error handlers
17
- process.on('uncaughtException', (error: Error) => {
18
- // Handle EPIPE and ECONNRESET gracefully (client disconnected)
19
- if (error.message.includes('EPIPE') || error.message.includes('ECONNRESET')) {
20
- logger.debug({
21
- error: error.message,
22
- type: 'uncaught_exception_network'
23
- }, 'Client disconnected (EPIPE/ECONNRESET)');
24
- return; // Don't exit for network errors
25
- }
26
-
27
- // For other uncaught exceptions, log and exit
28
- logger.error({ error, type: 'uncaught_exception' }, `Uncaught Exception: ${error.message}`);
29
- process.exit(1);
30
- });
31
-
32
- process.on('unhandledRejection', (reason: unknown, _promise: Promise<unknown>) => {
33
- logger.error(
34
- {
35
- type: 'unhandled_rejection',
36
- reason: reason instanceof Error ? reason.message : String(reason),
37
- stack: reason instanceof Error ? reason.stack : undefined,
38
- },
39
- 'Unhandled Promise Rejection'
40
- );
41
- process.exit(1);
42
- });
43
-
44
- async function main() {
45
- logger.info(
46
- {
47
- nodeEnv: config.nodeEnv,
48
- port: config.port,
49
- logLevel: config.logLevel,
50
- },
51
- 'Starting CSP AI Agent MCP Server...'
52
- );
53
-
54
- // Start log cleanup scheduler
55
- const cleanupTimer = startLogCleanupSchedule();
56
-
57
- // Wire up telemetry reporting (inject API client to avoid circular import).
58
- // Tokens are sourced exclusively from authenticated SSE connections via setUserToken().
59
- telemetry.configure(
60
- (payload, token) => apiClient.reportTelemetry(payload, token)
61
- );
62
-
63
- try {
64
- // Start MCP Server
65
- await startServer();
66
-
67
- logger.info({ port: config.port }, `✅ CSP AI Agent MCP Server started successfully`);
68
-
69
- // Start periodic telemetry flush (every 10 seconds)
70
- telemetry.startPeriodicFlush(10_000);
71
- logger.info('Telemetry flush scheduler started (interval: 10s)');
72
- } catch (error) {
73
- logger.error({ error }, 'Failed to start server');
74
- stopLogCleanupSchedule(cleanupTimer);
75
- process.exit(1);
76
- }
77
-
78
- // Graceful shutdown handlers
79
- let isShuttingDown = false;
80
- const SHUTDOWN_TIMEOUT = Number(process.env.SHUTDOWN_TIMEOUT) || 30000; // 30 seconds default
81
-
82
- const shutdown = async (signal: string) => {
83
- // Prevent multiple shutdown attempts
84
- if (isShuttingDown) {
85
- logger.warn({ signal }, 'Shutdown already in progress, ignoring signal');
86
- return;
87
- }
88
- isShuttingDown = true;
89
-
90
- logger.info({ signal, timeout: SHUTDOWN_TIMEOUT }, `Received ${signal}, starting graceful shutdown...`);
91
-
92
- // Set timeout for forced shutdown
93
- const shutdownTimer = setTimeout(() => {
94
- logger.error(
95
- { timeout: SHUTDOWN_TIMEOUT },
96
- `Graceful shutdown timeout (${SHUTDOWN_TIMEOUT}ms), forcing exit`
97
- );
98
- process.exit(1);
99
- }, SHUTDOWN_TIMEOUT);
100
-
101
- try {
102
- // Phase 1: Stop accepting new requests
103
- logger.info('Phase 1: Stopping new requests...');
104
-
105
- // Phase 2: Wait for ongoing requests to complete
106
- logger.info('Phase 2: Waiting for ongoing requests to complete...');
107
-
108
- // Stop MCP Server (this will close all active sessions and connections)
109
- await stopServer();
110
-
111
- // Phase 3: Stop background tasks
112
- logger.info('Phase 3: Stopping background tasks...');
113
-
114
- // Stop log cleanup
115
- stopLogCleanupSchedule(cleanupTimer);
116
-
117
- // Stop session cleanup
118
- sessionManager.stopCleanup();
119
- logger.info('Session cleanup stopped');
120
-
121
- // Stop token cache cleanup
122
- stopCacheCleanup();
123
- logger.info('Token cache cleanup stopped');
124
-
125
- // Stop telemetry scheduler and perform final flush
126
- telemetry.stopPeriodicFlush();
127
- logger.info('Telemetry scheduler stopped, performing final flush...');
128
- await telemetry.flush();
129
- logger.info('Final telemetry flush completed');
130
-
131
- // Phase 4: Flush logs
132
- logger.info('Phase 4: Flushing logs...');
133
-
134
- // Give logger time to flush
135
- await new Promise(resolve => setTimeout(resolve, 500));
136
-
137
- // Clear shutdown timeout
138
- clearTimeout(shutdownTimer);
139
-
140
- logger.info('✅ Graceful shutdown completed successfully');
141
- process.exit(0);
142
- } catch (error) {
143
- logger.error({ error }, 'Error during graceful shutdown');
144
- clearTimeout(shutdownTimer);
145
- process.exit(1);
146
- }
147
- };
148
-
149
- process.on('SIGINT', () => void shutdown('SIGINT'));
150
- process.on('SIGTERM', () => void shutdown('SIGTERM'));
151
- }
152
-
153
- // Start the application
154
- void main().catch((error: unknown) => {
155
- logger.error({ error }, 'Fatal error during startup');
156
- process.exit(1);
157
- });
@@ -1,132 +0,0 @@
1
- import { CacheManager } from '../cache/cache-manager.js';
2
-
3
- export interface HealthStatus {
4
- status: 'healthy' | 'unhealthy';
5
- timestamp: string;
6
- services: {
7
- http: 'up' | 'down';
8
- redis: 'up' | 'down' | 'not_configured';
9
- cache: 'healthy' | 'degraded' | 'down';
10
- };
11
- details?: {
12
- redisError?: string;
13
- cacheError?: string;
14
- };
15
- }
16
-
17
- export class HealthChecker {
18
- private cacheManager: CacheManager | null = null;
19
-
20
- constructor(cacheManager?: CacheManager) {
21
- this.cacheManager = cacheManager || null;
22
- }
23
-
24
- /**
25
- * Check HTTP Server health
26
- */
27
- private checkHttpServer(): 'up' | 'down' {
28
- // HTTP server is up if this code is running
29
- return 'up';
30
- }
31
-
32
- /**
33
- * Check Redis connection health
34
- */
35
- private async checkRedis(): Promise<{ status: 'up' | 'down' | 'not_configured'; error?: string }> {
36
- if (!this.cacheManager) {
37
- return { status: 'not_configured' };
38
- }
39
-
40
- try {
41
- // Try to check Redis connection via cache manager
42
- const redisCache = (this.cacheManager as any).l2Cache;
43
-
44
- if (!redisCache) {
45
- return { status: 'not_configured' };
46
- }
47
-
48
- // Try a simple Redis operation (check client status)
49
- const client = (redisCache as any).client;
50
-
51
- if (!client || !client.isReady) {
52
- return { status: 'down', error: 'Redis client not ready' };
53
- }
54
-
55
- // Try a ping operation
56
- await client.ping();
57
- return { status: 'up' };
58
- } catch (error) {
59
- return {
60
- status: 'down',
61
- error: error instanceof Error ? error.message : 'Unknown error'
62
- };
63
- }
64
- }
65
-
66
- /**
67
- * Check Cache health
68
- */
69
- private checkCache(): { status: 'healthy' | 'degraded' | 'down'; error?: string } {
70
- if (!this.cacheManager) {
71
- return { status: 'down', error: 'Cache manager not initialized' };
72
- }
73
-
74
- try {
75
- // Check if cache manager is functional
76
- const stats = this.cacheManager.getStats();
77
-
78
- // Cache is healthy if stats are available
79
- if (stats && typeof stats.hitRate === 'number') {
80
- // Check if hit rate is reasonable (> 0 means cache is working)
81
- if (stats.hitRate >= 0) {
82
- return { status: 'healthy' };
83
- }
84
- return { status: 'degraded', error: 'Low cache hit rate' };
85
- }
86
-
87
- return { status: 'degraded', error: 'Cache stats unavailable' };
88
- } catch (error) {
89
- return {
90
- status: 'down',
91
- error: error instanceof Error ? error.message : 'Unknown error'
92
- };
93
- }
94
- }
95
-
96
- /**
97
- * Perform comprehensive health check
98
- */
99
- async check(): Promise<HealthStatus> {
100
- const httpStatus = this.checkHttpServer();
101
- const redisResult = await this.checkRedis();
102
- const cacheResult = this.checkCache();
103
-
104
- const allHealthy =
105
- httpStatus === 'up' &&
106
- (redisResult.status === 'up' || redisResult.status === 'not_configured') &&
107
- cacheResult.status === 'healthy';
108
-
109
- const health: HealthStatus = {
110
- status: allHealthy ? 'healthy' : 'unhealthy',
111
- timestamp: new Date().toISOString(),
112
- services: {
113
- http: httpStatus,
114
- redis: redisResult.status,
115
- cache: cacheResult.status
116
- }
117
- };
118
-
119
- // Add error details if any
120
- if (redisResult.error || cacheResult.error) {
121
- health.details = {};
122
- if (redisResult.error) {
123
- health.details.redisError = redisResult.error;
124
- }
125
- if (cacheResult.error) {
126
- health.details.cacheError = cacheResult.error;
127
- }
128
- }
129
-
130
- return health;
131
- }
132
- }
@@ -1,140 +0,0 @@
1
- /**
2
- * PromptCache: manages the .prompt-cache/ directory inside the MCP Server's
3
- * runtime working directory.
4
- *
5
- * Cache files hold the fully-expanded Prompt content for each Command/Skill
6
- * resource so that the MCP Prompt handler can serve them without re-generating
7
- * on every invocation.
8
- *
9
- * The cache directory is intentionally NOT committed to Git — it is regenerated
10
- * from the canonical source files after every git pull or resource upload.
11
- *
12
- * File naming: {type}-{resource_id}.md
13
- * e.g. cmd-client-sdk-generate-testcase.md
14
- * skill-client-sdk-analyze-sdk-log.md
15
- */
16
-
17
- import * as fs from 'fs';
18
- import * as path from 'path';
19
- import { logger } from '../utils/logger.js';
20
-
21
- /** Relative directory name inside the MCP Server CWD for cached Prompt files. */
22
- const CACHE_DIR_NAME = '.prompt-cache';
23
-
24
- export class PromptCache {
25
- private readonly cacheDir: string;
26
-
27
- /**
28
- * @param baseDir Absolute base directory (defaults to process.cwd()).
29
- */
30
- constructor(baseDir: string = process.cwd()) {
31
- this.cacheDir = path.join(baseDir, CACHE_DIR_NAME);
32
- }
33
-
34
- /** Absolute path to the cache directory. */
35
- get directory(): string {
36
- return this.cacheDir;
37
- }
38
-
39
- /** Ensure the cache directory exists (idempotent). */
40
- ensureDir(): void {
41
- fs.mkdirSync(this.cacheDir, { recursive: true });
42
- }
43
-
44
- /**
45
- * Derive the cache file name for a resource.
46
- * @param resourceType 'command' | 'skill'
47
- * @param resourceId Canonical resource ID
48
- */
49
- private cacheFileName(resourceType: string, resourceId: string): string {
50
- // Normalise type prefix: 'command' → 'cmd', 'skill' → 'skill'
51
- const prefix = resourceType === 'command' ? 'cmd' : resourceType;
52
- // Sanitise resourceId — remove characters unsafe in filenames.
53
- const safeId = resourceId.replace(/[/\\:*?"<>|]/g, '-');
54
- return `${prefix}-${safeId}.md`;
55
- }
56
-
57
- /** Absolute path to the cache file for a given resource. */
58
- cachePath(resourceType: string, resourceId: string): string {
59
- return path.join(this.cacheDir, this.cacheFileName(resourceType, resourceId));
60
- }
61
-
62
- /**
63
- * Write (or overwrite) a resource's Prompt content to the cache.
64
- * Uses atomic write-then-rename to prevent partial reads.
65
- *
66
- * @param resourceType 'command' | 'skill'
67
- * @param resourceId Canonical resource ID
68
- * @param content Fully-expanded Prompt Markdown content
69
- */
70
- write(resourceType: string, resourceId: string, content: string): void {
71
- this.ensureDir();
72
- const dest = this.cachePath(resourceType, resourceId);
73
- const tmp = `${dest}.${process.pid}.tmp`;
74
- try {
75
- fs.writeFileSync(tmp, content, 'utf8');
76
- fs.renameSync(tmp, dest);
77
- logger.debug(
78
- { resourceId, resourceType, path: dest },
79
- 'Prompt cache written',
80
- );
81
- } catch (err) {
82
- // Best-effort cleanup of temp file
83
- try { fs.unlinkSync(tmp); } catch { /* ignore */ }
84
- throw new Error(
85
- `Failed to write prompt cache for ${resourceId}: ${(err as Error).message}`,
86
- );
87
- }
88
- }
89
-
90
- /**
91
- * Read the cached Prompt content for a resource.
92
- * Returns null if the cache file does not exist or cannot be read.
93
- *
94
- * @param resourceType 'command' | 'skill'
95
- * @param resourceId Canonical resource ID
96
- */
97
- read(resourceType: string, resourceId: string): string | null {
98
- const p = this.cachePath(resourceType, resourceId);
99
- try {
100
- return fs.readFileSync(p, 'utf8');
101
- } catch {
102
- return null;
103
- }
104
- }
105
-
106
- /**
107
- * Delete the cache file for a resource.
108
- * Silently succeeds if the file does not exist.
109
- *
110
- * @param resourceType 'command' | 'skill'
111
- * @param resourceId Canonical resource ID
112
- */
113
- delete(resourceType: string, resourceId: string): void {
114
- const p = this.cachePath(resourceType, resourceId);
115
- try {
116
- fs.unlinkSync(p);
117
- logger.debug({ resourceId, resourceType }, 'Prompt cache deleted');
118
- } catch (err: unknown) {
119
- if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {
120
- logger.warn(
121
- { resourceId, error: (err as Error).message },
122
- 'Failed to delete prompt cache file',
123
- );
124
- }
125
- }
126
- }
127
-
128
- /**
129
- * Check whether a valid cache entry exists for a resource.
130
- *
131
- * @param resourceType 'command' | 'skill'
132
- * @param resourceId Canonical resource ID
133
- */
134
- exists(resourceType: string, resourceId: string): boolean {
135
- return fs.existsSync(this.cachePath(resourceType, resourceId));
136
- }
137
- }
138
-
139
- /** Singleton cache instance using the process CWD as the base directory. */
140
- export const promptCache = new PromptCache();
@@ -1,143 +0,0 @@
1
- /**
2
- * PromptGenerator: converts raw Command/Skill Markdown assets into MCP Prompt content.
3
- *
4
- * Two-step pipeline:
5
- * 1. parseMarkdownWithImports — recursively inline `import 'path'` directives.
6
- * 2. replaceMDVariables — substitute ${VAR} placeholders with runtime values.
7
- *
8
- * The resulting string is returned to the caller who can pass it directly as
9
- * the MCP Prompt message text, or write it to the .prompt-cache/ directory.
10
- */
11
-
12
- import * as fs from 'fs';
13
- import * as path from 'path';
14
- import { logger } from '../utils/logger.js';
15
-
16
- // Maximum import recursion depth to guard against circular imports.
17
- const MAX_IMPORT_DEPTH = 20;
18
-
19
- // Matches lines like: import 'relative/path/to/file.md'
20
- const IMPORT_REGEX = /^import\s+['"]([^'"]+)['"]\s*$/gm;
21
-
22
- /**
23
- * Recursively resolve and inline all `import 'path'` statements in a Markdown
24
- * file. Each imported file's content replaces its import statement in the
25
- * parent document.
26
- *
27
- * @param filePath Absolute path to the root Markdown file.
28
- * @param depth Current recursion depth (used for cycle detection).
29
- * @returns Fully expanded Markdown string.
30
- */
31
- export async function parseMarkdownWithImports(
32
- filePath: string,
33
- depth = 0,
34
- ): Promise<string> {
35
- if (depth > MAX_IMPORT_DEPTH) {
36
- throw new Error(
37
- `Import depth exceeded ${MAX_IMPORT_DEPTH} levels at ${filePath}. ` +
38
- 'Check for circular imports.',
39
- );
40
- }
41
-
42
- let content: string;
43
- try {
44
- content = fs.readFileSync(filePath, 'utf8');
45
- } catch (err) {
46
- throw new Error(`Cannot read Markdown file: ${filePath} — ${(err as Error).message}`);
47
- }
48
-
49
- const fileDir = path.dirname(filePath);
50
- const matches: Array<{ statement: string; resolvedPath: string }> = [];
51
-
52
- let match: RegExpExecArray | null;
53
- // Reset lastIndex before each exec loop (regex is stateful with 'g' flag).
54
- IMPORT_REGEX.lastIndex = 0;
55
- while ((match = IMPORT_REGEX.exec(content)) !== null) {
56
- const importPath = match[1];
57
- if (importPath) {
58
- matches.push({
59
- statement: match[0],
60
- resolvedPath: path.resolve(fileDir, importPath),
61
- });
62
- }
63
- }
64
-
65
- // Process imports sequentially to preserve insertion order.
66
- for (const { statement, resolvedPath } of matches) {
67
- try {
68
- const importedContent = await parseMarkdownWithImports(resolvedPath, depth + 1);
69
- content = content.replace(statement, importedContent);
70
- } catch (err) {
71
- logger.warn(
72
- { importPath: resolvedPath, parentFile: filePath, error: (err as Error).message },
73
- 'Failed to resolve import — leaving placeholder in place',
74
- );
75
- }
76
- }
77
-
78
- return content;
79
- }
80
-
81
- /**
82
- * Replace ${VARIABLE_NAME} placeholders in content with values from the
83
- * provided variable map. Variables not found in the map are left unchanged so
84
- * they remain visible in the output for debugging.
85
- *
86
- * @param content Markdown string (after import expansion).
87
- * @param variables Key-value map of variable names to their replacement strings.
88
- * @returns Content with placeholders substituted.
89
- */
90
- export function replaceMDVariables(
91
- content: string,
92
- variables: Record<string, string>,
93
- ): string {
94
- let result = content;
95
- for (const [key, value] of Object.entries(variables)) {
96
- const regex = new RegExp(`\\$\\{${key}\\}`, 'g');
97
- result = result.replace(regex, value);
98
- }
99
- return result;
100
- }
101
-
102
- /**
103
- * High-level entry point: expand imports then substitute variables.
104
- *
105
- * @param filePath Absolute path to the root Markdown file.
106
- * @param variables Optional variable substitution map (defaults to empty).
107
- * @returns Final Prompt content ready for MCP registration.
108
- */
109
- export async function generatePromptContent(
110
- filePath: string,
111
- variables: Record<string, string> = {},
112
- ): Promise<string> {
113
- const expanded = await parseMarkdownWithImports(filePath);
114
- return replaceMDVariables(expanded, variables);
115
- }
116
-
117
- /**
118
- * Generate Prompt content from a raw Markdown string (no file I/O).
119
- * Used when the resource content has already been downloaded from the API.
120
- *
121
- * @param rawContent Raw Markdown string.
122
- * @param basePath Absolute directory used to resolve relative `import` paths.
123
- * @param variables Optional variable substitution map.
124
- * @returns Final Prompt content.
125
- */
126
- export async function generatePromptContentFromString(
127
- rawContent: string | undefined | null,
128
- basePath: string,
129
- variables: Record<string, string> = {},
130
- ): Promise<string> {
131
- if (!rawContent) return '';
132
- // Write to a temp file so parseMarkdownWithImports can resolve relative imports.
133
- const tmpPath = path.join(basePath, `.tmp-prompt-${Date.now()}-${process.pid}.md`);
134
- let result: string;
135
- try {
136
- fs.mkdirSync(basePath, { recursive: true });
137
- fs.writeFileSync(tmpPath, rawContent, 'utf8');
138
- result = await parseMarkdownWithImports(tmpPath);
139
- } finally {
140
- try { fs.unlinkSync(tmpPath); } catch { /* best-effort cleanup */ }
141
- }
142
- return replaceMDVariables(result, variables);
143
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * prompts module — public API
3
- *
4
- * Exports:
5
- * - PromptGenerator utilities (parseMarkdownWithImports, replaceMDVariables,
6
- * generatePromptContent, generatePromptContentFromString)
7
- * - PromptCache class and the shared singleton `promptCache`
8
- * - PromptManager class and the shared singleton `promptManager`
9
- */
10
-
11
- export {
12
- parseMarkdownWithImports,
13
- replaceMDVariables,
14
- generatePromptContent,
15
- generatePromptContentFromString,
16
- } from './generator.js';
17
-
18
- export { PromptCache, promptCache } from './cache.js';
19
-
20
- export { PromptManager, promptManager } from './manager.js';