@agents-at-scale/ark 0.1.31

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 (76) hide show
  1. package/README.md +95 -0
  2. package/dist/commands/cluster/get-ip.d.ts +2 -0
  3. package/dist/commands/cluster/get-ip.js +32 -0
  4. package/dist/commands/cluster/get-type.d.ts +2 -0
  5. package/dist/commands/cluster/get-type.js +26 -0
  6. package/dist/commands/cluster/index.d.ts +2 -0
  7. package/dist/commands/cluster/index.js +10 -0
  8. package/dist/commands/completion.d.ts +2 -0
  9. package/dist/commands/completion.js +108 -0
  10. package/dist/commands/config.d.ts +5 -0
  11. package/dist/commands/config.js +327 -0
  12. package/dist/commands/generate/config.d.ts +145 -0
  13. package/dist/commands/generate/config.js +253 -0
  14. package/dist/commands/generate/generators/agent.d.ts +2 -0
  15. package/dist/commands/generate/generators/agent.js +156 -0
  16. package/dist/commands/generate/generators/index.d.ts +6 -0
  17. package/dist/commands/generate/generators/index.js +6 -0
  18. package/dist/commands/generate/generators/marketplace.d.ts +2 -0
  19. package/dist/commands/generate/generators/marketplace.js +304 -0
  20. package/dist/commands/generate/generators/mcpserver.d.ts +25 -0
  21. package/dist/commands/generate/generators/mcpserver.js +350 -0
  22. package/dist/commands/generate/generators/project.d.ts +2 -0
  23. package/dist/commands/generate/generators/project.js +784 -0
  24. package/dist/commands/generate/generators/query.d.ts +2 -0
  25. package/dist/commands/generate/generators/query.js +213 -0
  26. package/dist/commands/generate/generators/team.d.ts +2 -0
  27. package/dist/commands/generate/generators/team.js +407 -0
  28. package/dist/commands/generate/index.d.ts +24 -0
  29. package/dist/commands/generate/index.js +357 -0
  30. package/dist/commands/generate/templateDiscovery.d.ts +30 -0
  31. package/dist/commands/generate/templateDiscovery.js +94 -0
  32. package/dist/commands/generate/templateEngine.d.ts +78 -0
  33. package/dist/commands/generate/templateEngine.js +368 -0
  34. package/dist/commands/generate/utils/nameUtils.d.ts +35 -0
  35. package/dist/commands/generate/utils/nameUtils.js +110 -0
  36. package/dist/commands/generate/utils/projectUtils.d.ts +28 -0
  37. package/dist/commands/generate/utils/projectUtils.js +133 -0
  38. package/dist/components/DashboardCLI.d.ts +3 -0
  39. package/dist/components/DashboardCLI.js +149 -0
  40. package/dist/components/GeneratorUI.d.ts +3 -0
  41. package/dist/components/GeneratorUI.js +167 -0
  42. package/dist/components/statusChecker.d.ts +48 -0
  43. package/dist/components/statusChecker.js +251 -0
  44. package/dist/config.d.ts +42 -0
  45. package/dist/config.js +243 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +67 -0
  48. package/dist/lib/arkClient.d.ts +32 -0
  49. package/dist/lib/arkClient.js +43 -0
  50. package/dist/lib/cluster.d.ts +8 -0
  51. package/dist/lib/cluster.js +134 -0
  52. package/dist/lib/config.d.ts +82 -0
  53. package/dist/lib/config.js +223 -0
  54. package/dist/lib/consts.d.ts +10 -0
  55. package/dist/lib/consts.js +15 -0
  56. package/dist/lib/errors.d.ts +56 -0
  57. package/dist/lib/errors.js +208 -0
  58. package/dist/lib/exec.d.ts +5 -0
  59. package/dist/lib/exec.js +20 -0
  60. package/dist/lib/gatewayManager.d.ts +24 -0
  61. package/dist/lib/gatewayManager.js +85 -0
  62. package/dist/lib/kubernetes.d.ts +28 -0
  63. package/dist/lib/kubernetes.js +122 -0
  64. package/dist/lib/progress.d.ts +128 -0
  65. package/dist/lib/progress.js +273 -0
  66. package/dist/lib/security.d.ts +37 -0
  67. package/dist/lib/security.js +295 -0
  68. package/dist/lib/types.d.ts +37 -0
  69. package/dist/lib/types.js +1 -0
  70. package/dist/lib/wrappers/git.d.ts +2 -0
  71. package/dist/lib/wrappers/git.js +43 -0
  72. package/dist/ui/MainMenu.d.ts +3 -0
  73. package/dist/ui/MainMenu.js +116 -0
  74. package/dist/ui/statusFormatter.d.ts +9 -0
  75. package/dist/ui/statusFormatter.js +47 -0
  76. package/package.json +62 -0
@@ -0,0 +1,357 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { createProjectGenerator, createAgentGenerator, createTeamGenerator, createQueryGenerator, createMcpServerGenerator, createMarketplaceGenerator, } from './generators/index.js';
7
+ import { normalizeAndValidateName, getNameValidationError, } from './utils/nameUtils.js';
8
+ import { ErrorHandler, ArkError, ErrorCode } from '../../lib/errors.js';
9
+ function getDefaultDestination() {
10
+ try {
11
+ // Get the path to this file
12
+ const currentFile = fileURLToPath(import.meta.url);
13
+ // Navigate up from tools/ark-cli/src/commands/generate/index.js to agents-at-scale/
14
+ const arkRoot = path.resolve(path.dirname(currentFile), '../../../../../');
15
+ // Get the parent directory of agents-at-scale
16
+ const parentDir = path.dirname(arkRoot);
17
+ return parentDir;
18
+ }
19
+ catch (_error) {
20
+ // Fallback to current working directory if we can't determine ark location
21
+ console.warn('Could not determine ark repository location, using current directory');
22
+ return process.cwd();
23
+ }
24
+ }
25
+ export function createGenerateCommand() {
26
+ const generate = new Command('generate');
27
+ generate
28
+ .alias('g')
29
+ .description('Generate ARK resources from templates (projects, agents, teams, queries, mcp-servers, marketplace)')
30
+ .helpOption('-h, --help', 'Display help for the generate command')
31
+ .addHelpText('before', `
32
+ ${chalk.blue('🎯 ARK Generator')}
33
+ Create new ARK resources quickly using interactive templates.
34
+
35
+ ${chalk.cyan('Available generators:')}
36
+ • project - Complete ARK project with structure, CI/CD, and samples
37
+ • agent - Single AI agent definition
38
+ • team - Team of collaborative agents
39
+ • query - Query to test agents or teams
40
+ • mcp-server - MCP server with Kubernetes deployment
41
+ • marketplace - Central repository for sharing reusable components
42
+ `)
43
+ .addHelpText('after', `
44
+ ${chalk.cyan('Examples:')}
45
+ ${chalk.yellow('ark g project')} # Create project with prompts
46
+ ${chalk.yellow('ark g agent')} # Create an agent
47
+ ${chalk.yellow('ark g team')} # Create a team
48
+ ${chalk.yellow('ark g query')} # Create a query
49
+ ${chalk.yellow('ark g mcp-server')} # Create MCP server
50
+ ${chalk.yellow('ark g marketplace')} # Create marketplace
51
+
52
+ ${chalk.cyan('Usage:')}
53
+ Generators will prompt for required information when not provided via options.
54
+
55
+ ${chalk.cyan('Getting started:')}
56
+ 1. ${chalk.yellow('ark generate project my-first-project')} # Create project
57
+ 2. ${chalk.yellow('cd my-first-project')} # Enter directory
58
+ 3. ${chalk.yellow('source .env')} # Set environment
59
+ 4. ${chalk.yellow('make quickstart')} # Deploy to cluster
60
+ `);
61
+ // Register generators
62
+ const generators = new Map();
63
+ // Register built-in generators
64
+ generators.set('project', createProjectGenerator());
65
+ generators.set('agent', createAgentGenerator());
66
+ generators.set('team', createTeamGenerator());
67
+ generators.set('query', createQueryGenerator());
68
+ generators.set('mcp-server', createMcpServerGenerator());
69
+ generators.set('marketplace', createMarketplaceGenerator());
70
+ // Add subcommands for each generator
71
+ for (const [type, generator] of generators) {
72
+ const subCommand = new Command(type);
73
+ // Enhanced descriptions and help text per generator type
74
+ const helpTexts = {
75
+ project: {
76
+ description: `${generator.description}
77
+
78
+ ${chalk.cyan('Features:')}
79
+ • Complete project structure with Helm charts
80
+ • CI/CD pipeline with GitHub Actions
81
+ • Sample agents, teams, and queries
82
+ • Model configurations for major providers
83
+ • Security best practices and RBAC
84
+ • Comprehensive documentation`,
85
+ examples: `
86
+ ${chalk.cyan('Examples:')}
87
+ ${chalk.yellow(`ark g project`)}
88
+ ${chalk.yellow(`ark generate project customer-service`)}
89
+
90
+ ${chalk.cyan('Options:')}
91
+ --project-type Project type: 'empty' or 'with-samples' (default: with-samples)
92
+ --namespace Kubernetes namespace (default: project name)
93
+ --skip-models Skip model provider configuration
94
+ --skip-git Skip git repository initialization`,
95
+ },
96
+ agent: {
97
+ description: `${generator.description}
98
+
99
+ ${chalk.cyan('Features:')}
100
+ • Creates agent YAML definition
101
+ • Validates project structure
102
+ • Optional query generation for testing
103
+ • Handles name conflicts gracefully`,
104
+ examples: `
105
+ ${chalk.cyan('Examples:')}
106
+ ${chalk.yellow(`ark generate agent customer-support`)}
107
+ ${chalk.yellow(`ark g agent`)}
108
+
109
+ ${chalk.cyan('Requirements:')}
110
+ • Must be run within an ARK project directory
111
+ • Project must have valid Chart.yaml and agents/ directory`,
112
+ },
113
+ team: {
114
+ description: `${generator.description}
115
+
116
+ ${chalk.cyan('Features:')}
117
+ • Interactive agent selection
118
+ • Multiple collaboration strategies
119
+ • Can create new agents on-the-fly
120
+ • Optional query generation for testing`,
121
+ examples: `
122
+ ${chalk.cyan('Examples:')}
123
+ ${chalk.yellow(`ark generate team research-team`)}
124
+ ${chalk.yellow(`ark g team support-escalation`)}
125
+
126
+ ${chalk.cyan('Strategies:')}
127
+ • sequential - Agents work in order
128
+ • round-robin - Agents take turns
129
+ • graph - Custom workflow with dependencies
130
+ • selector - AI chooses the next agent`,
131
+ },
132
+ query: {
133
+ description: `${generator.description}
134
+
135
+ ${chalk.cyan('Features:')}
136
+ • Interactive agent or team selection
137
+ • Customisable input message
138
+ • Automatic queries directory creation
139
+ • Validates project structure`,
140
+ examples: `
141
+ ${chalk.cyan('Examples:')}
142
+ ${chalk.yellow(`ark g query`)}
143
+ ${chalk.yellow(`ark generate query user-interaction`)}
144
+
145
+ ${chalk.cyan('Requirements:')}
146
+ • Must be run within an ARK project directory
147
+ • Target agent or team should exist (or will be created manually)`,
148
+ },
149
+ 'mcp-server': {
150
+ description: `${generator.description}
151
+
152
+ ${chalk.cyan('Features:')}
153
+ • Multi-technology support (Node.js, Deno, Go, Python)
154
+ • Complete Kubernetes deployment with Helm charts
155
+ • Docker containerization with mcp-proxy
156
+ • Authentication and configuration options
157
+ • Example agents and queries included
158
+ • Production-ready with security best practices`,
159
+ examples: `
160
+ ${chalk.cyan('Examples:')}
161
+ ${chalk.yellow(`ark g mcp-server`)}
162
+ ${chalk.yellow(`ark generate mcp-server github-tools`)}
163
+
164
+ ${chalk.cyan('Technologies:')}
165
+ • node - Node.js with NPM packages or local development
166
+ • deno - Deno with JSR packages or local development
167
+ • go - Go with go install packages or local development
168
+ • python - Python with pip packages or local development
169
+
170
+ ${chalk.cyan('Features:')}
171
+ • Authentication support for secured APIs
172
+ • Custom configuration for flexible deployment
173
+ • Example agent and query generation
174
+ • Kubernetes-native with MCPServer CRD integration`,
175
+ },
176
+ marketplace: {
177
+ description: `${generator.description}
178
+
179
+ ${chalk.cyan('Features:')}
180
+ • Central repository structure for component sharing
181
+ • Organized directories for all ARK component types
182
+ • Built-in contribution guidelines and documentation
183
+ • Git repository initialization with best practices
184
+ • Ready for CI/CD integration and automated validation
185
+ • Component templates for easy contribution`,
186
+ examples: `
187
+ ${chalk.cyan('Examples:')}
188
+ ${chalk.yellow(`ark g marketplace`)}
189
+
190
+ ${chalk.cyan('Structure:')}
191
+ • agents/ - Reusable agent definitions
192
+ • teams/ - Multi-agent workflow configurations
193
+ • models/ - Model configurations by provider
194
+ • queries/ - Query templates and patterns
195
+ • tools/ - Tool definitions and implementations
196
+ • mcp-servers/ - MCP server configurations
197
+ • docs/ - Documentation and guides
198
+
199
+ ${chalk.cyan('Use Cases:')}
200
+ • Team sharing of proven agent configurations
201
+ • Cross-project component libraries
202
+ • Community marketplace for ARK resources
203
+ • Internal organization component registry`,
204
+ },
205
+ };
206
+ const helpText = helpTexts[type];
207
+ subCommand
208
+ .description(helpText?.description || generator.description)
209
+ .argument('[name]', type === 'marketplace'
210
+ ? 'Ignored - marketplace is always named "ark-marketplace"'
211
+ : `Name of the ${type} to generate`)
212
+ .option('-d, --destination <path>', type === 'project' || type === 'marketplace'
213
+ ? 'Parent directory for the project (default: directory above ark)'
214
+ : 'Working directory (default: current directory)', type === 'project' || type === 'marketplace'
215
+ ? getDefaultDestination()
216
+ : undefined)
217
+ .option('-i, --interactive', type === 'marketplace'
218
+ ? 'Not supported for marketplace'
219
+ : 'Force additional configuration prompts (generators prompt by default when info is missing)', false);
220
+ if (helpText?.examples) {
221
+ subCommand.addHelpText('after', helpText.examples);
222
+ }
223
+ // Add project-specific options
224
+ if (type === 'project') {
225
+ subCommand
226
+ .option('-t, --project-type <type>', 'Project type (empty or with-samples)')
227
+ .option('-n, --namespace <namespace>', 'Kubernetes namespace (defaults to project name)')
228
+ .option('--skip-models', 'Skip model configuration', false)
229
+ .option('--skip-git', 'Skip git setup', false)
230
+ .option('--selected-models <models>', 'Selected model configuration (default, aigw, all, none)')
231
+ .option('--azure-api-key <key>', 'Azure OpenAI API key')
232
+ .option('--azure-base-url <url>', 'Azure OpenAI Base URL')
233
+ .option('--aigw-base-url <url>', 'AI Gateway Base URL')
234
+ .option('--git-user-name <name>', 'Git user name')
235
+ .option('--git-user-email <email>', 'Git user email')
236
+ .option('--git-create-commit', 'Create initial git commit', false);
237
+ }
238
+ subCommand.action(async (name, options) => {
239
+ await ErrorHandler.catchAndHandle(async () => {
240
+ let itemName = name;
241
+ let destination;
242
+ if (options.destination) {
243
+ destination = options.destination;
244
+ }
245
+ else if (type === 'project' || type === 'marketplace') {
246
+ destination = getDefaultDestination();
247
+ }
248
+ else {
249
+ destination = process.cwd();
250
+ }
251
+ // If no name provided or interactive mode, prompt for details
252
+ // Special case: marketplace always uses "ark-marketplace"
253
+ if (type === 'marketplace') {
254
+ itemName = 'ark-marketplace';
255
+ }
256
+ else if (!itemName || options.interactive) {
257
+ const answers = await inquirer.prompt([
258
+ {
259
+ type: 'input',
260
+ name: 'name',
261
+ message: `What name would you like to use for the ${type}?`,
262
+ default: itemName,
263
+ validate: (input) => {
264
+ const error = getNameValidationError(input);
265
+ return error || true;
266
+ },
267
+ filter: (input) => {
268
+ try {
269
+ const { name } = normalizeAndValidateName(input, type);
270
+ return name;
271
+ }
272
+ catch {
273
+ return input; // Let validate handle the error
274
+ }
275
+ },
276
+ },
277
+ {
278
+ type: 'input',
279
+ name: 'destination',
280
+ message: 'Where would you like to generate it?',
281
+ default: destination,
282
+ when: () => options.interactive && type === 'project',
283
+ },
284
+ ]);
285
+ itemName = answers.name;
286
+ if (answers.destination) {
287
+ destination = answers.destination;
288
+ }
289
+ }
290
+ // Validate the final name (skip for marketplace as it's fixed)
291
+ if (!itemName && type !== 'marketplace') {
292
+ throw new ArkError(`${type} name is required`, ErrorCode.INVALID_INPUT, undefined, [
293
+ `Provide a name for the ${type}`,
294
+ `Use: ark generate ${type} <name>`,
295
+ ]);
296
+ }
297
+ // Normalize name if provided as argument (not already normalized via prompts)
298
+ if (name && !options.interactive && type !== 'marketplace') {
299
+ const { name: normalizedName, wasTransformed } = normalizeAndValidateName(itemName, type);
300
+ if (wasTransformed) {
301
+ console.log(chalk.yellow(`📝 Name normalized: "${itemName}" → "${normalizedName}"`));
302
+ itemName = normalizedName;
303
+ }
304
+ }
305
+ console.log(chalk.blue(`\n🔧 Generating ${type}: ${itemName}`));
306
+ console.log(chalk.gray(`📁 Project directory: ${destination}\n`));
307
+ await generator.generate(itemName, destination, options);
308
+ console.log(chalk.green(`\n✅ Successfully generated ${type}: ${itemName}`));
309
+ }, `Generating ${type}`).catch((error) => ErrorHandler.handleAndExit(error));
310
+ });
311
+ generate.addCommand(subCommand);
312
+ }
313
+ // Add a list command to show available generators
314
+ const listCommand = new Command('list');
315
+ listCommand
316
+ .alias('ls')
317
+ .description('List available generators with detailed information')
318
+ .option('--detailed', 'Show detailed information for each generator', false)
319
+ .action((options) => {
320
+ console.log(chalk.blue('\n🎯 ARK Generators\n'));
321
+ for (const [type, generator] of generators) {
322
+ const icon = type === 'project'
323
+ ? '📦'
324
+ : type === 'agent'
325
+ ? '🤖'
326
+ : type === 'team'
327
+ ? '👥'
328
+ : type === 'query'
329
+ ? '🔍'
330
+ : '❓';
331
+ console.log(`${icon} ${chalk.green(type.padEnd(12))} ${chalk.gray(generator.description)}`);
332
+ if (options.detailed) {
333
+ const examples = {
334
+ project: 'ark g project my-ai-project',
335
+ agent: 'ark g agent customer-support',
336
+ team: 'ark g team research-team',
337
+ query: 'ark g query test-conversation',
338
+ };
339
+ console.log(chalk.gray(` Example: ${examples[type] || `ark g ${type} my-${type}`}\n`));
340
+ }
341
+ }
342
+ if (!options.detailed) {
343
+ console.log(chalk.gray('\n💡 Use --detailed for examples and more information'));
344
+ }
345
+ console.log(chalk.cyan('\n📖 Quick Start:'));
346
+ console.log(chalk.gray(' 1. ark generate project my-first-project'));
347
+ console.log(chalk.gray(' 2. cd my-first-project && source .env'));
348
+ console.log(chalk.gray(' 3. make quickstart'));
349
+ console.log(chalk.cyan('\n🔧 Usage:'));
350
+ console.log(chalk.gray(' ark generate <type> [name] [options]'));
351
+ console.log(chalk.gray(' ark g <type> [name] [options]'));
352
+ console.log(chalk.gray(' ark generate <type> --help'));
353
+ console.log();
354
+ });
355
+ generate.addCommand(listCommand);
356
+ return generate;
357
+ }
@@ -0,0 +1,30 @@
1
+ export interface TemplateInfo {
2
+ name: string;
3
+ path: string;
4
+ description?: string;
5
+ type: 'project' | 'tool' | 'component';
6
+ }
7
+ export declare class TemplateDiscovery {
8
+ private templatesPath;
9
+ constructor();
10
+ /**
11
+ * Discover all available templates in the templates directory
12
+ */
13
+ discoverTemplates(): Promise<TemplateInfo[]>;
14
+ /**
15
+ * Get the absolute path to a template
16
+ */
17
+ getTemplatePath(templateName: string): string;
18
+ /**
19
+ * Check if a template exists
20
+ */
21
+ templateExists(templateName: string): boolean;
22
+ /**
23
+ * Analyze a template directory to extract metadata
24
+ */
25
+ private analyzeTemplate;
26
+ /**
27
+ * Check if a template directory contains a specific file
28
+ */
29
+ private hasFile;
30
+ }
@@ -0,0 +1,94 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ export class TemplateDiscovery {
5
+ constructor() {
6
+ // Get the path to the templates directory relative to the ark CLI
7
+ // Navigate from tools/ark-cli/src/commands/generate/templateDiscovery.js to agents-at-scale/templates
8
+ const currentFile = fileURLToPath(import.meta.url);
9
+ const arkRoot = path.resolve(path.dirname(currentFile), '../../../../../');
10
+ this.templatesPath = path.join(arkRoot, 'templates');
11
+ }
12
+ /**
13
+ * Discover all available templates in the templates directory
14
+ */
15
+ async discoverTemplates() {
16
+ const templates = [];
17
+ try {
18
+ if (!fs.existsSync(this.templatesPath)) {
19
+ console.warn(`Templates directory not found at: ${this.templatesPath}`);
20
+ return templates;
21
+ }
22
+ const entries = fs.readdirSync(this.templatesPath, {
23
+ withFileTypes: true,
24
+ });
25
+ for (const entry of entries) {
26
+ if (entry.isDirectory()) {
27
+ const templatePath = path.join(this.templatesPath, entry.name);
28
+ const templateInfo = await this.analyzeTemplate(entry.name, templatePath);
29
+ if (templateInfo) {
30
+ templates.push(templateInfo);
31
+ }
32
+ }
33
+ }
34
+ }
35
+ catch (error) {
36
+ console.warn(`Failed to discover templates: ${error}`);
37
+ }
38
+ return templates;
39
+ }
40
+ /**
41
+ * Get the absolute path to a template
42
+ */
43
+ getTemplatePath(templateName) {
44
+ return path.join(this.templatesPath, templateName);
45
+ }
46
+ /**
47
+ * Check if a template exists
48
+ */
49
+ templateExists(templateName) {
50
+ const templatePath = this.getTemplatePath(templateName);
51
+ return (fs.existsSync(templatePath) && fs.statSync(templatePath).isDirectory());
52
+ }
53
+ /**
54
+ * Analyze a template directory to extract metadata
55
+ */
56
+ async analyzeTemplate(name, templatePath) {
57
+ try {
58
+ let description = '';
59
+ let type = 'component';
60
+ // Try to read description from README.md
61
+ const readmePath = path.join(templatePath, 'README.md');
62
+ if (fs.existsSync(readmePath)) {
63
+ const readmeContent = fs.readFileSync(readmePath, 'utf-8');
64
+ // Extract first line as description (remove # if present)
65
+ const firstLine = readmeContent.split('\n')[0];
66
+ description = firstLine.replace(/^#\s*/, '').trim();
67
+ }
68
+ // Determine template type based on content
69
+ if (this.hasFile(templatePath, 'Chart.yaml')) {
70
+ type = 'project';
71
+ }
72
+ else if (this.hasFile(templatePath, 'pyproject.toml') ||
73
+ this.hasFile(templatePath, 'main.py')) {
74
+ type = 'tool';
75
+ }
76
+ return {
77
+ name,
78
+ path: templatePath,
79
+ description,
80
+ type,
81
+ };
82
+ }
83
+ catch (error) {
84
+ console.warn(`Failed to analyze template ${name}: ${error}`);
85
+ return null;
86
+ }
87
+ }
88
+ /**
89
+ * Check if a template directory contains a specific file
90
+ */
91
+ hasFile(templatePath, fileName) {
92
+ return fs.existsSync(path.join(templatePath, fileName));
93
+ }
94
+ }
@@ -0,0 +1,78 @@
1
+ export interface TemplateVariables {
2
+ [key: string]: string | number | boolean;
3
+ }
4
+ export interface TemplateOptions {
5
+ skipIfExists?: boolean;
6
+ createDirectories?: boolean;
7
+ exclude?: string[];
8
+ include?: string[];
9
+ }
10
+ export declare class TemplateEngine {
11
+ private variables;
12
+ /**
13
+ * Set template variables for substitution
14
+ */
15
+ setVariables(variables: TemplateVariables): void;
16
+ /**
17
+ * Get current template variables
18
+ */
19
+ getVariables(): TemplateVariables;
20
+ /**
21
+ * Process a template directory and copy it to destination
22
+ */
23
+ processTemplate(templatePath: string, destinationPath: string, options?: TemplateOptions): Promise<void>;
24
+ /**
25
+ * Process a single template file
26
+ */
27
+ processFile(templateFilePath: string, destinationFilePath: string, options?: {
28
+ skipIfExists?: boolean;
29
+ baseDir?: string;
30
+ }): Promise<void>;
31
+ /**
32
+ * Substitute template variables in content
33
+ */
34
+ private substituteVariables;
35
+ /**
36
+ * Substitute variables in file/directory names
37
+ */
38
+ private substituteVariablesInPath;
39
+ /**
40
+ * Derive destination filename from template name
41
+ */
42
+ private deriveDestinationFilename;
43
+ /**
44
+ * Copy directory recursively with template processing
45
+ */
46
+ private copyDirectory;
47
+ private shouldProcessEntry;
48
+ private processDirectory;
49
+ private processFileEntry;
50
+ /**
51
+ * Ensure a directory exists, creating it if necessary
52
+ */
53
+ private ensureDirectory;
54
+ /**
55
+ * Safely ensure a directory exists with security validation
56
+ */
57
+ private ensureDirectorySafe;
58
+ /**
59
+ * Check if a file should be excluded
60
+ */
61
+ private shouldExclude;
62
+ /**
63
+ * Check if a file should be included
64
+ */
65
+ private shouldInclude;
66
+ /**
67
+ * Check if a file is a text file that should have variable substitution
68
+ */
69
+ private isTextFile;
70
+ /**
71
+ * Check if a file path represents important generated content
72
+ */
73
+ private isImportantContent;
74
+ /**
75
+ * Get relative path from a full file path for display
76
+ */
77
+ private getRelativePath;
78
+ }