@cat-factory/node-server 0.6.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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config.d.ts +3 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +297 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/container.d.ts +88 -0
  7. package/dist/container.d.ts.map +1 -0
  8. package/dist/container.js +937 -0
  9. package/dist/container.js.map +1 -0
  10. package/dist/db/client.d.ts +13 -0
  11. package/dist/db/client.d.ts.map +1 -0
  12. package/dist/db/client.js +21 -0
  13. package/dist/db/client.js.map +1 -0
  14. package/dist/db/migrate.d.ts +12 -0
  15. package/dist/db/migrate.d.ts.map +1 -0
  16. package/dist/db/migrate.js +40 -0
  17. package/dist/db/migrate.js.map +1 -0
  18. package/dist/db/schema.d.ts +7858 -0
  19. package/dist/db/schema.d.ts.map +1 -0
  20. package/dist/db/schema.js +928 -0
  21. package/dist/db/schema.js.map +1 -0
  22. package/dist/environments.d.ts +11 -0
  23. package/dist/environments.d.ts.map +1 -0
  24. package/dist/environments.js +31 -0
  25. package/dist/environments.js.map +1 -0
  26. package/dist/execution/bootstrapRunner.d.ts +27 -0
  27. package/dist/execution/bootstrapRunner.d.ts.map +1 -0
  28. package/dist/execution/bootstrapRunner.js +79 -0
  29. package/dist/execution/bootstrapRunner.js.map +1 -0
  30. package/dist/execution/config.d.ts +37 -0
  31. package/dist/execution/config.d.ts.map +1 -0
  32. package/dist/execution/config.js +86 -0
  33. package/dist/execution/config.js.map +1 -0
  34. package/dist/execution/drive.d.ts +6 -0
  35. package/dist/execution/drive.d.ts.map +1 -0
  36. package/dist/execution/drive.js +13 -0
  37. package/dist/execution/drive.js.map +1 -0
  38. package/dist/execution/pgBossRunner.d.ts +82 -0
  39. package/dist/execution/pgBossRunner.d.ts.map +1 -0
  40. package/dist/execution/pgBossRunner.js +163 -0
  41. package/dist/execution/pgBossRunner.js.map +1 -0
  42. package/dist/gateways.d.ts +4 -0
  43. package/dist/gateways.d.ts.map +1 -0
  44. package/dist/gateways.js +91 -0
  45. package/dist/gateways.js.map +1 -0
  46. package/dist/index.d.ts +13 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +22 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/main.d.ts +2 -0
  51. package/dist/main.d.ts.map +1 -0
  52. package/dist/main.js +9 -0
  53. package/dist/main.js.map +1 -0
  54. package/dist/modelProvider.d.ts +6 -0
  55. package/dist/modelProvider.d.ts.map +1 -0
  56. package/dist/modelProvider.js +72 -0
  57. package/dist/modelProvider.js.map +1 -0
  58. package/dist/realtime.d.ts +62 -0
  59. package/dist/realtime.d.ts.map +1 -0
  60. package/dist/realtime.js +171 -0
  61. package/dist/realtime.js.map +1 -0
  62. package/dist/recurring.d.ts +11 -0
  63. package/dist/recurring.d.ts.map +1 -0
  64. package/dist/recurring.js +33 -0
  65. package/dist/recurring.js.map +1 -0
  66. package/dist/repositories/bootstrap.d.ts +25 -0
  67. package/dist/repositories/bootstrap.d.ts.map +1 -0
  68. package/dist/repositories/bootstrap.js +280 -0
  69. package/dist/repositories/bootstrap.js.map +1 -0
  70. package/dist/repositories/containerExecution.d.ts +33 -0
  71. package/dist/repositories/containerExecution.d.ts.map +1 -0
  72. package/dist/repositories/containerExecution.js +199 -0
  73. package/dist/repositories/containerExecution.js.map +1 -0
  74. package/dist/repositories/documents.d.ts +31 -0
  75. package/dist/repositories/documents.d.ts.map +1 -0
  76. package/dist/repositories/documents.js +176 -0
  77. package/dist/repositories/documents.js.map +1 -0
  78. package/dist/repositories/drizzle.d.ts +105 -0
  79. package/dist/repositories/drizzle.d.ts.map +1 -0
  80. package/dist/repositories/drizzle.js +1872 -0
  81. package/dist/repositories/drizzle.js.map +1 -0
  82. package/dist/repositories/environments.d.ts +23 -0
  83. package/dist/repositories/environments.d.ts.map +1 -0
  84. package/dist/repositories/environments.js +162 -0
  85. package/dist/repositories/environments.js.map +1 -0
  86. package/dist/repositories/fragments.d.ts +23 -0
  87. package/dist/repositories/fragments.d.ts.map +1 -0
  88. package/dist/repositories/fragments.js +190 -0
  89. package/dist/repositories/fragments.js.map +1 -0
  90. package/dist/repositories/github.d.ts +53 -0
  91. package/dist/repositories/github.d.ts.map +1 -0
  92. package/dist/repositories/github.js +441 -0
  93. package/dist/repositories/github.js.map +1 -0
  94. package/dist/repositories/localModelEndpoint.d.ts +12 -0
  95. package/dist/repositories/localModelEndpoint.d.ts.map +1 -0
  96. package/dist/repositories/localModelEndpoint.js +75 -0
  97. package/dist/repositories/localModelEndpoint.js.map +1 -0
  98. package/dist/repositories/notifications.d.ts +11 -0
  99. package/dist/repositories/notifications.d.ts.map +1 -0
  100. package/dist/repositories/notifications.js +88 -0
  101. package/dist/repositories/notifications.js.map +1 -0
  102. package/dist/repositories/personalSubscription.d.ts +22 -0
  103. package/dist/repositories/personalSubscription.d.ts.map +1 -0
  104. package/dist/repositories/personalSubscription.js +159 -0
  105. package/dist/repositories/personalSubscription.js.map +1 -0
  106. package/dist/repositories/providerApiKey.d.ts +18 -0
  107. package/dist/repositories/providerApiKey.d.ts.map +1 -0
  108. package/dist/repositories/providerApiKey.js +111 -0
  109. package/dist/repositories/providerApiKey.js.map +1 -0
  110. package/dist/repositories/providerSubscription.d.ts +16 -0
  111. package/dist/repositories/providerSubscription.d.ts.map +1 -0
  112. package/dist/repositories/providerSubscription.js +88 -0
  113. package/dist/repositories/providerSubscription.js.map +1 -0
  114. package/dist/repositories/slack.d.ts +23 -0
  115. package/dist/repositories/slack.d.ts.map +1 -0
  116. package/dist/repositories/slack.js +150 -0
  117. package/dist/repositories/slack.js.map +1 -0
  118. package/dist/repositories/tasks.d.ts +24 -0
  119. package/dist/repositories/tasks.d.ts.map +1 -0
  120. package/dist/repositories/tasks.js +194 -0
  121. package/dist/repositories/tasks.js.map +1 -0
  122. package/dist/retention.d.ts +38 -0
  123. package/dist/retention.d.ts.map +1 -0
  124. package/dist/retention.js +53 -0
  125. package/dist/retention.js.map +1 -0
  126. package/dist/runtime.d.ts +10 -0
  127. package/dist/runtime.d.ts.map +1 -0
  128. package/dist/runtime.js +13 -0
  129. package/dist/runtime.js.map +1 -0
  130. package/dist/server.d.ts +41 -0
  131. package/dist/server.d.ts.map +1 -0
  132. package/dist/server.js +138 -0
  133. package/dist/server.js.map +1 -0
  134. package/dist/tasks/JiraProvider.d.ts +27 -0
  135. package/dist/tasks/JiraProvider.d.ts.map +1 -0
  136. package/dist/tasks/JiraProvider.js +79 -0
  137. package/dist/tasks/JiraProvider.js.map +1 -0
  138. package/drizzle/20260622175812_flashy_maginty/migration.sql +689 -0
  139. package/drizzle/20260622175812_flashy_maginty/snapshot.json +8318 -0
  140. package/drizzle/20260623172634_loud_wallop/migration.sql +11 -0
  141. package/drizzle/20260623172634_loud_wallop/snapshot.json +8439 -0
  142. package/drizzle/20260623174706_acoustic_zemo/migration.sql +16 -0
  143. package/drizzle/20260623174706_acoustic_zemo/snapshot.json +8506 -0
  144. package/drizzle/20260623184400_silent_cardiac/migration.sql +24 -0
  145. package/drizzle/20260623184400_silent_cardiac/snapshot.json +8639 -0
  146. package/drizzle/20260623205323_quick_arclight/migration.sql +1 -0
  147. package/drizzle/20260623205323_quick_arclight/snapshot.json +8963 -0
  148. package/drizzle/20260623221910_black_zombie/migration.sql +22 -0
  149. package/drizzle/20260623221910_black_zombie/snapshot.json +9189 -0
  150. package/drizzle/20260624131343_far_lily_hollister/migration.sql +3 -0
  151. package/drizzle/20260624131343_far_lily_hollister/snapshot.json +9228 -0
  152. package/drizzle/20260624135452_tiny_norman_osborn/migration.sql +11 -0
  153. package/drizzle/20260624135452_tiny_norman_osborn/snapshot.json +9126 -0
  154. package/drizzle/20260624140138_wandering_avengers/migration.sql +1 -0
  155. package/drizzle/20260624140138_wandering_avengers/snapshot.json +9045 -0
  156. package/package.json +62 -0
@@ -0,0 +1,171 @@
1
+ import { authorizeWsUpgrade } from '@cat-factory/server';
2
+ import { WebSocket, WebSocketServer } from 'ws';
3
+ const WS_EVENTS_PATH = /^\/workspaces\/([^/]+)\/events$/;
4
+ /**
5
+ * Per-workspace subscriber registry. Every browser subscribed to a workspace's stream
6
+ * converges here, so a published event fans out to all of them. In-memory and
7
+ * single-process: the Node service runs as one process (unlike the Worker's globally
8
+ * addressed Durable Object), which is the right model for the self-hosted / local
9
+ * deployments this facade targets. A multi-replica deployment would need a shared bus
10
+ * (Postgres LISTEN/NOTIFY) in front of this — a follow-up, not needed for local mode.
11
+ */
12
+ export class NodeRealtimeHub {
13
+ rooms = new Map();
14
+ /** Add a socket to a workspace's room; it is reaped on close/error. */
15
+ subscribe(workspaceId, socket) {
16
+ let room = this.rooms.get(workspaceId);
17
+ if (!room) {
18
+ room = new Set();
19
+ this.rooms.set(workspaceId, room);
20
+ }
21
+ room.add(socket);
22
+ const drop = () => this.unsubscribe(workspaceId, socket);
23
+ socket.on('close', drop);
24
+ socket.on('error', drop);
25
+ }
26
+ unsubscribe(workspaceId, socket) {
27
+ const room = this.rooms.get(workspaceId);
28
+ if (!room)
29
+ return;
30
+ room.delete(socket);
31
+ if (room.size === 0)
32
+ this.rooms.delete(workspaceId);
33
+ }
34
+ /** Fan a pre-serialised JSON event out to every socket on a workspace's stream. */
35
+ broadcast(workspaceId, payload) {
36
+ const room = this.rooms.get(workspaceId);
37
+ if (!room)
38
+ return;
39
+ for (const socket of room) {
40
+ if (socket.readyState !== WebSocket.OPEN)
41
+ continue;
42
+ try {
43
+ socket.send(payload);
44
+ }
45
+ catch {
46
+ // Socket is mid-close; its close handler reaps it. Ignore.
47
+ }
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Pushes execution/board events to the {@link NodeRealtimeHub}, which fans them out to
53
+ * subscribed browsers. The event shapes are IDENTICAL to the Worker's
54
+ * `DurableObjectEventPublisher`, so the SPA's stream handling is runtime-agnostic.
55
+ * Best-effort: a publish failure must never break a state transition (the persisted
56
+ * row is the source of truth and clients reconcile on reconnect), so each publish
57
+ * swallows its own errors.
58
+ */
59
+ export class NodeEventPublisher {
60
+ hub;
61
+ constructor(hub) {
62
+ this.hub = hub;
63
+ }
64
+ async executionChanged(workspaceId, instance, block) {
65
+ this.publish(workspaceId, {
66
+ type: 'execution',
67
+ instance,
68
+ block: block ?? null,
69
+ at: Date.now(),
70
+ });
71
+ }
72
+ async boardChanged(workspaceId, reason, _blockId) {
73
+ this.publish(workspaceId, { type: 'board', reason, at: Date.now() });
74
+ }
75
+ async bootstrapChanged(workspaceId, job, block) {
76
+ this.publish(workspaceId, { type: 'bootstrap', job, block: block ?? null, at: Date.now() });
77
+ }
78
+ async notificationChanged(workspaceId, notification) {
79
+ this.publish(workspaceId, { type: 'notification', notification, at: Date.now() });
80
+ }
81
+ async llmCallObserved(workspaceId, activity) {
82
+ this.publish(workspaceId, { type: 'llmCall', call: activity, at: Date.now() });
83
+ }
84
+ async requirementReviewChanged(workspaceId, review) {
85
+ this.publish(workspaceId, { type: 'requirements', review, at: Date.now() });
86
+ }
87
+ async consensusSessionChanged(workspaceId, session) {
88
+ this.publish(workspaceId, { type: 'consensus', session, at: Date.now() });
89
+ }
90
+ async clarityReviewChanged(workspaceId, review) {
91
+ this.publish(workspaceId, { type: 'clarity', review, at: Date.now() });
92
+ }
93
+ publish(workspaceId, event) {
94
+ try {
95
+ this.hub.broadcast(workspaceId, JSON.stringify(event));
96
+ }
97
+ catch {
98
+ // No subscribers / serialisation hiccup — the DB write is authoritative and the
99
+ // client's reconnect-resync covers any missed event.
100
+ }
101
+ }
102
+ }
103
+ /** How often to ping idle sockets to detect (and reap) half-open connections. */
104
+ const HEARTBEAT_INTERVAL_MS = 30_000;
105
+ /**
106
+ * Attach the real-time WebSocket transport to a running Node HTTP server: accept
107
+ * `GET /workspaces/:ws/events` upgrades (authorising the `?ticket=` exactly like the
108
+ * shared EventsController), register each socket into the {@link NodeRealtimeHub}, and
109
+ * run a heartbeat that terminates dead connections. Returns a stop function that clears
110
+ * the heartbeat and closes the WS server (call it on graceful shutdown).
111
+ */
112
+ export function attachRealtime(server, hub, auth, log) {
113
+ const wss = new WebSocketServer({ noServer: true });
114
+ server.on('upgrade', (request, socket, head) => {
115
+ const url = new URL(request.url ?? '/', 'http://localhost');
116
+ const match = WS_EVENTS_PATH.exec(url.pathname);
117
+ // Not our route: refuse rather than leave the socket dangling. (Node mode has no
118
+ // other WebSocket endpoints.)
119
+ if (!match) {
120
+ socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
121
+ socket.destroy();
122
+ return;
123
+ }
124
+ const workspaceId = decodeURIComponent(match[1]);
125
+ const ticket = url.searchParams.get('ticket') ?? undefined;
126
+ void authorizeWsUpgrade(auth, ticket, workspaceId).then((verdict) => {
127
+ if (!verdict.ok) {
128
+ const reason = verdict.status === 401 ? 'Unauthorized' : 'Service Unavailable';
129
+ socket.write(`HTTP/1.1 ${verdict.status} ${reason}\r\n\r\n`);
130
+ socket.destroy();
131
+ return;
132
+ }
133
+ wss.handleUpgrade(request, socket, head, (ws) => {
134
+ hub.subscribe(workspaceId, ws);
135
+ wss.emit('connection', ws, request);
136
+ });
137
+ });
138
+ });
139
+ // Liveness sweep: a socket that doesn't answer a ping before the next tick is
140
+ // half-open (the close event never fired) — terminate it so the room doesn't leak.
141
+ const alive = new WeakSet();
142
+ wss.on('connection', (ws) => {
143
+ alive.add(ws);
144
+ ws.on('pong', () => alive.add(ws));
145
+ });
146
+ const heartbeat = setInterval(() => {
147
+ for (const ws of wss.clients) {
148
+ if (!alive.has(ws)) {
149
+ ws.terminate();
150
+ continue;
151
+ }
152
+ alive.delete(ws);
153
+ try {
154
+ ws.ping();
155
+ }
156
+ catch {
157
+ ws.terminate();
158
+ }
159
+ }
160
+ }, HEARTBEAT_INTERVAL_MS);
161
+ // Don't let the heartbeat timer keep the process alive on shutdown.
162
+ heartbeat.unref?.();
163
+ log.info({}, 'real-time WebSocket transport attached (/workspaces/:ws/events)');
164
+ return () => {
165
+ clearInterval(heartbeat);
166
+ for (const ws of wss.clients)
167
+ ws.terminate();
168
+ wss.close();
169
+ };
170
+ }
171
+ //# sourceMappingURL=realtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAcA,OAAO,EAAmB,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACzE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,IAAI,CAAA;AAyB/C,MAAM,cAAc,GAAG,iCAAiC,CAAA;AAExD;;;;;;;GAOG;AACH,MAAM,OAAO,eAAe;IACT,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAA;IAE1D,uEAAuE;IACvE,SAAS,CAAC,WAAmB,EAAE,MAAiB;QAC9C,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,IAAI,GAAG,EAAE,CAAA;YAChB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;QACnC,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAChB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACxD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QACxB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAC1B,CAAC;IAEO,WAAW,CAAC,WAAmB,EAAE,MAAiB;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IACrD,CAAC;IAED,mFAAmF;IACnF,SAAS,CAAC,WAAmB,EAAE,OAAe;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;YAC1B,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI;gBAAE,SAAQ;YAClD,IAAI,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,2DAA2D;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IACA,GAAG;IAAhC,YAA6B,GAAoB;mBAApB,GAAG;IAAoB,CAAC;IAErD,KAAK,CAAC,gBAAgB,CACpB,WAAmB,EACnB,QAA2B,EAC3B,KAAoB;QAEpB,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;YACxB,IAAI,EAAE,WAAW;YACjB,QAAQ;YACR,KAAK,EAAE,KAAK,IAAI,IAAI;YACpB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;SACf,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,WAAmB,EAAE,MAAc,EAAE,QAAwB;QAC9E,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IACtE,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,WAAmB,EACnB,GAAiB,EACjB,KAAoB;QAEpB,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,IAAI,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,WAAmB,EAAE,YAA0B;QACvE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IACnF,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,WAAmB,EAAE,QAAyB;QAClE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAChF,CAAC;IAED,KAAK,CAAC,wBAAwB,CAAC,WAAmB,EAAE,MAAyB;QAC3E,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC7E,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,WAAmB,EAAE,OAAyB;QAC1E,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,WAAmB,EAAE,MAAqB;QACnE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IACxE,CAAC;IAEO,OAAO,CAAC,WAAmB,EAAE,KAAqB;QACxD,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,gFAAgF;YAChF,qDAAqD;QACvD,CAAC;IACH,CAAC;CACF;AAED,iFAAiF;AACjF,MAAM,qBAAqB,GAAG,MAAM,CAAA;AAEpC;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAwB,EACxB,GAAoB,EACpB,IAAgB,EAChB,GAAmB;IAEnB,MAAM,GAAG,GAAG,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAEnD,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC7C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAA;QAC3D,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC/C,iFAAiF;QACjF,8BAA8B;QAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;YAC9C,MAAM,CAAC,OAAO,EAAE,CAAA;YAChB,OAAM;QACR,CAAC;QACD,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAA;QACjD,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAA;QAE1D,KAAK,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;YAClE,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,qBAAqB,CAAA;gBAC9E,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,CAAC,MAAM,IAAI,MAAM,UAAU,CAAC,CAAA;gBAC5D,MAAM,CAAC,OAAO,EAAE,CAAA;gBAChB,OAAM;YACR,CAAC;YACD,GAAG,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;gBAC9C,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;gBAC9B,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;YACrC,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,8EAA8E;IAC9E,mFAAmF;IACnF,MAAM,KAAK,GAAG,IAAI,OAAO,EAAa,CAAA;IACtC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE;QAC1B,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACb,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;IACF,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnB,EAAE,CAAC,SAAS,EAAE,CAAA;gBACd,SAAQ;YACV,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAChB,IAAI,CAAC;gBACH,EAAE,CAAC,IAAI,EAAE,CAAA;YACX,CAAC;YAAC,MAAM,CAAC;gBACP,EAAE,CAAC,SAAS,EAAE,CAAA;YAChB,CAAC;QACH,CAAC;IACH,CAAC,EAAE,qBAAqB,CAAC,CAAA;IACzB,oEAAoE;IACpE,SAAS,CAAC,KAAK,EAAE,EAAE,CAAA;IAEnB,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,iEAAiE,CAAC,CAAA;IAE/E,OAAO,GAAG,EAAE;QACV,aAAa,CAAC,SAAS,CAAC,CAAA;QACxB,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,OAAO;YAAE,EAAE,CAAC,SAAS,EAAE,CAAA;QAC5C,GAAG,CAAC,KAAK,EAAE,CAAA;IACb,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Clock } from '@cat-factory/kernel';
2
+ import type { Logger, ServerContainer } from '@cat-factory/server';
3
+ /** How often the Node service checks for due schedules. */
4
+ export declare const SCHEDULE_SWEEP_INTERVAL_MS: number;
5
+ /**
6
+ * Start the periodic schedule sweep. Runs once immediately then on a one-minute
7
+ * timer. Best-effort: a failed sweep is logged and retried next tick, never thrown.
8
+ * Returns a stop function that clears the timer.
9
+ */
10
+ export declare function startScheduleSweeper(container: ServerContainer, clock: Clock, log: Logger): () => void;
11
+ //# sourceMappingURL=recurring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring.d.ts","sourceRoot":"","sources":["../src/recurring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAQlE,2DAA2D;AAC3D,eAAO,MAAM,0BAA0B,QAAY,CAAA;AAEnD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,MAAM,IAAI,CAoBZ"}
@@ -0,0 +1,33 @@
1
+ // Periodic recurring-pipeline sweep for the Node facade — the analogue of the
2
+ // Worker's every-2-min cron call to `runDue`. The Node service has no cron, so a
3
+ // timer fires every due schedule (the actual cadence is hours; a frequent tick just
4
+ // bounds the latency between "due" and "started"). No-op when the recurring module
5
+ // isn't wired.
6
+ /** How often the Node service checks for due schedules. */
7
+ export const SCHEDULE_SWEEP_INTERVAL_MS = 60 * 1000;
8
+ /**
9
+ * Start the periodic schedule sweep. Runs once immediately then on a one-minute
10
+ * timer. Best-effort: a failed sweep is logged and retried next tick, never thrown.
11
+ * Returns a stop function that clears the timer.
12
+ */
13
+ export function startScheduleSweeper(container, clock, log) {
14
+ const recurring = container.recurring;
15
+ if (!recurring)
16
+ return () => { };
17
+ const tick = async () => {
18
+ try {
19
+ const { fired, skipped } = await recurring.service.runDue(clock.now());
20
+ if (fired > 0 || skipped > 0) {
21
+ log.info({ fired, skipped }, 'fired recurring pipelines');
22
+ }
23
+ }
24
+ catch (error) {
25
+ log.error({ err: error instanceof Error ? error.message : String(error) }, 'recurring-pipeline sweep failed');
26
+ }
27
+ };
28
+ void tick();
29
+ const timer = setInterval(() => void tick(), SCHEDULE_SWEEP_INTERVAL_MS);
30
+ timer.unref?.();
31
+ return () => clearInterval(timer);
32
+ }
33
+ //# sourceMappingURL=recurring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring.js","sourceRoot":"","sources":["../src/recurring.ts"],"names":[],"mappings":"AAGA,8EAA8E;AAC9E,iFAAiF;AACjF,oFAAoF;AACpF,mFAAmF;AACnF,eAAe;AAEf,2DAA2D;AAC3D,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,IAAI,CAAA;AAEnD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA0B,EAC1B,KAAY,EACZ,GAAW;IAEX,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;IACrC,IAAI,CAAC,SAAS;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IAC/B,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;YACtE,IAAI,KAAK,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,2BAA2B,CAAC,CAAA;YAC3D,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CACP,EAAE,GAAG,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAC/D,iCAAiC,CAClC,CAAA;QACH,CAAC;IACH,CAAC,CAAA;IACD,KAAK,IAAI,EAAE,CAAA;IACX,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,EAAE,0BAA0B,CAAC,CAAA;IACxE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAA;IACf,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;AACnC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { BootstrapJobRecord, BootstrapJobRecordPatch, BootstrapJobRepository, ReferenceArchitectureRecord, ReferenceArchitectureRecordPatch, ReferenceArchitectureRepository } from '@cat-factory/kernel';
2
+ import type { DrizzleDb } from '../db/client.js';
3
+ export declare class DrizzleReferenceArchitectureRepository implements ReferenceArchitectureRepository {
4
+ private readonly db;
5
+ constructor(db: DrizzleDb);
6
+ insert(record: ReferenceArchitectureRecord): Promise<void>;
7
+ update(workspaceId: string, id: string, patch: ReferenceArchitectureRecordPatch): Promise<void>;
8
+ get(workspaceId: string, id: string): Promise<ReferenceArchitectureRecord | null>;
9
+ listByWorkspace(workspaceId: string): Promise<ReferenceArchitectureRecord[]>;
10
+ softDelete(workspaceId: string, id: string, at: number): Promise<void>;
11
+ }
12
+ /** Postgres-backed bootstrap runs, stored as kind='bootstrap' rows of agent_runs. */
13
+ export declare class DrizzleBootstrapJobRepository implements BootstrapJobRepository {
14
+ private readonly db;
15
+ constructor(db: DrizzleDb);
16
+ /** The service_id of a workspace's block, as a correlated subquery value. */
17
+ private blockServiceId;
18
+ insert(record: BootstrapJobRecord): Promise<void>;
19
+ update(workspaceId: string, id: string, patch: BootstrapJobRecordPatch): Promise<void>;
20
+ get(workspaceId: string, id: string): Promise<BootstrapJobRecord | null>;
21
+ listByWorkspace(workspaceId: string): Promise<BootstrapJobRecord[]>;
22
+ listByService(serviceId: string): Promise<BootstrapJobRecord[]>;
23
+ listByServices(serviceIds: string[]): Promise<BootstrapJobRecord[]>;
24
+ }
25
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/repositories/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,EAC3B,gCAAgC,EAChC,+BAA+B,EAEhC,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAqChD,qBAAa,sCAAuC,YAAW,+BAA+B;IAChF,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,SAAS,EAAI;IAExC,MAAM,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAa/D;IAEK,MAAM,CACV,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,gCAAgC,GACtC,OAAO,CAAC,IAAI,CAAC,CAmBf;IAEK,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAatF;IAEK,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,EAAE,CAAC,CAYjF;IAEK,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3E;CACF;AAqGD,qFAAqF;AACrF,qBAAa,6BAA8B,YAAW,sBAAsB;IAC9D,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,SAAS,EAAI;IAE9C,6EAA6E;IAC7E,OAAO,CAAC,cAAc;IAKhB,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBtD;IAEK,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC3F;IAEK,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAa7E;IAEK,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAOxE;IAEK,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAOpE;IAEK,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAQxE;CACF"}
@@ -0,0 +1,280 @@
1
+ import { and, desc, eq, inArray, isNull, sql } from 'drizzle-orm';
2
+ import { agentRuns, blocks, referenceArchitectures } from '../db/schema.js';
3
+ function rowToRefArch(row) {
4
+ return {
5
+ id: row.id,
6
+ workspaceId: row.workspace_id,
7
+ name: row.name,
8
+ description: row.description,
9
+ repoOwner: row.repo_owner,
10
+ repoName: row.repo_name,
11
+ defaultInstructions: row.default_instructions,
12
+ createdAt: row.created_at,
13
+ updatedAt: row.updated_at,
14
+ deletedAt: row.deleted_at,
15
+ };
16
+ }
17
+ const REF_ARCH_PATCH_COLUMNS = {
18
+ name: 'name',
19
+ description: 'description',
20
+ repoOwner: 'repo_owner',
21
+ repoName: 'repo_name',
22
+ defaultInstructions: 'default_instructions',
23
+ updatedAt: 'updated_at',
24
+ };
25
+ export class DrizzleReferenceArchitectureRepository {
26
+ db;
27
+ constructor(db) {
28
+ this.db = db;
29
+ }
30
+ async insert(record) {
31
+ await this.db.insert(referenceArchitectures).values({
32
+ id: record.id,
33
+ workspace_id: record.workspaceId,
34
+ name: record.name,
35
+ description: record.description,
36
+ repo_owner: record.repoOwner,
37
+ repo_name: record.repoName,
38
+ default_instructions: record.defaultInstructions,
39
+ created_at: record.createdAt,
40
+ updated_at: record.updatedAt,
41
+ deleted_at: null,
42
+ });
43
+ }
44
+ async update(workspaceId, id, patch) {
45
+ const set = {};
46
+ for (const [key, value] of Object.entries(patch)) {
47
+ if (value === undefined)
48
+ continue;
49
+ set[REF_ARCH_PATCH_COLUMNS[key]] = value;
50
+ }
51
+ if (Object.keys(set).length === 0)
52
+ return;
53
+ await this.db
54
+ .update(referenceArchitectures)
55
+ .set(set)
56
+ .where(and(eq(referenceArchitectures.workspace_id, workspaceId), eq(referenceArchitectures.id, id), isNull(referenceArchitectures.deleted_at)));
57
+ }
58
+ async get(workspaceId, id) {
59
+ const rows = await this.db
60
+ .select()
61
+ .from(referenceArchitectures)
62
+ .where(and(eq(referenceArchitectures.workspace_id, workspaceId), eq(referenceArchitectures.id, id), isNull(referenceArchitectures.deleted_at)))
63
+ .limit(1);
64
+ return rows[0] ? rowToRefArch(rows[0]) : null;
65
+ }
66
+ async listByWorkspace(workspaceId) {
67
+ const rows = await this.db
68
+ .select()
69
+ .from(referenceArchitectures)
70
+ .where(and(eq(referenceArchitectures.workspace_id, workspaceId), isNull(referenceArchitectures.deleted_at)))
71
+ .orderBy(desc(referenceArchitectures.created_at));
72
+ return rows.map(rowToRefArch);
73
+ }
74
+ async softDelete(workspaceId, id, at) {
75
+ await this.db
76
+ .update(referenceArchitectures)
77
+ .set({ deleted_at: at })
78
+ .where(and(eq(referenceArchitectures.workspace_id, workspaceId), eq(referenceArchitectures.id, id), isNull(referenceArchitectures.deleted_at)));
79
+ }
80
+ }
81
+ function parseSubtasks(raw) {
82
+ if (!raw)
83
+ return null;
84
+ try {
85
+ const o = JSON.parse(raw);
86
+ if (typeof o.completed === 'number' &&
87
+ typeof o.inProgress === 'number' &&
88
+ typeof o.total === 'number') {
89
+ let items;
90
+ if (Array.isArray(o.items)) {
91
+ items = [];
92
+ for (const it of o.items) {
93
+ if (!it || typeof it !== 'object')
94
+ continue;
95
+ const r = it;
96
+ const status = r.status;
97
+ if (typeof r.label === 'string' &&
98
+ (status === 'pending' || status === 'in_progress' || status === 'completed')) {
99
+ items.push({ label: r.label, status });
100
+ }
101
+ }
102
+ }
103
+ return { completed: o.completed, inProgress: o.inProgress, total: o.total, items };
104
+ }
105
+ }
106
+ catch {
107
+ // fall through
108
+ }
109
+ return null;
110
+ }
111
+ function parseFailure(raw) {
112
+ if (!raw)
113
+ return null;
114
+ try {
115
+ const o = JSON.parse(raw);
116
+ if (o && typeof o.kind === 'string' && typeof o.message === 'string')
117
+ return o;
118
+ }
119
+ catch {
120
+ // fall through
121
+ }
122
+ return null;
123
+ }
124
+ function parseDetail(raw) {
125
+ try {
126
+ const o = JSON.parse(raw);
127
+ return {
128
+ referenceArchitectureId: o.referenceArchitectureId ?? null,
129
+ referenceArchitectureName: o.referenceArchitectureName ?? null,
130
+ repoName: o.repoName ?? '',
131
+ repoOwner: o.repoOwner ?? null,
132
+ repoUrl: o.repoUrl ?? null,
133
+ instructions: o.instructions ?? '',
134
+ };
135
+ }
136
+ catch {
137
+ return {
138
+ referenceArchitectureId: null,
139
+ referenceArchitectureName: null,
140
+ repoName: '',
141
+ repoOwner: null,
142
+ repoUrl: null,
143
+ instructions: '',
144
+ };
145
+ }
146
+ }
147
+ function rowToBootstrapJob(row) {
148
+ const detail = parseDetail(row.detail);
149
+ return {
150
+ id: row.id,
151
+ workspaceId: row.workspace_id,
152
+ referenceArchitectureId: detail.referenceArchitectureId,
153
+ referenceArchitectureName: detail.referenceArchitectureName,
154
+ repoName: detail.repoName,
155
+ repoOwner: detail.repoOwner,
156
+ repoUrl: detail.repoUrl,
157
+ instructions: detail.instructions,
158
+ status: row.status,
159
+ blockId: row.block_id ?? null,
160
+ subtasks: parseSubtasks(row.subtasks ?? null),
161
+ error: row.error,
162
+ failure: parseFailure(row.failure ?? null),
163
+ createdAt: row.created_at,
164
+ updatedAt: row.updated_at,
165
+ };
166
+ }
167
+ /** Postgres-backed bootstrap runs, stored as kind='bootstrap' rows of agent_runs. */
168
+ export class DrizzleBootstrapJobRepository {
169
+ db;
170
+ constructor(db) {
171
+ this.db = db;
172
+ }
173
+ /** The service_id of a workspace's block, as a correlated subquery value. */
174
+ blockServiceId(workspaceId, blockId) {
175
+ return sql `(SELECT ${blocks.service_id} FROM ${blocks}
176
+ WHERE ${blocks.workspace_id} = ${workspaceId} AND ${blocks.id} = ${blockId})`;
177
+ }
178
+ async insert(record) {
179
+ const detail = {
180
+ referenceArchitectureId: record.referenceArchitectureId,
181
+ referenceArchitectureName: record.referenceArchitectureName,
182
+ repoName: record.repoName,
183
+ repoOwner: record.repoOwner,
184
+ repoUrl: record.repoUrl,
185
+ instructions: record.instructions,
186
+ };
187
+ await this.db.insert(agentRuns).values({
188
+ workspace_id: record.workspaceId,
189
+ id: record.id,
190
+ kind: 'bootstrap',
191
+ block_id: record.blockId,
192
+ status: record.status,
193
+ detail: JSON.stringify(detail),
194
+ subtasks: record.subtasks == null ? null : JSON.stringify(record.subtasks),
195
+ error: record.error,
196
+ failure: record.failure == null ? null : JSON.stringify(record.failure),
197
+ created_at: record.createdAt,
198
+ updated_at: record.updatedAt,
199
+ // Stamp service_id from the materialised service frame (when known) so a shared
200
+ // service's in-flight bootstrap surfaces on every board that mounts it.
201
+ service_id: this.blockServiceId(record.workspaceId, record.blockId),
202
+ });
203
+ }
204
+ async update(workspaceId, id, patch) {
205
+ const set = {};
206
+ // repoOwner/repoUrl live inside the `detail` JSON; patch them together with a
207
+ // single jsonb_set chain so a partial patch leaves the other field untouched.
208
+ let detailExpr = sql `${agentRuns.detail}::jsonb`;
209
+ let patchesDetail = false;
210
+ if (patch.repoOwner !== undefined) {
211
+ detailExpr = sql `jsonb_set(${detailExpr}, '{repoOwner}', ${JSON.stringify(patch.repoOwner)}::jsonb)`;
212
+ patchesDetail = true;
213
+ }
214
+ if (patch.repoUrl !== undefined) {
215
+ detailExpr = sql `jsonb_set(${detailExpr}, '{repoUrl}', ${JSON.stringify(patch.repoUrl)}::jsonb)`;
216
+ patchesDetail = true;
217
+ }
218
+ if (patchesDetail)
219
+ set.detail = sql `(${detailExpr})::text`;
220
+ if (patch.status !== undefined)
221
+ set.status = patch.status;
222
+ if (patch.blockId !== undefined) {
223
+ set.block_id = patch.blockId;
224
+ // The run row is inserted before its service frame exists, so refresh service_id
225
+ // from the block whenever block_id is (re)assigned.
226
+ set.service_id = this.blockServiceId(workspaceId, patch.blockId);
227
+ }
228
+ if (patch.subtasks !== undefined) {
229
+ set.subtasks = patch.subtasks == null ? null : JSON.stringify(patch.subtasks);
230
+ }
231
+ if (patch.error !== undefined)
232
+ set.error = patch.error;
233
+ if (patch.failure !== undefined) {
234
+ set.failure = patch.failure == null ? null : JSON.stringify(patch.failure);
235
+ }
236
+ if (patch.updatedAt !== undefined)
237
+ set.updated_at = patch.updatedAt;
238
+ if (Object.keys(set).length === 0)
239
+ return;
240
+ await this.db
241
+ .update(agentRuns)
242
+ .set(set)
243
+ .where(and(eq(agentRuns.workspace_id, workspaceId), eq(agentRuns.id, id), eq(agentRuns.kind, 'bootstrap')));
244
+ }
245
+ async get(workspaceId, id) {
246
+ const rows = await this.db
247
+ .select()
248
+ .from(agentRuns)
249
+ .where(and(eq(agentRuns.workspace_id, workspaceId), eq(agentRuns.id, id), eq(agentRuns.kind, 'bootstrap')))
250
+ .limit(1);
251
+ return rows[0] ? rowToBootstrapJob(rows[0]) : null;
252
+ }
253
+ async listByWorkspace(workspaceId) {
254
+ const rows = await this.db
255
+ .select()
256
+ .from(agentRuns)
257
+ .where(and(eq(agentRuns.workspace_id, workspaceId), eq(agentRuns.kind, 'bootstrap')))
258
+ .orderBy(desc(agentRuns.created_at));
259
+ return rows.map(rowToBootstrapJob);
260
+ }
261
+ async listByService(serviceId) {
262
+ const rows = await this.db
263
+ .select()
264
+ .from(agentRuns)
265
+ .where(and(eq(agentRuns.service_id, serviceId), eq(agentRuns.kind, 'bootstrap')))
266
+ .orderBy(desc(agentRuns.created_at));
267
+ return rows.map(rowToBootstrapJob);
268
+ }
269
+ async listByServices(serviceIds) {
270
+ if (serviceIds.length === 0)
271
+ return [];
272
+ const rows = await this.db
273
+ .select()
274
+ .from(agentRuns)
275
+ .where(and(inArray(agentRuns.service_id, serviceIds), eq(agentRuns.kind, 'bootstrap')))
276
+ .orderBy(desc(agentRuns.created_at));
277
+ return rows.map(rowToBootstrapJob);
278
+ }
279
+ }
280
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/repositories/bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { GitHubInstallation, GitHubInstallationRepository, RunnerPoolConnectionRecord, RunnerPoolConnectionRepository, Service, ServiceRepository } from '@cat-factory/kernel';
2
+ import type { DrizzleDb } from '../db/client.js';
3
+ /** Postgres-backed store of workspace → runner-pool bindings (mirror of D1 migration 0013). */
4
+ export declare class DrizzleRunnerPoolConnectionRepository implements RunnerPoolConnectionRepository {
5
+ private readonly db;
6
+ constructor(db: DrizzleDb);
7
+ getByWorkspace(workspaceId: string): Promise<RunnerPoolConnectionRecord | null>;
8
+ upsert(record: RunnerPoolConnectionRecord): Promise<void>;
9
+ softDelete(workspaceId: string, at: number): Promise<void>;
10
+ }
11
+ /** Postgres-backed store of workspace → GitHub App installation bindings (mirror of D1 migration 0004). */
12
+ export declare class DrizzleGitHubInstallationRepository implements GitHubInstallationRepository {
13
+ private readonly db;
14
+ constructor(db: DrizzleDb);
15
+ getByInstallationId(installationId: number): Promise<GitHubInstallation | null>;
16
+ getByWorkspace(workspaceId: string): Promise<GitHubInstallation | null>;
17
+ listWorkspacesForInstallation(installationId: number): Promise<string[]>;
18
+ listActive(): Promise<GitHubInstallation[]>;
19
+ upsert(installation: GitHubInstallation): Promise<void>;
20
+ updateCachedToken(installationId: number, token: string, expiresAt: number): Promise<void>;
21
+ softDelete(installationId: number, at: number): Promise<void>;
22
+ }
23
+ /**
24
+ * Minimal read adapter the shared `buildResolveRepoTarget` needs to resolve a frame's
25
+ * service (and, for a monorepo, its pinned subdirectory). Only `getByFrameBlock` is
26
+ * implemented — the full account-owned service store lives in `drizzle.ts`.
27
+ */
28
+ export declare class DrizzleServiceFrameRepository implements Pick<ServiceRepository, 'getByFrameBlock'> {
29
+ private readonly db;
30
+ constructor(db: DrizzleDb);
31
+ getByFrameBlock(frameBlockId: string): Promise<Service | null>;
32
+ }
33
+ //# sourceMappingURL=containerExecution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerExecution.d.ts","sourceRoot":"","sources":["../../src/repositories/containerExecution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,4BAA4B,EAC5B,0BAA0B,EAC1B,8BAA8B,EAC9B,OAAO,EACP,iBAAiB,EAClB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAUhD,+FAA+F;AAC/F,qBAAa,qCAAsC,YAAW,8BAA8B;IAC9E,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,SAAS,EAAI;IAExC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAuBpF;IAEK,MAAM,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB9D;IAEK,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/D;CACF;AAiBD,2GAA2G;AAC3G,qBAAa,mCAAoC,YAAW,4BAA4B;IAC1E,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,SAAS,EAAI;IAExC,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAOpF;IAEK,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA8B5E;IAEK,6BAA6B,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsB7E;IAEK,UAAU,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAMhD;IAEK,MAAM,CAAC,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB5D;IAEK,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/F;IAEK,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKlE;CACF;AAED;;;;GAIG;AACH,qBAAa,6BAA8B,YAAW,IAAI,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAClF,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,SAAS,EAAI;IAExC,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAgBnE;CACF"}