atabey 0.0.2 → 0.0.4
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/README.md +6 -3
- package/dist/framework-mcp/src/tools/definitions.js +1 -1
- package/dist/framework-mcp/src/tools/definitions.js.map +1 -1
- package/dist/framework-mcp/src/tools/framework/run_tests.js +5 -3
- package/dist/framework-mcp/src/tools/framework/run_tests.js.map +1 -1
- package/dist/framework-mcp/src/tools/quality/check_lint.js +7 -5
- package/dist/framework-mcp/src/tools/quality/check_lint.js.map +1 -1
- package/dist/framework-mcp/src/tools/shell/run_command.js +12 -2
- package/dist/framework-mcp/src/tools/shell/run_command.js.map +1 -1
- package/dist/framework-mcp/src/utils/cli.d.ts +14 -3
- package/dist/framework-mcp/src/utils/cli.js +51 -13
- package/dist/framework-mcp/src/utils/cli.js.map +1 -1
- package/dist/src/cli/adapters/core.js +34 -10
- package/dist/src/cli/adapters/core.js.map +1 -1
- package/dist/src/cli/adapters/scaffold.d.ts +1 -1
- package/dist/src/cli/adapters/scaffold.js +8 -8
- package/dist/src/cli/adapters/scaffold.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-core.d.ts +4 -1
- package/dist/src/cli/commands/init/scaffold-core.js +12 -5
- package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
- package/dist/src/cli/commands/init/scaffold-docs.d.ts +3 -0
- package/dist/src/cli/commands/init/scaffold-docs.js +37 -0
- package/dist/src/cli/commands/init/scaffold-docs.js.map +1 -0
- package/dist/src/cli/commands/init.js +41 -17
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/utils/i18n.d.ts +15 -0
- package/dist/src/cli/utils/i18n.js +29 -0
- package/dist/src/cli/utils/i18n.js.map +1 -0
- package/dist/src/modules/agents/definitions.d.ts +6 -6
- package/dist/src/modules/agents/definitions.js +30 -26
- package/dist/src/modules/agents/definitions.js.map +1 -1
- package/dist/src/modules/agents/registry/backend.js +5 -6
- package/dist/src/modules/agents/registry/backend.js.map +1 -1
- package/dist/src/modules/agents/registry/database.js +2 -2
- package/dist/src/modules/agents/registry/database.js.map +1 -1
- package/framework-mcp/dist/tools/definitions.js +1 -1
- package/framework-mcp/dist/tools/framework/run_tests.js +5 -3
- package/framework-mcp/dist/tools/quality/check_lint.js +7 -5
- package/framework-mcp/dist/tools/shell/run_command.js +12 -2
- package/framework-mcp/dist/utils/cli.js +51 -13
- package/framework-mcp/package.json +1 -1
- package/framework-mcp/src/tools/definitions.ts +1 -1
- package/framework-mcp/src/tools/framework/run_tests.ts +5 -3
- package/framework-mcp/src/tools/quality/check_lint.ts +8 -5
- package/framework-mcp/src/tools/shell/run_command.ts +12 -2
- package/framework-mcp/src/utils/cli.ts +45 -13
- package/package.json +2 -2
- package/src/cli/adapters/core.ts +36 -12
- package/src/cli/adapters/scaffold.ts +10 -8
- package/src/cli/commands/init/scaffold-core.ts +14 -6
- package/src/cli/commands/init/scaffold-docs.ts +44 -0
- package/src/cli/commands/init.ts +48 -18
- package/src/cli/utils/i18n.ts +44 -0
- package/src/modules/agents/definitions.ts +32 -26
- package/src/modules/agents/registry/backend.ts +5 -6
- package/src/modules/agents/registry/database.ts +2 -2
|
@@ -1,20 +1,58 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
1
3
|
import { execFileSync } from "child_process";
|
|
2
4
|
/**
|
|
3
|
-
* Executes a
|
|
4
|
-
* Captures stderr gracefully to prevent stream crashes.
|
|
5
|
+
* Executes a command safely and returns the output.
|
|
5
6
|
*/
|
|
6
|
-
export function safeExec(
|
|
7
|
+
export function safeExec(cmd, args, cwd, timeout = 30000) {
|
|
7
8
|
try {
|
|
8
|
-
return execFileSync(
|
|
9
|
-
cwd,
|
|
10
|
-
encoding: "utf8",
|
|
11
|
-
timeout: timeout || 30000,
|
|
12
|
-
maxBuffer: 1024 * 1024,
|
|
13
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
14
|
-
});
|
|
9
|
+
return execFileSync(cmd, args, { cwd, timeout, encoding: "utf8", stdio: "pipe" });
|
|
15
10
|
}
|
|
16
|
-
catch (
|
|
17
|
-
|
|
18
|
-
throw new Error(err.stderr || err.message || "Command execution failed", { cause: error });
|
|
11
|
+
catch (err) {
|
|
12
|
+
return err.stdout?.toString() || err.stderr?.toString() || err.message;
|
|
19
13
|
}
|
|
20
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Detects the backend language from the framework configuration.
|
|
17
|
+
*/
|
|
18
|
+
export function getBackendLanguage(projectRoot) {
|
|
19
|
+
try {
|
|
20
|
+
const configPath = path.join(projectRoot, ".atabey", "config.json");
|
|
21
|
+
if (fs.existsSync(configPath)) {
|
|
22
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
23
|
+
return config.backendLanguage || "Node.js (TypeScript)";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Fallback to default
|
|
28
|
+
}
|
|
29
|
+
return "Node.js (TypeScript)";
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns the default lint command for the given language.
|
|
33
|
+
*/
|
|
34
|
+
export function getDefaultLintCommand(language) {
|
|
35
|
+
if (language.includes("Go"))
|
|
36
|
+
return "go fmt ./...";
|
|
37
|
+
if (language.includes("Java"))
|
|
38
|
+
return "./gradlew check"; // or mvn check
|
|
39
|
+
if (language.includes("Python"))
|
|
40
|
+
return "ruff check .";
|
|
41
|
+
if (language.includes(".NET"))
|
|
42
|
+
return "dotnet format";
|
|
43
|
+
return "npm run lint";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Returns the default test command for the given language.
|
|
47
|
+
*/
|
|
48
|
+
export function getDefaultTestCommand(language) {
|
|
49
|
+
if (language.includes("Go"))
|
|
50
|
+
return "go test ./...";
|
|
51
|
+
if (language.includes("Java"))
|
|
52
|
+
return "./gradlew test"; // or mvn test
|
|
53
|
+
if (language.includes("Python"))
|
|
54
|
+
return "pytest";
|
|
55
|
+
if (language.includes(".NET"))
|
|
56
|
+
return "dotnet test";
|
|
57
|
+
return "npm test";
|
|
58
|
+
}
|
|
@@ -132,7 +132,7 @@ export const TOOLS: ToolDefinition[] = [
|
|
|
132
132
|
inputSchema: {
|
|
133
133
|
type: "object",
|
|
134
134
|
properties: {
|
|
135
|
-
command: { type: "string", description: "The test command to run (default: '
|
|
135
|
+
command: { type: "string", description: "The test command to run (default: project's standard test command)" }
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
},
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { execSync } from "child_process";
|
|
2
2
|
import { RunTestsArgs, ToolResult } from "../types.js";
|
|
3
|
+
import { getBackendLanguage, getDefaultTestCommand } from "../../utils/cli.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Executes project tests and returns results for agent analysis.
|
|
6
7
|
*/
|
|
7
8
|
export function handleRunTests(projectRoot: string, args: RunTestsArgs): ToolResult {
|
|
8
|
-
const
|
|
9
|
+
const language = getBackendLanguage(projectRoot);
|
|
10
|
+
const testCommand = args.command || getDefaultTestCommand(language);
|
|
9
11
|
|
|
10
12
|
try {
|
|
11
13
|
const output = execSync(testCommand, { cwd: projectRoot, encoding: "utf8", stdio: "pipe" });
|
|
12
14
|
return {
|
|
13
|
-
content: [{ type: "text", text: `✅ Tests passed successfully!\n\n${output}` }]
|
|
15
|
+
content: [{ type: "text", text: `✅ Tests passed successfully for ${language}!\n\n${output}` }]
|
|
14
16
|
};
|
|
15
17
|
} catch (error: unknown) {
|
|
16
18
|
const err = error as { stderr?: Buffer; stdout?: Buffer };
|
|
@@ -21,7 +23,7 @@ export function handleRunTests(projectRoot: string, args: RunTestsArgs): ToolRes
|
|
|
21
23
|
isError: true,
|
|
22
24
|
content: [{
|
|
23
25
|
type: "text",
|
|
24
|
-
text: `❌ Tests FAILED!\n\n--- STDOUT ---\n${stdout}\n\n--- STDERR ---\n${stderr}`
|
|
26
|
+
text: `❌ Tests FAILED for ${language}!\n\n--- STDOUT ---\n${stdout}\n\n--- STDERR ---\n${stderr}`
|
|
25
27
|
}]
|
|
26
28
|
};
|
|
27
29
|
}
|
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
import { exec } from "child_process";
|
|
2
2
|
import { ToolArgs, ToolResult } from "../types.js";
|
|
3
3
|
import { Metrics } from "../../utils/metrics.js";
|
|
4
|
+
import { getBackendLanguage, getDefaultLintCommand } from "../../utils/cli.js";
|
|
4
5
|
|
|
5
|
-
const LINT_COMMAND = "npm run lint";
|
|
6
6
|
const TIMEOUT = 60000; // 60 seconds
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Handles running the project's linter.
|
|
10
10
|
*/
|
|
11
11
|
export function handleCheckLint(projectRoot: string, _args: ToolArgs): Promise<ToolResult> {
|
|
12
|
+
const language = getBackendLanguage(projectRoot);
|
|
13
|
+
const lintCommand = getDefaultLintCommand(language);
|
|
14
|
+
|
|
12
15
|
return new Promise((resolve) => {
|
|
13
|
-
exec(
|
|
16
|
+
exec(lintCommand, { cwd: projectRoot, timeout: TIMEOUT }, (error, stdout, stderr) => {
|
|
14
17
|
const output = stdout + stderr;
|
|
15
18
|
const tokens = Metrics.estimateTokens(output);
|
|
16
19
|
|
|
17
20
|
if (error) {
|
|
18
|
-
const err = `Linting failed: ${error.message}`;
|
|
21
|
+
const err = `Linting failed for ${language} with command: ${lintCommand}. ${error.message}`;
|
|
19
22
|
Metrics.logError(projectRoot, "@mcp", "check_lint", err);
|
|
20
23
|
resolve({
|
|
21
24
|
isError: true,
|
|
22
|
-
content: [{ type: "text", text: `❌ Lint Errors Found:\n\n${output}` }]
|
|
25
|
+
content: [{ type: "text", text: `❌ Lint Errors Found (${language}):\n\n${output}` }]
|
|
23
26
|
});
|
|
24
27
|
return;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
Metrics.logUsage(projectRoot, "@mcp", "check_lint", tokens);
|
|
28
31
|
resolve({
|
|
29
|
-
content: [{ type: "text", text: `✅ Lint check passed successfully:\n\n${output}` }]
|
|
32
|
+
content: [{ type: "text", text: `✅ Lint check passed successfully for ${language}:\n\n${output}` }]
|
|
30
33
|
});
|
|
31
34
|
});
|
|
32
35
|
});
|
|
@@ -5,10 +5,20 @@ import { Metrics } from "../../utils/metrics.js";
|
|
|
5
5
|
const COMMAND_ALLOW_LIST = [
|
|
6
6
|
"npm test",
|
|
7
7
|
"npm run lint",
|
|
8
|
+
"npm run build",
|
|
8
9
|
"git status",
|
|
9
10
|
"git diff",
|
|
10
|
-
"npx vitest run",
|
|
11
|
-
"
|
|
11
|
+
"npx vitest run",
|
|
12
|
+
"go test",
|
|
13
|
+
"go fmt",
|
|
14
|
+
"go build",
|
|
15
|
+
"pytest",
|
|
16
|
+
"ruff check",
|
|
17
|
+
"dotnet test",
|
|
18
|
+
"dotnet format",
|
|
19
|
+
"dotnet build",
|
|
20
|
+
"./gradlew",
|
|
21
|
+
"mvn",
|
|
12
22
|
];
|
|
13
23
|
|
|
14
24
|
const TIMEOUT = 30000; // 30 seconds
|
|
@@ -1,20 +1,52 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
1
3
|
import { execFileSync } from "child_process";
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
|
-
* Executes a
|
|
5
|
-
* Captures stderr gracefully to prevent stream crashes.
|
|
6
|
+
* Executes a command safely and returns the output.
|
|
6
7
|
*/
|
|
7
|
-
export function safeExec(
|
|
8
|
+
export function safeExec(cmd: string, args: string[], cwd: string, timeout = 30000): string {
|
|
8
9
|
try {
|
|
9
|
-
return execFileSync(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
timeout: timeout || 30000,
|
|
13
|
-
maxBuffer: 1024 * 1024,
|
|
14
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
15
|
-
});
|
|
16
|
-
} catch (error: unknown) {
|
|
17
|
-
const err = error as { stderr?: string; message?: string };
|
|
18
|
-
throw new Error(err.stderr || err.message || "Command execution failed", { cause: error });
|
|
10
|
+
return execFileSync(cmd, args, { cwd, timeout, encoding: "utf8", stdio: "pipe" });
|
|
11
|
+
} catch (err: any) {
|
|
12
|
+
return err.stdout?.toString() || err.stderr?.toString() || err.message;
|
|
19
13
|
}
|
|
20
14
|
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Detects the backend language from the framework configuration.
|
|
18
|
+
*/
|
|
19
|
+
export function getBackendLanguage(projectRoot: string): string {
|
|
20
|
+
try {
|
|
21
|
+
const configPath = path.join(projectRoot, ".atabey", "config.json");
|
|
22
|
+
if (fs.existsSync(configPath)) {
|
|
23
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
24
|
+
return config.backendLanguage || "Node.js (TypeScript)";
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
// Fallback to default
|
|
28
|
+
}
|
|
29
|
+
return "Node.js (TypeScript)";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns the default lint command for the given language.
|
|
34
|
+
*/
|
|
35
|
+
export function getDefaultLintCommand(language: string): string {
|
|
36
|
+
if (language.includes("Go")) return "go fmt ./...";
|
|
37
|
+
if (language.includes("Java")) return "./gradlew check"; // or mvn check
|
|
38
|
+
if (language.includes("Python")) return "ruff check .";
|
|
39
|
+
if (language.includes(".NET")) return "dotnet format";
|
|
40
|
+
return "npm run lint";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Returns the default test command for the given language.
|
|
45
|
+
*/
|
|
46
|
+
export function getDefaultTestCommand(language: string): string {
|
|
47
|
+
if (language.includes("Go")) return "go test ./...";
|
|
48
|
+
if (language.includes("Java")) return "./gradlew test"; // or mvn test
|
|
49
|
+
if (language.includes("Python")) return "pytest";
|
|
50
|
+
if (language.includes(".NET")) return "dotnet test";
|
|
51
|
+
return "npm test";
|
|
52
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atabey",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "The Supreme AI Governance & Autonomous Orchestration Framework for Enterprise Development.
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "The Supreme AI Governance & Autonomous Orchestration Framework for Enterprise Development. Supports Polyglot Backends (Go, Java, Python, .NET, Node.js) and Multi-Language Communication (TR/EN).",
|
|
5
5
|
"author": "Yusuf BEKAR",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"readme": "README.md",
|
package/src/cli/adapters/core.ts
CHANGED
|
@@ -27,20 +27,44 @@ export const FRAMEWORK_DIR_CANDIDATES = [
|
|
|
27
27
|
export function buildMcpServerEntry(projectRoot: string) {
|
|
28
28
|
const packageRoot = getPackageRoot();
|
|
29
29
|
|
|
30
|
-
// Check
|
|
31
|
-
|
|
32
|
-
if (!fs.existsSync(mcpServerPath)) {
|
|
33
|
-
mcpServerPath = path.join(packageRoot, "../@atabey/mcp/dist/index.js");
|
|
34
|
-
}
|
|
35
|
-
if (!fs.existsSync(mcpServerPath)) {
|
|
36
|
-
mcpServerPath = path.join(projectRoot, "node_modules/@atabey/mcp/dist/index.js");
|
|
37
|
-
}
|
|
30
|
+
// Check if we are running in the framework local development repository itself
|
|
31
|
+
const isLocalFrameworkDev = path.resolve(packageRoot) === path.resolve(projectRoot);
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
console.warn("⚠️ MCP Server not found. Did you run 'npm run build' inside @atabey/mcp?");
|
|
41
|
-
}
|
|
33
|
+
let relativePath = "";
|
|
42
34
|
|
|
43
|
-
|
|
35
|
+
if (isLocalFrameworkDev) {
|
|
36
|
+
// In local framework dev, always use the build path directly relative to project root
|
|
37
|
+
let mcpServerPath = path.join(packageRoot, "framework-mcp/dist/index.js");
|
|
38
|
+
if (!fs.existsSync(mcpServerPath)) {
|
|
39
|
+
mcpServerPath = path.join(packageRoot, "../@atabey/mcp/dist/index.js");
|
|
40
|
+
}
|
|
41
|
+
if (!fs.existsSync(mcpServerPath)) {
|
|
42
|
+
mcpServerPath = path.join(projectRoot, "node_modules/@atabey/mcp/dist/index.js");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!fs.existsSync(mcpServerPath)) {
|
|
46
|
+
console.warn("⚠️ MCP Server not found. Did you run 'npm run build' inside @atabey/mcp?");
|
|
47
|
+
}
|
|
48
|
+
relativePath = path.relative(projectRoot, mcpServerPath) || mcpServerPath;
|
|
49
|
+
} else {
|
|
50
|
+
// If we are initializing in a user's project:
|
|
51
|
+
// We want to target the local node_modules of the user's project.
|
|
52
|
+
// Even if node_modules is not populated yet (e.g. running via npx before npm install),
|
|
53
|
+
// we should write the local node_modules path so that it will work once installed.
|
|
54
|
+
|
|
55
|
+
const localAtabeyPath = path.join(projectRoot, "node_modules/atabey/framework-mcp/dist/index.js");
|
|
56
|
+
const localScopedPath = path.join(projectRoot, "node_modules/@atabey/mcp/dist/index.js");
|
|
57
|
+
|
|
58
|
+
if (fs.existsSync(localScopedPath)) {
|
|
59
|
+
relativePath = path.relative(projectRoot, localScopedPath);
|
|
60
|
+
} else if (fs.existsSync(localAtabeyPath)) {
|
|
61
|
+
relativePath = path.relative(projectRoot, localAtabeyPath);
|
|
62
|
+
} else {
|
|
63
|
+
// Default to the standard relative local path in node_modules/atabey
|
|
64
|
+
// This is clean and portable across machines/developers.
|
|
65
|
+
relativePath = "node_modules/atabey/framework-mcp/dist/index.js";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
44
68
|
|
|
45
69
|
return {
|
|
46
70
|
command: "node",
|
|
@@ -21,7 +21,9 @@ export function scaffoldAgents(
|
|
|
21
21
|
agentsToScaffold?: string[],
|
|
22
22
|
explicitDestDir?: string,
|
|
23
23
|
explicitExt?: string,
|
|
24
|
-
paths?: Record<string, string
|
|
24
|
+
paths?: Record<string, string>,
|
|
25
|
+
backendLanguage?: string,
|
|
26
|
+
language?: string
|
|
25
27
|
): void {
|
|
26
28
|
const adapter = ADAPTERS[adapterId];
|
|
27
29
|
if (!adapter) return;
|
|
@@ -47,27 +49,27 @@ export function scaffoldAgents(
|
|
|
47
49
|
|
|
48
50
|
switch (adapterId) {
|
|
49
51
|
case "gemini":
|
|
50
|
-
content = toGeminiCliMd(agent, baseKnowledgeDir, paths);
|
|
52
|
+
content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
51
53
|
break;
|
|
52
54
|
case "grok":
|
|
53
55
|
// Grok uses same Gemini-compatible YAML format
|
|
54
|
-
content = toGeminiCliMd(agent, baseKnowledgeDir, paths);
|
|
56
|
+
content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
55
57
|
break;
|
|
56
58
|
case "claude":
|
|
57
|
-
content = toClaudeCodeMd(agent, baseKnowledgeDir, paths);
|
|
59
|
+
content = toClaudeCodeMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
58
60
|
break;
|
|
59
61
|
case "cursor":
|
|
60
|
-
content = toCursorMdc(agent, baseKnowledgeDir, paths);
|
|
62
|
+
content = toCursorMdc(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
61
63
|
break;
|
|
62
64
|
case "codex":
|
|
63
|
-
content = toCodexMd(agent, baseKnowledgeDir, paths);
|
|
65
|
+
content = toCodexMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
64
66
|
break;
|
|
65
67
|
case "antigravity-cli": {
|
|
66
68
|
// Antigravity uses nested folders: agents/{name}/agent.json and agents/{name}/agent.md
|
|
67
69
|
const agentDir = path.join(destAgentsDir, agent.name);
|
|
68
70
|
if (!dryRun) fs.mkdirSync(agentDir, { recursive: true });
|
|
69
71
|
|
|
70
|
-
content = toAntigravityJson(agent, baseKnowledgeDir, paths);
|
|
72
|
+
content = toAntigravityJson(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
71
73
|
fileName = path.join(agent.name, "agent.json");
|
|
72
74
|
|
|
73
75
|
secondaryContent = `# 🎖️ Agent Atabey — @${agent.name}\n\n${agent.instructions.identity}\n\n${agent.instructions.mission}`;
|
|
@@ -76,7 +78,7 @@ export function scaffoldAgents(
|
|
|
76
78
|
}
|
|
77
79
|
default:
|
|
78
80
|
// Fallback to Gemini format
|
|
79
|
-
content = toGeminiCliMd(agent, baseKnowledgeDir, paths);
|
|
81
|
+
content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
|
|
80
82
|
break;
|
|
81
83
|
}
|
|
82
84
|
|
|
@@ -11,6 +11,8 @@ import { writeJsonFile, writeTextFile } from "../../utils/fs.js";
|
|
|
11
11
|
import { getPackageRoot, getPackageVersion } from "../../utils/pkg.js";
|
|
12
12
|
import { ALL_AGENTS } from "../../../modules/agents/definitions.js";
|
|
13
13
|
|
|
14
|
+
import { TRANSLATIONS, type SupportedLanguage } from "../../utils/i18n.js";
|
|
15
|
+
|
|
14
16
|
const FRAMEWORK_NAME = "Agent Atabey";
|
|
15
17
|
|
|
16
18
|
const COLOR_PALETTES = {
|
|
@@ -19,9 +21,10 @@ const COLOR_PALETTES = {
|
|
|
19
21
|
"Deep Purple": { primary: "#8b5cf6", secondary: "#d8b4fe", accent: "#f59e0b" }
|
|
20
22
|
};
|
|
21
23
|
|
|
22
|
-
export function scaffoldConstitution(targetDir: string, frameworkDir: string, adapterId: AdapterId, dryRun: boolean) {
|
|
24
|
+
export function scaffoldConstitution(targetDir: string, frameworkDir: string, adapterId: AdapterId, dryRun: boolean, language: SupportedLanguage = "tr") {
|
|
23
25
|
if (dryRun) return;
|
|
24
|
-
|
|
26
|
+
const t = TRANSLATIONS[language];
|
|
27
|
+
let content = `# 🎖️ ${t.constitution_title}\n\nDiscipline and Order.`;
|
|
25
28
|
let readSuccess = false;
|
|
26
29
|
try {
|
|
27
30
|
const templatePath = path.join(getPackageRoot(), "ATABEY.md");
|
|
@@ -45,17 +48,21 @@ export function scaffoldFrameworkConfigs(
|
|
|
45
48
|
adapter: AdapterConfig,
|
|
46
49
|
dryRun: boolean,
|
|
47
50
|
selectedPalette: string,
|
|
48
|
-
options?: { unified?: boolean; adapters?: string[] }
|
|
51
|
+
options?: { unified?: boolean; adapters?: string[]; backendLanguage?: string; language?: SupportedLanguage }
|
|
49
52
|
) {
|
|
50
53
|
if (dryRun) return;
|
|
51
54
|
const frameworkDir = path.join(targetDir, fDir);
|
|
52
55
|
const palette = COLOR_PALETTES[selectedPalette as keyof typeof COLOR_PALETTES] || COLOR_PALETTES["Modern Blue"];
|
|
56
|
+
const language = options?.language || "tr";
|
|
57
|
+
const t = TRANSLATIONS[language];
|
|
53
58
|
|
|
54
59
|
const config = {
|
|
55
60
|
name: FRAMEWORK_NAME,
|
|
56
61
|
version: getPackageVersion(),
|
|
57
62
|
unified: options?.unified || false,
|
|
58
63
|
adapters: options?.adapters || [adapter.id],
|
|
64
|
+
backendLanguage: options?.backendLanguage || "Node.js (TypeScript)",
|
|
65
|
+
language: language,
|
|
59
66
|
theme: {
|
|
60
67
|
palette: selectedPalette,
|
|
61
68
|
colors: palette
|
|
@@ -71,12 +78,13 @@ export function scaffoldFrameworkConfigs(
|
|
|
71
78
|
writeJsonFile(sharedFactsPath, {
|
|
72
79
|
project: FRAMEWORK_NAME,
|
|
73
80
|
initializedAt: new Date().toISOString(),
|
|
74
|
-
stack: [],
|
|
81
|
+
stack: [options?.backendLanguage || "Node.js (TypeScript)"],
|
|
82
|
+
language: language,
|
|
75
83
|
policies: []
|
|
76
84
|
}, dryRun);
|
|
77
85
|
}
|
|
78
86
|
|
|
79
|
-
let statusContent =
|
|
87
|
+
let statusContent = `# 🎖️ ${t.status_title}\n\n| Agent | State | Active Task | Last Updated | Notes | Extra | Backup |\n|---|---|---|---|---|---|---|\n`;
|
|
80
88
|
|
|
81
89
|
const activeAgents = ALL_AGENTS;
|
|
82
90
|
|
|
@@ -84,7 +92,7 @@ export function scaffoldFrameworkConfigs(
|
|
|
84
92
|
const now = new Date().toISOString();
|
|
85
93
|
|
|
86
94
|
for (const ag of activeAgents) {
|
|
87
|
-
statusContent += "| @" + ag.name + " |
|
|
95
|
+
statusContent += "| @" + ag.name + " | " + t.agent_ready + " | Idle | - | - | - | - |\n";
|
|
88
96
|
initialStatusJson[ag.name] = { state: "READY", task: "Idle", lastUpdated: now };
|
|
89
97
|
}
|
|
90
98
|
writeTextFile(path.join(frameworkDir, "STATUS.md"), statusContent);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { writeTextFile } from "../../utils/fs.js";
|
|
4
|
+
import { getPackageRoot } from "../../utils/pkg.js";
|
|
5
|
+
import { logger } from "../../../shared/logger.js";
|
|
6
|
+
|
|
7
|
+
export function scaffoldProjectDocs(projectRoot: string, options: { backendLanguage: string }, dryRun: boolean) {
|
|
8
|
+
if (dryRun) return;
|
|
9
|
+
|
|
10
|
+
const docsDir = path.join(projectRoot, "docs");
|
|
11
|
+
if (!fs.existsSync(docsDir)) fs.mkdirSync(docsDir, { recursive: true });
|
|
12
|
+
|
|
13
|
+
// Scaffold tech-stack.md with dynamic content
|
|
14
|
+
const techStackPath = path.join(docsDir, "tech-stack.md");
|
|
15
|
+
let techStackContent = "";
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const templatePath = path.join(getPackageRoot(), "docs/tech-stack.md");
|
|
19
|
+
if (fs.existsSync(templatePath)) {
|
|
20
|
+
techStackContent = fs.readFileSync(templatePath, "utf8");
|
|
21
|
+
|
|
22
|
+
// Replace the backend language in the template
|
|
23
|
+
// Assuming the template has a row like: | **Backend Altyapısı** | Node.js v20+ & TypeScript v5+ | ... |
|
|
24
|
+
// We'll use a more generic replacement or just append/update the specific section.
|
|
25
|
+
const lang = options.backendLanguage;
|
|
26
|
+
|
|
27
|
+
// If it's a new project, we can just rewrite the table or use a placeholder in the template.
|
|
28
|
+
// For now, let's assume we want to update the "Backend" or "Geliştirme Ortamı" row.
|
|
29
|
+
techStackContent = techStackContent.replace(
|
|
30
|
+
/\| \*\*Geliştirme Ortamı\*\* \| .* \|/,
|
|
31
|
+
`| **Geliştirme Ortamı** | ${lang} |`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
} catch (e) {
|
|
35
|
+
logger.debug("Failed to read tech-stack.md template", e);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!techStackContent) {
|
|
39
|
+
techStackContent = `# 🛠️ Project Tech Stack\n\n- **Backend Language:** ${options.backendLanguage}\n`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
writeTextFile(techStackPath, techStackContent);
|
|
43
|
+
console.warn(`✅ Project documentation updated: docs/tech-stack.md (Language: ${options.backendLanguage})`);
|
|
44
|
+
}
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -26,6 +26,9 @@ import {
|
|
|
26
26
|
scaffoldStandards
|
|
27
27
|
} from "./init/scaffold-standards.js";
|
|
28
28
|
import { scaffoldOps } from "./init/scaffold-ops.js";
|
|
29
|
+
import { scaffoldProjectDocs } from "./init/scaffold-docs.js";
|
|
30
|
+
|
|
31
|
+
import { TRANSLATIONS, type SupportedLanguage } from "../utils/i18n.js";
|
|
29
32
|
|
|
30
33
|
const FRAMEWORK_NAME = "Agent Atabey";
|
|
31
34
|
|
|
@@ -41,29 +44,43 @@ const FRAMEWORK_SUBDIRS = [
|
|
|
41
44
|
"rules",
|
|
42
45
|
];
|
|
43
46
|
|
|
44
|
-
async function runInteractiveInit(): Promise<{ selectedDirs: string[], selectedAgents: string[], selectedPalette: string }> {
|
|
47
|
+
async function runInteractiveInit(): Promise<{ selectedDirs: string[], selectedAgents: string[], selectedPalette: string, backendLanguage: string, language: SupportedLanguage }> {
|
|
45
48
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
46
49
|
const question = (query: string): Promise<string> => new Promise((resolve) => rl.question(query, resolve));
|
|
47
50
|
|
|
48
51
|
try {
|
|
49
|
-
console.warn(
|
|
50
|
-
console.warn("
|
|
52
|
+
console.warn("\n🌐 Select Framework Language / Dil Seçimi:");
|
|
53
|
+
console.warn("1. Türkçe");
|
|
54
|
+
console.warn("2. English");
|
|
55
|
+
const langInput = await question("\nSelect (1-2) or Enter for 'tr': ");
|
|
56
|
+
const language: SupportedLanguage = langInput.trim() === "2" ? "en" : "tr";
|
|
57
|
+
const t = TRANSLATIONS[language];
|
|
58
|
+
|
|
59
|
+
console.warn(`\n🚀 ${t.welcome}`);
|
|
60
|
+
|
|
61
|
+
console.warn(`\n${t.select_backend}:`);
|
|
62
|
+
const languages = ["Node.js (TypeScript)", "Go", "Java (Spring Boot)", "Python (FastAPI)", ".NET"];
|
|
63
|
+
languages.forEach((l, i) => console.warn(`${i + 1}. ${l}`));
|
|
64
|
+
const bLangInput = await question(`\nSelect (1-5) or Enter for 'Node.js': `);
|
|
65
|
+
const backendLanguage = languages[parseInt(bLangInput.trim()) - 1] || "Node.js (TypeScript)";
|
|
66
|
+
|
|
67
|
+
console.warn(`\nAvailable Framework Directories:`);
|
|
51
68
|
FRAMEWORK_SUBDIRS.forEach((d, i) => console.warn(`${i + 1}. ${d}`));
|
|
52
|
-
const dirInput = await question(
|
|
69
|
+
const dirInput = await question(`\n${t.select_dirs} `);
|
|
53
70
|
const selectedDirs = dirInput ? dirInput.split(",").map(n => FRAMEWORK_SUBDIRS[parseInt(n.trim()) - 1]).filter(Boolean) : [...FRAMEWORK_SUBDIRS];
|
|
54
71
|
|
|
55
|
-
console.warn(
|
|
72
|
+
console.warn(`\nAvailable Core Agents:`);
|
|
56
73
|
ALL_AGENTS.forEach((a, i) => console.warn(`${i + 1}. ${a.name}`));
|
|
57
|
-
const agentInput = await question(
|
|
74
|
+
const agentInput = await question(`\n${t.select_agents} `);
|
|
58
75
|
const selectedAgents = agentInput ? agentInput.split(",").map(n => ALL_AGENTS[parseInt(n.trim()) - 1].name).filter(Boolean) : ALL_AGENTS.map(a => a.name);
|
|
59
76
|
|
|
60
|
-
console.warn(
|
|
77
|
+
console.warn(`\nAvailable Color Palettes:`);
|
|
61
78
|
const palettes = ["Modern Blue", "Enterprise Slate", "Deep Purple"];
|
|
62
79
|
palettes.forEach((p, i) => console.warn(`${i + 1}. ${p}`));
|
|
63
|
-
const palInput = await question(
|
|
80
|
+
const palInput = await question(`\n${t.select_palette} `);
|
|
64
81
|
const selectedPalette = palettes[parseInt(palInput.trim()) - 1] || "Modern Blue";
|
|
65
82
|
|
|
66
|
-
return { selectedDirs, selectedAgents, selectedPalette };
|
|
83
|
+
return { selectedDirs, selectedAgents, selectedPalette, backendLanguage, language };
|
|
67
84
|
} finally { rl.close(); }
|
|
68
85
|
}
|
|
69
86
|
|
|
@@ -91,19 +108,27 @@ export async function initCommand(adapterName: string, options: { unified?: bool
|
|
|
91
108
|
let selectedDirs: string[];
|
|
92
109
|
let selectedAgents: string[];
|
|
93
110
|
let selectedPalette: string;
|
|
111
|
+
let backendLanguage: string;
|
|
112
|
+
let language: SupportedLanguage;
|
|
94
113
|
|
|
95
114
|
if (forceYes) {
|
|
96
115
|
selectedDirs = ["knowledge", "prompts", "memory", "router", "registry", "observability", "rules"];
|
|
97
116
|
selectedAgents = ALL_AGENTS.map(a => a.name);
|
|
98
117
|
selectedPalette = "Modern Blue";
|
|
99
|
-
|
|
118
|
+
backendLanguage = "Node.js (TypeScript)";
|
|
119
|
+
language = "tr";
|
|
120
|
+
UI.success(`Non-interactive mode: Using default configurations (Language: tr, Backend: Node.js).`);
|
|
100
121
|
} else {
|
|
101
122
|
const result = await runInteractiveInit();
|
|
102
123
|
selectedDirs = result.selectedDirs.filter(d => d !== "agents" && d !== "skills");
|
|
103
124
|
selectedAgents = result.selectedAgents;
|
|
104
125
|
selectedPalette = result.selectedPalette;
|
|
126
|
+
backendLanguage = result.backendLanguage;
|
|
127
|
+
language = result.language;
|
|
105
128
|
}
|
|
106
129
|
|
|
130
|
+
const t = TRANSLATIONS[language];
|
|
131
|
+
|
|
107
132
|
ensureDir(path.join(projectRoot, coreDir), dryRun);
|
|
108
133
|
selectedDirs.forEach(dir => {
|
|
109
134
|
ensureDir(path.join(projectRoot, coreDir, dir), dryRun);
|
|
@@ -114,10 +139,12 @@ export async function initCommand(adapterName: string, options: { unified?: bool
|
|
|
114
139
|
adapter.nestedDirs.forEach(dir => ensureDir(path.join(projectRoot, aiToolDir, dir), dryRun));
|
|
115
140
|
}
|
|
116
141
|
|
|
117
|
-
scaffoldConstitution(projectRoot, coreDir, adapterId, dryRun);
|
|
142
|
+
scaffoldConstitution(projectRoot, coreDir, adapterId, dryRun, language);
|
|
118
143
|
scaffoldFrameworkConfigs(projectRoot, coreDir, adapter, dryRun, selectedPalette, {
|
|
119
144
|
unified: isUnified,
|
|
120
|
-
adapters: isUnified ? [...ADAPTER_IDS] : [adapterId]
|
|
145
|
+
adapters: isUnified ? [...ADAPTER_IDS] : [adapterId],
|
|
146
|
+
backendLanguage,
|
|
147
|
+
language
|
|
121
148
|
});
|
|
122
149
|
|
|
123
150
|
scaffoldStandards(path.join(projectRoot, coreDir), dryRun);
|
|
@@ -127,21 +154,23 @@ export async function initCommand(adapterName: string, options: { unified?: bool
|
|
|
127
154
|
if (isUnified) {
|
|
128
155
|
// Scaffold ALL agents for ALL adapters under unified hub
|
|
129
156
|
for (const id of ADAPTER_IDS) {
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
157
|
+
const adapterId = id as AdapterId;
|
|
158
|
+
const dest = resolveAgentsDir(adapterId, true, aiToolDir);
|
|
159
|
+
scaffoldAgents(projectRoot, adapterId, dryRun, selectedAgents, dest.agentsDir, dest.agentsExt, pathsMap, backendLanguage, language);
|
|
160
|
+
if (!dryRun) mirrorUnifiedAgentsToNative(projectRoot, adapterId);
|
|
133
161
|
}
|
|
134
162
|
UI.success(`✅ Scaffolding complete for all adapters under ${aiToolDir}/ with native mirrors.`);
|
|
135
163
|
} else {
|
|
136
164
|
// Standard single-adapter scaffold
|
|
137
165
|
const dest = resolveAgentsDir(adapterId, false);
|
|
138
|
-
scaffoldAgents(projectRoot, adapterId, dryRun, selectedAgents, dest.agentsDir, dest.agentsExt, pathsMap);
|
|
166
|
+
scaffoldAgents(projectRoot, adapterId, dryRun, selectedAgents, dest.agentsDir, dest.agentsExt, pathsMap, backendLanguage, language);
|
|
139
167
|
UI.success(`✅ Generated agent definitions under ${dest.agentsDir}/`);
|
|
140
168
|
}
|
|
141
169
|
|
|
142
170
|
const skillsBaseDir = path.join(projectRoot, aiToolDir, "skills");
|
|
143
171
|
scaffoldSkills(skillsBaseDir, dryRun);
|
|
144
172
|
scaffoldOps(path.join(projectRoot, coreDir), dryRun);
|
|
173
|
+
scaffoldProjectDocs(projectRoot, { backendLanguage }, dryRun);
|
|
145
174
|
scaffoldShims(projectRoot, coreDir, adapterId, adapter, dryRun, isUnified);
|
|
146
175
|
|
|
147
176
|
// Initialize runtime directories
|
|
@@ -154,10 +183,11 @@ export async function initCommand(adapterName: string, options: { unified?: bool
|
|
|
154
183
|
initializeMemory(path.join(projectRoot, coreDir), dryRun);
|
|
155
184
|
runAdapterPostInit(adapter, projectRoot);
|
|
156
185
|
|
|
157
|
-
UI.success(`\n🚀 ${FRAMEWORK_NAME} (v${getPackageVersion()})
|
|
186
|
+
UI.success(`\n🚀 ${FRAMEWORK_NAME} (v${getPackageVersion()}) ${t.init_success}`);
|
|
158
187
|
console.warn(`\n- Brain & Memory Hub (Protected): ${coreDir}/`);
|
|
159
188
|
console.warn(`- AI Agent Commands (Active): ${aiToolDir}/`);
|
|
160
|
-
console.warn(
|
|
189
|
+
console.warn(`\n${t.next_steps}`);
|
|
161
190
|
console.warn(" 1. Run 'atabey status' to verify the environment.");
|
|
162
191
|
console.warn(` 2. Open ${adapterId === "claude" ? "Claude Desktop" : "your AI Assistant"} and start commanding the Army.`);
|
|
163
192
|
}
|
|
193
|
+
|