@morten-olsen/builder-server 0.0.6

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 (270) hide show
  1. package/dist/app/app.d.ts +11 -0
  2. package/dist/app/app.d.ts.map +1 -0
  3. package/dist/app/app.js +141 -0
  4. package/dist/app/app.js.map +1 -0
  5. package/dist/app/app.routes.d.ts +4 -0
  6. package/dist/app/app.routes.d.ts.map +1 -0
  7. package/dist/app/app.routes.js +22 -0
  8. package/dist/app/app.routes.js.map +1 -0
  9. package/dist/app/app.types.d.ts +15 -0
  10. package/dist/app/app.types.d.ts.map +1 -0
  11. package/dist/app/app.types.js +2 -0
  12. package/dist/app/app.types.js.map +1 -0
  13. package/dist/config/config.d.ts +31 -0
  14. package/dist/config/config.d.ts.map +1 -0
  15. package/dist/config/config.js +93 -0
  16. package/dist/config/config.js.map +1 -0
  17. package/dist/config/config.testing.d.ts +4 -0
  18. package/dist/config/config.testing.d.ts.map +1 -0
  19. package/dist/config/config.testing.js +17 -0
  20. package/dist/config/config.testing.js.map +1 -0
  21. package/dist/container/container.d.ts +38 -0
  22. package/dist/container/container.d.ts.map +1 -0
  23. package/dist/container/container.js +33 -0
  24. package/dist/container/container.js.map +1 -0
  25. package/dist/container/container.test.d.ts +2 -0
  26. package/dist/container/container.test.d.ts.map +1 -0
  27. package/dist/container/container.test.js +65 -0
  28. package/dist/container/container.test.js.map +1 -0
  29. package/dist/exports.d.ts +67 -0
  30. package/dist/exports.d.ts.map +1 -0
  31. package/dist/exports.js +44 -0
  32. package/dist/exports.js.map +1 -0
  33. package/dist/routes/auth/auth.d.ts +4 -0
  34. package/dist/routes/auth/auth.d.ts.map +1 -0
  35. package/dist/routes/auth/auth.js +74 -0
  36. package/dist/routes/auth/auth.js.map +1 -0
  37. package/dist/routes/auth/auth.schemas.d.ts +42 -0
  38. package/dist/routes/auth/auth.schemas.d.ts.map +1 -0
  39. package/dist/routes/auth/auth.schemas.js +34 -0
  40. package/dist/routes/auth/auth.schemas.js.map +1 -0
  41. package/dist/routes/auth/auth.test.d.ts +2 -0
  42. package/dist/routes/auth/auth.test.d.ts.map +1 -0
  43. package/dist/routes/auth/auth.test.js +203 -0
  44. package/dist/routes/auth/auth.test.js.map +1 -0
  45. package/dist/routes/events/events.d.ts +4 -0
  46. package/dist/routes/events/events.d.ts.map +1 -0
  47. package/dist/routes/events/events.js +28 -0
  48. package/dist/routes/events/events.js.map +1 -0
  49. package/dist/routes/identities/identities.d.ts +4 -0
  50. package/dist/routes/identities/identities.d.ts.map +1 -0
  51. package/dist/routes/identities/identities.js +128 -0
  52. package/dist/routes/identities/identities.js.map +1 -0
  53. package/dist/routes/identities/identities.schemas.d.ts +52 -0
  54. package/dist/routes/identities/identities.schemas.d.ts.map +1 -0
  55. package/dist/routes/identities/identities.schemas.js +38 -0
  56. package/dist/routes/identities/identities.schemas.js.map +1 -0
  57. package/dist/routes/identities/identities.test.d.ts +2 -0
  58. package/dist/routes/identities/identities.test.d.ts.map +1 -0
  59. package/dist/routes/identities/identities.test.js +329 -0
  60. package/dist/routes/identities/identities.test.js.map +1 -0
  61. package/dist/routes/models/models.d.ts +4 -0
  62. package/dist/routes/models/models.d.ts.map +1 -0
  63. package/dist/routes/models/models.js +60 -0
  64. package/dist/routes/models/models.js.map +1 -0
  65. package/dist/routes/models/models.schemas.d.ts +16 -0
  66. package/dist/routes/models/models.schemas.d.ts.map +1 -0
  67. package/dist/routes/models/models.schemas.js +9 -0
  68. package/dist/routes/models/models.schemas.js.map +1 -0
  69. package/dist/routes/notifications/notifications.d.ts +4 -0
  70. package/dist/routes/notifications/notifications.d.ts.map +1 -0
  71. package/dist/routes/notifications/notifications.js +226 -0
  72. package/dist/routes/notifications/notifications.js.map +1 -0
  73. package/dist/routes/notifications/notifications.schemas.d.ts +61 -0
  74. package/dist/routes/notifications/notifications.schemas.d.ts.map +1 -0
  75. package/dist/routes/notifications/notifications.schemas.js +44 -0
  76. package/dist/routes/notifications/notifications.schemas.js.map +1 -0
  77. package/dist/routes/notifications/notifications.test.d.ts +2 -0
  78. package/dist/routes/notifications/notifications.test.d.ts.map +1 -0
  79. package/dist/routes/notifications/notifications.test.js +44 -0
  80. package/dist/routes/notifications/notifications.test.js.map +1 -0
  81. package/dist/routes/repos/repos.d.ts +4 -0
  82. package/dist/routes/repos/repos.d.ts.map +1 -0
  83. package/dist/routes/repos/repos.js +142 -0
  84. package/dist/routes/repos/repos.js.map +1 -0
  85. package/dist/routes/repos/repos.schemas.d.ts +47 -0
  86. package/dist/routes/repos/repos.schemas.d.ts.map +1 -0
  87. package/dist/routes/repos/repos.schemas.js +32 -0
  88. package/dist/routes/repos/repos.schemas.js.map +1 -0
  89. package/dist/routes/sessions/sessions.d.ts +4 -0
  90. package/dist/routes/sessions/sessions.d.ts.map +1 -0
  91. package/dist/routes/sessions/sessions.js +299 -0
  92. package/dist/routes/sessions/sessions.js.map +1 -0
  93. package/dist/routes/sessions/sessions.review.d.ts +4 -0
  94. package/dist/routes/sessions/sessions.review.d.ts.map +1 -0
  95. package/dist/routes/sessions/sessions.review.js +294 -0
  96. package/dist/routes/sessions/sessions.review.js.map +1 -0
  97. package/dist/routes/sessions/sessions.review.schemas.d.ts +83 -0
  98. package/dist/routes/sessions/sessions.review.schemas.d.ts.map +1 -0
  99. package/dist/routes/sessions/sessions.review.schemas.js +55 -0
  100. package/dist/routes/sessions/sessions.review.schemas.js.map +1 -0
  101. package/dist/routes/sessions/sessions.schemas.d.ts +81 -0
  102. package/dist/routes/sessions/sessions.schemas.d.ts.map +1 -0
  103. package/dist/routes/sessions/sessions.schemas.js +50 -0
  104. package/dist/routes/sessions/sessions.schemas.js.map +1 -0
  105. package/dist/routes/sessions/sessions.test.d.ts +2 -0
  106. package/dist/routes/sessions/sessions.test.d.ts.map +1 -0
  107. package/dist/routes/sessions/sessions.test.js +297 -0
  108. package/dist/routes/sessions/sessions.test.js.map +1 -0
  109. package/dist/routes/ws/ws.d.ts +4 -0
  110. package/dist/routes/ws/ws.d.ts.map +1 -0
  111. package/dist/routes/ws/ws.js +8 -0
  112. package/dist/routes/ws/ws.js.map +1 -0
  113. package/dist/services/agent/agent.claude.d.ts +4 -0
  114. package/dist/services/agent/agent.claude.d.ts.map +1 -0
  115. package/dist/services/agent/agent.claude.js +141 -0
  116. package/dist/services/agent/agent.claude.js.map +1 -0
  117. package/dist/services/agent/agent.claude.test.d.ts +2 -0
  118. package/dist/services/agent/agent.claude.test.d.ts.map +1 -0
  119. package/dist/services/agent/agent.claude.test.js +43 -0
  120. package/dist/services/agent/agent.claude.test.js.map +1 -0
  121. package/dist/services/agent/agent.d.ts +58 -0
  122. package/dist/services/agent/agent.d.ts.map +1 -0
  123. package/dist/services/agent/agent.errors.d.ts +8 -0
  124. package/dist/services/agent/agent.errors.d.ts.map +1 -0
  125. package/dist/services/agent/agent.errors.js +14 -0
  126. package/dist/services/agent/agent.errors.js.map +1 -0
  127. package/dist/services/agent/agent.js +21 -0
  128. package/dist/services/agent/agent.js.map +1 -0
  129. package/dist/services/agent/agent.queue.d.ts +8 -0
  130. package/dist/services/agent/agent.queue.d.ts.map +1 -0
  131. package/dist/services/agent/agent.queue.js +46 -0
  132. package/dist/services/agent/agent.queue.js.map +1 -0
  133. package/dist/services/auth/auth.d.ts +41 -0
  134. package/dist/services/auth/auth.d.ts.map +1 -0
  135. package/dist/services/auth/auth.errors.d.ts +17 -0
  136. package/dist/services/auth/auth.errors.d.ts.map +1 -0
  137. package/dist/services/auth/auth.errors.js +32 -0
  138. package/dist/services/auth/auth.errors.js.map +1 -0
  139. package/dist/services/auth/auth.js +147 -0
  140. package/dist/services/auth/auth.js.map +1 -0
  141. package/dist/services/auth/auth.test.d.ts +2 -0
  142. package/dist/services/auth/auth.test.d.ts.map +1 -0
  143. package/dist/services/auth/auth.test.js +55 -0
  144. package/dist/services/auth/auth.test.js.map +1 -0
  145. package/dist/services/auth/auth.utils.d.ts +4 -0
  146. package/dist/services/auth/auth.utils.d.ts.map +1 -0
  147. package/dist/services/auth/auth.utils.js +15 -0
  148. package/dist/services/auth/auth.utils.js.map +1 -0
  149. package/dist/services/auth/auth.utils.test.d.ts +2 -0
  150. package/dist/services/auth/auth.utils.test.d.ts.map +1 -0
  151. package/dist/services/auth/auth.utils.test.js +20 -0
  152. package/dist/services/auth/auth.utils.test.js.map +1 -0
  153. package/dist/services/database/database.d.ts +102 -0
  154. package/dist/services/database/database.d.ts.map +1 -0
  155. package/dist/services/database/database.js +41 -0
  156. package/dist/services/database/database.js.map +1 -0
  157. package/dist/services/database/database.migrations.d.ts +4 -0
  158. package/dist/services/database/database.migrations.d.ts.map +1 -0
  159. package/dist/services/database/database.migrations.js +290 -0
  160. package/dist/services/database/database.migrations.js.map +1 -0
  161. package/dist/services/database/database.test.d.ts +2 -0
  162. package/dist/services/database/database.test.d.ts.map +1 -0
  163. package/dist/services/database/database.test.js +60 -0
  164. package/dist/services/database/database.test.js.map +1 -0
  165. package/dist/services/file-review/file-review.d.ts +34 -0
  166. package/dist/services/file-review/file-review.d.ts.map +1 -0
  167. package/dist/services/file-review/file-review.js +71 -0
  168. package/dist/services/file-review/file-review.js.map +1 -0
  169. package/dist/services/file-review/file-review.test.d.ts +2 -0
  170. package/dist/services/file-review/file-review.test.d.ts.map +1 -0
  171. package/dist/services/file-review/file-review.test.js +171 -0
  172. package/dist/services/file-review/file-review.test.js.map +1 -0
  173. package/dist/services/git/git.d.ts +95 -0
  174. package/dist/services/git/git.d.ts.map +1 -0
  175. package/dist/services/git/git.errors.d.ts +20 -0
  176. package/dist/services/git/git.errors.d.ts.map +1 -0
  177. package/dist/services/git/git.errors.js +38 -0
  178. package/dist/services/git/git.errors.js.map +1 -0
  179. package/dist/services/git/git.js +341 -0
  180. package/dist/services/git/git.js.map +1 -0
  181. package/dist/services/git/git.test.d.ts +2 -0
  182. package/dist/services/git/git.test.d.ts.map +1 -0
  183. package/dist/services/git/git.test.js +304 -0
  184. package/dist/services/git/git.test.js.map +1 -0
  185. package/dist/services/identity/identity.d.ts +49 -0
  186. package/dist/services/identity/identity.d.ts.map +1 -0
  187. package/dist/services/identity/identity.errors.d.ts +11 -0
  188. package/dist/services/identity/identity.errors.d.ts.map +1 -0
  189. package/dist/services/identity/identity.errors.js +20 -0
  190. package/dist/services/identity/identity.errors.js.map +1 -0
  191. package/dist/services/identity/identity.js +196 -0
  192. package/dist/services/identity/identity.js.map +1 -0
  193. package/dist/services/identity/identity.test.d.ts +2 -0
  194. package/dist/services/identity/identity.test.d.ts.map +1 -0
  195. package/dist/services/identity/identity.test.js +184 -0
  196. package/dist/services/identity/identity.test.js.map +1 -0
  197. package/dist/services/identity/identity.utils.d.ts +9 -0
  198. package/dist/services/identity/identity.utils.d.ts.map +1 -0
  199. package/dist/services/identity/identity.utils.js +47 -0
  200. package/dist/services/identity/identity.utils.js.map +1 -0
  201. package/dist/services/identity/identity.utils.test.d.ts +2 -0
  202. package/dist/services/identity/identity.utils.test.d.ts.map +1 -0
  203. package/dist/services/identity/identity.utils.test.js +49 -0
  204. package/dist/services/identity/identity.utils.test.js.map +1 -0
  205. package/dist/services/message/message.d.ts +29 -0
  206. package/dist/services/message/message.d.ts.map +1 -0
  207. package/dist/services/message/message.js +85 -0
  208. package/dist/services/message/message.js.map +1 -0
  209. package/dist/services/notification/notification.d.ts +75 -0
  210. package/dist/services/notification/notification.d.ts.map +1 -0
  211. package/dist/services/notification/notification.errors.d.ts +14 -0
  212. package/dist/services/notification/notification.errors.d.ts.map +1 -0
  213. package/dist/services/notification/notification.errors.js +26 -0
  214. package/dist/services/notification/notification.errors.js.map +1 -0
  215. package/dist/services/notification/notification.js +212 -0
  216. package/dist/services/notification/notification.js.map +1 -0
  217. package/dist/services/notification/notification.ntfy.d.ts +12 -0
  218. package/dist/services/notification/notification.ntfy.d.ts.map +1 -0
  219. package/dist/services/notification/notification.ntfy.js +44 -0
  220. package/dist/services/notification/notification.ntfy.js.map +1 -0
  221. package/dist/services/repo/repo.d.ts +46 -0
  222. package/dist/services/repo/repo.d.ts.map +1 -0
  223. package/dist/services/repo/repo.errors.d.ts +11 -0
  224. package/dist/services/repo/repo.errors.d.ts.map +1 -0
  225. package/dist/services/repo/repo.errors.js +20 -0
  226. package/dist/services/repo/repo.errors.js.map +1 -0
  227. package/dist/services/repo/repo.js +138 -0
  228. package/dist/services/repo/repo.js.map +1 -0
  229. package/dist/services/session/session.d.ts +62 -0
  230. package/dist/services/session/session.d.ts.map +1 -0
  231. package/dist/services/session/session.errors.d.ts +11 -0
  232. package/dist/services/session/session.errors.d.ts.map +1 -0
  233. package/dist/services/session/session.errors.js +20 -0
  234. package/dist/services/session/session.errors.js.map +1 -0
  235. package/dist/services/session/session.js +168 -0
  236. package/dist/services/session/session.js.map +1 -0
  237. package/dist/services/session/session.runner.d.ts +8 -0
  238. package/dist/services/session/session.runner.d.ts.map +1 -0
  239. package/dist/services/session/session.runner.js +328 -0
  240. package/dist/services/session/session.runner.js.map +1 -0
  241. package/dist/services/session/session.runner.test.d.ts +2 -0
  242. package/dist/services/session/session.runner.test.d.ts.map +1 -0
  243. package/dist/services/session/session.runner.test.js +143 -0
  244. package/dist/services/session/session.runner.test.js.map +1 -0
  245. package/dist/services/session/session.test.d.ts +2 -0
  246. package/dist/services/session/session.test.d.ts.map +1 -0
  247. package/dist/services/session/session.test.js +146 -0
  248. package/dist/services/session/session.test.js.map +1 -0
  249. package/dist/services/session-event/session-event.d.ts +28 -0
  250. package/dist/services/session-event/session-event.d.ts.map +1 -0
  251. package/dist/services/session-event/session-event.js +86 -0
  252. package/dist/services/session-event/session-event.js.map +1 -0
  253. package/dist/sse/event-bus.d.ts +74 -0
  254. package/dist/sse/event-bus.d.ts.map +1 -0
  255. package/dist/sse/event-bus.js +137 -0
  256. package/dist/sse/event-bus.js.map +1 -0
  257. package/dist/sse/stream.d.ts +20 -0
  258. package/dist/sse/stream.d.ts.map +1 -0
  259. package/dist/sse/stream.js +66 -0
  260. package/dist/sse/stream.js.map +1 -0
  261. package/dist/tsconfig.tsbuildinfo +1 -0
  262. package/dist/utils/crypto.d.ts +4 -0
  263. package/dist/utils/crypto.d.ts.map +1 -0
  264. package/dist/utils/crypto.js +21 -0
  265. package/dist/utils/crypto.js.map +1 -0
  266. package/dist/ws/ws.d.ts +30 -0
  267. package/dist/ws/ws.d.ts.map +1 -0
  268. package/dist/ws/ws.js +137 -0
  269. package/dist/ws/ws.js.map +1 -0
  270. package/package.json +50 -0
@@ -0,0 +1,143 @@
1
+ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { simpleGit } from 'simple-git';
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import { createApp } from '../../app/app.js';
7
+ import { createTestConfig } from '../../config/config.testing.js';
8
+ import { Services, destroy } from '../../container/container.js';
9
+ import { registerAuthRoutes } from '../../routes/auth/auth.js';
10
+ import { registerIdentityRoutes } from '../../routes/identities/identities.js';
11
+ import { AgentService } from '../agent/agent.js';
12
+ import { EventBusService } from '../../sse/event-bus.js';
13
+ import { SessionService } from './session.js';
14
+ import { startSession } from './session.runner.js';
15
+ const createMockAgentProvider = () => ({
16
+ name: 'mock',
17
+ run: async ({ onEvent }) => {
18
+ await onEvent({
19
+ type: 'message',
20
+ message: {
21
+ role: 'assistant',
22
+ content: 'Working on it',
23
+ timestamp: new Date().toISOString(),
24
+ },
25
+ });
26
+ await onEvent({ type: 'completed', summary: 'Done' });
27
+ },
28
+ sendMessage: async () => { },
29
+ stop: async () => { },
30
+ abort: async () => { },
31
+ isRunning: () => false,
32
+ });
33
+ describe('startSession', () => {
34
+ let services;
35
+ let tmpDir;
36
+ let userId;
37
+ let identityId;
38
+ let originRepoPath;
39
+ beforeEach(async () => {
40
+ process.env.GIT_CONFIG_NOSYSTEM = '1';
41
+ process.env.GIT_CONFIG_GLOBAL = '/dev/null';
42
+ tmpDir = await mkdtemp(path.join(os.tmpdir(), 'runner-test-'));
43
+ // Create origin repo
44
+ originRepoPath = path.join(tmpDir, 'origin');
45
+ await mkdir(originRepoPath, { recursive: true });
46
+ const originGit = simpleGit(originRepoPath)
47
+ .env('GIT_CONFIG_NOSYSTEM', '1')
48
+ .env('GIT_CONFIG_GLOBAL', '/dev/null');
49
+ await originGit.raw(['init', '-b', 'main']);
50
+ await originGit.addConfig('user.email', 'test@test.com');
51
+ await originGit.addConfig('user.name', 'Test');
52
+ await originGit.addConfig('commit.gpgsign', 'false');
53
+ await writeFile(path.join(originRepoPath, 'README.md'), '# Test');
54
+ await originGit.add('.');
55
+ await originGit.commit('initial commit');
56
+ const config = createTestConfig({
57
+ session: { dataDir: tmpDir },
58
+ agent: { provider: 'mock', apiKey: '', model: 'test' },
59
+ });
60
+ services = new Services(config);
61
+ // Register mock agent provider
62
+ const agentService = services.get(AgentService);
63
+ agentService.registerProvider(createMockAgentProvider());
64
+ // Bootstrap user + identity
65
+ const app = await createApp({ services, config });
66
+ registerAuthRoutes(app);
67
+ registerIdentityRoutes(app);
68
+ await app.ready();
69
+ const registerRes = await app.inject({
70
+ method: 'POST',
71
+ url: '/api/auth/register',
72
+ payload: { email: 'test@example.com', password: 'password123' },
73
+ });
74
+ const authBody = registerRes.json();
75
+ userId = authBody.user.id;
76
+ const identityRes = await app.inject({
77
+ method: 'POST',
78
+ url: `/api/users/${userId}/identities`,
79
+ headers: { authorization: `Bearer ${authBody.token}` },
80
+ payload: {
81
+ name: 'Test Identity',
82
+ gitAuthorName: 'Test',
83
+ gitAuthorEmail: 'test@test.com',
84
+ },
85
+ });
86
+ identityId = identityRes.json().id;
87
+ await app.close();
88
+ });
89
+ afterEach(async () => {
90
+ delete process.env.GIT_CONFIG_NOSYSTEM;
91
+ delete process.env.GIT_CONFIG_GLOBAL;
92
+ await services[destroy]();
93
+ await rm(tmpDir, { recursive: true, force: true });
94
+ });
95
+ it('runs through the full session lifecycle', async () => {
96
+ const sessionService = services.get(SessionService);
97
+ const eventBus = services.get(EventBusService);
98
+ const session = await sessionService.create({
99
+ userId,
100
+ identityId,
101
+ repoUrl: `file://${originRepoPath}`,
102
+ branch: 'main',
103
+ prompt: 'Fix the bug',
104
+ });
105
+ const events = [];
106
+ eventBus.subscribe(session.id, (event) => events.push(event));
107
+ await startSession(services, session.id);
108
+ const updated = await sessionService.getById(session.id);
109
+ expect(updated.status).toBe('idle');
110
+ const statusEvents = events.filter((e) => e.type === 'session:status');
111
+ expect(statusEvents.length).toBeGreaterThan(0);
112
+ const completedEvents = events.filter((e) => e.type === 'session:completed');
113
+ expect(completedEvents).toHaveLength(1);
114
+ const idleStatuses = statusEvents.filter((e) => e.type === 'session:status' && e.data.status === 'idle');
115
+ expect(idleStatuses.length).toBeGreaterThan(0);
116
+ });
117
+ it('sets status to failed on error', async () => {
118
+ const agentService = services.get(AgentService);
119
+ agentService.registerProvider({
120
+ name: 'mock',
121
+ run: async ({ onEvent }) => {
122
+ await onEvent({ type: 'error', error: 'Something broke' });
123
+ },
124
+ sendMessage: async () => { },
125
+ stop: async () => { },
126
+ abort: async () => { },
127
+ isRunning: () => false,
128
+ });
129
+ const sessionService = services.get(SessionService);
130
+ const session = await sessionService.create({
131
+ userId,
132
+ identityId,
133
+ repoUrl: `file://${originRepoPath}`,
134
+ branch: 'main',
135
+ prompt: 'Break things',
136
+ });
137
+ await startSession(services, session.id);
138
+ const updated = await sessionService.getById(session.id);
139
+ expect(updated.status).toBe('failed');
140
+ expect(updated.error).toBe('Something broke');
141
+ });
142
+ });
143
+ //# sourceMappingURL=session.runner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.runner.test.js","sourceRoot":"","sources":["../../../src/services/session/session.runner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.test.d.ts","sourceRoot":"","sources":["../../../src/services/session/session.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,146 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { createApp } from '../../app/app.js';
3
+ import { createTestConfig } from '../../config/config.testing.js';
4
+ import { Services, destroy } from '../../container/container.js';
5
+ import { registerAuthRoutes } from '../../routes/auth/auth.js';
6
+ import { registerIdentityRoutes } from '../../routes/identities/identities.js';
7
+ import { SessionNotFoundError } from './session.errors.js';
8
+ import { SessionService } from './session.js';
9
+ describe('SessionService', () => {
10
+ let services;
11
+ let sessionService;
12
+ let userId;
13
+ let identityId;
14
+ beforeEach(async () => {
15
+ const config = createTestConfig();
16
+ services = new Services(config);
17
+ // Bootstrap a user + identity so FK constraints pass
18
+ const app = await createApp({ services, config });
19
+ registerAuthRoutes(app);
20
+ registerIdentityRoutes(app);
21
+ await app.ready();
22
+ const registerRes = await app.inject({
23
+ method: 'POST',
24
+ url: '/api/auth/register',
25
+ payload: { email: 'test@example.com', password: 'password123' },
26
+ });
27
+ const authBody = registerRes.json();
28
+ userId = authBody.user.id;
29
+ const identityRes = await app.inject({
30
+ method: 'POST',
31
+ url: `/api/users/${userId}/identities`,
32
+ headers: { authorization: `Bearer ${authBody.token}` },
33
+ payload: {
34
+ name: 'Test Identity',
35
+ gitAuthorName: 'Test',
36
+ gitAuthorEmail: 'test@test.com',
37
+ },
38
+ });
39
+ identityId = identityRes.json().id;
40
+ await app.close();
41
+ sessionService = services.get(SessionService);
42
+ });
43
+ afterEach(async () => {
44
+ await services[destroy]();
45
+ });
46
+ it('creates a session', async () => {
47
+ const session = await sessionService.create({
48
+ userId,
49
+ identityId,
50
+ repoUrl: 'git@github.com:test/repo.git',
51
+ branch: 'main',
52
+ prompt: 'Fix the bug',
53
+ });
54
+ expect(session.id).toBeTruthy();
55
+ expect(session.userId).toBe(userId);
56
+ expect(session.status).toBe('pending');
57
+ expect(session.error).toBeNull();
58
+ });
59
+ it('lists sessions for a user', async () => {
60
+ await sessionService.create({
61
+ userId,
62
+ identityId,
63
+ repoUrl: 'git@github.com:test/repo.git',
64
+ branch: 'main',
65
+ prompt: 'Task 1',
66
+ });
67
+ await sessionService.create({
68
+ userId,
69
+ identityId,
70
+ repoUrl: 'git@github.com:test/repo.git',
71
+ branch: 'main',
72
+ prompt: 'Task 2',
73
+ });
74
+ const sessions = await sessionService.list(userId);
75
+ expect(sessions).toHaveLength(2);
76
+ });
77
+ it('gets a session by userId and sessionId', async () => {
78
+ const created = await sessionService.create({
79
+ userId,
80
+ identityId,
81
+ repoUrl: 'git@github.com:test/repo.git',
82
+ branch: 'main',
83
+ prompt: 'Task',
84
+ });
85
+ const session = await sessionService.get({ userId, sessionId: created.id });
86
+ expect(session.id).toBe(created.id);
87
+ expect(session.prompt).toBe('Task');
88
+ });
89
+ it('throws SessionNotFoundError for non-existent session', async () => {
90
+ await expect(sessionService.get({ userId, sessionId: 'non-existent' })).rejects.toThrow(SessionNotFoundError);
91
+ });
92
+ it('throws SessionNotFoundError for cross-user access', async () => {
93
+ const session = await sessionService.create({
94
+ userId,
95
+ identityId,
96
+ repoUrl: 'git@github.com:test/repo.git',
97
+ branch: 'main',
98
+ prompt: 'Task',
99
+ });
100
+ await expect(sessionService.get({ userId: 'other-user', sessionId: session.id })).rejects.toThrow(SessionNotFoundError);
101
+ });
102
+ it('updates session status', async () => {
103
+ const session = await sessionService.create({
104
+ userId,
105
+ identityId,
106
+ repoUrl: 'git@github.com:test/repo.git',
107
+ branch: 'main',
108
+ prompt: 'Task',
109
+ });
110
+ await sessionService.updateStatus({ sessionId: session.id, status: 'running' });
111
+ const updated = await sessionService.get({ userId, sessionId: session.id });
112
+ expect(updated.status).toBe('running');
113
+ });
114
+ it('updates session status with error', async () => {
115
+ const session = await sessionService.create({
116
+ userId,
117
+ identityId,
118
+ repoUrl: 'git@github.com:test/repo.git',
119
+ branch: 'main',
120
+ prompt: 'Task',
121
+ });
122
+ await sessionService.updateStatus({
123
+ sessionId: session.id,
124
+ status: 'failed',
125
+ error: 'Something went wrong',
126
+ });
127
+ const updated = await sessionService.get({ userId, sessionId: session.id });
128
+ expect(updated.status).toBe('failed');
129
+ expect(updated.error).toBe('Something went wrong');
130
+ });
131
+ it('deletes a session', async () => {
132
+ const session = await sessionService.create({
133
+ userId,
134
+ identityId,
135
+ repoUrl: 'git@github.com:test/repo.git',
136
+ branch: 'main',
137
+ prompt: 'Task',
138
+ });
139
+ await sessionService.delete({ userId, sessionId: session.id });
140
+ await expect(sessionService.get({ userId, sessionId: session.id })).rejects.toThrow(SessionNotFoundError);
141
+ });
142
+ it('throws SessionNotFoundError when deleting non-existent session', async () => {
143
+ await expect(sessionService.delete({ userId, sessionId: 'non-existent' })).rejects.toThrow(SessionNotFoundError);
144
+ });
145
+ });
146
+ //# sourceMappingURL=session.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.test.js","sourceRoot":"","sources":["../../../src/services/session/session.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Services } from '../../container/container.js';
2
+ import type { SessionEvent } from '../../sse/event-bus.js';
3
+ type PersistedSessionEvent = {
4
+ id: string;
5
+ sessionId: string;
6
+ sequence: number;
7
+ type: string;
8
+ data: unknown;
9
+ createdAt: string;
10
+ };
11
+ declare class SessionEventService {
12
+ #private;
13
+ constructor(services: Services);
14
+ nextSequence: (sessionId: string) => Promise<number>;
15
+ persist: (sessionId: string, sequence: number, event: SessionEvent) => Promise<void>;
16
+ listBySession: (input: {
17
+ sessionId: string;
18
+ afterSequence?: number;
19
+ }) => Promise<PersistedSessionEvent[]>;
20
+ deleteAfterSequence: (input: {
21
+ sessionId: string;
22
+ afterSequence: number;
23
+ }) => Promise<void>;
24
+ remove: (sessionId: string) => void;
25
+ }
26
+ export type { PersistedSessionEvent };
27
+ export { SessionEventService };
28
+ //# sourceMappingURL=session-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-event.d.ts","sourceRoot":"","sources":["../../../src/services/session-event/session-event.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,KAAK,qBAAqB,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,cAAM,mBAAmB;;gBAKX,QAAQ,EAAE,QAAQ;IAyB9B,YAAY,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,CAMvD;IAEF,OAAO,GAAU,WAAW,MAAM,EAAE,UAAU,MAAM,EAAE,OAAO,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAavF;IAEF,aAAa,GAAU,OAAO;QAC5B,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,KAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAsBlC;IAEF,mBAAmB,GAAU,OAAO;QAClC,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,KAAG,OAAO,CAAC,IAAI,CAAC,CASf;IAEF,MAAM,GAAI,WAAW,MAAM,KAAG,IAAI,CAGhC;CACH;AAED,YAAY,EAAE,qBAAqB,EAAE,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { DatabaseService } from '../database/database.js';
3
+ class SessionEventService {
4
+ #services;
5
+ #counters = new Map();
6
+ #seedPromises = new Map();
7
+ constructor(services) {
8
+ this.#services = services;
9
+ }
10
+ get #database() {
11
+ return this.#services.get(DatabaseService);
12
+ }
13
+ #ensureSeeded = async (sessionId) => {
14
+ if (this.#counters.has(sessionId))
15
+ return;
16
+ if (!this.#seedPromises.has(sessionId)) {
17
+ const promise = (async () => {
18
+ const db = await this.#database.getInstance();
19
+ const row = await db
20
+ .selectFrom('session_events')
21
+ .select(db.fn.max('sequence').as('max_seq'))
22
+ .where('session_id', '=', sessionId)
23
+ .executeTakeFirst();
24
+ this.#counters.set(sessionId, row?.max_seq ?? 0);
25
+ })();
26
+ this.#seedPromises.set(sessionId, promise);
27
+ }
28
+ await this.#seedPromises.get(sessionId);
29
+ };
30
+ nextSequence = async (sessionId) => {
31
+ await this.#ensureSeeded(sessionId);
32
+ const current = this.#counters.get(sessionId) ?? 0;
33
+ const next = current + 1;
34
+ this.#counters.set(sessionId, next);
35
+ return next;
36
+ };
37
+ persist = async (sessionId, sequence, event) => {
38
+ const db = await this.#database.getInstance();
39
+ await db
40
+ .insertInto('session_events')
41
+ .values({
42
+ id: randomUUID(),
43
+ session_id: sessionId,
44
+ sequence,
45
+ type: event.type,
46
+ data: JSON.stringify(event.data),
47
+ created_at: new Date().toISOString(),
48
+ })
49
+ .execute();
50
+ };
51
+ listBySession = async (input) => {
52
+ const db = await this.#database.getInstance();
53
+ let query = db
54
+ .selectFrom('session_events')
55
+ .selectAll()
56
+ .where('session_id', '=', input.sessionId)
57
+ .orderBy('sequence', 'asc');
58
+ if (input.afterSequence !== undefined) {
59
+ query = query.where('sequence', '>', input.afterSequence);
60
+ }
61
+ const rows = await query.execute();
62
+ return rows.map((row) => ({
63
+ id: row.id,
64
+ sessionId: row.session_id,
65
+ sequence: row.sequence,
66
+ type: row.type,
67
+ data: JSON.parse(row.data),
68
+ createdAt: row.created_at,
69
+ }));
70
+ };
71
+ deleteAfterSequence = async (input) => {
72
+ const db = await this.#database.getInstance();
73
+ await db
74
+ .deleteFrom('session_events')
75
+ .where('session_id', '=', input.sessionId)
76
+ .where('sequence', '>', input.afterSequence)
77
+ .execute();
78
+ this.#counters.set(input.sessionId, input.afterSequence);
79
+ };
80
+ remove = (sessionId) => {
81
+ this.#counters.delete(sessionId);
82
+ this.#seedPromises.delete(sessionId);
83
+ };
84
+ }
85
+ export { SessionEventService };
86
+ //# sourceMappingURL=session-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-event.js","sourceRoot":"","sources":["../../../src/services/session-event/session-event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { destroy } from '../container/container.js';
2
+ import type { Services } from '../container/container.js';
3
+ type SessionEvent = {
4
+ type: 'agent:output';
5
+ data: {
6
+ text: string;
7
+ messageType: string;
8
+ };
9
+ } | {
10
+ type: 'agent:tool_use';
11
+ data: {
12
+ tool: string;
13
+ input: unknown;
14
+ };
15
+ } | {
16
+ type: 'agent:tool_result';
17
+ data: {
18
+ tool: string;
19
+ output: unknown;
20
+ };
21
+ } | {
22
+ type: 'user:message';
23
+ data: {
24
+ message: string;
25
+ };
26
+ } | {
27
+ type: 'session:status';
28
+ data: {
29
+ status: string;
30
+ };
31
+ } | {
32
+ type: 'session:waiting_for_input';
33
+ data: {
34
+ prompt: string;
35
+ };
36
+ } | {
37
+ type: 'session:completed';
38
+ data: {
39
+ summary: string;
40
+ };
41
+ } | {
42
+ type: 'session:error';
43
+ data: {
44
+ error: string;
45
+ };
46
+ } | {
47
+ type: 'session:snapshot';
48
+ data: {
49
+ messageId: string;
50
+ commitSha: string;
51
+ };
52
+ };
53
+ type UserEvent = {
54
+ type: 'session:updated';
55
+ data: {
56
+ sessionId: string;
57
+ status: string;
58
+ };
59
+ };
60
+ type SessionEventListener = (event: SessionEvent, sequence: number) => void;
61
+ type UserEventListener = (event: UserEvent) => void;
62
+ declare class EventBusService {
63
+ #private;
64
+ constructor(services: Services);
65
+ registerSession: (sessionId: string, userId: string) => void;
66
+ emit: (sessionId: string, event: SessionEvent) => void;
67
+ subscribe: (sessionId: string, listener: SessionEventListener) => (() => void);
68
+ subscribeUser: (userId: string, listener: UserEventListener) => (() => void);
69
+ remove: (sessionId: string) => void;
70
+ [destroy]: () => Promise<void>;
71
+ }
72
+ export type { SessionEvent, UserEvent, SessionEventListener, UserEventListener };
73
+ export { EventBusService };
74
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/sse/event-bus.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAK1D,KAAK,YAAY,GACb;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,2BAA2B,CAAC;IAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEjF,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAE1F,KAAK,oBAAoB,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AAC5E,KAAK,iBAAiB,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;AAEpD,cAAM,eAAe;;gBAMP,QAAQ,EAAE,QAAQ;IA0B9B,eAAe,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,KAAG,IAAI,CAEzD;IAEF,IAAI,GAAI,WAAW,MAAM,EAAE,OAAO,YAAY,KAAG,IAAI,CA4BnD;IAEF,SAAS,GAAI,WAAW,MAAM,EAAE,UAAU,oBAAoB,KAAG,CAAC,MAAM,IAAI,CAAC,CAM3E;IAEF,aAAa,GAAI,QAAQ,MAAM,EAAE,UAAU,iBAAiB,KAAG,CAAC,MAAM,IAAI,CAAC,CAMzE;IA6CF,MAAM,GAAI,WAAW,MAAM,KAAG,IAAI,CAQhC;IAEF,CAAC,OAAO,CAAC,QAAa,OAAO,CAAC,IAAI,CAAC,CAUjC;CACH;AAED,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,CAAC"}