agent-enderun 1.10.4 → 1.11.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 (183) hide show
  1. package/README.md +34 -45
  2. package/dist/framework-mcp/tests/tools/quality/check_lint.test.js +1 -1
  3. package/dist/framework-mcp/tests/tools/quality/check_lint.test.js.map +1 -1
  4. package/dist/src/cli/adapters/core.d.ts +1 -1
  5. package/dist/src/cli/adapters/core.js +0 -1
  6. package/dist/src/cli/adapters/core.js.map +1 -1
  7. package/dist/src/cli/adapters/index.d.ts +1 -0
  8. package/dist/src/cli/adapters/index.js +1 -0
  9. package/dist/src/cli/adapters/index.js.map +1 -1
  10. package/dist/src/cli/adapters/scaffold.d.ts +1 -1
  11. package/dist/src/cli/adapters/scaffold.js +8 -6
  12. package/dist/src/cli/adapters/scaffold.js.map +1 -1
  13. package/dist/src/cli/commands/init/scaffold-core.d.ts +5 -2
  14. package/dist/src/cli/commands/init/scaffold-core.js +28 -6
  15. package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
  16. package/dist/src/cli/commands/init.js +31 -4
  17. package/dist/src/cli/commands/init.js.map +1 -1
  18. package/dist/src/cli/commands/orchestrate.d.ts +6 -6
  19. package/dist/src/cli/commands/plan.d.ts +3 -1
  20. package/dist/src/cli/commands/plan.js +79 -22
  21. package/dist/src/cli/commands/plan.js.map +1 -1
  22. package/dist/src/cli/index.js +11 -15
  23. package/dist/src/cli/index.js.map +1 -1
  24. package/dist/src/cli/utils/compliance.js +0 -1
  25. package/dist/src/cli/utils/compliance.js.map +1 -1
  26. package/dist/src/cli/utils/config-schema.d.ts +7 -7
  27. package/dist/src/cli/utils/pkg.d.ts +19 -0
  28. package/dist/src/cli/utils/pkg.js +29 -5
  29. package/dist/src/cli/utils/pkg.js.map +1 -1
  30. package/dist/src/modules/agents/registry/analyst.js +1 -1
  31. package/dist/src/modules/agents/registry/analyst.js.map +1 -1
  32. package/dist/src/modules/agents/registry/backend.js +5 -4
  33. package/dist/src/modules/agents/registry/backend.js.map +1 -1
  34. package/dist/src/modules/agents/registry/database.js +2 -1
  35. package/dist/src/modules/agents/registry/database.js.map +1 -1
  36. package/dist/src/modules/agents/registry/git.js +1 -1
  37. package/dist/src/modules/agents/registry/git.js.map +1 -1
  38. package/dist/src/modules/agents/registry/manager.js +3 -2
  39. package/dist/src/modules/agents/registry/manager.js.map +1 -1
  40. package/dist/src/modules/agents/registry/native.js +1 -1
  41. package/dist/src/modules/agents/registry/native.js.map +1 -1
  42. package/dist/src/modules/agents/registry/security.js +1 -0
  43. package/dist/src/modules/agents/registry/security.js.map +1 -1
  44. package/dist/tests/approve.test.js +4 -9
  45. package/dist/tests/approve.test.js.map +1 -1
  46. package/framework-mcp/dist/constants.js +64 -0
  47. package/framework-mcp/dist/index.js +109 -0
  48. package/framework-mcp/dist/tools/control_plane/locking.js +64 -0
  49. package/framework-mcp/dist/tools/control_plane/registry.js +34 -0
  50. package/framework-mcp/dist/tools/dashboard/start_dashboard.js +29 -0
  51. package/framework-mcp/dist/tools/definitions.js +300 -0
  52. package/framework-mcp/dist/tools/file_system/batch_surgical_edit.js +59 -0
  53. package/framework-mcp/dist/tools/file_system/patch_file.js +25 -0
  54. package/framework-mcp/dist/tools/file_system/read_file.js +51 -0
  55. package/framework-mcp/dist/tools/file_system/replace_text.js +43 -0
  56. package/framework-mcp/dist/tools/file_system/write_file.js +38 -0
  57. package/framework-mcp/dist/tools/framework/audit_deps.js +41 -0
  58. package/framework-mcp/dist/tools/framework/get_status.js +5 -0
  59. package/framework-mcp/dist/tools/framework/orchestrate.js +5 -0
  60. package/framework-mcp/dist/tools/framework/run_tests.js +25 -0
  61. package/framework-mcp/dist/tools/framework/update_contract_hash.js +5 -0
  62. package/framework-mcp/dist/tools/framework/update_memory.js +8 -0
  63. package/framework-mcp/dist/tools/index.js +62 -0
  64. package/framework-mcp/dist/tools/memory/get_insights.js +34 -0
  65. package/framework-mcp/dist/tools/memory/read_memory.js +28 -0
  66. package/framework-mcp/dist/tools/messaging/log_action.js +22 -0
  67. package/framework-mcp/dist/tools/messaging/send_message.js +87 -0
  68. package/framework-mcp/dist/tools/observability/check_ports.js +26 -0
  69. package/framework-mcp/dist/tools/observability/get_health.js +19 -0
  70. package/framework-mcp/dist/tools/quality/check_lint.js +28 -0
  71. package/framework-mcp/dist/tools/search/get_gaps.js +48 -0
  72. package/framework-mcp/dist/tools/search/get_map.js +43 -0
  73. package/framework-mcp/dist/tools/search/grep_search.js +76 -0
  74. package/framework-mcp/dist/tools/search/list_dir.js +28 -0
  75. package/framework-mcp/dist/tools/shell/run_command.js +46 -0
  76. package/framework-mcp/dist/tools/types.js +1 -0
  77. package/framework-mcp/dist/utils/cli.js +20 -0
  78. package/framework-mcp/dist/utils/compliance.js +29 -0
  79. package/framework-mcp/dist/utils/fs.js +44 -0
  80. package/framework-mcp/dist/utils/metrics.js +56 -0
  81. package/framework-mcp/dist/utils/security.js +60 -0
  82. package/framework-mcp/package.json +19 -0
  83. package/framework-mcp/src/constants.ts +78 -0
  84. package/framework-mcp/src/declarations.d.ts +17 -0
  85. package/framework-mcp/src/index.ts +132 -0
  86. package/framework-mcp/src/tools/control_plane/locking.ts +71 -0
  87. package/framework-mcp/src/tools/control_plane/registry.ts +38 -0
  88. package/framework-mcp/src/tools/dashboard/start_dashboard.ts +33 -0
  89. package/framework-mcp/src/tools/definitions.ts +302 -0
  90. package/framework-mcp/src/tools/file_system/batch_surgical_edit.ts +79 -0
  91. package/framework-mcp/src/tools/file_system/patch_file.ts +33 -0
  92. package/framework-mcp/src/tools/file_system/read_file.ts +58 -0
  93. package/framework-mcp/src/tools/file_system/replace_text.ts +52 -0
  94. package/framework-mcp/src/tools/file_system/write_file.ts +45 -0
  95. package/framework-mcp/src/tools/framework/audit_deps.ts +49 -0
  96. package/framework-mcp/src/tools/framework/get_status.ts +7 -0
  97. package/framework-mcp/src/tools/framework/orchestrate.ts +7 -0
  98. package/framework-mcp/src/tools/framework/run_tests.ts +28 -0
  99. package/framework-mcp/src/tools/framework/update_contract_hash.ts +7 -0
  100. package/framework-mcp/src/tools/framework/update_memory.ts +10 -0
  101. package/framework-mcp/src/tools/index.ts +66 -0
  102. package/framework-mcp/src/tools/memory/get_insights.ts +41 -0
  103. package/framework-mcp/src/tools/memory/read_memory.ts +31 -0
  104. package/framework-mcp/src/tools/messaging/log_action.ts +28 -0
  105. package/framework-mcp/src/tools/messaging/send_message.ts +89 -0
  106. package/framework-mcp/src/tools/observability/check_ports.ts +30 -0
  107. package/framework-mcp/src/tools/observability/get_health.ts +24 -0
  108. package/framework-mcp/src/tools/quality/check_lint.ts +33 -0
  109. package/framework-mcp/src/tools/search/get_gaps.ts +54 -0
  110. package/framework-mcp/src/tools/search/get_map.ts +48 -0
  111. package/framework-mcp/src/tools/search/grep_search.ts +76 -0
  112. package/framework-mcp/src/tools/search/list_dir.ts +34 -0
  113. package/framework-mcp/src/tools/shell/run_command.ts +56 -0
  114. package/framework-mcp/src/tools/types.ts +89 -0
  115. package/framework-mcp/src/utils/cli.ts +20 -0
  116. package/framework-mcp/src/utils/compliance.ts +37 -0
  117. package/framework-mcp/src/utils/fs.ts +45 -0
  118. package/framework-mcp/src/utils/metrics.ts +73 -0
  119. package/framework-mcp/src/utils/security.ts +66 -0
  120. package/framework-mcp/tests/tools/file_system/file_system_tools.test.ts +212 -0
  121. package/framework-mcp/tests/tools/messaging/send_message.test.ts +136 -0
  122. package/framework-mcp/tests/tools/quality/check_lint.test.ts +46 -0
  123. package/framework-mcp/tests/tools/shell/run_command.test.ts +55 -0
  124. package/framework-mcp/tsconfig.json +14 -0
  125. package/package.json +5 -3
  126. package/src/cli/adapters/core.ts +2 -3
  127. package/src/cli/adapters/index.ts +1 -0
  128. package/src/cli/adapters/scaffold.ts +15 -6
  129. package/src/cli/commands/init/scaffold-core.ts +45 -6
  130. package/src/cli/commands/init.ts +31 -2
  131. package/src/cli/commands/plan.ts +89 -23
  132. package/src/cli/index.ts +14 -19
  133. package/src/cli/utils/compliance.ts +8 -9
  134. package/src/cli/utils/pkg.ts +42 -13
  135. package/src/modules/agents/registry/analyst.ts +1 -1
  136. package/src/modules/agents/registry/backend.ts +5 -4
  137. package/src/modules/agents/registry/database.ts +2 -1
  138. package/src/modules/agents/registry/git.ts +1 -1
  139. package/src/modules/agents/registry/manager.ts +3 -2
  140. package/src/modules/agents/registry/native.ts +1 -1
  141. package/src/modules/agents/registry/security.ts +1 -0
  142. package/templates/prompts/bug-fix-recipe.md +20 -0
  143. package/templates/prompts/contract-design-recipe.md +21 -0
  144. package/templates/prompts/db-management-recipe.md +25 -0
  145. package/templates/prompts/deployment-recipe.md +23 -0
  146. package/templates/prompts/new-feature-recipe.md +19 -0
  147. package/templates/prompts/performance-optimization-recipe.md +23 -0
  148. package/templates/prompts/pull-request-template.md +21 -0
  149. package/templates/prompts/refactoring-recipe.md +21 -0
  150. package/templates/prompts/security-audit-recipe.md +20 -0
  151. package/templates/standards/architecture-standards.md +23 -0
  152. package/templates/standards/auth-standards.md +125 -0
  153. package/templates/standards/crud-governance.md +21 -0
  154. package/templates/standards/deployment-standards.md +21 -0
  155. package/templates/standards/frontend-standards.md +37 -0
  156. package/templates/standards/github-actions-standards.md +43 -0
  157. package/templates/standards/i18n-standards.md +17 -0
  158. package/templates/standards/kysely-standards.md +47 -0
  159. package/templates/standards/llm-governance.md +15 -0
  160. package/templates/standards/logging-and-secrets.md +34 -0
  161. package/templates/standards/mobile-standards.md +23 -0
  162. package/templates/standards/observability-standards.md +15 -0
  163. package/templates/standards/performance-standards.md +15 -0
  164. package/templates/standards/pino-standards.md +46 -0
  165. package/templates/standards/playwright-standards.md +54 -0
  166. package/templates/standards/quality-standards.md +31 -0
  167. package/templates/standards/react-query-standards.md +72 -0
  168. package/templates/standards/react-router-standards.md +62 -0
  169. package/templates/standards/security-audit-standards.md +16 -0
  170. package/templates/standards/security-standards.md +21 -0
  171. package/templates/standards/swagger-standards.md +50 -0
  172. package/templates/standards/tailwind-standards.md +20 -0
  173. package/templates/standards/testing-standards.md +31 -0
  174. package/templates/standards/typeorm-standards.md +49 -0
  175. package/templates/standards/vitest-standards.md +110 -0
  176. package/src/cli/commands/app.ts +0 -56
  177. package/src/cli/utils/app-backend.ts +0 -257
  178. package/src/cli/utils/app-docs.ts +0 -83
  179. package/src/cli/utils/app-frontend.ts +0 -263
  180. package/src/cli/utils/app-inferrer.ts +0 -63
  181. package/src/cli/utils/app-mobile.ts +0 -113
  182. package/src/cli/utils/app-types.ts +0 -248
  183. package/src/cli/utils/app.ts +0 -6
@@ -0,0 +1,31 @@
1
+ # 🧪 Corporate Testing Standards
2
+
3
+ This document defines the testing discipline and scope rules for projects managed by Agent Enderun. Code quality must be ensured with automated tests.
4
+
5
+ ## 1. Test Pyramid and Strategy
6
+ - **Unit Tests:** Written for the smallest parts of business logic. Must be fast and isolated.
7
+ - **Integration Tests:** Audits the compatibility of services with the database or external APIs.
8
+ - **E2E Tests:** Simulates critical user flows (Login, Checkout, etc.) in a real browser environment.
9
+
10
+ ## 2. Writing Rules and Naming
11
+ - **Framework:** Vitest (Unit/Integration) and Playwright (E2E) are standard.
12
+ - **File Naming:** The `[module-name].test.ts` format is used.
13
+ - **Pattern (Given-When-Then):**
14
+ ```typescript
15
+ it("should create a user when valid data is provided", async () => {
16
+ // Given
17
+ const userData = { ... };
18
+ // When
19
+ const result = await userService.create(userData);
20
+ // Then
21
+ expect(result.id).toBeDefined();
22
+ });
23
+ ```
24
+
25
+ ## 3. Scope and Success Criteria
26
+ - **Critical Path Coverage:** Auth, Payment, and Data Mutation processes must have 100% test coverage.
27
+ - **Zero Mock Policy (Internal):** Real contracts and test databases should be used between internal project services instead of mocks. External services (Stripe, Twilio, etc.) can be mocked.
28
+
29
+ ## 4. Auditing
30
+ - The `@quality` agent verifies that the relevant test file is updated in each new function.
31
+ - Code that does not pass tests (`npm run test`) is never approved.
@@ -0,0 +1,49 @@
1
+ # TypeORM Standards
2
+
3
+ > Full-featured ORM with decorator-based entity definitions.
4
+
5
+ ## Setup
6
+
7
+ ```typescript
8
+ import { DataSource } from "typeorm";
9
+
10
+ export const AppDataSource = new DataSource({
11
+ type: "sqlite",
12
+ database: process.env.DATABASE_PATH || "./dev.db",
13
+ synchronize: process.env.NODE_ENV === "development",
14
+ logging: process.env.NODE_ENV === "development",
15
+ entities: ["src/database/typeorm/entities/*.ts"],
16
+ migrations: ["src/database/typeorm/migrations/*.ts"],
17
+ });
18
+ ```
19
+
20
+ ## Entity Pattern
21
+
22
+ ```typescript
23
+ import { Entity, PrimaryColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn } from "typeorm";
24
+
25
+ @Entity("users")
26
+ export class UserEntity {
27
+ @PrimaryColumn()
28
+ id!: string;
29
+ @Column({ unique: true })
30
+ email!: string;
31
+ @Column()
32
+ fullName!: string;
33
+ @Column({ default: "VIEWER" })
34
+ role!: string;
35
+ @CreateDateColumn()
36
+ createdAt!: Date;
37
+ @UpdateDateColumn()
38
+ updatedAt!: Date;
39
+ @DeleteDateColumn()
40
+ deletedAt?: Date;
41
+ }
42
+ ```
43
+
44
+ ## Best Practices
45
+ 1. Use `@DeleteDateColumn()` for soft deletes
46
+ 2. Set `synchronize: false` in production
47
+ 3. Use `@ManyToOne` / `@OneToMany` for relations
48
+ 4. Import `reflect-metadata` at entry point
49
+ 5. Generate migrations, don't rely on synchronize
@@ -0,0 +1,110 @@
1
+ # Testing Standards
2
+
3
+ > Unit and integration testing with Vitest for Node.js applications.
4
+
5
+ ## Overview
6
+
7
+ Vitest is a blazing-fast unit test framework compatible with Jest API. It is used for both unit tests and API integration tests.
8
+
9
+ ## Setup
10
+
11
+ ```bash
12
+ npm install -D vitest
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ ```typescript
18
+ // vitest.config.ts
19
+ import { defineConfig } from "vitest/config";
20
+
21
+ export default defineConfig({
22
+ test: {
23
+ globals: true,
24
+ environment: "node",
25
+ include: ["src/tests/**/*.test.ts"],
26
+ coverage: {
27
+ provider: "v8",
28
+ reporter: ["text", "json", "html"],
29
+ thresholds: {
30
+ lines: 80,
31
+ functions: 80,
32
+ branches: 80,
33
+ statements: 80,
34
+ },
35
+ },
36
+ },
37
+ });
38
+ ```
39
+
40
+ ## Test Structure
41
+
42
+ ```
43
+ src/tests/
44
+ ├── auth.test.ts # Authentication tests
45
+ ├── customers.test.ts # Customer CRUD tests
46
+ ├── helpers/
47
+ │ ├── setup.ts # Test setup & teardown
48
+ │ └── factories.ts # Test data factories
49
+ └── integration/
50
+ └── api.test.ts # Full API integration tests
51
+ ```
52
+
53
+ ## Unit Test Example
54
+
55
+ ```typescript
56
+ import { describe, it, expect } from "vitest";
57
+ import { createCustomerSchema } from "../validators/schemas.js";
58
+
59
+ describe("Customer Validation", () => {
60
+ it("should validate create customer schema", () => {
61
+ const result = createCustomerSchema.parse({
62
+ name: "Test Corp",
63
+ status: "LEAD",
64
+ annualValue: 50000,
65
+ });
66
+ expect(result.name).toBe("Test Corp");
67
+ });
68
+
69
+ it("should reject invalid data", () => {
70
+ expect(() => createCustomerSchema.parse({ name: "" })).toThrow();
71
+ });
72
+ });
73
+ ```
74
+
75
+ ## API Integration Test Example
76
+
77
+ ```typescript
78
+ import { describe, it, expect, beforeAll, afterAll } from "vitest";
79
+ import Fastify from "fastify";
80
+
81
+ describe("Auth API", () => {
82
+ const app = Fastify();
83
+
84
+ beforeAll(async () => {
85
+ await app.register(publicRoutes, { prefix: "/api/v1" });
86
+ await app.ready();
87
+ });
88
+
89
+ afterAll(async () => await app.close());
90
+
91
+ it("should reject invalid login", async () => {
92
+ const response = await app.inject({
93
+ method: "POST",
94
+ url: "/api/v1/auth/login",
95
+ payload: { email: "invalid", password: "test" },
96
+ });
97
+ expect(response.statusCode).toBe(400);
98
+ });
99
+ });
100
+ ```
101
+
102
+ ## Best Practices
103
+
104
+ 1. Use `describe`/`it` blocks for organized test suites
105
+ 2. Test both success and failure scenarios
106
+ 3. Use `app.inject()` for API tests (no server needed)
107
+ 4. Keep tests isolated — clean state between tests
108
+ 5. Aim for >80% coverage on business logic
109
+ 6. Use factories for test data generation
110
+ 7. Follow Given-When-Then pattern in all test suites
@@ -1,56 +0,0 @@
1
- import fs from "fs";
2
-
3
- import { updateMemoryForGeneratedApp, collectCreateAppDescription, inferAppSpec, createBackendFiles, createWebFiles, createMobileFiles, updateProjectDocs } from "../utils/app.js";
4
- import { traceNewCommand } from "./trace.js";
5
- import { getMemoryPath } from "../utils/memory.js";
6
-
7
- import { ValidationError } from "../../shared/errors.js";
8
-
9
- /**
10
- * Generate a new application based on natural language input.
11
- */
12
- export async function createAppCommand(args: string[]) {
13
- if (!fs.existsSync("apps")) {
14
- throw new ValidationError(
15
- "The 'apps/' directory is missing.",
16
- null,
17
- "Ensure you are in the project root and the 'apps/' folder exists. Run 'mkdir apps' if needed."
18
- );
19
- }
20
- const description = await collectCreateAppDescription(args);
21
- const spec = inferAppSpec(description);
22
-
23
- console.warn(`🚀 Generating Enterprise App: ${spec.title} (Platform: ${spec.platform})...`);
24
-
25
- if (spec.platform === "full-stack") {
26
- createBackendFiles(spec);
27
- createWebFiles(spec);
28
- } else if (spec.platform === "web") {
29
- createWebFiles(spec);
30
- } else if (spec.platform === "mobile") {
31
- createMobileFiles(spec);
32
- } else if (spec.platform === "backend") {
33
- createBackendFiles(spec);
34
- }
35
-
36
- updateProjectDocs(spec);
37
-
38
- const memoryPath = getMemoryPath();
39
- let traceId = "01HGT8J5E2N0W0W0W0W0W0W0W0"; // default fallback
40
-
41
- if (fs.existsSync(memoryPath)) {
42
- const memory = fs.readFileSync(memoryPath, "utf8");
43
- const match = memory.match(/- Trace ID: (.*)/);
44
- if (match) traceId = match[1].trim();
45
- }
46
-
47
- const activeTraceId = (await traceNewCommand(`Generate ${spec.title} from natural language request`, "manager", "P1")) || traceId;
48
- updateMemoryForGeneratedApp(spec, activeTraceId);
49
-
50
- console.warn("\n✨ Application scaffolded successfully!");
51
- console.warn("📜 Updated project docs and app-local types contract");
52
- console.warn("\nNext commands:");
53
- console.warn(" npm install");
54
- console.warn(" npm run enderun:build");
55
- console.warn(" agent-enderun frontend:dev\n");
56
- }
@@ -1,257 +0,0 @@
1
- import path from "path";
2
- import type { AppSpec } from "./app-inferrer.js";
3
- import { createBaseTypeFiles } from "./app-types.js";
4
- import { ensureDir, writeJsonFile, writeTextFile } from "./fs.js";
5
- import { getConfiguredPaths } from "./memory.js";
6
- import { getDependencyVersions } from "./pkg.js";
7
-
8
- const targetDir = process.cwd();
9
-
10
- export function createBackendFiles(spec: AppSpec): void {
11
- const pathsMap = getConfiguredPaths();
12
- const backendDir = pathsMap.backend;
13
- const { fastify, "@fastify/cors": fastifyCors, zod, "@types/node": typesNode, tsx, typescript, "vitest-backend": vitest } = getDependencyVersions();
14
-
15
- createBaseTypeFiles(path.join(targetDir, backendDir, "src"));
16
- writeJsonFile(path.join(targetDir, backendDir, "contract.version.json"), {
17
- "contract_hash": "initial_hash_placeholder",
18
- "last_updated": new Date().toISOString()
19
- });
20
- writeJsonFile(path.join(targetDir, backendDir, "package.json"), {
21
- name: "@agent-enderun/backend",
22
- version: "0.1.0",
23
- private: true,
24
- type: "module",
25
- scripts: {
26
- dev: "tsx src/server.ts",
27
- build: "tsc -p tsconfig.json",
28
- start: "node dist/server.js",
29
- test: "vitest run",
30
- },
31
- dependencies: {
32
- "@fastify/cors": fastifyCors,
33
- fastify: fastify,
34
- zod: zod,
35
- },
36
- devDependencies: {
37
- "@types/node": typesNode,
38
- tsx: tsx,
39
- typescript: typescript,
40
- vitest: vitest,
41
- },
42
- });
43
-
44
- writeJsonFile(path.join(targetDir, backendDir, "tsconfig.json"), {
45
- extends: "../../tsconfig.json",
46
- compilerOptions: {
47
- outDir: "dist",
48
- rootDir: "src",
49
- module: "NodeNext",
50
- moduleResolution: "NodeNext",
51
- target: "ES2022",
52
- strict: true,
53
- skipLibCheck: true,
54
- },
55
- include: ["src/**/*.ts"],
56
- });
57
-
58
- const srcDir = path.join(targetDir, backendDir, "src");
59
- ensureDir(path.join(srcDir, "database"));
60
- ensureDir(path.join(srcDir, "repositories"));
61
- ensureDir(path.join(srcDir, "services"));
62
-
63
- writeTextFile(path.join(srcDir, "database/memoryDb.ts"), [
64
- "import type { Customer, ReportMetric, Role, User } from \"../types/index.js\";",
65
- "",
66
- "const now = new Date().toISOString();",
67
- "",
68
- "export const rolesDb: Role[] = [",
69
- " { id: \"role_admin\" as Role[\"id\"], name: \"Admin\", permissions: [\"users:manage\", \"reports:view\", \"customers:manage\"] },",
70
- " { id: \"role_manager\" as Role[\"id\"], name: \"Manager\", permissions: [\"reports:view\", \"customers:manage\"] },",
71
- " { id: \"role_viewer\" as Role[\"id\"], name: \"Viewer\", permissions: [\"reports:view\"] },",
72
- "];",
73
- "",
74
- "export const usersDb: User[] = [",
75
- " { id: \"user_1\" as User[\"id\"], email: \"admin@example.com\", fullName: \"Admin User\", role: \"ADMIN\", createdAt: now, updatedAt: now },",
76
- " { id: \"user_2\" as User[\"id\"], email: \"manager@example.com\", fullName: \"Sales Manager\", role: \"DEVELOPER\", createdAt: now, updatedAt: now },",
77
- "];",
78
- "",
79
- "export const customersDb: Customer[] = [",
80
- " { id: \"customer_1\" as Customer[\"id\"], name: \"Northwind\", ownerId: usersDb[1].id, status: \"ACTIVE\", annualValue: 125000, createdAt: now, updatedAt: now },",
81
- " { id: \"customer_2\" as Customer[\"id\"], name: \"Acme Corp\", ownerId: usersDb[1].id, status: \"LEAD\", annualValue: 82000, createdAt: now, updatedAt: now },",
82
- " { id: \"customer_3\" as Customer[\"id\"], name: \"Globex\", ownerId: usersDb[0].id, status: \"AT_RISK\", annualValue: 54000, createdAt: now, updatedAt: now },",
83
- "];",
84
- "",
85
- "export const reportsDb: ReportMetric[] = [",
86
- " { id: \"report_pipeline\" as ReportMetric[\"id\"], label: \"Pipeline\", value: 261000, trend: \"UP\" },",
87
- " { id: \"report_active_customers\" as ReportMetric[\"id\"], label: \"Active Customers\", value: 1, trend: \"FLAT\" },",
88
- " { id: \"report_risk\" as ReportMetric[\"id\"], label: \"At Risk\", value: 1, trend: \"DOWN\" },",
89
- "];",
90
- ].join("\n"));
91
-
92
- writeTextFile(path.join(srcDir, "repositories/user.repository.ts"), [
93
- "import { usersDb } from \"../database/memoryDb.js\";",
94
- "import type { User } from \"../types/index.js\";",
95
- "",
96
- "export class UserRepository {",
97
- " async findAll(): Promise<User[]> {",
98
- " return usersDb.filter(u => !u.deletedAt);",
99
- " }",
100
- "",
101
- " async findByEmail(email: string): Promise<User | null> {",
102
- " return usersDb.find(u => u.email === email && !u.deletedAt) || null;",
103
- " }",
104
- "}",
105
- ].join("\n"));
106
-
107
- writeTextFile(path.join(srcDir, "repositories/customer.repository.ts"), [
108
- "import { customersDb } from \"../database/memoryDb.js\";",
109
- "import type { Customer } from \"../types/index.js\";",
110
- "",
111
- "export class CustomerRepository {",
112
- " async findAll(): Promise<Customer[]> {",
113
- " return customersDb.filter(c => !c.deletedAt);",
114
- " }",
115
- "}",
116
- ].join("\n"));
117
-
118
- writeTextFile(path.join(srcDir, "repositories/role.repository.ts"), [
119
- "import { rolesDb } from \"../database/memoryDb.js\";",
120
- "import type { Role } from \"../types/index.js\";",
121
- "",
122
- "export class RoleRepository {",
123
- " async findAll(): Promise<Role[]> {",
124
- " return rolesDb;",
125
- " }",
126
- "}",
127
- ].join("\n"));
128
-
129
- writeTextFile(path.join(srcDir, "repositories/report.repository.ts"), [
130
- "import { reportsDb } from \"../database/memoryDb.js\";",
131
- "import type { ReportMetric } from \"../types/index.js\";",
132
- "",
133
- "export class ReportRepository {",
134
- " async findAll(): Promise<ReportMetric[]> {",
135
- " return reportsDb;",
136
- " }",
137
- "}",
138
- ].join("\n"));
139
-
140
- writeTextFile(path.join(srcDir, "services/dashboard.service.ts"), [
141
- "import { UserRepository } from \"../repositories/user.repository.js\";",
142
- "import { CustomerRepository } from \"../repositories/customer.repository.js\";",
143
- "import { RoleRepository } from \"../repositories/role.repository.js\";",
144
- "import { ReportRepository } from \"../repositories/report.repository.js\";",
145
- "import type { DashboardSummary } from \"../types/index.js\";",
146
- "",
147
- "export class DashboardService {",
148
- " private userRepo = new UserRepository();",
149
- " private customerRepo = new CustomerRepository();",
150
- " private roleRepo = new RoleRepository();",
151
- " private reportRepo = new ReportRepository();",
152
- "",
153
- " async getSummary(): Promise<DashboardSummary> {",
154
- " const [users, customers, roles, reports] = await Promise.all([",
155
- " this.userRepo.findAll(),",
156
- " this.customerRepo.findAll(),",
157
- " this.roleRepo.findAll(),",
158
- " this.reportRepo.findAll(),",
159
- " ]);",
160
- "",
161
- " return { users, customers, roles, reports };",
162
- " }",
163
- "}",
164
- ].join("\n"));
165
-
166
- writeTextFile(path.join(targetDir, backendDir, "src/server.ts"), [
167
- "import Fastify from \"fastify\";",
168
- "import cors from \"@fastify/cors\";",
169
- "import { z } from \"zod\";",
170
- "import { UserRepository } from \"./repositories/user.repository.js\";",
171
- "import { CustomerRepository } from \"./repositories/customer.repository.js\";",
172
- "import { RoleRepository } from \"./repositories/role.repository.js\";",
173
- "import { ReportRepository } from \"./repositories/report.repository.js\";",
174
- "import { DashboardService } from \"./services/dashboard.service.js\";",
175
- "",
176
- "const app = Fastify({ logger: true });",
177
- "await app.register(cors, { origin: true });",
178
- "",
179
- "const userRepo = new UserRepository();",
180
- "const customerRepo = new CustomerRepository();",
181
- "const roleRepo = new RoleRepository();",
182
- "const reportRepo = new ReportRepository();",
183
- "const dashboardService = new DashboardService();",
184
- "",
185
- "app.get(\"/health\", async () => ({ ok: true, service: \"agent-enderun-backend\" }));",
186
- "app.get(\"/api/v1/dashboard\", async () => {",
187
- " const summary = await dashboardService.getSummary();",
188
- " return { data: summary };",
189
- "});",
190
- "app.get(\"/api/v1/users\", async () => {",
191
- " const users = await userRepo.findAll();",
192
- " return { data: users };",
193
- "});",
194
- "app.get(\"/api/v1/roles\", async () => {",
195
- " const roles = await roleRepo.findAll();",
196
- " return { data: roles };",
197
- "});",
198
- "app.get(\"/api/v1/customers\", async () => {",
199
- " const customers = await customerRepo.findAll();",
200
- " return { data: customers };",
201
- "});",
202
- "app.get(\"/api/v1/reports\", async (request, reply) => {",
203
- " interface QueryParams {",
204
- " page?: number;",
205
- " limit?: number;",
206
- " }",
207
- " const { page = 1, limit = 10 } = request.query as QueryParams;",
208
- " const reports = await reportRepo.findAll();",
209
- " const startIndex = (Number(page) - 1) * Number(limit);",
210
- " const endIndex = startIndex + Number(limit);",
211
- " const paginatedReports = reports.slice(startIndex, endIndex);",
212
- " reply.send({",
213
- " data: paginatedReports,",
214
- " meta: {",
215
- " total: reports.length,",
216
- " page: Number(page),",
217
- " limit: Number(limit),",
218
- " },",
219
- " });",
220
- "});",
221
- "",
222
- "app.post(\"/api/v1/auth/login\", async (request, reply) => {",
223
- " const body = z.object({ email: z.string().email(), password: z.string().min(1) }).safeParse(request.body);",
224
- " if (!body.success) return reply.code(400).send({ error: { code: \"VALIDATION_ERROR\", message: \"Invalid login payload\" } });",
225
- "",
226
- " const user = await userRepo.findByEmail(body.data.email);",
227
- " if (!user) {",
228
- " const allUsers = await userRepo.findAll();",
229
- " return { data: { user: allUsers[0], token: \"demo-token\", expiresAt: new Date(Date.now() + 3600000).toISOString() } };",
230
- " }",
231
- " return { data: { user, token: \"demo-token\", expiresAt: new Date(Date.now() + 3600000).toISOString() } };",
232
- "});",
233
- "",
234
- "const port = Number(process.env.PORT || 4000);",
235
- "await app.listen({ port, host: \"0.0.0.0\" });",
236
- ].join("\n"));
237
-
238
- writeTextFile(path.join(targetDir, backendDir, ".env.example"), [
239
- "# Agent Enderun - Backend Environment Variables",
240
- "PORT=4000",
241
- "NODE_ENV=development",
242
- "DATABASE_URL=sqlite://./dev.db",
243
- "JWT_SECRET=your_secret_key_here",
244
- ].join("\n"));
245
-
246
- writeTextFile(path.join(targetDir, backendDir, "README.md"), [
247
- `# ${spec.title} Backend`,
248
- "",
249
- "Fastify API generated by Agent Enderun.",
250
- "",
251
- "## Commands",
252
- "",
253
- "- `npm run dev` strings",
254
- "- `npm run build` strings",
255
- "- `npm run test` strings",
256
- ].join("\n"));
257
- }
@@ -1,83 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { ensureDir, writeTextFile } from "./fs.js";
4
- import { getConfiguredPaths, getMemoryPath, updateProjectMemory } from "./memory.js";
5
- import type { AppSpec } from "./app-inferrer.js";
6
-
7
- const targetDir = process.cwd();
8
-
9
- export function updateProjectDocs(spec: AppSpec): void {
10
- const pathsMap = getConfiguredPaths();
11
- const docsDir = path.join(targetDir, pathsMap.docs);
12
- const apiDir = path.join(docsDir, "api");
13
- ensureDir(apiDir);
14
-
15
- const architecture = [];
16
- if (spec.platform === "full-stack" || spec.platform === "backend") {
17
- architecture.push(`- \`${pathsMap.backend}\`: Fastify API`);
18
- architecture.push(`- \`${pathsMap.backend}/src/types\`: Contract-first backend TypeScript types`);
19
- }
20
- if (spec.platform === "full-stack" || spec.platform === "web") {
21
- architecture.push(`- \`${pathsMap.frontend}\`: React dashboard`);
22
- }
23
- if (spec.platform === "mobile") {
24
- architecture.push(`- \`${pathsMap.mobile || "apps/mobile"}\`: Expo / React Native App`);
25
- }
26
-
27
- writeTextFile(path.join(docsDir, "project-docs.md"), [
28
- `# ${spec.title} Requirements`,
29
- "",
30
- "## Request",
31
- "",
32
- spec.rawDescription,
33
- "",
34
- "## Generated Scope",
35
- "",
36
- `- Platform: ${spec.platform}`,
37
- `- Domain: ${spec.domain}`,
38
- `- Auth: ${spec.modules.auth ? "yes" : "no"}`,
39
- `- Users: ${spec.modules.users ? "yes" : "no"}`,
40
- `- Roles: ${spec.modules.roles ? "yes" : "no"}`,
41
- `- Reports: ${spec.modules.reports ? "yes" : "no"}`,
42
- "",
43
- "## Architecture",
44
- "",
45
- ...architecture,
46
- ].join("\n"));
47
-
48
- writeTextFile(path.join(apiDir, "README.md"), [
49
- "# API Registry",
50
- "",
51
- "- `POST /api/v1/auth/login`",
52
- "- `GET /api/v1/dashboard`",
53
- "- `GET /api/v1/users`",
54
- "- `GET /api/v1/roles`",
55
- "- `GET /api/v1/customers`",
56
- "- `GET /api/v1/reports`",
57
- ].join("\n"));
58
- }
59
-
60
- export function updateMemoryForGeneratedApp(spec: AppSpec, traceId: string): void {
61
- const memoryPath = getMemoryPath();
62
- if (!fs.existsSync(memoryPath)) return;
63
-
64
- const pathsMap = getConfiguredPaths();
65
- const today = new Date().toISOString().split("T")[0];
66
-
67
- const impactedFiles = [];
68
- if (spec.platform === "full-stack" || spec.platform === "backend") impactedFiles.push(pathsMap.backend);
69
- if (spec.platform === "full-stack" || spec.platform === "web") impactedFiles.push(pathsMap.frontend);
70
- if (spec.platform === "mobile") impactedFiles.push(pathsMap.mobile || "apps/mobile");
71
- impactedFiles.push("project docs");
72
-
73
- const history = [
74
- `### ${today} — Generated ${spec.title}`,
75
- "",
76
- "- **Agent:** @manager",
77
- `- **Trace ID:** ${traceId}`,
78
- `- **Action:** Created ${spec.platform} starter from natural language request.`,
79
- `- **Files:** ${impactedFiles.join(", ")}`,
80
- ].join("\n");
81
-
82
- updateProjectMemory("HISTORY", history);
83
- }