@data-club/ai-hub-server 0.0.1

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 (248) hide show
  1. package/dist/auth/argon2.d.ts +72 -0
  2. package/dist/auth/argon2.d.ts.map +1 -0
  3. package/dist/auth/argon2.js +145 -0
  4. package/dist/auth/argon2.js.map +1 -0
  5. package/dist/auth/encryption.d.ts +52 -0
  6. package/dist/auth/encryption.d.ts.map +1 -0
  7. package/dist/auth/encryption.js +98 -0
  8. package/dist/auth/encryption.js.map +1 -0
  9. package/dist/auth/jwt.d.ts +133 -0
  10. package/dist/auth/jwt.d.ts.map +1 -0
  11. package/dist/auth/jwt.js +147 -0
  12. package/dist/auth/jwt.js.map +1 -0
  13. package/dist/auth/middleware.d.ts +101 -0
  14. package/dist/auth/middleware.d.ts.map +1 -0
  15. package/dist/auth/middleware.js +161 -0
  16. package/dist/auth/middleware.js.map +1 -0
  17. package/dist/auth/passwordPolicy.d.ts +72 -0
  18. package/dist/auth/passwordPolicy.d.ts.map +1 -0
  19. package/dist/auth/passwordPolicy.js +88 -0
  20. package/dist/auth/passwordPolicy.js.map +1 -0
  21. package/dist/auth/roleRules.d.ts +200 -0
  22. package/dist/auth/roleRules.d.ts.map +1 -0
  23. package/dist/auth/roleRules.js +365 -0
  24. package/dist/auth/roleRules.js.map +1 -0
  25. package/dist/auth/userView.d.ts +55 -0
  26. package/dist/auth/userView.d.ts.map +1 -0
  27. package/dist/auth/userView.js +77 -0
  28. package/dist/auth/userView.js.map +1 -0
  29. package/dist/bootstrap.d.ts +104 -0
  30. package/dist/bootstrap.d.ts.map +1 -0
  31. package/dist/bootstrap.js +160 -0
  32. package/dist/bootstrap.js.map +1 -0
  33. package/dist/db/connection.d.ts +39 -0
  34. package/dist/db/connection.d.ts.map +1 -0
  35. package/dist/db/connection.js +62 -0
  36. package/dist/db/connection.js.map +1 -0
  37. package/dist/db/migrate.d.ts +31 -0
  38. package/dist/db/migrate.d.ts.map +1 -0
  39. package/dist/db/migrate.js +197 -0
  40. package/dist/db/migrate.js.map +1 -0
  41. package/dist/db/schema.d.ts +1902 -0
  42. package/dist/db/schema.d.ts.map +1 -0
  43. package/dist/db/schema.js +662 -0
  44. package/dist/db/schema.js.map +1 -0
  45. package/dist/db/seed.d.ts +92 -0
  46. package/dist/db/seed.d.ts.map +1 -0
  47. package/dist/db/seed.js +160 -0
  48. package/dist/db/seed.js.map +1 -0
  49. package/dist/handlers/fetch.d.ts +89 -0
  50. package/dist/handlers/fetch.d.ts.map +1 -0
  51. package/dist/handlers/fetch.js +173 -0
  52. package/dist/handlers/fetch.js.map +1 -0
  53. package/dist/handlers/nextjs.d.ts +40 -0
  54. package/dist/handlers/nextjs.d.ts.map +1 -0
  55. package/dist/handlers/nextjs.js +42 -0
  56. package/dist/handlers/nextjs.js.map +1 -0
  57. package/dist/handlers/responses.d.ts +46 -0
  58. package/dist/handlers/responses.d.ts.map +1 -0
  59. package/dist/handlers/responses.js +74 -0
  60. package/dist/handlers/responses.js.map +1 -0
  61. package/dist/handlers/routeTable.d.ts +21 -0
  62. package/dist/handlers/routeTable.d.ts.map +1 -0
  63. package/dist/handlers/routeTable.js +133 -0
  64. package/dist/handlers/routeTable.js.map +1 -0
  65. package/dist/handlers/router.d.ts +37 -0
  66. package/dist/handlers/router.d.ts.map +1 -0
  67. package/dist/handlers/router.js +82 -0
  68. package/dist/handlers/router.js.map +1 -0
  69. package/dist/handlers/sse.d.ts +38 -0
  70. package/dist/handlers/sse.d.ts.map +1 -0
  71. package/dist/handlers/sse.js +52 -0
  72. package/dist/handlers/sse.js.map +1 -0
  73. package/dist/handlers/types.d.ts +96 -0
  74. package/dist/handlers/types.d.ts.map +1 -0
  75. package/dist/handlers/types.js +14 -0
  76. package/dist/handlers/types.js.map +1 -0
  77. package/dist/index.d.ts +25 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +24 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/letta/client.d.ts +355 -0
  82. package/dist/letta/client.d.ts.map +1 -0
  83. package/dist/letta/client.js +529 -0
  84. package/dist/letta/client.js.map +1 -0
  85. package/dist/letta/eventTranslator.d.ts +166 -0
  86. package/dist/letta/eventTranslator.d.ts.map +1 -0
  87. package/dist/letta/eventTranslator.js +532 -0
  88. package/dist/letta/eventTranslator.js.map +1 -0
  89. package/dist/letta/index.d.ts +13 -0
  90. package/dist/letta/index.d.ts.map +1 -0
  91. package/dist/letta/index.js +12 -0
  92. package/dist/letta/index.js.map +1 -0
  93. package/dist/letta/modelSettings.d.ts +176 -0
  94. package/dist/letta/modelSettings.d.ts.map +1 -0
  95. package/dist/letta/modelSettings.js +314 -0
  96. package/dist/letta/modelSettings.js.map +1 -0
  97. package/dist/letta/promptWrapping.d.ts +141 -0
  98. package/dist/letta/promptWrapping.d.ts.map +1 -0
  99. package/dist/letta/promptWrapping.js +213 -0
  100. package/dist/letta/promptWrapping.js.map +1 -0
  101. package/dist/letta/sandbox.d.ts +100 -0
  102. package/dist/letta/sandbox.d.ts.map +1 -0
  103. package/dist/letta/sandbox.js +151 -0
  104. package/dist/letta/sandbox.js.map +1 -0
  105. package/dist/letta/settingsFileSeed.d.ts +146 -0
  106. package/dist/letta/settingsFileSeed.d.ts.map +1 -0
  107. package/dist/letta/settingsFileSeed.js +177 -0
  108. package/dist/letta/settingsFileSeed.js.map +1 -0
  109. package/dist/letta/subprocessThrottle.d.ts +151 -0
  110. package/dist/letta/subprocessThrottle.d.ts.map +1 -0
  111. package/dist/letta/subprocessThrottle.js +195 -0
  112. package/dist/letta/subprocessThrottle.js.map +1 -0
  113. package/dist/letta/tpmRecovery.d.ts +202 -0
  114. package/dist/letta/tpmRecovery.d.ts.map +1 -0
  115. package/dist/letta/tpmRecovery.js +314 -0
  116. package/dist/letta/tpmRecovery.js.map +1 -0
  117. package/dist/letta/types.d.ts +54 -0
  118. package/dist/letta/types.d.ts.map +1 -0
  119. package/dist/letta/types.js +16 -0
  120. package/dist/letta/types.js.map +1 -0
  121. package/dist/observability/logger.d.ts +48 -0
  122. package/dist/observability/logger.d.ts.map +1 -0
  123. package/dist/observability/logger.js +81 -0
  124. package/dist/observability/logger.js.map +1 -0
  125. package/dist/observability/metrics.d.ts +53 -0
  126. package/dist/observability/metrics.d.ts.map +1 -0
  127. package/dist/observability/metrics.js +92 -0
  128. package/dist/observability/metrics.js.map +1 -0
  129. package/dist/routes/admin/agents.d.ts +63 -0
  130. package/dist/routes/admin/agents.d.ts.map +1 -0
  131. package/dist/routes/admin/agents.js +461 -0
  132. package/dist/routes/admin/agents.js.map +1 -0
  133. package/dist/routes/admin/rotatingMessages.d.ts +51 -0
  134. package/dist/routes/admin/rotatingMessages.d.ts.map +1 -0
  135. package/dist/routes/admin/rotatingMessages.js +292 -0
  136. package/dist/routes/admin/rotatingMessages.js.map +1 -0
  137. package/dist/routes/admin/sessions.d.ts +61 -0
  138. package/dist/routes/admin/sessions.d.ts.map +1 -0
  139. package/dist/routes/admin/sessions.js +232 -0
  140. package/dist/routes/admin/sessions.js.map +1 -0
  141. package/dist/routes/admin/settings.d.ts +110 -0
  142. package/dist/routes/admin/settings.d.ts.map +1 -0
  143. package/dist/routes/admin/settings.js +401 -0
  144. package/dist/routes/admin/settings.js.map +1 -0
  145. package/dist/routes/admin/users.d.ts +115 -0
  146. package/dist/routes/admin/users.d.ts.map +1 -0
  147. package/dist/routes/admin/users.js +374 -0
  148. package/dist/routes/admin/users.js.map +1 -0
  149. package/dist/routes/agents.d.ts +30 -0
  150. package/dist/routes/agents.d.ts.map +1 -0
  151. package/dist/routes/agents.js +55 -0
  152. package/dist/routes/agents.js.map +1 -0
  153. package/dist/routes/auth.d.ts +121 -0
  154. package/dist/routes/auth.d.ts.map +1 -0
  155. package/dist/routes/auth.js +422 -0
  156. package/dist/routes/auth.js.map +1 -0
  157. package/dist/routes/chat.d.ts +97 -0
  158. package/dist/routes/chat.d.ts.map +1 -0
  159. package/dist/routes/chat.js +484 -0
  160. package/dist/routes/chat.js.map +1 -0
  161. package/dist/routes/featureToggles.d.ts +34 -0
  162. package/dist/routes/featureToggles.d.ts.map +1 -0
  163. package/dist/routes/featureToggles.js +47 -0
  164. package/dist/routes/featureToggles.js.map +1 -0
  165. package/dist/routes/health.d.ts +24 -0
  166. package/dist/routes/health.d.ts.map +1 -0
  167. package/dist/routes/health.js +37 -0
  168. package/dist/routes/health.js.map +1 -0
  169. package/dist/routes/metrics.d.ts +35 -0
  170. package/dist/routes/metrics.d.ts.map +1 -0
  171. package/dist/routes/metrics.js +106 -0
  172. package/dist/routes/metrics.js.map +1 -0
  173. package/dist/routes/sessions.d.ts +161 -0
  174. package/dist/routes/sessions.d.ts.map +1 -0
  175. package/dist/routes/sessions.js +1501 -0
  176. package/dist/routes/sessions.js.map +1 -0
  177. package/dist/routes/stubs.d.ts +25 -0
  178. package/dist/routes/stubs.d.ts.map +1 -0
  179. package/dist/routes/stubs.js +25 -0
  180. package/dist/routes/stubs.js.map +1 -0
  181. package/dist/state/cron.d.ts +58 -0
  182. package/dist/state/cron.d.ts.map +1 -0
  183. package/dist/state/cron.js +160 -0
  184. package/dist/state/cron.js.map +1 -0
  185. package/dist/state/rotationRunner.d.ts +96 -0
  186. package/dist/state/rotationRunner.d.ts.map +1 -0
  187. package/dist/state/rotationRunner.js +246 -0
  188. package/dist/state/rotationRunner.js.map +1 -0
  189. package/dist/state/rotationScheduler.d.ts +76 -0
  190. package/dist/state/rotationScheduler.d.ts.map +1 -0
  191. package/dist/state/rotationScheduler.js +124 -0
  192. package/dist/state/rotationScheduler.js.map +1 -0
  193. package/dist/state/turnRegistry.d.ts +95 -0
  194. package/dist/state/turnRegistry.d.ts.map +1 -0
  195. package/dist/state/turnRegistry.js +149 -0
  196. package/dist/state/turnRegistry.js.map +1 -0
  197. package/dist/state/turnRunner.d.ts +134 -0
  198. package/dist/state/turnRunner.d.ts.map +1 -0
  199. package/dist/state/turnRunner.js +476 -0
  200. package/dist/state/turnRunner.js.map +1 -0
  201. package/package.json +47 -0
  202. package/src/auth/argon2.ts +152 -0
  203. package/src/auth/encryption.ts +110 -0
  204. package/src/auth/jwt.ts +217 -0
  205. package/src/auth/middleware.ts +250 -0
  206. package/src/auth/passwordPolicy.ts +99 -0
  207. package/src/auth/roleRules.ts +497 -0
  208. package/src/auth/userView.ts +88 -0
  209. package/src/bootstrap.ts +254 -0
  210. package/src/db/connection.ts +75 -0
  211. package/src/db/migrate.ts +212 -0
  212. package/src/db/schema.ts +750 -0
  213. package/src/db/seed.ts +236 -0
  214. package/src/handlers/fetch.ts +251 -0
  215. package/src/handlers/nextjs.ts +49 -0
  216. package/src/handlers/responses.ts +95 -0
  217. package/src/handlers/routeTable.ts +188 -0
  218. package/src/handlers/router.ts +96 -0
  219. package/src/handlers/sse.ts +55 -0
  220. package/src/handlers/types.ts +104 -0
  221. package/src/index.ts +60 -0
  222. package/src/letta/client.ts +860 -0
  223. package/src/letta/eventTranslator.ts +667 -0
  224. package/src/letta/index.ts +46 -0
  225. package/src/letta/lettaCliShim.mjs +40 -0
  226. package/src/letta/sandbox.ts +167 -0
  227. package/src/letta/settingsFileSeed.ts +254 -0
  228. package/src/letta/subprocessThrottle.ts +251 -0
  229. package/src/letta/types.ts +65 -0
  230. package/src/observability/logger.ts +103 -0
  231. package/src/observability/metrics.ts +114 -0
  232. package/src/routes/admin/agents.ts +574 -0
  233. package/src/routes/admin/rotatingMessages.ts +351 -0
  234. package/src/routes/admin/sessions.ts +283 -0
  235. package/src/routes/admin/settings.ts +463 -0
  236. package/src/routes/admin/users.ts +455 -0
  237. package/src/routes/agents.ts +66 -0
  238. package/src/routes/auth.ts +513 -0
  239. package/src/routes/chat.ts +534 -0
  240. package/src/routes/featureToggles.ts +52 -0
  241. package/src/routes/health.ts +44 -0
  242. package/src/routes/metrics.ts +111 -0
  243. package/src/routes/sessions.ts +1878 -0
  244. package/src/state/cron.ts +179 -0
  245. package/src/state/rotationRunner.ts +326 -0
  246. package/src/state/rotationScheduler.ts +164 -0
  247. package/src/state/turnRegistry.ts +210 -0
  248. package/src/state/turnRunner.ts +588 -0
@@ -0,0 +1,210 @@
1
+ /**
2
+ * In-memory broadcaster for live turn streams.
3
+ *
4
+ * Every active turn has at most one writer (the runner) and zero-or-more
5
+ * subscribers (the original `POST /chat` connection + every
6
+ * `GET /chat/:turn_id/events?from_seq=N` resumption connection still
7
+ * running while the turn is live).
8
+ *
9
+ * Persistence lives in `turn_events` (§11) — the registry only handles the
10
+ * **live attach** part of resumption. The first half of a resumption read
11
+ * (replay from `from_seq`) is a plain DB query.
12
+ *
13
+ * The registry is process-local — this matches the single-customer
14
+ * deployment model (§1). When ai-hub scales to multiple replicas in a
15
+ * v1.x release, this gets a Redis-backed implementation behind the same
16
+ * interface; the wire protocol (§9) and the resumption contract (§6.3.2)
17
+ * stay unchanged.
18
+ *
19
+ * @see SPECIFICATIONS.md §6.3.2 — resumption endpoint
20
+ * @see SPECIFICATIONS.md §6.6 — server-authoritative state machine
21
+ * @see SPECIFICATIONS.md §11 — `turn_events` table
22
+ */
23
+
24
+ import type { AIHubEvent } from "@data-club/ai-hub";
25
+
26
+ /** Callback signature for a live subscriber. */
27
+ export type TurnEventListener = (event: AIHubEvent) => void;
28
+
29
+ /** Returned by `subscribe()` so the caller can unsubscribe. */
30
+ export type Unsubscribe = () => void;
31
+
32
+ /**
33
+ * Per-turn live channel. The runner calls `publish()` once per event it
34
+ * emits; subscribers receive every event from the point of subscription
35
+ * onward. When the runner calls `close()`, every remaining subscriber's
36
+ * stream gets `null` so it knows to flush + close its SSE writer.
37
+ */
38
+ interface ActiveTurn {
39
+ /** Highest-seen seq on this channel (informational; the runner is the source of truth). */
40
+ lastSeq: number;
41
+ /** Whether the runner has called `close()`. */
42
+ closed: boolean;
43
+ /** Active listeners. */
44
+ listeners: Set<TurnEventListener>;
45
+ /** Listeners notified once when the turn closes. */
46
+ closeListeners: Set<() => void>;
47
+ /**
48
+ * AbortController exposed to the runner — fired by
49
+ * `requestTurnCancellation(turnId)` so a separate `POST /chat/:id/cancel`
50
+ * request can short-circuit the in-process runner without having to
51
+ * abort the runner's originating request signal (which lives on a
52
+ * different `Request` instance). The runner translates this into a
53
+ * `handle.abort()` call on the spawned Letta Code subprocess (which
54
+ * sends an `interrupt` control to the CLI).
55
+ *
56
+ * Pre-migration this also drove an `agents.messages.cancel({run_ids})`
57
+ * call on the Letta server side via the captured `lettaRunId`. Post-
58
+ * migration the run-id tracking is gone — the SDK abstracts it — and
59
+ * cancel is `handle.abort()` only. See migration plan §4.2.
60
+ */
61
+ cancelController: AbortController;
62
+ }
63
+
64
+ /**
65
+ * Process-local map of live turn channels. The map prunes a channel on
66
+ * close as soon as every subscriber has unsubscribed (or immediately if
67
+ * no subscribers are attached).
68
+ */
69
+ const channels = new Map<string, ActiveTurn>();
70
+
71
+ /**
72
+ * Begins a new live turn channel.
73
+ *
74
+ * The runner calls this when it inserts the `turn` row, before it starts
75
+ * pumping events. Returns an opaque `TurnPublisher` the runner uses to
76
+ * publish + close.
77
+ *
78
+ * @param turnId - the freshly-created turn id.
79
+ * @returns the publisher handle.
80
+ */
81
+ export function openTurnChannel(turnId: string): TurnPublisher {
82
+ if (channels.has(turnId)) {
83
+ throw new Error(`Turn ${turnId} already has an open channel.`);
84
+ }
85
+ const channel: ActiveTurn = {
86
+ lastSeq: -1,
87
+ closed: false,
88
+ listeners: new Set(),
89
+ closeListeners: new Set(),
90
+ cancelController: new AbortController(),
91
+ };
92
+ channels.set(turnId, channel);
93
+ return {
94
+ cancelSignal: channel.cancelController.signal,
95
+ publish(event: AIHubEvent) {
96
+ channel.lastSeq = event.seq;
97
+ for (const listener of channel.listeners) {
98
+ try {
99
+ listener(event);
100
+ } catch {
101
+ /* swallow — a misbehaving listener cannot break the channel */
102
+ }
103
+ }
104
+ },
105
+ close() {
106
+ if (channel.closed) return;
107
+ channel.closed = true;
108
+ for (const cb of channel.closeListeners) {
109
+ try {
110
+ cb();
111
+ } catch {
112
+ /* ignored */
113
+ }
114
+ }
115
+ channel.closeListeners.clear();
116
+ // Drop the channel once every subscriber unsubscribed. If nobody is
117
+ // listening at close time, prune immediately.
118
+ if (channel.listeners.size === 0) {
119
+ channels.delete(turnId);
120
+ }
121
+ },
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Subscribes to a live turn channel.
127
+ *
128
+ * Returns `null` when the turn is not active (either never opened or
129
+ * already closed) — the caller should fall back to replaying persisted
130
+ * events from `turn_events` instead.
131
+ *
132
+ * @param turnId - the turn id to attach to.
133
+ * @param listener - called once per event (with `seq` already assigned).
134
+ * @param onClose - called once when the channel closes (after final event).
135
+ * @returns an unsubscribe function, or `null` when the channel is closed.
136
+ */
137
+ export function subscribeToTurn(
138
+ turnId: string,
139
+ listener: TurnEventListener,
140
+ onClose: () => void,
141
+ ): Unsubscribe | null {
142
+ const channel = channels.get(turnId);
143
+ if (!channel || channel.closed) return null;
144
+ channel.listeners.add(listener);
145
+ channel.closeListeners.add(onClose);
146
+ return () => {
147
+ channel.listeners.delete(listener);
148
+ channel.closeListeners.delete(onClose);
149
+ if (channel.closed && channel.listeners.size === 0) {
150
+ channels.delete(turnId);
151
+ }
152
+ };
153
+ }
154
+
155
+ /**
156
+ * Returns `true` when the turn has an open channel right now.
157
+ *
158
+ * The chat handler uses this to disambiguate "turn is in flight" from
159
+ * "turn completed long ago" without having to query the DB twice.
160
+ */
161
+ export function isTurnLive(turnId: string): boolean {
162
+ const channel = channels.get(turnId);
163
+ return !!channel && !channel.closed;
164
+ }
165
+
166
+ /**
167
+ * Test-only utility — wipes the registry so tests can isolate from each
168
+ * other. Production code never calls this.
169
+ */
170
+ export function _resetTurnRegistryForTests(): void {
171
+ channels.clear();
172
+ }
173
+
174
+ /**
175
+ * The runner's handle on a live channel. Opaque on purpose — the runner
176
+ * is the only writer.
177
+ */
178
+ export interface TurnPublisher {
179
+ /**
180
+ * AbortSignal that fires when a separate `POST /chat/:id/cancel`
181
+ * request calls `requestTurnCancellation(turnId)`. The runner listens
182
+ * to this in addition to the originating request's signal.
183
+ */
184
+ cancelSignal: AbortSignal;
185
+ /** Push one event to every current subscriber. */
186
+ publish(event: AIHubEvent): void;
187
+ /** Mark the channel closed. After this, `subscribeToTurn` returns null. */
188
+ close(): void;
189
+ }
190
+
191
+ /**
192
+ * Triggers cancellation of the named turn. The runner is expected to
193
+ * have wired its run to the publisher's `cancelSignal`; firing it from
194
+ * here aborts the upstream Letta call and short-circuits the loop.
195
+ *
196
+ * Idempotent: calling on a closed / unknown turn is a no-op. The
197
+ * `POST /chat/:id/cancel` route's user-facing 200 response covers
198
+ * race-conditions where the turn terminated between the request and
199
+ * this call.
200
+ *
201
+ * @param turnId - the turn to cancel.
202
+ * @returns `true` if the signal was fired, `false` if the channel is
203
+ * closed or unknown.
204
+ */
205
+ export function requestTurnCancellation(turnId: string): boolean {
206
+ const channel = channels.get(turnId);
207
+ if (!channel || channel.closed) return false;
208
+ channel.cancelController.abort();
209
+ return true;
210
+ }