@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,302 @@
1
+ /**
2
+ * Agent Session Persistence API Routes
3
+ *
4
+ * Provides endpoints for workspace containers to persist agent session data.
5
+ * Workspaces call these endpoints instead of accessing the database directly,
6
+ * which provides better security isolation (workspaces can only write their own data).
7
+ *
8
+ * Authentication: Workspace token (same as git gateway)
9
+ */
10
+ import crypto from 'crypto';
11
+ import { Router } from 'express';
12
+ import { eq } from 'drizzle-orm';
13
+ import { getDb } from '../db/drizzle.js';
14
+ import { agentSessions, agentSummaries } from '../db/schema.js';
15
+ import { getConfig } from '../config.js';
16
+ export const sessionsRouter = Router();
17
+ // Validation patterns
18
+ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19
+ const AGENT_NAME_REGEX = /^[a-zA-Z0-9_-]+$/;
20
+ const MAX_AGENT_NAME_LENGTH = 255;
21
+ /**
22
+ * Generate expected workspace token using HMAC
23
+ */
24
+ function generateExpectedToken(workspaceId) {
25
+ const config = getConfig();
26
+ return crypto
27
+ .createHmac('sha256', config.sessionSecret)
28
+ .update(`workspace:${workspaceId}`)
29
+ .digest('hex');
30
+ }
31
+ /**
32
+ * Verify workspace access token
33
+ */
34
+ function verifyWorkspaceToken(req, workspaceId) {
35
+ const authHeader = req.get('authorization');
36
+ if (!authHeader) {
37
+ return { valid: false, reason: 'No Authorization header. WORKSPACE_TOKEN may not be set in the container.' };
38
+ }
39
+ if (!authHeader.startsWith('Bearer ')) {
40
+ return { valid: false, reason: 'Invalid Authorization header format. Expected: Bearer <token>' };
41
+ }
42
+ const providedToken = authHeader.slice(7);
43
+ if (!providedToken) {
44
+ return { valid: false, reason: 'Empty bearer token provided.' };
45
+ }
46
+ const expectedToken = generateExpectedToken(workspaceId);
47
+ try {
48
+ const isValid = crypto.timingSafeEqual(Buffer.from(providedToken), Buffer.from(expectedToken));
49
+ if (!isValid) {
50
+ return { valid: false, reason: 'Token mismatch. Workspace may need reprovisioning or SESSION_SECRET changed.' };
51
+ }
52
+ return { valid: true };
53
+ }
54
+ catch {
55
+ return { valid: false, reason: 'Token comparison failed (length mismatch). Workspace may need reprovisioning.' };
56
+ }
57
+ }
58
+ /**
59
+ * Validate UUID format
60
+ */
61
+ function isValidUUID(value) {
62
+ return UUID_REGEX.test(value);
63
+ }
64
+ /**
65
+ * Validate agent name format
66
+ */
67
+ function isValidAgentName(name) {
68
+ if (name.length > MAX_AGENT_NAME_LENGTH) {
69
+ return { valid: false, reason: `agentName exceeds maximum length of ${MAX_AGENT_NAME_LENGTH} characters` };
70
+ }
71
+ if (!AGENT_NAME_REGEX.test(name)) {
72
+ return { valid: false, reason: 'agentName contains invalid characters (only alphanumeric, underscore, and hyphen allowed)' };
73
+ }
74
+ return { valid: true };
75
+ }
76
+ /**
77
+ * Validate summary object structure
78
+ */
79
+ function validateSummary(summary) {
80
+ if (typeof summary !== 'object' || summary === null || Array.isArray(summary)) {
81
+ return { valid: false, reason: 'summary must be an object' };
82
+ }
83
+ const s = summary;
84
+ const allowedKeys = ['currentTask', 'completedTasks', 'decisions', 'context', 'files'];
85
+ for (const key of Object.keys(s)) {
86
+ if (!allowedKeys.includes(key)) {
87
+ // Allow extra keys but log warning (don't reject - for forward compatibility)
88
+ continue;
89
+ }
90
+ }
91
+ // Validate types of known fields
92
+ if (s.currentTask !== undefined && typeof s.currentTask !== 'string') {
93
+ return { valid: false, reason: 'summary.currentTask must be a string' };
94
+ }
95
+ if (s.completedTasks !== undefined && !Array.isArray(s.completedTasks)) {
96
+ return { valid: false, reason: 'summary.completedTasks must be an array' };
97
+ }
98
+ if (s.decisions !== undefined && !Array.isArray(s.decisions)) {
99
+ return { valid: false, reason: 'summary.decisions must be an array' };
100
+ }
101
+ if (s.context !== undefined && typeof s.context !== 'string') {
102
+ return { valid: false, reason: 'summary.context must be a string' };
103
+ }
104
+ if (s.files !== undefined && !Array.isArray(s.files)) {
105
+ return { valid: false, reason: 'summary.files must be an array' };
106
+ }
107
+ return { valid: true };
108
+ }
109
+ /**
110
+ * POST /api/sessions/create
111
+ * Create a new agent session
112
+ *
113
+ * Body: { workspaceId: string, agentName: string }
114
+ * Returns: { sessionId: string }
115
+ */
116
+ sessionsRouter.post('/create', async (req, res) => {
117
+ const { workspaceId, agentName } = req.body;
118
+ if (!workspaceId || typeof workspaceId !== 'string') {
119
+ return res.status(400).json({ error: 'workspaceId is required', code: 'MISSING_WORKSPACE_ID' });
120
+ }
121
+ if (!isValidUUID(workspaceId)) {
122
+ return res.status(400).json({ error: 'workspaceId must be a valid UUID', code: 'INVALID_WORKSPACE_ID' });
123
+ }
124
+ if (!agentName || typeof agentName !== 'string') {
125
+ return res.status(400).json({ error: 'agentName is required', code: 'MISSING_AGENT_NAME' });
126
+ }
127
+ const agentNameValidation = isValidAgentName(agentName);
128
+ if (!agentNameValidation.valid) {
129
+ return res.status(400).json({ error: agentNameValidation.reason, code: 'INVALID_AGENT_NAME' });
130
+ }
131
+ const tokenVerification = verifyWorkspaceToken(req, workspaceId);
132
+ if (!tokenVerification.valid) {
133
+ console.warn(`[sessions] Token verification failed for workspace ${workspaceId.substring(0, 8)}: ${tokenVerification.reason}`);
134
+ return res.status(401).json({
135
+ error: 'Invalid workspace token',
136
+ code: 'INVALID_WORKSPACE_TOKEN',
137
+ hint: tokenVerification.reason,
138
+ });
139
+ }
140
+ try {
141
+ const db = getDb();
142
+ const result = await db.insert(agentSessions).values({
143
+ workspaceId,
144
+ agentName,
145
+ status: 'active',
146
+ startedAt: new Date(),
147
+ }).returning();
148
+ const session = result[0];
149
+ if (!session) {
150
+ return res.status(500).json({ error: 'Failed to create session', code: 'CREATE_FAILED' });
151
+ }
152
+ console.log(`[sessions] Created session ${session.id.substring(0, 8)} for ${agentName} in workspace ${workspaceId.substring(0, 8)}`);
153
+ return res.json({ sessionId: session.id });
154
+ }
155
+ catch (err) {
156
+ console.error(`[sessions] Failed to create session:`, err);
157
+ return res.status(500).json({ error: 'Internal server error', code: 'INTERNAL_ERROR' });
158
+ }
159
+ });
160
+ /**
161
+ * POST /api/sessions/summary
162
+ * Add a summary to an existing session
163
+ *
164
+ * Body: {
165
+ * workspaceId: string,
166
+ * sessionId: string,
167
+ * agentName: string,
168
+ * summary: { currentTask?: string, completedTasks?: string[], ... }
169
+ * }
170
+ * Returns: { summaryId: string }
171
+ */
172
+ sessionsRouter.post('/summary', async (req, res) => {
173
+ const { workspaceId, sessionId, agentName, summary } = req.body;
174
+ if (!workspaceId || typeof workspaceId !== 'string') {
175
+ return res.status(400).json({ error: 'workspaceId is required', code: 'MISSING_WORKSPACE_ID' });
176
+ }
177
+ if (!isValidUUID(workspaceId)) {
178
+ return res.status(400).json({ error: 'workspaceId must be a valid UUID', code: 'INVALID_WORKSPACE_ID' });
179
+ }
180
+ if (!sessionId || typeof sessionId !== 'string') {
181
+ return res.status(400).json({ error: 'sessionId is required', code: 'MISSING_SESSION_ID' });
182
+ }
183
+ if (!isValidUUID(sessionId)) {
184
+ return res.status(400).json({ error: 'sessionId must be a valid UUID', code: 'INVALID_SESSION_ID' });
185
+ }
186
+ if (!agentName || typeof agentName !== 'string') {
187
+ return res.status(400).json({ error: 'agentName is required', code: 'MISSING_AGENT_NAME' });
188
+ }
189
+ const agentNameValidation = isValidAgentName(agentName);
190
+ if (!agentNameValidation.valid) {
191
+ return res.status(400).json({ error: agentNameValidation.reason, code: 'INVALID_AGENT_NAME' });
192
+ }
193
+ if (!summary) {
194
+ return res.status(400).json({ error: 'summary is required', code: 'MISSING_SUMMARY' });
195
+ }
196
+ const summaryValidation = validateSummary(summary);
197
+ if (!summaryValidation.valid) {
198
+ return res.status(400).json({ error: summaryValidation.reason, code: 'INVALID_SUMMARY' });
199
+ }
200
+ const tokenVerification = verifyWorkspaceToken(req, workspaceId);
201
+ if (!tokenVerification.valid) {
202
+ console.warn(`[sessions] Summary: Token verification failed for workspace ${workspaceId.substring(0, 8)}`);
203
+ return res.status(401).json({
204
+ error: 'Invalid workspace token',
205
+ code: 'INVALID_WORKSPACE_TOKEN',
206
+ hint: tokenVerification.reason,
207
+ });
208
+ }
209
+ try {
210
+ const db = getDb();
211
+ // Verify the session exists and belongs to this workspace
212
+ const existingSession = await db.select()
213
+ .from(agentSessions)
214
+ .where(eq(agentSessions.id, sessionId))
215
+ .limit(1);
216
+ if (!existingSession[0]) {
217
+ return res.status(404).json({ error: 'Session not found', code: 'SESSION_NOT_FOUND' });
218
+ }
219
+ if (existingSession[0].workspaceId !== workspaceId) {
220
+ return res.status(403).json({ error: 'Session does not belong to this workspace', code: 'SESSION_FORBIDDEN' });
221
+ }
222
+ const result = await db.insert(agentSummaries).values({
223
+ sessionId,
224
+ agentName,
225
+ summary,
226
+ createdAt: new Date(),
227
+ }).returning();
228
+ const summaryRecord = result[0];
229
+ if (!summaryRecord) {
230
+ return res.status(500).json({ error: 'Failed to create summary', code: 'CREATE_FAILED' });
231
+ }
232
+ console.log(`[sessions] Saved summary for ${agentName}: ${summary.currentTask || 'no task'}`);
233
+ return res.json({ summaryId: summaryRecord.id });
234
+ }
235
+ catch (err) {
236
+ console.error(`[sessions] Failed to save summary:`, err);
237
+ return res.status(500).json({ error: 'Internal server error', code: 'INTERNAL_ERROR' });
238
+ }
239
+ });
240
+ /**
241
+ * POST /api/sessions/end
242
+ * Mark a session as ended
243
+ *
244
+ * Body: {
245
+ * workspaceId: string,
246
+ * sessionId: string,
247
+ * endMarker: { summary?: string, completedTasks?: string[] }
248
+ * }
249
+ * Returns: { success: true }
250
+ */
251
+ sessionsRouter.post('/end', async (req, res) => {
252
+ const { workspaceId, sessionId, endMarker } = req.body;
253
+ if (!workspaceId || typeof workspaceId !== 'string') {
254
+ return res.status(400).json({ error: 'workspaceId is required', code: 'MISSING_WORKSPACE_ID' });
255
+ }
256
+ if (!isValidUUID(workspaceId)) {
257
+ return res.status(400).json({ error: 'workspaceId must be a valid UUID', code: 'INVALID_WORKSPACE_ID' });
258
+ }
259
+ if (!sessionId || typeof sessionId !== 'string') {
260
+ return res.status(400).json({ error: 'sessionId is required', code: 'MISSING_SESSION_ID' });
261
+ }
262
+ if (!isValidUUID(sessionId)) {
263
+ return res.status(400).json({ error: 'sessionId must be a valid UUID', code: 'INVALID_SESSION_ID' });
264
+ }
265
+ const tokenVerification = verifyWorkspaceToken(req, workspaceId);
266
+ if (!tokenVerification.valid) {
267
+ console.warn(`[sessions] End: Token verification failed for workspace ${workspaceId.substring(0, 8)}`);
268
+ return res.status(401).json({
269
+ error: 'Invalid workspace token',
270
+ code: 'INVALID_WORKSPACE_TOKEN',
271
+ hint: tokenVerification.reason,
272
+ });
273
+ }
274
+ try {
275
+ const db = getDb();
276
+ // Verify the session exists and belongs to this workspace
277
+ const existingSession = await db.select()
278
+ .from(agentSessions)
279
+ .where(eq(agentSessions.id, sessionId))
280
+ .limit(1);
281
+ if (!existingSession[0]) {
282
+ return res.status(404).json({ error: 'Session not found', code: 'SESSION_NOT_FOUND' });
283
+ }
284
+ if (existingSession[0].workspaceId !== workspaceId) {
285
+ return res.status(403).json({ error: 'Session does not belong to this workspace', code: 'SESSION_FORBIDDEN' });
286
+ }
287
+ await db.update(agentSessions)
288
+ .set({
289
+ status: 'ended',
290
+ endedAt: new Date(),
291
+ endMarker: endMarker || {},
292
+ })
293
+ .where(eq(agentSessions.id, sessionId));
294
+ console.log(`[sessions] Session ended for workspace ${workspaceId.substring(0, 8)}: ${endMarker?.summary || 'no summary'}`);
295
+ return res.json({ success: true });
296
+ }
297
+ catch (err) {
298
+ console.error(`[sessions] Failed to end session:`, err);
299
+ return res.status(500).json({ error: 'Internal server error', code: 'INTERNAL_ERROR' });
300
+ }
301
+ });
302
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/api/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Teams API Routes
3
+ *
4
+ * Manage workspace members, invitations, and roles.
5
+ */
6
+ export declare const teamsRouter: import("express-serve-static-core").Router;
7
+ //# sourceMappingURL=teams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams.d.ts","sourceRoot":"","sources":["../../src/api/teams.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,eAAO,MAAM,WAAW,4CAAW,CAAC"}
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Teams API Routes
3
+ *
4
+ * Manage workspace members, invitations, and roles.
5
+ */
6
+ import { Router } from 'express';
7
+ import { requireAuth } from './auth.js';
8
+ import { db } from '../db/index.js';
9
+ export const teamsRouter = Router();
10
+ // All routes require authentication
11
+ teamsRouter.use(requireAuth);
12
+ /**
13
+ * GET /api/workspaces/:workspaceId/members
14
+ * List workspace members
15
+ */
16
+ teamsRouter.get('/workspaces/:workspaceId/members', async (req, res) => {
17
+ const userId = req.session.userId;
18
+ const workspaceId = req.params.workspaceId;
19
+ try {
20
+ // Check user has access to workspace
21
+ const canView = await db.workspaceMembers.canView(workspaceId, userId);
22
+ if (!canView) {
23
+ // Also check if user is the workspace owner (legacy single-user workspaces)
24
+ const workspace = await db.workspaces.findById(workspaceId);
25
+ if (!workspace || workspace.userId !== userId) {
26
+ return res.status(403).json({ error: 'Access denied' });
27
+ }
28
+ }
29
+ const members = await db.workspaceMembers.findByWorkspaceId(workspaceId);
30
+ // Fetch user info for each member
31
+ const membersWithUsers = await Promise.all(members.map(async (m) => {
32
+ const user = await db.users.findById(m.userId);
33
+ return {
34
+ id: m.id,
35
+ userId: m.userId,
36
+ role: m.role,
37
+ invitedAt: m.invitedAt,
38
+ acceptedAt: m.acceptedAt,
39
+ isPending: !m.acceptedAt,
40
+ user: user
41
+ ? {
42
+ githubUsername: user.githubUsername,
43
+ email: user.email ?? undefined,
44
+ avatarUrl: user.avatarUrl ?? undefined,
45
+ }
46
+ : undefined,
47
+ };
48
+ }));
49
+ res.json({ members: membersWithUsers });
50
+ }
51
+ catch (error) {
52
+ console.error('Error listing members:', error);
53
+ res.status(500).json({ error: 'Failed to list members' });
54
+ }
55
+ });
56
+ /**
57
+ * POST /api/workspaces/:workspaceId/members
58
+ * Invite a user to workspace
59
+ */
60
+ teamsRouter.post('/workspaces/:workspaceId/members', async (req, res) => {
61
+ const userId = req.session.userId;
62
+ const workspaceId = req.params.workspaceId;
63
+ const { githubUsername, role = 'member' } = req.body;
64
+ if (!githubUsername) {
65
+ return res.status(400).json({ error: 'GitHub username is required' });
66
+ }
67
+ const validRoles = ['admin', 'member', 'viewer'];
68
+ if (!validRoles.includes(role)) {
69
+ return res.status(400).json({ error: 'Invalid role. Must be admin, member, or viewer' });
70
+ }
71
+ try {
72
+ // Check user is owner or admin
73
+ const isOwner = await db.workspaceMembers.isOwner(workspaceId, userId);
74
+ const workspace = await db.workspaces.findById(workspaceId);
75
+ if (!isOwner && workspace?.userId !== userId) {
76
+ const membership = await db.workspaceMembers.findMembership(workspaceId, userId);
77
+ if (!membership || membership.role !== 'admin') {
78
+ return res.status(403).json({ error: 'Only owners and admins can invite members' });
79
+ }
80
+ }
81
+ // Check plan allows team members
82
+ const owner = await db.users.findById(workspace.userId);
83
+ if (owner?.plan !== 'team' && owner?.plan !== 'enterprise') {
84
+ return res.status(402).json({
85
+ error: 'Team members require Team or Enterprise plan',
86
+ upgrade: '/settings/billing',
87
+ });
88
+ }
89
+ // Find user by GitHub username
90
+ const invitee = await db.users.findByGithubUsername(githubUsername);
91
+ if (!invitee) {
92
+ return res.status(404).json({
93
+ error: 'User not found. They must sign up first.',
94
+ inviteLink: `https://agent-relay.com/invite?workspace=${workspaceId}`,
95
+ });
96
+ }
97
+ // Check if already a member
98
+ const existing = await db.workspaceMembers.findMembership(workspaceId, invitee.id);
99
+ if (existing) {
100
+ return res.status(409).json({ error: 'User is already a member' });
101
+ }
102
+ // Add member (pending acceptance)
103
+ const member = await db.workspaceMembers.addMember({
104
+ workspaceId,
105
+ userId: invitee.id,
106
+ role,
107
+ invitedBy: userId,
108
+ });
109
+ // TODO: Send email notification to invitee
110
+ res.status(201).json({
111
+ success: true,
112
+ member: {
113
+ id: member.id,
114
+ userId: member.userId,
115
+ role: member.role,
116
+ isPending: true,
117
+ user: {
118
+ githubUsername: invitee.githubUsername,
119
+ email: invitee.email,
120
+ avatarUrl: invitee.avatarUrl,
121
+ },
122
+ },
123
+ });
124
+ }
125
+ catch (error) {
126
+ console.error('Error inviting member:', error);
127
+ res.status(500).json({ error: 'Failed to invite member' });
128
+ }
129
+ });
130
+ /**
131
+ * PATCH /api/workspaces/:workspaceId/members/:memberId
132
+ * Update member role
133
+ */
134
+ teamsRouter.patch('/workspaces/:workspaceId/members/:memberId', async (req, res) => {
135
+ const userId = req.session.userId;
136
+ const workspaceId = req.params.workspaceId;
137
+ const memberId = req.params.memberId;
138
+ const { role } = req.body;
139
+ const validRoles = ['admin', 'member', 'viewer'];
140
+ if (!validRoles.includes(role)) {
141
+ return res.status(400).json({ error: 'Invalid role' });
142
+ }
143
+ try {
144
+ // Check user is owner or admin
145
+ const isOwner = await db.workspaceMembers.isOwner(workspaceId, userId);
146
+ const workspace = await db.workspaces.findById(workspaceId);
147
+ if (!isOwner && workspace?.userId !== userId) {
148
+ return res.status(403).json({ error: 'Only owners can change roles' });
149
+ }
150
+ // Get the member to update
151
+ const members = await db.workspaceMembers.findByWorkspaceId(workspaceId);
152
+ const member = members.find((m) => m.id === memberId);
153
+ if (!member) {
154
+ return res.status(404).json({ error: 'Member not found' });
155
+ }
156
+ // Can't change owner role
157
+ if (member.role === 'owner') {
158
+ return res.status(400).json({ error: 'Cannot change owner role' });
159
+ }
160
+ await db.workspaceMembers.updateRole(workspaceId, member.userId, role);
161
+ res.json({ success: true, role });
162
+ }
163
+ catch (error) {
164
+ console.error('Error updating role:', error);
165
+ res.status(500).json({ error: 'Failed to update role' });
166
+ }
167
+ });
168
+ /**
169
+ * DELETE /api/workspaces/:workspaceId/members/:memberId
170
+ * Remove member from workspace
171
+ */
172
+ teamsRouter.delete('/workspaces/:workspaceId/members/:memberId', async (req, res) => {
173
+ const userId = req.session.userId;
174
+ const workspaceId = req.params.workspaceId;
175
+ const memberId = req.params.memberId;
176
+ try {
177
+ const members = await db.workspaceMembers.findByWorkspaceId(workspaceId);
178
+ const member = members.find((m) => m.id === memberId);
179
+ if (!member) {
180
+ return res.status(404).json({ error: 'Member not found' });
181
+ }
182
+ // Users can remove themselves
183
+ if (member.userId === userId) {
184
+ if (member.role === 'owner') {
185
+ return res.status(400).json({ error: 'Owner cannot leave. Transfer ownership first.' });
186
+ }
187
+ await db.workspaceMembers.removeMember(workspaceId, userId);
188
+ return res.json({ success: true });
189
+ }
190
+ // Otherwise, must be owner or admin
191
+ const isOwner = await db.workspaceMembers.isOwner(workspaceId, userId);
192
+ const workspace = await db.workspaces.findById(workspaceId);
193
+ if (!isOwner && workspace?.userId !== userId) {
194
+ const myMembership = await db.workspaceMembers.findMembership(workspaceId, userId);
195
+ if (!myMembership || myMembership.role !== 'admin') {
196
+ return res.status(403).json({ error: 'Permission denied' });
197
+ }
198
+ }
199
+ // Can't remove owner
200
+ if (member.role === 'owner') {
201
+ return res.status(400).json({ error: 'Cannot remove owner' });
202
+ }
203
+ await db.workspaceMembers.removeMember(workspaceId, member.userId);
204
+ res.json({ success: true });
205
+ }
206
+ catch (error) {
207
+ console.error('Error removing member:', error);
208
+ res.status(500).json({ error: 'Failed to remove member' });
209
+ }
210
+ });
211
+ /**
212
+ * GET /api/invites
213
+ * Get pending invites for current user
214
+ */
215
+ teamsRouter.get('/invites', async (req, res) => {
216
+ const userId = req.session.userId;
217
+ try {
218
+ const invites = await db.workspaceMembers.getPendingInvites(userId);
219
+ res.json({
220
+ invites: invites.map((inv) => ({
221
+ id: inv.id,
222
+ workspaceId: inv.workspaceId,
223
+ workspaceName: inv.workspace_name,
224
+ role: inv.role,
225
+ invitedAt: inv.invitedAt,
226
+ invitedBy: inv.inviter_username,
227
+ })),
228
+ });
229
+ }
230
+ catch (error) {
231
+ console.error('Error getting invites:', error);
232
+ res.status(500).json({ error: 'Failed to get invites' });
233
+ }
234
+ });
235
+ /**
236
+ * POST /api/invites/:inviteId/accept
237
+ * Accept workspace invitation
238
+ */
239
+ teamsRouter.post('/invites/:inviteId/accept', async (req, res) => {
240
+ const userId = req.session.userId;
241
+ const inviteId = req.params.inviteId;
242
+ try {
243
+ const invites = await db.workspaceMembers.getPendingInvites(userId);
244
+ const invite = invites.find((i) => i.id === inviteId);
245
+ if (!invite) {
246
+ return res.status(404).json({ error: 'Invite not found' });
247
+ }
248
+ await db.workspaceMembers.acceptInvite(invite.workspaceId, userId);
249
+ res.json({
250
+ success: true,
251
+ workspaceId: invite.workspaceId,
252
+ message: 'Invitation accepted',
253
+ });
254
+ }
255
+ catch (error) {
256
+ console.error('Error accepting invite:', error);
257
+ res.status(500).json({ error: 'Failed to accept invite' });
258
+ }
259
+ });
260
+ /**
261
+ * POST /api/invites/:inviteId/decline
262
+ * Decline workspace invitation
263
+ */
264
+ teamsRouter.post('/invites/:inviteId/decline', async (req, res) => {
265
+ const userId = req.session.userId;
266
+ const inviteId = req.params.inviteId;
267
+ try {
268
+ const invites = await db.workspaceMembers.getPendingInvites(userId);
269
+ const invite = invites.find((i) => i.id === inviteId);
270
+ if (!invite) {
271
+ return res.status(404).json({ error: 'Invite not found' });
272
+ }
273
+ await db.workspaceMembers.removeMember(invite.workspaceId, userId);
274
+ res.json({ success: true, message: 'Invitation declined' });
275
+ }
276
+ catch (error) {
277
+ console.error('Error declining invite:', error);
278
+ res.status(500).json({ error: 'Failed to decline invite' });
279
+ }
280
+ });
281
+ //# sourceMappingURL=teams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams.js","sourceRoot":"","sources":["../../src/api/teams.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
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
+ export declare const testHelpersRouter: import("express-serve-static-core").Router;
10
+ //# sourceMappingURL=test-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../src/api/test-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,eAAO,MAAM,iBAAiB,4CAAW,CAAC"}