expxagents 0.25.1 → 0.25.2

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 (594) hide show
  1. package/assets/agents/_catalog.yaml +35 -0
  2. package/assets/agents/accounting/accountant.agent.md +41 -0
  3. package/assets/agents/accounting/audit-analyst.agent.md +41 -0
  4. package/assets/agents/accounting/financial-reporting.agent.md +41 -0
  5. package/assets/agents/accounting/fiscal-analyst.agent.md +41 -0
  6. package/assets/agents/accounting/payroll-specialist.agent.md +41 -0
  7. package/assets/agents/accounting/tax-compliance.agent.md +41 -0
  8. package/assets/agents/administrative/document-controller.agent.md +41 -0
  9. package/assets/agents/administrative/office-manager.agent.md +41 -0
  10. package/assets/agents/administrative/process-documentation-officer.agent.md +41 -0
  11. package/assets/agents/administrative/procurement-specialist.agent.md +41 -0
  12. package/assets/agents/board/board-report-writer.agent.md +41 -0
  13. package/assets/agents/board/business-intelligence.agent.md +41 -0
  14. package/assets/agents/board/governance-officer.agent.md +41 -0
  15. package/assets/agents/board/okr-manager.agent.md +41 -0
  16. package/assets/agents/board/risk-analyst.agent.md +41 -0
  17. package/assets/agents/board/strategic-advisor.agent.md +41 -0
  18. package/assets/agents/commercial/account-executive.agent.md +41 -0
  19. package/assets/agents/commercial/crm-manager.agent.md +41 -0
  20. package/assets/agents/commercial/pricing-strategist.agent.md +41 -0
  21. package/assets/agents/commercial/proposal-writer.agent.md +41 -0
  22. package/assets/agents/commercial/sdr.agent.md +41 -0
  23. package/assets/agents/compliance/compliance-officer.agent.md +41 -0
  24. package/assets/agents/compliance/data-privacy-specialist.agent.md +41 -0
  25. package/assets/agents/compliance/internal-auditor.agent.md +41 -0
  26. package/assets/agents/compliance/regulatory-monitor.agent.md +41 -0
  27. package/assets/agents/customer-success/churn-prevention.agent.md +41 -0
  28. package/assets/agents/customer-success/csm.agent.md +41 -0
  29. package/assets/agents/customer-success/expansion-manager.agent.md +41 -0
  30. package/assets/agents/customer-success/nps-analyst.agent.md +41 -0
  31. package/assets/agents/customer-success/renewal-manager.agent.md +41 -0
  32. package/assets/agents/development/android-developer.agent.md +41 -0
  33. package/assets/agents/development/backend-developer.agent.md +42 -0
  34. package/assets/agents/development/business-analyst.agent.md +41 -0
  35. package/assets/agents/development/code-reviewer.agent.md +41 -0
  36. package/assets/agents/development/cross-platform-mobile.agent.md +41 -0
  37. package/assets/agents/development/dba.agent.md +41 -0
  38. package/assets/agents/development/desktop-developer.agent.md +41 -0
  39. package/assets/agents/development/devops-engineer.agent.md +41 -0
  40. package/assets/agents/development/frontend-developer.agent.md +103 -0
  41. package/assets/agents/development/ios-developer.agent.md +41 -0
  42. package/assets/agents/development/product-manager.agent.md +41 -0
  43. package/assets/agents/development/qa-engineer.agent.md +41 -0
  44. package/assets/agents/development/scrum-master.agent.md +41 -0
  45. package/assets/agents/development/security-analyst.agent.md +41 -0
  46. package/assets/agents/development/tech-lead.agent.md +42 -0
  47. package/assets/agents/development/tech-writer.agent.md +41 -0
  48. package/assets/agents/development/ux-design-expert.agent.md +108 -0
  49. package/assets/agents/development/ux-designer.agent.md +41 -0
  50. package/assets/agents/finance/accounts-manager.agent.md +41 -0
  51. package/assets/agents/finance/billing-analyst.agent.md +41 -0
  52. package/assets/agents/finance/budget-planner.agent.md +41 -0
  53. package/assets/agents/finance/financial-controller.agent.md +41 -0
  54. package/assets/agents/hr/benefits-manager.agent.md +41 -0
  55. package/assets/agents/hr/hr-onboarding.agent.md +41 -0
  56. package/assets/agents/hr/interview-coordinator.agent.md +41 -0
  57. package/assets/agents/hr/people-culture.agent.md +41 -0
  58. package/assets/agents/hr/performance-analyst.agent.md +41 -0
  59. package/assets/agents/hr/recruiter.agent.md +41 -0
  60. package/assets/agents/implantation/deployment-manager.agent.md +41 -0
  61. package/assets/agents/implantation/environment-specialist.agent.md +41 -0
  62. package/assets/agents/implantation/go-live-coordinator.agent.md +41 -0
  63. package/assets/agents/implantation/integration-specialist.agent.md +41 -0
  64. package/assets/agents/implantation/migration-specialist.agent.md +41 -0
  65. package/assets/agents/legal/contract-manager.agent.md +41 -0
  66. package/assets/agents/legal/ip-specialist.agent.md +41 -0
  67. package/assets/agents/legal/labor-attorney.agent.md +41 -0
  68. package/assets/agents/legal/legal-counsel.agent.md +41 -0
  69. package/assets/agents/marketing/brand-guardian.agent.md +40 -0
  70. package/assets/agents/marketing/content-creator.agent.md +41 -0
  71. package/assets/agents/marketing/email-marketing.agent.md +41 -0
  72. package/assets/agents/marketing/landing-page-builder.agent.md +138 -0
  73. package/assets/agents/marketing/marketing-analyst.agent.md +41 -0
  74. package/assets/agents/marketing/paid-ads-manager.agent.md +41 -0
  75. package/assets/agents/marketing/seo-specialist.agent.md +41 -0
  76. package/assets/agents/marketing/social-media-manager.agent.md +41 -0
  77. package/assets/agents/rnd/benchmark-analyst.agent.md +41 -0
  78. package/assets/agents/rnd/innovation-scout.agent.md +41 -0
  79. package/assets/agents/rnd/market-researcher.agent.md +41 -0
  80. package/assets/agents/rnd/product-analyst.agent.md +41 -0
  81. package/assets/agents/rnd/prototype-builder.agent.md +41 -0
  82. package/assets/agents/support/knowledge-base-manager.agent.md +41 -0
  83. package/assets/agents/support/l1-support.agent.md +41 -0
  84. package/assets/agents/support/l2-support.agent.md +41 -0
  85. package/assets/agents/support/l3-support.agent.md +41 -0
  86. package/assets/agents/support/sla-monitor.agent.md +41 -0
  87. package/assets/agents/training/assessment-creator.agent.md +41 -0
  88. package/assets/agents/training/onboarding-coach.agent.md +41 -0
  89. package/assets/agents/training/training-designer.agent.md +41 -0
  90. package/assets/agents/training/workshop-facilitator.agent.md +41 -0
  91. package/assets/core/best-practices/_catalog.yaml +91 -0
  92. package/assets/core/best-practices/api-documentation.md +137 -0
  93. package/assets/core/best-practices/blog-post.md +86 -0
  94. package/assets/core/best-practices/blog-seo.md +91 -0
  95. package/assets/core/best-practices/code-review.md +97 -0
  96. package/assets/core/best-practices/copywriting.md +75 -0
  97. package/assets/core/best-practices/data-analysis.md +93 -0
  98. package/assets/core/best-practices/deploy-checklist.md +99 -0
  99. package/assets/core/best-practices/email-newsletter.md +84 -0
  100. package/assets/core/best-practices/email-sales.md +91 -0
  101. package/assets/core/best-practices/fullstack-page-generation.md +936 -0
  102. package/assets/core/best-practices/image-design.md +78 -0
  103. package/assets/core/best-practices/instagram-feed.md +70 -0
  104. package/assets/core/best-practices/instagram-reels.md +75 -0
  105. package/assets/core/best-practices/instagram-stories.md +68 -0
  106. package/assets/core/best-practices/landing-page-react.md +2263 -0
  107. package/assets/core/best-practices/landing-page.md +279 -0
  108. package/assets/core/best-practices/linkedin-article.md +83 -0
  109. package/assets/core/best-practices/linkedin-post.md +84 -0
  110. package/assets/core/best-practices/researching.md +89 -0
  111. package/assets/core/best-practices/review.md +95 -0
  112. package/assets/core/best-practices/sprint-planning.md +91 -0
  113. package/assets/core/best-practices/strategist.md +95 -0
  114. package/assets/core/best-practices/technical-writing.md +104 -0
  115. package/assets/core/best-practices/twitter-post.md +75 -0
  116. package/assets/core/best-practices/twitter-thread.md +92 -0
  117. package/assets/core/best-practices/whatsapp-broadcast.md +95 -0
  118. package/assets/core/best-practices/youtube-script.md +80 -0
  119. package/assets/core/best-practices/youtube-shorts.md +76 -0
  120. package/assets/core/prompts/insight-hunter.prompt.md +62 -0
  121. package/assets/core/runner.pipeline.md +200 -0
  122. package/assets/core/skills.engine.md +65 -0
  123. package/assets/core/solution-architect.agent.md +329 -0
  124. package/assets/mcps/_catalog.yaml +17 -0
  125. package/assets/mcps/figma.mcp.yaml +35 -0
  126. package/assets/mcps/github.mcp.yaml +44 -0
  127. package/assets/mcps/linear.mcp.yaml +37 -0
  128. package/assets/mcps/notion.mcp.yaml +37 -0
  129. package/assets/mcps/pencil.mcp.yaml +32 -0
  130. package/assets/mcps/postgresql.mcp.yaml +39 -0
  131. package/assets/mcps/sentry.mcp.yaml +41 -0
  132. package/assets/mcps/slack.mcp.yaml +37 -0
  133. package/assets/mcps/vercel.mcp.yaml +39 -0
  134. package/assets/templates/_expxagents/_memory/company.md +25 -0
  135. package/assets/templates/_expxagents/_memory/preferences.md +6 -0
  136. package/assets/templates/squads/_memory/memories.md +16 -0
  137. package/dist/dashboard/assets/BufferResource-D79vaoFm.js +185 -0
  138. package/dist/dashboard/assets/CanvasRenderer-BUoxTNKV.js +1 -0
  139. package/dist/dashboard/assets/JarvisView-DSN7xWMz.js +1 -0
  140. package/dist/dashboard/assets/RenderTargetSystem-B7rwTXA1.js +172 -0
  141. package/dist/dashboard/assets/ThreeBackground-BQTdScX-.js +1 -0
  142. package/dist/dashboard/assets/WebGLRenderer-DgdVNsZ9.js +156 -0
  143. package/dist/dashboard/assets/WebGPURenderer-DnQNvjEQ.js +41 -0
  144. package/dist/dashboard/assets/browserAll-Cbsk7DE4.js +14 -0
  145. package/dist/dashboard/assets/index-CrlhoBta.js +783 -0
  146. package/dist/dashboard/assets/index-DtbIzZ5n.css +1 -0
  147. package/dist/dashboard/assets/three-BZk_I9Ly.js +4057 -0
  148. package/dist/dashboard/assets/webworkerAll-BLmfReEj.js +83 -0
  149. package/dist/dashboard/index.html +13 -0
  150. package/dist/server/api/__tests__/cost-routes.test.d.ts +2 -0
  151. package/dist/server/api/__tests__/cost-routes.test.d.ts.map +1 -0
  152. package/dist/server/api/__tests__/cost-routes.test.js +54 -0
  153. package/dist/server/api/__tests__/cost-routes.test.js.map +1 -0
  154. package/dist/server/api/__tests__/files-routes.test.d.ts +2 -0
  155. package/dist/server/api/__tests__/files-routes.test.d.ts.map +1 -0
  156. package/dist/server/api/__tests__/files-routes.test.js +85 -0
  157. package/dist/server/api/__tests__/files-routes.test.js.map +1 -0
  158. package/dist/server/api/__tests__/graph-routes.test.d.ts +2 -0
  159. package/dist/server/api/__tests__/graph-routes.test.d.ts.map +1 -0
  160. package/dist/server/api/__tests__/graph-routes.test.js +105 -0
  161. package/dist/server/api/__tests__/graph-routes.test.js.map +1 -0
  162. package/dist/server/api/__tests__/health-routes.test.d.ts +2 -0
  163. package/dist/server/api/__tests__/health-routes.test.d.ts.map +1 -0
  164. package/dist/server/api/__tests__/health-routes.test.js +22 -0
  165. package/dist/server/api/__tests__/health-routes.test.js.map +1 -0
  166. package/dist/server/api/__tests__/integration-routes.test.d.ts +2 -0
  167. package/dist/server/api/__tests__/integration-routes.test.d.ts.map +1 -0
  168. package/dist/server/api/__tests__/integration-routes.test.js +243 -0
  169. package/dist/server/api/__tests__/integration-routes.test.js.map +1 -0
  170. package/dist/server/api/__tests__/kanban-routes.test.d.ts +2 -0
  171. package/dist/server/api/__tests__/kanban-routes.test.d.ts.map +1 -0
  172. package/dist/server/api/__tests__/kanban-routes.test.js +316 -0
  173. package/dist/server/api/__tests__/kanban-routes.test.js.map +1 -0
  174. package/dist/server/api/__tests__/log-routes.test.d.ts +2 -0
  175. package/dist/server/api/__tests__/log-routes.test.d.ts.map +1 -0
  176. package/dist/server/api/__tests__/log-routes.test.js +35 -0
  177. package/dist/server/api/__tests__/log-routes.test.js.map +1 -0
  178. package/dist/server/api/__tests__/orgchart-routes.test.d.ts +2 -0
  179. package/dist/server/api/__tests__/orgchart-routes.test.d.ts.map +1 -0
  180. package/dist/server/api/__tests__/orgchart-routes.test.js +161 -0
  181. package/dist/server/api/__tests__/orgchart-routes.test.js.map +1 -0
  182. package/dist/server/api/__tests__/settings-routes.test.d.ts +2 -0
  183. package/dist/server/api/__tests__/settings-routes.test.d.ts.map +1 -0
  184. package/dist/server/api/__tests__/settings-routes.test.js +177 -0
  185. package/dist/server/api/__tests__/settings-routes.test.js.map +1 -0
  186. package/dist/server/api/__tests__/system-routes.test.d.ts +2 -0
  187. package/dist/server/api/__tests__/system-routes.test.d.ts.map +1 -0
  188. package/dist/server/api/__tests__/system-routes.test.js +79 -0
  189. package/dist/server/api/__tests__/system-routes.test.js.map +1 -0
  190. package/dist/server/api/__tests__/team-routes.test.d.ts +2 -0
  191. package/dist/server/api/__tests__/team-routes.test.d.ts.map +1 -0
  192. package/dist/server/api/__tests__/team-routes.test.js +116 -0
  193. package/dist/server/api/__tests__/team-routes.test.js.map +1 -0
  194. package/dist/server/api/__tests__/webhook-routes.test.d.ts +2 -0
  195. package/dist/server/api/__tests__/webhook-routes.test.d.ts.map +1 -0
  196. package/dist/server/api/__tests__/webhook-routes.test.js +111 -0
  197. package/dist/server/api/__tests__/webhook-routes.test.js.map +1 -0
  198. package/dist/server/api/activity-routes.d.ts +8 -0
  199. package/dist/server/api/activity-routes.d.ts.map +1 -0
  200. package/dist/server/api/activity-routes.js +34 -0
  201. package/dist/server/api/activity-routes.js.map +1 -0
  202. package/dist/server/api/chat-api-routes.d.ts +4 -0
  203. package/dist/server/api/chat-api-routes.d.ts.map +1 -0
  204. package/dist/server/api/chat-api-routes.js +28 -0
  205. package/dist/server/api/chat-api-routes.js.map +1 -0
  206. package/dist/server/api/cost-routes.d.ts +8 -0
  207. package/dist/server/api/cost-routes.d.ts.map +1 -0
  208. package/dist/server/api/cost-routes.js +39 -0
  209. package/dist/server/api/cost-routes.js.map +1 -0
  210. package/dist/server/api/dashboard-routes.d.ts +10 -0
  211. package/dist/server/api/dashboard-routes.d.ts.map +1 -0
  212. package/dist/server/api/dashboard-routes.js +128 -0
  213. package/dist/server/api/dashboard-routes.js.map +1 -0
  214. package/dist/server/api/files-routes.d.ts +5 -0
  215. package/dist/server/api/files-routes.d.ts.map +1 -0
  216. package/dist/server/api/files-routes.js +218 -0
  217. package/dist/server/api/files-routes.js.map +1 -0
  218. package/dist/server/api/graph-routes.d.ts +24 -0
  219. package/dist/server/api/graph-routes.d.ts.map +1 -0
  220. package/dist/server/api/graph-routes.js +208 -0
  221. package/dist/server/api/graph-routes.js.map +1 -0
  222. package/dist/server/api/health-routes.d.ts +9 -0
  223. package/dist/server/api/health-routes.d.ts.map +1 -0
  224. package/dist/server/api/health-routes.js +46 -0
  225. package/dist/server/api/health-routes.js.map +1 -0
  226. package/dist/server/api/integration-routes.d.ts +23 -0
  227. package/dist/server/api/integration-routes.d.ts.map +1 -0
  228. package/dist/server/api/integration-routes.js +326 -0
  229. package/dist/server/api/integration-routes.js.map +1 -0
  230. package/dist/server/api/kanban-routes.d.ts +8 -0
  231. package/dist/server/api/kanban-routes.d.ts.map +1 -0
  232. package/dist/server/api/kanban-routes.js +128 -0
  233. package/dist/server/api/kanban-routes.js.map +1 -0
  234. package/dist/server/api/knowledge-routes.d.ts +8 -0
  235. package/dist/server/api/knowledge-routes.d.ts.map +1 -0
  236. package/dist/server/api/knowledge-routes.js +82 -0
  237. package/dist/server/api/knowledge-routes.js.map +1 -0
  238. package/dist/server/api/log-routes.d.ts +8 -0
  239. package/dist/server/api/log-routes.d.ts.map +1 -0
  240. package/dist/server/api/log-routes.js +31 -0
  241. package/dist/server/api/log-routes.js.map +1 -0
  242. package/dist/server/api/orgchart-routes.d.ts +7 -0
  243. package/dist/server/api/orgchart-routes.d.ts.map +1 -0
  244. package/dist/server/api/orgchart-routes.js +154 -0
  245. package/dist/server/api/orgchart-routes.js.map +1 -0
  246. package/dist/server/api/permissions-routes.d.ts +8 -0
  247. package/dist/server/api/permissions-routes.d.ts.map +1 -0
  248. package/dist/server/api/permissions-routes.js +37 -0
  249. package/dist/server/api/permissions-routes.js.map +1 -0
  250. package/dist/server/api/registry-routes.d.ts +7 -0
  251. package/dist/server/api/registry-routes.d.ts.map +1 -0
  252. package/dist/server/api/registry-routes.js +51 -0
  253. package/dist/server/api/registry-routes.js.map +1 -0
  254. package/dist/server/api/settings-routes.d.ts +11 -0
  255. package/dist/server/api/settings-routes.d.ts.map +1 -0
  256. package/dist/server/api/settings-routes.js +167 -0
  257. package/dist/server/api/settings-routes.js.map +1 -0
  258. package/dist/server/api/squads-routes.d.ts +9 -0
  259. package/dist/server/api/squads-routes.d.ts.map +1 -0
  260. package/dist/server/api/squads-routes.js +171 -0
  261. package/dist/server/api/squads-routes.js.map +1 -0
  262. package/dist/server/api/system-routes.d.ts +9 -0
  263. package/dist/server/api/system-routes.d.ts.map +1 -0
  264. package/dist/server/api/system-routes.js +241 -0
  265. package/dist/server/api/system-routes.js.map +1 -0
  266. package/dist/server/api/team-routes.d.ts +8 -0
  267. package/dist/server/api/team-routes.d.ts.map +1 -0
  268. package/dist/server/api/team-routes.js +55 -0
  269. package/dist/server/api/team-routes.js.map +1 -0
  270. package/dist/server/api/users-routes.d.ts +8 -0
  271. package/dist/server/api/users-routes.d.ts.map +1 -0
  272. package/dist/server/api/users-routes.js +65 -0
  273. package/dist/server/api/users-routes.js.map +1 -0
  274. package/dist/server/api/webhook-routes.d.ts +9 -0
  275. package/dist/server/api/webhook-routes.d.ts.map +1 -0
  276. package/dist/server/api/webhook-routes.js +82 -0
  277. package/dist/server/api/webhook-routes.js.map +1 -0
  278. package/dist/server/app.d.ts +9 -0
  279. package/dist/server/app.d.ts.map +1 -0
  280. package/dist/server/app.js +265 -0
  281. package/dist/server/app.js.map +1 -0
  282. package/dist/server/auth/auth-middleware.d.ts +13 -0
  283. package/dist/server/auth/auth-middleware.d.ts.map +1 -0
  284. package/dist/server/auth/auth-middleware.js +25 -0
  285. package/dist/server/auth/auth-middleware.js.map +1 -0
  286. package/dist/server/auth/auth-routes.d.ts +9 -0
  287. package/dist/server/auth/auth-routes.d.ts.map +1 -0
  288. package/dist/server/auth/auth-routes.js +152 -0
  289. package/dist/server/auth/auth-routes.js.map +1 -0
  290. package/dist/server/auth/jwt.d.ts +14 -0
  291. package/dist/server/auth/jwt.d.ts.map +1 -0
  292. package/dist/server/auth/jwt.js +16 -0
  293. package/dist/server/auth/jwt.js.map +1 -0
  294. package/dist/server/auth/password.d.ts +3 -0
  295. package/dist/server/auth/password.d.ts.map +1 -0
  296. package/dist/server/auth/password.js +9 -0
  297. package/dist/server/auth/password.js.map +1 -0
  298. package/dist/server/bridge/__tests__/chat-handler.test.d.ts +2 -0
  299. package/dist/server/bridge/__tests__/chat-handler.test.d.ts.map +1 -0
  300. package/dist/server/bridge/__tests__/chat-handler.test.js +143 -0
  301. package/dist/server/bridge/__tests__/chat-handler.test.js.map +1 -0
  302. package/dist/server/bridge/__tests__/chat-integration.test.d.ts +2 -0
  303. package/dist/server/bridge/__tests__/chat-integration.test.d.ts.map +1 -0
  304. package/dist/server/bridge/__tests__/chat-integration.test.js +129 -0
  305. package/dist/server/bridge/__tests__/chat-integration.test.js.map +1 -0
  306. package/dist/server/bridge/__tests__/claude-bridge.test.d.ts +2 -0
  307. package/dist/server/bridge/__tests__/claude-bridge.test.d.ts.map +1 -0
  308. package/dist/server/bridge/__tests__/claude-bridge.test.js +300 -0
  309. package/dist/server/bridge/__tests__/claude-bridge.test.js.map +1 -0
  310. package/dist/server/bridge/__tests__/conversation.test.d.ts +2 -0
  311. package/dist/server/bridge/__tests__/conversation.test.d.ts.map +1 -0
  312. package/dist/server/bridge/__tests__/conversation.test.js +168 -0
  313. package/dist/server/bridge/__tests__/conversation.test.js.map +1 -0
  314. package/dist/server/bridge/__tests__/registry.test.d.ts +2 -0
  315. package/dist/server/bridge/__tests__/registry.test.d.ts.map +1 -0
  316. package/dist/server/bridge/__tests__/registry.test.js +45 -0
  317. package/dist/server/bridge/__tests__/registry.test.js.map +1 -0
  318. package/dist/server/bridge/__tests__/stream-parser.test.d.ts +2 -0
  319. package/dist/server/bridge/__tests__/stream-parser.test.d.ts.map +1 -0
  320. package/dist/server/bridge/__tests__/stream-parser.test.js +66 -0
  321. package/dist/server/bridge/__tests__/stream-parser.test.js.map +1 -0
  322. package/dist/server/bridge/chat-handler.d.ts +32 -0
  323. package/dist/server/bridge/chat-handler.d.ts.map +1 -0
  324. package/dist/server/bridge/chat-handler.js +356 -0
  325. package/dist/server/bridge/chat-handler.js.map +1 -0
  326. package/dist/server/bridge/claude-bridge.d.ts +21 -0
  327. package/dist/server/bridge/claude-bridge.d.ts.map +1 -0
  328. package/dist/server/bridge/claude-bridge.js +273 -0
  329. package/dist/server/bridge/claude-bridge.js.map +1 -0
  330. package/dist/server/bridge/conversation.d.ts +45 -0
  331. package/dist/server/bridge/conversation.d.ts.map +1 -0
  332. package/dist/server/bridge/conversation.js +78 -0
  333. package/dist/server/bridge/conversation.js.map +1 -0
  334. package/dist/server/bridge/engine-manager.d.ts +13 -0
  335. package/dist/server/bridge/engine-manager.d.ts.map +1 -0
  336. package/dist/server/bridge/engine-manager.js +54 -0
  337. package/dist/server/bridge/engine-manager.js.map +1 -0
  338. package/dist/server/bridge/engine.d.ts +37 -0
  339. package/dist/server/bridge/engine.d.ts.map +1 -0
  340. package/dist/server/bridge/engine.js +2 -0
  341. package/dist/server/bridge/engine.js.map +1 -0
  342. package/dist/server/bridge/factory.d.ts +4 -0
  343. package/dist/server/bridge/factory.d.ts.map +1 -0
  344. package/dist/server/bridge/factory.js +18 -0
  345. package/dist/server/bridge/factory.js.map +1 -0
  346. package/dist/server/bridge/opencode-bridge.d.ts +27 -0
  347. package/dist/server/bridge/opencode-bridge.d.ts.map +1 -0
  348. package/dist/server/bridge/opencode-bridge.js +163 -0
  349. package/dist/server/bridge/opencode-bridge.js.map +1 -0
  350. package/dist/server/bridge/registry.d.ts +19 -0
  351. package/dist/server/bridge/registry.d.ts.map +1 -0
  352. package/dist/server/bridge/registry.js +29 -0
  353. package/dist/server/bridge/registry.js.map +1 -0
  354. package/dist/server/bridge/session-journal.d.ts +25 -0
  355. package/dist/server/bridge/session-journal.d.ts.map +1 -0
  356. package/dist/server/bridge/session-journal.js +69 -0
  357. package/dist/server/bridge/session-journal.js.map +1 -0
  358. package/dist/server/bridge/stream-parser.d.ts +14 -0
  359. package/dist/server/bridge/stream-parser.d.ts.map +1 -0
  360. package/dist/server/bridge/stream-parser.js +26 -0
  361. package/dist/server/bridge/stream-parser.js.map +1 -0
  362. package/dist/server/config/engine-config.d.ts +4 -0
  363. package/dist/server/config/engine-config.d.ts.map +1 -0
  364. package/dist/server/config/engine-config.js +24 -0
  365. package/dist/server/config/engine-config.js.map +1 -0
  366. package/dist/server/config.d.ts +17 -0
  367. package/dist/server/config.d.ts.map +1 -0
  368. package/dist/server/config.js +39 -0
  369. package/dist/server/config.js.map +1 -0
  370. package/dist/server/db/__tests__/chat-tables.test.d.ts +2 -0
  371. package/dist/server/db/__tests__/chat-tables.test.d.ts.map +1 -0
  372. package/dist/server/db/__tests__/chat-tables.test.js +82 -0
  373. package/dist/server/db/__tests__/chat-tables.test.js.map +1 -0
  374. package/dist/server/db/__tests__/email-schema.test.d.ts +2 -0
  375. package/dist/server/db/__tests__/email-schema.test.d.ts.map +1 -0
  376. package/dist/server/db/__tests__/email-schema.test.js +53 -0
  377. package/dist/server/db/__tests__/email-schema.test.js.map +1 -0
  378. package/dist/server/db/__tests__/scheduler-schema.test.d.ts +2 -0
  379. package/dist/server/db/__tests__/scheduler-schema.test.d.ts.map +1 -0
  380. package/dist/server/db/__tests__/scheduler-schema.test.js +52 -0
  381. package/dist/server/db/__tests__/scheduler-schema.test.js.map +1 -0
  382. package/dist/server/db/connection.d.ts +4 -0
  383. package/dist/server/db/connection.d.ts.map +1 -0
  384. package/dist/server/db/connection.js +40 -0
  385. package/dist/server/db/connection.js.map +1 -0
  386. package/dist/server/db/migrations.d.ts +4 -0
  387. package/dist/server/db/migrations.d.ts.map +1 -0
  388. package/dist/server/db/migrations.js +47 -0
  389. package/dist/server/db/migrations.js.map +1 -0
  390. package/dist/server/db/schema.d.ts +2 -0
  391. package/dist/server/db/schema.d.ts.map +1 -0
  392. package/dist/server/db/schema.js +288 -0
  393. package/dist/server/db/schema.js.map +1 -0
  394. package/dist/server/email/__tests__/campaign-routes.test.d.ts +2 -0
  395. package/dist/server/email/__tests__/campaign-routes.test.d.ts.map +1 -0
  396. package/dist/server/email/__tests__/campaign-routes.test.js +216 -0
  397. package/dist/server/email/__tests__/campaign-routes.test.js.map +1 -0
  398. package/dist/server/email/__tests__/campaign-service.test.d.ts +2 -0
  399. package/dist/server/email/__tests__/campaign-service.test.d.ts.map +1 -0
  400. package/dist/server/email/__tests__/campaign-service.test.js +79 -0
  401. package/dist/server/email/__tests__/campaign-service.test.js.map +1 -0
  402. package/dist/server/email/__tests__/email-queue-worker.test.d.ts +2 -0
  403. package/dist/server/email/__tests__/email-queue-worker.test.d.ts.map +1 -0
  404. package/dist/server/email/__tests__/email-queue-worker.test.js +93 -0
  405. package/dist/server/email/__tests__/email-queue-worker.test.js.map +1 -0
  406. package/dist/server/email/__tests__/email-utils.test.d.ts +2 -0
  407. package/dist/server/email/__tests__/email-utils.test.d.ts.map +1 -0
  408. package/dist/server/email/__tests__/email-utils.test.js +36 -0
  409. package/dist/server/email/__tests__/email-utils.test.js.map +1 -0
  410. package/dist/server/email/__tests__/lead-routes.test.d.ts +2 -0
  411. package/dist/server/email/__tests__/lead-routes.test.d.ts.map +1 -0
  412. package/dist/server/email/__tests__/lead-routes.test.js +180 -0
  413. package/dist/server/email/__tests__/lead-routes.test.js.map +1 -0
  414. package/dist/server/email/__tests__/lead-service.test.d.ts +2 -0
  415. package/dist/server/email/__tests__/lead-service.test.d.ts.map +1 -0
  416. package/dist/server/email/__tests__/lead-service.test.js +113 -0
  417. package/dist/server/email/__tests__/lead-service.test.js.map +1 -0
  418. package/dist/server/email/__tests__/ses-client.test.d.ts +2 -0
  419. package/dist/server/email/__tests__/ses-client.test.d.ts.map +1 -0
  420. package/dist/server/email/__tests__/ses-client.test.js +48 -0
  421. package/dist/server/email/__tests__/ses-client.test.js.map +1 -0
  422. package/dist/server/email/__tests__/sns-webhook.test.d.ts +2 -0
  423. package/dist/server/email/__tests__/sns-webhook.test.d.ts.map +1 -0
  424. package/dist/server/email/__tests__/sns-webhook.test.js +40 -0
  425. package/dist/server/email/__tests__/sns-webhook.test.js.map +1 -0
  426. package/dist/server/email/campaign-routes.d.ts +8 -0
  427. package/dist/server/email/campaign-routes.d.ts.map +1 -0
  428. package/dist/server/email/campaign-routes.js +65 -0
  429. package/dist/server/email/campaign-routes.js.map +1 -0
  430. package/dist/server/email/campaign-service.d.ts +55 -0
  431. package/dist/server/email/campaign-service.d.ts.map +1 -0
  432. package/dist/server/email/campaign-service.js +89 -0
  433. package/dist/server/email/campaign-service.js.map +1 -0
  434. package/dist/server/email/email-queue-worker.d.ts +27 -0
  435. package/dist/server/email/email-queue-worker.d.ts.map +1 -0
  436. package/dist/server/email/email-queue-worker.js +119 -0
  437. package/dist/server/email/email-queue-worker.js.map +1 -0
  438. package/dist/server/email/email-utils.d.ts +5 -0
  439. package/dist/server/email/email-utils.d.ts.map +1 -0
  440. package/dist/server/email/email-utils.js +24 -0
  441. package/dist/server/email/email-utils.js.map +1 -0
  442. package/dist/server/email/lead-routes.d.ts +8 -0
  443. package/dist/server/email/lead-routes.d.ts.map +1 -0
  444. package/dist/server/email/lead-routes.js +56 -0
  445. package/dist/server/email/lead-routes.js.map +1 -0
  446. package/dist/server/email/lead-service.d.ts +66 -0
  447. package/dist/server/email/lead-service.d.ts.map +1 -0
  448. package/dist/server/email/lead-service.js +138 -0
  449. package/dist/server/email/lead-service.js.map +1 -0
  450. package/dist/server/email/ses-client.d.ts +27 -0
  451. package/dist/server/email/ses-client.d.ts.map +1 -0
  452. package/dist/server/email/ses-client.js +44 -0
  453. package/dist/server/email/ses-client.js.map +1 -0
  454. package/dist/server/email/sns-webhook.d.ts +10 -0
  455. package/dist/server/email/sns-webhook.d.ts.map +1 -0
  456. package/dist/server/email/sns-webhook.js +73 -0
  457. package/dist/server/email/sns-webhook.js.map +1 -0
  458. package/dist/server/index.d.ts +2 -0
  459. package/dist/server/index.d.ts.map +1 -0
  460. package/dist/server/index.js +36 -0
  461. package/dist/server/index.js.map +1 -0
  462. package/dist/server/mcp/expxagents-mcp.d.ts +2 -0
  463. package/dist/server/mcp/expxagents-mcp.d.ts.map +1 -0
  464. package/dist/server/mcp/expxagents-mcp.js +230 -0
  465. package/dist/server/mcp/expxagents-mcp.js.map +1 -0
  466. package/dist/server/routes/__tests__/conversations.test.d.ts +2 -0
  467. package/dist/server/routes/__tests__/conversations.test.d.ts.map +1 -0
  468. package/dist/server/routes/__tests__/conversations.test.js +111 -0
  469. package/dist/server/routes/__tests__/conversations.test.js.map +1 -0
  470. package/dist/server/routes/conversations.d.ts +8 -0
  471. package/dist/server/routes/conversations.d.ts.map +1 -0
  472. package/dist/server/routes/conversations.js +36 -0
  473. package/dist/server/routes/conversations.js.map +1 -0
  474. package/dist/server/scheduler/__tests__/job-runner.test.d.ts +2 -0
  475. package/dist/server/scheduler/__tests__/job-runner.test.d.ts.map +1 -0
  476. package/dist/server/scheduler/__tests__/job-runner.test.js +488 -0
  477. package/dist/server/scheduler/__tests__/job-runner.test.js.map +1 -0
  478. package/dist/server/scheduler/__tests__/scheduler-routes.test.d.ts +2 -0
  479. package/dist/server/scheduler/__tests__/scheduler-routes.test.d.ts.map +1 -0
  480. package/dist/server/scheduler/__tests__/scheduler-routes.test.js +167 -0
  481. package/dist/server/scheduler/__tests__/scheduler-routes.test.js.map +1 -0
  482. package/dist/server/scheduler/__tests__/scheduler-service.test.d.ts +2 -0
  483. package/dist/server/scheduler/__tests__/scheduler-service.test.d.ts.map +1 -0
  484. package/dist/server/scheduler/__tests__/scheduler-service.test.js +207 -0
  485. package/dist/server/scheduler/__tests__/scheduler-service.test.js.map +1 -0
  486. package/dist/server/scheduler/job-runner.d.ts +73 -0
  487. package/dist/server/scheduler/job-runner.d.ts.map +1 -0
  488. package/dist/server/scheduler/job-runner.js +407 -0
  489. package/dist/server/scheduler/job-runner.js.map +1 -0
  490. package/dist/server/scheduler/scheduler-routes.d.ts +10 -0
  491. package/dist/server/scheduler/scheduler-routes.d.ts.map +1 -0
  492. package/dist/server/scheduler/scheduler-routes.js +105 -0
  493. package/dist/server/scheduler/scheduler-routes.js.map +1 -0
  494. package/dist/server/scheduler/scheduler-service.d.ts +55 -0
  495. package/dist/server/scheduler/scheduler-service.d.ts.map +1 -0
  496. package/dist/server/scheduler/scheduler-service.js +271 -0
  497. package/dist/server/scheduler/scheduler-service.js.map +1 -0
  498. package/dist/server/services/__tests__/cost-service.test.d.ts +2 -0
  499. package/dist/server/services/__tests__/cost-service.test.d.ts.map +1 -0
  500. package/dist/server/services/__tests__/cost-service.test.js +72 -0
  501. package/dist/server/services/__tests__/cost-service.test.js.map +1 -0
  502. package/dist/server/services/__tests__/execution-log-service.test.d.ts +2 -0
  503. package/dist/server/services/__tests__/execution-log-service.test.d.ts.map +1 -0
  504. package/dist/server/services/__tests__/execution-log-service.test.js +40 -0
  505. package/dist/server/services/__tests__/execution-log-service.test.js.map +1 -0
  506. package/dist/server/services/__tests__/integration-registry.test.d.ts +2 -0
  507. package/dist/server/services/__tests__/integration-registry.test.d.ts.map +1 -0
  508. package/dist/server/services/__tests__/integration-registry.test.js +28 -0
  509. package/dist/server/services/__tests__/integration-registry.test.js.map +1 -0
  510. package/dist/server/services/__tests__/log-service.test.d.ts +2 -0
  511. package/dist/server/services/__tests__/log-service.test.d.ts.map +1 -0
  512. package/dist/server/services/__tests__/log-service.test.js +49 -0
  513. package/dist/server/services/__tests__/log-service.test.js.map +1 -0
  514. package/dist/server/services/__tests__/permissions-service.test.d.ts +2 -0
  515. package/dist/server/services/__tests__/permissions-service.test.d.ts.map +1 -0
  516. package/dist/server/services/__tests__/permissions-service.test.js +46 -0
  517. package/dist/server/services/__tests__/permissions-service.test.js.map +1 -0
  518. package/dist/server/services/__tests__/pipeline-task-service.test.d.ts +2 -0
  519. package/dist/server/services/__tests__/pipeline-task-service.test.d.ts.map +1 -0
  520. package/dist/server/services/__tests__/pipeline-task-service.test.js +268 -0
  521. package/dist/server/services/__tests__/pipeline-task-service.test.js.map +1 -0
  522. package/dist/server/services/__tests__/state-service.test.d.ts +2 -0
  523. package/dist/server/services/__tests__/state-service.test.d.ts.map +1 -0
  524. package/dist/server/services/__tests__/state-service.test.js +136 -0
  525. package/dist/server/services/__tests__/state-service.test.js.map +1 -0
  526. package/dist/server/services/activity-service.d.ts +35 -0
  527. package/dist/server/services/activity-service.d.ts.map +1 -0
  528. package/dist/server/services/activity-service.js +92 -0
  529. package/dist/server/services/activity-service.js.map +1 -0
  530. package/dist/server/services/cost-service.d.ts +55 -0
  531. package/dist/server/services/cost-service.d.ts.map +1 -0
  532. package/dist/server/services/cost-service.js +59 -0
  533. package/dist/server/services/cost-service.js.map +1 -0
  534. package/dist/server/services/execution-log-service.d.ts +20 -0
  535. package/dist/server/services/execution-log-service.d.ts.map +1 -0
  536. package/dist/server/services/execution-log-service.js +17 -0
  537. package/dist/server/services/execution-log-service.js.map +1 -0
  538. package/dist/server/services/integration-registry.d.ts +9 -0
  539. package/dist/server/services/integration-registry.d.ts.map +1 -0
  540. package/dist/server/services/integration-registry.js +14 -0
  541. package/dist/server/services/integration-registry.js.map +1 -0
  542. package/dist/server/services/log-service.d.ts +28 -0
  543. package/dist/server/services/log-service.d.ts.map +1 -0
  544. package/dist/server/services/log-service.js +34 -0
  545. package/dist/server/services/log-service.js.map +1 -0
  546. package/dist/server/services/permissions-service.d.ts +10 -0
  547. package/dist/server/services/permissions-service.d.ts.map +1 -0
  548. package/dist/server/services/permissions-service.js +48 -0
  549. package/dist/server/services/permissions-service.js.map +1 -0
  550. package/dist/server/services/pipeline-task-service.d.ts +79 -0
  551. package/dist/server/services/pipeline-task-service.d.ts.map +1 -0
  552. package/dist/server/services/pipeline-task-service.js +122 -0
  553. package/dist/server/services/pipeline-task-service.js.map +1 -0
  554. package/dist/server/services/squad-registry.d.ts +35 -0
  555. package/dist/server/services/squad-registry.d.ts.map +1 -0
  556. package/dist/server/services/squad-registry.js +141 -0
  557. package/dist/server/services/squad-registry.js.map +1 -0
  558. package/dist/server/services/state-service.d.ts +22 -0
  559. package/dist/server/services/state-service.d.ts.map +1 -0
  560. package/dist/server/services/state-service.js +114 -0
  561. package/dist/server/services/state-service.js.map +1 -0
  562. package/dist/server/types/a2ui.d.ts +27 -0
  563. package/dist/server/types/a2ui.d.ts.map +1 -0
  564. package/dist/server/types/a2ui.js +2 -0
  565. package/dist/server/types/a2ui.js.map +1 -0
  566. package/dist/server/utils/find-free-port.d.ts +2 -0
  567. package/dist/server/utils/find-free-port.d.ts.map +1 -0
  568. package/dist/server/utils/find-free-port.js +17 -0
  569. package/dist/server/utils/find-free-port.js.map +1 -0
  570. package/dist/server/watcher/__tests__/file-watcher.test.d.ts +2 -0
  571. package/dist/server/watcher/__tests__/file-watcher.test.d.ts.map +1 -0
  572. package/dist/server/watcher/__tests__/file-watcher.test.js +81 -0
  573. package/dist/server/watcher/__tests__/file-watcher.test.js.map +1 -0
  574. package/dist/server/watcher/file-watcher.d.ts +19 -0
  575. package/dist/server/watcher/file-watcher.d.ts.map +1 -0
  576. package/dist/server/watcher/file-watcher.js +105 -0
  577. package/dist/server/watcher/file-watcher.js.map +1 -0
  578. package/dist/server/watcher/state-parser.d.ts +77 -0
  579. package/dist/server/watcher/state-parser.d.ts.map +1 -0
  580. package/dist/server/watcher/state-parser.js +78 -0
  581. package/dist/server/watcher/state-parser.js.map +1 -0
  582. package/dist/server/ws/ws-auth.d.ts +4 -0
  583. package/dist/server/ws/ws-auth.d.ts.map +1 -0
  584. package/dist/server/ws/ws-auth.js +42 -0
  585. package/dist/server/ws/ws-auth.js.map +1 -0
  586. package/dist/server/ws/ws-handler.d.ts +12 -0
  587. package/dist/server/ws/ws-handler.d.ts.map +1 -0
  588. package/dist/server/ws/ws-handler.js +171 -0
  589. package/dist/server/ws/ws-handler.js.map +1 -0
  590. package/dist/server/ws/ws-rooms.d.ts +12 -0
  591. package/dist/server/ws/ws-rooms.d.ts.map +1 -0
  592. package/dist/server/ws/ws-rooms.js +52 -0
  593. package/dist/server/ws/ws-rooms.js.map +1 -0
  594. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orgchart-routes.test.d.ts","sourceRoot":"","sources":["../../../src/api/__tests__/orgchart-routes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,161 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import Fastify from 'fastify';
3
+ import cookie from '@fastify/cookie';
4
+ import Database from 'better-sqlite3';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import os from 'node:os';
8
+ import { orgchartRoutes } from '../orgchart-routes.js';
9
+ import { registerAuthMiddleware } from '../../auth/auth-middleware.js';
10
+ import { authRoutes } from '../../auth/auth-routes.js';
11
+ import { hashPassword } from '../../auth/password.js';
12
+ import { runMigrations } from '../../db/migrations.js';
13
+ const SECRET = 'test-secret-that-is-at-least-32-chars-long!!';
14
+ async function buildApp(db, squadsDir) {
15
+ const app = Fastify();
16
+ await app.register(cookie);
17
+ registerAuthMiddleware(app, SECRET);
18
+ await app.register(authRoutes, { db, jwtSecret: SECRET });
19
+ await app.register(orgchartRoutes, { squadsDir });
20
+ await app.ready();
21
+ return app;
22
+ }
23
+ async function getAuthCookie(app) {
24
+ const res = await app.inject({
25
+ method: 'POST',
26
+ url: '/api/auth/login',
27
+ payload: { username: 'admin', password: 'admin123' },
28
+ });
29
+ const cookies = res.cookies;
30
+ const accessToken = cookies.find(c => c.name === 'access_token');
31
+ return `access_token=${accessToken.value}`;
32
+ }
33
+ describe('orgchart routes', () => {
34
+ let db;
35
+ let app;
36
+ let authCookie;
37
+ let tmpDir;
38
+ let squadsDir;
39
+ beforeEach(async () => {
40
+ db = new Database(':memory:');
41
+ runMigrations(db);
42
+ const hash = await hashPassword('admin123');
43
+ db.prepare("INSERT INTO users (id, username, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?)").run('admin-id', 'admin', hash, 'admin', new Date().toISOString());
44
+ tmpDir = path.join(os.tmpdir(), `orgchart-test-${Date.now()}`);
45
+ squadsDir = path.join(tmpDir, 'squads');
46
+ fs.mkdirSync(squadsDir, { recursive: true });
47
+ // Create company memory
48
+ const memDir = path.join(tmpDir, '_expxagents', '_memory');
49
+ fs.mkdirSync(memDir, { recursive: true });
50
+ fs.writeFileSync(path.join(memDir, 'company.md'), '# TestCorp\nA test company');
51
+ });
52
+ afterEach(async () => {
53
+ await app?.close();
54
+ db?.close();
55
+ fs.rmSync(tmpDir, { recursive: true, force: true });
56
+ });
57
+ it('GET /api/orgchart — returns tree from directory hierarchy', async () => {
58
+ // Create hierarchy: comercial/vendas/hunter-squad
59
+ const setorDir = path.join(squadsDir, 'comercial');
60
+ const grupoDir = path.join(setorDir, 'vendas');
61
+ const squadDir = path.join(grupoDir, 'hunter-squad');
62
+ fs.mkdirSync(squadDir, { recursive: true });
63
+ fs.writeFileSync(path.join(squadDir, 'squad.yaml'), `squad:
64
+ code: hunter-squad
65
+ name: Hunter Squad
66
+ description: Prospecta leads
67
+ icon: rocket
68
+ agents:
69
+ - id: researcher
70
+ name: Researcher
71
+ icon: magnifying-glass
72
+ pipeline:
73
+ steps:
74
+ - id: step-01
75
+ agent: researcher
76
+ label: Research
77
+ `);
78
+ app = await buildApp(db, squadsDir);
79
+ authCookie = await getAuthCookie(app);
80
+ const res = await app.inject({
81
+ method: 'GET', url: '/api/orgchart',
82
+ headers: { cookie: authCookie },
83
+ });
84
+ expect(res.statusCode).toBe(200);
85
+ const body = JSON.parse(res.payload);
86
+ expect(body.tree.name).toBe('TestCorp');
87
+ expect(body.tree.type).toBe('company');
88
+ // Hierarchy: company → setor(comercial) → grupo(vendas) → squad(hunter)
89
+ const setor = body.tree.children[0];
90
+ expect(setor.type).toBe('setor');
91
+ expect(setor.name).toBe('Comercial');
92
+ const grupo = setor.children[0];
93
+ expect(grupo.type).toBe('grupo');
94
+ expect(grupo.name).toBe('Vendas');
95
+ const squad = grupo.children[0];
96
+ expect(squad.type).toBe('squad');
97
+ expect(squad.name).toBe('Hunter Squad');
98
+ });
99
+ it('returns squads directly under squadsDir without hierarchy', async () => {
100
+ const squadDir = path.join(squadsDir, 'alpha-team');
101
+ fs.mkdirSync(squadDir, { recursive: true });
102
+ fs.writeFileSync(path.join(squadDir, 'squad.yaml'), `squad:
103
+ code: alpha-team
104
+ name: Alpha Team
105
+ description: Dev squad
106
+ icon: star
107
+ agents:
108
+ - id: dev
109
+ name: Dev
110
+ icon: code
111
+ pipeline:
112
+ steps:
113
+ - id: step-01
114
+ agent: dev
115
+ label: Build
116
+ `);
117
+ app = await buildApp(db, squadsDir);
118
+ authCookie = await getAuthCookie(app);
119
+ const res = await app.inject({
120
+ method: 'GET', url: '/api/orgchart',
121
+ headers: { cookie: authCookie },
122
+ });
123
+ const body = JSON.parse(res.payload);
124
+ // Squad appears directly under company (no hierarchy levels)
125
+ const squad = body.tree.children[0];
126
+ expect(squad.type).toBe('squad');
127
+ expect(squad.name).toBe('Alpha Team');
128
+ expect(body.squads).toHaveLength(1);
129
+ });
130
+ it('works with empty squads directory', async () => {
131
+ app = await buildApp(db, squadsDir);
132
+ authCookie = await getAuthCookie(app);
133
+ const res = await app.inject({
134
+ method: 'GET', url: '/api/orgchart',
135
+ headers: { cookie: authCookie },
136
+ });
137
+ expect(res.statusCode).toBe(200);
138
+ const body = JSON.parse(res.payload);
139
+ expect(body.tree.children).toEqual([]);
140
+ expect(body.squads).toEqual([]);
141
+ });
142
+ it('defaults company name when no company.md', async () => {
143
+ fs.unlinkSync(path.join(tmpDir, '_expxagents', '_memory', 'company.md'));
144
+ app = await buildApp(db, squadsDir);
145
+ authCookie = await getAuthCookie(app);
146
+ const res = await app.inject({
147
+ method: 'GET', url: '/api/orgchart',
148
+ headers: { cookie: authCookie },
149
+ });
150
+ const body = JSON.parse(res.payload);
151
+ expect(body.tree.name).toBe('Company');
152
+ });
153
+ it('rejects unauthenticated requests', async () => {
154
+ app = await buildApp(db, squadsDir);
155
+ const res = await app.inject({
156
+ method: 'GET', url: '/api/orgchart',
157
+ });
158
+ expect(res.statusCode).toBe(401);
159
+ });
160
+ });
161
+ //# sourceMappingURL=orgchart-routes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orgchart-routes.test.js","sourceRoot":"","sources":["../../../src/api/__tests__/orgchart-routes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=settings-routes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-routes.test.d.ts","sourceRoot":"","sources":["../../../src/api/__tests__/settings-routes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,177 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import Fastify from 'fastify';
3
+ import cookie from '@fastify/cookie';
4
+ import Database from 'better-sqlite3';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import os from 'node:os';
8
+ import { settingsRoutes, parseEnvFile, maskValue } from '../settings-routes.js';
9
+ import { registerAuthMiddleware } from '../../auth/auth-middleware.js';
10
+ import { authRoutes } from '../../auth/auth-routes.js';
11
+ import { hashPassword } from '../../auth/password.js';
12
+ import { runMigrations } from '../../db/migrations.js';
13
+ const SECRET = 'test-secret-that-is-at-least-32-chars-long!!';
14
+ async function buildApp(db) {
15
+ const app = Fastify();
16
+ await app.register(cookie);
17
+ registerAuthMiddleware(app, SECRET);
18
+ await app.register(authRoutes, { db, jwtSecret: SECRET });
19
+ await app.register(settingsRoutes);
20
+ await app.ready();
21
+ return app;
22
+ }
23
+ async function getAuthCookie(app) {
24
+ const res = await app.inject({
25
+ method: 'POST',
26
+ url: '/api/auth/login',
27
+ payload: { username: 'admin', password: 'admin123' },
28
+ });
29
+ const cookies = res.cookies;
30
+ const accessToken = cookies.find(c => c.name === 'access_token');
31
+ return `access_token=${accessToken.value}`;
32
+ }
33
+ describe('settings routes', () => {
34
+ let db;
35
+ let app;
36
+ let authCookie;
37
+ let tmpEnvPath;
38
+ let origDotenvPath;
39
+ beforeEach(async () => {
40
+ db = new Database(':memory:');
41
+ runMigrations(db);
42
+ const hash = await hashPassword('admin123');
43
+ db.prepare("INSERT INTO users (id, username, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?)").run('admin-id', 'admin', hash, 'admin', new Date().toISOString());
44
+ // Create temp .env file
45
+ tmpEnvPath = path.join(os.tmpdir(), `.env-test-${Date.now()}`);
46
+ fs.writeFileSync(tmpEnvPath, 'AWS_REGION=us-east-1\nSES_FROM_EMAIL=test@example.com\nJWT_SECRET=should-not-be-exposed\n');
47
+ origDotenvPath = process.env.DOTENV_PATH;
48
+ process.env.DOTENV_PATH = tmpEnvPath;
49
+ app = await buildApp(db);
50
+ authCookie = await getAuthCookie(app);
51
+ });
52
+ afterEach(async () => {
53
+ await app?.close();
54
+ db?.close();
55
+ if (origDotenvPath !== undefined) {
56
+ process.env.DOTENV_PATH = origDotenvPath;
57
+ }
58
+ else {
59
+ delete process.env.DOTENV_PATH;
60
+ }
61
+ try {
62
+ fs.unlinkSync(tmpEnvPath);
63
+ }
64
+ catch { /* ignore */ }
65
+ });
66
+ it('GET /api/settings/env — returns allowed keys only', async () => {
67
+ const res = await app.inject({
68
+ method: 'GET',
69
+ url: '/api/settings/env',
70
+ headers: { cookie: authCookie },
71
+ });
72
+ expect(res.statusCode).toBe(200);
73
+ const body = JSON.parse(res.payload);
74
+ expect(body.settings.AWS_REGION).toBe('us-east-1');
75
+ expect(body.settings.SES_FROM_EMAIL).toBe('test@example.com');
76
+ // JWT_SECRET should NOT be in the response (not in ALLOWED_KEYS)
77
+ expect(body.settings.JWT_SECRET).toBeUndefined();
78
+ });
79
+ it('GET /api/settings/env — masks secret values', async () => {
80
+ fs.writeFileSync(tmpEnvPath, 'AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE\nAWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n');
81
+ const res = await app.inject({
82
+ method: 'GET',
83
+ url: '/api/settings/env',
84
+ headers: { cookie: authCookie },
85
+ });
86
+ expect(res.statusCode).toBe(200);
87
+ const body = JSON.parse(res.payload);
88
+ expect(body.settings.AWS_ACCESS_KEY_ID).toBe('****MPLE');
89
+ expect(body.settings.AWS_SECRET_ACCESS_KEY).toBe('****EKEY');
90
+ });
91
+ it('PATCH /api/settings/env — updates values', async () => {
92
+ const res = await app.inject({
93
+ method: 'PATCH',
94
+ url: '/api/settings/env',
95
+ headers: { cookie: authCookie },
96
+ payload: { SES_FROM_EMAIL: 'new@example.com', AWS_REGION: 'eu-west-1' },
97
+ });
98
+ expect(res.statusCode).toBe(200);
99
+ const body = JSON.parse(res.payload);
100
+ expect(body.settings.SES_FROM_EMAIL).toBe('new@example.com');
101
+ expect(body.settings.AWS_REGION).toBe('eu-west-1');
102
+ // Verify file was written
103
+ const content = fs.readFileSync(tmpEnvPath, 'utf-8');
104
+ expect(content).toContain('SES_FROM_EMAIL=new@example.com');
105
+ expect(content).toContain('AWS_REGION=eu-west-1');
106
+ // Verify process.env was updated
107
+ expect(process.env.SES_FROM_EMAIL).toBe('new@example.com');
108
+ });
109
+ it('PATCH /api/settings/env — rejects invalid keys', async () => {
110
+ const res = await app.inject({
111
+ method: 'PATCH',
112
+ url: '/api/settings/env',
113
+ headers: { cookie: authCookie },
114
+ payload: { JWT_SECRET: 'hacked', SOME_RANDOM: 'value' },
115
+ });
116
+ expect(res.statusCode).toBe(400);
117
+ expect(JSON.parse(res.payload).error).toContain('Invalid keys');
118
+ });
119
+ it('PATCH /api/settings/env — empty string removes key', async () => {
120
+ await app.inject({
121
+ method: 'PATCH',
122
+ url: '/api/settings/env',
123
+ headers: { cookie: authCookie },
124
+ payload: { SES_FROM_EMAIL: '' },
125
+ });
126
+ const content = fs.readFileSync(tmpEnvPath, 'utf-8');
127
+ expect(content).not.toContain('SES_FROM_EMAIL');
128
+ });
129
+ it('rejects non-admin users', async () => {
130
+ // Create operator user
131
+ const hash = await hashPassword('op123');
132
+ db.prepare("INSERT INTO users (id, username, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?)").run('op-id', 'operator', hash, 'operator', new Date().toISOString());
133
+ const loginRes = await app.inject({
134
+ method: 'POST',
135
+ url: '/api/auth/login',
136
+ payload: { username: 'operator', password: 'op123' },
137
+ });
138
+ const cookies = loginRes.cookies;
139
+ const opCookie = `access_token=${cookies.find(c => c.name === 'access_token').value}`;
140
+ const res = await app.inject({
141
+ method: 'GET',
142
+ url: '/api/settings/env',
143
+ headers: { cookie: opCookie },
144
+ });
145
+ expect(res.statusCode).toBe(403);
146
+ });
147
+ it('rejects unauthenticated requests', async () => {
148
+ const res = await app.inject({
149
+ method: 'GET',
150
+ url: '/api/settings/env',
151
+ });
152
+ expect(res.statusCode).toBe(401);
153
+ });
154
+ });
155
+ describe('parseEnvFile', () => {
156
+ it('parses key=value pairs, skips comments and blanks', () => {
157
+ const tmpFile = path.join(os.tmpdir(), `.env-parse-${Date.now()}`);
158
+ fs.writeFileSync(tmpFile, '# Comment\nKEY1=value1\n\nKEY2=value2\n');
159
+ const result = parseEnvFile(tmpFile);
160
+ expect(result.get('KEY1')).toBe('value1');
161
+ expect(result.get('KEY2')).toBe('value2');
162
+ expect(result.size).toBe(2);
163
+ fs.unlinkSync(tmpFile);
164
+ });
165
+ });
166
+ describe('maskValue', () => {
167
+ it('masks secret keys', () => {
168
+ expect(maskValue('AWS_ACCESS_KEY_ID', 'AKIAIOSFODNN7EXAMPLE')).toBe('****MPLE');
169
+ });
170
+ it('does not mask non-secret keys', () => {
171
+ expect(maskValue('AWS_REGION', 'us-east-1')).toBe('us-east-1');
172
+ });
173
+ it('returns **** for short secrets', () => {
174
+ expect(maskValue('AWS_SECRET_ACCESS_KEY', 'abc')).toBe('****');
175
+ });
176
+ });
177
+ //# sourceMappingURL=settings-routes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-routes.test.js","sourceRoot":"","sources":["../../../src/api/__tests__/settings-routes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=system-routes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-routes.test.d.ts","sourceRoot":"","sources":["../../../src/api/__tests__/system-routes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import Fastify from 'fastify';
3
+ import { systemRoutes } from '../system-routes.js';
4
+ // Mock child_process
5
+ vi.mock('node:child_process', () => ({
6
+ execFile: vi.fn((_cmd, args, _opts, cb) => {
7
+ if (args[0] === 'view' && args[1] === 'expxagents') {
8
+ cb(null, { stdout: '0.15.0\n' });
9
+ }
10
+ else {
11
+ cb(null, { stdout: '' });
12
+ }
13
+ }),
14
+ }));
15
+ // Mock promisify to work with our mock
16
+ vi.mock('node:util', async () => {
17
+ const actual = await vi.importActual('node:util');
18
+ return {
19
+ ...actual,
20
+ promisify: (fn) => {
21
+ return (...args) => {
22
+ return new Promise((resolve, reject) => {
23
+ fn(...args, (err, result) => {
24
+ if (err)
25
+ reject(err);
26
+ else
27
+ resolve(result);
28
+ });
29
+ });
30
+ };
31
+ },
32
+ };
33
+ });
34
+ describe('system-routes', () => {
35
+ let app;
36
+ beforeEach(async () => {
37
+ app = Fastify();
38
+ app.decorate('requireAuth', async () => { });
39
+ await app.register(systemRoutes, { packageVersion: '0.14.2' });
40
+ });
41
+ afterEach(async () => {
42
+ await app.close();
43
+ });
44
+ it('GET /api/system/version should return current and latest versions', async () => {
45
+ const res = await app.inject({ method: 'GET', url: '/api/system/version' });
46
+ expect(res.statusCode).toBe(200);
47
+ const body = res.json();
48
+ expect(body.current).toBe('0.14.2');
49
+ expect(body.latest).toBe('0.15.0');
50
+ expect(body.updateAvailable).toBe(true);
51
+ });
52
+ it('GET /api/system/version should detect no update when current equals latest', async () => {
53
+ await app.close();
54
+ app = Fastify();
55
+ app.decorate('requireAuth', async () => { });
56
+ await app.register(systemRoutes, { packageVersion: '0.15.0' });
57
+ const res = await app.inject({ method: 'GET', url: '/api/system/version' });
58
+ const body = res.json();
59
+ expect(body.updateAvailable).toBe(false);
60
+ });
61
+ it('POST /api/system/update should respond with ok when update available', async () => {
62
+ const res = await app.inject({ method: 'POST', url: '/api/system/update' });
63
+ expect(res.statusCode).toBe(200);
64
+ const body = res.json();
65
+ expect(body.ok).toBe(true);
66
+ expect(body.message).toContain('0.15.0');
67
+ });
68
+ it('POST /api/system/update should respond with not ok when already up to date', async () => {
69
+ await app.close();
70
+ app = Fastify();
71
+ app.decorate('requireAuth', async () => { });
72
+ await app.register(systemRoutes, { packageVersion: '0.15.0' });
73
+ const res = await app.inject({ method: 'POST', url: '/api/system/update' });
74
+ const body = res.json();
75
+ expect(body.ok).toBe(false);
76
+ expect(body.message).toContain('up to date');
77
+ });
78
+ });
79
+ //# sourceMappingURL=system-routes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-routes.test.js","sourceRoot":"","sources":["../../../src/api/__tests__/system-routes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=team-routes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-routes.test.d.ts","sourceRoot":"","sources":["../../../src/api/__tests__/team-routes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,116 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { buildApp } from '../../app.js';
3
+ describe('team routes', () => {
4
+ let app;
5
+ let cookie;
6
+ beforeAll(async () => {
7
+ app = await buildApp({ config: { jwtSecret: 'test-secret-team' } });
8
+ await app.ready();
9
+ // Login as default admin
10
+ const loginRes = await app.inject({
11
+ method: 'POST',
12
+ url: '/api/auth/login',
13
+ payload: { username: 'admin', password: 'admin' },
14
+ });
15
+ const cookies = loginRes.cookies;
16
+ const access = cookies.find((c) => c.name === 'access_token');
17
+ const refresh = cookies.find((c) => c.name === 'refresh_token');
18
+ cookie = `access_token=${access.value}; refresh_token=${refresh.value}`;
19
+ // Clean table from previous runs
20
+ app.db.exec('DELETE FROM team_members');
21
+ });
22
+ afterAll(async () => {
23
+ await app.close();
24
+ });
25
+ it('GET /api/team — returns empty list initially', async () => {
26
+ const res = await app.inject({
27
+ method: 'GET',
28
+ url: '/api/team',
29
+ headers: { cookie },
30
+ });
31
+ expect(res.statusCode).toBe(200);
32
+ const body = res.json();
33
+ expect(body.members).toEqual([]);
34
+ });
35
+ it('POST /api/team — creates a team member', async () => {
36
+ const res = await app.inject({
37
+ method: 'POST',
38
+ url: '/api/team',
39
+ headers: { cookie },
40
+ payload: {
41
+ name: 'Maria Silva',
42
+ role: 'Designer',
43
+ email: 'maria@example.com',
44
+ phone: '+55 11 99999-0000',
45
+ },
46
+ });
47
+ expect(res.statusCode).toBe(201);
48
+ const body = res.json();
49
+ expect(body.member.name).toBe('Maria Silva');
50
+ expect(body.member.role).toBe('Designer');
51
+ expect(body.member.email).toBe('maria@example.com');
52
+ expect(body.member.phone).toBe('+55 11 99999-0000');
53
+ expect(body.member.id).toMatch(/^tm-/);
54
+ });
55
+ it('POST /api/team — rejects missing name', async () => {
56
+ const res = await app.inject({
57
+ method: 'POST',
58
+ url: '/api/team',
59
+ headers: { cookie },
60
+ payload: { role: 'Dev' },
61
+ });
62
+ expect(res.statusCode).toBe(400);
63
+ });
64
+ it('PATCH /api/team/:id — updates a team member', async () => {
65
+ // Create first
66
+ const createRes = await app.inject({
67
+ method: 'POST',
68
+ url: '/api/team',
69
+ headers: { cookie },
70
+ payload: { name: 'Joao', role: 'Dev' },
71
+ });
72
+ const { member } = createRes.json();
73
+ const res = await app.inject({
74
+ method: 'PATCH',
75
+ url: `/api/team/${member.id}`,
76
+ headers: { cookie },
77
+ payload: { role: 'Senior Dev', email: 'joao@test.com' },
78
+ });
79
+ expect(res.statusCode).toBe(200);
80
+ const updated = res.json().member;
81
+ expect(updated.name).toBe('Joao');
82
+ expect(updated.role).toBe('Senior Dev');
83
+ expect(updated.email).toBe('joao@test.com');
84
+ });
85
+ it('DELETE /api/team/:id — deletes a team member', async () => {
86
+ const createRes = await app.inject({
87
+ method: 'POST',
88
+ url: '/api/team',
89
+ headers: { cookie },
90
+ payload: { name: 'Temp User', role: 'Intern' },
91
+ });
92
+ const { member } = createRes.json();
93
+ const res = await app.inject({
94
+ method: 'DELETE',
95
+ url: `/api/team/${member.id}`,
96
+ headers: { cookie },
97
+ });
98
+ expect(res.statusCode).toBe(200);
99
+ expect(res.json().ok).toBe(true);
100
+ // Verify deleted
101
+ const delRes = await app.inject({
102
+ method: 'DELETE',
103
+ url: `/api/team/${member.id}`,
104
+ headers: { cookie },
105
+ });
106
+ expect(delRes.statusCode).toBe(404);
107
+ });
108
+ it('rejects unauthenticated requests', async () => {
109
+ const res = await app.inject({
110
+ method: 'GET',
111
+ url: '/api/team',
112
+ });
113
+ expect(res.statusCode).toBe(401);
114
+ });
115
+ });
116
+ //# sourceMappingURL=team-routes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-routes.test.js","sourceRoot":"","sources":["../../../src/api/__tests__/team-routes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=webhook-routes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-routes.test.d.ts","sourceRoot":"","sources":["../../../src/api/__tests__/webhook-routes.test.ts"],"names":[],"mappings":""}