atabey 0.0.13 → 0.0.15

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 (282) hide show
  1. package/ATABEY.md +1 -1
  2. package/PRIVACY.md +8 -14
  3. package/README.md +405 -56
  4. package/bin/cli.js +72 -5
  5. package/dist/framework-mcp/src/index.js +988 -63
  6. package/dist/framework-mcp/src/index.js.map +1 -1
  7. package/dist/framework-mcp/src/tools/compliance/mask_pii.d.ts +17 -0
  8. package/dist/framework-mcp/src/tools/compliance/mask_pii.js +56 -0
  9. package/dist/framework-mcp/src/tools/compliance/mask_pii.js.map +1 -0
  10. package/dist/framework-mcp/src/tools/definitions.js +10 -9
  11. package/dist/framework-mcp/src/tools/definitions.js.map +1 -1
  12. package/dist/framework-mcp/src/tools/framework/run_tests.js +25 -0
  13. package/dist/framework-mcp/src/tools/framework/run_tests.js.map +1 -1
  14. package/dist/framework-mcp/src/tools/index.js +7 -8
  15. package/dist/framework-mcp/src/tools/index.js.map +1 -1
  16. package/dist/framework-mcp/src/tools/messaging/approve_operation.d.ts +22 -0
  17. package/dist/framework-mcp/src/tools/messaging/approve_operation.js +81 -0
  18. package/dist/framework-mcp/src/tools/messaging/approve_operation.js.map +1 -0
  19. package/dist/framework-mcp/src/tools/messaging/ask_human.d.ts +15 -0
  20. package/dist/framework-mcp/src/tools/messaging/ask_human.js +89 -20
  21. package/dist/framework-mcp/src/tools/messaging/ask_human.js.map +1 -1
  22. package/dist/framework-mcp/src/tools/observability/check_ports.d.ts +1 -0
  23. package/dist/framework-mcp/src/tools/observability/check_ports.js +24 -8
  24. package/dist/framework-mcp/src/tools/observability/check_ports.js.map +1 -1
  25. package/dist/framework-mcp/src/tools/quality/analyze_code_quality.js +13 -64
  26. package/dist/framework-mcp/src/tools/quality/analyze_code_quality.js.map +1 -1
  27. package/dist/framework-mcp/src/tools/schemas.d.ts +48 -53
  28. package/dist/framework-mcp/src/tools/schemas.js +18 -22
  29. package/dist/framework-mcp/src/tools/schemas.js.map +1 -1
  30. package/dist/framework-mcp/src/tools/shell/run_command.js +146 -90
  31. package/dist/framework-mcp/src/tools/shell/run_command.js.map +1 -1
  32. package/dist/framework-mcp/src/tools/types.d.ts +11 -105
  33. package/dist/framework-mcp/src/tools/types.js +1 -0
  34. package/dist/framework-mcp/src/tools/types.js.map +1 -1
  35. package/dist/framework-mcp/src/utils/auth.d.ts +36 -0
  36. package/dist/framework-mcp/src/utils/auth.js +79 -0
  37. package/dist/framework-mcp/src/utils/auth.js.map +1 -0
  38. package/dist/framework-mcp/src/utils/auto-rollback.d.ts +71 -0
  39. package/dist/framework-mcp/src/utils/auto-rollback.js +266 -0
  40. package/dist/framework-mcp/src/utils/auto-rollback.js.map +1 -0
  41. package/dist/framework-mcp/src/utils/compliance.js +12 -4
  42. package/dist/framework-mcp/src/utils/compliance.js.map +1 -1
  43. package/dist/framework-mcp/src/utils/context-optimizer.d.ts +69 -0
  44. package/dist/framework-mcp/src/utils/context-optimizer.js +157 -0
  45. package/dist/framework-mcp/src/utils/context-optimizer.js.map +1 -0
  46. package/dist/framework-mcp/src/utils/discipline.d.ts +68 -0
  47. package/dist/framework-mcp/src/utils/discipline.js +218 -0
  48. package/dist/framework-mcp/src/utils/discipline.js.map +1 -0
  49. package/dist/framework-mcp/src/utils/finops.d.ts +143 -0
  50. package/dist/framework-mcp/src/utils/finops.js +326 -0
  51. package/dist/framework-mcp/src/utils/finops.js.map +1 -0
  52. package/dist/framework-mcp/src/utils/human-in-loop.d.ts +95 -0
  53. package/dist/framework-mcp/src/utils/human-in-loop.js +216 -0
  54. package/dist/framework-mcp/src/utils/human-in-loop.js.map +1 -0
  55. package/dist/framework-mcp/src/utils/license-scanner.d.ts +71 -0
  56. package/dist/framework-mcp/src/utils/license-scanner.js +284 -0
  57. package/dist/framework-mcp/src/utils/license-scanner.js.map +1 -0
  58. package/dist/framework-mcp/src/utils/loop-detector.d.ts +105 -0
  59. package/dist/framework-mcp/src/utils/loop-detector.js +362 -0
  60. package/dist/framework-mcp/src/utils/loop-detector.js.map +1 -0
  61. package/dist/framework-mcp/src/utils/quality.d.ts +19 -0
  62. package/dist/framework-mcp/src/utils/quality.js +125 -0
  63. package/dist/framework-mcp/src/utils/quality.js.map +1 -0
  64. package/dist/framework-mcp/src/utils/rules-engine.d.ts +78 -0
  65. package/dist/framework-mcp/src/utils/rules-engine.js +232 -0
  66. package/dist/framework-mcp/src/utils/rules-engine.js.map +1 -0
  67. package/dist/framework-mcp/src/utils/silent-router.d.ts +49 -0
  68. package/dist/framework-mcp/src/utils/silent-router.js +155 -0
  69. package/dist/framework-mcp/src/utils/silent-router.js.map +1 -0
  70. package/dist/framework-mcp/src/utils/storage.d.ts +1 -0
  71. package/dist/framework-mcp/src/utils/storage.js +2 -2
  72. package/dist/framework-mcp/src/utils/storage.js.map +1 -1
  73. package/dist/framework-mcp/src/utils/telemetry-streamer.d.ts +133 -0
  74. package/dist/framework-mcp/src/utils/telemetry-streamer.js +397 -0
  75. package/dist/framework-mcp/src/utils/telemetry-streamer.js.map +1 -0
  76. package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js +2 -2
  77. package/dist/framework-mcp/tests/tools/file_system/file_system_tools.test.js.map +1 -1
  78. package/dist/framework-mcp/tests/tools/framework/run_tests.test.d.ts +1 -0
  79. package/dist/framework-mcp/tests/tools/framework/run_tests.test.js +49 -0
  80. package/dist/framework-mcp/tests/tools/framework/run_tests.test.js.map +1 -0
  81. package/dist/framework-mcp/tests/tools/messaging/send_message.test.js +14 -5
  82. package/dist/framework-mcp/tests/tools/messaging/send_message.test.js.map +1 -1
  83. package/dist/framework-mcp/tests/tools/observability/check_ports.test.d.ts +1 -0
  84. package/dist/framework-mcp/tests/tools/observability/check_ports.test.js +44 -0
  85. package/dist/framework-mcp/tests/tools/observability/check_ports.test.js.map +1 -0
  86. package/dist/framework-mcp/tests/tools/shell/run_command.test.js +44 -14
  87. package/dist/framework-mcp/tests/tools/shell/run_command.test.js.map +1 -1
  88. package/dist/framework-mcp/tests/utils/auto-rollback.test.d.ts +7 -0
  89. package/dist/framework-mcp/tests/utils/auto-rollback.test.js +178 -0
  90. package/dist/framework-mcp/tests/utils/auto-rollback.test.js.map +1 -0
  91. package/dist/framework-mcp/tests/utils/context-optimizer.test.d.ts +1 -0
  92. package/dist/framework-mcp/tests/utils/context-optimizer.test.js +62 -0
  93. package/dist/framework-mcp/tests/utils/context-optimizer.test.js.map +1 -0
  94. package/dist/framework-mcp/tests/utils/finops.test.d.ts +7 -0
  95. package/dist/framework-mcp/tests/utils/finops.test.js +157 -0
  96. package/dist/framework-mcp/tests/utils/finops.test.js.map +1 -0
  97. package/dist/framework-mcp/tests/utils/human-in-loop.test.d.ts +1 -0
  98. package/dist/framework-mcp/tests/utils/human-in-loop.test.js +59 -0
  99. package/dist/framework-mcp/tests/utils/human-in-loop.test.js.map +1 -0
  100. package/dist/framework-mcp/tests/utils/license-scanner.test.d.ts +7 -0
  101. package/dist/framework-mcp/tests/utils/license-scanner.test.js +131 -0
  102. package/dist/framework-mcp/tests/utils/license-scanner.test.js.map +1 -0
  103. package/dist/framework-mcp/tests/utils/loop-detector.test.d.ts +7 -0
  104. package/dist/framework-mcp/tests/utils/loop-detector.test.js +204 -0
  105. package/dist/framework-mcp/tests/utils/loop-detector.test.js.map +1 -0
  106. package/dist/framework-mcp/tests/utils/rules-engine.test.d.ts +1 -0
  107. package/dist/framework-mcp/tests/utils/rules-engine.test.js +106 -0
  108. package/dist/framework-mcp/tests/utils/rules-engine.test.js.map +1 -0
  109. package/dist/framework-mcp/tests/utils/telemetry-streamer.test.d.ts +7 -0
  110. package/dist/framework-mcp/tests/utils/telemetry-streamer.test.js +201 -0
  111. package/dist/framework-mcp/tests/utils/telemetry-streamer.test.js.map +1 -0
  112. package/dist/src/cli/commands/check.js +16 -1
  113. package/dist/src/cli/commands/check.js.map +1 -1
  114. package/dist/src/cli/commands/dashboard.js +188 -164
  115. package/dist/src/cli/commands/dashboard.js.map +1 -1
  116. package/dist/src/cli/commands/gateway.js +2 -2
  117. package/dist/src/cli/commands/gateway.js.map +1 -1
  118. package/dist/src/cli/commands/init/scaffold-core.d.ts +2 -0
  119. package/dist/src/cli/commands/init/scaffold-core.js +16 -1
  120. package/dist/src/cli/commands/init/scaffold-core.js.map +1 -1
  121. package/dist/src/cli/commands/init/scaffold-ops.js +2 -2
  122. package/dist/src/cli/commands/init/scaffold-ops.js.map +1 -1
  123. package/dist/src/cli/commands/init/scaffold-standards.js +13 -1
  124. package/dist/src/cli/commands/init/scaffold-standards.js.map +1 -1
  125. package/dist/src/cli/commands/init.d.ts +4 -0
  126. package/dist/src/cli/commands/init.js +94 -31
  127. package/dist/src/cli/commands/init.js.map +1 -1
  128. package/dist/src/cli/commands/mcp.js +3 -1
  129. package/dist/src/cli/commands/mcp.js.map +1 -1
  130. package/dist/src/cli/commands/quickstart.d.ts +1 -1
  131. package/dist/src/cli/commands/quickstart.js +12 -24
  132. package/dist/src/cli/commands/quickstart.js.map +1 -1
  133. package/dist/src/cli/commands/script.js +8 -1
  134. package/dist/src/cli/commands/script.js.map +1 -1
  135. package/dist/src/cli/index.js +24 -23
  136. package/dist/src/cli/index.js.map +1 -1
  137. package/dist/src/cli/shims.js +7 -7
  138. package/dist/src/cli/utils/pkg.js +2 -3
  139. package/dist/src/cli/utils/pkg.js.map +1 -1
  140. package/dist/src/cli/utils/quality.d.ts +10 -0
  141. package/dist/src/cli/utils/quality.js +10 -0
  142. package/dist/src/cli/utils/quality.js.map +1 -0
  143. package/dist/src/modules/agents/definitions.js +45 -40
  144. package/dist/src/modules/agents/definitions.js.map +1 -1
  145. package/dist/src/modules/agents/registry/manager.js +6 -1
  146. package/dist/src/modules/agents/registry/manager.js.map +1 -1
  147. package/dist/src/modules/engines/agent-executor.d.ts +6 -10
  148. package/dist/src/modules/engines/agent-executor.js +63 -21
  149. package/dist/src/modules/engines/agent-executor.js.map +1 -1
  150. package/dist/src/modules/engines/agent-loop.d.ts +34 -0
  151. package/dist/src/modules/engines/agent-loop.js +102 -0
  152. package/dist/src/modules/engines/agent-loop.js.map +1 -0
  153. package/dist/src/modules/engines/evaluation-engine.d.ts +12 -2
  154. package/dist/src/modules/engines/evaluation-engine.js +78 -11
  155. package/dist/src/modules/engines/evaluation-engine.js.map +1 -1
  156. package/dist/src/modules/engines/quality-gate.d.ts +13 -5
  157. package/dist/src/modules/engines/quality-gate.js +39 -31
  158. package/dist/src/modules/engines/quality-gate.js.map +1 -1
  159. package/dist/src/modules/engines/routing-engine.d.ts +5 -3
  160. package/dist/src/modules/engines/routing-engine.js +16 -9
  161. package/dist/src/modules/engines/routing-engine.js.map +1 -1
  162. package/dist/src/modules/gateway/cost-tracker.d.ts +5 -0
  163. package/dist/src/modules/gateway/cost-tracker.js +71 -0
  164. package/dist/src/modules/gateway/cost-tracker.js.map +1 -1
  165. package/dist/src/modules/gateway/gateway.d.ts +4 -0
  166. package/dist/src/modules/gateway/gateway.js +8 -0
  167. package/dist/src/modules/gateway/gateway.js.map +1 -1
  168. package/dist/src/shared/audit.js +3 -2
  169. package/dist/src/shared/audit.js.map +1 -1
  170. package/dist/src/shared/pii.d.ts +41 -9
  171. package/dist/src/shared/pii.js +122 -31
  172. package/dist/src/shared/pii.js.map +1 -1
  173. package/dist/src/shared/storage.d.ts +62 -0
  174. package/dist/src/shared/storage.js +47 -7
  175. package/dist/src/shared/storage.js.map +1 -1
  176. package/dist/tests/embedding.test.d.ts +1 -0
  177. package/dist/tests/embedding.test.js +82 -0
  178. package/dist/tests/embedding.test.js.map +1 -0
  179. package/dist/tests/engines/evaluation-engine.test.d.ts +1 -0
  180. package/dist/tests/engines/evaluation-engine.test.js +71 -0
  181. package/dist/tests/engines/evaluation-engine.test.js.map +1 -0
  182. package/dist/tests/engines/planning-engine.test.d.ts +1 -0
  183. package/dist/tests/engines/planning-engine.test.js +100 -0
  184. package/dist/tests/engines/planning-engine.test.js.map +1 -0
  185. package/dist/tests/engines/quality-gate.test.d.ts +1 -0
  186. package/dist/tests/engines/quality-gate.test.js +59 -0
  187. package/dist/tests/engines/quality-gate.test.js.map +1 -0
  188. package/dist/tests/engines/risk-engine.test.d.ts +1 -0
  189. package/dist/tests/engines/risk-engine.test.js +80 -0
  190. package/dist/tests/engines/risk-engine.test.js.map +1 -0
  191. package/dist/tests/engines/routing-engine.test.d.ts +1 -0
  192. package/dist/tests/engines/routing-engine.test.js +78 -0
  193. package/dist/tests/engines/routing-engine.test.js.map +1 -0
  194. package/dist/tests/integration/hermes_locking.test.js +1 -0
  195. package/dist/tests/integration/hermes_locking.test.js.map +1 -1
  196. package/dist/tests/modules/engines/agent-executor.test.js +1 -1
  197. package/dist/tests/modules/engines/agent-executor.test.js.map +1 -1
  198. package/dist/tests/modules/gateway/cost-tracker.test.js +20 -1
  199. package/dist/tests/modules/gateway/cost-tracker.test.js.map +1 -1
  200. package/dist/tests/shared/lock.test.d.ts +1 -0
  201. package/dist/tests/shared/lock.test.js +95 -0
  202. package/dist/tests/shared/lock.test.js.map +1 -0
  203. package/dist/tests/shared/pii.test.d.ts +1 -0
  204. package/dist/tests/shared/pii.test.js +183 -0
  205. package/dist/tests/shared/pii.test.js.map +1 -0
  206. package/framework-mcp/README.md +307 -35
  207. package/framework-mcp/dist/dashboard/assets/index-B_rK57vi.js +1221 -0
  208. package/framework-mcp/dist/dashboard/index.html +1 -1
  209. package/framework-mcp/dist/framework-mcp/src/index.js +988 -63
  210. package/framework-mcp/dist/framework-mcp/src/tools/compliance/mask_pii.js +55 -0
  211. package/framework-mcp/dist/framework-mcp/src/tools/definitions.js +10 -9
  212. package/framework-mcp/dist/framework-mcp/src/tools/framework/run_tests.js +25 -0
  213. package/framework-mcp/dist/framework-mcp/src/tools/index.js +7 -8
  214. package/framework-mcp/dist/framework-mcp/src/tools/messaging/approve_operation.js +80 -0
  215. package/framework-mcp/dist/framework-mcp/src/tools/messaging/ask_human.js +89 -20
  216. package/framework-mcp/dist/framework-mcp/src/tools/observability/check_ports.js +24 -8
  217. package/framework-mcp/dist/framework-mcp/src/tools/quality/analyze_code_quality.js +13 -64
  218. package/framework-mcp/dist/framework-mcp/src/tools/schemas.js +18 -22
  219. package/framework-mcp/dist/framework-mcp/src/tools/shell/run_command.js +146 -90
  220. package/framework-mcp/dist/framework-mcp/src/tools/types.js +1 -0
  221. package/framework-mcp/dist/framework-mcp/src/utils/auth.js +78 -0
  222. package/framework-mcp/dist/framework-mcp/src/utils/auto-rollback.js +265 -0
  223. package/framework-mcp/dist/framework-mcp/src/utils/compliance.js +12 -4
  224. package/framework-mcp/dist/framework-mcp/src/utils/context-optimizer.js +156 -0
  225. package/framework-mcp/dist/framework-mcp/src/utils/discipline.js +217 -0
  226. package/framework-mcp/dist/framework-mcp/src/utils/finops.js +325 -0
  227. package/framework-mcp/dist/framework-mcp/src/utils/human-in-loop.js +215 -0
  228. package/framework-mcp/dist/framework-mcp/src/utils/license-scanner.js +283 -0
  229. package/framework-mcp/dist/framework-mcp/src/utils/loop-detector.js +361 -0
  230. package/framework-mcp/dist/framework-mcp/src/utils/quality.js +124 -0
  231. package/framework-mcp/dist/framework-mcp/src/utils/rules-engine.js +231 -0
  232. package/framework-mcp/dist/framework-mcp/src/utils/silent-router.js +154 -0
  233. package/framework-mcp/dist/framework-mcp/src/utils/storage.js +2 -2
  234. package/framework-mcp/dist/framework-mcp/src/utils/telemetry-streamer.js +396 -0
  235. package/framework-mcp/dist/src/cli/platforms/core.js +72 -0
  236. package/framework-mcp/dist/src/cli/platforms/index.js +5 -0
  237. package/framework-mcp/dist/src/cli/platforms/paths.js +101 -0
  238. package/framework-mcp/dist/src/cli/platforms/scaffold.js +72 -0
  239. package/framework-mcp/dist/src/cli/platforms/utils.js +75 -0
  240. package/framework-mcp/dist/src/cli/utils/claude.js +57 -0
  241. package/framework-mcp/dist/src/cli/utils/compliance.js +12 -0
  242. package/framework-mcp/dist/src/cli/utils/fs.js +138 -0
  243. package/framework-mcp/dist/src/cli/utils/pkg.js +282 -0
  244. package/framework-mcp/dist/src/cli/utils/quality.js +9 -0
  245. package/framework-mcp/dist/src/modules/agents/definitions.js +563 -0
  246. package/framework-mcp/dist/src/modules/agents/registry/analyst.js +39 -0
  247. package/framework-mcp/dist/src/modules/agents/registry/architect.js +42 -0
  248. package/framework-mcp/dist/src/modules/agents/registry/backend.js +50 -0
  249. package/framework-mcp/dist/src/modules/agents/registry/database.js +45 -0
  250. package/framework-mcp/dist/src/modules/agents/registry/devops.js +45 -0
  251. package/framework-mcp/dist/src/modules/agents/registry/explorer.js +37 -0
  252. package/framework-mcp/dist/src/modules/agents/registry/frontend.js +52 -0
  253. package/framework-mcp/dist/src/modules/agents/registry/git.js +36 -0
  254. package/framework-mcp/dist/src/modules/agents/registry/manager.js +64 -0
  255. package/framework-mcp/dist/src/modules/agents/registry/mobile.js +41 -0
  256. package/framework-mcp/dist/src/modules/agents/registry/native.js +41 -0
  257. package/framework-mcp/dist/src/modules/agents/registry/quality.js +43 -0
  258. package/framework-mcp/dist/src/modules/agents/registry/security.js +42 -0
  259. package/framework-mcp/dist/src/modules/agents/types.js +1 -0
  260. package/framework-mcp/dist/src/modules/engines/evaluation-engine.js +169 -0
  261. package/framework-mcp/dist/src/modules/engines/quality-gate.js +92 -0
  262. package/framework-mcp/dist/src/modules/engines/risk-engine.js +105 -0
  263. package/framework-mcp/dist/src/modules/engines/routing-engine.js +408 -0
  264. package/framework-mcp/dist/src/modules/engines/types.js +1 -0
  265. package/framework-mcp/dist/src/modules/providers/definitions.js +140 -0
  266. package/framework-mcp/dist/src/modules/providers/registry.js +18 -0
  267. package/framework-mcp/dist/src/modules/providers/shared.js +104 -0
  268. package/framework-mcp/dist/src/modules/providers/types.js +1 -0
  269. package/framework-mcp/dist/src/modules/skills/adapter-skills.js +449 -0
  270. package/framework-mcp/dist/src/modules/skills/definitions.js +70 -0
  271. package/framework-mcp/dist/src/shared/audit.js +220 -0
  272. package/framework-mcp/dist/src/shared/errors.js +68 -0
  273. package/framework-mcp/dist/src/shared/lock.js +159 -0
  274. package/framework-mcp/dist/src/shared/pii.js +122 -31
  275. package/framework-mcp/dist/src/shared/retention.js +170 -0
  276. package/framework-mcp/dist/src/shared/storage.js +47 -7
  277. package/framework-mcp/dist/src/shared/string.js +29 -0
  278. package/framework-mcp/package.json +8 -2
  279. package/mcp.json +12 -6
  280. package/package.json +11 -5
  281. package/templates/full/ATABEY_FULL.md +1 -1
  282. package/framework-mcp/dist/dashboard/assets/index-BAPGLiWE.js +0 -267
@@ -0,0 +1,396 @@
1
+ /**
2
+ * ─── ASYNCHRONOUS TELEMETRY STREAMER ───────────────────────────────
3
+ *
4
+ * Streams local audit logs, metrics, and governance events to the
5
+ * central enterprise server asynchronously without blocking the
6
+ * developer's AI CLI workflow.
7
+ *
8
+ * Features:
9
+ * - Batch streaming (accumulates events, sends in batches)
10
+ * - Retry with exponential backoff
11
+ * - Queue persistence (survives process restarts)
12
+ * - Bandwidth throttling (max N events per minute)
13
+ * - PII masking before transmission (GDPR/KVKK)
14
+ * - Connection health monitoring
15
+ *
16
+ * Architecture:
17
+ * [Local MCP] → SQLite Queue → Batch Processor → HTTPS/WS → [Enterprise Server]
18
+ *
19
+ * [KVKK/GDPR] All PII is masked BEFORE leaving the local machine.
20
+ */
21
+ import fs from "fs";
22
+ import os from "os";
23
+ import path from "path";
24
+ import { maskObject, maskText } from "../../../src/shared/pii.js";
25
+ // ─── Configuration ────────────────────────────────────────────────
26
+ const CONFIG = {
27
+ /** Enterprise server URL (e.g., https://atabey.company.com) */
28
+ SERVER_URL: process.env.ATABEY_SERVER_URL || "",
29
+ /** Auth token for enterprise server */
30
+ AUTH_TOKEN: process.env.ATABEY_SERVER_TOKEN || "",
31
+ /** Max events per batch */
32
+ BATCH_SIZE: parseInt(process.env.ATABEY_TELEMETRY_BATCH_SIZE || "50", 10),
33
+ /** Flush interval in ms */
34
+ FLUSH_INTERVAL_MS: parseInt(process.env.ATABEY_TELEMETRY_FLUSH_INTERVAL || "30000", 10),
35
+ /** Max retries per batch */
36
+ MAX_RETRIES: parseInt(process.env.ATABEY_TELEMETRY_MAX_RETRIES || "3", 10),
37
+ /** Retry base delay (exponential backoff) */
38
+ RETRY_BASE_DELAY_MS: parseInt(process.env.ATABEY_TELEMETRY_RETRY_DELAY || "1000", 10),
39
+ /** Max events per minute (throttle) */
40
+ MAX_EVENTS_PER_MINUTE: parseInt(process.env.ATABEY_TELEMETRY_RATE_LIMIT || "200", 10),
41
+ /** Enable/disable telemetry */
42
+ ENABLED: process.env.ATABEY_TELEMETRY_ENABLED !== "false",
43
+ /** Use WebSocket for real-time streaming (fallback to HTTPS) */
44
+ USE_WEBSOCKET: process.env.ATABEY_TELEMETRY_WS === "true",
45
+ };
46
+ // ─── Telemetry Streamer ───────────────────────────────────────────
47
+ export class TelemetryStreamer {
48
+ static instance;
49
+ queue = [];
50
+ flushTimer = null;
51
+ ws = null;
52
+ wsReconnectTimer = null;
53
+ eventCountThisMinute = 0;
54
+ minuteResetTimer = null;
55
+ machineId;
56
+ projectHash;
57
+ isFlushing = false;
58
+ constructor() {
59
+ this.machineId = this.generateMachineId();
60
+ this.projectHash = this.generateProjectHash();
61
+ }
62
+ static getInstance() {
63
+ if (!TelemetryStreamer.instance) {
64
+ TelemetryStreamer.instance = new TelemetryStreamer();
65
+ }
66
+ return TelemetryStreamer.instance;
67
+ }
68
+ /**
69
+ * Start the telemetry streamer.
70
+ * Begins periodic flush and WebSocket connection if configured.
71
+ */
72
+ start() {
73
+ if (!CONFIG.ENABLED || !CONFIG.SERVER_URL) {
74
+ process.stderr.write("[TELEMETRY] Disabled or no server URL configured.\n");
75
+ return;
76
+ }
77
+ process.stderr.write(`[TELEMETRY] Starting streamer → ${CONFIG.SERVER_URL}\n`);
78
+ // Periodic flush
79
+ this.flushTimer = setInterval(() => this.flush(), CONFIG.FLUSH_INTERVAL_MS);
80
+ // Minute counter reset
81
+ this.minuteResetTimer = setInterval(() => {
82
+ this.eventCountThisMinute = 0;
83
+ }, 60000);
84
+ // WebSocket connection (if enabled)
85
+ if (CONFIG.USE_WEBSOCKET) {
86
+ this.connectWebSocket();
87
+ }
88
+ // Flush on exit
89
+ process.on("beforeExit", () => this.flushSync());
90
+ process.on("SIGINT", () => { this.flushSync(); });
91
+ process.on("SIGTERM", () => { this.flushSync(); });
92
+ }
93
+ /**
94
+ * Stop the telemetry streamer.
95
+ */
96
+ stop() {
97
+ if (this.flushTimer) {
98
+ clearInterval(this.flushTimer);
99
+ this.flushTimer = null;
100
+ }
101
+ if (this.minuteResetTimer) {
102
+ clearInterval(this.minuteResetTimer);
103
+ this.minuteResetTimer = null;
104
+ }
105
+ if (this.ws) {
106
+ this.ws.close();
107
+ this.ws = null;
108
+ }
109
+ if (this.wsReconnectTimer) {
110
+ clearTimeout(this.wsReconnectTimer);
111
+ this.wsReconnectTimer = null;
112
+ }
113
+ this.flushSync();
114
+ }
115
+ /**
116
+ * Enqueue a telemetry event for streaming.
117
+ * Events are batched and sent asynchronously.
118
+ */
119
+ enqueue(event) {
120
+ if (!CONFIG.ENABLED)
121
+ return;
122
+ // Rate limiting
123
+ if (this.eventCountThisMinute >= CONFIG.MAX_EVENTS_PER_MINUTE) {
124
+ return; // Silently drop
125
+ }
126
+ this.eventCountThisMinute++;
127
+ const fullEvent = {
128
+ ...event,
129
+ id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
130
+ machineId: this.machineId,
131
+ projectHash: this.projectHash,
132
+ // [KVKK/GDPR] Mask PII before queuing
133
+ payload: maskObject(event.payload),
134
+ };
135
+ this.queue.push({ event: fullEvent, retries: 0, lastAttempt: null });
136
+ // If queue is large enough, flush immediately
137
+ if (this.queue.length >= CONFIG.BATCH_SIZE) {
138
+ this.flush();
139
+ }
140
+ }
141
+ /**
142
+ * Convenience method for logging tool calls.
143
+ */
144
+ logToolCall(agent, toolName, tokens, traceId, durationMs) {
145
+ this.enqueue({
146
+ type: "tool_call",
147
+ timestamp: new Date().toISOString(),
148
+ agent,
149
+ payload: {
150
+ tool: toolName,
151
+ estimatedTokens: tokens,
152
+ traceId,
153
+ durationMs,
154
+ },
155
+ });
156
+ }
157
+ /**
158
+ * Convenience method for logging governance violations.
159
+ */
160
+ logGovernanceViolation(agent, toolName, error) {
161
+ this.enqueue({
162
+ type: "governance_violation",
163
+ timestamp: new Date().toISOString(),
164
+ agent,
165
+ payload: {
166
+ tool: toolName,
167
+ error: maskText(error),
168
+ },
169
+ });
170
+ }
171
+ /**
172
+ * Convenience method for logging errors.
173
+ */
174
+ logError(agent, action, error) {
175
+ this.enqueue({
176
+ type: "error",
177
+ timestamp: new Date().toISOString(),
178
+ agent,
179
+ payload: {
180
+ action,
181
+ error: maskText(error),
182
+ },
183
+ });
184
+ }
185
+ // ─── Private Methods ───────────────────────────────────────
186
+ /**
187
+ * Flush queued events to the enterprise server.
188
+ */
189
+ async flush() {
190
+ if (this.isFlushing || this.queue.length === 0)
191
+ return;
192
+ this.isFlushing = true;
193
+ let success;
194
+ const batch = this.queue.splice(0, CONFIG.BATCH_SIZE);
195
+ try {
196
+ const events = batch.map(q => q.event);
197
+ // [KVKK/GDPR] Double-check PII masking before transmission
198
+ const sanitizedEvents = events.map(e => ({
199
+ ...e,
200
+ payload: maskObject(e.payload),
201
+ }));
202
+ success = await this.sendBatch(sanitizedEvents);
203
+ }
204
+ catch (err) {
205
+ const message = err instanceof Error ? err.message : "Unknown error";
206
+ process.stderr.write(`[TELEMETRY] Send batch failed: ${message}\n`);
207
+ success = false;
208
+ }
209
+ if (!success) {
210
+ // Re-queue with retry count
211
+ for (const q of batch) {
212
+ q.retries++;
213
+ q.lastAttempt = Date.now();
214
+ if (q.retries < CONFIG.MAX_RETRIES) {
215
+ this.queue.push(q);
216
+ }
217
+ else {
218
+ // Max retries exceeded, log locally and drop
219
+ process.stderr.write(`[TELEMETRY] Dropped event after ${CONFIG.MAX_RETRIES} retries: ${q.event.type}\n`);
220
+ this.saveToLocalFallback(q.event);
221
+ }
222
+ }
223
+ }
224
+ this.isFlushing = false;
225
+ }
226
+ /**
227
+ * Synchronous flush (for process exit).
228
+ */
229
+ flushSync() {
230
+ if (this.queue.length === 0)
231
+ return;
232
+ const batch = this.queue.splice(0, CONFIG.BATCH_SIZE);
233
+ const events = batch.map(q => q.event);
234
+ // Save to local fallback file (best effort)
235
+ for (const event of events) {
236
+ this.saveToLocalFallback(event);
237
+ }
238
+ }
239
+ /**
240
+ * Send a batch of events to the enterprise server via HTTPS.
241
+ */
242
+ async sendBatch(events) {
243
+ try {
244
+ const url = `${CONFIG.SERVER_URL.replace(/\/$/, "")}/api/telemetry/ingest`;
245
+ const response = await fetch(url, {
246
+ method: "POST",
247
+ headers: {
248
+ "Content-Type": "application/json",
249
+ "Authorization": `Bearer ${CONFIG.AUTH_TOKEN}`,
250
+ "X-Machine-Id": this.machineId,
251
+ "X-Project-Hash": this.projectHash,
252
+ },
253
+ body: JSON.stringify({
254
+ batch: events,
255
+ sentAt: new Date().toISOString(),
256
+ machineId: this.machineId,
257
+ }),
258
+ });
259
+ if (!response.ok) {
260
+ process.stderr.write(`[TELEMETRY] Server returned ${response.status}: ${response.statusText}\n`);
261
+ return false;
262
+ }
263
+ return true;
264
+ }
265
+ catch (error) {
266
+ const message = error instanceof Error ? error.message : String(error);
267
+ process.stderr.write(`[TELEMETRY] Send failed: ${message}\n`);
268
+ return false;
269
+ }
270
+ }
271
+ /**
272
+ * Connect to enterprise server via WebSocket for real-time streaming.
273
+ */
274
+ connectWebSocket() {
275
+ // Native WebSocket is available in Node.js >= 22.
276
+ // For older versions, we skip WebSocket and rely on HTTPS batch mode.
277
+ const NodeWebSocket = typeof WebSocket !== "undefined" ? WebSocket : undefined;
278
+ if (!NodeWebSocket) {
279
+ process.stderr.write("[TELEMETRY] WebSocket unavailable (Node.js < 22). Using HTTPS batch mode only.\n");
280
+ // Force HTTPS mode by disabling WS flag
281
+ return;
282
+ }
283
+ try {
284
+ const wsUrl = CONFIG.SERVER_URL.replace(/^http/, "ws").replace(/\/$/, "") + "/ws/telemetry";
285
+ this.ws = new NodeWebSocket(wsUrl);
286
+ this.ws.onopen = () => {
287
+ process.stderr.write("[TELEMETRY] WebSocket connected.\n");
288
+ // Authenticate
289
+ this.ws?.send(JSON.stringify({
290
+ type: "auth",
291
+ token: CONFIG.AUTH_TOKEN,
292
+ machineId: this.machineId,
293
+ projectHash: this.projectHash,
294
+ }));
295
+ };
296
+ this.ws.onclose = () => {
297
+ process.stderr.write("[TELEMETRY] WebSocket disconnected. Reconnecting...\n");
298
+ this.ws = null;
299
+ // Reconnect after delay
300
+ this.wsReconnectTimer = setTimeout(() => this.connectWebSocket(), 5000);
301
+ };
302
+ this.ws.onerror = () => {
303
+ // onclose will handle reconnection
304
+ };
305
+ this.ws.onmessage = (msg) => {
306
+ try {
307
+ const data = JSON.parse(msg.data.toString());
308
+ if (data.type === "config_update") {
309
+ process.stderr.write(`[TELEMETRY] Config update received: ${JSON.stringify(data.payload)}\n`);
310
+ // Apply remote config changes
311
+ if (data.payload.maxEventsPerMinute) {
312
+ // Dynamic rate limiting from server
313
+ }
314
+ }
315
+ }
316
+ catch { /* ignore */ }
317
+ };
318
+ }
319
+ catch (error) {
320
+ process.stderr.write(`[TELEMETRY] WebSocket connection failed: ${error}\n`);
321
+ // Retry
322
+ this.wsReconnectTimer = setTimeout(() => this.connectWebSocket(), 10000);
323
+ }
324
+ }
325
+ /**
326
+ * Save event to local fallback file (when server is unreachable).
327
+ */
328
+ saveToLocalFallback(event) {
329
+ try {
330
+ const frameworkDir = process.env.ATABEY_FRAMEWORK_DIR || path.join(process.cwd(), ".atabey");
331
+ const telemetryDir = path.join(frameworkDir, "telemetry");
332
+ if (!fs.existsSync(telemetryDir)) {
333
+ fs.mkdirSync(telemetryDir, { recursive: true });
334
+ }
335
+ const fallbackPath = path.join(telemetryDir, "pending-events.jsonl");
336
+ fs.appendFileSync(fallbackPath, JSON.stringify(event) + "\n");
337
+ }
338
+ catch { /* ignore: best effort */ }
339
+ }
340
+ /**
341
+ * Generate a unique machine ID.
342
+ */
343
+ generateMachineId() {
344
+ try {
345
+ const hostname = os.hostname();
346
+ const cpus = os.cpus();
347
+ const cpuModel = cpus.length > 0 ? cpus[0].model : "unknown";
348
+ const hash = this.simpleHash(`${hostname}-${cpuModel}`);
349
+ return `machine-${hash}`;
350
+ }
351
+ catch {
352
+ return `machine-${Math.random().toString(36).substr(2, 8)}`;
353
+ }
354
+ }
355
+ /**
356
+ * Generate a project hash for grouping.
357
+ */
358
+ generateProjectHash() {
359
+ try {
360
+ const pkgPath = path.join(process.cwd(), "package.json");
361
+ if (fs.existsSync(pkgPath)) {
362
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
363
+ return this.simpleHash(pkg.name || pkgPath);
364
+ }
365
+ }
366
+ catch { /* ignore */ }
367
+ return this.simpleHash(process.cwd());
368
+ }
369
+ /**
370
+ * Simple string hash.
371
+ */
372
+ simpleHash(str) {
373
+ let hash = 0;
374
+ for (let i = 0; i < str.length; i++) {
375
+ const char = str.charCodeAt(i);
376
+ hash = ((hash << 5) - hash) + char;
377
+ hash = hash & hash; // Convert to 32bit integer
378
+ }
379
+ return Math.abs(hash).toString(16).substring(0, 8);
380
+ }
381
+ /**
382
+ * Get streamer status.
383
+ */
384
+ getStatus() {
385
+ return {
386
+ enabled: CONFIG.ENABLED,
387
+ serverUrl: CONFIG.SERVER_URL,
388
+ queueSize: this.queue.length,
389
+ wsConnected: this.ws?.readyState === WebSocket.OPEN,
390
+ eventsThisMinute: this.eventCountThisMinute,
391
+ };
392
+ }
393
+ }
394
+ // ─── Singleton Export ─────────────────────────────────────────────
395
+ export const telemetryStreamer = TelemetryStreamer.getInstance();
396
+ export { CONFIG as TelemetryConfig };
@@ -0,0 +1,72 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { MCP } from "../../shared/constants.js";
4
+ import { writeJsonFile } from "../utils/fs.js";
5
+ import { getPackageRoot } from "../utils/pkg.js";
6
+ import { UI } from "../utils/ui.js";
7
+ import { ADAPTER_CONFIGS, POST_INIT_HANDLERS } from "../../modules/providers/definitions.js";
8
+ export const ADAPTERS = ADAPTER_CONFIGS;
9
+ export const SHIM_FILES = Object.keys(ADAPTERS).map((id) => ADAPTERS[id].shimFile);
10
+ export const FRAMEWORK_DIR_CANDIDATES = [
11
+ ".atabey",
12
+ ".cursor",
13
+ ".claude",
14
+ ".github",
15
+ ".grok",
16
+ ".antigravity",
17
+ ".agent",
18
+ ".gemini/antigravity-cli",
19
+ ".gemini",
20
+ ".agents",
21
+ "antigravity-cli"
22
+ ];
23
+ export function buildMcpServerEntry(projectRoot) {
24
+ const packageRoot = getPackageRoot();
25
+ // Check if we are running in the framework local development repository itself
26
+ const isLocalFrameworkDev = path.resolve(packageRoot) === path.resolve(projectRoot);
27
+ let relativePath;
28
+ if (isLocalFrameworkDev) {
29
+ // In local framework dev, always use the build path directly relative to project root
30
+ let mcpServerPath = path.join(packageRoot, MCP.SERVER_DIST_PATH);
31
+ if (!fs.existsSync(mcpServerPath)) {
32
+ mcpServerPath = path.join(packageRoot, "../atabey-mcp/dist/index.js");
33
+ }
34
+ if (!fs.existsSync(mcpServerPath)) {
35
+ mcpServerPath = path.join(projectRoot, "node_modules/atabey-mcp/dist/index.js");
36
+ }
37
+ if (!fs.existsSync(mcpServerPath)) {
38
+ UI.warning(" MCP Server not found. Did you run 'npm run build' inside atabey-mcp?");
39
+ }
40
+ relativePath = path.relative(projectRoot, mcpServerPath) || mcpServerPath;
41
+ }
42
+ else {
43
+ // If we are initializing in a user's project:
44
+ // We target the atabey-mcp package which is a dependency of atabey.
45
+ // This ensures a stable path across different npm/pnpm/yarn setups.
46
+ relativePath = "node_modules/atabey-mcp/dist/index.js";
47
+ // Fallback check if it actually exists in a different location during init
48
+ const localAtabeyPath = path.join(projectRoot, "node_modules/atabey", MCP.SERVER_DIST_PATH);
49
+ if (!fs.existsSync(path.join(projectRoot, relativePath)) && fs.existsSync(localAtabeyPath)) {
50
+ relativePath = path.join("node_modules/atabey", MCP.SERVER_DIST_PATH);
51
+ }
52
+ }
53
+ return {
54
+ command: "node",
55
+ args: [relativePath],
56
+ env: {
57
+ [MCP.PROJECT_ROOT_ENV]: projectRoot,
58
+ },
59
+ };
60
+ }
61
+ export function runAdapterPostInit(adapter, projectRoot) {
62
+ const mcpEntry = buildMcpServerEntry(projectRoot);
63
+ const mcpBlock = { mcpServers: { [MCP.SERVER_NAME]: mcpEntry } };
64
+ const postInitFn = POST_INIT_HANDLERS[adapter.id];
65
+ if (postInitFn) {
66
+ postInitFn(projectRoot, mcpBlock);
67
+ }
68
+ const rootMcpPath = path.join(projectRoot, MCP.ROOT_CONFIG_FILE);
69
+ if (!fs.existsSync(rootMcpPath)) {
70
+ writeJsonFile(rootMcpPath, mcpBlock);
71
+ }
72
+ }
@@ -0,0 +1,5 @@
1
+ export { ADAPTER_IDS } from "../../modules/providers/types.js";
2
+ export { ADAPTERS, buildMcpServerEntry, FRAMEWORK_DIR_CANDIDATES, runAdapterPostInit } from "./core.js";
3
+ export { mirrorUnifiedAgentsToNative, resolveAgentsDir } from "./paths.js";
4
+ export { scaffoldAgents } from "./scaffold.js";
5
+ export { isAdapterShimFile, remapFrameworkContent, resolveAdapter } from "./utils.js";
@@ -0,0 +1,101 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { ADAPTER_IDS } from "../../modules/providers/types.js";
4
+ import { LEGACY_AGENT_LAYOUT_BASES, UNIFIED_ADAPTER_SLUG, UNIFIED_HUB_DIR, pathJoin, unifiedAdapterPath, } from "../../shared/constants.js";
5
+ import { ADAPTERS } from "./core.js";
6
+ export { CORE_FRAMEWORK_DIR, UNIFIED_ADAPTER_SLUG, UNIFIED_HUB_DIR } from "../../shared/constants.js";
7
+ export function unifiedAdapterRoot(aiToolDir, adapterId) {
8
+ return pathJoin(aiToolDir, UNIFIED_ADAPTER_SLUG[adapterId]);
9
+ }
10
+ export function resolveAgentsDir(adapterId, isUnified, aiToolDir = UNIFIED_HUB_DIR) {
11
+ const adapter = ADAPTERS[adapterId];
12
+ if (!isUnified) {
13
+ return {
14
+ agentsDir: adapter.agentsDir ?? pathJoin(adapter.frameworkDir, "agents"),
15
+ agentsExt: adapter.agentsExt ?? ".md",
16
+ nestedAntigravity: adapterId === "antigravity-cli",
17
+ };
18
+ }
19
+ const base = unifiedAdapterRoot(aiToolDir, adapterId);
20
+ switch (adapterId) {
21
+ case "cursor":
22
+ return { agentsDir: pathJoin(base, "rules"), agentsExt: ".mdc", nestedAntigravity: false };
23
+ case "codex":
24
+ return { agentsDir: pathJoin(base, "instructions"), agentsExt: ".md", nestedAntigravity: false };
25
+ case "antigravity-cli":
26
+ // Antigravity CLI expects workspace agents at .agents/agents/{agent_name}/agent.json
27
+ return { agentsDir: pathJoin(aiToolDir, "agents"), agentsExt: ".json", nestedAntigravity: true };
28
+ default:
29
+ return { agentsDir: pathJoin(base, "agents"), agentsExt: ".md", nestedAntigravity: false };
30
+ }
31
+ }
32
+ export function getUnifiedAgentLayoutBases(aiToolDir = UNIFIED_HUB_DIR) {
33
+ return ADAPTER_IDS.map((id) => resolveAgentsDir(id, true, aiToolDir).agentsDir);
34
+ }
35
+ const AGENT_INSTRUCTION_CANDIDATES = [
36
+ (n) => ADAPTER_IDS.flatMap((id) => {
37
+ const { agentsDir, nestedAntigravity, agentsExt } = resolveAgentsDir(id, true);
38
+ if (nestedAntigravity) {
39
+ return [pathJoin(agentsDir, n, "agent.json"), pathJoin(agentsDir, n, "agent.md")];
40
+ }
41
+ return [pathJoin(agentsDir, `${n}${agentsExt}`)];
42
+ }),
43
+ (n) => LEGACY_AGENT_LAYOUT_BASES.flatMap((base) => {
44
+ if (base.includes("antigravity")) {
45
+ return [pathJoin(base, n, "agent.json"), pathJoin(base, n, "agent.md")];
46
+ }
47
+ const ext = base.includes("rules") ? ".mdc" : ".md";
48
+ return [pathJoin(base, `${n}${ext}`)];
49
+ }),
50
+ ];
51
+ export function findAgentInstruction(projectRoot, agentName) {
52
+ for (const buildPaths of AGENT_INSTRUCTION_CANDIDATES) {
53
+ for (const rel of buildPaths(agentName)) {
54
+ const full = path.join(projectRoot, rel);
55
+ if (fs.existsSync(full))
56
+ return rel;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ export function detectActiveAgentLayouts(projectRoot) {
62
+ const unified = getUnifiedAgentLayoutBases()
63
+ .filter((b) => fs.existsSync(path.join(projectRoot, b)));
64
+ const legacy = LEGACY_AGENT_LAYOUT_BASES
65
+ .filter((b) => fs.existsSync(path.join(projectRoot, b)));
66
+ return [...new Set([...unified, ...legacy])];
67
+ }
68
+ function copyDirectoryRecursive(src, dest) {
69
+ fs.mkdirSync(dest, { recursive: true });
70
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
71
+ const srcPath = path.join(src, entry.name);
72
+ const destPath = path.join(dest, entry.name);
73
+ if (entry.isDirectory()) {
74
+ copyDirectoryRecursive(srcPath, destPath);
75
+ }
76
+ else {
77
+ fs.copyFileSync(srcPath, destPath);
78
+ }
79
+ }
80
+ }
81
+ export function mirrorUnifiedAgentsToNative(projectRoot, adapterId) {
82
+ const { agentsDir: unifiedDir } = resolveAgentsDir(adapterId, true);
83
+ const nativeRel = ADAPTERS[adapterId].agentsDir;
84
+ if (!nativeRel)
85
+ return;
86
+ const src = path.join(projectRoot, unifiedDir);
87
+ const dest = path.join(projectRoot, nativeRel);
88
+ if (!fs.existsSync(src) || path.resolve(src) === path.resolve(dest))
89
+ return;
90
+ if (fs.existsSync(dest)) {
91
+ fs.rmSync(dest, { recursive: true, force: true });
92
+ }
93
+ copyDirectoryRecursive(src, dest);
94
+ }
95
+ /** Cursor global rule destinations (native + unified hub). */
96
+ export function getCursorGlobalRulePaths(projectRoot) {
97
+ return [
98
+ path.join(projectRoot, ADAPTERS.cursor.frameworkDir, "rules", "global.mdc"),
99
+ path.join(projectRoot, unifiedAdapterPath(UNIFIED_ADAPTER_SLUG.cursor, "rules", "global.mdc")),
100
+ ];
101
+ }
@@ -0,0 +1,72 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { ALL_AGENTS, toAntigravityJson, toClaudeCodeMd, toCodexMd, toCursorMdc, toGeminiCliMd } from "../../modules/agents/definitions.js";
4
+ import { writeTextFile } from "../utils/fs.js";
5
+ import { getPackageRoot } from "../utils/pkg.js";
6
+ import { UI } from "../utils/ui.js";
7
+ import { ADAPTERS } from "./core.js";
8
+ export function scaffoldAgents(projectRoot, adapterId, dryRun, agentsToScaffold, explicitDestDir, explicitExt, paths, backendLanguage, _language) {
9
+ const adapter = ADAPTERS[adapterId];
10
+ if (!adapter)
11
+ return;
12
+ const allowedAgents = agentsToScaffold ? new Set(agentsToScaffold) : undefined;
13
+ const destAgentsDir = explicitDestDir ? path.join(projectRoot, explicitDestDir) : (adapter.agentsDir ? path.join(projectRoot, adapter.agentsDir) : null);
14
+ const extension = explicitExt || adapter.agentsExt || ".md";
15
+ if (!destAgentsDir)
16
+ return;
17
+ const baseKnowledgeDir = path.join(getPackageRoot(), "templates/standards");
18
+ try {
19
+ if (!dryRun)
20
+ fs.mkdirSync(destAgentsDir, { recursive: true });
21
+ for (const agent of ALL_AGENTS) {
22
+ if (allowedAgents && !allowedAgents.has(agent.name))
23
+ continue;
24
+ let content = "";
25
+ let fileName = `${agent.name}${extension}`;
26
+ let secondaryContent = null;
27
+ let secondaryFileName = null;
28
+ switch (adapterId) {
29
+ case "gemini":
30
+ content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
31
+ break;
32
+ case "grok":
33
+ // Grok uses same Gemini-compatible YAML format
34
+ content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
35
+ break;
36
+ case "claude":
37
+ content = toClaudeCodeMd(agent, baseKnowledgeDir, paths, backendLanguage);
38
+ break;
39
+ case "cursor":
40
+ content = toCursorMdc(agent, baseKnowledgeDir, paths, backendLanguage);
41
+ break;
42
+ case "codex":
43
+ content = toCodexMd(agent, baseKnowledgeDir, paths, backendLanguage);
44
+ break;
45
+ case "antigravity-cli": {
46
+ // Antigravity uses nested folders: agents/{name}/agent.json and agents/{name}/agent.md
47
+ const agentDir = path.join(destAgentsDir, agent.name);
48
+ if (!dryRun)
49
+ fs.mkdirSync(agentDir, { recursive: true });
50
+ content = toAntigravityJson(agent, baseKnowledgeDir, paths, backendLanguage);
51
+ fileName = path.join(agent.name, "agent.json");
52
+ secondaryContent = `# [ATABEY] Agent Atabey — @${agent.name}\n\n${agent.instructions.identity}\n\n${agent.instructions.mission}`;
53
+ secondaryFileName = path.join(agent.name, "agent.md");
54
+ break;
55
+ }
56
+ default:
57
+ // Fallback to Gemini format
58
+ content = toGeminiCliMd(agent, baseKnowledgeDir, paths, backendLanguage);
59
+ break;
60
+ }
61
+ if (!dryRun) {
62
+ writeTextFile(path.join(destAgentsDir, fileName), content, dryRun);
63
+ if (secondaryContent && secondaryFileName) {
64
+ writeTextFile(path.join(destAgentsDir, secondaryFileName), secondaryContent, dryRun);
65
+ }
66
+ }
67
+ }
68
+ }
69
+ catch (e) {
70
+ UI.warning(` Failed to scaffold agents for ${adapterId}: ${e}`);
71
+ }
72
+ }