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.
Files changed (56) hide show
  1. package/README.md +6 -3
  2. package/dist/framework-mcp/src/tools/definitions.js +1 -1
  3. package/dist/framework-mcp/src/tools/definitions.js.map +1 -1
  4. package/dist/framework-mcp/src/tools/framework/run_tests.js +5 -3
  5. package/dist/framework-mcp/src/tools/framework/run_tests.js.map +1 -1
  6. package/dist/framework-mcp/src/tools/quality/check_lint.js +7 -5
  7. package/dist/framework-mcp/src/tools/quality/check_lint.js.map +1 -1
  8. package/dist/framework-mcp/src/tools/shell/run_command.js +12 -2
  9. package/dist/framework-mcp/src/tools/shell/run_command.js.map +1 -1
  10. package/dist/framework-mcp/src/utils/cli.d.ts +14 -3
  11. package/dist/framework-mcp/src/utils/cli.js +51 -13
  12. package/dist/framework-mcp/src/utils/cli.js.map +1 -1
  13. package/dist/src/cli/adapters/core.js +34 -10
  14. package/dist/src/cli/adapters/core.js.map +1 -1
  15. package/dist/src/cli/adapters/scaffold.d.ts +1 -1
  16. package/dist/src/cli/adapters/scaffold.js +8 -8
  17. package/dist/src/cli/adapters/scaffold.js.map +1 -1
  18. package/dist/src/cli/commands/init/scaffold-core.d.ts +4 -1
  19. package/dist/src/cli/commands/init/scaffold-core.js +12 -5
  20. package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
  21. package/dist/src/cli/commands/init/scaffold-docs.d.ts +3 -0
  22. package/dist/src/cli/commands/init/scaffold-docs.js +37 -0
  23. package/dist/src/cli/commands/init/scaffold-docs.js.map +1 -0
  24. package/dist/src/cli/commands/init.js +41 -17
  25. package/dist/src/cli/commands/init.js.map +1 -1
  26. package/dist/src/cli/utils/i18n.d.ts +15 -0
  27. package/dist/src/cli/utils/i18n.js +29 -0
  28. package/dist/src/cli/utils/i18n.js.map +1 -0
  29. package/dist/src/modules/agents/definitions.d.ts +6 -6
  30. package/dist/src/modules/agents/definitions.js +30 -26
  31. package/dist/src/modules/agents/definitions.js.map +1 -1
  32. package/dist/src/modules/agents/registry/backend.js +5 -6
  33. package/dist/src/modules/agents/registry/backend.js.map +1 -1
  34. package/dist/src/modules/agents/registry/database.js +2 -2
  35. package/dist/src/modules/agents/registry/database.js.map +1 -1
  36. package/framework-mcp/dist/tools/definitions.js +1 -1
  37. package/framework-mcp/dist/tools/framework/run_tests.js +5 -3
  38. package/framework-mcp/dist/tools/quality/check_lint.js +7 -5
  39. package/framework-mcp/dist/tools/shell/run_command.js +12 -2
  40. package/framework-mcp/dist/utils/cli.js +51 -13
  41. package/framework-mcp/package.json +1 -1
  42. package/framework-mcp/src/tools/definitions.ts +1 -1
  43. package/framework-mcp/src/tools/framework/run_tests.ts +5 -3
  44. package/framework-mcp/src/tools/quality/check_lint.ts +8 -5
  45. package/framework-mcp/src/tools/shell/run_command.ts +12 -2
  46. package/framework-mcp/src/utils/cli.ts +45 -13
  47. package/package.json +2 -2
  48. package/src/cli/adapters/core.ts +36 -12
  49. package/src/cli/adapters/scaffold.ts +10 -8
  50. package/src/cli/commands/init/scaffold-core.ts +14 -6
  51. package/src/cli/commands/init/scaffold-docs.ts +44 -0
  52. package/src/cli/commands/init.ts +48 -18
  53. package/src/cli/utils/i18n.ts +44 -0
  54. package/src/modules/agents/definitions.ts +32 -26
  55. package/src/modules/agents/registry/backend.ts +5 -6
  56. 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 CLI command safely using execFileSync (no shell injection risk).
4
- * Captures stderr gracefully to prevent stream crashes.
5
+ * Executes a command safely and returns the output.
5
6
  */
6
- export function safeExec(command, args, cwd, timeout) {
7
+ export function safeExec(cmd, args, cwd, timeout = 30000) {
7
8
  try {
8
- return execFileSync(command, args, {
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 (error) {
17
- const err = error;
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
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atabey/mcp",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "description": "Agent Atabey Model Context Protocol (MCP) Server",
5
5
  "author": "Yusuf BEKAR",
6
6
  "license": "MIT",
@@ -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: 'npm test')" }
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 testCommand = args.command || "npm test";
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(LINT_COMMAND, { cwd: projectRoot, timeout: TIMEOUT }, (error, stdout, stderr) => {
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", // From the audit, this is the test command
11
- "npm run build", // From the audit
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 CLI command safely using execFileSync (no shell injection risk).
5
- * Captures stderr gracefully to prevent stream crashes.
6
+ * Executes a command safely and returns the output.
6
7
  */
7
- export function safeExec(command: string, args: string[], cwd: string, timeout?: number): string {
8
+ export function safeExec(cmd: string, args: string[], cwd: string, timeout = 30000): string {
8
9
  try {
9
- return execFileSync(command, args, {
10
- cwd,
11
- encoding: "utf8",
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.2",
4
- "description": "The Supreme AI Governance & Autonomous Orchestration Framework for Enterprise Development. Acts as a Corporate AI Management Assistant.",
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",
@@ -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 both local development workspace path and installed node_modules path
31
- let mcpServerPath = path.join(packageRoot, "framework-mcp/dist/index.js");
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
- if (!fs.existsSync(mcpServerPath)) {
40
- console.warn("⚠️ MCP Server not found. Did you run 'npm run build' inside @atabey/mcp?");
41
- }
33
+ let relativePath = "";
42
34
 
43
- const relativePath = path.relative(projectRoot, mcpServerPath) || mcpServerPath;
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
- let content = `# 🎖️ ${FRAMEWORK_NAME} — Constitution\n\nDiscipline and Order.`;
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 = "# 🎖️ Status\n\n| Agent | State | Active Task | Last Updated | Notes | Extra | Backup |\n|---|---|---|---|---|---|---|\n";
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 + " | READY | Idle | - | - | - | - |\n";
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
+ }
@@ -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(`\n🚀 Welcome to ${FRAMEWORK_NAME} Interactive Setup!`);
50
- console.warn("\nAvailable Framework Directories:");
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("\nEnter directory numbers to include (e.g. 1,2,3) or Enter for ALL: ");
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("\nAvailable Core Agents:");
72
+ console.warn(`\nAvailable Core Agents:`);
56
73
  ALL_AGENTS.forEach((a, i) => console.warn(`${i + 1}. ${a.name}`));
57
- const agentInput = await question("\nEnter agent numbers to include (e.g. 1,2) or Enter for ALL: ");
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("\nAvailable Color Palettes:");
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("\nSelect palette (1-3) or Enter for 'Modern Blue': ");
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
- UI.success(`Non-interactive mode: Using default configurations.`);
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 dest = resolveAgentsDir(id, true, aiToolDir);
131
- scaffoldAgents(projectRoot, id, dryRun, selectedAgents, dest.agentsDir, dest.agentsExt, pathsMap);
132
- if (!dryRun) mirrorUnifiedAgentsToNative(projectRoot, id);
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()}) initialized successfully!`);
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("\nNext Steps:");
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
+