@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,415 @@
1
+ /**
2
+ * Scaling Policy Service
3
+ *
4
+ * Defines rules and policies for auto-scaling workspaces based on:
5
+ * - Memory pressure
6
+ * - Agent count
7
+ * - CPU usage
8
+ * - Trend analysis
9
+ *
10
+ * Policies are configurable per user/plan tier.
11
+ */
12
+ import { EventEmitter } from 'events';
13
+ // Default thresholds by plan
14
+ const DEFAULT_THRESHOLDS = {
15
+ free: {
16
+ memoryWarningBytes: 256 * 1024 * 1024, // 256MB
17
+ memoryCriticalBytes: 512 * 1024 * 1024, // 512MB
18
+ memoryScaleUpBytes: 400 * 1024 * 1024, // 400MB (no auto-scale for free)
19
+ memoryGrowthRateWarning: 5 * 1024 * 1024, // 5MB/min
20
+ memoryGrowthRateScaleUp: 10 * 1024 * 1024, // 10MB/min
21
+ agentsPerWorkspaceWarning: 3,
22
+ agentsPerWorkspaceMax: 5,
23
+ cpuWarningPercent: 70,
24
+ cpuScaleUpPercent: 85,
25
+ evaluationWindowMs: 5 * 60 * 1000, // 5 minutes
26
+ cooldownMs: 30 * 60 * 1000, // 30 minutes (free tier)
27
+ },
28
+ pro: {
29
+ memoryWarningBytes: 512 * 1024 * 1024, // 512MB
30
+ memoryCriticalBytes: 1024 * 1024 * 1024, // 1GB
31
+ memoryScaleUpBytes: 768 * 1024 * 1024, // 768MB
32
+ memoryGrowthRateWarning: 10 * 1024 * 1024, // 10MB/min
33
+ memoryGrowthRateScaleUp: 20 * 1024 * 1024, // 20MB/min
34
+ agentsPerWorkspaceWarning: 8,
35
+ agentsPerWorkspaceMax: 15,
36
+ cpuWarningPercent: 75,
37
+ cpuScaleUpPercent: 90,
38
+ evaluationWindowMs: 3 * 60 * 1000, // 3 minutes
39
+ cooldownMs: 10 * 60 * 1000, // 10 minutes
40
+ },
41
+ team: {
42
+ memoryWarningBytes: 768 * 1024 * 1024, // 768MB
43
+ memoryCriticalBytes: 1.5 * 1024 * 1024 * 1024, // 1.5GB
44
+ memoryScaleUpBytes: 1024 * 1024 * 1024, // 1GB
45
+ memoryGrowthRateWarning: 15 * 1024 * 1024, // 15MB/min
46
+ memoryGrowthRateScaleUp: 30 * 1024 * 1024, // 30MB/min
47
+ agentsPerWorkspaceWarning: 15,
48
+ agentsPerWorkspaceMax: 25,
49
+ cpuWarningPercent: 80,
50
+ cpuScaleUpPercent: 92,
51
+ evaluationWindowMs: 2 * 60 * 1000, // 2 minutes
52
+ cooldownMs: 5 * 60 * 1000, // 5 minutes
53
+ },
54
+ enterprise: {
55
+ memoryWarningBytes: 1024 * 1024 * 1024, // 1GB
56
+ memoryCriticalBytes: 2 * 1024 * 1024 * 1024, // 2GB
57
+ memoryScaleUpBytes: 1.5 * 1024 * 1024 * 1024, // 1.5GB
58
+ memoryGrowthRateWarning: 20 * 1024 * 1024, // 20MB/min
59
+ memoryGrowthRateScaleUp: 50 * 1024 * 1024, // 50MB/min
60
+ agentsPerWorkspaceWarning: 25,
61
+ agentsPerWorkspaceMax: 50,
62
+ cpuWarningPercent: 85,
63
+ cpuScaleUpPercent: 95,
64
+ evaluationWindowMs: 1 * 60 * 1000, // 1 minute
65
+ cooldownMs: 2 * 60 * 1000, // 2 minutes
66
+ },
67
+ };
68
+ // Default policies - ordered by priority (higher = evaluated first)
69
+ // In-workspace scaling is preferred over adding new workspaces (more efficient)
70
+ const DEFAULT_POLICIES = [
71
+ // === In-Workspace Scaling (Higher Priority) ===
72
+ {
73
+ id: 'agent-limit-increase',
74
+ name: 'Increase Agent Limit',
75
+ description: 'Increase max agents when approaching limit within single workspace',
76
+ enabled: true,
77
+ priority: 150, // Higher priority - try this before adding workspaces
78
+ conditions: [
79
+ { metric: 'agent_count', operator: 'gte', value: 0.85 }, // 85% of max agents
80
+ { metric: 'workspace_count', operator: 'eq', value: 1 }, // Only 1 workspace
81
+ ],
82
+ action: { type: 'increase_agent_limit', percentage: 50 }, // Increase limit by 50%
83
+ maxInstances: 10,
84
+ minInstances: 1,
85
+ },
86
+ {
87
+ id: 'workspace-resize-up',
88
+ name: 'Resize Workspace Up',
89
+ description: 'Vertically scale workspace when memory is high',
90
+ enabled: true,
91
+ priority: 140, // Higher priority than horizontal scaling
92
+ conditions: [
93
+ { metric: 'memory_usage', operator: 'gte', value: 0.75, duration: 120000 }, // 75% for 2min
94
+ { metric: 'workspace_count', operator: 'eq', value: 1 }, // Only 1 workspace
95
+ ],
96
+ action: { type: 'resize_up', percentage: 100 }, // Double resources
97
+ maxInstances: 10,
98
+ minInstances: 1,
99
+ },
100
+ {
101
+ id: 'cpu-pressure-resize',
102
+ name: 'CPU Pressure Resize',
103
+ description: 'Resize workspace when CPU is consistently high',
104
+ enabled: true,
105
+ priority: 135,
106
+ conditions: [
107
+ { metric: 'cpu_usage', operator: 'gte', value: 0.85, duration: 180000 }, // 85% for 3min
108
+ ],
109
+ action: { type: 'resize_up', percentage: 50 }, // 50% more resources
110
+ maxInstances: 10,
111
+ minInstances: 1,
112
+ },
113
+ {
114
+ id: 'workspace-resize-down',
115
+ name: 'Resize Workspace Down',
116
+ description: 'Reduce workspace resources when underutilized',
117
+ enabled: true,
118
+ priority: 45, // Lower priority
119
+ conditions: [
120
+ { metric: 'memory_usage', operator: 'lt', value: 0.15, duration: 900000 }, // Under 15% for 15min
121
+ { metric: 'cpu_usage', operator: 'lt', value: 0.1, duration: 900000 }, // Under 10% CPU
122
+ ],
123
+ action: { type: 'resize_down', percentage: 50 }, // Halve resources
124
+ maxInstances: 10,
125
+ minInstances: 1,
126
+ },
127
+ // === Horizontal Scaling (Add/Remove Workspaces) ===
128
+ {
129
+ id: 'memory-pressure-scale-up',
130
+ name: 'Memory Pressure Scale Up',
131
+ description: 'Add workspace when memory exceeds threshold across all workspaces',
132
+ enabled: true,
133
+ priority: 100,
134
+ conditions: [
135
+ { metric: 'memory_usage', operator: 'gte', value: 0.8, duration: 60000 }, // 80% for 1min
136
+ ],
137
+ action: { type: 'scale_up', targetCount: 1 },
138
+ maxInstances: 10,
139
+ minInstances: 1,
140
+ },
141
+ {
142
+ id: 'memory-trend-scale-up',
143
+ name: 'Memory Trend Scale Up',
144
+ description: 'Add workspace when memory growth rate is high',
145
+ enabled: true,
146
+ priority: 90,
147
+ conditions: [
148
+ { metric: 'memory_trend', operator: 'gte', value: 1.0, duration: 180000 }, // At threshold for 3min
149
+ ],
150
+ action: { type: 'scale_up', targetCount: 1 },
151
+ maxInstances: 10,
152
+ minInstances: 1,
153
+ },
154
+ {
155
+ id: 'agent-count-scale-up',
156
+ name: 'Agent Count Scale Up',
157
+ description: 'Add workspace when agent count is high across all workspaces',
158
+ enabled: true,
159
+ priority: 80,
160
+ conditions: [
161
+ { metric: 'agent_count', operator: 'gte', value: 0.9 }, // 90% of max agents
162
+ { metric: 'workspace_count', operator: 'gte', value: 1 }, // Already tried in-workspace scaling
163
+ ],
164
+ action: { type: 'scale_up', targetCount: 1 },
165
+ maxInstances: 10,
166
+ minInstances: 1,
167
+ },
168
+ // === Rebalancing ===
169
+ {
170
+ id: 'agent-rebalance',
171
+ name: 'Agent Rebalance',
172
+ description: 'Redistribute agents when load is uneven across workspaces',
173
+ enabled: true,
174
+ priority: 60,
175
+ conditions: [
176
+ { metric: 'workspace_count', operator: 'gte', value: 2 }, // Multiple workspaces
177
+ ],
178
+ action: { type: 'rebalance' },
179
+ maxInstances: 10,
180
+ minInstances: 1,
181
+ },
182
+ // === Scale Down ===
183
+ {
184
+ id: 'low-usage-scale-down',
185
+ name: 'Low Usage Scale Down',
186
+ description: 'Remove workspace when usage is low',
187
+ enabled: true,
188
+ priority: 50,
189
+ conditions: [
190
+ { metric: 'memory_usage', operator: 'lt', value: 0.2, duration: 600000 }, // Under 20% for 10min
191
+ { metric: 'workspace_count', operator: 'gt', value: 1 }, // More than 1 workspace
192
+ ],
193
+ action: { type: 'scale_down', targetCount: 1 },
194
+ maxInstances: 10,
195
+ minInstances: 1,
196
+ },
197
+ ];
198
+ export class ScalingPolicyService extends EventEmitter {
199
+ thresholds = new Map();
200
+ policies = new Map();
201
+ conditionHistory = new Map();
202
+ constructor() {
203
+ super();
204
+ // Initialize with defaults
205
+ for (const [plan, thresholds] of Object.entries(DEFAULT_THRESHOLDS)) {
206
+ this.thresholds.set(plan, thresholds);
207
+ }
208
+ }
209
+ /**
210
+ * Get thresholds for a plan tier
211
+ */
212
+ getThresholds(plan) {
213
+ return this.thresholds.get(plan) || this.thresholds.get('free');
214
+ }
215
+ /**
216
+ * Set custom thresholds for a plan
217
+ */
218
+ setThresholds(plan, thresholds) {
219
+ const current = this.getThresholds(plan);
220
+ this.thresholds.set(plan, { ...current, ...thresholds });
221
+ }
222
+ /**
223
+ * Get policies for a user (default + custom)
224
+ */
225
+ getPolicies(userId) {
226
+ const userPolicies = this.policies.get(userId) || [];
227
+ return [...DEFAULT_POLICIES, ...userPolicies].sort((a, b) => b.priority - a.priority);
228
+ }
229
+ /**
230
+ * Add custom policy for a user
231
+ */
232
+ addPolicy(userId, policy) {
233
+ const existing = this.policies.get(userId) || [];
234
+ existing.push(policy);
235
+ this.policies.set(userId, existing);
236
+ }
237
+ /**
238
+ * Evaluate scaling decision based on current context
239
+ */
240
+ evaluate(context) {
241
+ const thresholds = this.getThresholds(context.plan);
242
+ const policies = this.getPolicies(context.userId);
243
+ // Calculate aggregate metrics
244
+ const metrics = this.calculateAggregateMetrics(context, thresholds);
245
+ // Check cooldown
246
+ if (context.lastScalingAction) {
247
+ const timeSinceLastScale = Date.now() - context.lastScalingAction.getTime();
248
+ if (timeSinceLastScale < thresholds.cooldownMs) {
249
+ return {
250
+ shouldScale: false,
251
+ action: null,
252
+ reason: `Cooldown active (${Math.round((thresholds.cooldownMs - timeSinceLastScale) / 1000)}s remaining)`,
253
+ triggeredPolicy: null,
254
+ metrics,
255
+ timestamp: new Date(),
256
+ };
257
+ }
258
+ }
259
+ // Evaluate policies in priority order
260
+ for (const policy of policies) {
261
+ if (!policy.enabled)
262
+ continue;
263
+ const conditionsMet = this.evaluateConditions(policy.conditions, metrics, thresholds, context.userId);
264
+ if (conditionsMet) {
265
+ // Check instance limits for horizontal scaling only
266
+ if (policy.action.type === 'scale_up') {
267
+ // Block if at workspace limit (for adding new workspaces)
268
+ if (context.currentWorkspaceCount >= context.maxWorkspaces) {
269
+ continue; // Try next policy (could be in-workspace scaling)
270
+ }
271
+ if (context.currentWorkspaceCount >= policy.maxInstances) {
272
+ continue;
273
+ }
274
+ }
275
+ if (policy.action.type === 'scale_down' && context.currentWorkspaceCount <= policy.minInstances) {
276
+ continue;
277
+ }
278
+ this.emit('scaling_decision', {
279
+ userId: context.userId,
280
+ policy: policy.id,
281
+ action: policy.action,
282
+ metrics,
283
+ });
284
+ return {
285
+ shouldScale: true,
286
+ action: policy.action,
287
+ reason: policy.description,
288
+ triggeredPolicy: policy.id,
289
+ metrics,
290
+ timestamp: new Date(),
291
+ };
292
+ }
293
+ }
294
+ return {
295
+ shouldScale: false,
296
+ action: null,
297
+ reason: 'No scaling conditions met',
298
+ triggeredPolicy: null,
299
+ metrics,
300
+ timestamp: new Date(),
301
+ };
302
+ }
303
+ /**
304
+ * Calculate aggregate metrics from workspace metrics
305
+ */
306
+ calculateAggregateMetrics(context, thresholds) {
307
+ const workspaces = context.workspaceMetrics;
308
+ if (workspaces.length === 0) {
309
+ return {
310
+ memory_usage: 0,
311
+ memory_trend: 0,
312
+ agent_count: 0,
313
+ cpu_usage: 0,
314
+ workspace_count: 0,
315
+ total_memory_bytes: 0,
316
+ total_agents: 0,
317
+ };
318
+ }
319
+ const totalMemory = workspaces.reduce((sum, w) => sum + w.totalMemoryBytes, 0);
320
+ const avgTrend = workspaces.reduce((sum, w) => sum + w.memoryTrendPerMinute, 0) / workspaces.length;
321
+ const totalAgents = workspaces.reduce((sum, w) => sum + w.agentCount, 0);
322
+ const avgCpu = workspaces.reduce((sum, w) => sum + w.cpuPercent, 0) / workspaces.length;
323
+ // Normalized metrics (0-1 scale relative to thresholds)
324
+ return {
325
+ memory_usage: totalMemory / (thresholds.memoryScaleUpBytes * workspaces.length),
326
+ memory_trend: avgTrend / thresholds.memoryGrowthRateScaleUp,
327
+ agent_count: totalAgents / (thresholds.agentsPerWorkspaceMax * workspaces.length),
328
+ cpu_usage: avgCpu / thresholds.cpuScaleUpPercent,
329
+ workspace_count: context.currentWorkspaceCount,
330
+ total_memory_bytes: totalMemory,
331
+ total_agents: totalAgents,
332
+ };
333
+ }
334
+ /**
335
+ * Evaluate conditions with duration support
336
+ */
337
+ evaluateConditions(conditions, metrics, thresholds, userId) {
338
+ for (const condition of conditions) {
339
+ const metricValue = metrics[condition.metric];
340
+ if (metricValue === undefined)
341
+ continue;
342
+ const conditionMet = this.compareValues(metricValue, condition.operator, condition.value);
343
+ if (condition.duration) {
344
+ // Track condition history for duration-based evaluation
345
+ const historyKey = `${userId}:${condition.metric}`;
346
+ const history = this.conditionHistory.get(historyKey) || [];
347
+ // Add current value
348
+ history.push({ timestamp: new Date(), value: metricValue });
349
+ // Clean old entries
350
+ const cutoff = Date.now() - condition.duration;
351
+ const recentHistory = history.filter((h) => h.timestamp.getTime() > cutoff);
352
+ this.conditionHistory.set(historyKey, recentHistory);
353
+ // Check if condition has been met for the full duration
354
+ if (recentHistory.length === 0)
355
+ return false;
356
+ const allMet = recentHistory.every((h) => this.compareValues(h.value, condition.operator, condition.value));
357
+ // Also check if we have enough history
358
+ const oldestEntry = recentHistory[0].timestamp.getTime();
359
+ const hasEnoughHistory = Date.now() - oldestEntry >= condition.duration * 0.8; // 80% of duration
360
+ if (!allMet || !hasEnoughHistory)
361
+ return false;
362
+ }
363
+ else {
364
+ if (!conditionMet)
365
+ return false;
366
+ }
367
+ }
368
+ return true;
369
+ }
370
+ /**
371
+ * Compare values based on operator
372
+ */
373
+ compareValues(actual, operator, target) {
374
+ switch (operator) {
375
+ case 'gt':
376
+ return actual > target;
377
+ case 'gte':
378
+ return actual >= target;
379
+ case 'lt':
380
+ return actual < target;
381
+ case 'lte':
382
+ return actual <= target;
383
+ case 'eq':
384
+ return actual === target;
385
+ default:
386
+ return false;
387
+ }
388
+ }
389
+ /**
390
+ * Get max workspaces for a plan
391
+ */
392
+ getMaxWorkspaces(plan) {
393
+ switch (plan) {
394
+ case 'free':
395
+ return 1;
396
+ case 'pro':
397
+ return 3;
398
+ case 'team':
399
+ return 10;
400
+ case 'enterprise':
401
+ return 50;
402
+ default:
403
+ return 1;
404
+ }
405
+ }
406
+ }
407
+ // Singleton instance
408
+ let _scalingPolicyService = null;
409
+ export function getScalingPolicyService() {
410
+ if (!_scalingPolicyService) {
411
+ _scalingPolicyService = new ScalingPolicyService();
412
+ }
413
+ return _scalingPolicyService;
414
+ }
415
+ //# sourceMappingURL=scaling-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaling-policy.js","sourceRoot":"","sources":["../../src/services/scaling-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * SSH Security Utilities
3
+ *
4
+ * Provides secure SSH password derivation for workspace containers.
5
+ * Uses a deterministic approach based on workspace ID + secret salt,
6
+ * ensuring each workspace has a unique password without storage.
7
+ */
8
+ /**
9
+ * Derive a unique SSH password for a workspace.
10
+ *
11
+ * Uses SHA-256 hash of (workspaceId + salt) to generate a deterministic
12
+ * but unique password for each workspace. This approach:
13
+ * - Ensures each workspace has a unique password
14
+ * - Requires no database storage
15
+ * - Produces consistent results across cloud server and container
16
+ *
17
+ * SECURITY: Set SSH_PASSWORD_SALT environment variable in production!
18
+ * The default salt is insecure and should never be used in production.
19
+ *
20
+ * @param workspaceId - The workspace UUID
21
+ * @returns A 24-character hex password (96 bits of entropy)
22
+ */
23
+ export declare function deriveSshPassword(workspaceId: string): string;
24
+ /**
25
+ * Validate that SSH security is properly configured.
26
+ * Call this at server startup to catch configuration issues early.
27
+ *
28
+ * @returns true if properly configured, false otherwise
29
+ */
30
+ export declare function validateSshSecurityConfig(): boolean;
31
+ //# sourceMappingURL=ssh-security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-security.d.ts","sourceRoot":"","sources":["../../src/services/ssh-security.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAsB7D;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAoBnD"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * SSH Security Utilities
3
+ *
4
+ * Provides secure SSH password derivation for workspace containers.
5
+ * Uses a deterministic approach based on workspace ID + secret salt,
6
+ * ensuring each workspace has a unique password without storage.
7
+ */
8
+ import * as crypto from 'crypto';
9
+ const DEFAULT_SALT = 'default-salt-change-in-prod';
10
+ /**
11
+ * Derive a unique SSH password for a workspace.
12
+ *
13
+ * Uses SHA-256 hash of (workspaceId + salt) to generate a deterministic
14
+ * but unique password for each workspace. This approach:
15
+ * - Ensures each workspace has a unique password
16
+ * - Requires no database storage
17
+ * - Produces consistent results across cloud server and container
18
+ *
19
+ * SECURITY: Set SSH_PASSWORD_SALT environment variable in production!
20
+ * The default salt is insecure and should never be used in production.
21
+ *
22
+ * @param workspaceId - The workspace UUID
23
+ * @returns A 24-character hex password (96 bits of entropy)
24
+ */
25
+ export function deriveSshPassword(workspaceId) {
26
+ const salt = process.env.SSH_PASSWORD_SALT;
27
+ // Warn if using default salt in production
28
+ if (!salt) {
29
+ const isProduction = process.env.NODE_ENV === 'production' || process.env.FLY_APP_NAME;
30
+ if (isProduction) {
31
+ console.warn('[SECURITY WARNING] SSH_PASSWORD_SALT is not set! ' +
32
+ 'Using default salt is INSECURE in production. ' +
33
+ 'Set SSH_PASSWORD_SALT to a random 32+ character secret.');
34
+ }
35
+ }
36
+ const effectiveSalt = salt || DEFAULT_SALT;
37
+ return crypto
38
+ .createHash('sha256')
39
+ .update(`${workspaceId}:${effectiveSalt}`)
40
+ .digest('hex')
41
+ .substring(0, 24); // 24 hex chars = 96 bits of entropy
42
+ }
43
+ /**
44
+ * Validate that SSH security is properly configured.
45
+ * Call this at server startup to catch configuration issues early.
46
+ *
47
+ * @returns true if properly configured, false otherwise
48
+ */
49
+ export function validateSshSecurityConfig() {
50
+ const salt = process.env.SSH_PASSWORD_SALT;
51
+ const isProduction = process.env.NODE_ENV === 'production' || process.env.FLY_APP_NAME;
52
+ if (isProduction && !salt) {
53
+ console.error('[SECURITY ERROR] SSH_PASSWORD_SALT must be set in production! ' +
54
+ 'Generate one with: openssl rand -hex 32');
55
+ return false;
56
+ }
57
+ if (salt && salt.length < 16) {
58
+ console.warn('[SECURITY WARNING] SSH_PASSWORD_SALT should be at least 16 characters. ' +
59
+ 'Current length: ' + salt.length);
60
+ }
61
+ return true;
62
+ }
63
+ //# sourceMappingURL=ssh-security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-security.js","sourceRoot":"","sources":["../../src/services/ssh-security.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,YAAY,GAAG,6BAA6B,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAE3C,2CAA2C;IAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QACvF,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CACV,mDAAmD;gBACnD,gDAAgD;gBAChD,yDAAyD,CAC1D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,IAAI,YAAY,CAAC;IAE3C,OAAO,MAAM;SACV,UAAU,CAAC,QAAQ,CAAC;SACpB,MAAM,CAAC,GAAG,WAAW,IAAI,aAAa,EAAE,CAAC;SACzC,MAAM,CAAC,KAAK,CAAC;SACb,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,oCAAoC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAEvF,IAAI,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CACX,gEAAgE;YAChE,yCAAyC,CAC1C,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CACV,yEAAyE;YACzE,kBAAkB,GAAG,IAAI,CAAC,MAAM,CACjC,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Workspace Keepalive Service
3
+ *
4
+ * Prevents Fly.io from idling workspace machines that have active agents running.
5
+ *
6
+ * Problem: Fly.io uses request-based concurrency tracking to determine when to
7
+ * idle a machine. If a Claude agent is running but no HTTP requests are coming
8
+ * in (e.g., no one has the dashboard open), Fly.io may idle the machine.
9
+ *
10
+ * Solution: The cloud server periodically pings workspace machines that have
11
+ * active agents. This inbound HTTP request counts as activity for Fly.io's
12
+ * idle detection, keeping the machine awake.
13
+ *
14
+ * Flow:
15
+ * 1. Daemons report their running agents via heartbeat
16
+ * 2. This service queries for workspaces with active agents
17
+ * 3. Pings each workspace's /keep-alive endpoint
18
+ * 4. Workspace stays awake as long as agents are active
19
+ */
20
+ import { EventEmitter } from 'events';
21
+ export interface WorkspaceKeepaliveConfig {
22
+ /** How often to ping active workspaces (default: 60s) */
23
+ pingIntervalMs: number;
24
+ /** Request timeout for keep-alive pings (default: 5s) */
25
+ requestTimeoutMs: number;
26
+ /** Consider daemon stale if last heartbeat older than this (default: 2 min) */
27
+ staleThresholdMs: number;
28
+ /** Enable verbose logging (default: false) */
29
+ verbose: boolean;
30
+ }
31
+ export interface KeepaliveStats {
32
+ lastRun: Date | null;
33
+ totalPings: number;
34
+ successfulPings: number;
35
+ failedPings: number;
36
+ activeWorkspaces: number;
37
+ }
38
+ export declare class WorkspaceKeepaliveService extends EventEmitter {
39
+ private config;
40
+ private pingTimer;
41
+ private stats;
42
+ constructor(config?: Partial<WorkspaceKeepaliveConfig>);
43
+ /**
44
+ * Start the keepalive service
45
+ */
46
+ start(): void;
47
+ /**
48
+ * Stop the keepalive service
49
+ */
50
+ stop(): void;
51
+ /**
52
+ * Get current statistics
53
+ */
54
+ getStats(): KeepaliveStats;
55
+ /**
56
+ * Find workspaces with active agents and ping them
57
+ */
58
+ pingActiveWorkspaces(): Promise<void>;
59
+ /**
60
+ * Find all workspaces that have daemons with active agents
61
+ */
62
+ private findWorkspacesWithActiveAgents;
63
+ /**
64
+ * Ping a single workspace's keep-alive endpoint
65
+ */
66
+ private pingWorkspace;
67
+ }
68
+ /**
69
+ * Get or create the keepalive service singleton
70
+ */
71
+ export declare function getWorkspaceKeepaliveService(config?: Partial<WorkspaceKeepaliveConfig>): WorkspaceKeepaliveService;
72
+ /**
73
+ * Create a new keepalive service (for testing)
74
+ */
75
+ export declare function createWorkspaceKeepaliveService(config?: Partial<WorkspaceKeepaliveConfig>): WorkspaceKeepaliveService;
76
+ //# sourceMappingURL=workspace-keepalive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-keepalive.d.ts","sourceRoot":"","sources":["../../src/services/workspace-keepalive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,MAAM,WAAW,wBAAwB;IACvC,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,+EAA+E;IAC/E,gBAAgB,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAiBD,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,KAAK,CAMX;gBAEU,MAAM,GAAE,OAAO,CAAC,wBAAwB,CAAM;IAK1D;;OAEG;IACH,KAAK,IAAI,IAAI;IAsBb;;OAEG;IACH,IAAI,IAAI,IAAI;IAQZ;;OAEG;IACH,QAAQ,IAAI,cAAc;IAI1B;;OAEG;IACG,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAsD3C;;OAEG;YACW,8BAA8B;IAgD5C;;OAEG;YACW,aAAa;CA6C5B;AAKD;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GACzC,yBAAyB,CAK3B;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GACzC,yBAAyB,CAE3B"}