agent-enderun 0.1.10 → 0.2.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.
- package/.enderun/BRAIN_DASHBOARD.md +43 -0
- package/.enderun/ENDERUN.md +203 -0
- package/.enderun/PROJECT_MEMORY.md +137 -36
- package/.enderun/agents/analyst.md +21 -10
- package/.enderun/agents/backend.md +12 -11
- package/.enderun/agents/explorer.md +10 -7
- package/.enderun/agents/frontend.md +9 -20
- package/.enderun/agents/git.md +16 -12
- package/.enderun/agents/manager.md +14 -15
- package/.enderun/agents/mobile.md +5 -5
- package/.enderun/agents/native.md +5 -5
- package/.enderun/benchmarks/.gitkeep +0 -0
- package/.enderun/cli-commands.json +13 -1
- package/.enderun/config.json +1 -1
- package/.enderun/docs/api/README.md +10 -9
- package/.enderun/docs/api/auth.md +11 -0
- package/.enderun/docs/api/errors.md +7 -0
- package/.enderun/docs/error-handling.md +12 -0
- package/.enderun/docs/privacy.md +3 -0
- package/.enderun/docs/security.md +12 -0
- package/.enderun/docs/tech-stack.md +1 -0
- package/.enderun/docs/troubleshooting.md +7 -0
- package/.enderun/knowledge/api_design_rules.md +6 -0
- package/.enderun/knowledge/async_error_handling.md +18 -0
- package/.enderun/knowledge/branded_types_pattern.md +1 -0
- package/.enderun/knowledge/code_review_checklist.md +7 -0
- package/.enderun/knowledge/contract_versioning.md +7 -0
- package/.enderun/knowledge/database_migration.md +6 -0
- package/.enderun/knowledge/deployment_checklist.md +7 -0
- package/.enderun/knowledge/git_commit_strategy.md +10 -0
- package/.enderun/knowledge/legacy_onboarding.md +7 -0
- package/.enderun/knowledge/monitoring_setup.md +5 -0
- package/.enderun/knowledge/performance_guidelines.md +11 -0
- package/.enderun/knowledge/repository_patterns.md +9 -0
- package/.enderun/knowledge/security_scanning.md +6 -0
- package/.enderun/knowledge/testing_standards.md +7 -0
- package/.enderun/knowledge/troubleshooting_guide.md +5 -0
- package/.enderun/knowledge/zero_ui_library_policy.md +1 -0
- package/.enderun/logs/analyst.json +1 -0
- package/.enderun/logs/backend.json +1 -0
- package/.enderun/logs/explorer.json +1 -0
- package/.enderun/logs/frontend.json +1 -0
- package/.enderun/logs/git.json +1 -0
- package/.enderun/logs/manager.json +363 -0
- package/.enderun/logs/mobile.json +1 -0
- package/.enderun/logs/native.json +1 -0
- package/.enderun/monitoring/.gitkeep +0 -0
- package/ENDERUN.md +8 -8
- package/LICENSE +21 -0
- package/README.md +595 -195
- package/bin/cli.js +306 -79
- package/package.json +35 -2
- package/packages/framework-mcp/README.md +47 -81
- package/packages/framework-mcp/dist/index.js +13 -971
- package/packages/framework-mcp/dist/schemas.js +84 -0
- package/packages/framework-mcp/dist/tools/academy.js +184 -0
- package/packages/framework-mcp/dist/tools/codebase.js +294 -0
- package/packages/framework-mcp/dist/tools/contract.js +95 -0
- package/packages/framework-mcp/dist/tools/database.js +52 -0
- package/packages/framework-mcp/dist/tools/framework.js +161 -0
- package/packages/framework-mcp/dist/tools/git.js +53 -0
- package/packages/framework-mcp/dist/tools/index.js +42 -0
- package/packages/framework-mcp/dist/tools/knowledge.js +69 -0
- package/packages/framework-mcp/dist/tools/memory.js +94 -0
- package/packages/framework-mcp/dist/tools/messages.js +71 -0
- package/packages/framework-mcp/dist/tools/repository.js +76 -0
- package/packages/framework-mcp/dist/tools/security.js +122 -0
- package/packages/framework-mcp/dist/utils.js +82 -0
- package/packages/framework-mcp/package-lock.json +1836 -0
- package/packages/framework-mcp/package.json +1 -1
- package/packages/framework-mcp/src/index.ts +20 -970
- package/packages/framework-mcp/src/schemas.ts +106 -0
- package/packages/framework-mcp/src/tools/academy.ts +178 -0
- package/packages/framework-mcp/src/tools/codebase.ts +284 -0
- package/packages/framework-mcp/src/tools/contract.ts +91 -0
- package/packages/framework-mcp/src/tools/database.ts +49 -0
- package/packages/framework-mcp/src/tools/framework.ts +157 -0
- package/packages/framework-mcp/src/tools/git.ts +43 -0
- package/packages/framework-mcp/src/tools/index.ts +45 -0
- package/packages/framework-mcp/src/tools/knowledge.ts +68 -0
- package/packages/framework-mcp/src/tools/memory.ts +88 -0
- package/packages/framework-mcp/src/tools/messages.ts +70 -0
- package/packages/framework-mcp/src/tools/repository.ts +76 -0
- package/packages/framework-mcp/src/tools/security.ts +122 -0
- package/packages/framework-mcp/src/utils.ts +90 -0
- package/packages/framework-mcp/tests/mcp-server.test.ts +6 -0
- package/packages/shared-types/README.md +28 -51
- package/packages/shared-types/contract.version.json +4 -4
- package/packages/shared-types/dist/index.d.ts +80 -48
- package/packages/shared-types/dist/index.d.ts.map +1 -1
- package/packages/shared-types/dist/index.js +5 -8
- package/packages/shared-types/dist/index.js.map +1 -1
- package/packages/shared-types/package.json +1 -1
- package/packages/shared-types/src/index.ts +79 -51
- package/CHANGELOG.md +0 -97
- package/CLAUDE.md +0 -7
- package/CODEX.md +0 -7
- package/CURSOR.md +0 -7
- package/GEMINI.md +0 -7
- package/docs/tech-stack.md +0 -10
- package/gemini-extension.json +0 -5
- package/panda.config.ts +0 -20
- /package/{docs → .enderun/docs}/project-docs.md +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { Project, SyntaxKind } from "ts-morph";
|
|
4
|
+
import {
|
|
5
|
+
collectFilesRecursively,
|
|
6
|
+
resolveSafePath,
|
|
7
|
+
buildLineMatches
|
|
8
|
+
} from "../utils.js";
|
|
9
|
+
import {
|
|
10
|
+
SECURITY_AUDIT_ARGS_SCHEMA,
|
|
11
|
+
ANALYZE_CONSTITUTION_COMPLIANCE_ARGS_SCHEMA
|
|
12
|
+
} from "../schemas.js";
|
|
13
|
+
|
|
14
|
+
export const securityTools = [
|
|
15
|
+
{
|
|
16
|
+
name: "security_audit_scan",
|
|
17
|
+
description: "Scans the codebase for security vulnerabilities like hardcoded secrets, raw SQL, and unsafe async patterns.",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
path: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Path to scan (relative to project root)",
|
|
24
|
+
default: ".",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "analyze_constitution_compliance",
|
|
31
|
+
description: "Scans a file or directory for violations of the project's ENDERUN.md rules (e.g. Zero UI Library, Branded Types).",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
path: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "Path to scan (relative to project root)",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
required: ["path"],
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
export const securityHandlers = {
|
|
46
|
+
security_audit_scan: async (args: any, projectRoot: string) => {
|
|
47
|
+
const parsed = SECURITY_AUDIT_ARGS_SCHEMA.safeParse(args ?? {});
|
|
48
|
+
if (!parsed.success) return { content: [{ type: "text", text: "Invalid path argument." }] };
|
|
49
|
+
const vulnerabilities: string[] = [];
|
|
50
|
+
const scanRules = [
|
|
51
|
+
{ pattern: /sql`/, message: "Potential Raw SQL usage detected (check Kysely usage)", severity: "HIGH" },
|
|
52
|
+
{ pattern: /(?<!\/\/\s*)console\.log/, message: "console.log found in production code", severity: "LOW" },
|
|
53
|
+
{ pattern: /(password|secret|api_?key)\s*[:=]\s*['"][^'"]+['"]/i, message: "Potential hardcoded secret/password detected", severity: "CRITICAL" },
|
|
54
|
+
{ pattern: /:\s*any(?!\w)/, message: "Usage of 'any' type detected", severity: "MEDIUM" },
|
|
55
|
+
{ pattern: /(?<!\w)eval\s*\(/, message: "Dangerous 'eval()' usage detected", severity: "HIGH" },
|
|
56
|
+
{ pattern: /\.innerHTML\s*=/, message: "Unsafe innerHTML assignment detected (XSS risk)", severity: "MEDIUM" },
|
|
57
|
+
{ pattern: /dangerouslySetInnerHTML/, message: "React dangerouslySetInnerHTML detected", severity: "MEDIUM" },
|
|
58
|
+
{ pattern: /TODO:/, message: "Outstanding TODO item found", severity: "LOW" },
|
|
59
|
+
];
|
|
60
|
+
try {
|
|
61
|
+
const safeTargetPath = resolveSafePath(projectRoot, parsed.data.path);
|
|
62
|
+
if (!fs.existsSync(safeTargetPath)) return { content: [{ type: "text", text: "Target path not found." }] };
|
|
63
|
+
const files = collectFilesRecursively(safeTargetPath, new Set(["ts", "tsx"]));
|
|
64
|
+
for (const rule of scanRules) {
|
|
65
|
+
const ruleMatches = buildLineMatches(files, (line) => typeof rule.pattern === "string" ? line.includes(rule.pattern) : rule.pattern.test(line), 5, projectRoot);
|
|
66
|
+
if (ruleMatches.length > 0) vulnerabilities.push(`[${rule.severity}] ${rule.message}:\n${ruleMatches.join("\n")}`);
|
|
67
|
+
}
|
|
68
|
+
const tsProject = new Project({ compilerOptions: { allowJs: true } });
|
|
69
|
+
tsProject.addSourceFilesAtPaths(path.join(safeTargetPath, "**/*.{ts,tsx}"));
|
|
70
|
+
for (const sourceFile of tsProject.getSourceFiles()) {
|
|
71
|
+
const relativePath = path.relative(projectRoot, sourceFile.getFilePath());
|
|
72
|
+
sourceFile.forEachDescendant((node) => {
|
|
73
|
+
if (node.getKindName() === "AnyKeyword") {
|
|
74
|
+
vulnerabilities.push(`[MEDIUM] Precise 'any' type detected in AST at ${relativePath}:${node.getStartLineNumber()}`);
|
|
75
|
+
}
|
|
76
|
+
if (node.getKind() === SyntaxKind.CallExpression) {
|
|
77
|
+
const callExp = node.asKind(SyntaxKind.CallExpression);
|
|
78
|
+
if (callExp?.getExpression().getText() === "console.log") {
|
|
79
|
+
vulnerabilities.push(`[LOW] Production 'console.log' detected in AST at ${relativePath}:${node.getStartLineNumber()}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return { content: [{ type: "text", text: vulnerabilities.length > 0 ? `### ADVANCED SECURITY AUDIT RESULTS\n\n${Array.from(new Set(vulnerabilities)).join("\n\n")}` : "No security patterns or rule violations detected (Regex & AST verified)." }] };
|
|
85
|
+
} catch (error) {
|
|
86
|
+
return { content: [{ type: "text", text: "Security scan failed." }] };
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
analyze_constitution_compliance: async (args: any, projectRoot: string) => {
|
|
90
|
+
const parsed = ANALYZE_CONSTITUTION_COMPLIANCE_ARGS_SCHEMA.safeParse(args ?? {});
|
|
91
|
+
if (!parsed.success) return { content: [{ type: "text", text: "Invalid path argument." }] };
|
|
92
|
+
try {
|
|
93
|
+
const safePath = resolveSafePath(projectRoot, parsed.data.path);
|
|
94
|
+
const violations: string[] = [];
|
|
95
|
+
const checkFile = (filePath: string) => {
|
|
96
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
97
|
+
const relativePath = path.relative(projectRoot, filePath);
|
|
98
|
+
const forbiddenLibraries = ["@shadcn", "mui", "@chakra-ui", "antd", "bootstrap", "tailwindcss"];
|
|
99
|
+
for (const lib of forbiddenLibraries) {
|
|
100
|
+
if (content.includes(lib)) violations.push(`${relativePath}: Violation of Zero UI Library Policy (found '${lib}')`);
|
|
101
|
+
}
|
|
102
|
+
if (content.includes("console.log") && !filePath.includes("cli.js") && !filePath.includes("node_modules")) {
|
|
103
|
+
violations.push(`${relativePath}: Violation of Logging Policy (found 'console.log', use proper logger)`);
|
|
104
|
+
}
|
|
105
|
+
if (content.includes("sql`") && !filePath.includes("node_modules")) {
|
|
106
|
+
violations.push(`${relativePath}: Potential Violation of Kysely Standards (found raw 'sql' tag)`);
|
|
107
|
+
}
|
|
108
|
+
if (filePath.endsWith(".ts") && !filePath.includes("shared-types") && !filePath.includes("node_modules")) {
|
|
109
|
+
if (content.match(/interface.*ID\s*:\s*string/)) violations.push(`${relativePath}: Violation of Branded Types Law (found ID typed as plain string)`);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
if (fs.lstatSync(safePath).isDirectory()) {
|
|
113
|
+
collectFilesRecursively(safePath, new Set(["ts", "tsx", "js", "jsx"])).forEach(checkFile);
|
|
114
|
+
} else {
|
|
115
|
+
checkFile(safePath);
|
|
116
|
+
}
|
|
117
|
+
return { content: [{ type: "text", text: `### CONSTITUTION COMPLIANCE REPORT\n\n` + (violations.length > 0 ? `⚠️ **VIOLATIONS FOUND:**\n${violations.map(v => `- ${v}`).join("\n")}` : "✅ **ALL SYSTEMS COMPLIANT:** No violations of ENDERUN.md rules detected.") }] };
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return { content: [{ type: "text", text: "Compliance analysis failed." }] };
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
|
|
4
|
+
export const FRAMEWORK_VERSION = "0.2.0";
|
|
5
|
+
|
|
6
|
+
export function getFrameworkDir(projectRoot: string): string {
|
|
7
|
+
const adapters = [".gemini", ".claude", ".cursor", ".codex", ".enderun"];
|
|
8
|
+
for (const adp of adapters) {
|
|
9
|
+
const fullPath = path.join(projectRoot, adp);
|
|
10
|
+
if (fs.existsSync(fullPath) && fs.lstatSync(fullPath).isDirectory()) {
|
|
11
|
+
return adp;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return ".enderun";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function resolveSafePath(projectRoot: string, targetPath: string): string {
|
|
18
|
+
const resolved = path.resolve(projectRoot, targetPath);
|
|
19
|
+
const relative = path.relative(projectRoot, resolved);
|
|
20
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
21
|
+
throw new Error("Path escapes project root.");
|
|
22
|
+
}
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function collectFilesRecursively(targetPath: string, extensions: Set<string>): string[] {
|
|
27
|
+
const results: string[] = [];
|
|
28
|
+
const entries = fs.readdirSync(targetPath, { withFileTypes: true });
|
|
29
|
+
for (const entry of entries) {
|
|
30
|
+
const fullPath = path.join(targetPath, entry.name);
|
|
31
|
+
if (entry.isDirectory()) {
|
|
32
|
+
if (entry.name === "node_modules" || entry.name === ".git")
|
|
33
|
+
continue;
|
|
34
|
+
results.push(...collectFilesRecursively(fullPath, extensions));
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const ext = path.extname(entry.name).slice(1).toLowerCase();
|
|
38
|
+
if (extensions.has(ext))
|
|
39
|
+
results.push(fullPath);
|
|
40
|
+
}
|
|
41
|
+
return results;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function buildLineMatches(files: string[], matcher: (line: string) => boolean, maxResults: number, projectRoot: string): string[] {
|
|
45
|
+
const matches: string[] = [];
|
|
46
|
+
for (const filePath of files) {
|
|
47
|
+
if (matches.length >= maxResults)
|
|
48
|
+
break;
|
|
49
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
50
|
+
const lines = content.split("\n");
|
|
51
|
+
for (let i = 0; i < lines.length; i++) {
|
|
52
|
+
if (matches.length >= maxResults)
|
|
53
|
+
break;
|
|
54
|
+
const line = lines[i];
|
|
55
|
+
if (!matcher(line))
|
|
56
|
+
continue;
|
|
57
|
+
const relativePath = path.relative(projectRoot, filePath);
|
|
58
|
+
matches.push(`${relativePath}:${i + 1}:${line}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return matches;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function collectMarkdownArtifacts(projectRoot: string): string[] {
|
|
65
|
+
const docsRoot = path.join(projectRoot, "docs");
|
|
66
|
+
if (!fs.existsSync(docsRoot))
|
|
67
|
+
return [];
|
|
68
|
+
return collectFilesRecursively(docsRoot, new Set(["md"])).map((filePath) => path.relative(projectRoot, filePath));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function replaceSectionContent(markdown: string, sectionTitle: string, newBody: string): string {
|
|
72
|
+
const escaped = sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
73
|
+
const sectionRegex = new RegExp(`## ${escaped}[\\s\\S]*?(?=\\n## |$)`, "m");
|
|
74
|
+
if (!sectionRegex.test(markdown)) {
|
|
75
|
+
throw new Error(`Section not found: ${sectionTitle}`);
|
|
76
|
+
}
|
|
77
|
+
return markdown.replace(sectionRegex, `## ${sectionTitle}\n\n${newBody.trim()}\n`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function prependToSection(markdown: string, sectionTitle: string, contentToPrepend: string): string {
|
|
81
|
+
const escaped = sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
82
|
+
const sectionRegex = new RegExp(`(## ${escaped}\\n)([\\s\\S]*?)(?=\\n## |$)`, "m");
|
|
83
|
+
const match = markdown.match(sectionRegex);
|
|
84
|
+
if (!match) {
|
|
85
|
+
throw new Error(`Section not found: ${sectionTitle}`);
|
|
86
|
+
}
|
|
87
|
+
const currentBody = match[2].trimStart();
|
|
88
|
+
const updatedBody = `${contentToPrepend.trim()}\n\n${currentBody}`.trim();
|
|
89
|
+
return markdown.replace(sectionRegex, `$1\n${updatedBody}\n`);
|
|
90
|
+
}
|
|
@@ -1,79 +1,56 @@
|
|
|
1
|
-
# AI-Enderun Shared Types v0.
|
|
1
|
+
# AI-Enderun Shared Types (v0.2.0)
|
|
2
2
|
|
|
3
3
|
English | [Türkçe](#türkçe)
|
|
4
4
|
|
|
5
|
-
The `@ai-enderun/shared-types` package is the
|
|
5
|
+
The `@ai-enderun/shared-types` package is the "Supreme Law" of data within the Agent Enderun framework. It ensures perfect synchronization between backend and frontend through a **Contract-First** approach.
|
|
6
6
|
|
|
7
7
|
## English
|
|
8
8
|
|
|
9
|
-
###
|
|
9
|
+
### Core Principles
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- **Zero Drift:** Backend and frontend implementation must strictly follow these types.
|
|
12
|
+
- **Branded Types:** We use the "Branded Types" pattern to ensure type safety for domain identifiers (e.g., `UserID` vs. `ProjectID`).
|
|
13
|
+
- **Atomic Versioning:** Every change to this package triggers a hash mismatch in the framework, forcing a contract verification step.
|
|
12
14
|
|
|
13
|
-
###
|
|
15
|
+
### Key Components
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
### Principles
|
|
21
|
-
|
|
22
|
-
- **Contract-First:** Define shared types before implementation.
|
|
23
|
-
- **Branded Identifiers:** Use domain-specific IDs such as `UserID` and `SessionID`.
|
|
24
|
-
- **Explicit Response Shapes:** Keep success and error payloads consistent.
|
|
25
|
-
- **ULID Support:** Native support for sortable 26-character identifiers.
|
|
26
|
-
- **Hash Verification:** Recalculate and verify the contract hash whenever shared types change.
|
|
27
|
-
|
|
28
|
-
### Development
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
cd packages/shared-types
|
|
32
|
-
npm install
|
|
33
|
-
npm run build
|
|
34
|
-
npm run typecheck
|
|
17
|
+
#### Branded Identifiers
|
|
18
|
+
Prevents accidental usage of a UserID where a ProjectID is expected.
|
|
19
|
+
```typescript
|
|
20
|
+
export type UserID = string & { readonly __brand: "UserID" };
|
|
21
|
+
export type ProjectID = string & { readonly __brand: "ProjectID" };
|
|
35
22
|
```
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
#### API Contracts
|
|
25
|
+
Standardized shapes for requests and responses.
|
|
39
26
|
```typescript
|
|
40
|
-
|
|
27
|
+
export interface ApiResponse<T> {
|
|
28
|
+
data: T;
|
|
29
|
+
traceId: string;
|
|
30
|
+
timestamp: string;
|
|
31
|
+
}
|
|
41
32
|
```
|
|
42
33
|
|
|
43
34
|
### Contract Workflow
|
|
44
35
|
|
|
45
|
-
1. Modify
|
|
46
|
-
2. Build
|
|
47
|
-
3.
|
|
48
|
-
4.
|
|
36
|
+
1. **Modify**: Update `src/index.ts` with new DTOs or Types.
|
|
37
|
+
2. **Build**: `npm run build`
|
|
38
|
+
3. **Verify**: Run `agent-enderun verify-contract` to detect changes.
|
|
39
|
+
4. **Sync**: Update `contract.version.json` with the new hash using the MCP tool `update_contract_hash`.
|
|
49
40
|
|
|
50
41
|
## Türkçe
|
|
51
42
|
|
|
52
|
-
`@ai-enderun/shared-types`,
|
|
53
|
-
|
|
54
|
-
### Amaç
|
|
55
|
-
|
|
56
|
-
Bu paket, kontrat kaymasını önler ve depo genelinde kontrat-öncelikli bir iş akışı sağlar. Ortak türler, domain ID’leri ve yanıt yapıları için tek kaynak olarak çalışır.
|
|
57
|
-
|
|
58
|
-
### Neden önemli?
|
|
59
|
-
|
|
60
|
-
- Frontend ve backend’in aynı veri yapıları üzerinde anlaşmasını sağlar.
|
|
61
|
-
- Tekrarlanan tip tanımlarını engeller.
|
|
62
|
-
- `contract.version.json` ile API sözleşmesi doğrulanmasını destekler.
|
|
63
|
-
- AI destekli geliştirmeyi daha güvenli ve öngörülebilir hale getirir.
|
|
43
|
+
`@ai-enderun/shared-types`, Agent Enderun çerçevesindeki verilerin "Yüce Yasası"dır. **Kontrat Öncelikli** (Contract-First) yaklaşımıyla backend ve frontend arasında kusursuz bir uyum sağlar.
|
|
64
44
|
|
|
65
|
-
###
|
|
45
|
+
### Temel Özellikler
|
|
66
46
|
|
|
67
|
-
-
|
|
68
|
-
- **
|
|
69
|
-
- **
|
|
70
|
-
- **ULID Desteği:** 26 karakterlik sıralanabilir kimlikler.
|
|
71
|
-
- **Hash Doğrulama:** Paylaşılan tipler değiştiğinde kontrat hash’i güncellenir.
|
|
47
|
+
- **Branded Types:** Kimlik karışıklıklarını önlemek için özel tipler kullanılır.
|
|
48
|
+
- **API Sözleşmeleri:** Tüm istek ve yanıtlar için standart şablonlar.
|
|
49
|
+
- **Hash Doğrulama:** Tip değişiklikleri merkezi bir hash üzerinden takip edilir.
|
|
72
50
|
|
|
73
51
|
### Geliştirme
|
|
74
52
|
|
|
75
53
|
```bash
|
|
76
|
-
cd packages/shared-types
|
|
77
54
|
npm install
|
|
78
55
|
npm run build
|
|
79
56
|
npm run typecheck
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
3
|
-
"last_updated": "2026-05-
|
|
4
|
-
"contract_hash": "
|
|
2
|
+
"version": "0.1.11",
|
|
3
|
+
"last_updated": "2026-05-11T13:45:00Z",
|
|
4
|
+
"contract_hash": "a8ff433521ce2d7e249d67e84ae8ef0e54082260195b672789ef7a48a9a1e35a",
|
|
5
5
|
"breaking_changes": [
|
|
6
|
-
{ "version": "0.1.
|
|
6
|
+
{ "version": "0.1.11", "description": "Extended shared types for Enderun Brain Dashboard" }
|
|
7
7
|
],
|
|
8
8
|
"deprecated_versions": []
|
|
9
9
|
}
|
|
@@ -1,61 +1,93 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Agent Enderun — Shared Types
|
|
3
|
+
*
|
|
4
|
+
* This file is the Single Source of Truth for all Backend and Frontend communication.
|
|
5
|
+
* All IDs use the Branded Types pattern for type safety.
|
|
5
6
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Branded Type Utility
|
|
9
|
+
*/
|
|
10
|
+
export type Brand<K, T> = K & {
|
|
11
|
+
__brand: T;
|
|
8
12
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
export
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
data: T[];
|
|
20
|
-
total: number;
|
|
21
|
-
page: number;
|
|
22
|
-
limit: number;
|
|
23
|
-
hasMore: boolean;
|
|
24
|
-
}
|
|
25
|
-
export interface ApiSuccess<T> {
|
|
26
|
-
success: true;
|
|
27
|
-
data: T;
|
|
28
|
-
}
|
|
29
|
-
export interface ApiError {
|
|
30
|
-
success: false;
|
|
31
|
-
code: string;
|
|
32
|
-
message: string;
|
|
33
|
-
statusCode: number;
|
|
34
|
-
}
|
|
35
|
-
export type ApiResponse<T> = ApiSuccess<T> | ApiError;
|
|
13
|
+
/**
|
|
14
|
+
* Entity IDs (Branded)
|
|
15
|
+
*/
|
|
16
|
+
export type TraceID = Brand<string, "TraceID">;
|
|
17
|
+
export type AgentID = Brand<string, "AgentID">;
|
|
18
|
+
export type ProjectID = Brand<string, "ProjectID">;
|
|
19
|
+
export type UserID = Brand<string, "UserID">;
|
|
20
|
+
/**
|
|
21
|
+
* Domain Models
|
|
22
|
+
*/
|
|
36
23
|
export interface User {
|
|
37
24
|
id: UserID;
|
|
38
25
|
email: string;
|
|
39
|
-
|
|
40
|
-
role:
|
|
26
|
+
fullName: string;
|
|
27
|
+
role: "ADMIN" | "DEVELOPER" | "VIEWER";
|
|
41
28
|
createdAt: string;
|
|
42
|
-
updatedAt: string;
|
|
43
29
|
}
|
|
44
|
-
export interface
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
30
|
+
export interface UserProfile extends User {
|
|
31
|
+
avatarUrl?: string;
|
|
32
|
+
bio?: string;
|
|
33
|
+
preferences: Record<string, unknown>;
|
|
48
34
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Project Status Types
|
|
37
|
+
*/
|
|
38
|
+
export type ProjectPhase = "PHASE_0" | "PHASE_1" | "PHASE_2" | "PHASE_3" | "PHASE_4";
|
|
39
|
+
export type ExecutionProfile = "Lightweight" | "Full";
|
|
40
|
+
export interface ProjectStatus {
|
|
41
|
+
phase: ProjectPhase;
|
|
42
|
+
profile: ExecutionProfile;
|
|
43
|
+
lastUpdate: string;
|
|
44
|
+
activeTraceId: TraceID | null;
|
|
45
|
+
blockers: string[];
|
|
52
46
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Task Management Types
|
|
49
|
+
*/
|
|
50
|
+
export type TaskPriority = "P0" | "P1" | "P2" | "P3";
|
|
51
|
+
export type TaskStatus = "PENDING" | "IN_PROGRESS" | "BLOCKED" | "COMPLETED" | "FAILED";
|
|
52
|
+
export interface Task {
|
|
53
|
+
id: TraceID;
|
|
54
|
+
description: string;
|
|
55
|
+
agent: AgentID;
|
|
56
|
+
priority: TaskPriority;
|
|
57
|
+
status: TaskStatus;
|
|
58
|
+
createdAt: string;
|
|
59
|
+
updatedAt: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Audit & Agent Logging Types
|
|
63
|
+
*/
|
|
64
|
+
export type ActionType = "CREATE" | "MODIFY" | "DELETE" | "RESEARCH" | "ORCHESTRATE";
|
|
65
|
+
export type ActionStatus = "SUCCESS" | "FAILURE" | "WAITING";
|
|
66
|
+
export interface AgentActionLog {
|
|
67
|
+
timestamp: string;
|
|
68
|
+
agent: AgentID;
|
|
69
|
+
action: ActionType;
|
|
70
|
+
requestId: TraceID | "—";
|
|
71
|
+
status: ActionStatus;
|
|
72
|
+
summary: string;
|
|
73
|
+
files?: string[];
|
|
74
|
+
details?: Record<string, unknown>;
|
|
57
75
|
}
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
/**
|
|
77
|
+
* API Response Wrappers
|
|
78
|
+
*/
|
|
79
|
+
export interface ApiResponse<T> {
|
|
80
|
+
data: T;
|
|
81
|
+
meta?: {
|
|
82
|
+
requestId: TraceID;
|
|
83
|
+
timestamp: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export interface ApiError {
|
|
87
|
+
error: {
|
|
88
|
+
code: string;
|
|
89
|
+
message: string;
|
|
90
|
+
details?: unknown;
|
|
91
|
+
};
|
|
60
92
|
}
|
|
61
93
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Agent Enderun — Shared Types
|
|
3
|
+
*
|
|
4
|
+
* This file is the Single Source of Truth for all Backend and Frontend communication.
|
|
5
|
+
* All IDs use the Branded Types pattern for type safety.
|
|
5
6
|
*/
|
|
6
|
-
export
|
|
7
|
-
return seedTime.toString(36) + Math.random().toString(36).substring(2, 10);
|
|
8
|
-
};
|
|
9
|
-
export const createUserID = () => `usr_${createULID()}`;
|
|
10
|
-
export const createSessionID = () => `sess_${createULID()}`;
|
|
7
|
+
export {};
|
|
11
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|