@ggakila/agentx-framework 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 (228) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/LICENSE +21 -0
  3. package/README.md +335 -0
  4. package/dist/agent/Agent.d.ts +110 -0
  5. package/dist/agent/Agent.d.ts.map +1 -0
  6. package/dist/agent/Agent.js +291 -0
  7. package/dist/agent/Agent.js.map +1 -0
  8. package/dist/agent/index.d.ts +5 -0
  9. package/dist/agent/index.d.ts.map +1 -0
  10. package/dist/agent/index.js +11 -0
  11. package/dist/agent/index.js.map +1 -0
  12. package/dist/cli/CLI.d.ts +74 -0
  13. package/dist/cli/CLI.d.ts.map +1 -0
  14. package/dist/cli/CLI.js +255 -0
  15. package/dist/cli/CLI.js.map +1 -0
  16. package/dist/cli/InteractiveSetup.d.ts +104 -0
  17. package/dist/cli/InteractiveSetup.d.ts.map +1 -0
  18. package/dist/cli/InteractiveSetup.js +2225 -0
  19. package/dist/cli/InteractiveSetup.js.map +1 -0
  20. package/dist/cli/bin.d.ts +7 -0
  21. package/dist/cli/bin.d.ts.map +1 -0
  22. package/dist/cli/bin.js +35 -0
  23. package/dist/cli/bin.js.map +1 -0
  24. package/dist/cli/commands/ProjectCommands.d.ts +23 -0
  25. package/dist/cli/commands/ProjectCommands.d.ts.map +1 -0
  26. package/dist/cli/commands/ProjectCommands.js +504 -0
  27. package/dist/cli/commands/ProjectCommands.js.map +1 -0
  28. package/dist/cli/index.d.ts +7 -0
  29. package/dist/cli/index.d.ts.map +1 -0
  30. package/dist/cli/index.js +21 -0
  31. package/dist/cli/index.js.map +1 -0
  32. package/dist/credential/CredentialManager.d.ts +112 -0
  33. package/dist/credential/CredentialManager.d.ts.map +1 -0
  34. package/dist/credential/CredentialManager.js +343 -0
  35. package/dist/credential/CredentialManager.js.map +1 -0
  36. package/dist/credential/OAuth2Manager.d.ts +206 -0
  37. package/dist/credential/OAuth2Manager.d.ts.map +1 -0
  38. package/dist/credential/OAuth2Manager.js +463 -0
  39. package/dist/credential/OAuth2Manager.js.map +1 -0
  40. package/dist/credential/index.d.ts +6 -0
  41. package/dist/credential/index.d.ts.map +1 -0
  42. package/dist/credential/index.js +16 -0
  43. package/dist/credential/index.js.map +1 -0
  44. package/dist/error/ErrorHandler.d.ts +74 -0
  45. package/dist/error/ErrorHandler.d.ts.map +1 -0
  46. package/dist/error/ErrorHandler.js +279 -0
  47. package/dist/error/ErrorHandler.js.map +1 -0
  48. package/dist/index.d.ts +30 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +100 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/integrations/DatabaseTool.d.ts +149 -0
  53. package/dist/integrations/DatabaseTool.d.ts.map +1 -0
  54. package/dist/integrations/DatabaseTool.js +900 -0
  55. package/dist/integrations/DatabaseTool.js.map +1 -0
  56. package/dist/integrations/EmailTool.d.ts +142 -0
  57. package/dist/integrations/EmailTool.d.ts.map +1 -0
  58. package/dist/integrations/EmailTool.js +259 -0
  59. package/dist/integrations/EmailTool.js.map +1 -0
  60. package/dist/integrations/FileSystemTool.d.ts +153 -0
  61. package/dist/integrations/FileSystemTool.d.ts.map +1 -0
  62. package/dist/integrations/FileSystemTool.js +835 -0
  63. package/dist/integrations/FileSystemTool.js.map +1 -0
  64. package/dist/integrations/GoogleWorkspaceTool.d.ts +125 -0
  65. package/dist/integrations/GoogleWorkspaceTool.d.ts.map +1 -0
  66. package/dist/integrations/GoogleWorkspaceTool.js +765 -0
  67. package/dist/integrations/GoogleWorkspaceTool.js.map +1 -0
  68. package/dist/integrations/HttpTool.d.ts +55 -0
  69. package/dist/integrations/HttpTool.d.ts.map +1 -0
  70. package/dist/integrations/HttpTool.js +209 -0
  71. package/dist/integrations/HttpTool.js.map +1 -0
  72. package/dist/integrations/MessagingTool.d.ts +136 -0
  73. package/dist/integrations/MessagingTool.d.ts.map +1 -0
  74. package/dist/integrations/MessagingTool.js +503 -0
  75. package/dist/integrations/MessagingTool.js.map +1 -0
  76. package/dist/integrations/SchedulerTool.d.ts +147 -0
  77. package/dist/integrations/SchedulerTool.d.ts.map +1 -0
  78. package/dist/integrations/SchedulerTool.js +471 -0
  79. package/dist/integrations/SchedulerTool.js.map +1 -0
  80. package/dist/integrations/WebhookTool.d.ts +97 -0
  81. package/dist/integrations/WebhookTool.d.ts.map +1 -0
  82. package/dist/integrations/WebhookTool.js +351 -0
  83. package/dist/integrations/WebhookTool.js.map +1 -0
  84. package/dist/integrations/index.d.ts +13 -0
  85. package/dist/integrations/index.d.ts.map +1 -0
  86. package/dist/integrations/index.js +60 -0
  87. package/dist/integrations/index.js.map +1 -0
  88. package/dist/llm/LLMProvider.d.ts +83 -0
  89. package/dist/llm/LLMProvider.d.ts.map +1 -0
  90. package/dist/llm/LLMProvider.js +370 -0
  91. package/dist/llm/LLMProvider.js.map +1 -0
  92. package/dist/llm/index.d.ts +5 -0
  93. package/dist/llm/index.d.ts.map +1 -0
  94. package/dist/llm/index.js +14 -0
  95. package/dist/llm/index.js.map +1 -0
  96. package/dist/payment/PaymentProvider.d.ts +157 -0
  97. package/dist/payment/PaymentProvider.d.ts.map +1 -0
  98. package/dist/payment/PaymentProvider.js +525 -0
  99. package/dist/payment/PaymentProvider.js.map +1 -0
  100. package/dist/payment/index.d.ts +5 -0
  101. package/dist/payment/index.d.ts.map +1 -0
  102. package/dist/payment/index.js +16 -0
  103. package/dist/payment/index.js.map +1 -0
  104. package/dist/plugin/PluginManager.d.ts +156 -0
  105. package/dist/plugin/PluginManager.d.ts.map +1 -0
  106. package/dist/plugin/PluginManager.js +288 -0
  107. package/dist/plugin/PluginManager.js.map +1 -0
  108. package/dist/plugin/index.d.ts +5 -0
  109. package/dist/plugin/index.d.ts.map +1 -0
  110. package/dist/plugin/index.js +10 -0
  111. package/dist/plugin/index.js.map +1 -0
  112. package/dist/runtime/AgentXRuntime.d.ts +90 -0
  113. package/dist/runtime/AgentXRuntime.d.ts.map +1 -0
  114. package/dist/runtime/AgentXRuntime.js +469 -0
  115. package/dist/runtime/AgentXRuntime.js.map +1 -0
  116. package/dist/security/SecurityManager.d.ts +245 -0
  117. package/dist/security/SecurityManager.d.ts.map +1 -0
  118. package/dist/security/SecurityManager.js +512 -0
  119. package/dist/security/SecurityManager.js.map +1 -0
  120. package/dist/security/index.d.ts +5 -0
  121. package/dist/security/index.d.ts.map +1 -0
  122. package/dist/security/index.js +14 -0
  123. package/dist/security/index.js.map +1 -0
  124. package/dist/tool/ToolRegistry.d.ts +58 -0
  125. package/dist/tool/ToolRegistry.d.ts.map +1 -0
  126. package/dist/tool/ToolRegistry.js +173 -0
  127. package/dist/tool/ToolRegistry.js.map +1 -0
  128. package/dist/tool/ToolValidator.d.ts +41 -0
  129. package/dist/tool/ToolValidator.d.ts.map +1 -0
  130. package/dist/tool/ToolValidator.js +158 -0
  131. package/dist/tool/ToolValidator.js.map +1 -0
  132. package/dist/tool/index.d.ts +6 -0
  133. package/dist/tool/index.d.ts.map +1 -0
  134. package/dist/tool/index.js +11 -0
  135. package/dist/tool/index.js.map +1 -0
  136. package/dist/transport/BaseTransport.d.ts +66 -0
  137. package/dist/transport/BaseTransport.d.ts.map +1 -0
  138. package/dist/transport/BaseTransport.js +103 -0
  139. package/dist/transport/BaseTransport.js.map +1 -0
  140. package/dist/transport/HttpTransport.d.ts +41 -0
  141. package/dist/transport/HttpTransport.d.ts.map +1 -0
  142. package/dist/transport/HttpTransport.js +160 -0
  143. package/dist/transport/HttpTransport.js.map +1 -0
  144. package/dist/transport/LocalTransport.d.ts +40 -0
  145. package/dist/transport/LocalTransport.d.ts.map +1 -0
  146. package/dist/transport/LocalTransport.js +157 -0
  147. package/dist/transport/LocalTransport.js.map +1 -0
  148. package/dist/transport/QueueTransport.d.ts +63 -0
  149. package/dist/transport/QueueTransport.d.ts.map +1 -0
  150. package/dist/transport/QueueTransport.js +194 -0
  151. package/dist/transport/QueueTransport.js.map +1 -0
  152. package/dist/transport/StdioTransport.d.ts +51 -0
  153. package/dist/transport/StdioTransport.d.ts.map +1 -0
  154. package/dist/transport/StdioTransport.js +216 -0
  155. package/dist/transport/StdioTransport.js.map +1 -0
  156. package/dist/transport/TransportFactory.d.ts +35 -0
  157. package/dist/transport/TransportFactory.d.ts.map +1 -0
  158. package/dist/transport/TransportFactory.js +100 -0
  159. package/dist/transport/TransportFactory.js.map +1 -0
  160. package/dist/transport/index.d.ts +10 -0
  161. package/dist/transport/index.d.ts.map +1 -0
  162. package/dist/transport/index.js +19 -0
  163. package/dist/transport/index.js.map +1 -0
  164. package/dist/types/agent.d.ts +66 -0
  165. package/dist/types/agent.d.ts.map +1 -0
  166. package/dist/types/agent.js +3 -0
  167. package/dist/types/agent.js.map +1 -0
  168. package/dist/types/config.d.ts +60 -0
  169. package/dist/types/config.d.ts.map +1 -0
  170. package/dist/types/config.js +6 -0
  171. package/dist/types/config.js.map +1 -0
  172. package/dist/types/credential.d.ts +38 -0
  173. package/dist/types/credential.d.ts.map +1 -0
  174. package/dist/types/credential.js +3 -0
  175. package/dist/types/credential.js.map +1 -0
  176. package/dist/types/error.d.ts +136 -0
  177. package/dist/types/error.d.ts.map +1 -0
  178. package/dist/types/error.js +223 -0
  179. package/dist/types/error.js.map +1 -0
  180. package/dist/types/index.d.ts +10 -0
  181. package/dist/types/index.d.ts.map +1 -0
  182. package/dist/types/index.js +27 -0
  183. package/dist/types/index.js.map +1 -0
  184. package/dist/types/llm.d.ts +43 -0
  185. package/dist/types/llm.d.ts.map +1 -0
  186. package/dist/types/llm.js +3 -0
  187. package/dist/types/llm.js.map +1 -0
  188. package/dist/types/payment.d.ts +129 -0
  189. package/dist/types/payment.d.ts.map +1 -0
  190. package/dist/types/payment.js +6 -0
  191. package/dist/types/payment.js.map +1 -0
  192. package/dist/types/runtime.d.ts +31 -0
  193. package/dist/types/runtime.d.ts.map +1 -0
  194. package/dist/types/runtime.js +3 -0
  195. package/dist/types/runtime.js.map +1 -0
  196. package/dist/types/tool.d.ts +72 -0
  197. package/dist/types/tool.d.ts.map +1 -0
  198. package/dist/types/tool.js +3 -0
  199. package/dist/types/tool.js.map +1 -0
  200. package/dist/types/transport.d.ts +53 -0
  201. package/dist/types/transport.d.ts.map +1 -0
  202. package/dist/types/transport.js +3 -0
  203. package/dist/types/transport.js.map +1 -0
  204. package/dist/types/workflow.d.ts +72 -0
  205. package/dist/types/workflow.d.ts.map +1 -0
  206. package/dist/types/workflow.js +6 -0
  207. package/dist/types/workflow.js.map +1 -0
  208. package/dist/utils/factory.d.ts +14 -0
  209. package/dist/utils/factory.d.ts.map +1 -0
  210. package/dist/utils/factory.js +146 -0
  211. package/dist/utils/factory.js.map +1 -0
  212. package/dist/workflow/StateManager.d.ts +93 -0
  213. package/dist/workflow/StateManager.d.ts.map +1 -0
  214. package/dist/workflow/StateManager.js +223 -0
  215. package/dist/workflow/StateManager.js.map +1 -0
  216. package/dist/workflow/WorkflowDefinition.d.ts +49 -0
  217. package/dist/workflow/WorkflowDefinition.d.ts.map +1 -0
  218. package/dist/workflow/WorkflowDefinition.js +264 -0
  219. package/dist/workflow/WorkflowDefinition.js.map +1 -0
  220. package/dist/workflow/WorkflowExecutor.d.ts +42 -0
  221. package/dist/workflow/WorkflowExecutor.d.ts.map +1 -0
  222. package/dist/workflow/WorkflowExecutor.js +372 -0
  223. package/dist/workflow/WorkflowExecutor.js.map +1 -0
  224. package/dist/workflow/index.d.ts +7 -0
  225. package/dist/workflow/index.d.ts.map +1 -0
  226. package/dist/workflow/index.js +17 -0
  227. package/dist/workflow/index.js.map +1 -0
  228. package/package.json +122 -0
@@ -0,0 +1,2225 @@
1
+ "use strict";
2
+ /**
3
+ * Interactive Setup for AgentX
4
+ * Provides a Next.js-like interactive CLI experience for project setup
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.ProjectGenerator = exports.SetupWizard = exports.InteractivePrompt = exports.AGENT_PERSONALITIES = exports.SECURITY_OPTIONS = exports.DEPLOYMENT_OPTIONS = exports.FEATURES = exports.INTEGRATIONS = exports.LLM_PROVIDERS = void 0;
41
+ const readline = __importStar(require("readline"));
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ // Available LLM providers
45
+ exports.LLM_PROVIDERS = [
46
+ { value: 'openai', label: 'OpenAI', description: 'GPT-4, GPT-3.5 (requires OPENAI_API_KEY)' },
47
+ { value: 'anthropic', label: 'Anthropic', description: 'Claude 3 (requires ANTHROPIC_API_KEY)' },
48
+ { value: 'local', label: 'Local Model', description: 'Ollama, LM Studio (no API key needed)' },
49
+ ];
50
+ // Available integrations
51
+ exports.INTEGRATIONS = [
52
+ { value: 'http', label: 'HTTP/REST', description: 'Make HTTP requests to APIs', selected: true },
53
+ { value: 'webhook', label: 'Webhooks', description: 'Receive and send webhooks' },
54
+ { value: 'scheduler', label: 'Scheduler', description: 'Cron jobs and scheduled tasks' },
55
+ { value: 'email', label: 'Email', description: 'Send emails via SMTP' },
56
+ { value: 'slack', label: 'Slack', description: 'Slack messaging integration' },
57
+ { value: 'whatsapp', label: 'WhatsApp', description: 'WhatsApp Business API' },
58
+ { value: 'telegram', label: 'Telegram', description: 'Telegram Bot API' },
59
+ { value: 'google-docs', label: 'Google Docs', description: 'Google Docs API' },
60
+ { value: 'google-sheets', label: 'Google Sheets', description: 'Google Sheets API' },
61
+ { value: 'google-drive', label: 'Google Drive', description: 'Google Drive API' },
62
+ { value: 'sql', label: 'SQL Database', description: 'PostgreSQL, MySQL, SQLite' },
63
+ { value: 'mongodb', label: 'MongoDB', description: 'MongoDB connector' },
64
+ { value: 'redis', label: 'Redis', description: 'Redis cache/store' },
65
+ { value: 's3', label: 'Amazon S3', description: 'S3 file storage' },
66
+ { value: 'filesystem', label: 'File System', description: 'Local file operations' },
67
+ ];
68
+ // Available features
69
+ exports.FEATURES = [
70
+ { value: 'workflows', label: 'Workflows', description: 'DAG-based workflow execution', selected: true },
71
+ { value: 'agents', label: 'AI Agents', description: 'Autonomous AI agents with tool use', selected: true },
72
+ { value: 'credentials', label: 'Credential Manager', description: 'Encrypted credential storage' },
73
+ { value: 'security', label: 'Security', description: 'RBAC, rate limiting, audit logs' },
74
+ { value: 'plugins', label: 'Plugin System', description: 'Extensible plugin architecture' },
75
+ { value: 'payments', label: 'Payments', description: 'Stripe, PayPal, M-Pesa integration' },
76
+ ];
77
+ // Deployment options
78
+ exports.DEPLOYMENT_OPTIONS = [
79
+ { value: 'docker', label: 'Docker', description: 'Containerized deployment with Dockerfile' },
80
+ { value: 'docker-compose', label: 'Docker Compose', description: 'Multi-service setup with databases' },
81
+ { value: 'kubernetes', label: 'Kubernetes', description: 'K8s manifests for production deployment' },
82
+ { value: 'railway', label: 'Railway', description: 'One-click Railway deployment' },
83
+ { value: 'vercel', label: 'Vercel', description: 'Serverless deployment on Vercel' },
84
+ { value: 'aws-lambda', label: 'AWS Lambda', description: 'Serverless functions on AWS' },
85
+ { value: 'systemd', label: 'Systemd Service', description: 'Linux service configuration' },
86
+ ];
87
+ // Security enhancements
88
+ exports.SECURITY_OPTIONS = [
89
+ { value: 'https-only', label: 'HTTPS Only', description: 'Force HTTPS and security headers', selected: true },
90
+ { value: 'api-keys', label: 'API Key Authentication', description: 'Secure API access with keys' },
91
+ { value: 'jwt', label: 'JWT Authentication', description: 'JSON Web Token authentication' },
92
+ { value: 'rate-limiting', label: 'Rate Limiting', description: 'Prevent API abuse and DoS attacks' },
93
+ { value: 'input-validation', label: 'Input Validation', description: 'Strict input sanitization' },
94
+ { value: 'audit-logging', label: 'Audit Logging', description: 'Security event logging' },
95
+ { value: 'secrets-manager', label: 'Secrets Manager', description: 'External secrets management' },
96
+ ];
97
+ // Agent personality presets
98
+ exports.AGENT_PERSONALITIES = [
99
+ { value: 'helpful', label: 'Helpful Assistant', description: 'Friendly and supportive' },
100
+ { value: 'professional', label: 'Professional', description: 'Formal and business-focused' },
101
+ { value: 'concise', label: 'Concise', description: 'Brief and to-the-point' },
102
+ { value: 'creative', label: 'Creative', description: 'Imaginative and exploratory' },
103
+ { value: 'custom', label: 'Custom', description: 'Define your own personality' },
104
+ ];
105
+ /**
106
+ * Interactive prompt utilities
107
+ */
108
+ class InteractivePrompt {
109
+ rl;
110
+ constructor() {
111
+ this.rl = readline.createInterface({
112
+ input: process.stdin,
113
+ output: process.stdout,
114
+ });
115
+ }
116
+ async text(question, defaultValue) {
117
+ const prompt = defaultValue ? `${question} (${defaultValue}): ` : `${question}: `;
118
+ return new Promise((resolve) => {
119
+ this.rl.question(prompt, (answer) => {
120
+ resolve(answer.trim() || defaultValue || '');
121
+ });
122
+ });
123
+ }
124
+ async confirm(question, defaultValue = true) {
125
+ const hint = defaultValue ? '(Y/n)' : '(y/N)';
126
+ return new Promise((resolve) => {
127
+ this.rl.question(`${question} ${hint}: `, (answer) => {
128
+ const normalized = answer.trim().toLowerCase();
129
+ if (normalized === '')
130
+ resolve(defaultValue);
131
+ else
132
+ resolve(normalized === 'y' || normalized === 'yes');
133
+ });
134
+ });
135
+ }
136
+ async select(question, choices) {
137
+ console.log(`\n${question}`);
138
+ choices.forEach((choice, index) => {
139
+ const desc = choice.description ? ` - ${choice.description}` : '';
140
+ console.log(` ${index + 1}. ${choice.label}${desc}`);
141
+ });
142
+ return new Promise((resolve) => {
143
+ const ask = () => {
144
+ this.rl.question('\nEnter number: ', (answer) => {
145
+ const index = parseInt(answer.trim(), 10) - 1;
146
+ if (index >= 0 && index < choices.length) {
147
+ resolve(choices[index].value);
148
+ }
149
+ else {
150
+ console.log('Invalid selection. Please try again.');
151
+ ask();
152
+ }
153
+ });
154
+ };
155
+ ask();
156
+ });
157
+ }
158
+ async multiSelect(question, choices) {
159
+ console.log(`\n${question}`);
160
+ console.log('(Enter numbers separated by commas, or "all" for all, "none" to skip)\n');
161
+ choices.forEach((choice, index) => {
162
+ const selected = choice.selected ? '✓' : ' ';
163
+ const desc = choice.description ? ` - ${choice.description}` : '';
164
+ console.log(` [${selected}] ${index + 1}. ${choice.label}${desc}`);
165
+ });
166
+ return new Promise((resolve) => {
167
+ const ask = () => {
168
+ this.rl.question('\nEnter numbers (e.g., 1,2,3) or "all"/"none": ', (answer) => {
169
+ const normalized = answer.trim().toLowerCase();
170
+ if (normalized === 'all') {
171
+ resolve(choices.map(c => c.value));
172
+ return;
173
+ }
174
+ if (normalized === '' || normalized === 'none') {
175
+ resolve(choices.filter(c => c.selected).map(c => c.value));
176
+ return;
177
+ }
178
+ const indices = normalized.split(',').map(s => parseInt(s.trim(), 10) - 1);
179
+ const valid = indices.every(i => i >= 0 && i < choices.length);
180
+ if (valid) {
181
+ resolve(indices.map(i => choices[i].value));
182
+ }
183
+ else {
184
+ console.log('Invalid selection. Please try again.');
185
+ ask();
186
+ }
187
+ });
188
+ };
189
+ ask();
190
+ });
191
+ }
192
+ close() {
193
+ this.rl.close();
194
+ }
195
+ }
196
+ exports.InteractivePrompt = InteractivePrompt;
197
+ /**
198
+ * Setup Wizard - orchestrates the interactive project setup
199
+ */
200
+ class SetupWizard {
201
+ prompt;
202
+ constructor() {
203
+ this.prompt = new InteractivePrompt();
204
+ }
205
+ /**
206
+ * Run the interactive setup wizard
207
+ */
208
+ async run(projectName) {
209
+ this.printBanner();
210
+ // Project name
211
+ const name = projectName || await this.prompt.text('What is your project named?', 'my-agentx-app');
212
+ // LLM Providers
213
+ console.log('\n📦 LLM Providers');
214
+ const llmProviders = await this.prompt.multiSelect('Which LLM providers would you like to use?', exports.LLM_PROVIDERS);
215
+ // Integrations
216
+ console.log('\n🔌 Integrations');
217
+ const integrations = await this.prompt.multiSelect('Which integrations would you like to include?', exports.INTEGRATIONS);
218
+ // Features
219
+ console.log('\n⚡ Features');
220
+ const features = await this.prompt.multiSelect('Which features would you like to enable?', exports.FEATURES);
221
+ // Agent personality
222
+ console.log('\n🤖 Agent Configuration');
223
+ let agentPersonality = await this.prompt.select('Choose a default agent personality:', exports.AGENT_PERSONALITIES);
224
+ if (agentPersonality === 'custom') {
225
+ agentPersonality = await this.prompt.text('Describe your agent personality', 'You are a helpful AI assistant.');
226
+ }
227
+ // TypeScript
228
+ const typescript = await this.prompt.confirm('Use TypeScript?', true);
229
+ // Deployment options
230
+ console.log('\n🚀 Deployment');
231
+ const deployment = await this.prompt.multiSelect('How would you like to deploy your application?', exports.DEPLOYMENT_OPTIONS);
232
+ // Security options
233
+ console.log('\n🔒 Security');
234
+ const security = await this.prompt.multiSelect('Which security features would you like to enable?', exports.SECURITY_OPTIONS);
235
+ // Git
236
+ const git = await this.prompt.confirm('Initialize a git repository?', true);
237
+ this.prompt.close();
238
+ return {
239
+ projectName: name,
240
+ llmProviders,
241
+ integrations,
242
+ features,
243
+ agentPersonality,
244
+ typescript,
245
+ git,
246
+ deployment,
247
+ security,
248
+ };
249
+ }
250
+ printBanner() {
251
+ console.log(`
252
+ ╔═══════════════════════════════════════════════════════════╗
253
+ ║ ║
254
+ ║ █████╗ ██████╗ ███████╗███╗ ██╗████████╗██╗ ██╗ ║
255
+ ║ ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝╚██╗██╔╝ ║
256
+ ║ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ╚███╔╝ ║
257
+ ║ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██╔██╗ ║
258
+ ║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ██╔╝ ██╗ ║
259
+ ║ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ║
260
+ ║ ║
261
+ ║ Production-Grade AI Agent Framework ║
262
+ ║ ║
263
+ ╚═══════════════════════════════════════════════════════════╝
264
+ `);
265
+ }
266
+ }
267
+ exports.SetupWizard = SetupWizard;
268
+ /**
269
+ * Project Generator - creates project files based on setup options
270
+ */
271
+ class ProjectGenerator {
272
+ /**
273
+ * Generate project from setup options
274
+ */
275
+ async generate(options, targetDir) {
276
+ const projectDir = path.join(targetDir, options.projectName);
277
+ // Create directories
278
+ this.createDirectories(projectDir, options);
279
+ // Generate files
280
+ await this.generatePackageJson(projectDir, options);
281
+ await this.generateTsConfig(projectDir, options);
282
+ await this.generateConfig(projectDir, options);
283
+ await this.generateEnvFile(projectDir, options);
284
+ await this.generateEntryPoint(projectDir, options);
285
+ await this.generateExampleAgent(projectDir, options);
286
+ // Generate payment examples if payments feature is selected
287
+ if (options.features.includes('payments')) {
288
+ await this.generatePaymentExamples(projectDir, options);
289
+ }
290
+ // Generate deployment files
291
+ await this.generateDeploymentFiles(projectDir, options);
292
+ // Generate security files
293
+ await this.generateSecurityFiles(projectDir, options);
294
+ if (options.git) {
295
+ await this.generateGitIgnore(projectDir);
296
+ }
297
+ console.log(`\n✅ Project created at ${projectDir}`);
298
+ this.printNextSteps(options);
299
+ }
300
+ createDirectories(projectDir, options) {
301
+ const dirs = [
302
+ projectDir,
303
+ path.join(projectDir, 'src'),
304
+ path.join(projectDir, 'src', 'agents'),
305
+ ];
306
+ if (options.features.includes('workflows')) {
307
+ dirs.push(path.join(projectDir, 'src', 'workflows'));
308
+ }
309
+ if (options.integrations.length > 0) {
310
+ dirs.push(path.join(projectDir, 'src', 'tools'));
311
+ }
312
+ for (const dir of dirs) {
313
+ if (!fs.existsSync(dir)) {
314
+ fs.mkdirSync(dir, { recursive: true });
315
+ }
316
+ }
317
+ }
318
+ async generatePackageJson(projectDir, options) {
319
+ const dependencies = {
320
+ agentx: '^0.1.0',
321
+ };
322
+ const devDependencies = {
323
+ jest: '^29.0.0',
324
+ };
325
+ // Add TypeScript dependencies
326
+ if (options.typescript) {
327
+ devDependencies['@types/node'] = '^20.0.0';
328
+ devDependencies['typescript'] = '^5.0.0';
329
+ devDependencies['ts-node'] = '^10.0.0';
330
+ devDependencies['@types/jest'] = '^29.0.0';
331
+ }
332
+ // Add security dependencies
333
+ if (options.security.includes('input-validation')) {
334
+ dependencies['joi'] = '^17.11.0';
335
+ if (options.typescript) {
336
+ devDependencies['@types/joi'] = '^17.2.0';
337
+ }
338
+ }
339
+ if (options.security.includes('jwt')) {
340
+ dependencies['jsonwebtoken'] = '^9.0.2';
341
+ if (options.typescript) {
342
+ devDependencies['@types/jsonwebtoken'] = '^9.0.5';
343
+ }
344
+ }
345
+ if (options.security.includes('rate-limiting')) {
346
+ dependencies['express-rate-limit'] = '^7.1.5';
347
+ }
348
+ // Add deployment dependencies
349
+ if (options.deployment.includes('aws-lambda')) {
350
+ dependencies['aws-lambda'] = '^1.0.7';
351
+ if (options.typescript) {
352
+ devDependencies['@types/aws-lambda'] = '^8.10.130';
353
+ }
354
+ }
355
+ // Add integration-specific dependencies
356
+ if (options.integrations.includes('email')) {
357
+ dependencies['nodemailer'] = '^6.9.7';
358
+ if (options.typescript) {
359
+ devDependencies['@types/nodemailer'] = '^6.4.14';
360
+ }
361
+ }
362
+ const scripts = {
363
+ test: 'jest',
364
+ };
365
+ if (options.typescript) {
366
+ scripts.build = 'tsc';
367
+ scripts.start = 'node dist/index.js';
368
+ scripts.dev = 'ts-node src/index.ts';
369
+ scripts['type-check'] = 'tsc --noEmit';
370
+ }
371
+ else {
372
+ scripts.start = 'node src/index.js';
373
+ scripts.dev = 'nodemon src/index.js';
374
+ devDependencies.nodemon = '^3.0.2';
375
+ }
376
+ // Add deployment scripts
377
+ if (options.deployment.includes('docker')) {
378
+ scripts['docker:build'] = `docker build -t ${options.projectName} .`;
379
+ scripts['docker:run'] = `docker run -p 3000:3000 ${options.projectName}`;
380
+ }
381
+ if (options.deployment.includes('docker-compose')) {
382
+ scripts['compose:up'] = 'docker-compose up -d';
383
+ scripts['compose:down'] = 'docker-compose down';
384
+ scripts['compose:logs'] = 'docker-compose logs -f';
385
+ }
386
+ if (options.deployment.includes('kubernetes')) {
387
+ scripts['k8s:deploy'] = 'kubectl apply -f k8s/';
388
+ scripts['k8s:delete'] = 'kubectl delete -f k8s/';
389
+ }
390
+ // Add security scripts
391
+ if (options.security.length > 0) {
392
+ scripts['security:audit'] = 'npm audit';
393
+ scripts['security:fix'] = 'npm audit fix';
394
+ }
395
+ const pkg = {
396
+ name: options.projectName,
397
+ version: '1.0.0',
398
+ description: 'AgentX AI Agent Project',
399
+ main: options.typescript ? 'dist/index.js' : 'src/index.js',
400
+ scripts,
401
+ dependencies,
402
+ devDependencies,
403
+ engines: {
404
+ node: '>=18.0.0',
405
+ },
406
+ keywords: [
407
+ 'agentx',
408
+ 'ai',
409
+ 'agent',
410
+ 'automation',
411
+ ...options.integrations,
412
+ ...options.features,
413
+ ],
414
+ };
415
+ fs.writeFileSync(path.join(projectDir, 'package.json'), JSON.stringify(pkg, null, 2));
416
+ }
417
+ async generateTsConfig(projectDir, options) {
418
+ if (!options.typescript)
419
+ return;
420
+ const tsconfig = {
421
+ compilerOptions: {
422
+ target: 'ES2020',
423
+ module: 'commonjs',
424
+ lib: ['ES2020'],
425
+ outDir: './dist',
426
+ rootDir: './src',
427
+ strict: true,
428
+ esModuleInterop: true,
429
+ skipLibCheck: true,
430
+ forceConsistentCasingInFileNames: true,
431
+ declaration: true,
432
+ },
433
+ include: ['src/**/*'],
434
+ exclude: ['node_modules', 'dist'],
435
+ };
436
+ fs.writeFileSync(path.join(projectDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2));
437
+ }
438
+ async generateConfig(projectDir, options) {
439
+ const ext = options.typescript ? 'ts' : 'js';
440
+ const exportKeyword = options.typescript ? 'export default' : 'module.exports =';
441
+ const llmConfig = this.generateLLMConfig(options);
442
+ const integrationsConfig = this.generateIntegrationsConfig(options);
443
+ const content = `/**
444
+ * AgentX Configuration
445
+ * Generated by create-agentx
446
+ */
447
+ ${exportKeyword} {
448
+ runtime: {
449
+ name: '${options.projectName}',
450
+ version: '1.0.0',
451
+ },
452
+ llm: {
453
+ defaultProvider: '${options.llmProviders[0] || 'openai'}',
454
+ providers: {
455
+ ${llmConfig}
456
+ },
457
+ },
458
+ integrations: {
459
+ ${integrationsConfig}
460
+ },
461
+ features: {
462
+ workflows: ${options.features.includes('workflows')},
463
+ agents: ${options.features.includes('agents')},
464
+ credentials: ${options.features.includes('credentials')},
465
+ security: ${options.features.includes('security')},
466
+ plugins: ${options.features.includes('plugins')},
467
+ payments: ${options.features.includes('payments')},
468
+ },
469
+ agent: {
470
+ defaultPersonality: '${this.escapeString(options.agentPersonality)}',
471
+ },
472
+ };
473
+ `;
474
+ fs.writeFileSync(path.join(projectDir, 'src', `config.${ext}`), content);
475
+ }
476
+ generateLLMConfig(options) {
477
+ const configs = [];
478
+ if (options.llmProviders.includes('openai')) {
479
+ configs.push(` openai: {
480
+ apiKey: process.env.OPENAI_API_KEY,
481
+ model: 'gpt-4',
482
+ }`);
483
+ }
484
+ if (options.llmProviders.includes('anthropic')) {
485
+ configs.push(` anthropic: {
486
+ apiKey: process.env.ANTHROPIC_API_KEY,
487
+ model: 'claude-3-opus-20240229',
488
+ }`);
489
+ }
490
+ if (options.llmProviders.includes('local')) {
491
+ configs.push(` local: {
492
+ baseUrl: process.env.LOCAL_LLM_URL || 'http://localhost:11434',
493
+ model: 'llama2',
494
+ }`);
495
+ }
496
+ return configs.join(',\n');
497
+ }
498
+ generateIntegrationsConfig(options) {
499
+ const configs = [];
500
+ for (const integration of options.integrations) {
501
+ configs.push(` '${integration}': { enabled: true }`);
502
+ }
503
+ return configs.join(',\n');
504
+ }
505
+ async generateEnvFile(projectDir, options) {
506
+ const lines = ['# AgentX Environment Variables', '# Generated based on your selections', ''];
507
+ // Core application settings
508
+ lines.push('# Application Configuration');
509
+ lines.push(`NODE_ENV=development`);
510
+ lines.push(`PORT=3000`);
511
+ lines.push('');
512
+ // LLM Provider configurations (only selected ones)
513
+ if (options.llmProviders.includes('openai')) {
514
+ lines.push('# OpenAI Configuration');
515
+ lines.push('OPENAI_API_KEY=your-openai-api-key-here');
516
+ lines.push('# Optional: OPENAI_ORG_ID=your-org-id');
517
+ lines.push('');
518
+ }
519
+ if (options.llmProviders.includes('anthropic')) {
520
+ lines.push('# Anthropic Configuration');
521
+ lines.push('ANTHROPIC_API_KEY=your-anthropic-api-key-here');
522
+ lines.push('');
523
+ }
524
+ if (options.llmProviders.includes('local')) {
525
+ lines.push('# Local LLM Configuration');
526
+ lines.push('LOCAL_LLM_URL=http://localhost:11434');
527
+ lines.push('# For Ollama: LOCAL_LLM_MODEL=llama2');
528
+ lines.push('');
529
+ }
530
+ // Integration-specific env vars (only selected ones)
531
+ if (options.integrations.includes('email')) {
532
+ lines.push('# Email Configuration (SMTP)');
533
+ lines.push('SMTP_HOST=smtp.gmail.com');
534
+ lines.push('SMTP_PORT=587');
535
+ lines.push('SMTP_SECURE=false');
536
+ lines.push('SMTP_USER=your-email@gmail.com');
537
+ lines.push('SMTP_PASS=your-app-password');
538
+ lines.push('');
539
+ }
540
+ if (options.integrations.includes('slack')) {
541
+ lines.push('# Slack Configuration');
542
+ lines.push('SLACK_BOT_TOKEN=xoxb-your-bot-token');
543
+ lines.push('SLACK_SIGNING_SECRET=your-signing-secret');
544
+ lines.push('');
545
+ }
546
+ if (options.integrations.includes('whatsapp')) {
547
+ lines.push('# WhatsApp Business API');
548
+ lines.push('WHATSAPP_TOKEN=your-whatsapp-token');
549
+ lines.push('WHATSAPP_PHONE_ID=your-phone-number-id');
550
+ lines.push('WHATSAPP_VERIFY_TOKEN=your-verify-token');
551
+ lines.push('');
552
+ }
553
+ if (options.integrations.includes('telegram')) {
554
+ lines.push('# Telegram Bot Configuration');
555
+ lines.push('TELEGRAM_BOT_TOKEN=your-bot-token');
556
+ lines.push('');
557
+ }
558
+ if (options.integrations.includes('google-docs') ||
559
+ options.integrations.includes('google-sheets') ||
560
+ options.integrations.includes('google-drive')) {
561
+ lines.push('# Google Workspace Configuration');
562
+ lines.push('GOOGLE_CLIENT_ID=your-client-id');
563
+ lines.push('GOOGLE_CLIENT_SECRET=your-client-secret');
564
+ lines.push('GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback');
565
+ lines.push('# Service Account (alternative to OAuth)');
566
+ lines.push('# GOOGLE_SERVICE_ACCOUNT_KEY=path/to/service-account.json');
567
+ lines.push('');
568
+ }
569
+ if (options.integrations.includes('sql')) {
570
+ lines.push('# Database Configuration');
571
+ lines.push('DATABASE_URL=postgresql://user:password@localhost:5432/agentx_db');
572
+ lines.push('# Alternative formats:');
573
+ lines.push('# DATABASE_URL=mysql://user:password@localhost:3306/agentx_db');
574
+ lines.push('# DATABASE_URL=sqlite:./data/agentx.db');
575
+ lines.push('');
576
+ }
577
+ if (options.integrations.includes('mongodb')) {
578
+ lines.push('# MongoDB Configuration');
579
+ lines.push('MONGODB_URI=mongodb://localhost:27017/agentx');
580
+ lines.push('# For MongoDB Atlas:');
581
+ lines.push('# MONGODB_URI=mongodb+srv://user:password@cluster.mongodb.net/agentx');
582
+ lines.push('');
583
+ }
584
+ if (options.integrations.includes('redis')) {
585
+ lines.push('# Redis Configuration');
586
+ lines.push('REDIS_URL=redis://localhost:6379');
587
+ lines.push('# For Redis Cloud:');
588
+ lines.push('# REDIS_URL=redis://user:password@host:port');
589
+ lines.push('');
590
+ }
591
+ if (options.integrations.includes('s3')) {
592
+ lines.push('# AWS S3 Configuration');
593
+ lines.push('AWS_ACCESS_KEY_ID=your-access-key-id');
594
+ lines.push('AWS_SECRET_ACCESS_KEY=your-secret-access-key');
595
+ lines.push('AWS_REGION=us-east-1');
596
+ lines.push('S3_BUCKET_NAME=your-bucket-name');
597
+ lines.push('');
598
+ }
599
+ // Payment integrations (only if selected)
600
+ if (options.features.includes('payments')) {
601
+ lines.push('# Payment Configuration');
602
+ lines.push('# Stripe');
603
+ lines.push('STRIPE_SECRET_KEY=sk_test_your-stripe-secret-key');
604
+ lines.push('STRIPE_PUBLISHABLE_KEY=pk_test_your-stripe-publishable-key');
605
+ lines.push('STRIPE_WEBHOOK_SECRET=whsec_your-webhook-secret');
606
+ lines.push('');
607
+ lines.push('# PayPal Configuration');
608
+ lines.push('PAYPAL_CLIENT_ID=your-paypal-client-id');
609
+ lines.push('PAYPAL_CLIENT_SECRET=your-paypal-client-secret');
610
+ lines.push('PAYPAL_MODE=sandbox # or live');
611
+ lines.push('');
612
+ lines.push('# M-Pesa Configuration (Safaricom)');
613
+ lines.push('MPESA_CONSUMER_KEY=your-mpesa-consumer-key');
614
+ lines.push('MPESA_CONSUMER_SECRET=your-mpesa-consumer-secret');
615
+ lines.push('MPESA_SHORTCODE=174379 # Your business shortcode');
616
+ lines.push('MPESA_PASSKEY=your-mpesa-passkey');
617
+ lines.push('MPESA_ENVIRONMENT=sandbox # or production');
618
+ lines.push('MPESA_CALLBACK_URL=https://yourdomain.com/api/mpesa/callback');
619
+ lines.push('MPESA_WEBHOOK_URL=https://yourdomain.com/api/mpesa/webhook');
620
+ lines.push('');
621
+ }
622
+ // Security configurations (only if selected)
623
+ if (options.security.includes('jwt')) {
624
+ lines.push('# JWT Configuration');
625
+ lines.push('JWT_SECRET=your-super-secret-jwt-key-change-this-in-production');
626
+ lines.push('JWT_EXPIRES_IN=24h');
627
+ lines.push('');
628
+ }
629
+ if (options.security.includes('api-keys')) {
630
+ lines.push('# API Key Configuration');
631
+ lines.push('API_KEY_HEADER=X-API-Key');
632
+ lines.push('MASTER_API_KEY=your-master-api-key-change-this');
633
+ lines.push('');
634
+ }
635
+ if (options.security.includes('rate-limiting')) {
636
+ lines.push('# Rate Limiting Configuration');
637
+ lines.push('RATE_LIMIT_WINDOW_MS=900000 # 15 minutes');
638
+ lines.push('RATE_LIMIT_MAX_REQUESTS=100');
639
+ lines.push('');
640
+ }
641
+ if (options.security.includes('secrets-manager')) {
642
+ lines.push('# External Secrets Manager');
643
+ lines.push('# AWS Secrets Manager');
644
+ lines.push('# AWS_SECRETS_REGION=us-east-1');
645
+ lines.push('# HashiCorp Vault');
646
+ lines.push('# VAULT_ADDR=https://vault.example.com');
647
+ lines.push('# VAULT_TOKEN=your-vault-token');
648
+ lines.push('');
649
+ }
650
+ // Credential manager (only if selected)
651
+ if (options.features.includes('credentials')) {
652
+ lines.push('# Credential Manager');
653
+ lines.push('CREDENTIAL_ENCRYPTION_KEY=your-32-character-encryption-key-here');
654
+ lines.push('');
655
+ }
656
+ // Deployment-specific variables
657
+ if (options.deployment.includes('docker') || options.deployment.includes('docker-compose')) {
658
+ lines.push('# Docker Configuration');
659
+ lines.push('DOCKER_REGISTRY=your-registry.com');
660
+ lines.push('IMAGE_TAG=latest');
661
+ lines.push('');
662
+ }
663
+ if (options.deployment.includes('kubernetes')) {
664
+ lines.push('# Kubernetes Configuration');
665
+ lines.push('K8S_NAMESPACE=agentx');
666
+ lines.push('K8S_SERVICE_ACCOUNT=agentx-service');
667
+ lines.push('');
668
+ }
669
+ // Monitoring and logging (recommended for production)
670
+ if (options.security.includes('audit-logging') || options.deployment.length > 0) {
671
+ lines.push('# Monitoring & Logging');
672
+ lines.push('LOG_LEVEL=info # debug, info, warn, error');
673
+ lines.push('# SENTRY_DSN=your-sentry-dsn-for-error-tracking');
674
+ lines.push('# DATADOG_API_KEY=your-datadog-api-key');
675
+ lines.push('');
676
+ }
677
+ fs.writeFileSync(path.join(projectDir, '.env.example'), lines.join('\n'));
678
+ // Create actual .env with placeholder values
679
+ const envContent = lines
680
+ .map(line => {
681
+ if (line.includes('=') && !line.startsWith('#')) {
682
+ // Keep the structure but make values obviously placeholder
683
+ return line.replace(/=.*/, '=CHANGE_ME');
684
+ }
685
+ return line;
686
+ })
687
+ .join('\n');
688
+ fs.writeFileSync(path.join(projectDir, '.env'), envContent);
689
+ }
690
+ async generateEntryPoint(projectDir, options) {
691
+ const ext = options.typescript ? 'ts' : 'js';
692
+ const importStyle = options.typescript
693
+ ? "import { AgentXRuntime } from 'agentx';\nimport config from './config';"
694
+ : "const { AgentXRuntime } = require('agentx');\nconst config = require('./config');";
695
+ const content = `/**
696
+ * AgentX Application Entry Point
697
+ * Generated by create-agentx
698
+ */
699
+ ${importStyle}
700
+
701
+ async function main() {
702
+ console.log('🚀 Starting ${options.projectName}...');
703
+
704
+ const runtime = new AgentXRuntime(config);
705
+ await runtime.start();
706
+
707
+ console.log('✅ AgentX runtime started successfully');
708
+ console.log('📦 Loaded providers:', ${options.typescript ? 'config.llm.providers' : 'Object.keys(config.llm.providers)'});
709
+
710
+ // Graceful shutdown
711
+ process.on('SIGINT', async () => {
712
+ console.log('\\n🛑 Shutting down...');
713
+ await runtime.stop();
714
+ process.exit(0);
715
+ });
716
+ }
717
+
718
+ main().catch((error) => {
719
+ console.error('❌ Failed to start:', error);
720
+ process.exit(1);
721
+ });
722
+ `;
723
+ fs.writeFileSync(path.join(projectDir, 'src', `index.${ext}`), content);
724
+ }
725
+ async generateExampleAgent(projectDir, options) {
726
+ if (!options.features.includes('agents'))
727
+ return;
728
+ const ext = options.typescript ? 'ts' : 'js';
729
+ const exportStyle = options.typescript ? 'export const' : 'module.exports.myAgent =';
730
+ const typeAnnotation = options.typescript ? ': AgentConfig' : '';
731
+ const importLine = options.typescript
732
+ ? "import { AgentConfig } from 'agentx';\n\n"
733
+ : '';
734
+ const personality = this.getPersonalityPrompt(options.agentPersonality);
735
+ const content = `/**
736
+ * Example AI Agent
737
+ * Generated by create-agentx
738
+ */
739
+ ${importLine}${exportStyle} myAgent${typeAnnotation} = {
740
+ name: 'my-agent',
741
+ description: 'Your custom AI agent',
742
+ llmProvider: '${options.llmProviders[0] || 'openai'}',
743
+ model: '${this.getDefaultModel(options.llmProviders[0])}',
744
+ systemPrompt: \`${personality}\`,
745
+ allowedTools: [${options.integrations.map(i => `'${i}'`).join(', ')}],
746
+ maxIterations: 10,
747
+ temperature: 0.7,
748
+ };
749
+ `;
750
+ fs.writeFileSync(path.join(projectDir, 'src', 'agents', `myAgent.${ext}`), content);
751
+ }
752
+ async generateGitIgnore(projectDir) {
753
+ const content = `# Dependencies
754
+ node_modules/
755
+
756
+ # Build output
757
+ dist/
758
+
759
+ # Environment
760
+ .env
761
+ .env.local
762
+ .env.production
763
+
764
+ # IDE
765
+ .idea/
766
+ .vscode/
767
+ *.swp
768
+ *.swo
769
+
770
+ # OS
771
+ .DS_Store
772
+ Thumbs.db
773
+
774
+ # Logs
775
+ *.log
776
+ npm-debug.log*
777
+ logs/
778
+
779
+ # Test coverage
780
+ coverage/
781
+
782
+ # Runtime data
783
+ pids/
784
+ *.pid
785
+ *.seed
786
+ *.pid.lock
787
+
788
+ # Docker
789
+ .dockerignore
790
+
791
+ # Secrets
792
+ secrets/
793
+ *.pem
794
+ *.key
795
+ service-account.json
796
+ `;
797
+ fs.writeFileSync(path.join(projectDir, '.gitignore'), content);
798
+ }
799
+ /**
800
+ * Generate deployment files based on selected options
801
+ */
802
+ async generateDeploymentFiles(projectDir, options) {
803
+ if (options.deployment.includes('docker')) {
804
+ await this.generateDockerfile(projectDir, options);
805
+ await this.generateDockerIgnore(projectDir);
806
+ }
807
+ if (options.deployment.includes('docker-compose')) {
808
+ await this.generateDockerCompose(projectDir, options);
809
+ }
810
+ if (options.deployment.includes('kubernetes')) {
811
+ await this.generateKubernetesManifests(projectDir, options);
812
+ }
813
+ if (options.deployment.includes('railway')) {
814
+ await this.generateRailwayConfig(projectDir, options);
815
+ }
816
+ if (options.deployment.includes('vercel')) {
817
+ await this.generateVercelConfig(projectDir, options);
818
+ }
819
+ if (options.deployment.includes('aws-lambda')) {
820
+ await this.generateLambdaConfig(projectDir, options);
821
+ }
822
+ if (options.deployment.includes('systemd')) {
823
+ await this.generateSystemdService(projectDir, options);
824
+ }
825
+ }
826
+ async generateDockerfile(projectDir, options) {
827
+ const content = `# Multi-stage Docker build for ${options.projectName}
828
+ FROM node:18-alpine AS builder
829
+
830
+ WORKDIR /app
831
+
832
+ # Copy package files
833
+ COPY package*.json ./
834
+ ${options.typescript ? 'COPY tsconfig.json ./' : ''}
835
+
836
+ # Install dependencies
837
+ RUN npm ci --only=production && npm cache clean --force
838
+
839
+ # Copy source code
840
+ COPY src/ ./src/
841
+
842
+ # Build application
843
+ ${options.typescript ? 'RUN npm run build' : ''}
844
+
845
+ # Production stage
846
+ FROM node:18-alpine AS production
847
+
848
+ # Create non-root user
849
+ RUN addgroup -g 1001 -S agentx && \\
850
+ adduser -S agentx -u 1001
851
+
852
+ WORKDIR /app
853
+
854
+ # Copy built application
855
+ COPY --from=builder /app/node_modules ./node_modules
856
+ ${options.typescript ?
857
+ 'COPY --from=builder /app/dist ./dist' :
858
+ 'COPY --from=builder /app/src ./src'}
859
+ COPY --from=builder /app/package*.json ./
860
+
861
+ # Set ownership
862
+ RUN chown -R agentx:agentx /app
863
+ USER agentx
864
+
865
+ # Health check
866
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\
867
+ CMD node -e "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"
868
+
869
+ # Expose port
870
+ EXPOSE 3000
871
+
872
+ # Start application
873
+ CMD ["npm", "start"]
874
+ `;
875
+ fs.writeFileSync(path.join(projectDir, 'Dockerfile'), content);
876
+ }
877
+ async generateDockerIgnore(projectDir) {
878
+ const content = `node_modules
879
+ npm-debug.log
880
+ .env
881
+ .env.local
882
+ .git
883
+ .gitignore
884
+ README.md
885
+ Dockerfile
886
+ .dockerignore
887
+ coverage
888
+ .nyc_output
889
+ `;
890
+ fs.writeFileSync(path.join(projectDir, '.dockerignore'), content);
891
+ }
892
+ async generateDockerCompose(projectDir, options) {
893
+ const services = [];
894
+ // Main application service
895
+ services.push(` ${options.projectName}:
896
+ build: .
897
+ ports:
898
+ - "3000:3000"
899
+ environment:
900
+ - NODE_ENV=production
901
+ env_file:
902
+ - .env
903
+ depends_on:${options.integrations.includes('sql') ? '\n - postgres' : ''}${options.integrations.includes('redis') ? '\n - redis' : ''}${options.integrations.includes('mongodb') ? '\n - mongodb' : ''}
904
+ restart: unless-stopped
905
+ networks:
906
+ - agentx-network`);
907
+ // Add database services based on integrations
908
+ if (options.integrations.includes('sql')) {
909
+ services.push(` postgres:
910
+ image: postgres:15-alpine
911
+ environment:
912
+ POSTGRES_DB: agentx
913
+ POSTGRES_USER: agentx
914
+ POSTGRES_PASSWORD: agentx_password
915
+ volumes:
916
+ - postgres_data:/var/lib/postgresql/data
917
+ ports:
918
+ - "5432:5432"
919
+ restart: unless-stopped
920
+ networks:
921
+ - agentx-network`);
922
+ }
923
+ if (options.integrations.includes('redis')) {
924
+ services.push(` redis:
925
+ image: redis:7-alpine
926
+ ports:
927
+ - "6379:6379"
928
+ volumes:
929
+ - redis_data:/data
930
+ restart: unless-stopped
931
+ networks:
932
+ - agentx-network`);
933
+ }
934
+ if (options.integrations.includes('mongodb')) {
935
+ services.push(` mongodb:
936
+ image: mongo:6
937
+ environment:
938
+ MONGO_INITDB_ROOT_USERNAME: agentx
939
+ MONGO_INITDB_ROOT_PASSWORD: agentx_password
940
+ volumes:
941
+ - mongodb_data:/data/db
942
+ ports:
943
+ - "27017:27017"
944
+ restart: unless-stopped
945
+ networks:
946
+ - agentx-network`);
947
+ }
948
+ // Add monitoring if security features are enabled
949
+ if (options.security.includes('audit-logging')) {
950
+ services.push(` # Uncomment for monitoring
951
+ # grafana:
952
+ # image: grafana/grafana:latest
953
+ # ports:
954
+ # - "3001:3000"
955
+ # environment:
956
+ # - GF_SECURITY_ADMIN_PASSWORD=admin
957
+ # networks:
958
+ # - agentx-network`);
959
+ }
960
+ const volumes = [];
961
+ if (options.integrations.includes('sql'))
962
+ volumes.push(' postgres_data:');
963
+ if (options.integrations.includes('redis'))
964
+ volumes.push(' redis_data:');
965
+ if (options.integrations.includes('mongodb'))
966
+ volumes.push(' mongodb_data:');
967
+ const content = `version: '3.8'
968
+
969
+ services:
970
+ ${services.join('\n\n')}
971
+
972
+ ${volumes.length > 0 ? `volumes:\n${volumes.join('\n')}\n` : ''}
973
+ networks:
974
+ agentx-network:
975
+ driver: bridge
976
+ `;
977
+ fs.writeFileSync(path.join(projectDir, 'docker-compose.yml'), content);
978
+ }
979
+ async generateKubernetesManifests(projectDir, options) {
980
+ const k8sDir = path.join(projectDir, 'k8s');
981
+ if (!fs.existsSync(k8sDir)) {
982
+ fs.mkdirSync(k8sDir, { recursive: true });
983
+ }
984
+ // Namespace
985
+ const namespace = `apiVersion: v1
986
+ kind: Namespace
987
+ metadata:
988
+ name: agentx
989
+ `;
990
+ // Deployment
991
+ const deployment = `apiVersion: apps/v1
992
+ kind: Deployment
993
+ metadata:
994
+ name: ${options.projectName}
995
+ namespace: agentx
996
+ spec:
997
+ replicas: 3
998
+ selector:
999
+ matchLabels:
1000
+ app: ${options.projectName}
1001
+ template:
1002
+ metadata:
1003
+ labels:
1004
+ app: ${options.projectName}
1005
+ spec:
1006
+ containers:
1007
+ - name: ${options.projectName}
1008
+ image: ${options.projectName}:latest
1009
+ ports:
1010
+ - containerPort: 3000
1011
+ env:
1012
+ - name: NODE_ENV
1013
+ value: "production"
1014
+ envFrom:
1015
+ - secretRef:
1016
+ name: ${options.projectName}-secrets
1017
+ resources:
1018
+ requests:
1019
+ memory: "256Mi"
1020
+ cpu: "250m"
1021
+ limits:
1022
+ memory: "512Mi"
1023
+ cpu: "500m"
1024
+ livenessProbe:
1025
+ httpGet:
1026
+ path: /health
1027
+ port: 3000
1028
+ initialDelaySeconds: 30
1029
+ periodSeconds: 10
1030
+ readinessProbe:
1031
+ httpGet:
1032
+ path: /ready
1033
+ port: 3000
1034
+ initialDelaySeconds: 5
1035
+ periodSeconds: 5
1036
+ `;
1037
+ // Service
1038
+ const service = `apiVersion: v1
1039
+ kind: Service
1040
+ metadata:
1041
+ name: ${options.projectName}-service
1042
+ namespace: agentx
1043
+ spec:
1044
+ selector:
1045
+ app: ${options.projectName}
1046
+ ports:
1047
+ - protocol: TCP
1048
+ port: 80
1049
+ targetPort: 3000
1050
+ type: ClusterIP
1051
+ `;
1052
+ // Ingress
1053
+ const ingress = `apiVersion: networking.k8s.io/v1
1054
+ kind: Ingress
1055
+ metadata:
1056
+ name: ${options.projectName}-ingress
1057
+ namespace: agentx
1058
+ annotations:
1059
+ kubernetes.io/ingress.class: nginx
1060
+ cert-manager.io/cluster-issuer: letsencrypt-prod
1061
+ spec:
1062
+ tls:
1063
+ - hosts:
1064
+ - ${options.projectName}.yourdomain.com
1065
+ secretName: ${options.projectName}-tls
1066
+ rules:
1067
+ - host: ${options.projectName}.yourdomain.com
1068
+ http:
1069
+ paths:
1070
+ - path: /
1071
+ pathType: Prefix
1072
+ backend:
1073
+ service:
1074
+ name: ${options.projectName}-service
1075
+ port:
1076
+ number: 80
1077
+ `;
1078
+ fs.writeFileSync(path.join(k8sDir, '01-namespace.yaml'), namespace);
1079
+ fs.writeFileSync(path.join(k8sDir, '02-deployment.yaml'), deployment);
1080
+ fs.writeFileSync(path.join(k8sDir, '03-service.yaml'), service);
1081
+ fs.writeFileSync(path.join(k8sDir, '04-ingress.yaml'), ingress);
1082
+ }
1083
+ async generateRailwayConfig(projectDir, options) {
1084
+ const content = `{
1085
+ "build": {
1086
+ "builder": "NIXPACKS"
1087
+ },
1088
+ "deploy": {
1089
+ "startCommand": "npm start",
1090
+ "healthcheckPath": "/health",
1091
+ "healthcheckTimeout": 300,
1092
+ "restartPolicyType": "ON_FAILURE",
1093
+ "restartPolicyMaxRetries": 10
1094
+ }
1095
+ }
1096
+ `;
1097
+ fs.writeFileSync(path.join(projectDir, 'railway.json'), content);
1098
+ }
1099
+ async generateVercelConfig(projectDir, options) {
1100
+ const content = `{
1101
+ "version": 2,
1102
+ "builds": [
1103
+ {
1104
+ "src": "${options.typescript ? 'dist/index.js' : 'src/index.js'}",
1105
+ "use": "@vercel/node"
1106
+ }
1107
+ ],
1108
+ "routes": [
1109
+ {
1110
+ "src": "/(.*)",
1111
+ "dest": "${options.typescript ? 'dist/index.js' : 'src/index.js'}"
1112
+ }
1113
+ ],
1114
+ "env": {
1115
+ "NODE_ENV": "production"
1116
+ }
1117
+ }
1118
+ `;
1119
+ fs.writeFileSync(path.join(projectDir, 'vercel.json'), content);
1120
+ }
1121
+ async generateLambdaConfig(projectDir, options) {
1122
+ const content = `{
1123
+ "name": "${options.projectName}",
1124
+ "description": "AgentX application deployed on AWS Lambda",
1125
+ "runtime": "nodejs18.x",
1126
+ "handler": "${options.typescript ? 'dist/lambda.handler' : 'src/lambda.handler'}",
1127
+ "timeout": 30,
1128
+ "memorySize": 512,
1129
+ "environment": {
1130
+ "NODE_ENV": "production"
1131
+ },
1132
+ "layers": [],
1133
+ "events": [
1134
+ {
1135
+ "http": {
1136
+ "path": "/{proxy+}",
1137
+ "method": "ANY",
1138
+ "cors": true
1139
+ }
1140
+ }
1141
+ ]
1142
+ }
1143
+ `;
1144
+ fs.writeFileSync(path.join(projectDir, 'serverless.yml'), content);
1145
+ // Create Lambda handler
1146
+ const ext = options.typescript ? 'ts' : 'js';
1147
+ const lambdaHandler = `/**
1148
+ * AWS Lambda Handler
1149
+ */
1150
+ ${options.typescript ? "import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';" : ""}
1151
+
1152
+ export const handler = async (event${options.typescript ? ': APIGatewayProxyEvent' : ''}, context${options.typescript ? ': Context' : ''})${options.typescript ? ': Promise<APIGatewayProxyResult>' : ''} => {
1153
+ // Initialize your AgentX runtime here
1154
+ // This is a basic example - adapt based on your needs
1155
+
1156
+ return {
1157
+ statusCode: 200,
1158
+ headers: {
1159
+ 'Content-Type': 'application/json',
1160
+ 'Access-Control-Allow-Origin': '*',
1161
+ },
1162
+ body: JSON.stringify({
1163
+ message: 'AgentX Lambda function is running',
1164
+ event: event.path,
1165
+ }),
1166
+ };
1167
+ };
1168
+ `;
1169
+ fs.writeFileSync(path.join(projectDir, 'src', `lambda.${ext}`), lambdaHandler);
1170
+ }
1171
+ async generateSystemdService(projectDir, options) {
1172
+ const content = `[Unit]
1173
+ Description=${options.projectName} - AgentX Application
1174
+ After=network.target
1175
+
1176
+ [Service]
1177
+ Type=simple
1178
+ User=agentx
1179
+ WorkingDirectory=/opt/${options.projectName}
1180
+ ExecStart=/usr/bin/npm start
1181
+ Restart=on-failure
1182
+ RestartSec=10
1183
+ StandardOutput=syslog
1184
+ StandardError=syslog
1185
+ SyslogIdentifier=${options.projectName}
1186
+ Environment=NODE_ENV=production
1187
+ EnvironmentFile=/opt/${options.projectName}/.env
1188
+
1189
+ [Install]
1190
+ WantedBy=multi-user.target
1191
+ `;
1192
+ fs.writeFileSync(path.join(projectDir, `${options.projectName}.service`), content);
1193
+ // Create installation script
1194
+ const installScript = `#!/bin/bash
1195
+ # Installation script for ${options.projectName}
1196
+
1197
+ set -e
1198
+
1199
+ echo "Installing ${options.projectName} as systemd service..."
1200
+
1201
+ # Create user
1202
+ sudo useradd -r -s /bin/false agentx || true
1203
+
1204
+ # Create directory
1205
+ sudo mkdir -p /opt/${options.projectName}
1206
+ sudo cp -r . /opt/${options.projectName}/
1207
+ sudo chown -R agentx:agentx /opt/${options.projectName}
1208
+
1209
+ # Install service
1210
+ sudo cp ${options.projectName}.service /etc/systemd/system/
1211
+ sudo systemctl daemon-reload
1212
+ sudo systemctl enable ${options.projectName}
1213
+
1214
+ echo "Installation complete!"
1215
+ echo "Start the service with: sudo systemctl start ${options.projectName}"
1216
+ echo "Check status with: sudo systemctl status ${options.projectName}"
1217
+ `;
1218
+ fs.writeFileSync(path.join(projectDir, 'install.sh'), installScript);
1219
+ // Make install script executable (on Unix systems)
1220
+ try {
1221
+ fs.chmodSync(path.join(projectDir, 'install.sh'), 0o755);
1222
+ }
1223
+ catch (error) {
1224
+ // Ignore on Windows
1225
+ }
1226
+ }
1227
+ /**
1228
+ * Generate security-related files
1229
+ */
1230
+ async generateSecurityFiles(projectDir, options) {
1231
+ if (options.security.includes('https-only')) {
1232
+ await this.generateSecurityHeaders(projectDir);
1233
+ }
1234
+ if (options.security.includes('input-validation')) {
1235
+ await this.generateValidationSchemas(projectDir, options);
1236
+ }
1237
+ if (options.security.includes('audit-logging')) {
1238
+ await this.generateAuditConfig(projectDir);
1239
+ }
1240
+ // Generate security documentation
1241
+ await this.generateSecurityDocs(projectDir, options);
1242
+ }
1243
+ async generateSecurityHeaders(projectDir) {
1244
+ const ext = 'ts'; // Always generate TypeScript for middleware
1245
+ const content = `/**
1246
+ * Security Headers Middleware
1247
+ * Implements security best practices
1248
+ */
1249
+ import { Request, Response, NextFunction } from 'express';
1250
+
1251
+ export function securityHeaders(req: Request, res: Response, next: NextFunction): void {
1252
+ // Force HTTPS
1253
+ res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
1254
+
1255
+ // Prevent clickjacking
1256
+ res.setHeader('X-Frame-Options', 'DENY');
1257
+
1258
+ // Prevent MIME type sniffing
1259
+ res.setHeader('X-Content-Type-Options', 'nosniff');
1260
+
1261
+ // XSS Protection
1262
+ res.setHeader('X-XSS-Protection', '1; mode=block');
1263
+
1264
+ // Content Security Policy
1265
+ res.setHeader('Content-Security-Policy',
1266
+ "default-src 'self'; " +
1267
+ "script-src 'self' 'unsafe-inline'; " +
1268
+ "style-src 'self' 'unsafe-inline'; " +
1269
+ "img-src 'self' data: https:; " +
1270
+ "connect-src 'self'; " +
1271
+ "font-src 'self'; " +
1272
+ "object-src 'none'; " +
1273
+ "media-src 'self'; " +
1274
+ "frame-src 'none';"
1275
+ );
1276
+
1277
+ // Referrer Policy
1278
+ res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
1279
+
1280
+ // Permissions Policy
1281
+ res.setHeader('Permissions-Policy',
1282
+ 'camera=(), microphone=(), geolocation=(), payment=()'
1283
+ );
1284
+
1285
+ next();
1286
+ }
1287
+ `;
1288
+ const middlewareDir = path.join(projectDir, 'src', 'middleware');
1289
+ if (!fs.existsSync(middlewareDir)) {
1290
+ fs.mkdirSync(middlewareDir, { recursive: true });
1291
+ }
1292
+ fs.writeFileSync(path.join(middlewareDir, `security.${ext}`), content);
1293
+ }
1294
+ async generateValidationSchemas(projectDir, options) {
1295
+ const ext = options.typescript ? 'ts' : 'js';
1296
+ const content = `/**
1297
+ * Input Validation Schemas
1298
+ * Define validation rules for all inputs
1299
+ */
1300
+ ${options.typescript ? "import Joi from 'joi';" : "const Joi = require('joi');"}
1301
+
1302
+ // Common validation patterns
1303
+ const patterns = {
1304
+ email: Joi.string().email().required(),
1305
+ password: Joi.string().min(8).pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]/).required(),
1306
+ apiKey: Joi.string().alphanum().length(32).required(),
1307
+ uuid: Joi.string().uuid().required(),
1308
+ };
1309
+
1310
+ // Agent configuration validation
1311
+ export const agentConfigSchema = Joi.object({
1312
+ name: Joi.string().alphanum().min(3).max(50).required(),
1313
+ description: Joi.string().max(500),
1314
+ llmProvider: Joi.string().valid('openai', 'anthropic', 'local').required(),
1315
+ model: Joi.string().required(),
1316
+ systemPrompt: Joi.string().max(2000).required(),
1317
+ temperature: Joi.number().min(0).max(2).default(0.7),
1318
+ maxIterations: Joi.number().integer().min(1).max(50).default(10),
1319
+ });
1320
+
1321
+ // Workflow validation
1322
+ export const workflowSchema = Joi.object({
1323
+ id: Joi.string().alphanum().required(),
1324
+ name: Joi.string().min(3).max(100).required(),
1325
+ version: Joi.string().pattern(/^\\d+\\.\\d+\\.\\d+$/).required(),
1326
+ steps: Joi.array().items(Joi.object({
1327
+ id: Joi.string().required(),
1328
+ name: Joi.string().required(),
1329
+ type: Joi.string().valid('tool', 'condition', 'loop').required(),
1330
+ config: Joi.object().required(),
1331
+ })).min(1).required(),
1332
+ });
1333
+
1334
+ // API request validation
1335
+ export const apiRequestSchema = Joi.object({
1336
+ method: Joi.string().valid('GET', 'POST', 'PUT', 'DELETE', 'PATCH').required(),
1337
+ url: Joi.string().uri().required(),
1338
+ headers: Joi.object().pattern(Joi.string(), Joi.string()),
1339
+ body: Joi.any(),
1340
+ timeout: Joi.number().integer().min(1000).max(30000).default(10000),
1341
+ });
1342
+
1343
+ ${options.typescript ? 'export default { patterns, agentConfigSchema, workflowSchema, apiRequestSchema };' : 'module.exports = { patterns, agentConfigSchema, workflowSchema, apiRequestSchema };'}
1344
+ `;
1345
+ const schemasDir = path.join(projectDir, 'src', 'schemas');
1346
+ if (!fs.existsSync(schemasDir)) {
1347
+ fs.mkdirSync(schemasDir, { recursive: true });
1348
+ }
1349
+ fs.writeFileSync(path.join(schemasDir, `validation.${ext}`), content);
1350
+ }
1351
+ async generateAuditConfig(projectDir) {
1352
+ const content = `/**
1353
+ * Audit Logging Configuration
1354
+ * Tracks security-relevant events
1355
+ */
1356
+
1357
+ export interface AuditEvent {
1358
+ timestamp: string;
1359
+ userId?: string;
1360
+ action: string;
1361
+ resource: string;
1362
+ outcome: 'success' | 'failure';
1363
+ details?: Record<string, any>;
1364
+ ipAddress?: string;
1365
+ userAgent?: string;
1366
+ }
1367
+
1368
+ export const auditEvents = {
1369
+ // Authentication events
1370
+ LOGIN_SUCCESS: 'auth.login.success',
1371
+ LOGIN_FAILURE: 'auth.login.failure',
1372
+ LOGOUT: 'auth.logout',
1373
+
1374
+ // API access events
1375
+ API_ACCESS: 'api.access',
1376
+ API_KEY_CREATED: 'api.key.created',
1377
+ API_KEY_REVOKED: 'api.key.revoked',
1378
+
1379
+ // Agent events
1380
+ AGENT_CREATED: 'agent.created',
1381
+ AGENT_MODIFIED: 'agent.modified',
1382
+ AGENT_DELETED: 'agent.deleted',
1383
+ AGENT_EXECUTED: 'agent.executed',
1384
+
1385
+ // Workflow events
1386
+ WORKFLOW_CREATED: 'workflow.created',
1387
+ WORKFLOW_EXECUTED: 'workflow.executed',
1388
+ WORKFLOW_FAILED: 'workflow.failed',
1389
+
1390
+ // Security events
1391
+ RATE_LIMIT_EXCEEDED: 'security.rate_limit.exceeded',
1392
+ INVALID_INPUT: 'security.input.invalid',
1393
+ UNAUTHORIZED_ACCESS: 'security.access.unauthorized',
1394
+ };
1395
+
1396
+ export class AuditLogger {
1397
+ static log(event: AuditEvent): void {
1398
+ // In production, send to your logging service
1399
+ console.log('[AUDIT]', JSON.stringify(event));
1400
+ }
1401
+
1402
+ static logAuth(action: string, userId?: string, outcome: 'success' | 'failure' = 'success'): void {
1403
+ this.log({
1404
+ timestamp: new Date().toISOString(),
1405
+ userId,
1406
+ action,
1407
+ resource: 'authentication',
1408
+ outcome,
1409
+ });
1410
+ }
1411
+
1412
+ static logApiAccess(endpoint: string, userId?: string, outcome: 'success' | 'failure' = 'success'): void {
1413
+ this.log({
1414
+ timestamp: new Date().toISOString(),
1415
+ userId,
1416
+ action: auditEvents.API_ACCESS,
1417
+ resource: endpoint,
1418
+ outcome,
1419
+ });
1420
+ }
1421
+ }
1422
+ `;
1423
+ const securityDir = path.join(projectDir, 'src', 'security');
1424
+ if (!fs.existsSync(securityDir)) {
1425
+ fs.mkdirSync(securityDir, { recursive: true });
1426
+ }
1427
+ fs.writeFileSync(path.join(securityDir, 'audit.ts'), content);
1428
+ }
1429
+ async generateSecurityDocs(projectDir, options) {
1430
+ const content = `# Security Guide for ${options.projectName}
1431
+
1432
+ ## Overview
1433
+
1434
+ This document outlines the security measures implemented in your AgentX application.
1435
+
1436
+ ## Implemented Security Features
1437
+
1438
+ ${options.security.map(feature => {
1439
+ switch (feature) {
1440
+ case 'https-only':
1441
+ return '### HTTPS Only\n- Strict Transport Security headers\n- Secure cookie settings\n- Content Security Policy';
1442
+ case 'api-keys':
1443
+ return '### API Key Authentication\n- Secure API key generation\n- Key rotation capabilities\n- Rate limiting per key';
1444
+ case 'jwt':
1445
+ return '### JWT Authentication\n- Secure token generation\n- Configurable expiration\n- Refresh token support';
1446
+ case 'rate-limiting':
1447
+ return '### Rate Limiting\n- Per-IP rate limiting\n- Per-user rate limiting\n- Configurable limits';
1448
+ case 'input-validation':
1449
+ return '### Input Validation\n- Schema-based validation\n- SQL injection prevention\n- XSS protection';
1450
+ case 'audit-logging':
1451
+ return '### Audit Logging\n- Security event tracking\n- User action logging\n- Compliance reporting';
1452
+ case 'secrets-manager':
1453
+ return '### Secrets Management\n- External secrets integration\n- Encrypted storage\n- Access control';
1454
+ default:
1455
+ return `### ${feature}\n- Feature implemented`;
1456
+ }
1457
+ }).join('\n\n')}
1458
+
1459
+ ## Security Checklist
1460
+
1461
+ ### Before Production
1462
+
1463
+ - [ ] Change all default passwords and API keys
1464
+ - [ ] Enable HTTPS with valid SSL certificates
1465
+ - [ ] Configure firewall rules
1466
+ - [ ] Set up monitoring and alerting
1467
+ - [ ] Review and test backup procedures
1468
+ - [ ] Conduct security audit
1469
+ - [ ] Update dependencies to latest versions
1470
+
1471
+ ### Environment Variables
1472
+
1473
+ Ensure these environment variables are properly configured:
1474
+
1475
+ ${options.security.includes('jwt') ? '- `JWT_SECRET`: Use a strong, random secret key' : ''}
1476
+ ${options.security.includes('api-keys') ? '- `MASTER_API_KEY`: Change from default value' : ''}
1477
+ ${options.features.includes('credentials') ? '- `CREDENTIAL_ENCRYPTION_KEY`: 32-character encryption key' : ''}
1478
+
1479
+ ### Regular Maintenance
1480
+
1481
+ - [ ] Regular security updates
1482
+ - [ ] Log monitoring and analysis
1483
+ - [ ] Access review and cleanup
1484
+ - [ ] Backup testing
1485
+ - [ ] Incident response testing
1486
+
1487
+ ## Deployment Security
1488
+
1489
+ ${options.deployment.includes('docker') ? `
1490
+ ### Docker Security
1491
+ - Use non-root user in containers
1492
+ - Scan images for vulnerabilities
1493
+ - Use minimal base images
1494
+ - Keep containers updated
1495
+ ` : ''}
1496
+
1497
+ ${options.deployment.includes('kubernetes') ? `
1498
+ ### Kubernetes Security
1499
+ - Use network policies
1500
+ - Enable RBAC
1501
+ - Scan container images
1502
+ - Use secrets for sensitive data
1503
+ - Regular cluster updates
1504
+ ` : ''}
1505
+
1506
+ ## Incident Response
1507
+
1508
+ 1. **Detection**: Monitor logs and alerts
1509
+ 2. **Assessment**: Determine scope and impact
1510
+ 3. **Containment**: Isolate affected systems
1511
+ 4. **Recovery**: Restore normal operations
1512
+ 5. **Lessons Learned**: Update procedures
1513
+
1514
+ ## Contact
1515
+
1516
+ For security issues, contact: security@yourcompany.com
1517
+ `;
1518
+ fs.writeFileSync(path.join(projectDir, 'SECURITY.md'), content);
1519
+ }
1520
+ /**
1521
+ * Generate payment integration examples
1522
+ */
1523
+ async generatePaymentExamples(projectDir, options) {
1524
+ const paymentsDir = path.join(projectDir, 'src', 'payments');
1525
+ if (!fs.existsSync(paymentsDir)) {
1526
+ fs.mkdirSync(paymentsDir, { recursive: true });
1527
+ }
1528
+ const ext = options.typescript ? 'ts' : 'js';
1529
+ // Generate payment service
1530
+ await this.generatePaymentService(paymentsDir, ext, options.typescript);
1531
+ // Generate M-Pesa specific example
1532
+ await this.generateMPesaExample(paymentsDir, ext, options.typescript);
1533
+ // Generate payment webhook handler
1534
+ await this.generatePaymentWebhooks(paymentsDir, ext, options.typescript);
1535
+ // Generate payment documentation
1536
+ await this.generatePaymentDocs(projectDir);
1537
+ }
1538
+ async generatePaymentService(paymentsDir, ext, typescript) {
1539
+ const imports = typescript
1540
+ ? `import { PaymentProviderRegistry, createPaymentProvider, PaymentRequest, PaymentResult } from 'agentx';
1541
+ import { Logger } from 'agentx';`
1542
+ : `const { PaymentProviderRegistry, createPaymentProvider } = require('agentx');`;
1543
+ const content = `/**
1544
+ * Payment Service
1545
+ * Handles all payment operations
1546
+ */
1547
+ ${imports}
1548
+
1549
+ export class PaymentService {
1550
+ private registry${typescript ? ': PaymentProviderRegistry' : ''};
1551
+ private logger${typescript ? ': Logger' : ''};
1552
+
1553
+ constructor(logger${typescript ? ': Logger' : ''}) {
1554
+ this.logger = logger;
1555
+ this.registry = new PaymentProviderRegistry(logger);
1556
+ }
1557
+
1558
+ /**
1559
+ * Initialize payment providers
1560
+ */
1561
+ async initialize()${typescript ? ': Promise<void>' : ''} {
1562
+ // Initialize Stripe
1563
+ if (process.env.STRIPE_SECRET_KEY) {
1564
+ const stripe = createPaymentProvider('stripe', this.logger);
1565
+ await this.registry.register(stripe, {
1566
+ name: 'stripe',
1567
+ credentials: {
1568
+ apiKey: process.env.STRIPE_SECRET_KEY,
1569
+ webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
1570
+ },
1571
+ environment: process.env.NODE_ENV === 'production' ? 'production' : 'test',
1572
+ });
1573
+ }
1574
+
1575
+ // Initialize PayPal
1576
+ if (process.env.PAYPAL_CLIENT_ID) {
1577
+ const paypal = createPaymentProvider('paypal', this.logger);
1578
+ await this.registry.register(paypal, {
1579
+ name: 'paypal',
1580
+ credentials: {
1581
+ clientId: process.env.PAYPAL_CLIENT_ID,
1582
+ clientSecret: process.env.PAYPAL_CLIENT_SECRET,
1583
+ },
1584
+ environment: process.env.PAYPAL_MODE || 'sandbox',
1585
+ });
1586
+ }
1587
+
1588
+ // Initialize M-Pesa
1589
+ if (process.env.MPESA_CONSUMER_KEY) {
1590
+ const mpesa = createPaymentProvider('mpesa', this.logger);
1591
+ await this.registry.register(mpesa, {
1592
+ name: 'mpesa',
1593
+ credentials: {
1594
+ consumerKey: process.env.MPESA_CONSUMER_KEY,
1595
+ consumerSecret: process.env.MPESA_CONSUMER_SECRET,
1596
+ shortcode: process.env.MPESA_SHORTCODE,
1597
+ passkey: process.env.MPESA_PASSKEY,
1598
+ },
1599
+ environment: process.env.MPESA_ENVIRONMENT || 'sandbox',
1600
+ callbackUrl: process.env.MPESA_CALLBACK_URL,
1601
+ webhookUrl: process.env.MPESA_WEBHOOK_URL,
1602
+ });
1603
+ }
1604
+
1605
+ this.logger.info('Payment service initialized');
1606
+ }
1607
+
1608
+ /**
1609
+ * Process payment with specified provider
1610
+ */
1611
+ async processPayment(
1612
+ providerName${typescript ? ': string' : ''},
1613
+ request${typescript ? ': PaymentRequest' : ''}
1614
+ )${typescript ? ': Promise<PaymentResult>' : ''} {
1615
+ const provider = this.registry.get(providerName);
1616
+ if (!provider) {
1617
+ throw new Error(\`Payment provider not found: \${providerName}\`);
1618
+ }
1619
+
1620
+ return await provider.processPayment(request);
1621
+ }
1622
+
1623
+ /**
1624
+ * Get available payment providers
1625
+ */
1626
+ getAvailableProviders()${typescript ? ': string[]' : ''} {
1627
+ return this.registry.list();
1628
+ }
1629
+
1630
+ /**
1631
+ * Get payment status
1632
+ */
1633
+ async getPaymentStatus(
1634
+ providerName${typescript ? ': string' : ''},
1635
+ paymentId${typescript ? ': string' : ''}
1636
+ )${typescript ? ': Promise<string>' : ''} {
1637
+ const provider = this.registry.get(providerName);
1638
+ if (!provider) {
1639
+ throw new Error(\`Payment provider not found: \${providerName}\`);
1640
+ }
1641
+
1642
+ return await provider.getPaymentStatus(paymentId);
1643
+ }
1644
+ }
1645
+ `;
1646
+ fs.writeFileSync(path.join(paymentsDir, `PaymentService.${ext}`), content);
1647
+ }
1648
+ async generateMPesaExample(paymentsDir, ext, typescript) {
1649
+ const imports = typescript
1650
+ ? `import { PaymentService } from './PaymentService';
1651
+ import { Logger } from 'agentx';`
1652
+ : `const { PaymentService } = require('./PaymentService');`;
1653
+ const content = `/**
1654
+ * M-Pesa Payment Example
1655
+ * Complete working example for M-Pesa STK Push
1656
+ */
1657
+ ${imports}
1658
+
1659
+ export class MPesaPaymentExample {
1660
+ private paymentService${typescript ? ': PaymentService' : ''};
1661
+ private logger${typescript ? ': Logger' : ''};
1662
+
1663
+ constructor(logger${typescript ? ': Logger' : ''}) {
1664
+ this.logger = logger;
1665
+ this.paymentService = new PaymentService(logger);
1666
+ }
1667
+
1668
+ /**
1669
+ * Initialize M-Pesa payment service
1670
+ */
1671
+ async initialize()${typescript ? ': Promise<void>' : ''} {
1672
+ await this.paymentService.initialize();
1673
+ }
1674
+
1675
+ /**
1676
+ * Process M-Pesa STK Push payment
1677
+ * @param phoneNumber - Customer phone number (254XXXXXXXXX format)
1678
+ * @param amount - Amount in KES
1679
+ * @param accountReference - Account reference (optional)
1680
+ * @param description - Transaction description
1681
+ */
1682
+ async processMPesaPayment(
1683
+ phoneNumber${typescript ? ': string' : ''},
1684
+ amount${typescript ? ': number' : ''},
1685
+ accountReference${typescript ? ': string' : ''} = 'Payment',
1686
+ description${typescript ? ': string' : ''} = 'Payment for services'
1687
+ )${typescript ? ': Promise<any>' : ''} {
1688
+ try {
1689
+ // Validate phone number format
1690
+ const formattedPhone = this.formatPhoneNumber(phoneNumber);
1691
+
1692
+ const paymentRequest = {
1693
+ amount,
1694
+ currency: 'KES',
1695
+ paymentMethod: {
1696
+ type: 'mobile_money',
1697
+ provider: 'mpesa',
1698
+ details: {
1699
+ phoneNumber: formattedPhone,
1700
+ accountReference,
1701
+ transactionDesc: description,
1702
+ },
1703
+ },
1704
+ metadata: {
1705
+ phoneNumber: formattedPhone,
1706
+ accountReference,
1707
+ },
1708
+ description,
1709
+ callbackUrl: process.env.MPESA_CALLBACK_URL,
1710
+ };
1711
+
1712
+ const result = await this.paymentService.processPayment('mpesa', paymentRequest);
1713
+
1714
+ this.logger.info('M-Pesa payment initiated', {
1715
+ paymentId: result.paymentId,
1716
+ phoneNumber: formattedPhone,
1717
+ amount,
1718
+ });
1719
+
1720
+ return {
1721
+ success: result.success,
1722
+ paymentId: result.paymentId,
1723
+ message: result.success
1724
+ ? 'Payment request sent. Please check your phone for M-Pesa prompt.'
1725
+ : 'Payment failed. Please try again.',
1726
+ error: result.error,
1727
+ };
1728
+ } catch (error) {
1729
+ this.logger.error('M-Pesa payment error', error);
1730
+ throw error;
1731
+ }
1732
+ }
1733
+
1734
+ /**
1735
+ * Check M-Pesa payment status
1736
+ */
1737
+ async checkPaymentStatus(paymentId${typescript ? ': string' : ''})${typescript ? ': Promise<string>' : ''} {
1738
+ try {
1739
+ const status = await this.paymentService.getPaymentStatus('mpesa', paymentId);
1740
+ this.logger.info('M-Pesa payment status checked', { paymentId, status });
1741
+ return status;
1742
+ } catch (error) {
1743
+ this.logger.error('M-Pesa status check error', error);
1744
+ throw error;
1745
+ }
1746
+ }
1747
+
1748
+ /**
1749
+ * Format phone number to M-Pesa format (254XXXXXXXXX)
1750
+ */
1751
+ private formatPhoneNumber(phone${typescript ? ': string' : ''})${typescript ? ': string' : ''} {
1752
+ // Remove all non-digits
1753
+ let formatted = phone.replace(/\\D/g, '');
1754
+
1755
+ // Handle different formats
1756
+ if (formatted.startsWith('0')) {
1757
+ // Convert 07XXXXXXXX to 2547XXXXXXXX
1758
+ formatted = '254' + formatted.slice(1);
1759
+ } else if (formatted.startsWith('7')) {
1760
+ // Convert 7XXXXXXXX to 2547XXXXXXXX
1761
+ formatted = '254' + formatted;
1762
+ } else if (!formatted.startsWith('254')) {
1763
+ // Assume it needs 254 prefix
1764
+ formatted = '254' + formatted;
1765
+ }
1766
+
1767
+ // Validate length (should be 12 digits: 254XXXXXXXXX)
1768
+ if (formatted.length !== 12) {
1769
+ throw new Error('Invalid phone number format. Expected format: 254XXXXXXXXX');
1770
+ }
1771
+
1772
+ return formatted;
1773
+ }
1774
+
1775
+ /**
1776
+ * Example usage function
1777
+ */
1778
+ static async example()${typescript ? ': Promise<void>' : ''} {
1779
+ const logger${typescript ? ': Logger' : ''} = {
1780
+ debug: (msg${typescript ? ': string' : ''}) => console.log(\`[DEBUG] \${msg}\`),
1781
+ info: (msg${typescript ? ': string' : ''}) => console.log(\`[INFO] \${msg}\`),
1782
+ warn: (msg${typescript ? ': string' : ''}) => console.warn(\`[WARN] \${msg}\`),
1783
+ error: (msg${typescript ? ': string' : ''}) => console.error(\`[ERROR] \${msg}\`),
1784
+ };
1785
+
1786
+ const mpesa = new MPesaPaymentExample(logger);
1787
+ await mpesa.initialize();
1788
+
1789
+ // Example: Process payment
1790
+ try {
1791
+ const result = await mpesa.processMPesaPayment(
1792
+ '0712345678', // Phone number
1793
+ 100, // Amount in KES
1794
+ 'ORDER123', // Account reference
1795
+ 'Payment for Order #123'
1796
+ );
1797
+
1798
+ console.log('Payment Result:', result);
1799
+
1800
+ // Check status after a delay
1801
+ if (result.success && result.paymentId) {
1802
+ setTimeout(async () => {
1803
+ const status = await mpesa.checkPaymentStatus(result.paymentId);
1804
+ console.log('Payment Status:', status);
1805
+ }, 5000);
1806
+ }
1807
+ } catch (error) {
1808
+ console.error('Payment failed:', error);
1809
+ }
1810
+ }
1811
+ }
1812
+
1813
+ // Uncomment to run example
1814
+ // MPesaPaymentExample.example();
1815
+ `;
1816
+ fs.writeFileSync(path.join(paymentsDir, `MPesaExample.${ext}`), content);
1817
+ }
1818
+ async generatePaymentWebhooks(paymentsDir, ext, typescript) {
1819
+ const imports = typescript
1820
+ ? `import { Request, Response } from 'express';
1821
+ import { PaymentProviderRegistry } from 'agentx';`
1822
+ : `// const express = require('express');`;
1823
+ const content = `/**
1824
+ * Payment Webhook Handlers
1825
+ * Handle webhooks from payment providers
1826
+ */
1827
+ ${imports}
1828
+
1829
+ export class PaymentWebhookHandler {
1830
+ private registry${typescript ? ': PaymentProviderRegistry' : ''};
1831
+
1832
+ constructor(registry${typescript ? ': PaymentProviderRegistry' : ''}) {
1833
+ this.registry = registry;
1834
+ }
1835
+
1836
+ /**
1837
+ * Handle M-Pesa callback webhook
1838
+ */
1839
+ async handleMPesaCallback(req${typescript ? ': Request' : ''}, res${typescript ? ': Response' : ''})${typescript ? ': Promise<void>' : ''} {
1840
+ try {
1841
+ const payload = req.body;
1842
+ console.log('M-Pesa Callback received:', JSON.stringify(payload, null, 2));
1843
+
1844
+ const mpesa = this.registry.get('mpesa');
1845
+ if (!mpesa) {
1846
+ throw new Error('M-Pesa provider not initialized');
1847
+ }
1848
+
1849
+ // Validate and process webhook
1850
+ const isValid = await mpesa.validateWebhook(payload, '');
1851
+ if (!isValid) {
1852
+ return res.status(400).json({ error: 'Invalid webhook' });
1853
+ }
1854
+
1855
+ const result = await mpesa.processWebhook(payload);
1856
+
1857
+ if (result.processed) {
1858
+ // Handle successful payment
1859
+ const callback = payload.Body?.stkCallback;
1860
+ if (callback?.ResultCode === 0) {
1861
+ console.log('Payment successful:', {
1862
+ paymentId: callback.CheckoutRequestID,
1863
+ mpesaReceiptNumber: callback.CallbackMetadata?.Item?.find((item${typescript ? ': any' : ''}) => item.Name === 'MpesaReceiptNumber')?.Value,
1864
+ amount: callback.CallbackMetadata?.Item?.find((item${typescript ? ': any' : ''}) => item.Name === 'Amount')?.Value,
1865
+ phoneNumber: callback.CallbackMetadata?.Item?.find((item${typescript ? ': any' : ''}) => item.Name === 'PhoneNumber')?.Value,
1866
+ });
1867
+
1868
+ // TODO: Update your database with payment success
1869
+ // await updatePaymentStatus(callback.CheckoutRequestID, 'completed');
1870
+ } else {
1871
+ console.log('Payment failed:', {
1872
+ paymentId: callback.CheckoutRequestID,
1873
+ errorCode: callback.ResultCode,
1874
+ errorMessage: callback.ResultDesc,
1875
+ });
1876
+
1877
+ // TODO: Update your database with payment failure
1878
+ // await updatePaymentStatus(callback.CheckoutRequestID, 'failed');
1879
+ }
1880
+ }
1881
+
1882
+ res.status(200).json({ message: 'Webhook processed successfully' });
1883
+ } catch (error) {
1884
+ console.error('M-Pesa webhook error:', error);
1885
+ res.status(500).json({ error: 'Webhook processing failed' });
1886
+ }
1887
+ }
1888
+
1889
+ /**
1890
+ * Handle Stripe webhook
1891
+ */
1892
+ async handleStripeWebhook(req${typescript ? ': Request' : ''}, res${typescript ? ': Response' : ''})${typescript ? ': Promise<void>' : ''} {
1893
+ try {
1894
+ const signature = req.headers['stripe-signature']${typescript ? ' as string' : ''};
1895
+ const payload = req.body;
1896
+
1897
+ const stripe = this.registry.get('stripe');
1898
+ if (!stripe) {
1899
+ throw new Error('Stripe provider not initialized');
1900
+ }
1901
+
1902
+ const isValid = await stripe.validateWebhook(payload, signature);
1903
+ if (!isValid) {
1904
+ return res.status(400).json({ error: 'Invalid webhook signature' });
1905
+ }
1906
+
1907
+ const result = await stripe.processWebhook(payload);
1908
+ console.log('Stripe webhook processed:', result);
1909
+
1910
+ res.status(200).json({ received: true });
1911
+ } catch (error) {
1912
+ console.error('Stripe webhook error:', error);
1913
+ res.status(500).json({ error: 'Webhook processing failed' });
1914
+ }
1915
+ }
1916
+
1917
+ /**
1918
+ * Handle PayPal webhook
1919
+ */
1920
+ async handlePayPalWebhook(req${typescript ? ': Request' : ''}, res${typescript ? ': Response' : ''})${typescript ? ': Promise<void>' : ''} {
1921
+ try {
1922
+ const payload = req.body;
1923
+
1924
+ const paypal = this.registry.get('paypal');
1925
+ if (!paypal) {
1926
+ throw new Error('PayPal provider not initialized');
1927
+ }
1928
+
1929
+ const result = await paypal.processWebhook(payload);
1930
+ console.log('PayPal webhook processed:', result);
1931
+
1932
+ res.status(200).json({ received: true });
1933
+ } catch (error) {
1934
+ console.error('PayPal webhook error:', error);
1935
+ res.status(500).json({ error: 'Webhook processing failed' });
1936
+ }
1937
+ }
1938
+ }
1939
+
1940
+ /**
1941
+ * Express.js route setup example
1942
+ */
1943
+ export function setupPaymentRoutes(app${typescript ? ': any' : ''}, webhookHandler${typescript ? ': PaymentWebhookHandler' : ''})${typescript ? ': void' : ''} {
1944
+ // M-Pesa callback endpoint
1945
+ app.post('/api/payments/mpesa/callback', (req${typescript ? ': Request' : ''}, res${typescript ? ': Response' : ''}) => {
1946
+ webhookHandler.handleMPesaCallback(req, res);
1947
+ });
1948
+
1949
+ // Stripe webhook endpoint
1950
+ app.post('/api/payments/stripe/webhook', (req${typescript ? ': Request' : ''}, res${typescript ? ': Response' : ''}) => {
1951
+ webhookHandler.handleStripeWebhook(req, res);
1952
+ });
1953
+
1954
+ // PayPal webhook endpoint
1955
+ app.post('/api/payments/paypal/webhook', (req${typescript ? ': Request' : ''}, res${typescript ? ': Response' : ''}) => {
1956
+ webhookHandler.handlePayPalWebhook(req, res);
1957
+ });
1958
+ }
1959
+ `;
1960
+ fs.writeFileSync(path.join(paymentsDir, `WebhookHandler.${ext}`), content);
1961
+ }
1962
+ async generatePaymentDocs(projectDir) {
1963
+ const content = `# Payment Integration Guide
1964
+
1965
+ ## Overview
1966
+
1967
+ This project includes complete payment integration with Stripe, PayPal, and M-Pesa (Safaricom). All providers are production-ready and only require API credentials to be configured.
1968
+
1969
+ ## Supported Payment Providers
1970
+
1971
+ ### 1. M-Pesa (Safaricom)
1972
+ - **Type**: Mobile Money
1973
+ - **Currency**: KES (Kenyan Shillings)
1974
+ - **Features**: STK Push, Payment Status Checking, Webhooks
1975
+ - **Use Case**: Kenya mobile payments
1976
+
1977
+ ### 2. Stripe
1978
+ - **Type**: Credit/Debit Cards, Bank Transfers
1979
+ - **Currencies**: USD, EUR, GBP, CAD, AUD, JPY
1980
+ - **Features**: Full payment lifecycle, refunds, webhooks
1981
+ - **Use Case**: Global card payments
1982
+
1983
+ ### 3. PayPal
1984
+ - **Type**: Digital Wallet, Cards
1985
+ - **Currencies**: USD, EUR, GBP, CAD, AUD
1986
+ - **Features**: PayPal wallet, card processing, refunds
1987
+ - **Use Case**: Global digital payments
1988
+
1989
+ ## Quick Start
1990
+
1991
+ ### 1. Configure Environment Variables
1992
+
1993
+ Copy the values from \`.env.example\` to \`.env\` and fill in your credentials:
1994
+
1995
+ \`\`\`bash
1996
+ # M-Pesa Configuration
1997
+ MPESA_CONSUMER_KEY=your-consumer-key
1998
+ MPESA_CONSUMER_SECRET=your-consumer-secret
1999
+ MPESA_SHORTCODE=174379
2000
+ MPESA_PASSKEY=your-passkey
2001
+ MPESA_ENVIRONMENT=sandbox
2002
+ MPESA_CALLBACK_URL=https://yourdomain.com/api/payments/mpesa/callback
2003
+ \`\`\`
2004
+
2005
+ ### 2. Initialize Payment Service
2006
+
2007
+ \`\`\`typescript
2008
+ import { PaymentService } from './src/payments/PaymentService';
2009
+
2010
+ const paymentService = new PaymentService(logger);
2011
+ await paymentService.initialize();
2012
+ \`\`\`
2013
+
2014
+ ### 3. Process M-Pesa Payment
2015
+
2016
+ \`\`\`typescript
2017
+ import { MPesaPaymentExample } from './src/payments/MPesaExample';
2018
+
2019
+ const mpesa = new MPesaPaymentExample(logger);
2020
+ await mpesa.initialize();
2021
+
2022
+ const result = await mpesa.processMPesaPayment(
2023
+ '0712345678', // Phone number
2024
+ 100, // Amount in KES
2025
+ 'ORDER123', // Account reference
2026
+ 'Payment for services' // Description
2027
+ );
2028
+
2029
+ console.log('Payment initiated:', result);
2030
+ \`\`\`
2031
+
2032
+ ## M-Pesa Integration Details
2033
+
2034
+ ### Getting M-Pesa Credentials
2035
+
2036
+ 1. **Register on Safaricom Developer Portal**
2037
+ - Visit: https://developer.safaricom.co.ke/
2038
+ - Create an account and verify your email
2039
+
2040
+ 2. **Create an App**
2041
+ - Go to "My Apps" and create a new app
2042
+ - Select "Lipa Na M-Pesa Online" product
2043
+ - Get your Consumer Key and Consumer Secret
2044
+
2045
+ 3. **Get Shortcode and Passkey**
2046
+ - For sandbox: Use test shortcode 174379
2047
+ - For production: Apply for your business shortcode
2048
+ - Passkey is provided when you get your shortcode
2049
+
2050
+ ### Phone Number Format
2051
+
2052
+ M-Pesa requires phone numbers in international format:
2053
+ - ✅ Correct: \`254712345678\`
2054
+ - ❌ Wrong: \`0712345678\`, \`+254712345678\`, \`712345678\`
2055
+
2056
+ The \`MPesaExample\` class automatically formats phone numbers for you.
2057
+
2058
+ ### Webhook Setup
2059
+
2060
+ 1. **Configure Callback URL**
2061
+ - Set \`MPESA_CALLBACK_URL\` to your webhook endpoint
2062
+ - Must be HTTPS in production
2063
+ - Example: \`https://yourdomain.com/api/payments/mpesa/callback\`
2064
+
2065
+ 2. **Handle Webhooks**
2066
+ \`\`\`typescript
2067
+ import { PaymentWebhookHandler } from './src/payments/WebhookHandler';
2068
+
2069
+ const webhookHandler = new PaymentWebhookHandler(paymentRegistry);
2070
+ app.post('/api/payments/mpesa/callback', webhookHandler.handleMPesaCallback);
2071
+ \`\`\`
2072
+
2073
+ ### Testing M-Pesa
2074
+
2075
+ 1. **Sandbox Testing**
2076
+ - Use test credentials from Safaricom
2077
+ - Use test phone numbers: 254708374149, 254711XXXXXX
2078
+ - No real money is charged
2079
+
2080
+ 2. **Production Testing**
2081
+ - Use real credentials
2082
+ - Test with small amounts first
2083
+ - Real money will be charged
2084
+
2085
+ ## Error Handling
2086
+
2087
+ All payment methods include comprehensive error handling:
2088
+
2089
+ \`\`\`typescript
2090
+ try {
2091
+ const result = await mpesa.processMPesaPayment('0712345678', 100);
2092
+ if (result.success) {
2093
+ console.log('Payment initiated successfully');
2094
+ } else {
2095
+ console.error('Payment failed:', result.error);
2096
+ }
2097
+ } catch (error) {
2098
+ console.error('Payment error:', error.message);
2099
+ }
2100
+ \`\`\`
2101
+
2102
+ ## Security Best Practices
2103
+
2104
+ 1. **Environment Variables**
2105
+ - Never commit API keys to version control
2106
+ - Use different credentials for sandbox/production
2107
+ - Rotate keys regularly
2108
+
2109
+ 2. **Webhook Security**
2110
+ - Validate webhook signatures
2111
+ - Use HTTPS for all webhook URLs
2112
+ - Implement idempotency for webhook processing
2113
+
2114
+ 3. **Error Logging**
2115
+ - Log all payment attempts
2116
+ - Monitor failed payments
2117
+ - Set up alerts for unusual activity
2118
+
2119
+ ## Production Checklist
2120
+
2121
+ - [ ] M-Pesa production credentials configured
2122
+ - [ ] Webhook URLs are HTTPS
2123
+ - [ ] Error monitoring set up
2124
+ - [ ] Payment logging implemented
2125
+ - [ ] Backup payment method available
2126
+ - [ ] Customer support process defined
2127
+ - [ ] Refund process documented
2128
+
2129
+ ## Support
2130
+
2131
+ - **M-Pesa**: developer.safaricom.co.ke
2132
+ - **Stripe**: stripe.com/docs
2133
+ - **PayPal**: developer.paypal.com
2134
+
2135
+ For implementation questions, check the example files in \`src/payments/\`.
2136
+ `;
2137
+ fs.writeFileSync(path.join(projectDir, 'PAYMENTS.md'), content);
2138
+ }
2139
+ getPersonalityPrompt(personality) {
2140
+ const presets = {
2141
+ helpful: 'You are a helpful AI assistant. You are friendly, supportive, and always try to provide useful information.',
2142
+ professional: 'You are a professional AI assistant. You communicate formally and focus on business objectives.',
2143
+ concise: 'You are a concise AI assistant. You provide brief, direct answers without unnecessary elaboration.',
2144
+ creative: 'You are a creative AI assistant. You think outside the box and offer imaginative solutions.',
2145
+ };
2146
+ return presets[personality] || personality;
2147
+ }
2148
+ getDefaultModel(provider) {
2149
+ const models = {
2150
+ openai: 'gpt-4',
2151
+ anthropic: 'claude-3-opus-20240229',
2152
+ local: 'llama2',
2153
+ };
2154
+ return models[provider] || 'gpt-4';
2155
+ }
2156
+ escapeString(str) {
2157
+ return str.replace(/'/g, "\\'").replace(/\n/g, '\\n');
2158
+ }
2159
+ printNextSteps(options) {
2160
+ const deploymentInstructions = this.getDeploymentInstructions(options);
2161
+ console.log(`
2162
+ ╔═══════════════════════════════════════════════════════════╗
2163
+ ║ 🎉 Success! ║
2164
+ ╚═══════════════════════════════════════════════════════════╝
2165
+
2166
+ Next steps:
2167
+
2168
+ cd ${options.projectName}
2169
+ npm install
2170
+
2171
+ # Configure your environment
2172
+ # Edit .env with your API keys and settings
2173
+
2174
+ ${options.typescript ? 'npm run dev' : 'npm start'}
2175
+
2176
+ ${deploymentInstructions}
2177
+
2178
+ Security Notes:
2179
+ ${options.security.includes('https-only') ? ' ✅ HTTPS security headers configured' : ''}
2180
+ ${options.security.includes('input-validation') ? ' ✅ Input validation schemas created' : ''}
2181
+ ${options.security.includes('jwt') ? ' ✅ JWT authentication ready' : ''}
2182
+ ${options.security.includes('rate-limiting') ? ' ✅ Rate limiting configured' : ''}
2183
+ ${options.security.includes('audit-logging') ? ' ✅ Audit logging enabled' : ''}
2184
+
2185
+ 📚 Documentation:
2186
+ - README.md - Getting started guide
2187
+ - SECURITY.md - Security configuration
2188
+ ${options.features.includes('payments') ? ' - PAYMENTS.md - Complete payment integration guide' : ''}
2189
+ ${options.deployment.length > 0 ? ' - Deployment files in project root' : ''}
2190
+
2191
+ 🔗 Resources:
2192
+ - AgentX Docs: https://agentx.dev/docs
2193
+ - Community: https://github.com/agentx/community
2194
+ `);
2195
+ }
2196
+ getDeploymentInstructions(options) {
2197
+ if (options.deployment.length === 0)
2198
+ return '';
2199
+ const instructions = ['Deployment Options:'];
2200
+ if (options.deployment.includes('docker')) {
2201
+ instructions.push(' 🐳 Docker: npm run docker:build && npm run docker:run');
2202
+ }
2203
+ if (options.deployment.includes('docker-compose')) {
2204
+ instructions.push(' 🐙 Docker Compose: npm run compose:up');
2205
+ }
2206
+ if (options.deployment.includes('kubernetes')) {
2207
+ instructions.push(' ☸️ Kubernetes: npm run k8s:deploy');
2208
+ }
2209
+ if (options.deployment.includes('railway')) {
2210
+ instructions.push(' 🚂 Railway: Connect your GitHub repo at railway.app');
2211
+ }
2212
+ if (options.deployment.includes('vercel')) {
2213
+ instructions.push(' ▲ Vercel: vercel --prod');
2214
+ }
2215
+ if (options.deployment.includes('aws-lambda')) {
2216
+ instructions.push(' λ AWS Lambda: Use serverless framework or AWS SAM');
2217
+ }
2218
+ if (options.deployment.includes('systemd')) {
2219
+ instructions.push(' 🐧 Linux Service: sudo ./install.sh');
2220
+ }
2221
+ return instructions.join('\n');
2222
+ }
2223
+ }
2224
+ exports.ProjectGenerator = ProjectGenerator;
2225
+ //# sourceMappingURL=InteractiveSetup.js.map