@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
@@ -186,7 +186,7 @@ export declare function handleListGenerators(args?: {
186
186
  byFramework: Record<string, number>;
187
187
  byDomain: Record<string, number> | undefined;
188
188
  availableUiLibraries: string[];
189
- filteredByDomain?: "api" | "frontend" | "component" | undefined;
189
+ filteredByDomain?: "api" | "component" | "frontend" | undefined;
190
190
  total: number;
191
191
  };
192
192
  usage: {
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Handle the unified codegen tool
3
+ */
4
+ export declare function handleCodegen(args: Record<string, unknown>): Promise<{
5
+ success: boolean;
6
+ files?: Array<{
7
+ path: string;
8
+ content: string;
9
+ description: string;
10
+ }>;
11
+ entities?: string[];
12
+ summary?: string;
13
+ error?: string;
14
+ errors?: string[];
15
+ stack?: {
16
+ orm: string;
17
+ api: string;
18
+ db: string;
19
+ };
20
+ }>;
@@ -0,0 +1,60 @@
1
+ // =============================================================================
2
+ // Unified Codegen Handler
3
+ // =============================================================================
4
+ //
5
+ // ONE tool to replace 20+ broken CodeDNA/Kappa tools.
6
+ // Natural language in → generated code out.
7
+ //
8
+ import { codegen, detectStack } from '../codegen/index.js';
9
+ /**
10
+ * Handle the unified codegen tool
11
+ */
12
+ export async function handleCodegen(args) {
13
+ const describe = args.describe;
14
+ if (!describe || typeof describe !== 'string') {
15
+ return {
16
+ success: false,
17
+ error: 'Missing required "describe" parameter. Describe what you want to generate, e.g., "User with email, password, role (admin/user)"',
18
+ };
19
+ }
20
+ // Build input
21
+ const input = {
22
+ describe,
23
+ };
24
+ // Optional stack override
25
+ if (args.stack && typeof args.stack === 'object') {
26
+ input.stack = args.stack;
27
+ }
28
+ // Optional generate filter
29
+ if (args.generate && Array.isArray(args.generate)) {
30
+ input.generate = args.generate;
31
+ }
32
+ // Optional package.json for stack detection
33
+ let packageJson;
34
+ if (args.package_json && typeof args.package_json === 'object') {
35
+ packageJson = args.package_json;
36
+ }
37
+ // Run codegen
38
+ const result = codegen(input, packageJson);
39
+ if (!result.success) {
40
+ return {
41
+ success: false,
42
+ error: result.summary,
43
+ errors: result.errors,
44
+ };
45
+ }
46
+ // Detect stack for response
47
+ const detected = detectStack(packageJson);
48
+ const stack = {
49
+ orm: input.stack?.orm || detected.orm || 'drizzle',
50
+ api: input.stack?.api || detected.api || 'hono',
51
+ db: input.stack?.db || detected.db || 'sqlite',
52
+ };
53
+ return {
54
+ success: true,
55
+ files: result.files,
56
+ entities: result.entities,
57
+ summary: result.summary,
58
+ stack,
59
+ };
60
+ }
@@ -114,3 +114,100 @@ export declare function handleKappaGenerateAll(args: {
114
114
  typescript?: boolean;
115
115
  };
116
116
  }): Promise<KappaGenerateResult>;
117
+ /**
118
+ * Handle kappa_generate_mongoose tool call
119
+ * Generates MongoDB/Mongoose models from Kappa entity definitions
120
+ */
121
+ export declare function handleKappaGenerateMongoose(args: {
122
+ spec: string;
123
+ options?: {
124
+ provenance?: boolean;
125
+ typescript?: boolean;
126
+ separateTypes?: boolean;
127
+ };
128
+ }): Promise<KappaGenerateResult>;
129
+ /**
130
+ * Handle kappa_generate_typeorm tool call
131
+ * Generates TypeORM entities from Kappa entity definitions
132
+ */
133
+ export declare function handleKappaGenerateTypeorm(args: {
134
+ spec: string;
135
+ dialect?: 'postgres' | 'mysql' | 'sqlite';
136
+ options?: {
137
+ provenance?: boolean;
138
+ migrations?: boolean;
139
+ repositories?: boolean;
140
+ };
141
+ }): Promise<KappaGenerateResult>;
142
+ /**
143
+ * Handle kappa_generate_tests tool call
144
+ * Generates Vitest/Jest test suites from Kappa specifications
145
+ */
146
+ export declare function handleKappaGenerateTests(args: {
147
+ spec: string;
148
+ framework?: 'vitest' | 'jest';
149
+ testType?: 'unit' | 'integration' | 'e2e';
150
+ options?: {
151
+ provenance?: boolean;
152
+ factories?: boolean;
153
+ mocks?: boolean;
154
+ coverage?: boolean;
155
+ };
156
+ }): Promise<KappaGenerateResult>;
157
+ /**
158
+ * Handle kappa_generate_radix tool call
159
+ * Generates Radix UI components from Kappa component blocks
160
+ */
161
+ export declare function handleKappaGenerateRadix(args: {
162
+ spec: string;
163
+ options?: {
164
+ provenance?: boolean;
165
+ typescript?: boolean;
166
+ forwardRef?: boolean;
167
+ tailwind?: boolean;
168
+ };
169
+ }): Promise<KappaGenerateResult>;
170
+ /**
171
+ * Handle kappa_generate_mantine tool call
172
+ * Generates Mantine UI components from Kappa specifications
173
+ */
174
+ export declare function handleKappaGenerateMantine(args: {
175
+ spec: string;
176
+ options?: {
177
+ provenance?: boolean;
178
+ typescript?: boolean;
179
+ notifications?: boolean;
180
+ modals?: boolean;
181
+ };
182
+ }): Promise<KappaGenerateResult>;
183
+ /**
184
+ * Handle kappa_generate_gofiber tool call
185
+ * Generates Go code with Fiber framework from Kappa specifications
186
+ */
187
+ export declare function handleKappaGenerateGoFiber(args: {
188
+ spec: string;
189
+ options?: {
190
+ packageName?: string;
191
+ provenance?: boolean;
192
+ gorm?: boolean;
193
+ validation?: boolean;
194
+ basePath?: string;
195
+ modulePath?: string;
196
+ };
197
+ }): Promise<KappaGenerateResult>;
198
+ /**
199
+ * Handle kappa_generate_laravel tool call
200
+ * Generates Laravel code from Kappa specifications
201
+ */
202
+ export declare function handleKappaGenerateLaravel(args: {
203
+ spec: string;
204
+ options?: {
205
+ modelNamespace?: string;
206
+ controllerNamespace?: string;
207
+ provenance?: boolean;
208
+ migrations?: boolean;
209
+ formRequests?: boolean;
210
+ apiResources?: boolean;
211
+ basePath?: string;
212
+ };
213
+ }): Promise<KappaGenerateResult>;
@@ -463,3 +463,411 @@ export async function handleKappaGenerateAll(args) {
463
463
  };
464
464
  }
465
465
  }
466
+ // =============================================================================
467
+ // Phase 1: Extended ORM Generators
468
+ // =============================================================================
469
+ /**
470
+ * Handle kappa_generate_mongoose tool call
471
+ * Generates MongoDB/Mongoose models from Kappa entity definitions
472
+ */
473
+ export async function handleKappaGenerateMongoose(args) {
474
+ const { spec, options = {} } = args;
475
+ try {
476
+ const ast = parseKappaToAST(spec);
477
+ if (!ast) {
478
+ return { success: false, errors: ['Failed to parse Kappa specification'] };
479
+ }
480
+ if (!ast.entities || ast.entities.length === 0) {
481
+ return { success: false, errors: ['No entity blocks found in specification'] };
482
+ }
483
+ // Import generator dynamically to avoid circular dependencies
484
+ const { generateMongooseSchema } = await import('../codedna/kappa-mongoose-generator.js');
485
+ const result = generateMongooseSchema(ast.entities, {
486
+ provenance: options.provenance ?? true,
487
+ typescript: options.typescript ?? true,
488
+ separateTypes: options.separateTypes ?? true,
489
+ });
490
+ const files = [
491
+ { path: 'models/schemas.ts', content: result.schema },
492
+ ];
493
+ if (result.types) {
494
+ files.push({ path: 'models/types.ts', content: result.types });
495
+ }
496
+ const totalLines = files.reduce((sum, f) => sum + f.content.split('\n').length, 0);
497
+ return {
498
+ success: true,
499
+ files,
500
+ metadata: {
501
+ filesGenerated: files.length,
502
+ linesOfCode: totalLines,
503
+ estimatedTokensSaved: totalLines * 25 - 200,
504
+ },
505
+ };
506
+ }
507
+ catch (error) {
508
+ return {
509
+ success: false,
510
+ errors: [error instanceof Error ? error.message : String(error)],
511
+ };
512
+ }
513
+ }
514
+ /**
515
+ * Handle kappa_generate_typeorm tool call
516
+ * Generates TypeORM entities from Kappa entity definitions
517
+ */
518
+ export async function handleKappaGenerateTypeorm(args) {
519
+ const { spec, dialect = 'postgres', options = {} } = args;
520
+ try {
521
+ const ast = parseKappaToAST(spec);
522
+ if (!ast) {
523
+ return { success: false, errors: ['Failed to parse Kappa specification'] };
524
+ }
525
+ if (!ast.entities || ast.entities.length === 0) {
526
+ return { success: false, errors: ['No entity blocks found in specification'] };
527
+ }
528
+ // Import generator dynamically
529
+ const { generateTypeORMEntities } = await import('../codedna/kappa-typeorm-generator.js');
530
+ const result = generateTypeORMEntities(ast.entities, {
531
+ dialect,
532
+ provenance: options.provenance ?? true,
533
+ migrations: options.migrations ?? false,
534
+ repositories: options.repositories ?? false,
535
+ });
536
+ const files = [];
537
+ // Convert entities record to file array
538
+ for (const [entityName, content] of Object.entries(result.entities)) {
539
+ files.push({
540
+ path: `src/entities/${entityName}.ts`,
541
+ content,
542
+ });
543
+ }
544
+ // Add data source
545
+ files.push({
546
+ path: 'src/data-source.ts',
547
+ content: result.dataSource,
548
+ });
549
+ // Add repositories if enabled
550
+ if (result.repositories) {
551
+ for (const [repoName, content] of Object.entries(result.repositories)) {
552
+ files.push({
553
+ path: `src/repositories/${repoName}.ts`,
554
+ content,
555
+ });
556
+ }
557
+ }
558
+ // Add migration if enabled
559
+ if (result.migration) {
560
+ const timestamp = Date.now();
561
+ files.push({
562
+ path: `src/migrations/${timestamp}-CreateInitialSchema.ts`,
563
+ content: result.migration,
564
+ });
565
+ }
566
+ const totalLines = files.reduce((sum, f) => sum + f.content.split('\n').length, 0);
567
+ return {
568
+ success: true,
569
+ files,
570
+ metadata: {
571
+ filesGenerated: files.length,
572
+ linesOfCode: totalLines,
573
+ estimatedTokensSaved: totalLines * 25 - 200,
574
+ },
575
+ };
576
+ }
577
+ catch (error) {
578
+ return {
579
+ success: false,
580
+ errors: [error instanceof Error ? error.message : String(error)],
581
+ };
582
+ }
583
+ }
584
+ // =============================================================================
585
+ // Phase 1: Testing Generator
586
+ // =============================================================================
587
+ /**
588
+ * Handle kappa_generate_tests tool call
589
+ * Generates Vitest/Jest test suites from Kappa specifications
590
+ */
591
+ export async function handleKappaGenerateTests(args) {
592
+ const { spec, framework = 'vitest', testType = 'unit', options = {} } = args;
593
+ try {
594
+ const ast = parseKappaToAST(spec);
595
+ if (!ast) {
596
+ return { success: false, errors: ['Failed to parse Kappa specification'] };
597
+ }
598
+ if (!ast.entities || ast.entities.length === 0) {
599
+ return { success: false, errors: ['No entity blocks found in specification'] };
600
+ }
601
+ // Import generator dynamically
602
+ const { generateTests } = await import('../codedna/kappa-vitest-generator.js');
603
+ const result = generateTests(ast.entities, ast.apis, {
604
+ testType,
605
+ provenance: options.provenance ?? true,
606
+ factories: options.factories ?? true,
607
+ mocks: options.mocks ?? true,
608
+ });
609
+ const files = result.testFiles.map((t) => ({
610
+ path: t.path,
611
+ content: t.content,
612
+ }));
613
+ if (result.factories) {
614
+ files.push({ path: '__tests__/factories.ts', content: result.factories });
615
+ }
616
+ if (result.mocks) {
617
+ files.push({ path: '__tests__/mocks.ts', content: result.mocks });
618
+ }
619
+ const totalLines = files.reduce((sum, f) => sum + f.content.split('\n').length, 0);
620
+ return {
621
+ success: true,
622
+ files,
623
+ metadata: {
624
+ filesGenerated: files.length,
625
+ linesOfCode: totalLines,
626
+ estimatedTokensSaved: totalLines * 25 - 200,
627
+ },
628
+ };
629
+ }
630
+ catch (error) {
631
+ return {
632
+ success: false,
633
+ errors: [error instanceof Error ? error.message : String(error)],
634
+ };
635
+ }
636
+ }
637
+ // =============================================================================
638
+ // Phase 1: UI Library Generators
639
+ // =============================================================================
640
+ /**
641
+ * Handle kappa_generate_radix tool call
642
+ * Generates Radix UI components from Kappa component blocks
643
+ */
644
+ export async function handleKappaGenerateRadix(args) {
645
+ const { spec, options = {} } = args;
646
+ try {
647
+ const ast = parseKappaToAST(spec);
648
+ if (!ast) {
649
+ return { success: false, errors: ['Failed to parse Kappa specification'] };
650
+ }
651
+ if (!ast.components || ast.components.length === 0) {
652
+ return { success: false, errors: ['No component blocks found in specification'] };
653
+ }
654
+ // Import generator dynamically
655
+ const { generateRadixComponents } = await import('../codedna/kappa-radix-generator.js');
656
+ const result = generateRadixComponents(ast.components, {
657
+ provenance: options.provenance ?? true,
658
+ typescript: options.typescript ?? true,
659
+ });
660
+ const files = result.components.map((c) => ({
661
+ path: c.path,
662
+ content: c.content,
663
+ }));
664
+ const totalLines = files.reduce((sum, f) => sum + f.content.split('\n').length, 0);
665
+ return {
666
+ success: true,
667
+ files,
668
+ metadata: {
669
+ filesGenerated: files.length,
670
+ linesOfCode: totalLines,
671
+ estimatedTokensSaved: totalLines * 25 - 200,
672
+ },
673
+ };
674
+ }
675
+ catch (error) {
676
+ return {
677
+ success: false,
678
+ errors: [error instanceof Error ? error.message : String(error)],
679
+ };
680
+ }
681
+ }
682
+ /**
683
+ * Handle kappa_generate_mantine tool call
684
+ * Generates Mantine UI components from Kappa specifications
685
+ */
686
+ export async function handleKappaGenerateMantine(args) {
687
+ const { spec, options = {} } = args;
688
+ try {
689
+ const ast = parseKappaToAST(spec);
690
+ if (!ast) {
691
+ return { success: false, errors: ['Failed to parse Kappa specification'] };
692
+ }
693
+ if ((!ast.components || ast.components.length === 0) && (!ast.forms || ast.forms.length === 0)) {
694
+ return { success: false, errors: ['No component or form blocks found in specification'] };
695
+ }
696
+ // Import generators dynamically
697
+ const { generateMantineComponents, generateMantineForms } = await import('../codedna/kappa-mantine-generator.js');
698
+ const generatorOptions = {
699
+ provenance: options.provenance ?? true,
700
+ typescript: options.typescript ?? true,
701
+ };
702
+ const componentResult = generateMantineComponents(ast.components || [], generatorOptions);
703
+ const formResult = generateMantineForms(ast.forms || [], generatorOptions);
704
+ const files = [
705
+ ...componentResult.files.map((c) => ({ path: c.path, content: c.content })),
706
+ ...formResult.files.map((f) => ({ path: f.path, content: f.content })),
707
+ ];
708
+ const totalLines = files.reduce((sum, f) => sum + f.content.split('\n').length, 0);
709
+ return {
710
+ success: true,
711
+ files,
712
+ metadata: {
713
+ filesGenerated: files.length,
714
+ linesOfCode: totalLines,
715
+ estimatedTokensSaved: totalLines * 25 - 200,
716
+ },
717
+ };
718
+ }
719
+ catch (error) {
720
+ return {
721
+ success: false,
722
+ errors: [error instanceof Error ? error.message : String(error)],
723
+ };
724
+ }
725
+ }
726
+ // =============================================================================
727
+ // Go/Fiber Generation Handler
728
+ // =============================================================================
729
+ /**
730
+ * Handle kappa_generate_gofiber tool call
731
+ * Generates Go code with Fiber framework from Kappa specifications
732
+ */
733
+ export async function handleKappaGenerateGoFiber(args) {
734
+ const { spec, options = {} } = args;
735
+ try {
736
+ const ast = parseKappaToAST(spec);
737
+ if (!ast) {
738
+ return { success: false, errors: ['Failed to parse Kappa specification'] };
739
+ }
740
+ if (ast.apis.length === 0 && ast.entities.length === 0) {
741
+ return { success: false, errors: ['No API or entity blocks found in specification'] };
742
+ }
743
+ // Import generator dynamically
744
+ const { KappaGoFiberGenerator } = await import('../codedna/kappa-gofiber-generator.js');
745
+ const generator = new KappaGoFiberGenerator({
746
+ packageName: options.packageName ?? 'main',
747
+ provenance: options.provenance ?? true,
748
+ gorm: options.gorm ?? true,
749
+ validation: options.validation ?? true,
750
+ basePath: options.basePath ?? '/api',
751
+ modulePath: options.modulePath ?? 'app',
752
+ });
753
+ const result = generator.generateAll(ast.apis, ast.entities);
754
+ const files = [];
755
+ let totalLines = 0;
756
+ if (result.routes) {
757
+ files.push({ path: 'routes.go', content: result.routes });
758
+ totalLines += result.routes.split('\n').length;
759
+ }
760
+ if (result.handlers) {
761
+ files.push({ path: 'handlers.go', content: result.handlers });
762
+ totalLines += result.handlers.split('\n').length;
763
+ }
764
+ if (result.models) {
765
+ files.push({ path: 'models.go', content: result.models });
766
+ totalLines += result.models.split('\n').length;
767
+ }
768
+ if (result.types) {
769
+ files.push({ path: 'types.go', content: result.types });
770
+ totalLines += result.types.split('\n').length;
771
+ }
772
+ return {
773
+ success: true,
774
+ files,
775
+ metadata: {
776
+ filesGenerated: files.length,
777
+ linesOfCode: totalLines,
778
+ estimatedTokensSaved: totalLines * 25 - 200,
779
+ },
780
+ };
781
+ }
782
+ catch (error) {
783
+ return {
784
+ success: false,
785
+ errors: [error instanceof Error ? error.message : String(error)],
786
+ };
787
+ }
788
+ }
789
+ // =============================================================================
790
+ // PHP/Laravel Generation Handler
791
+ // =============================================================================
792
+ /**
793
+ * Handle kappa_generate_laravel tool call
794
+ * Generates Laravel code from Kappa specifications
795
+ */
796
+ export async function handleKappaGenerateLaravel(args) {
797
+ const { spec, options = {} } = args;
798
+ try {
799
+ const ast = parseKappaToAST(spec);
800
+ if (!ast) {
801
+ return { success: false, errors: ['Failed to parse Kappa specification'] };
802
+ }
803
+ if (ast.apis.length === 0 && ast.entities.length === 0) {
804
+ return { success: false, errors: ['No API or entity blocks found in specification'] };
805
+ }
806
+ // Import generator dynamically
807
+ const { KappaLaravelGenerator } = await import('../codedna/kappa-laravel-generator.js');
808
+ const generator = new KappaLaravelGenerator({
809
+ modelNamespace: options.modelNamespace ?? 'App\\Models',
810
+ controllerNamespace: options.controllerNamespace ?? 'App\\Http\\Controllers',
811
+ provenance: options.provenance ?? true,
812
+ migrations: options.migrations ?? true,
813
+ formRequests: options.formRequests ?? true,
814
+ apiResources: options.apiResources ?? true,
815
+ basePath: options.basePath ?? '/api',
816
+ });
817
+ const result = generator.generateAll(ast.apis, ast.entities);
818
+ const files = [];
819
+ let totalLines = 0;
820
+ // Add routes
821
+ if (result.routes) {
822
+ files.push({ path: 'routes/api.php', content: result.routes });
823
+ totalLines += result.routes.split('\n').length;
824
+ }
825
+ // Add controllers
826
+ for (const [name, content] of Object.entries(result.controllers)) {
827
+ files.push({ path: `app/Http/Controllers/${name}.php`, content });
828
+ totalLines += content.split('\n').length;
829
+ }
830
+ // Add models
831
+ for (const [name, content] of Object.entries(result.models)) {
832
+ files.push({ path: `app/Models/${name}.php`, content });
833
+ totalLines += content.split('\n').length;
834
+ }
835
+ // Add migrations
836
+ if (result.migrations) {
837
+ for (const [name, content] of Object.entries(result.migrations)) {
838
+ const timestamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14);
839
+ files.push({ path: `database/migrations/${timestamp}_${name}.php`, content });
840
+ totalLines += content.split('\n').length;
841
+ }
842
+ }
843
+ // Add form requests
844
+ if (result.formRequests) {
845
+ for (const [name, content] of Object.entries(result.formRequests)) {
846
+ files.push({ path: `app/Http/Requests/${name}.php`, content });
847
+ totalLines += content.split('\n').length;
848
+ }
849
+ }
850
+ // Add resources
851
+ if (result.resources) {
852
+ for (const [name, content] of Object.entries(result.resources)) {
853
+ files.push({ path: `app/Http/Resources/${name}.php`, content });
854
+ totalLines += content.split('\n').length;
855
+ }
856
+ }
857
+ return {
858
+ success: true,
859
+ files,
860
+ metadata: {
861
+ filesGenerated: files.length,
862
+ linesOfCode: totalLines,
863
+ estimatedTokensSaved: totalLines * 25 - 200,
864
+ },
865
+ };
866
+ }
867
+ catch (error) {
868
+ return {
869
+ success: false,
870
+ errors: [error instanceof Error ? error.message : String(error)],
871
+ };
872
+ }
873
+ }