@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,476 @@
1
+ /**
2
+ * Server-authoritative turn lifecycle (§6.6, §10).
3
+ *
4
+ * `runTurn(...)` is the one entry point that:
5
+ *
6
+ * 1. Inserts the `turn` row in status=running, phase=model_text.
7
+ * 2. Opens a live channel (`turnRegistry.openTurnChannel`) so concurrent
8
+ * resumption attempts can attach.
9
+ * 3. Emits `stream_start` (seq 0).
10
+ * 4. Calls `LettaClient.streamUserMessage(...)` which spawns a Letta
11
+ * Code subprocess, acquires the throttle lease, sends the user
12
+ * message. Returns a `ChatTurnHandle`.
13
+ * 5. Iterates the handle's `events` stream:
14
+ * - Non-terminal SDK messages → `translateSdkMessage(...)` →
15
+ * stamps + persists + broadcasts each emitted ai-hub event.
16
+ * - Terminal `result` SDK message → `finalizeTerminal(...)` →
17
+ * emits the closing `assistant_message_complete` + `stream_end`
18
+ * with the correct reason (`done` / `cancelled` / `error`).
19
+ * 6. On cancellation (caller signal OR `requestTurnCancellation`):
20
+ * calls `handle.abort()` to send `interrupt` to the CLI, keeps
21
+ * draining until terminal, then closes.
22
+ * 7. On throttle rejection (`ServerOverloadedError`): emits
23
+ * `error{code:"server_overloaded"}` + `stream_end{error}`.
24
+ * Transitions turn → failed.
25
+ * 8. On unhandled error: emits `error` + `stream_end{error}`,
26
+ * `turn.status = "failed"`.
27
+ * 9. Always calls `handle.close()` in finally (releases subprocess +
28
+ * throttle lease).
29
+ *
30
+ * @see SPECIFICATIONS.md §6.3.2 — chat / SSE
31
+ * @see SPECIFICATIONS.md §6.6 — state-machine ownership
32
+ * @see SPECIFICATIONS.md §6.9 — cancellation
33
+ * @see SPECIFICATIONS.md §9 — wire protocol
34
+ * @see SPECIFICATIONS.md §10 — state machine
35
+ */
36
+ import { randomUUID } from "node:crypto";
37
+ import { eq, sql } from "drizzle-orm";
38
+ import { messageUsage, turn, turnEvent } from "../db/schema.js";
39
+ import { ServerOverloadedError } from "../letta/client.js";
40
+ import { finalizeAssistantMessage, finalizeTerminal, initialTranslatorState, translateSdkMessage, } from "../letta/eventTranslator.js";
41
+ import * as metrics from "../observability/metrics.js";
42
+ /** The ai-hub SSE wire-protocol version this server speaks (§9.1). */
43
+ export const WIRE_PROTOCOL_VERSION = "1.0";
44
+ /* ────────────────────────────────────────────────────────────────────────── */
45
+ /* Runner */
46
+ /* ────────────────────────────────────────────────────────────────────────── */
47
+ /**
48
+ * Runs one turn from "user pressed Send" to terminal status. Returns a
49
+ * promise that resolves when the runner has persisted the terminal
50
+ * event(s), closed the live channel, and torn down the Letta Code
51
+ * subprocess.
52
+ *
53
+ * The caller is expected to keep `onEvent` alive for the entire run.
54
+ *
55
+ * @param opts - see `RunTurnOpts`.
56
+ * @returns the turn id and terminal status.
57
+ */
58
+ export async function runTurn(opts) {
59
+ const turnId = randomUUID();
60
+ const startedAt = new Date().toISOString();
61
+ const startedMs = Date.now();
62
+ metrics.chatRequestsTotal.inc();
63
+ // Step 1 — insert turn row in running/model_text.
64
+ opts.db
65
+ .insert(turn)
66
+ .values({
67
+ id: turnId,
68
+ sessionId: opts.sessionId,
69
+ status: "running",
70
+ phase: "model_text",
71
+ lastSeq: 0,
72
+ idempotencyKey: opts.idempotencyKey ?? null,
73
+ startedAt,
74
+ })
75
+ .run();
76
+ const { openTurnChannel } = await import("./turnRegistry.js");
77
+ const publisher = openTurnChannel(turnId);
78
+ // Compose the caller's signal with the registry-supplied cancel
79
+ // signal: either side can fire to cancel the turn. The registry
80
+ // cancel is what `POST /chat/:id/cancel` triggers from a separate
81
+ // HTTP request.
82
+ const registryCancelSignal = publisher.cancelSignal;
83
+ const cancelController = new AbortController();
84
+ const propagateCancel = () => cancelController.abort();
85
+ if (opts.signal) {
86
+ if (opts.signal.aborted)
87
+ cancelController.abort();
88
+ else
89
+ opts.signal.addEventListener("abort", propagateCancel, { once: true });
90
+ }
91
+ if (registryCancelSignal.aborted)
92
+ cancelController.abort();
93
+ else
94
+ registryCancelSignal.addEventListener("abort", propagateCancel, { once: true });
95
+ let translatorState = initialTranslatorState();
96
+ let nextSeq = 0;
97
+ /** Stamps + persists + broadcasts one event. Also fills in
98
+ * `request_id` on error events — the translator emits them without
99
+ * a request_id (it has no access to the request), so we add it here. */
100
+ const emit = (unsequenced) => {
101
+ let withRequestId = unsequenced;
102
+ if (unsequenced.event === "error") {
103
+ withRequestId = {
104
+ ...unsequenced,
105
+ data: { ...unsequenced.data, request_id: opts.requestId },
106
+ };
107
+ }
108
+ const event = { ...withRequestId, seq: nextSeq++ };
109
+ const persistedData = "data" in event ? event.data : {};
110
+ opts.db
111
+ .insert(turnEvent)
112
+ .values({
113
+ turnId,
114
+ seq: event.seq,
115
+ eventName: event.event,
116
+ data: persistedData,
117
+ state: event.state,
118
+ })
119
+ .run();
120
+ publisher.publish(event);
121
+ opts.onEvent(event);
122
+ return event;
123
+ };
124
+ /** Persists turn-row mutations driven by translator-state changes. */
125
+ const syncTurnRow = (status, phase) => {
126
+ const sets = { lastSeq: nextSeq - 1 };
127
+ if (status !== "running") {
128
+ sets.status = status;
129
+ sets.phase = null;
130
+ sets.finishedAt = new Date().toISOString();
131
+ }
132
+ else {
133
+ sets.status = "running";
134
+ sets.phase = phase;
135
+ }
136
+ opts.db.update(turn).set(sets).where(eq(turn.id, turnId)).run();
137
+ };
138
+ let handle = null;
139
+ try {
140
+ // Step 3 — stream_start (emitted once, at the top of the run).
141
+ emit({
142
+ event: "stream_start",
143
+ data: {
144
+ protocol_version: WIRE_PROTOCOL_VERSION,
145
+ session_id: opts.sessionId,
146
+ turn_id: turnId,
147
+ },
148
+ state: { status: "running", phase: "model_text" },
149
+ });
150
+ syncTurnRow("running", "model_text");
151
+ if (cancelController.signal.aborted) {
152
+ // Caller cancelled before we even spawned — emit cancelled and
153
+ // bail without ever calling streamUserMessage.
154
+ throw new AbortLikeError();
155
+ }
156
+ // Step 4 — spawn + send. Throttle gate runs inside
157
+ // streamUserMessage; ServerOverloadedError is caught below and
158
+ // turned into a `server_overloaded` SSE error event.
159
+ const lettaStartedMs = Date.now();
160
+ try {
161
+ handle = await opts.lettaClient.streamUserMessage({
162
+ conversationId: opts.lettaConversationId,
163
+ lettaAgentId: opts.lettaAgentId,
164
+ userMessage: opts.userMessage,
165
+ ...(opts.sandboxDir !== null ? { cwd: opts.sandboxDir } : {}),
166
+ });
167
+ }
168
+ catch (err) {
169
+ metrics.lettaRequestDurationMs.set(Date.now() - lettaStartedMs);
170
+ throw err;
171
+ }
172
+ // Wire the cancel signal to the handle's abort once we have one.
173
+ // If the signal already fired during the await above, abort + bail
174
+ // immediately. Otherwise install a listener for future aborts.
175
+ if (cancelController.signal.aborted) {
176
+ void handle.abort();
177
+ throw new AbortLikeError();
178
+ }
179
+ const onCancel = () => {
180
+ void handle?.abort();
181
+ };
182
+ cancelController.signal.addEventListener("abort", onCancel, { once: true });
183
+ // Step 5 — drain the SDK message stream.
184
+ // Track the last Letta run id we see — used to fetch usage stats
185
+ // after the terminal `result`. The SDK strips Letta message ids
186
+ // from its translated payloads, so we re-fetch via REST
187
+ // (`getRunUsageStats(runId)`) to get both the usage_statistics
188
+ // and the last assistant message id we'll stamp the badge on.
189
+ let lastRunId = null;
190
+ try {
191
+ for await (const sdkMsg of handle.events) {
192
+ // SDKAssistantMessage / SDKReasoningMessage / SDKToolCallMessage
193
+ // each carry `runId`. Take the most recent — a multi-step turn
194
+ // can have several runs, and we want the latest.
195
+ if (sdkMsg.runId) {
196
+ lastRunId = sdkMsg.runId;
197
+ }
198
+ if (sdkMsg.type === "result") {
199
+ // Terminal — finalizeTerminal emits the right closing events
200
+ // based on success / interrupted / error.
201
+ // Override the reason to `cancelled` when our cancel fired
202
+ // (even if the SDK reports success — see the cancel fixture
203
+ // open-question-5 finding: the SDK may complete the run if
204
+ // the interrupt arrived during a tool call).
205
+ const cancelOverride = cancelController.signal.aborted;
206
+ const terminalToUse = cancelOverride
207
+ ? { ...sdkMsg, success: false, errorCode: "interrupted" }
208
+ : sdkMsg;
209
+ const step = finalizeTerminal(terminalToUse, translatorState);
210
+ translatorState = step.state;
211
+ for (const ev of step.events) {
212
+ emit(ev);
213
+ }
214
+ syncTurnRow(translatorState.status, null);
215
+ break;
216
+ }
217
+ const step = translateSdkMessage(sdkMsg, translatorState);
218
+ translatorState = step.state;
219
+ for (const ev of step.events) {
220
+ emit(ev);
221
+ }
222
+ syncTurnRow(translatorState.status, translatorState.phase);
223
+ }
224
+ }
225
+ finally {
226
+ cancelController.signal.removeEventListener("abort", onCancel);
227
+ metrics.lettaRequestDurationMs.set(Date.now() - lettaStartedMs);
228
+ }
229
+ // Step 5.5 — usage emission + persistence. Only fire on successful
230
+ // termination (cancelled / failed turns may or may not have a
231
+ // usable runId, and the badge isn't load-bearing). Best-effort:
232
+ // any failure here logs and continues — we already emitted
233
+ // stream_end above, so the turn is "done" from the client's POV.
234
+ if (lastRunId !== null &&
235
+ translatorState.status === "done") {
236
+ try {
237
+ const usage = await opts.lettaClient.getRunUsageStats(lastRunId);
238
+ if (usage && usage.lastAssistantMessageId) {
239
+ // Persist for /sessions/{id}/messages history rendering.
240
+ opts.db
241
+ .insert(messageUsage)
242
+ .values({
243
+ lettaMessageId: usage.lastAssistantMessageId,
244
+ sessionId: opts.sessionId,
245
+ promptTokens: usage.promptTokens,
246
+ completionTokens: usage.completionTokens,
247
+ totalTokens: usage.totalTokens,
248
+ cachedInputTokens: usage.cachedInputTokens,
249
+ cacheWriteTokens: usage.cacheWriteTokens,
250
+ reasoningTokens: usage.reasoningTokens,
251
+ contextTokens: usage.contextTokens,
252
+ runId: lastRunId,
253
+ })
254
+ .onConflictDoUpdate({
255
+ target: messageUsage.lettaMessageId,
256
+ set: {
257
+ promptTokens: usage.promptTokens,
258
+ completionTokens: usage.completionTokens,
259
+ totalTokens: usage.totalTokens,
260
+ cachedInputTokens: usage.cachedInputTokens,
261
+ cacheWriteTokens: usage.cacheWriteTokens,
262
+ reasoningTokens: usage.reasoningTokens,
263
+ contextTokens: usage.contextTokens,
264
+ runId: lastRunId,
265
+ },
266
+ })
267
+ .run();
268
+ // Live wire event — UI can attach the badge immediately
269
+ // without waiting for a /messages refetch.
270
+ opts.onEvent({
271
+ seq: 0, // emit() bypassed here; the stream's already drained.
272
+ event: "usage",
273
+ data: {
274
+ letta_message_id: usage.lastAssistantMessageId,
275
+ ...(usage.promptTokens !== null ? { input: usage.promptTokens } : {}),
276
+ ...(usage.completionTokens !== null ? { output: usage.completionTokens } : {}),
277
+ ...(usage.cachedInputTokens !== null ? { cache_read: usage.cachedInputTokens } : {}),
278
+ ...(usage.cacheWriteTokens !== null ? { cache_write: usage.cacheWriteTokens } : {}),
279
+ ...(usage.reasoningTokens !== null ? { reasoning: usage.reasoningTokens } : {}),
280
+ ...(usage.contextTokens !== null ? { context: usage.contextTokens } : {}),
281
+ ...(usage.totalTokens !== null ? { total: usage.totalTokens } : {}),
282
+ },
283
+ state: { status: "done", phase: null },
284
+ });
285
+ }
286
+ }
287
+ catch (err) {
288
+ opts.logger.warn({ err, runId: lastRunId }, "usage-stats fetch/persist failed");
289
+ }
290
+ }
291
+ publisher.close();
292
+ opts.onEvent(null);
293
+ metrics.chatDurationMs.set(Date.now() - startedMs);
294
+ const finalStatus = translatorState.status;
295
+ opts.logger.info({
296
+ event: `turn_${finalStatus}`,
297
+ turn_id: turnId,
298
+ session_id: opts.sessionId,
299
+ }, `Turn ${finalStatus}.`);
300
+ return { turnId, status: finalStatus };
301
+ }
302
+ catch (err) {
303
+ if (err instanceof ServerOverloadedError) {
304
+ emit({
305
+ event: "error",
306
+ data: {
307
+ code: "server_overloaded",
308
+ message: err.message,
309
+ },
310
+ state: { status: "failed", phase: null },
311
+ });
312
+ emit({
313
+ event: "stream_end",
314
+ data: { reason: "error" },
315
+ state: { status: "failed", phase: null },
316
+ });
317
+ syncTurnRow("failed", null);
318
+ publisher.close();
319
+ opts.onEvent(null);
320
+ metrics.chatDurationMs.set(Date.now() - startedMs);
321
+ opts.logger.warn({
322
+ event: "turn_rejected_overloaded",
323
+ turn_id: turnId,
324
+ session_id: opts.sessionId,
325
+ gate: err.gate,
326
+ detail: err.detail,
327
+ }, "Turn rejected: server overloaded.");
328
+ return { turnId, status: "failed" };
329
+ }
330
+ if (cancelController.signal.aborted || err instanceof AbortLikeError) {
331
+ // Emit any partial assistant text the turn produced before the
332
+ // cancel landed, then the cancelled stream_end.
333
+ for (const ev of finalizeAssistantMessage(translatorState, "cancelled")) {
334
+ emit(ev);
335
+ }
336
+ emit({
337
+ event: "stream_end",
338
+ data: { reason: "cancelled" },
339
+ state: { status: "cancelled", phase: null },
340
+ });
341
+ syncTurnRow("cancelled", null);
342
+ publisher.close();
343
+ opts.onEvent(null);
344
+ metrics.chatDurationMs.set(Date.now() - startedMs);
345
+ opts.logger.info({ event: "turn_cancelled", turn_id: turnId, session_id: opts.sessionId }, "Turn cancelled.");
346
+ return { turnId, status: "cancelled" };
347
+ }
348
+ const message = err instanceof Error ? err.message : String(err);
349
+ emit({
350
+ event: "error",
351
+ data: { code: classifyServerError(err), message },
352
+ state: { status: "failed", phase: null },
353
+ });
354
+ emit({
355
+ event: "stream_end",
356
+ data: { reason: "error" },
357
+ state: { status: "failed", phase: null },
358
+ });
359
+ syncTurnRow("failed", null);
360
+ publisher.close();
361
+ opts.onEvent(null);
362
+ metrics.chatDurationMs.set(Date.now() - startedMs);
363
+ opts.logger.error({
364
+ event: "turn_failed",
365
+ turn_id: turnId,
366
+ session_id: opts.sessionId,
367
+ err: message,
368
+ }, "Turn failed.");
369
+ return { turnId, status: "failed" };
370
+ }
371
+ finally {
372
+ if (handle) {
373
+ try {
374
+ handle.close();
375
+ }
376
+ catch {
377
+ // best-effort
378
+ }
379
+ }
380
+ if (opts.signal)
381
+ opts.signal.removeEventListener("abort", propagateCancel);
382
+ registryCancelSignal.removeEventListener("abort", propagateCancel);
383
+ }
384
+ }
385
+ /* ────────────────────────────────────────────────────────────────────────── */
386
+ /* Helpers */
387
+ /* ────────────────────────────────────────────────────────────────────────── */
388
+ /** Sentinel for "the cancel path fired" — the catch arm checks
389
+ * `err instanceof AbortLikeError` plus the cancel signal. */
390
+ class AbortLikeError extends Error {
391
+ constructor() {
392
+ super("Turn aborted.");
393
+ this.name = "AbortLikeError";
394
+ }
395
+ }
396
+ /**
397
+ * Maps an unhandled runner error onto an ai-hub `error.code`.
398
+ *
399
+ * Post-migration the set of error sources is much smaller — most of
400
+ * the provider/upstream signals come through the translator (which
401
+ * maps them via `classifyErrorCode`). What lands here is
402
+ * spawn-failure, network-down-to-Letta, decryption errors, and other
403
+ * "couldn't even start the turn" failures.
404
+ *
405
+ * @param err - the unhandled error.
406
+ * @returns the SSE `error.code` to emit.
407
+ */
408
+ function classifyServerError(err) {
409
+ if (err instanceof Error) {
410
+ const msg = err.message.toLowerCase();
411
+ if (msg.includes("letta") || msg.includes("upstream"))
412
+ return "provider_error";
413
+ }
414
+ return "internal";
415
+ }
416
+ /* ────────────────────────────────────────────────────────────────────────── */
417
+ /* Resumption helpers */
418
+ /* ────────────────────────────────────────────────────────────────────────── */
419
+ /**
420
+ * Replays persisted `turn_event` rows newer than `fromSeq`, returned as
421
+ * ai-hub-shaped events. Used by `GET /chat/:turn_id/events?from_seq=N`
422
+ * for the replay half of resumption.
423
+ *
424
+ * @param db - Drizzle handle.
425
+ * @param turnId - the turn id.
426
+ * @param fromSeq - replays events with `seq > fromSeq`.
427
+ * @returns the persisted events.
428
+ *
429
+ * @see SPECIFICATIONS.md §6.3.2 — resumption
430
+ */
431
+ export function replayPersistedEvents(db, turnId, fromSeq) {
432
+ const rows = db
433
+ .select()
434
+ .from(turnEvent)
435
+ .where(sql `${turnEvent.turnId} = ${turnId} AND ${turnEvent.seq} > ${fromSeq}`)
436
+ .orderBy(turnEvent.seq)
437
+ .all();
438
+ return rows.map((row) => ({
439
+ event: row.eventName,
440
+ data: row.data,
441
+ state: row.state,
442
+ seq: row.seq,
443
+ }));
444
+ }
445
+ /**
446
+ * Idempotently marks a turn as cancelled in the DB. Returns the row's
447
+ * resulting status. Called by `POST /chat/:turn_id/cancel` after firing
448
+ * `requestTurnCancellation`. The runner's catch arm also persists
449
+ * `cancelled` via `syncTurnRow`; this helper just guarantees the row
450
+ * is updated when the runner has already exited (terminal-after-cancel
451
+ * race).
452
+ *
453
+ * Does not overwrite `done` / `failed` — those are terminal states.
454
+ *
455
+ * @param db - Drizzle handle.
456
+ * @param turnId - the turn to cancel.
457
+ * @returns the row's resulting status, or `null` if no such row.
458
+ */
459
+ export function markCancelled(db, turnId) {
460
+ const row = db.select().from(turn).where(eq(turn.id, turnId)).get();
461
+ if (!row)
462
+ return null;
463
+ if (row.status === "running") {
464
+ db.update(turn)
465
+ .set({
466
+ status: "cancelled",
467
+ phase: null,
468
+ finishedAt: new Date().toISOString(),
469
+ })
470
+ .where(eq(turn.id, turnId))
471
+ .run();
472
+ return "cancelled";
473
+ }
474
+ return row.status;
475
+ }
476
+ //# sourceMappingURL=turnRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turnRunner.js","sourceRoot":"","sources":["../../src/state/turnRunner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAStC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAyC,MAAM,oBAAoB,CAAC;AAClG,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,GAGpB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AAEvD,sEAAsE;AACtE,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AA4D3C,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAiB;IAC7C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC;IAEhC,kDAAkD;IAClD,IAAI,CAAC,EAAE;SACJ,MAAM,CAAC,IAAI,CAAC;SACZ,MAAM,CAAC;QACN,EAAE,EAAE,MAAM;QACV,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,CAAC;QACV,cAAc,EAAE,IAAI,CAAC,cAAc,IAAI,IAAI;QAC3C,SAAS;KACV,CAAC;SACD,GAAG,EAAE,CAAC;IAET,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAE1C,gEAAgE;IAChE,gEAAgE;IAChE,kEAAkE;IAClE,gBAAgB;IAChB,MAAM,oBAAoB,GAAG,SAAS,CAAC,YAAY,CAAC;IACpD,MAAM,gBAAgB,GAAG,IAAI,eAAe,EAAE,CAAC;IAC/C,MAAM,eAAe,GAAG,GAAS,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;IAC7D,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC;;YAC7C,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,oBAAoB,CAAC,OAAO;QAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC;;QACtD,oBAAoB,CAAC,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAErF,IAAI,eAAe,GAAoB,sBAAsB,EAAE,CAAC;IAChE,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB;;6EAEyE;IACzE,MAAM,IAAI,GAAG,CAAC,WAA6B,EAAc,EAAE;QACzD,IAAI,aAAa,GAAqB,WAAW,CAAC;QAClD,IAAI,WAAW,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YAClC,aAAa,GAAG;gBACd,GAAG,WAAW;gBACd,IAAI,EAAE,EAAE,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE;aACtC,CAAC;QACxB,CAAC;QACD,MAAM,KAAK,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,EAAE,OAAO,EAAE,EAAgB,CAAC;QACjE,MAAM,aAAa,GACjB,MAAM,IAAI,KAAK,CAAC,CAAC,CAAE,KAAK,CAAC,IAA0B,CAAC,CAAC,CAAE,EAAa,CAAC;QACvE,IAAI,CAAC,EAAE;aACJ,MAAM,CAAC,SAAS,CAAC;aACjB,MAAM,CAAC;YACN,MAAM;YACN,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,KAAK;YACtB,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,KAAK,CAAC,KAA0B;SACxC,CAAC;aACD,GAAG,EAAE,CAAC;QACT,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,sEAAsE;IACtE,MAAM,WAAW,GAAG,CAAC,MAAkB,EAAE,KAA0B,EAAQ,EAAE;QAC3E,MAAM,IAAI,GAA4B,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,CAAC;QAC/D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IAClE,CAAC,CAAC;IAEF,IAAI,MAAM,GAA0B,IAAI,CAAC;IAEzC,IAAI,CAAC;QACH,+DAA+D;QAC/D,IAAI,CAAC;YACH,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE;gBACJ,gBAAgB,EAAE,qBAAqB;gBACvC,UAAU,EAAE,IAAI,CAAC,SAAS;gBAC1B,OAAO,EAAE,MAAM;aAChB;YACD,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAA4B;SAC5E,CAAC,CAAC;QACH,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAErC,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,+DAA+D;YAC/D,+CAA+C;YAC/C,MAAM,IAAI,cAAc,EAAE,CAAC;QAC7B,CAAC;QAED,mDAAmD;QACnD,+DAA+D;QAC/D,qDAAqD;QACrD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC;gBAChD,cAAc,EAAE,IAAI,CAAC,mBAAmB;gBACxC,YAAY,EAAE,IAAI,CAAC,YAAY;gBAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC,CAAC;YAChE,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,iEAAiE;QACjE,mEAAmE;QACnE,+DAA+D;QAC/D,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,IAAI,cAAc,EAAE,CAAC;QAC7B,CAAC;QACD,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,KAAK,MAAM,EAAE,KAAK,EAAE,CAAC;QACvB,CAAC,CAAC;QACF,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5E,yCAAyC;QACzC,iEAAiE;QACjE,gEAAgE;QAChE,wDAAwD;QACxD,+DAA+D;QAC/D,8DAA8D;QAC9D,IAAI,SAAS,GAAkB,IAAI,CAAC;QACpC,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBACzC,iEAAiE;gBACjE,+DAA+D;gBAC/D,iDAAiD;gBACjD,IAAK,MAA6B,CAAC,KAAK,EAAE,CAAC;oBACzC,SAAS,GAAI,MAA4B,CAAC,KAAK,CAAC;gBAClD,CAAC;gBACD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC7B,6DAA6D;oBAC7D,0CAA0C;oBAC1C,2DAA2D;oBAC3D,4DAA4D;oBAC5D,2DAA2D;oBAC3D,6CAA6C;oBAC7C,MAAM,cAAc,GAAG,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC;oBACvD,MAAM,aAAa,GAAG,cAAc;wBAClC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,aAAsB,EAAE;wBAClE,CAAC,CAAC,MAAM,CAAC;oBACX,MAAM,IAAI,GAAG,gBAAgB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;oBAC9D,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC;oBAC7B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBAC7B,IAAI,CAAC,EAAE,CAAC,CAAC;oBACX,CAAC;oBACD,WAAW,CAAC,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;oBAC1C,MAAM;gBACR,CAAC;gBAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;gBAC1D,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC;gBAC7B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC7B,IAAI,CAAC,EAAE,CAAC,CAAC;gBACX,CAAC;gBACD,WAAW,CAAC,eAAe,CAAC,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,gBAAgB,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC/D,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC,CAAC;QAClE,CAAC;QAED,mEAAmE;QACnE,8DAA8D;QAC9D,gEAAgE;QAChE,2DAA2D;QAC3D,iEAAiE;QACjE,IACE,SAAS,KAAK,IAAI;YAClB,eAAe,CAAC,MAAM,KAAK,MAAM,EACjC,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBACjE,IAAI,KAAK,IAAI,KAAK,CAAC,sBAAsB,EAAE,CAAC;oBAC1C,yDAAyD;oBACzD,IAAI,CAAC,EAAE;yBACJ,MAAM,CAAC,YAAY,CAAC;yBACpB,MAAM,CAAC;wBACN,cAAc,EAAE,KAAK,CAAC,sBAAsB;wBAC5C,SAAS,EAAE,IAAI,CAAC,SAAS;wBACzB,YAAY,EAAE,KAAK,CAAC,YAAY;wBAChC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;wBACxC,WAAW,EAAE,KAAK,CAAC,WAAW;wBAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;wBAC1C,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;wBACxC,eAAe,EAAE,KAAK,CAAC,eAAe;wBACtC,aAAa,EAAE,KAAK,CAAC,aAAa;wBAClC,KAAK,EAAE,SAAS;qBACjB,CAAC;yBACD,kBAAkB,CAAC;wBAClB,MAAM,EAAE,YAAY,CAAC,cAAc;wBACnC,GAAG,EAAE;4BACH,YAAY,EAAE,KAAK,CAAC,YAAY;4BAChC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;4BACxC,WAAW,EAAE,KAAK,CAAC,WAAW;4BAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;4BAC1C,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;4BACxC,eAAe,EAAE,KAAK,CAAC,eAAe;4BACtC,aAAa,EAAE,KAAK,CAAC,aAAa;4BAClC,KAAK,EAAE,SAAS;yBACjB;qBACF,CAAC;yBACD,GAAG,EAAE,CAAC;oBACT,wDAAwD;oBACxD,2CAA2C;oBAC3C,IAAI,CAAC,OAAO,CAAC;wBACX,GAAG,EAAE,CAAC,EAAE,sDAAsD;wBAC9D,KAAK,EAAE,OAAO;wBACd,IAAI,EAAE;4BACJ,gBAAgB,EAAE,KAAK,CAAC,sBAAsB;4BAC9C,GAAG,CAAC,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BACrE,GAAG,CAAC,KAAK,CAAC,gBAAgB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BAC9E,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BACpF,GAAG,CAAC,KAAK,CAAC,gBAAgB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BACnF,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BAC/E,GAAG,CAAC,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BACzE,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;yBACpE;wBACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAA4B;qBACjE,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,kCAAkC,CAAC,CAAC;YAClF,CAAC;QACH,CAAC;QAED,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;QAEnD,MAAM,WAAW,GAAG,eAAe,CAAC,MAAiC,CAAC;QACtE,IAAI,CAAC,MAAM,CAAC,IAAI,CACd;YACE,KAAK,EAAE,QAAQ,WAAW,EAAE;YAC5B,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,IAAI,CAAC,SAAS;SAC3B,EACD,QAAQ,WAAW,GAAG,CACvB,CAAC;QACF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,qBAAqB,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE;oBACJ,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,GAAG,CAAC,OAAO;iBACrB;gBACD,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;aACzC,CAAC,CAAC;YACH,IAAI,CAAC;gBACH,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;gBACzB,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;aACzC,CAAC,CAAC;YACH,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC5B,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,CAAC,IAAI,CACd;gBACE,KAAK,EAAE,0BAA0B;gBACjC,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,IAAI,CAAC,SAAS;gBAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,MAAM;aACnB,EACD,mCAAmC,CACpC,CAAC;YACF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACtC,CAAC;QAED,IAAI,gBAAgB,CAAC,MAAM,CAAC,OAAO,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YACrE,+DAA+D;YAC/D,gDAAgD;YAChD,KAAK,MAAM,EAAE,IAAI,wBAAwB,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,CAAC;gBACxE,IAAI,CAAC,EAAE,CAAC,CAAC;YACX,CAAC;YACD,IAAI,CAAC;gBACH,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE;gBAC7B,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE;aAC5C,CAAC,CAAC;YACH,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAC/B,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,EACxE,iBAAiB,CAClB,CAAC;YACF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QACzC,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,IAAI,CAAC;YACH,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,EAAE,IAAI,EAAE,mBAAmB,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE;YACjD,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;SACzC,CAAC,CAAC;QACH,IAAI,CAAC;YACH,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;YACzB,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;SACzC,CAAC,CAAC;QACH,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5B,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,KAAK,CACf;YACE,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,IAAI,CAAC,SAAS;YAC1B,GAAG,EAAE,OAAO;SACb,EACD,cAAc,CACf,CAAC;QACF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACtC,CAAC;YAAS,CAAC;QACT,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,cAAc;YAChB,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAC3E,oBAAoB,CAAC,mBAAmB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF;8DAC8D;AAC9D,MAAM,cAAe,SAAQ,KAAK;IAChC;QACE,KAAK,CAAC,eAAe,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,SAAS,mBAAmB,CAAC,GAAY;IACvC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACtC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,OAAO,gBAAgB,CAAC;IACjF,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CACnC,EAAa,EACb,MAAc,EACd,OAAe;IAEf,MAAM,IAAI,GAAG,EAAE;SACZ,MAAM,EAAE;SACR,IAAI,CAAC,SAAS,CAAC;SACf,KAAK,CAAC,GAAG,CAAA,GAAG,SAAS,CAAC,MAAM,MAAM,MAAM,QAAQ,SAAS,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;SAC7E,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;SACtB,GAAG,EAAE,CAAC;IACT,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACxB,KAAK,EAAE,GAAG,CAAC,SAAS;QACpB,IAAI,EAAE,GAAG,CAAC,IAA+B;QACzC,KAAK,EAAE,GAAG,CAAC,KAAwB;QACnC,GAAG,EAAE,GAAG,CAAC,GAAG;KACb,CAAC,CAA4B,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAC3B,EAAa,EACb,MAAc;IAEd,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACpE,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;aACZ,GAAG,CAAC;YACH,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;aACD,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;aAC1B,GAAG,EAAE,CAAC;QACT,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@data-club/ai-hub-server",
3
+ "version": "0.0.1",
4
+ "description": "Server package for the data-club ai-hub: Web-Standard Fetch handlers, Letta integration, SSE wire protocol, RBAC, admin endpoints. Mounts into per-customer Next.js wrappers via createNextRouteHandler. See docs/SPECIFICATIONS.md §6.",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "src"
19
+ ],
20
+ "dependencies": {
21
+ "@data-club/letta-code": "^0.26.2",
22
+ "@letta-ai/letta-client": "^1.11.0",
23
+ "@letta-ai/letta-code-sdk": "0.1.14",
24
+ "@node-rs/argon2": "^2.0.2",
25
+ "better-sqlite3": "^11.5.0",
26
+ "drizzle-orm": "^0.36.4",
27
+ "jose": "^5.9.6",
28
+ "pino": "^9.5.0",
29
+ "zod": "^3.23.8",
30
+ "@data-club/ai-hub": "0.0.1"
31
+ },
32
+ "devDependencies": {
33
+ "@types/better-sqlite3": "^7.6.12",
34
+ "dotenv": "^16.4.7",
35
+ "pino-pretty": "^11.3.0",
36
+ "tsx": "^4.19.2",
37
+ "typescript": "^5.5.4",
38
+ "vitest": "^1.6.1"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.build.json",
42
+ "typecheck": "tsc -p tsconfig.json --noEmit",
43
+ "test": "vitest run --passWithNoTests",
44
+ "dev:server": "tsx --tsconfig ./tsconfig.json dev/server.ts",
45
+ "clean": "rm -rf dist .tsbuildinfo"
46
+ }
47
+ }