@claudetools/tools 0.9.0 → 0.9.2

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 (85) hide show
  1. package/dist/cli.js +9 -1
  2. package/dist/codedna/__tests__/examples/mongoose-example.d.ts +6 -0
  3. package/dist/codedna/__tests__/examples/mongoose-example.js +163 -0
  4. package/dist/codedna/__tests__/fixtures/typeorm-production-test.d.ts +1 -0
  5. package/dist/codedna/__tests__/fixtures/typeorm-production-test.js +231 -0
  6. package/dist/codedna/__tests__/fixtures/typeorm-test.d.ts +1 -0
  7. package/dist/codedna/__tests__/fixtures/typeorm-test.js +124 -0
  8. package/dist/codedna/__tests__/laravel-output-review.d.ts +1 -0
  9. package/dist/codedna/__tests__/laravel-output-review.js +249 -0
  10. package/dist/codedna/__tests__/mongoose-output-test.d.ts +1 -0
  11. package/dist/codedna/__tests__/mongoose-output-test.js +178 -0
  12. package/dist/codedna/examples/radix-example.d.ts +2 -0
  13. package/dist/codedna/examples/radix-example.js +259 -0
  14. package/dist/codedna/index.d.ts +5 -3
  15. package/dist/codedna/index.js +6 -3
  16. package/dist/codedna/kappa-ast.d.ts +143 -5
  17. package/dist/codedna/kappa-drizzle-generator.js +8 -5
  18. package/dist/codedna/kappa-gofiber-generator.d.ts +65 -0
  19. package/dist/codedna/kappa-gofiber-generator.js +587 -0
  20. package/dist/codedna/kappa-laravel-generator.d.ts +68 -0
  21. package/dist/codedna/kappa-laravel-generator.js +741 -0
  22. package/dist/codedna/kappa-lexer.d.ts +44 -0
  23. package/dist/codedna/kappa-lexer.js +124 -0
  24. package/dist/codedna/kappa-mantine-generator.d.ts +65 -0
  25. package/dist/codedna/kappa-mantine-generator.js +518 -0
  26. package/dist/codedna/kappa-mongoose-generator.d.ts +44 -0
  27. package/dist/codedna/kappa-mongoose-generator.js +442 -0
  28. package/dist/codedna/kappa-parser.d.ts +43 -1
  29. package/dist/codedna/kappa-parser.js +601 -0
  30. package/dist/codedna/kappa-radix-generator.d.ts +61 -0
  31. package/dist/codedna/kappa-radix-generator.js +566 -0
  32. package/dist/codedna/kappa-typeorm-generator.d.ts +59 -0
  33. package/dist/codedna/kappa-typeorm-generator.js +723 -0
  34. package/dist/codedna/kappa-vitest-generator.d.ts +85 -0
  35. package/dist/codedna/kappa-vitest-generator.js +739 -0
  36. package/dist/codedna/parser.js +26 -1
  37. package/dist/codegen/cloud-client.d.ts +160 -0
  38. package/dist/codegen/cloud-client.js +195 -0
  39. package/dist/codegen/codegen-tool.d.ts +35 -0
  40. package/dist/codegen/codegen-tool.js +312 -0
  41. package/dist/codegen/field-inference.d.ts +24 -0
  42. package/dist/codegen/field-inference.js +101 -0
  43. package/dist/codegen/form-parser.d.ts +13 -0
  44. package/dist/codegen/form-parser.js +186 -0
  45. package/dist/codegen/index.d.ts +2 -0
  46. package/dist/codegen/index.js +4 -0
  47. package/dist/codegen/natural-parser.d.ts +50 -0
  48. package/dist/codegen/natural-parser.js +769 -0
  49. package/dist/handlers/codedna-handlers.d.ts +1 -1
  50. package/dist/handlers/codegen-handlers.d.ts +20 -0
  51. package/dist/handlers/codegen-handlers.js +60 -0
  52. package/dist/handlers/kappa-handlers.d.ts +97 -0
  53. package/dist/handlers/kappa-handlers.js +408 -0
  54. package/dist/handlers/tool-handlers.js +124 -221
  55. package/dist/helpers/api-client.js +48 -3
  56. package/dist/helpers/compact-formatter.d.ts +9 -2
  57. package/dist/helpers/compact-formatter.js +26 -2
  58. package/dist/helpers/config.d.ts +7 -2
  59. package/dist/helpers/config.js +25 -10
  60. package/dist/helpers/session-validation.d.ts +1 -1
  61. package/dist/helpers/session-validation.js +2 -4
  62. package/dist/helpers/tasks.d.ts +21 -0
  63. package/dist/helpers/tasks.js +52 -0
  64. package/dist/helpers/workers.d.ts +1 -1
  65. package/dist/helpers/workers.js +19 -19
  66. package/dist/setup.d.ts +1 -0
  67. package/dist/setup.js +228 -3
  68. package/dist/templates/claude-md.d.ts +1 -1
  69. package/dist/templates/claude-md.js +37 -152
  70. package/dist/templates/orchestrator-prompt.d.ts +2 -2
  71. package/dist/templates/orchestrator-prompt.js +31 -38
  72. package/dist/templates/self-critique.d.ts +50 -0
  73. package/dist/templates/self-critique.js +209 -0
  74. package/dist/templates/worker-prompt.d.ts +3 -3
  75. package/dist/templates/worker-prompt.js +18 -18
  76. package/dist/tools.js +77 -413
  77. package/docs/codedna/generator-testing-summary.md +205 -0
  78. package/docs/codedna/radix-ui-generator.md +478 -0
  79. package/docs/kappa-gofiber-generator.md +274 -0
  80. package/docs/kappa-laravel-fixes.md +172 -0
  81. package/docs/kappa-mongoose-generator.md +322 -0
  82. package/docs/kappa-vitest-generator.md +337 -0
  83. package/package.json +1 -1
  84. package/dist/context/deduplication.test.d.ts +0 -6
  85. package/dist/context/deduplication.test.js +0 -84
@@ -79,7 +79,16 @@ export class EntityParser {
79
79
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
80
80
  throw new Error(`Invalid field name: ${name}`);
81
81
  }
82
- const type = this.parseType(typeStr);
82
+ let type = this.parseType(typeStr);
83
+ // Check for relationship annotations (one-to-many, many-to-many) in constraints
84
+ // These modify reference types to add relation metadata
85
+ const relationIndex = constraintStrs.findIndex(c => c === 'one-to-many' || c === 'many-to-many');
86
+ if (relationIndex !== -1 && type.kind === 'reference') {
87
+ const relation = constraintStrs[relationIndex] === 'one-to-many' ? 'oneToMany' : 'manyToMany';
88
+ type = { ...type, relation };
89
+ // Remove the relation annotation from constraints since it's been applied to the type
90
+ constraintStrs.splice(relationIndex, 1);
91
+ }
83
92
  const constraints = constraintStrs.map(c => this.parseConstraint(c));
84
93
  return { name, type, constraints };
85
94
  }
@@ -103,6 +112,22 @@ export class EntityParser {
103
112
  if (refMatch) {
104
113
  return { kind: 'reference', entity: refMatch[1] };
105
114
  }
115
+ // Check for array notation: EntityName[] (reference array)
116
+ const refArrayMatch = typeStr.match(/^([A-Z][a-zA-Z0-9]*)\[\]$/);
117
+ if (refArrayMatch) {
118
+ return { kind: 'reference', entity: refArrayMatch[1] };
119
+ }
120
+ // Check for simple reference: EntityName (capitalized = entity reference)
121
+ const entityRefMatch = typeStr.match(/^([A-Z][a-zA-Z0-9]*)$/);
122
+ if (entityRefMatch) {
123
+ return { kind: 'reference', entity: entityRefMatch[1] };
124
+ }
125
+ // Check for primitive array: string[], integer[], boolean[], decimal[]
126
+ const primitiveArrayMatch = typeStr.match(/^(string|integer|decimal|boolean)\[\]$/);
127
+ if (primitiveArrayMatch) {
128
+ const itemType = primitiveArrayMatch[1];
129
+ return { kind: 'array', itemType };
130
+ }
106
131
  // Check for array: array(string), array(integer), etc.
107
132
  const arrayMatch = typeStr.match(/^array\((string|integer|decimal|boolean)\)$/);
108
133
  if (arrayMatch) {
@@ -0,0 +1,160 @@
1
+ export interface CloudCodegenConfig {
2
+ /** API base URL (default: https://api.claudetools.dev) */
3
+ apiUrl?: string;
4
+ /** API key for authentication */
5
+ apiKey?: string;
6
+ /** User ID for analytics */
7
+ userId?: string;
8
+ /** Project ID for analytics */
9
+ projectId?: string;
10
+ /** Request timeout in ms (default: 30000) */
11
+ timeout?: number;
12
+ }
13
+ export interface CodegenInput {
14
+ /** Natural language description */
15
+ describe: string;
16
+ /** What to generate (schema, types, validators, api, components, forms, pages, tests, all) */
17
+ generate?: string[];
18
+ /** Override auto-detected stack */
19
+ stack?: {
20
+ orm?: string;
21
+ api?: string;
22
+ ui?: string;
23
+ db?: string;
24
+ framework?: string;
25
+ };
26
+ }
27
+ export interface GeneratedFile {
28
+ path: string;
29
+ content: string;
30
+ description: string;
31
+ }
32
+ export interface CodegenResult {
33
+ success: boolean;
34
+ files: GeneratedFile[];
35
+ entities: string[];
36
+ summary: string;
37
+ errors?: string[];
38
+ /** Generation time in ms */
39
+ generationTimeMs?: number;
40
+ /** Generators used */
41
+ generators?: Array<{
42
+ id: string;
43
+ name: string;
44
+ category: string;
45
+ }>;
46
+ }
47
+ export interface GeneratorInfo {
48
+ id: string;
49
+ name: string;
50
+ slug: string;
51
+ description: string;
52
+ category: string;
53
+ categoryName: string;
54
+ qualityScore: number;
55
+ usageCount: number;
56
+ version: string;
57
+ outputFiles: string[];
58
+ dependencies: string[];
59
+ }
60
+ export interface CategoryInfo {
61
+ id: string;
62
+ name: string;
63
+ description: string;
64
+ parentId: string | null;
65
+ icon: string | null;
66
+ generatorCount: number;
67
+ }
68
+ export interface FrameworkInfo {
69
+ id: string;
70
+ name: string;
71
+ packageName: string;
72
+ currentVersion: string;
73
+ language: string;
74
+ ecosystem: string;
75
+ generatorCount: number;
76
+ }
77
+ export declare class CloudCodegenClient {
78
+ private config;
79
+ constructor(config?: CloudCodegenConfig);
80
+ /**
81
+ * Generate code from natural language description
82
+ */
83
+ generate(input: CodegenInput): Promise<CodegenResult>;
84
+ /**
85
+ * List available generators
86
+ */
87
+ listGenerators(options?: {
88
+ category?: string;
89
+ framework?: string;
90
+ status?: string;
91
+ }): Promise<GeneratorInfo[]>;
92
+ /**
93
+ * Get generator details
94
+ */
95
+ getGenerator(id: string): Promise<GeneratorInfo & {
96
+ frameworks: Array<{
97
+ id: string;
98
+ name: string;
99
+ language: string;
100
+ minVersion: string;
101
+ maxVersion: string;
102
+ isPrimary: boolean;
103
+ }>;
104
+ recentVersions: Array<{
105
+ version: string;
106
+ changelog: string;
107
+ qualityScore: number;
108
+ createdAt: string;
109
+ }>;
110
+ }>;
111
+ /**
112
+ * List categories
113
+ */
114
+ listCategories(): Promise<CategoryInfo[]>;
115
+ /**
116
+ * List frameworks
117
+ */
118
+ listFrameworks(language?: string): Promise<{
119
+ frameworks: FrameworkInfo[];
120
+ byLanguage: Record<string, FrameworkInfo[]>;
121
+ languages: string[];
122
+ }>;
123
+ /**
124
+ * Check API health
125
+ */
126
+ health(): Promise<{
127
+ status: string;
128
+ timestamp: string;
129
+ services: {
130
+ database: boolean;
131
+ storage: boolean;
132
+ };
133
+ stats: {
134
+ publishedGenerators: number;
135
+ categories: number;
136
+ frameworks: number;
137
+ totalUsage: number;
138
+ averageQuality: number;
139
+ };
140
+ }>;
141
+ private fetch;
142
+ }
143
+ /**
144
+ * Generate code using the cloud API
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * const result = await cloudCodegen({
149
+ * describe: 'User with email, password, role (admin/user)',
150
+ * generate: ['schema', 'types', 'api'],
151
+ * stack: { orm: 'drizzle', api: 'hono' }
152
+ * });
153
+ *
154
+ * for (const file of result.files) {
155
+ * console.log(`${file.path}: ${file.description}`);
156
+ * }
157
+ * ```
158
+ */
159
+ export declare function cloudCodegen(input: CodegenInput, config?: CloudCodegenConfig): Promise<CodegenResult>;
160
+ export declare const defaultClient: CloudCodegenClient;
@@ -0,0 +1,195 @@
1
+ // =============================================================================
2
+ // Codegen Cloud Client
3
+ // =============================================================================
4
+ //
5
+ // Thin client that delegates ALL code generation to the cloud API.
6
+ // No local parsing or generation - cloud handles everything.
7
+ //
8
+ // =============================================================================
9
+ // =============================================================================
10
+ // Cloud Client
11
+ // =============================================================================
12
+ export class CloudCodegenClient {
13
+ config;
14
+ constructor(config = {}) {
15
+ this.config = {
16
+ apiUrl: config.apiUrl || 'https://api.claudetools.dev',
17
+ apiKey: config.apiKey || '',
18
+ userId: config.userId || '',
19
+ projectId: config.projectId || '',
20
+ timeout: config.timeout || 30000,
21
+ };
22
+ }
23
+ /**
24
+ * Generate code from natural language description
25
+ */
26
+ async generate(input) {
27
+ if (!input.describe || input.describe.trim() === '') {
28
+ return {
29
+ success: false,
30
+ files: [],
31
+ entities: [],
32
+ summary: 'Missing description',
33
+ errors: ['Please provide a description of what to generate'],
34
+ };
35
+ }
36
+ try {
37
+ const response = await this.fetch('/api/v1/codegen/generate', {
38
+ method: 'POST',
39
+ body: JSON.stringify({
40
+ describe: input.describe,
41
+ generate: input.generate || ['schema', 'types', 'validators'],
42
+ stack: input.stack,
43
+ userId: this.config.userId,
44
+ projectId: this.config.projectId,
45
+ }),
46
+ });
47
+ if (!response.success) {
48
+ return {
49
+ success: false,
50
+ files: [],
51
+ entities: [],
52
+ summary: response.error || 'Generation failed',
53
+ errors: [response.error || 'Unknown error'],
54
+ };
55
+ }
56
+ const data = response.data;
57
+ return {
58
+ success: true,
59
+ files: data.files || [],
60
+ entities: data.entities || [],
61
+ summary: data.summary || `Generated ${data.files?.length || 0} files`,
62
+ generators: data.generators,
63
+ generationTimeMs: data.generationTimeMs,
64
+ errors: data.errors,
65
+ };
66
+ }
67
+ catch (error) {
68
+ return {
69
+ success: false,
70
+ files: [],
71
+ entities: [],
72
+ summary: 'API request failed',
73
+ errors: [error instanceof Error ? error.message : String(error)],
74
+ };
75
+ }
76
+ }
77
+ /**
78
+ * List available generators
79
+ */
80
+ async listGenerators(options) {
81
+ const params = new URLSearchParams();
82
+ if (options?.category)
83
+ params.set('category', options.category);
84
+ if (options?.framework)
85
+ params.set('framework', options.framework);
86
+ if (options?.status)
87
+ params.set('status', options.status);
88
+ const url = `/api/v1/codegen/generators${params.toString() ? `?${params}` : ''}`;
89
+ const response = await this.fetch(url);
90
+ if (!response.success) {
91
+ throw new Error(response.error || 'Failed to list generators');
92
+ }
93
+ return response.data.generators;
94
+ }
95
+ /**
96
+ * Get generator details
97
+ */
98
+ async getGenerator(id) {
99
+ const response = await this.fetch(`/api/v1/codegen/generators/${id}`);
100
+ if (!response.success) {
101
+ throw new Error(response.error || 'Failed to get generator');
102
+ }
103
+ return response.data;
104
+ }
105
+ /**
106
+ * List categories
107
+ */
108
+ async listCategories() {
109
+ const response = await this.fetch('/api/v1/codegen/categories');
110
+ if (!response.success) {
111
+ throw new Error(response.error || 'Failed to list categories');
112
+ }
113
+ return response.data.categories;
114
+ }
115
+ /**
116
+ * List frameworks
117
+ */
118
+ async listFrameworks(language) {
119
+ const url = language
120
+ ? `/api/v1/codegen/frameworks?language=${language}`
121
+ : '/api/v1/codegen/frameworks';
122
+ const response = await this.fetch(url);
123
+ if (!response.success) {
124
+ throw new Error(response.error || 'Failed to list frameworks');
125
+ }
126
+ return response.data;
127
+ }
128
+ /**
129
+ * Check API health
130
+ */
131
+ async health() {
132
+ const response = await this.fetch('/api/v1/codegen/health');
133
+ if (!response.success) {
134
+ throw new Error(response.error || 'Health check failed');
135
+ }
136
+ return response.data;
137
+ }
138
+ // ===========================================================================
139
+ // Private Methods
140
+ // ===========================================================================
141
+ async fetch(path, options = {}) {
142
+ const url = `${this.config.apiUrl}${path}`;
143
+ const controller = new AbortController();
144
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
145
+ try {
146
+ const response = await fetch(url, {
147
+ ...options,
148
+ signal: controller.signal,
149
+ headers: {
150
+ 'Content-Type': 'application/json',
151
+ ...(this.config.apiKey && { Authorization: `Bearer ${this.config.apiKey}` }),
152
+ ...options.headers,
153
+ },
154
+ });
155
+ clearTimeout(timeoutId);
156
+ const data = await response.json();
157
+ return data;
158
+ }
159
+ catch (error) {
160
+ clearTimeout(timeoutId);
161
+ if (error instanceof Error && error.name === 'AbortError') {
162
+ return { success: false, error: 'Request timeout' };
163
+ }
164
+ return {
165
+ success: false,
166
+ error: error instanceof Error ? error.message : 'Network error',
167
+ };
168
+ }
169
+ }
170
+ }
171
+ // =============================================================================
172
+ // Convenience Function
173
+ // =============================================================================
174
+ /**
175
+ * Generate code using the cloud API
176
+ *
177
+ * @example
178
+ * ```ts
179
+ * const result = await cloudCodegen({
180
+ * describe: 'User with email, password, role (admin/user)',
181
+ * generate: ['schema', 'types', 'api'],
182
+ * stack: { orm: 'drizzle', api: 'hono' }
183
+ * });
184
+ *
185
+ * for (const file of result.files) {
186
+ * console.log(`${file.path}: ${file.description}`);
187
+ * }
188
+ * ```
189
+ */
190
+ export async function cloudCodegen(input, config) {
191
+ const client = new CloudCodegenClient(config);
192
+ return client.generate(input);
193
+ }
194
+ // Export default client instance
195
+ export const defaultClient = new CloudCodegenClient();
@@ -0,0 +1,35 @@
1
+ export interface CodegenInput {
2
+ /** Natural language description of what to generate */
3
+ describe: string;
4
+ /** Override auto-detected stack (optional) */
5
+ stack?: {
6
+ orm?: 'drizzle' | 'prisma' | 'typeorm' | 'mongoose';
7
+ api?: 'hono' | 'express' | 'trpc';
8
+ ui?: 'shadcn' | 'mantine' | 'radix';
9
+ db?: 'sqlite' | 'postgres' | 'mysql';
10
+ };
11
+ /** What to generate (default: schema, types, validators) */
12
+ generate?: ('schema' | 'types' | 'validators' | 'api' | 'tests' | 'components' | 'pages' | 'forms' | 'all')[];
13
+ }
14
+ export interface GeneratedFile {
15
+ path: string;
16
+ content: string;
17
+ description: string;
18
+ }
19
+ export interface CodegenResult {
20
+ success: boolean;
21
+ files: GeneratedFile[];
22
+ entities: string[];
23
+ summary: string;
24
+ errors?: string[];
25
+ }
26
+ export interface DetectedStack {
27
+ orm: 'drizzle' | 'prisma' | 'typeorm' | 'mongoose' | null;
28
+ api: 'hono' | 'express' | 'trpc' | 'fastify' | null;
29
+ ui: 'shadcn' | 'mantine' | 'radix' | 'chakra' | null;
30
+ db: 'sqlite' | 'postgres' | 'mysql' | 'mongodb' | null;
31
+ framework: 'tanstack-start' | 'nextjs' | null;
32
+ lang: 'typescript' | 'javascript';
33
+ }
34
+ export declare function detectStack(packageJson?: Record<string, unknown>): DetectedStack;
35
+ export declare function codegen(input: CodegenInput, packageJson?: Record<string, unknown>): CodegenResult;