@agent-relay/cloud 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/dist/api/admin.d.ts +8 -0
  2. package/dist/api/admin.d.ts.map +1 -0
  3. package/dist/api/admin.js +225 -0
  4. package/dist/api/admin.js.map +1 -0
  5. package/dist/api/auth.d.ts +20 -0
  6. package/dist/api/auth.d.ts.map +1 -0
  7. package/dist/api/auth.js +136 -0
  8. package/dist/api/auth.js.map +1 -0
  9. package/dist/api/billing.d.ts +7 -0
  10. package/dist/api/billing.d.ts.map +1 -0
  11. package/dist/api/billing.js +564 -0
  12. package/dist/api/billing.js.map +1 -0
  13. package/dist/api/cli-pty-runner.d.ts +53 -0
  14. package/dist/api/cli-pty-runner.d.ts.map +1 -0
  15. package/dist/api/cli-pty-runner.js +193 -0
  16. package/dist/api/cli-pty-runner.js.map +1 -0
  17. package/dist/api/codex-auth-helper.d.ts +21 -0
  18. package/dist/api/codex-auth-helper.d.ts.map +1 -0
  19. package/dist/api/codex-auth-helper.js +327 -0
  20. package/dist/api/codex-auth-helper.js.map +1 -0
  21. package/dist/api/consensus.d.ts +13 -0
  22. package/dist/api/consensus.d.ts.map +1 -0
  23. package/dist/api/consensus.js +261 -0
  24. package/dist/api/consensus.js.map +1 -0
  25. package/dist/api/coordinators.d.ts +8 -0
  26. package/dist/api/coordinators.d.ts.map +1 -0
  27. package/dist/api/coordinators.js +750 -0
  28. package/dist/api/coordinators.js.map +1 -0
  29. package/dist/api/daemons.d.ts +12 -0
  30. package/dist/api/daemons.d.ts.map +1 -0
  31. package/dist/api/daemons.js +535 -0
  32. package/dist/api/daemons.js.map +1 -0
  33. package/dist/api/generic-webhooks.d.ts +8 -0
  34. package/dist/api/generic-webhooks.d.ts.map +1 -0
  35. package/dist/api/generic-webhooks.js +129 -0
  36. package/dist/api/generic-webhooks.js.map +1 -0
  37. package/dist/api/git.d.ts +8 -0
  38. package/dist/api/git.d.ts.map +1 -0
  39. package/dist/api/git.js +269 -0
  40. package/dist/api/git.js.map +1 -0
  41. package/dist/api/github-app.d.ts +11 -0
  42. package/dist/api/github-app.d.ts.map +1 -0
  43. package/dist/api/github-app.js +223 -0
  44. package/dist/api/github-app.js.map +1 -0
  45. package/dist/api/middleware/planLimits.d.ts +43 -0
  46. package/dist/api/middleware/planLimits.d.ts.map +1 -0
  47. package/dist/api/middleware/planLimits.js +202 -0
  48. package/dist/api/middleware/planLimits.js.map +1 -0
  49. package/dist/api/monitoring.d.ts +11 -0
  50. package/dist/api/monitoring.d.ts.map +1 -0
  51. package/dist/api/monitoring.js +578 -0
  52. package/dist/api/monitoring.js.map +1 -0
  53. package/dist/api/nango-auth.d.ts +9 -0
  54. package/dist/api/nango-auth.d.ts.map +1 -0
  55. package/dist/api/nango-auth.js +674 -0
  56. package/dist/api/nango-auth.js.map +1 -0
  57. package/dist/api/onboarding.d.ts +15 -0
  58. package/dist/api/onboarding.d.ts.map +1 -0
  59. package/dist/api/onboarding.js +679 -0
  60. package/dist/api/onboarding.js.map +1 -0
  61. package/dist/api/policy.d.ts +8 -0
  62. package/dist/api/policy.d.ts.map +1 -0
  63. package/dist/api/policy.js +229 -0
  64. package/dist/api/policy.js.map +1 -0
  65. package/dist/api/provider-env.d.ts +14 -0
  66. package/dist/api/provider-env.d.ts.map +1 -0
  67. package/dist/api/provider-env.js +75 -0
  68. package/dist/api/provider-env.js.map +1 -0
  69. package/dist/api/providers.d.ts +7 -0
  70. package/dist/api/providers.d.ts.map +1 -0
  71. package/dist/api/providers.js +564 -0
  72. package/dist/api/providers.js.map +1 -0
  73. package/dist/api/repos.d.ts +8 -0
  74. package/dist/api/repos.d.ts.map +1 -0
  75. package/dist/api/repos.js +577 -0
  76. package/dist/api/repos.js.map +1 -0
  77. package/dist/api/sessions.d.ts +11 -0
  78. package/dist/api/sessions.d.ts.map +1 -0
  79. package/dist/api/sessions.js +302 -0
  80. package/dist/api/sessions.js.map +1 -0
  81. package/dist/api/teams.d.ts +7 -0
  82. package/dist/api/teams.d.ts.map +1 -0
  83. package/dist/api/teams.js +281 -0
  84. package/dist/api/teams.js.map +1 -0
  85. package/dist/api/test-helpers.d.ts +10 -0
  86. package/dist/api/test-helpers.d.ts.map +1 -0
  87. package/dist/api/test-helpers.js +745 -0
  88. package/dist/api/test-helpers.js.map +1 -0
  89. package/dist/api/usage.d.ts +7 -0
  90. package/dist/api/usage.d.ts.map +1 -0
  91. package/dist/api/usage.js +111 -0
  92. package/dist/api/usage.js.map +1 -0
  93. package/dist/api/webhooks.d.ts +8 -0
  94. package/dist/api/webhooks.d.ts.map +1 -0
  95. package/dist/api/webhooks.js +645 -0
  96. package/dist/api/webhooks.js.map +1 -0
  97. package/dist/api/workspaces.d.ts +25 -0
  98. package/dist/api/workspaces.d.ts.map +1 -0
  99. package/dist/api/workspaces.js +1799 -0
  100. package/dist/api/workspaces.js.map +1 -0
  101. package/dist/billing/index.d.ts +9 -0
  102. package/dist/billing/index.d.ts.map +1 -0
  103. package/dist/billing/index.js +9 -0
  104. package/dist/billing/index.js.map +1 -0
  105. package/dist/billing/plans.d.ts +39 -0
  106. package/dist/billing/plans.d.ts.map +1 -0
  107. package/dist/billing/plans.js +245 -0
  108. package/dist/billing/plans.js.map +1 -0
  109. package/dist/billing/service.d.ts +80 -0
  110. package/dist/billing/service.d.ts.map +1 -0
  111. package/dist/billing/service.js +388 -0
  112. package/dist/billing/service.js.map +1 -0
  113. package/dist/billing/types.d.ts +141 -0
  114. package/dist/billing/types.d.ts.map +1 -0
  115. package/dist/billing/types.js +7 -0
  116. package/dist/billing/types.js.map +1 -0
  117. package/dist/config.d.ts +5 -0
  118. package/dist/config.d.ts.map +1 -0
  119. package/dist/config.js +5 -0
  120. package/dist/config.js.map +1 -0
  121. package/dist/db/bulk-ingest.d.ts +89 -0
  122. package/dist/db/bulk-ingest.d.ts.map +1 -0
  123. package/dist/db/bulk-ingest.js +268 -0
  124. package/dist/db/bulk-ingest.js.map +1 -0
  125. package/dist/db/drizzle.d.ts +256 -0
  126. package/dist/db/drizzle.d.ts.map +1 -0
  127. package/dist/db/drizzle.js +1286 -0
  128. package/dist/db/drizzle.js.map +1 -0
  129. package/dist/db/index.d.ts +55 -0
  130. package/dist/db/index.d.ts.map +1 -0
  131. package/dist/db/index.js +68 -0
  132. package/dist/db/index.js.map +1 -0
  133. package/dist/db/schema.d.ts +4873 -0
  134. package/dist/db/schema.d.ts.map +1 -0
  135. package/dist/db/schema.js +620 -0
  136. package/dist/db/schema.js.map +1 -0
  137. package/dist/index.d.ts +11 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +38 -0
  140. package/dist/index.js.map +1 -0
  141. package/dist/provisioner/index.d.ts +207 -0
  142. package/dist/provisioner/index.d.ts.map +1 -0
  143. package/dist/provisioner/index.js +2114 -0
  144. package/dist/provisioner/index.js.map +1 -0
  145. package/dist/server.d.ts +17 -0
  146. package/dist/server.d.ts.map +1 -0
  147. package/dist/server.js +1924 -0
  148. package/dist/server.js.map +1 -0
  149. package/dist/services/auto-scaler.d.ts +152 -0
  150. package/dist/services/auto-scaler.d.ts.map +1 -0
  151. package/dist/services/auto-scaler.js +439 -0
  152. package/dist/services/auto-scaler.js.map +1 -0
  153. package/dist/services/capacity-manager.d.ts +148 -0
  154. package/dist/services/capacity-manager.d.ts.map +1 -0
  155. package/dist/services/capacity-manager.js +449 -0
  156. package/dist/services/capacity-manager.js.map +1 -0
  157. package/dist/services/ci-agent-spawner.d.ts +49 -0
  158. package/dist/services/ci-agent-spawner.d.ts.map +1 -0
  159. package/dist/services/ci-agent-spawner.js +373 -0
  160. package/dist/services/ci-agent-spawner.js.map +1 -0
  161. package/dist/services/cloud-message-bus.d.ts +28 -0
  162. package/dist/services/cloud-message-bus.d.ts.map +1 -0
  163. package/dist/services/cloud-message-bus.js +19 -0
  164. package/dist/services/cloud-message-bus.js.map +1 -0
  165. package/dist/services/compute-enforcement.d.ts +57 -0
  166. package/dist/services/compute-enforcement.d.ts.map +1 -0
  167. package/dist/services/compute-enforcement.js +175 -0
  168. package/dist/services/compute-enforcement.js.map +1 -0
  169. package/dist/services/coordinator.d.ts +62 -0
  170. package/dist/services/coordinator.d.ts.map +1 -0
  171. package/dist/services/coordinator.js +389 -0
  172. package/dist/services/coordinator.js.map +1 -0
  173. package/dist/services/index.d.ts +17 -0
  174. package/dist/services/index.d.ts.map +1 -0
  175. package/dist/services/index.js +25 -0
  176. package/dist/services/index.js.map +1 -0
  177. package/dist/services/intro-expiration.d.ts +60 -0
  178. package/dist/services/intro-expiration.d.ts.map +1 -0
  179. package/dist/services/intro-expiration.js +252 -0
  180. package/dist/services/intro-expiration.js.map +1 -0
  181. package/dist/services/mention-handler.d.ts +65 -0
  182. package/dist/services/mention-handler.d.ts.map +1 -0
  183. package/dist/services/mention-handler.js +405 -0
  184. package/dist/services/mention-handler.js.map +1 -0
  185. package/dist/services/nango.d.ts +201 -0
  186. package/dist/services/nango.d.ts.map +1 -0
  187. package/dist/services/nango.js +392 -0
  188. package/dist/services/nango.js.map +1 -0
  189. package/dist/services/persistence.d.ts +131 -0
  190. package/dist/services/persistence.d.ts.map +1 -0
  191. package/dist/services/persistence.js +200 -0
  192. package/dist/services/persistence.js.map +1 -0
  193. package/dist/services/planLimits.d.ts +147 -0
  194. package/dist/services/planLimits.d.ts.map +1 -0
  195. package/dist/services/planLimits.js +335 -0
  196. package/dist/services/planLimits.js.map +1 -0
  197. package/dist/services/presence-registry.d.ts +56 -0
  198. package/dist/services/presence-registry.d.ts.map +1 -0
  199. package/dist/services/presence-registry.js +91 -0
  200. package/dist/services/presence-registry.js.map +1 -0
  201. package/dist/services/scaling-orchestrator.d.ts +159 -0
  202. package/dist/services/scaling-orchestrator.d.ts.map +1 -0
  203. package/dist/services/scaling-orchestrator.js +502 -0
  204. package/dist/services/scaling-orchestrator.js.map +1 -0
  205. package/dist/services/scaling-policy.d.ts +121 -0
  206. package/dist/services/scaling-policy.d.ts.map +1 -0
  207. package/dist/services/scaling-policy.js +415 -0
  208. package/dist/services/scaling-policy.js.map +1 -0
  209. package/dist/services/ssh-security.d.ts +31 -0
  210. package/dist/services/ssh-security.d.ts.map +1 -0
  211. package/dist/services/ssh-security.js +63 -0
  212. package/dist/services/ssh-security.js.map +1 -0
  213. package/dist/services/workspace-keepalive.d.ts +76 -0
  214. package/dist/services/workspace-keepalive.d.ts.map +1 -0
  215. package/dist/services/workspace-keepalive.js +234 -0
  216. package/dist/services/workspace-keepalive.js.map +1 -0
  217. package/dist/shims/consensus.d.ts +23 -0
  218. package/dist/shims/consensus.d.ts.map +1 -0
  219. package/dist/shims/consensus.js +5 -0
  220. package/dist/shims/consensus.js.map +1 -0
  221. package/dist/webhooks/index.d.ts +24 -0
  222. package/dist/webhooks/index.d.ts.map +1 -0
  223. package/dist/webhooks/index.js +29 -0
  224. package/dist/webhooks/index.js.map +1 -0
  225. package/dist/webhooks/parsers/github.d.ts +8 -0
  226. package/dist/webhooks/parsers/github.d.ts.map +1 -0
  227. package/dist/webhooks/parsers/github.js +234 -0
  228. package/dist/webhooks/parsers/github.js.map +1 -0
  229. package/dist/webhooks/parsers/index.d.ts +23 -0
  230. package/dist/webhooks/parsers/index.d.ts.map +1 -0
  231. package/dist/webhooks/parsers/index.js +30 -0
  232. package/dist/webhooks/parsers/index.js.map +1 -0
  233. package/dist/webhooks/parsers/linear.d.ts +9 -0
  234. package/dist/webhooks/parsers/linear.d.ts.map +1 -0
  235. package/dist/webhooks/parsers/linear.js +258 -0
  236. package/dist/webhooks/parsers/linear.js.map +1 -0
  237. package/dist/webhooks/parsers/slack.d.ts +9 -0
  238. package/dist/webhooks/parsers/slack.d.ts.map +1 -0
  239. package/dist/webhooks/parsers/slack.js +214 -0
  240. package/dist/webhooks/parsers/slack.js.map +1 -0
  241. package/dist/webhooks/responders/github.d.ts +8 -0
  242. package/dist/webhooks/responders/github.d.ts.map +1 -0
  243. package/dist/webhooks/responders/github.js +73 -0
  244. package/dist/webhooks/responders/github.js.map +1 -0
  245. package/dist/webhooks/responders/index.d.ts +23 -0
  246. package/dist/webhooks/responders/index.d.ts.map +1 -0
  247. package/dist/webhooks/responders/index.js +30 -0
  248. package/dist/webhooks/responders/index.js.map +1 -0
  249. package/dist/webhooks/responders/linear.d.ts +9 -0
  250. package/dist/webhooks/responders/linear.d.ts.map +1 -0
  251. package/dist/webhooks/responders/linear.js +149 -0
  252. package/dist/webhooks/responders/linear.js.map +1 -0
  253. package/dist/webhooks/responders/slack.d.ts +20 -0
  254. package/dist/webhooks/responders/slack.d.ts.map +1 -0
  255. package/dist/webhooks/responders/slack.js +178 -0
  256. package/dist/webhooks/responders/slack.js.map +1 -0
  257. package/dist/webhooks/router.d.ts +25 -0
  258. package/dist/webhooks/router.d.ts.map +1 -0
  259. package/dist/webhooks/router.js +504 -0
  260. package/dist/webhooks/router.js.map +1 -0
  261. package/dist/webhooks/rules-engine.d.ts +24 -0
  262. package/dist/webhooks/rules-engine.d.ts.map +1 -0
  263. package/dist/webhooks/rules-engine.js +287 -0
  264. package/dist/webhooks/rules-engine.js.map +1 -0
  265. package/dist/webhooks/types.d.ts +186 -0
  266. package/dist/webhooks/types.d.ts.map +1 -0
  267. package/dist/webhooks/types.js +8 -0
  268. package/dist/webhooks/types.js.map +1 -0
  269. package/package.json +55 -0
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Compute Enforcement Service
3
+ *
4
+ * Enforces compute hour limits for free tier users.
5
+ * Runs periodically to check usage and stop workspaces that have exceeded limits.
6
+ */
7
+ import { db } from '../db/index.js';
8
+ import { getProvisioner } from '../provisioner/index.js';
9
+ import { getUserUsage, PLAN_LIMITS } from './planLimits.js';
10
+ const DEFAULT_CONFIG = {
11
+ enabled: true,
12
+ checkIntervalMs: 15 * 60 * 1000, // 15 minutes
13
+ warningThresholdPercent: 80,
14
+ };
15
+ export class ComputeEnforcementService {
16
+ config;
17
+ checkTimer = null;
18
+ isRunning = false;
19
+ constructor(config = {}) {
20
+ this.config = { ...DEFAULT_CONFIG, ...config };
21
+ }
22
+ /**
23
+ * Start the enforcement service
24
+ */
25
+ start() {
26
+ if (!this.config.enabled) {
27
+ console.log('[compute-enforcement] Service disabled');
28
+ return;
29
+ }
30
+ if (this.isRunning) {
31
+ console.warn('[compute-enforcement] Service already running');
32
+ return;
33
+ }
34
+ this.isRunning = true;
35
+ console.log(`[compute-enforcement] Started (checking every ${this.config.checkIntervalMs / 1000}s)`);
36
+ // Run immediately on start
37
+ this.runEnforcement().catch((err) => {
38
+ console.error('[compute-enforcement] Initial run failed:', err);
39
+ });
40
+ // Then run periodically
41
+ this.checkTimer = setInterval(() => {
42
+ this.runEnforcement().catch((err) => {
43
+ console.error('[compute-enforcement] Periodic run failed:', err);
44
+ });
45
+ }, this.config.checkIntervalMs);
46
+ }
47
+ /**
48
+ * Stop the enforcement service
49
+ */
50
+ stop() {
51
+ if (this.checkTimer) {
52
+ clearInterval(this.checkTimer);
53
+ this.checkTimer = null;
54
+ }
55
+ this.isRunning = false;
56
+ console.log('[compute-enforcement] Stopped');
57
+ }
58
+ /**
59
+ * Run enforcement check for all free tier users
60
+ */
61
+ async runEnforcement() {
62
+ const results = [];
63
+ try {
64
+ // Get all users on free tier
65
+ const freeUsers = await db.users.findByPlan('free');
66
+ console.log(`[compute-enforcement] Checking ${freeUsers.length} free tier users`);
67
+ for (const user of freeUsers) {
68
+ try {
69
+ const result = await this.enforceUserLimits(user.id);
70
+ results.push(result);
71
+ if (result.action !== 'none') {
72
+ console.log(`[compute-enforcement] User ${user.id.substring(0, 8)}: ${result.action} ` +
73
+ `(${result.computeHoursUsed.toFixed(2)}/${result.computeHoursLimit}h)`);
74
+ }
75
+ }
76
+ catch (err) {
77
+ console.error(`[compute-enforcement] Error for user ${user.id}:`, err);
78
+ }
79
+ }
80
+ const stopped = results.filter((r) => r.action === 'stopped').length;
81
+ const warned = results.filter((r) => r.action === 'warning').length;
82
+ if (stopped > 0 || warned > 0) {
83
+ console.log(`[compute-enforcement] Summary: ${stopped} stopped, ${warned} warned, ` +
84
+ `${results.length - stopped - warned} ok`);
85
+ }
86
+ }
87
+ catch (err) {
88
+ console.error('[compute-enforcement] Failed to run enforcement:', err);
89
+ }
90
+ return results;
91
+ }
92
+ /**
93
+ * Enforce limits for a specific user
94
+ */
95
+ async enforceUserLimits(userId) {
96
+ const user = await db.users.findById(userId);
97
+ const plan = user?.plan || 'free';
98
+ const limits = PLAN_LIMITS[plan];
99
+ const usage = await getUserUsage(userId);
100
+ const result = {
101
+ userId,
102
+ plan,
103
+ computeHoursUsed: usage.computeHoursThisMonth,
104
+ computeHoursLimit: limits.maxComputeHoursPerMonth,
105
+ action: 'none',
106
+ workspacesStopped: [],
107
+ };
108
+ // Skip if user has unlimited compute (paid plans may have high limits)
109
+ if (limits.maxComputeHoursPerMonth === Infinity) {
110
+ return result;
111
+ }
112
+ // Check if user has exceeded limit
113
+ if (usage.computeHoursThisMonth >= limits.maxComputeHoursPerMonth) {
114
+ // Stop all running workspaces
115
+ const workspaces = await db.workspaces.findByUserId(userId);
116
+ const runningWorkspaces = workspaces.filter((w) => w.status === 'running');
117
+ if (runningWorkspaces.length > 0) {
118
+ const provisioner = getProvisioner();
119
+ for (const workspace of runningWorkspaces) {
120
+ try {
121
+ await provisioner.stop(workspace.id);
122
+ result.workspacesStopped.push(workspace.id);
123
+ console.log(`[compute-enforcement] Stopped workspace ${workspace.id.substring(0, 8)} ` +
124
+ `for user ${userId.substring(0, 8)} (limit exceeded)`);
125
+ }
126
+ catch (err) {
127
+ console.error(`[compute-enforcement] Failed to stop workspace ${workspace.id}:`, err);
128
+ }
129
+ }
130
+ result.action = 'stopped';
131
+ // TODO: Send notification email to user
132
+ // await sendLimitReachedEmail(userId, usage.computeHoursThisMonth, limits.maxComputeHoursPerMonth);
133
+ }
134
+ }
135
+ else {
136
+ // Check if approaching limit (warning)
137
+ const usagePercent = (usage.computeHoursThisMonth / limits.maxComputeHoursPerMonth) * 100;
138
+ if (usagePercent >= this.config.warningThresholdPercent) {
139
+ result.action = 'warning';
140
+ // TODO: Send warning email to user (once per day)
141
+ // await sendLimitWarningEmail(userId, usage.computeHoursThisMonth, limits.maxComputeHoursPerMonth);
142
+ }
143
+ }
144
+ return result;
145
+ }
146
+ /**
147
+ * Manually trigger enforcement for a specific user
148
+ */
149
+ async enforceUser(userId) {
150
+ return this.enforceUserLimits(userId);
151
+ }
152
+ /**
153
+ * Get service status
154
+ */
155
+ getStatus() {
156
+ return {
157
+ enabled: this.config.enabled,
158
+ isRunning: this.isRunning,
159
+ checkIntervalMs: this.config.checkIntervalMs,
160
+ };
161
+ }
162
+ }
163
+ // Singleton instance
164
+ let _computeEnforcement = null;
165
+ export function getComputeEnforcementService() {
166
+ if (!_computeEnforcement) {
167
+ _computeEnforcement = new ComputeEnforcementService();
168
+ }
169
+ return _computeEnforcement;
170
+ }
171
+ export function createComputeEnforcementService(config = {}) {
172
+ _computeEnforcement = new ComputeEnforcementService(config);
173
+ return _computeEnforcement;
174
+ }
175
+ //# sourceMappingURL=compute-enforcement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-enforcement.js","sourceRoot":"","sources":["../../src/services/compute-enforcement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Coordinator Agent Service
3
+ *
4
+ * Manages lifecycle of coordinator agents for project groups.
5
+ * Coordinators oversee and orchestrate work across repositories in a group.
6
+ */
7
+ import { Repository } from '../db/index.js';
8
+ /**
9
+ * Coordinator agent state
10
+ */
11
+ interface CoordinatorState {
12
+ groupId: string;
13
+ groupName: string;
14
+ agentName: string;
15
+ model: string;
16
+ status: 'starting' | 'running' | 'stopping' | 'stopped' | 'error';
17
+ startedAt?: Date;
18
+ stoppedAt?: Date;
19
+ error?: string;
20
+ repositories: Repository[];
21
+ }
22
+ export interface CoordinatorService {
23
+ start(groupId: string): Promise<void>;
24
+ stop(groupId: string): Promise<void>;
25
+ restart(groupId: string): Promise<void>;
26
+ getStatus(groupId: string): Promise<CoordinatorState | null>;
27
+ listActive(): Promise<CoordinatorState[]>;
28
+ }
29
+ /**
30
+ * Send a message from coordinator to a workspace
31
+ */
32
+ export declare function sendToWorkspace(coordinatorGroupId: string, targetWorkspaceId: string, agentName: string, message: string, thread?: string): Promise<void>;
33
+ /**
34
+ * Broadcast a message to all workspaces in a project group
35
+ */
36
+ export declare function broadcastToGroup(coordinatorGroupId: string, message: string, thread?: string): Promise<void>;
37
+ /**
38
+ * Route a message from a workspace to the coordinator
39
+ */
40
+ export declare function routeToCoordinator(workspaceId: string, agentName: string, message: string, thread?: string): Promise<void>;
41
+ /**
42
+ * Get all active coordinators
43
+ */
44
+ export declare function getActiveCoordinators(): Promise<Array<{
45
+ groupId: string;
46
+ groupName: string;
47
+ agentName: string;
48
+ model: string;
49
+ startedAt: string;
50
+ workspaces: string[];
51
+ }>>;
52
+ /**
53
+ * Get the coordinator service singleton
54
+ */
55
+ export declare function getCoordinatorService(): CoordinatorService;
56
+ /**
57
+ * Initialize coordinator service
58
+ * Restarts any coordinators that should be running
59
+ */
60
+ export declare function initializeCoordinatorService(): Promise<void>;
61
+ export {};
62
+ //# sourceMappingURL=coordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../src/services/coordinator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAoB,UAAU,EAA0B,MAAM,gBAAgB,CAAC;AAItF;;GAEG;AACH,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;IAClE,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,UAAU,EAAE,CAAC;CAC5B;AAQD,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC7D,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CAC3C;AAmLD;;GAEG;AACH,wBAAsB,eAAe,CACnC,kBAAkB,EAAE,MAAM,EAC1B,iBAAiB,EAAE,MAAM,EACzB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAqCf;AAyED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,KAAK,CAAC;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC,CAAC,CAyBF;AA+CD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,kBAAkB,CAW1D;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAUlE"}
@@ -0,0 +1,389 @@
1
+ /**
2
+ * Coordinator Agent Service
3
+ *
4
+ * Manages lifecycle of coordinator agents for project groups.
5
+ * Coordinators oversee and orchestrate work across repositories in a group.
6
+ */
7
+ import { db } from '../db/index.js';
8
+ import { createClient } from 'redis';
9
+ import { getConfig } from '../config.js';
10
+ /**
11
+ * In-memory coordinator state tracker
12
+ * In production, this would be persisted to database or Redis
13
+ */
14
+ const coordinatorStates = new Map();
15
+ /**
16
+ * Start a coordinator agent for a project group
17
+ */
18
+ async function start(groupId) {
19
+ const group = await db.projectGroups.findById(groupId);
20
+ if (!group) {
21
+ throw new Error('Project group not found');
22
+ }
23
+ if (!group.coordinatorAgent?.enabled) {
24
+ throw new Error('Coordinator is not enabled for this group');
25
+ }
26
+ const repositories = await db.repositories.findByProjectGroupId(groupId);
27
+ if (repositories.length === 0) {
28
+ throw new Error('Cannot start coordinator for empty group');
29
+ }
30
+ const config = group.coordinatorAgent;
31
+ const agentName = config.name || `${group.name} Coordinator`;
32
+ const model = config.model || 'claude-sonnet-4-5';
33
+ // Check if already running
34
+ const existing = coordinatorStates.get(groupId);
35
+ if (existing && existing.status === 'running') {
36
+ console.log(`Coordinator for group ${groupId} is already running`);
37
+ return;
38
+ }
39
+ // Update state to starting
40
+ const state = {
41
+ groupId,
42
+ groupName: group.name,
43
+ agentName,
44
+ model,
45
+ status: 'starting',
46
+ repositories,
47
+ };
48
+ coordinatorStates.set(groupId, state);
49
+ try {
50
+ // Spawn the coordinator agent
51
+ // In a real implementation, this would:
52
+ // 1. Connect to agent-relay daemon or cloud workspace
53
+ // 2. Spawn agent with configured name and model
54
+ // 3. Provide system prompt with group context
55
+ // 4. Configure capabilities (read repos, create PRs, etc.)
56
+ await spawnCoordinatorAgent(group, config, repositories);
57
+ // Update state to running
58
+ state.status = 'running';
59
+ state.startedAt = new Date();
60
+ coordinatorStates.set(groupId, state);
61
+ console.log(`Coordinator agent started for group ${groupId}: ${agentName}`);
62
+ }
63
+ catch (error) {
64
+ state.status = 'error';
65
+ state.error = error instanceof Error ? error.message : 'Unknown error';
66
+ coordinatorStates.set(groupId, state);
67
+ throw error;
68
+ }
69
+ }
70
+ /**
71
+ * Stop a coordinator agent for a project group
72
+ */
73
+ async function stop(groupId) {
74
+ const state = coordinatorStates.get(groupId);
75
+ if (!state) {
76
+ // Not running, nothing to do
77
+ return;
78
+ }
79
+ if (state.status === 'stopped') {
80
+ return;
81
+ }
82
+ // Update state to stopping
83
+ state.status = 'stopping';
84
+ coordinatorStates.set(groupId, state);
85
+ try {
86
+ // Stop the coordinator agent
87
+ // In a real implementation, this would:
88
+ // 1. Send stop signal to the agent
89
+ // 2. Wait for graceful shutdown
90
+ // 3. Clean up resources
91
+ await stopCoordinatorAgent(groupId, state);
92
+ // Update state to stopped
93
+ state.status = 'stopped';
94
+ state.stoppedAt = new Date();
95
+ coordinatorStates.set(groupId, state);
96
+ console.log(`Coordinator agent stopped for group ${groupId}`);
97
+ }
98
+ catch (error) {
99
+ state.status = 'error';
100
+ state.error = error instanceof Error ? error.message : 'Unknown error';
101
+ coordinatorStates.set(groupId, state);
102
+ throw error;
103
+ }
104
+ }
105
+ /**
106
+ * Restart a coordinator agent
107
+ */
108
+ async function restart(groupId) {
109
+ await stop(groupId);
110
+ await start(groupId);
111
+ }
112
+ /**
113
+ * Get status of a coordinator agent
114
+ */
115
+ async function getStatus(groupId) {
116
+ return coordinatorStates.get(groupId) || null;
117
+ }
118
+ /**
119
+ * List all active coordinators
120
+ */
121
+ async function listActive() {
122
+ return Array.from(coordinatorStates.values()).filter((state) => state.status === 'running' || state.status === 'starting');
123
+ }
124
+ /**
125
+ * Redis pub/sub for cross-workspace messaging
126
+ */
127
+ let pubClient = null;
128
+ let subClient = null;
129
+ const messageHandlers = new Map();
130
+ /**
131
+ * Initialize Redis pub/sub clients
132
+ */
133
+ async function initRedisClients() {
134
+ if (pubClient && subClient)
135
+ return;
136
+ const config = getConfig();
137
+ pubClient = createClient({ url: config.redisUrl });
138
+ subClient = createClient({ url: config.redisUrl });
139
+ await pubClient.connect();
140
+ await subClient.connect();
141
+ // Subscribe to coordinator channel
142
+ await subClient.subscribe('coordinator:messages', (message) => {
143
+ try {
144
+ const parsed = JSON.parse(message);
145
+ const handler = messageHandlers.get(parsed.toWorkspace || '*');
146
+ if (handler) {
147
+ handler(parsed);
148
+ }
149
+ }
150
+ catch (error) {
151
+ console.error('Failed to parse coordinator message:', error);
152
+ }
153
+ });
154
+ console.log('[coordinator] Redis pub/sub initialized');
155
+ }
156
+ /**
157
+ * Send a message from coordinator to a workspace
158
+ */
159
+ export async function sendToWorkspace(coordinatorGroupId, targetWorkspaceId, agentName, message, thread) {
160
+ if (!pubClient) {
161
+ await initRedisClients();
162
+ }
163
+ const crossMessage = {
164
+ type: 'relay',
165
+ from: 'Coordinator',
166
+ fromWorkspace: `coordinator:${coordinatorGroupId}`,
167
+ to: agentName,
168
+ toWorkspace: targetWorkspaceId,
169
+ body: message,
170
+ thread,
171
+ timestamp: new Date().toISOString(),
172
+ };
173
+ await pubClient.publish('workspace:messages', JSON.stringify(crossMessage));
174
+ console.log(`[coordinator] Sent message to ${targetWorkspaceId}:${agentName}`);
175
+ }
176
+ /**
177
+ * Broadcast a message to all workspaces in a project group
178
+ */
179
+ export async function broadcastToGroup(coordinatorGroupId, message, thread) {
180
+ if (!pubClient) {
181
+ await initRedisClients();
182
+ }
183
+ const group = await db.projectGroups.findById(coordinatorGroupId);
184
+ if (!group) {
185
+ throw new Error('Project group not found');
186
+ }
187
+ const repositories = await db.repositories.findByProjectGroupId(coordinatorGroupId);
188
+ // Get all workspaces containing these repositories
189
+ const workspaceIds = new Set();
190
+ for (const repo of repositories) {
191
+ if (repo.workspaceId) {
192
+ workspaceIds.add(repo.workspaceId);
193
+ }
194
+ }
195
+ const crossMessage = {
196
+ type: 'relay',
197
+ from: 'Coordinator',
198
+ fromWorkspace: `coordinator:${coordinatorGroupId}`,
199
+ to: '*',
200
+ body: message,
201
+ thread,
202
+ timestamp: new Date().toISOString(),
203
+ };
204
+ // Broadcast to each workspace
205
+ for (const workspaceId of workspaceIds) {
206
+ crossMessage.toWorkspace = workspaceId;
207
+ await pubClient.publish('workspace:messages', JSON.stringify(crossMessage));
208
+ }
209
+ console.log(`[coordinator] Broadcast to ${workspaceIds.size} workspace(s)`);
210
+ }
211
+ /**
212
+ * Spawn the actual coordinator agent
213
+ */
214
+ async function spawnCoordinatorAgent(group, config, repositories) {
215
+ // Initialize Redis for cross-workspace messaging
216
+ await initRedisClients();
217
+ // Build system prompt for the coordinator
218
+ const systemPrompt = buildCoordinatorSystemPrompt(group, config, repositories);
219
+ // Get workspaces for the repositories
220
+ const workspaceIds = new Set();
221
+ for (const repo of repositories) {
222
+ if (repo.workspaceId) {
223
+ workspaceIds.add(repo.workspaceId);
224
+ }
225
+ }
226
+ const workspaces = await Promise.all(Array.from(workspaceIds).map(id => db.workspaces.findById(id)));
227
+ console.log(`[coordinator] Spawning coordinator agent: ${config.name || group.name}`);
228
+ console.log(`[coordinator] Model: ${config.model || 'claude-sonnet-4-5'}`);
229
+ console.log(`[coordinator] Repositories: ${repositories.map((r) => r.githubFullName).join(', ')}`);
230
+ console.log(`[coordinator] Connected workspaces: ${workspaces.filter(Boolean).length}`);
231
+ // Register message handler for this coordinator
232
+ messageHandlers.set(`coordinator:${group.id}`, async (message) => {
233
+ console.log(`[coordinator:${group.id}] Received: ${message.body.substring(0, 100)}...`);
234
+ // In a full implementation, this would:
235
+ // 1. Parse the message for coordinator commands
236
+ // 2. Route to appropriate workspace(s)
237
+ // 3. Track conversation state
238
+ });
239
+ // Store coordinator connection info in Redis for workspace discovery
240
+ if (pubClient) {
241
+ await pubClient.hSet(`coordinator:${group.id}`, {
242
+ groupId: group.id,
243
+ groupName: group.name,
244
+ agentName: config.name || `${group.name} Coordinator`,
245
+ model: config.model || 'claude-sonnet-4-5',
246
+ startedAt: new Date().toISOString(),
247
+ workspaces: JSON.stringify(Array.from(workspaceIds)),
248
+ systemPrompt,
249
+ });
250
+ await pubClient.expire(`coordinator:${group.id}`, 86400); // 24h TTL
251
+ }
252
+ }
253
+ /**
254
+ * Stop the actual coordinator agent
255
+ */
256
+ async function stopCoordinatorAgent(groupId, state) {
257
+ console.log(`[coordinator] Stopping coordinator agent for group ${groupId}: ${state.agentName}`);
258
+ // Remove message handler
259
+ messageHandlers.delete(`coordinator:${groupId}`);
260
+ // Remove from Redis
261
+ if (pubClient) {
262
+ await pubClient.del(`coordinator:${groupId}`);
263
+ }
264
+ }
265
+ /**
266
+ * Route a message from a workspace to the coordinator
267
+ */
268
+ export async function routeToCoordinator(workspaceId, agentName, message, thread) {
269
+ if (!pubClient) {
270
+ await initRedisClients();
271
+ }
272
+ // Find which coordinator is managing this workspace
273
+ // by scanning all coordinator keys
274
+ const coordinatorKeys = await pubClient.keys('coordinator:*');
275
+ for (const key of coordinatorKeys) {
276
+ if (key === 'coordinator:messages')
277
+ continue; // Skip the channel
278
+ const data = await pubClient.hGetAll(key);
279
+ if (data.workspaces) {
280
+ const workspaces = JSON.parse(data.workspaces);
281
+ if (workspaces.includes(workspaceId)) {
282
+ // Found the coordinator for this workspace
283
+ const crossMessage = {
284
+ type: 'relay',
285
+ from: agentName,
286
+ fromWorkspace: workspaceId,
287
+ to: 'Coordinator',
288
+ toWorkspace: key,
289
+ body: message,
290
+ thread,
291
+ timestamp: new Date().toISOString(),
292
+ };
293
+ await pubClient.publish('coordinator:messages', JSON.stringify(crossMessage));
294
+ console.log(`[coordinator] Routed message from ${workspaceId}:${agentName} to ${key}`);
295
+ return;
296
+ }
297
+ }
298
+ }
299
+ console.warn(`[coordinator] No coordinator found for workspace ${workspaceId}`);
300
+ }
301
+ /**
302
+ * Get all active coordinators
303
+ */
304
+ export async function getActiveCoordinators() {
305
+ if (!pubClient) {
306
+ await initRedisClients();
307
+ }
308
+ const coordinatorKeys = await pubClient.keys('coordinator:*');
309
+ const coordinators = [];
310
+ for (const key of coordinatorKeys) {
311
+ if (key === 'coordinator:messages')
312
+ continue;
313
+ const data = await pubClient.hGetAll(key);
314
+ if (data.groupId) {
315
+ coordinators.push({
316
+ groupId: data.groupId,
317
+ groupName: data.groupName,
318
+ agentName: data.agentName,
319
+ model: data.model,
320
+ startedAt: data.startedAt,
321
+ workspaces: data.workspaces ? JSON.parse(data.workspaces) : [],
322
+ });
323
+ }
324
+ }
325
+ return coordinators;
326
+ }
327
+ /**
328
+ * Build system prompt for coordinator agent
329
+ */
330
+ function buildCoordinatorSystemPrompt(group, config, repositories) {
331
+ const repoList = repositories.map((r) => r.githubFullName).join('\n- ');
332
+ let prompt = `You are the coordinator agent for the "${group.name}" project group.
333
+
334
+ Your role is to oversee and orchestrate work across the following repositories:
335
+ - ${repoList}
336
+
337
+ `;
338
+ if (config.capabilities && config.capabilities.length > 0) {
339
+ prompt += `You have the following capabilities:
340
+ ${config.capabilities.map((c) => `- ${c}`).join('\n')}
341
+
342
+ `;
343
+ }
344
+ if (config.systemPrompt) {
345
+ prompt += `${config.systemPrompt}\n\n`;
346
+ }
347
+ prompt += `When coordinating work:
348
+ 1. Monitor all repositories in your group
349
+ 2. Identify dependencies and coordination points
350
+ 3. Delegate tasks to project-specific agents when appropriate
351
+ 4. Ensure consistency across repositories
352
+ 5. Report status and blockers to the team
353
+
354
+ Use the Agent Relay messaging system to communicate with other agents and team members.`;
355
+ return prompt;
356
+ }
357
+ /**
358
+ * Singleton instance
359
+ */
360
+ let coordinatorServiceInstance = null;
361
+ /**
362
+ * Get the coordinator service singleton
363
+ */
364
+ export function getCoordinatorService() {
365
+ if (!coordinatorServiceInstance) {
366
+ coordinatorServiceInstance = {
367
+ start,
368
+ stop,
369
+ restart,
370
+ getStatus,
371
+ listActive,
372
+ };
373
+ }
374
+ return coordinatorServiceInstance;
375
+ }
376
+ /**
377
+ * Initialize coordinator service
378
+ * Restarts any coordinators that should be running
379
+ */
380
+ export async function initializeCoordinatorService() {
381
+ console.log('Initializing coordinator service...');
382
+ // In a production system, this would:
383
+ // 1. Query database for all enabled coordinators
384
+ // 2. Check their expected state
385
+ // 3. Restart any that should be running
386
+ // For now, just log initialization
387
+ console.log('Coordinator service initialized');
388
+ }
389
+ //# sourceMappingURL=coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../src/services/coordinator.ts"],"names":[],"mappings":"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"}