@agent-relay/cloud 2.0.23 → 6.0.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 (289) hide show
  1. package/dist/api-client.d.ts +33 -0
  2. package/dist/api-client.d.ts.map +1 -0
  3. package/dist/api-client.js +123 -0
  4. package/dist/api-client.js.map +1 -0
  5. package/dist/auth.d.ts +13 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +299 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/index.d.ts +4 -10
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +4 -37
  12. package/dist/index.js.map +1 -1
  13. package/dist/types.d.ts +73 -0
  14. package/dist/types.d.ts.map +1 -0
  15. package/dist/types.js +12 -0
  16. package/dist/types.js.map +1 -0
  17. package/dist/workflows.d.ts +46 -0
  18. package/dist/workflows.d.ts.map +1 -0
  19. package/dist/workflows.js +464 -0
  20. package/dist/workflows.js.map +1 -0
  21. package/package.json +8 -25
  22. package/dist/api/admin.d.ts +0 -8
  23. package/dist/api/admin.d.ts.map +0 -1
  24. package/dist/api/admin.js +0 -225
  25. package/dist/api/admin.js.map +0 -1
  26. package/dist/api/auth.d.ts +0 -20
  27. package/dist/api/auth.d.ts.map +0 -1
  28. package/dist/api/auth.js +0 -138
  29. package/dist/api/auth.js.map +0 -1
  30. package/dist/api/billing.d.ts +0 -7
  31. package/dist/api/billing.d.ts.map +0 -1
  32. package/dist/api/billing.js +0 -564
  33. package/dist/api/billing.js.map +0 -1
  34. package/dist/api/cli-pty-runner.d.ts +0 -53
  35. package/dist/api/cli-pty-runner.d.ts.map +0 -1
  36. package/dist/api/cli-pty-runner.js +0 -175
  37. package/dist/api/cli-pty-runner.js.map +0 -1
  38. package/dist/api/codex-auth-helper.d.ts +0 -21
  39. package/dist/api/codex-auth-helper.d.ts.map +0 -1
  40. package/dist/api/codex-auth-helper.js +0 -327
  41. package/dist/api/codex-auth-helper.js.map +0 -1
  42. package/dist/api/consensus.d.ts +0 -13
  43. package/dist/api/consensus.d.ts.map +0 -1
  44. package/dist/api/consensus.js +0 -261
  45. package/dist/api/consensus.js.map +0 -1
  46. package/dist/api/coordinators.d.ts +0 -8
  47. package/dist/api/coordinators.d.ts.map +0 -1
  48. package/dist/api/coordinators.js +0 -750
  49. package/dist/api/coordinators.js.map +0 -1
  50. package/dist/api/daemons.d.ts +0 -12
  51. package/dist/api/daemons.d.ts.map +0 -1
  52. package/dist/api/daemons.js +0 -535
  53. package/dist/api/daemons.js.map +0 -1
  54. package/dist/api/email-auth.d.ts +0 -11
  55. package/dist/api/email-auth.d.ts.map +0 -1
  56. package/dist/api/email-auth.js +0 -347
  57. package/dist/api/email-auth.js.map +0 -1
  58. package/dist/api/generic-webhooks.d.ts +0 -8
  59. package/dist/api/generic-webhooks.d.ts.map +0 -1
  60. package/dist/api/generic-webhooks.js +0 -129
  61. package/dist/api/generic-webhooks.js.map +0 -1
  62. package/dist/api/git.d.ts +0 -8
  63. package/dist/api/git.d.ts.map +0 -1
  64. package/dist/api/git.js +0 -269
  65. package/dist/api/git.js.map +0 -1
  66. package/dist/api/github-app.d.ts +0 -11
  67. package/dist/api/github-app.d.ts.map +0 -1
  68. package/dist/api/github-app.js +0 -223
  69. package/dist/api/github-app.js.map +0 -1
  70. package/dist/api/middleware/planLimits.d.ts +0 -43
  71. package/dist/api/middleware/planLimits.d.ts.map +0 -1
  72. package/dist/api/middleware/planLimits.js +0 -202
  73. package/dist/api/middleware/planLimits.js.map +0 -1
  74. package/dist/api/monitoring.d.ts +0 -11
  75. package/dist/api/monitoring.d.ts.map +0 -1
  76. package/dist/api/monitoring.js +0 -578
  77. package/dist/api/monitoring.js.map +0 -1
  78. package/dist/api/nango-auth.d.ts +0 -9
  79. package/dist/api/nango-auth.d.ts.map +0 -1
  80. package/dist/api/nango-auth.js +0 -741
  81. package/dist/api/nango-auth.js.map +0 -1
  82. package/dist/api/onboarding.d.ts +0 -15
  83. package/dist/api/onboarding.d.ts.map +0 -1
  84. package/dist/api/onboarding.js +0 -679
  85. package/dist/api/onboarding.js.map +0 -1
  86. package/dist/api/policy.d.ts +0 -8
  87. package/dist/api/policy.d.ts.map +0 -1
  88. package/dist/api/policy.js +0 -229
  89. package/dist/api/policy.js.map +0 -1
  90. package/dist/api/provider-env.d.ts +0 -26
  91. package/dist/api/provider-env.d.ts.map +0 -1
  92. package/dist/api/provider-env.js +0 -141
  93. package/dist/api/provider-env.js.map +0 -1
  94. package/dist/api/providers.d.ts +0 -7
  95. package/dist/api/providers.d.ts.map +0 -1
  96. package/dist/api/providers.js +0 -574
  97. package/dist/api/providers.js.map +0 -1
  98. package/dist/api/repos.d.ts +0 -8
  99. package/dist/api/repos.d.ts.map +0 -1
  100. package/dist/api/repos.js +0 -577
  101. package/dist/api/repos.js.map +0 -1
  102. package/dist/api/sessions.d.ts +0 -11
  103. package/dist/api/sessions.d.ts.map +0 -1
  104. package/dist/api/sessions.js +0 -302
  105. package/dist/api/sessions.js.map +0 -1
  106. package/dist/api/teams.d.ts +0 -7
  107. package/dist/api/teams.d.ts.map +0 -1
  108. package/dist/api/teams.js +0 -281
  109. package/dist/api/teams.js.map +0 -1
  110. package/dist/api/test-helpers.d.ts +0 -10
  111. package/dist/api/test-helpers.d.ts.map +0 -1
  112. package/dist/api/test-helpers.js +0 -745
  113. package/dist/api/test-helpers.js.map +0 -1
  114. package/dist/api/usage.d.ts +0 -7
  115. package/dist/api/usage.d.ts.map +0 -1
  116. package/dist/api/usage.js +0 -111
  117. package/dist/api/usage.js.map +0 -1
  118. package/dist/api/webhooks.d.ts +0 -8
  119. package/dist/api/webhooks.d.ts.map +0 -1
  120. package/dist/api/webhooks.js +0 -645
  121. package/dist/api/webhooks.js.map +0 -1
  122. package/dist/api/workspaces.d.ts +0 -25
  123. package/dist/api/workspaces.d.ts.map +0 -1
  124. package/dist/api/workspaces.js +0 -1799
  125. package/dist/api/workspaces.js.map +0 -1
  126. package/dist/billing/index.d.ts +0 -9
  127. package/dist/billing/index.d.ts.map +0 -1
  128. package/dist/billing/index.js +0 -9
  129. package/dist/billing/index.js.map +0 -1
  130. package/dist/billing/plans.d.ts +0 -39
  131. package/dist/billing/plans.d.ts.map +0 -1
  132. package/dist/billing/plans.js +0 -245
  133. package/dist/billing/plans.js.map +0 -1
  134. package/dist/billing/service.d.ts +0 -80
  135. package/dist/billing/service.d.ts.map +0 -1
  136. package/dist/billing/service.js +0 -388
  137. package/dist/billing/service.js.map +0 -1
  138. package/dist/billing/types.d.ts +0 -141
  139. package/dist/billing/types.d.ts.map +0 -1
  140. package/dist/billing/types.js +0 -7
  141. package/dist/billing/types.js.map +0 -1
  142. package/dist/config.d.ts +0 -5
  143. package/dist/config.d.ts.map +0 -1
  144. package/dist/config.js +0 -5
  145. package/dist/config.js.map +0 -1
  146. package/dist/db/bulk-ingest.d.ts +0 -89
  147. package/dist/db/bulk-ingest.d.ts.map +0 -1
  148. package/dist/db/bulk-ingest.js +0 -268
  149. package/dist/db/bulk-ingest.js.map +0 -1
  150. package/dist/db/drizzle.d.ts +0 -290
  151. package/dist/db/drizzle.d.ts.map +0 -1
  152. package/dist/db/drizzle.js +0 -1422
  153. package/dist/db/drizzle.js.map +0 -1
  154. package/dist/db/index.d.ts +0 -56
  155. package/dist/db/index.d.ts.map +0 -1
  156. package/dist/db/index.js +0 -70
  157. package/dist/db/index.js.map +0 -1
  158. package/dist/db/schema.d.ts +0 -5117
  159. package/dist/db/schema.d.ts.map +0 -1
  160. package/dist/db/schema.js +0 -656
  161. package/dist/db/schema.js.map +0 -1
  162. package/dist/provisioner/index.d.ts +0 -207
  163. package/dist/provisioner/index.d.ts.map +0 -1
  164. package/dist/provisioner/index.js +0 -2118
  165. package/dist/provisioner/index.js.map +0 -1
  166. package/dist/server.d.ts +0 -17
  167. package/dist/server.d.ts.map +0 -1
  168. package/dist/server.js +0 -2055
  169. package/dist/server.js.map +0 -1
  170. package/dist/services/auto-scaler.d.ts +0 -152
  171. package/dist/services/auto-scaler.d.ts.map +0 -1
  172. package/dist/services/auto-scaler.js +0 -439
  173. package/dist/services/auto-scaler.js.map +0 -1
  174. package/dist/services/capacity-manager.d.ts +0 -148
  175. package/dist/services/capacity-manager.d.ts.map +0 -1
  176. package/dist/services/capacity-manager.js +0 -449
  177. package/dist/services/capacity-manager.js.map +0 -1
  178. package/dist/services/ci-agent-spawner.d.ts +0 -49
  179. package/dist/services/ci-agent-spawner.d.ts.map +0 -1
  180. package/dist/services/ci-agent-spawner.js +0 -373
  181. package/dist/services/ci-agent-spawner.js.map +0 -1
  182. package/dist/services/cloud-message-bus.d.ts +0 -28
  183. package/dist/services/cloud-message-bus.d.ts.map +0 -1
  184. package/dist/services/cloud-message-bus.js +0 -19
  185. package/dist/services/cloud-message-bus.js.map +0 -1
  186. package/dist/services/compute-enforcement.d.ts +0 -57
  187. package/dist/services/compute-enforcement.d.ts.map +0 -1
  188. package/dist/services/compute-enforcement.js +0 -175
  189. package/dist/services/compute-enforcement.js.map +0 -1
  190. package/dist/services/coordinator.d.ts +0 -62
  191. package/dist/services/coordinator.d.ts.map +0 -1
  192. package/dist/services/coordinator.js +0 -389
  193. package/dist/services/coordinator.js.map +0 -1
  194. package/dist/services/index.d.ts +0 -17
  195. package/dist/services/index.d.ts.map +0 -1
  196. package/dist/services/index.js +0 -25
  197. package/dist/services/index.js.map +0 -1
  198. package/dist/services/intro-expiration.d.ts +0 -60
  199. package/dist/services/intro-expiration.d.ts.map +0 -1
  200. package/dist/services/intro-expiration.js +0 -252
  201. package/dist/services/intro-expiration.js.map +0 -1
  202. package/dist/services/mention-handler.d.ts +0 -65
  203. package/dist/services/mention-handler.d.ts.map +0 -1
  204. package/dist/services/mention-handler.js +0 -405
  205. package/dist/services/mention-handler.js.map +0 -1
  206. package/dist/services/nango.d.ts +0 -219
  207. package/dist/services/nango.d.ts.map +0 -1
  208. package/dist/services/nango.js +0 -424
  209. package/dist/services/nango.js.map +0 -1
  210. package/dist/services/persistence.d.ts +0 -131
  211. package/dist/services/persistence.d.ts.map +0 -1
  212. package/dist/services/persistence.js +0 -200
  213. package/dist/services/persistence.js.map +0 -1
  214. package/dist/services/planLimits.d.ts +0 -147
  215. package/dist/services/planLimits.d.ts.map +0 -1
  216. package/dist/services/planLimits.js +0 -335
  217. package/dist/services/planLimits.js.map +0 -1
  218. package/dist/services/presence-registry.d.ts +0 -56
  219. package/dist/services/presence-registry.d.ts.map +0 -1
  220. package/dist/services/presence-registry.js +0 -91
  221. package/dist/services/presence-registry.js.map +0 -1
  222. package/dist/services/scaling-orchestrator.d.ts +0 -159
  223. package/dist/services/scaling-orchestrator.d.ts.map +0 -1
  224. package/dist/services/scaling-orchestrator.js +0 -502
  225. package/dist/services/scaling-orchestrator.js.map +0 -1
  226. package/dist/services/scaling-policy.d.ts +0 -121
  227. package/dist/services/scaling-policy.d.ts.map +0 -1
  228. package/dist/services/scaling-policy.js +0 -415
  229. package/dist/services/scaling-policy.js.map +0 -1
  230. package/dist/services/ssh-security.d.ts +0 -31
  231. package/dist/services/ssh-security.d.ts.map +0 -1
  232. package/dist/services/ssh-security.js +0 -63
  233. package/dist/services/ssh-security.js.map +0 -1
  234. package/dist/services/workspace-keepalive.d.ts +0 -76
  235. package/dist/services/workspace-keepalive.d.ts.map +0 -1
  236. package/dist/services/workspace-keepalive.js +0 -234
  237. package/dist/services/workspace-keepalive.js.map +0 -1
  238. package/dist/shims/consensus.d.ts +0 -23
  239. package/dist/shims/consensus.d.ts.map +0 -1
  240. package/dist/shims/consensus.js +0 -5
  241. package/dist/shims/consensus.js.map +0 -1
  242. package/dist/webhooks/index.d.ts +0 -24
  243. package/dist/webhooks/index.d.ts.map +0 -1
  244. package/dist/webhooks/index.js +0 -29
  245. package/dist/webhooks/index.js.map +0 -1
  246. package/dist/webhooks/parsers/github.d.ts +0 -8
  247. package/dist/webhooks/parsers/github.d.ts.map +0 -1
  248. package/dist/webhooks/parsers/github.js +0 -234
  249. package/dist/webhooks/parsers/github.js.map +0 -1
  250. package/dist/webhooks/parsers/index.d.ts +0 -23
  251. package/dist/webhooks/parsers/index.d.ts.map +0 -1
  252. package/dist/webhooks/parsers/index.js +0 -30
  253. package/dist/webhooks/parsers/index.js.map +0 -1
  254. package/dist/webhooks/parsers/linear.d.ts +0 -9
  255. package/dist/webhooks/parsers/linear.d.ts.map +0 -1
  256. package/dist/webhooks/parsers/linear.js +0 -258
  257. package/dist/webhooks/parsers/linear.js.map +0 -1
  258. package/dist/webhooks/parsers/slack.d.ts +0 -9
  259. package/dist/webhooks/parsers/slack.d.ts.map +0 -1
  260. package/dist/webhooks/parsers/slack.js +0 -214
  261. package/dist/webhooks/parsers/slack.js.map +0 -1
  262. package/dist/webhooks/responders/github.d.ts +0 -8
  263. package/dist/webhooks/responders/github.d.ts.map +0 -1
  264. package/dist/webhooks/responders/github.js +0 -73
  265. package/dist/webhooks/responders/github.js.map +0 -1
  266. package/dist/webhooks/responders/index.d.ts +0 -23
  267. package/dist/webhooks/responders/index.d.ts.map +0 -1
  268. package/dist/webhooks/responders/index.js +0 -30
  269. package/dist/webhooks/responders/index.js.map +0 -1
  270. package/dist/webhooks/responders/linear.d.ts +0 -9
  271. package/dist/webhooks/responders/linear.d.ts.map +0 -1
  272. package/dist/webhooks/responders/linear.js +0 -149
  273. package/dist/webhooks/responders/linear.js.map +0 -1
  274. package/dist/webhooks/responders/slack.d.ts +0 -20
  275. package/dist/webhooks/responders/slack.d.ts.map +0 -1
  276. package/dist/webhooks/responders/slack.js +0 -178
  277. package/dist/webhooks/responders/slack.js.map +0 -1
  278. package/dist/webhooks/router.d.ts +0 -25
  279. package/dist/webhooks/router.d.ts.map +0 -1
  280. package/dist/webhooks/router.js +0 -504
  281. package/dist/webhooks/router.js.map +0 -1
  282. package/dist/webhooks/rules-engine.d.ts +0 -24
  283. package/dist/webhooks/rules-engine.d.ts.map +0 -1
  284. package/dist/webhooks/rules-engine.js +0 -287
  285. package/dist/webhooks/rules-engine.js.map +0 -1
  286. package/dist/webhooks/types.d.ts +0 -186
  287. package/dist/webhooks/types.d.ts.map +0 -1
  288. package/dist/webhooks/types.js +0 -8
  289. package/dist/webhooks/types.js.map +0 -1
@@ -1,745 +0,0 @@
1
- /**
2
- * Test Helper API Routes
3
- *
4
- * These endpoints are ONLY available in test/development mode.
5
- * They allow integration tests to create users and daemons without OAuth.
6
- *
7
- * IMPORTANT: These routes are disabled in production (NODE_ENV=production).
8
- */
9
- import { Router } from 'express';
10
- import { randomUUID, createHash, randomBytes } from 'crypto';
11
- import { getDb } from '../db/drizzle.js';
12
- import { users, linkedDaemons, workspaces, repositories } from '../db/schema.js';
13
- import { getProvisioner } from '../provisioner/index.js';
14
- import { db } from '../db/index.js';
15
- import { nangoService } from '../services/nango.js';
16
- export const testHelpersRouter = Router();
17
- // Only enable in test/development mode
18
- const isTestMode = process.env.NODE_ENV !== 'production';
19
- if (!isTestMode) {
20
- console.warn('[test-helpers] Test helper routes are disabled in production');
21
- }
22
- /**
23
- * POST /api/test/create-user
24
- * Creates a test user without OAuth
25
- */
26
- testHelpersRouter.post('/create-user', async (req, res) => {
27
- if (!isTestMode) {
28
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
29
- }
30
- try {
31
- const { email, name } = req.body;
32
- const db = getDb();
33
- const testId = `test-${randomUUID()}`;
34
- // Create user with required GitHub fields
35
- const [user] = await db.insert(users).values({
36
- email: email || `${testId}@test.local`,
37
- githubId: testId,
38
- githubUsername: name || 'test-user',
39
- avatarUrl: null,
40
- }).returning();
41
- // Create session
42
- const sessionId = randomUUID();
43
- req.session.userId = user.id;
44
- // Get session cookie (simplified for testing)
45
- const sessionCookie = `connect.sid=s%3A${sessionId}`;
46
- res.json({
47
- userId: user.id,
48
- email: user.email,
49
- sessionCookie,
50
- });
51
- }
52
- catch (error) {
53
- console.error('Error creating test user:', error);
54
- res.status(500).json({ error: 'Failed to create test user' });
55
- }
56
- });
57
- /**
58
- * POST /api/test/create-daemon
59
- * Creates a test daemon with API key
60
- */
61
- testHelpersRouter.post('/create-daemon', async (req, res) => {
62
- if (!isTestMode) {
63
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
64
- }
65
- try {
66
- const { name, machineId } = req.body;
67
- if (!name) {
68
- return res.status(400).json({ error: 'name is required' });
69
- }
70
- const db = getDb();
71
- // First, ensure we have a test user to associate with the daemon
72
- let [testUser] = await db.select().from(users).limit(1);
73
- if (!testUser) {
74
- // Create a test user if none exists
75
- const testId = `test-system-${randomUUID()}`;
76
- [testUser] = await db.insert(users).values({
77
- email: `${testId}@test.local`,
78
- githubId: testId,
79
- githubUsername: 'test-system-user',
80
- avatarUrl: null,
81
- }).returning();
82
- }
83
- // Generate API key
84
- const apiKey = `ar_live_${randomBytes(32).toString('hex')}`;
85
- const apiKeyHash = createHash('sha256').update(apiKey).digest('hex');
86
- // Create daemon - only include fields that exist in schema
87
- const [daemon] = await db.insert(linkedDaemons).values({
88
- userId: testUser.id,
89
- name,
90
- machineId: machineId || randomUUID(),
91
- apiKeyHash,
92
- status: 'online',
93
- metadata: {
94
- hostname: 'test-host',
95
- platform: 'linux',
96
- version: '1.0.0-test',
97
- },
98
- }).returning();
99
- res.json({
100
- daemonId: daemon.id,
101
- apiKey,
102
- name: daemon.name,
103
- machineId: daemon.machineId,
104
- });
105
- }
106
- catch (error) {
107
- console.error('Error creating test daemon:', error);
108
- res.status(500).json({ error: 'Failed to create test daemon' });
109
- }
110
- });
111
- /**
112
- * POST /api/test/create-workspace
113
- * Creates a test workspace for integration tests with optional linked repository
114
- */
115
- testHelpersRouter.post('/create-workspace', async (req, res) => {
116
- if (!isTestMode) {
117
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
118
- }
119
- try {
120
- const { name, repoFullName, userId: providedUserId } = req.body;
121
- const db = getDb();
122
- // Use provided userId, session userId, or create a test user
123
- let targetUserId = providedUserId || req.session.userId;
124
- if (!targetUserId) {
125
- // Create a test user if none exists
126
- const testId = `test-ws-${randomUUID()}`;
127
- const [newUser] = await db.insert(users).values({
128
- email: `${testId}@test.local`,
129
- githubId: testId,
130
- githubUsername: 'workspace-test-user',
131
- avatarUrl: null,
132
- plan: 'free',
133
- }).returning();
134
- targetUserId = newUser.id;
135
- }
136
- const targetRepoFullName = repoFullName || `test-org/test-repo-${Date.now()}`;
137
- // Create workspace
138
- const [workspace] = await db.insert(workspaces).values({
139
- userId: targetUserId,
140
- name: name || `Test Workspace ${Date.now()}`,
141
- status: 'running',
142
- publicUrl: 'http://localhost:3889',
143
- computeProvider: 'docker',
144
- computeId: `test-${randomUUID().slice(0, 8)}`,
145
- config: {
146
- providers: ['anthropic'],
147
- repositories: [targetRepoFullName],
148
- supervisorEnabled: true,
149
- maxAgents: 10,
150
- },
151
- }).returning();
152
- // Create a linked repository for workspace lookup via repoFullName
153
- const [repo] = await db.insert(repositories).values({
154
- userId: targetUserId,
155
- workspaceId: workspace.id,
156
- githubId: Math.floor(Math.random() * 1000000),
157
- githubFullName: targetRepoFullName,
158
- isPrivate: false,
159
- defaultBranch: 'main',
160
- syncStatus: 'synced',
161
- nangoConnectionId: `mock-${randomUUID().slice(0, 8)}`,
162
- lastSyncedAt: new Date(),
163
- }).returning();
164
- res.json({
165
- workspaceId: workspace.id,
166
- name: workspace.name,
167
- repoFullName: repo.githubFullName,
168
- repoId: repo.id,
169
- userId: targetUserId,
170
- });
171
- }
172
- catch (error) {
173
- console.error('Error creating test workspace:', error);
174
- res.status(500).json({ error: 'Failed to create test workspace' });
175
- }
176
- });
177
- /**
178
- * POST /api/test/create-daemon-with-workspace
179
- * Creates a test daemon linked to a workspace
180
- */
181
- testHelpersRouter.post('/create-daemon-with-workspace', async (req, res) => {
182
- if (!isTestMode) {
183
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
184
- }
185
- try {
186
- const { name, machineId, workspaceId, userId: providedUserId } = req.body;
187
- if (!name) {
188
- return res.status(400).json({ error: 'name is required' });
189
- }
190
- const db = getDb();
191
- // Get or create test user
192
- let targetUserId = providedUserId;
193
- if (!targetUserId) {
194
- const existingUsers = await db.select().from(users).limit(1);
195
- if (existingUsers.length > 0) {
196
- targetUserId = existingUsers[0].id;
197
- }
198
- else {
199
- const testId = `test-daemon-${randomUUID()}`;
200
- const [newUser] = await db.insert(users).values({
201
- email: `${testId}@test.local`,
202
- githubId: testId,
203
- githubUsername: 'daemon-test-user',
204
- avatarUrl: null,
205
- plan: 'free',
206
- }).returning();
207
- targetUserId = newUser.id;
208
- }
209
- }
210
- // Generate API key
211
- const apiKey = `ar_live_${randomBytes(32).toString('hex')}`;
212
- const apiKeyHash = createHash('sha256').update(apiKey).digest('hex');
213
- // Create daemon with optional workspace link
214
- const [daemon] = await db.insert(linkedDaemons).values({
215
- userId: targetUserId,
216
- workspaceId: workspaceId || null,
217
- name,
218
- machineId: machineId || randomUUID(),
219
- apiKeyHash,
220
- status: 'online',
221
- metadata: {
222
- hostname: 'test-host',
223
- platform: 'linux',
224
- version: '1.0.0-test',
225
- },
226
- }).returning();
227
- res.json({
228
- daemonId: daemon.id,
229
- apiKey,
230
- name: daemon.name,
231
- machineId: daemon.machineId,
232
- workspaceId: daemon.workspaceId,
233
- userId: targetUserId,
234
- });
235
- }
236
- catch (error) {
237
- console.error('Error creating test daemon:', error);
238
- res.status(500).json({ error: 'Failed to create test daemon' });
239
- }
240
- });
241
- /**
242
- * DELETE /api/test/cleanup
243
- * Cleans up test data
244
- */
245
- testHelpersRouter.delete('/cleanup', async (req, res) => {
246
- if (!isTestMode) {
247
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
248
- }
249
- try {
250
- const _db = getDb();
251
- // Delete test data (users with test- prefix in githubId)
252
- // Note: This cascades to linked daemons due to FK constraints
253
- res.json({ success: true, message: 'Test data cleaned up' });
254
- }
255
- catch (error) {
256
- console.error('Error cleaning up test data:', error);
257
- res.status(500).json({ error: 'Failed to cleanup test data' });
258
- }
259
- });
260
- /**
261
- * GET /api/test/status
262
- * Returns test mode status
263
- */
264
- testHelpersRouter.get('/status', (req, res) => {
265
- res.json({
266
- testMode: isTestMode,
267
- nodeEnv: process.env.NODE_ENV,
268
- timestamp: new Date().toISOString(),
269
- });
270
- });
271
- /**
272
- * POST /api/test/create-mock-workspace
273
- * Creates a mock workspace pointing to a local dashboard server
274
- *
275
- * Use this to test the cloud flow locally without real provisioning.
276
- * The workspace will have publicUrl pointing to localhost:3889.
277
- */
278
- testHelpersRouter.post('/create-mock-workspace', async (req, res) => {
279
- if (!isTestMode) {
280
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
281
- }
282
- try {
283
- const { name, publicUrl } = req.body;
284
- const userId = req.session.userId;
285
- if (!userId) {
286
- return res.status(401).json({ error: 'Must be logged in. Use /api/test/create-user first or log in via OAuth.' });
287
- }
288
- const db = getDb();
289
- // Create a mock workspace with local publicUrl
290
- const [workspace] = await db.insert(workspaces).values({
291
- userId,
292
- name: name || 'Local Test Workspace',
293
- status: 'running',
294
- publicUrl: publicUrl || 'http://localhost:3889',
295
- computeProvider: 'docker',
296
- computeId: `mock-${randomUUID().slice(0, 8)}`,
297
- config: {
298
- providers: ['anthropic'],
299
- repositories: [],
300
- supervisorEnabled: true,
301
- maxAgents: 10,
302
- },
303
- }).returning();
304
- res.json({
305
- workspaceId: workspace.id,
306
- name: workspace.name,
307
- status: workspace.status,
308
- publicUrl: workspace.publicUrl,
309
- message: 'Mock workspace created. Start agent-relay locally and navigate to /app.',
310
- });
311
- }
312
- catch (error) {
313
- console.error('Error creating mock workspace:', error);
314
- res.status(500).json({ error: 'Failed to create mock workspace' });
315
- }
316
- });
317
- /**
318
- * POST /api/test/create-mock-repo
319
- * Creates a mock repository for the current user
320
- *
321
- * Use this to test the cloud flow without connecting real GitHub repos.
322
- */
323
- testHelpersRouter.post('/create-mock-repo', async (req, res) => {
324
- if (!isTestMode) {
325
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
326
- }
327
- try {
328
- const { fullName, isPrivate } = req.body;
329
- const userId = req.session.userId;
330
- if (!userId) {
331
- return res.status(401).json({ error: 'Must be logged in. Use /api/test/create-user first or log in via OAuth.' });
332
- }
333
- if (!fullName) {
334
- return res.status(400).json({ error: 'fullName is required (e.g., "owner/repo")' });
335
- }
336
- const db = getDb();
337
- // Create a mock repository
338
- const [repo] = await db.insert(repositories).values({
339
- userId,
340
- githubId: Math.floor(Math.random() * 1000000),
341
- githubFullName: fullName,
342
- isPrivate: isPrivate ?? false,
343
- defaultBranch: 'main',
344
- syncStatus: 'synced',
345
- nangoConnectionId: `mock-connection-${randomUUID().slice(0, 8)}`,
346
- lastSyncedAt: new Date(),
347
- }).returning();
348
- res.json({
349
- repoId: repo.id,
350
- fullName: repo.githubFullName,
351
- isPrivate: repo.isPrivate,
352
- message: 'Mock repository created.',
353
- });
354
- }
355
- catch (error) {
356
- console.error('Error creating mock repo:', error);
357
- res.status(500).json({ error: 'Failed to create mock repo' });
358
- }
359
- });
360
- /**
361
- * GET /api/test/auto-login
362
- * Browser-friendly auto-login - visit this URL to login and redirect
363
- * Usage: /api/test/auto-login?redirect=/providers/setup/claude?workspace=xxx
364
- */
365
- testHelpersRouter.get('/auto-login', async (req, res) => {
366
- if (!isTestMode) {
367
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
368
- }
369
- try {
370
- const db = getDb();
371
- const redirect = req.query.redirect || '/app';
372
- // Find or create test user
373
- let user;
374
- const existingUsers = await db.select().from(users).limit(1);
375
- if (existingUsers.length > 0) {
376
- user = existingUsers[0];
377
- }
378
- else {
379
- const testId = `test-${randomUUID()}`;
380
- const [newUser] = await db.insert(users).values({
381
- email: `${testId}@test.local`,
382
- githubId: testId,
383
- githubUsername: 'test-user',
384
- avatarUrl: null,
385
- plan: 'free',
386
- }).returning();
387
- user = newUser;
388
- }
389
- // Set session and CSRF token
390
- req.session.userId = user.id;
391
- req.session.csrfToken = randomUUID();
392
- // Redirect to requested page
393
- res.redirect(redirect);
394
- }
395
- catch (error) {
396
- console.error('Error in auto-login:', error);
397
- res.status(500).json({ error: 'Failed to auto-login' });
398
- }
399
- });
400
- /**
401
- * POST /api/test/login-as
402
- * Quick login for testing - creates session for existing or new test user
403
- */
404
- testHelpersRouter.post('/login-as', async (req, res) => {
405
- if (!isTestMode) {
406
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
407
- }
408
- try {
409
- const { username } = req.body;
410
- const db = getDb();
411
- // Find or create user
412
- let user;
413
- const existingUsers = await db.select().from(users).limit(1);
414
- if (existingUsers.length > 0 && !username) {
415
- user = existingUsers[0];
416
- }
417
- else {
418
- const testId = `test-${randomUUID()}`;
419
- const [newUser] = await db.insert(users).values({
420
- email: `${username || testId}@test.local`,
421
- githubId: testId,
422
- githubUsername: username || 'test-user',
423
- avatarUrl: null,
424
- plan: 'free',
425
- }).returning();
426
- user = newUser;
427
- }
428
- // Set session
429
- req.session.userId = user.id;
430
- res.json({
431
- success: true,
432
- userId: user.id,
433
- username: user.githubUsername,
434
- message: 'Logged in. You can now access /app and other authenticated routes.',
435
- });
436
- }
437
- catch (error) {
438
- console.error('Error in login-as:', error);
439
- res.status(500).json({ error: 'Failed to login' });
440
- }
441
- });
442
- /**
443
- * GET /api/test/setup-local-cloud
444
- * One-shot setup: creates user, mock repo, and mock workspace
445
- *
446
- * After calling this, start agent-relay locally and go to /app
447
- */
448
- testHelpersRouter.post('/setup-local-cloud', async (req, res) => {
449
- if (!isTestMode) {
450
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
451
- }
452
- try {
453
- const { repoName, workspaceName } = req.body;
454
- const db = getDb();
455
- // 1. Create or get test user
456
- const testId = `test-${randomUUID().slice(0, 8)}`;
457
- const [user] = await db.insert(users).values({
458
- email: `${testId}@test.local`,
459
- githubId: testId,
460
- githubUsername: 'local-tester',
461
- avatarUrl: null,
462
- plan: 'free',
463
- }).returning();
464
- // Set session
465
- req.session.userId = user.id;
466
- // 2. Create mock repository
467
- const [repo] = await db.insert(repositories).values({
468
- userId: user.id,
469
- githubId: Math.floor(Math.random() * 1000000),
470
- githubFullName: repoName || 'test-org/test-repo',
471
- isPrivate: false,
472
- defaultBranch: 'main',
473
- syncStatus: 'synced',
474
- nangoConnectionId: `mock-${randomUUID().slice(0, 8)}`,
475
- lastSyncedAt: new Date(),
476
- }).returning();
477
- // 3. Create mock workspace pointing to local dashboard
478
- const [workspace] = await db.insert(workspaces).values({
479
- userId: user.id,
480
- name: workspaceName || 'Local Development',
481
- status: 'running',
482
- publicUrl: 'http://localhost:3889',
483
- computeProvider: 'docker',
484
- computeId: `mock-${randomUUID().slice(0, 8)}`,
485
- config: {
486
- providers: ['anthropic'],
487
- repositories: [repo.githubFullName],
488
- supervisorEnabled: true,
489
- maxAgents: 10,
490
- },
491
- }).returning();
492
- res.json({
493
- success: true,
494
- user: {
495
- id: user.id,
496
- username: user.githubUsername,
497
- },
498
- repo: {
499
- id: repo.id,
500
- fullName: repo.githubFullName,
501
- },
502
- workspace: {
503
- id: workspace.id,
504
- name: workspace.name,
505
- publicUrl: workspace.publicUrl,
506
- },
507
- instructions: [
508
- '1. Start agent-relay daemon: npm run dev (or agent-relay up)',
509
- '2. Go to http://localhost:4567/app',
510
- '3. The app should auto-connect to the local workspace',
511
- '4. The WebSocket will connect to ws://localhost:3889/ws',
512
- ],
513
- });
514
- }
515
- catch (error) {
516
- console.error('Error in setup-local-cloud:', error);
517
- res.status(500).json({ error: 'Failed to setup local cloud' });
518
- }
519
- });
520
- /**
521
- * POST /api/test/provision-real-workspace
522
- * Provision a REAL Docker container using your Nango GitHub App connection.
523
- *
524
- * This tests the full flow including:
525
- * - Fetching GitHub App token from Nango
526
- * - Spinning up a Docker container
527
- * - Cloning your actual repositories
528
- *
529
- * Prerequisites:
530
- * - Must be logged in (via real OAuth or /api/test/login-as)
531
- * - Must have connected repos via /connect-repos (real Nango GitHub App OAuth)
532
- * - Docker must be running locally
533
- * - COMPUTE_PROVIDER must be 'docker' (default for dev)
534
- */
535
- testHelpersRouter.post('/provision-real-workspace', async (req, res) => {
536
- if (!isTestMode) {
537
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
538
- }
539
- const userId = req.session.userId;
540
- if (!userId) {
541
- return res.status(401).json({
542
- error: 'Must be logged in. Use real OAuth or /api/test/login-as first.',
543
- });
544
- }
545
- try {
546
- const { name, repositoryFullName, providers, githubToken } = req.body;
547
- // Get user's connected repositories
548
- const userRepos = await db.repositories.findByUserId(userId);
549
- const reposWithNango = userRepos.filter(r => r.nangoConnectionId);
550
- if (reposWithNango.length === 0) {
551
- return res.status(400).json({
552
- error: 'No repositories with Nango connection found. Complete /connect-repos first with real GitHub OAuth.',
553
- hint: 'Go to http://localhost:4567/connect-repos and connect your GitHub App, or pass githubToken directly',
554
- });
555
- }
556
- // Determine which repo to use
557
- let targetRepo = reposWithNango[0];
558
- if (repositoryFullName) {
559
- const found = reposWithNango.find(r => r.githubFullName === repositoryFullName);
560
- if (!found) {
561
- return res.status(400).json({
562
- error: `Repository ${repositoryFullName} not found or not connected via Nango`,
563
- availableRepos: reposWithNango.map(r => r.githubFullName),
564
- });
565
- }
566
- targetRepo = found;
567
- }
568
- // Use the real provisioner (Docker in dev mode)
569
- const provisioner = getProvisioner();
570
- const result = await provisioner.provision({
571
- userId,
572
- name: name || `Test Workspace - ${targetRepo.githubFullName}`,
573
- providers: providers || ['anthropic'], // Default to anthropic if not specified
574
- repositories: [targetRepo.githubFullName],
575
- supervisorEnabled: true,
576
- maxAgents: 10,
577
- // Allow passing GitHub token directly for local testing
578
- githubToken: githubToken || undefined,
579
- });
580
- if (result.status === 'error') {
581
- return res.status(500).json({
582
- error: 'Provisioning failed',
583
- details: result.error,
584
- });
585
- }
586
- res.json({
587
- success: true,
588
- workspace: {
589
- id: result.workspaceId,
590
- status: result.status,
591
- publicUrl: result.publicUrl,
592
- },
593
- repository: targetRepo.githubFullName,
594
- instructions: [
595
- `1. Workspace is running at ${result.publicUrl}`,
596
- `2. Repository ${targetRepo.githubFullName} should be cloned`,
597
- `3. Go to http://localhost:4567/app to connect`,
598
- `4. Check container: docker logs ar-${result.workspaceId.substring(0, 8)}`,
599
- `5. Verify clone: docker exec ar-${result.workspaceId.substring(0, 8)} ls /workspace/repos`,
600
- ],
601
- });
602
- }
603
- catch (error) {
604
- console.error('Error provisioning real workspace:', error);
605
- res.status(500).json({
606
- error: 'Failed to provision workspace',
607
- details: error instanceof Error ? error.message : 'Unknown error',
608
- });
609
- }
610
- });
611
- /**
612
- * GET /api/test/my-repos
613
- * List current user's connected repositories (for debugging)
614
- */
615
- testHelpersRouter.get('/my-repos', async (req, res) => {
616
- if (!isTestMode) {
617
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
618
- }
619
- const userId = req.session.userId;
620
- if (!userId) {
621
- return res.status(401).json({ error: 'Not logged in' });
622
- }
623
- try {
624
- const repos = await db.repositories.findByUserId(userId);
625
- res.json({
626
- userId,
627
- repositories: repos.map(r => ({
628
- id: r.id,
629
- fullName: r.githubFullName,
630
- isPrivate: r.isPrivate,
631
- hasNangoConnection: !!r.nangoConnectionId,
632
- nangoConnectionId: r.nangoConnectionId, // For debugging
633
- syncStatus: r.syncStatus,
634
- })),
635
- });
636
- }
637
- catch (error) {
638
- console.error('Error fetching repos:', error);
639
- res.status(500).json({ error: 'Failed to fetch repositories' });
640
- }
641
- });
642
- /**
643
- * GET /api/test/my-workspaces
644
- * List current user's workspaces (for debugging)
645
- */
646
- testHelpersRouter.get('/my-workspaces', async (req, res) => {
647
- if (!isTestMode) {
648
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
649
- }
650
- const userId = req.session.userId;
651
- if (!userId) {
652
- return res.status(401).json({ error: 'Not logged in' });
653
- }
654
- try {
655
- const userWorkspaces = await db.workspaces.findByUserId(userId);
656
- res.json({
657
- userId,
658
- workspaces: userWorkspaces.map(w => ({
659
- id: w.id,
660
- name: w.name,
661
- status: w.status,
662
- publicUrl: w.publicUrl,
663
- computeProvider: w.computeProvider,
664
- computeId: w.computeId,
665
- config: w.config,
666
- })),
667
- });
668
- }
669
- catch (error) {
670
- console.error('Error fetching workspaces:', error);
671
- res.status(500).json({ error: 'Failed to fetch workspaces' });
672
- }
673
- });
674
- /**
675
- * GET /api/test/nango-token
676
- * Test fetching GitHub App token from Nango (for debugging)
677
- */
678
- testHelpersRouter.get('/nango-token', async (req, res) => {
679
- if (!isTestMode) {
680
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
681
- }
682
- const userId = req.session.userId;
683
- if (!userId) {
684
- return res.status(401).json({ error: 'Not logged in' });
685
- }
686
- try {
687
- const repos = await db.repositories.findByUserId(userId);
688
- const repoWithConnection = repos.find(r => r.nangoConnectionId);
689
- if (!repoWithConnection?.nangoConnectionId) {
690
- return res.status(400).json({
691
- error: 'No Nango connection found',
692
- repos: repos.map(r => ({ fullName: r.githubFullName, nangoConnectionId: r.nangoConnectionId })),
693
- });
694
- }
695
- console.log('[test] Fetching token for connection:', repoWithConnection.nangoConnectionId);
696
- const token = await nangoService.getGithubAppToken(repoWithConnection.nangoConnectionId);
697
- res.json({
698
- success: true,
699
- connectionId: repoWithConnection.nangoConnectionId,
700
- tokenLength: token.length,
701
- tokenPrefix: token.substring(0, 10) + '...',
702
- });
703
- }
704
- catch (error) {
705
- console.error('[test] Nango token fetch error:', error);
706
- res.status(500).json({
707
- error: 'Failed to fetch token',
708
- details: error instanceof Error ? error.message : 'Unknown error',
709
- });
710
- }
711
- });
712
- /**
713
- * DELETE /api/test/workspace/:id
714
- * Delete/deprovision a workspace (for cleanup)
715
- */
716
- testHelpersRouter.delete('/workspace/:id', async (req, res) => {
717
- if (!isTestMode) {
718
- return res.status(403).json({ error: 'Test endpoints disabled in production' });
719
- }
720
- const userId = req.session.userId;
721
- if (!userId) {
722
- return res.status(401).json({ error: 'Not logged in' });
723
- }
724
- try {
725
- const id = req.params.id;
726
- const workspace = await db.workspaces.findById(id);
727
- if (!workspace) {
728
- return res.status(404).json({ error: 'Workspace not found' });
729
- }
730
- if (workspace.userId !== userId) {
731
- return res.status(403).json({ error: 'Not your workspace' });
732
- }
733
- const provisioner = getProvisioner();
734
- await provisioner.deprovision(id);
735
- res.json({
736
- success: true,
737
- message: `Workspace ${id} deleted`,
738
- });
739
- }
740
- catch (error) {
741
- console.error('Error deleting workspace:', error);
742
- res.status(500).json({ error: 'Failed to delete workspace' });
743
- }
744
- });
745
- //# sourceMappingURL=test-helpers.js.map