@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,25 @@
1
+ /**
2
+ * Public entry point for `@data-club/ai-hub-server`.
3
+ *
4
+ * Step 2 ships:
5
+ *
6
+ * - `createFetchHandler({...})` — the canonical Web-Standard Fetch entry point.
7
+ * - `createNextRouteHandler({...})` — first-class Next.js App Router adapter.
8
+ * - `bootServer({...})` — convenience: env → DB → migrate → seed → handler.
9
+ * - The shared types re-exported from `@data-club/ai-hub`.
10
+ *
11
+ * Subsequent steps add: full `/auth/*` + role middleware (Step 3), `/admin/*`
12
+ * + `/sessions` + `/agents` + `/metrics` (Step 4), Letta integration + `/chat`
13
+ * SSE (Step 5), TPM recovery (Step 6).
14
+ *
15
+ * @see SPECIFICATIONS.md §6 — server responsibilities
16
+ * @see SPECIFICATIONS.md §6.2 — stack
17
+ * @see docs/IMPLEMENTATION_PLAN.md — step-by-step delivery schedule
18
+ */
19
+ export type { AIHubRole, AIHubUser, Session, AIHubMessage, TurnStatus, RunningPhase, AIHubState, AIHubEventState, AIHubEvent, AIHubError, } from "@data-club/ai-hub";
20
+ export { createFetchHandler, type CreateFetchHandlerOptions, type FetchHandler, } from "./handlers/fetch.js";
21
+ export { createNextRouteHandler } from "./handlers/nextjs.js";
22
+ export { bootServer, parseEnvConfig, type BootServerOptions, type BootedServer, type EnvConfig, type EnvLike, } from "./bootstrap.js";
23
+ export { SUPER_ADMIN_SEED_PASSWORD, SUPER_ADMIN_SEED_USERNAME, } from "./db/seed.js";
24
+ export { createDefaultLettaClient, type CreateLettaClientDeps, type LettaClient, type StreamUserMessageOpts, } from "./letta/client.js";
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,YAAY,EACV,SAAS,EACT,SAAS,EACT,OAAO,EACP,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,UAAU,EACV,eAAe,EACf,UAAU,EACV,UAAU,GACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EACL,UAAU,EACV,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,OAAO,GACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,qBAAqB,GAC3B,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Public entry point for `@data-club/ai-hub-server`.
3
+ *
4
+ * Step 2 ships:
5
+ *
6
+ * - `createFetchHandler({...})` — the canonical Web-Standard Fetch entry point.
7
+ * - `createNextRouteHandler({...})` — first-class Next.js App Router adapter.
8
+ * - `bootServer({...})` — convenience: env → DB → migrate → seed → handler.
9
+ * - The shared types re-exported from `@data-club/ai-hub`.
10
+ *
11
+ * Subsequent steps add: full `/auth/*` + role middleware (Step 3), `/admin/*`
12
+ * + `/sessions` + `/agents` + `/metrics` (Step 4), Letta integration + `/chat`
13
+ * SSE (Step 5), TPM recovery (Step 6).
14
+ *
15
+ * @see SPECIFICATIONS.md §6 — server responsibilities
16
+ * @see SPECIFICATIONS.md §6.2 — stack
17
+ * @see docs/IMPLEMENTATION_PLAN.md — step-by-step delivery schedule
18
+ */
19
+ export { createFetchHandler, } from "./handlers/fetch.js";
20
+ export { createNextRouteHandler } from "./handlers/nextjs.js";
21
+ export { bootServer, parseEnvConfig, } from "./bootstrap.js";
22
+ export { SUPER_ADMIN_SEED_PASSWORD, SUPER_ADMIN_SEED_USERNAME, } from "./db/seed.js";
23
+ export { createDefaultLettaClient, } from "./letta/client.js";
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAeH,OAAO,EACL,kBAAkB,GAGnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EACL,UAAU,EACV,cAAc,GAKf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,wBAAwB,GAIzB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,355 @@
1
+ /**
2
+ * Hybrid Letta access layer.
3
+ *
4
+ * **Two SDKs, two roles:**
5
+ *
6
+ * - **`@letta-ai/letta-client`** owns *direct REST operations* —
7
+ * `retrieveAgent`, `createConversation`, `listMessages`. These are
8
+ * stable agent / conversation / message CRUD against the Letta
9
+ * server's REST surface; they don't involve model routing or
10
+ * provider shape.
11
+ * - **`@letta-ai/letta-code-sdk`** owns the *chat-streaming path* —
12
+ * `streamUserMessage`. Spawns a Letta Code CLI subprocess per turn;
13
+ * the CLI's internal Pi (Provider Interface) + bundled `models.json`
14
+ * handle model selection, reasoning-tier presets, and provider
15
+ * fallback routing (e.g. Anthropic → Bedrock Opus 4.7). This is what
16
+ * keeps ai-hub current with model releases without code changes.
17
+ *
18
+ * **The hard rule from §6.4 is preserved** — every Letta interaction
19
+ * goes through one of these two SDKs; no raw HTTP, no parallel fetch.
20
+ *
21
+ * Configuration source: `admin_setting.letta_base_url` +
22
+ * `admin_setting.letta_api_key_encrypted` (decrypted with
23
+ * `AI_HUB_ENCRYPTION_KEY`). The Letta-Client wrapper memoizes one SDK
24
+ * instance per `(apiKey, baseURL)` pair so super-admin connection
25
+ * edits propagate without restart. The Letta-Code subprocess inherits
26
+ * `process.env` (which must carry `LETTA_BASE_URL` + `LETTA_API_KEY` —
27
+ * the boot script sets these from the same decrypted DB row).
28
+ *
29
+ * @see SPECIFICATIONS.md §6.4 — Letta integration
30
+ * @see SPECIFICATIONS.md §6.4.1 — first-class SDK surfaces
31
+ */
32
+ import LettaSdkDefault from "@letta-ai/letta-client";
33
+ import { resumeSession, type SDKMessage } from "@letta-ai/letta-code-sdk";
34
+ import type { DrizzleDB } from "../db/connection.js";
35
+ import { type SubprocessThrottle } from "./subprocessThrottle.js";
36
+ import type { LettaMessage } from "./types.js";
37
+ export { ServerOverloadedError, SubprocessThrottle } from "./subprocessThrottle.js";
38
+ /**
39
+ * Thrown when `forkConversation(sourceId)` or `retrieveConversation(id)`
40
+ * resolves to "no such conversation" (Letta 404). The admin agents
41
+ * validator catches this and returns `400 fork_source_not_found` inline
42
+ * on the field; the chat route surfaces it as a 500 (admin-side
43
+ * validation should have caught it before any user-facing session
44
+ * create reached the fork path).
45
+ *
46
+ * @see docs/server/session-sandboxes.md
47
+ */
48
+ export declare class ForkSourceNotFoundError extends Error {
49
+ readonly conversationId: string;
50
+ constructor(conversationId: string);
51
+ }
52
+ /**
53
+ * Provider-reported token usage for a single Letta run + the run's
54
+ * last assistant-message id (so callers can stamp the badge on the
55
+ * visible bubble). All token fields are nullable because the
56
+ * producing provider may not report every dimension — Anthropic
57
+ * reports `cache_write_tokens`, others don't; reasoning tokens come
58
+ * back only when the model produced any; etc.
59
+ *
60
+ * Sourced via a single `GET /v1/runs/{run_id}/messages` call.
61
+ */
62
+ export interface RunUsageStats {
63
+ /**
64
+ * Id of the LAST `assistant_message`-typed entry in the run. `null`
65
+ * when the run had no assistant messages (rare — error-only runs).
66
+ * Callers stamp `message_usage` against this id.
67
+ */
68
+ lastAssistantMessageId: string | null;
69
+ promptTokens: number | null;
70
+ completionTokens: number | null;
71
+ totalTokens: number | null;
72
+ cachedInputTokens: number | null;
73
+ cacheWriteTokens: number | null;
74
+ reasoningTokens: number | null;
75
+ contextTokens: number | null;
76
+ }
77
+ /** Parameters for `streamUserMessage`. */
78
+ export interface StreamUserMessageOpts {
79
+ /** The Letta conversation id (`session.letta_conversation_id`). */
80
+ conversationId: string;
81
+ /**
82
+ * The Letta agent id the session is against. Required so we can
83
+ * re-seed `~/.letta/settings.json` on every spawn — concurrent CLI
84
+ * subprocesses race on writes and can wipe the entry, so the
85
+ * agent-registration-time seed isn't reliable on its own. The
86
+ * seed-on-spawn call below is idempotent (no-op when the entry
87
+ * is already present with the same value).
88
+ */
89
+ lettaAgentId: string;
90
+ /**
91
+ * Plain-text user message body. Sent verbatim to Letta. The admin's
92
+ * system prompt is delivered through Letta's normal channel (the
93
+ * agent's persisted `system` field), so we don't re-inject it here.
94
+ */
95
+ userMessage: string;
96
+ /**
97
+ * Step-12.5 — optional working directory for the spawned Letta Code
98
+ * subprocess. When set, threaded into the SDK's `resumeSession({ cwd })`
99
+ * option (maps to the CLI's `--cwd` flag). Used to confine the agent's
100
+ * filesystem-tool access to a per-session sandbox folder; when
101
+ * provided, the spawn ALSO drops the `FILESYSTEM_TOOLS` group from
102
+ * the `disallowedTools` list so the agent can actually read / write
103
+ * inside that folder.
104
+ *
105
+ * When `undefined`, no `cwd` is passed (the CLI inherits the
106
+ * ai-hub-server process's working directory, as it always has) AND
107
+ * the filesystem tools remain disallowed — today's stateless agent
108
+ * shape.
109
+ *
110
+ * @see docs/server/session-sandboxes.md
111
+ */
112
+ cwd?: string;
113
+ }
114
+ /**
115
+ * Handle returned by `streamUserMessage`. Wraps the Letta Code SDK
116
+ * `Session` + the subprocess-throttle lease so the caller owns one
117
+ * resource bundle to drain, cancel, and clean up.
118
+ *
119
+ * Lifecycle expectations:
120
+ *
121
+ * 1. Caller iterates `events` to consume `SDKMessage`s in real time.
122
+ * 2. At any point, calling `abort()` sends an `interrupt` control to
123
+ * the spawned CLI. Behavior depends on what the CLI is doing —
124
+ * during model generation interrupts work cleanly; during a
125
+ * long-running tool call the interrupt is currently queued (see
126
+ * migration plan §7 open question 5).
127
+ * 3. Caller MUST call `close()` in a `finally` regardless of how the
128
+ * iteration ended (done, cancelled, error). `close()` terminates
129
+ * the CLI subprocess + releases the throttle lease. Idempotent.
130
+ */
131
+ export interface ChatTurnHandle {
132
+ /** Async iterable of Letta Code SDK messages — caller drains this. */
133
+ events: AsyncIterable<SDKMessage>;
134
+ /**
135
+ * Sends an `interrupt` control to the spawned CLI. Best-effort; if
136
+ * the CLI is mid-tool the interrupt may be queued. The caller still
137
+ * needs to call `close()` to release subprocess + lease.
138
+ */
139
+ abort(): Promise<void>;
140
+ /**
141
+ * Tears down the Letta Code subprocess + releases the throttle slot.
142
+ * Idempotent — safe to call twice. Caller MUST invoke this in a
143
+ * `finally`. Sync because the SDK's `session.close()` is sync.
144
+ */
145
+ close(): void;
146
+ }
147
+ /**
148
+ * Project-shaped Letta client. The handlers depend on this interface,
149
+ * not on the underlying SDKs, so tests can plug a mock implementation
150
+ * in via `getLettaClient` on the server context.
151
+ *
152
+ * @see SPECIFICATIONS.md §6.4
153
+ */
154
+ export interface LettaClient {
155
+ /**
156
+ * Retrieves a Letta agent by id (via `@letta-ai/letta-client`).
157
+ * Returns `null` (not throws) on miss so the agent-validation flow
158
+ * on `POST/PATCH /admin/agents` can return a 400
159
+ * `letta_agent_not_found` without try/catch noise. Any non-404 SDK
160
+ * error rethrows — the admin handler returns 500.
161
+ *
162
+ * @param lettaAgentId - candidate Letta-side agent id.
163
+ * @returns the agent state or `null` if not found.
164
+ */
165
+ retrieveAgent(lettaAgentId: string): Promise<{
166
+ id: string;
167
+ name: string;
168
+ /** Provider-prefixed model handle (e.g. `"anthropic/claude-opus-4-7"`). */
169
+ model: string;
170
+ } | null>;
171
+ /**
172
+ * Creates a fresh conversation against the given Letta agent (via
173
+ * `@letta-ai/letta-client`). Returns the conversation id we store
174
+ * on the new session row.
175
+ *
176
+ * @param lettaAgentId - the Letta-side agent id.
177
+ * @returns the new conversation's id.
178
+ */
179
+ createConversation(lettaAgentId: string): Promise<{
180
+ id: string;
181
+ }>;
182
+ /**
183
+ * Step-12.5 — retrieves a Letta conversation by id (via
184
+ * `client.conversations.retrieve`). Used by the admin agents
185
+ * validator to verify `fork_source_conversation_id` resolves to a
186
+ * real conversation AND that its `agent_id` matches the agent's
187
+ * `letta_agent_id` (Letta's fork API requires same-agent forking).
188
+ *
189
+ * Returns `null` on Letta 404 so the handler can surface
190
+ * `400 fork_source_not_found` without try/catch noise; non-404
191
+ * SDK errors propagate.
192
+ *
193
+ * @param conversationId - the candidate Letta conversation id.
194
+ * @returns `{ id, agentId }` or `null` if not found.
195
+ */
196
+ retrieveConversation(conversationId: string): Promise<{
197
+ id: string;
198
+ agentId: string;
199
+ } | null>;
200
+ /**
201
+ * Step-12.5 — forks an existing Letta conversation into a new
202
+ * conversation belonging to the same agent (via
203
+ * `client.conversations.fork`). The new conversation shares the
204
+ * source's in-context messages and gets a freshly compiled system
205
+ * message reflecting the agent's current memory-block values.
206
+ *
207
+ * Used by `POST /sessions` when the parent agent's
208
+ * `fork_source_conversation_id` is set. The admin endpoint validates
209
+ * source existence + agent match at write time, so this call is
210
+ * expected to succeed in the happy path; a 404 here is treated as
211
+ * "operator deleted the source conversation between admin-validate
212
+ * and user-session-create" and surfaced as `ForkSourceNotFoundError`.
213
+ *
214
+ * @param sourceConversationId - the Letta conversation id to fork.
215
+ * @returns the new conversation's `{ id, agentId }`.
216
+ * @throws ForkSourceNotFoundError on Letta 404.
217
+ */
218
+ forkConversation(sourceConversationId: string): Promise<{
219
+ id: string;
220
+ agentId: string;
221
+ }>;
222
+ /**
223
+ * Lists every message in a conversation, oldest first (via
224
+ * `@letta-ai/letta-client`). Used for `GET /sessions/{id}/messages`
225
+ * history rendering.
226
+ *
227
+ * @param conversationId - the Letta conversation id.
228
+ * @returns the (oldest-first) array of messages.
229
+ */
230
+ listMessages(conversationId: string): Promise<ReadonlyArray<LettaMessage>>;
231
+ /**
232
+ * Deletes a single message from an agent's history by id.
233
+ *
234
+ * The typed SDK only exposes `create` / `list` on conversation messages,
235
+ * so this reaches the Letta server's `DELETE /v1/agents/{agent_id}/messages/{message_id}`
236
+ * endpoint via the SDK's raw HTTP escape hatch (`sdk.delete(...)`) — the
237
+ * same pattern `getRunUsageStats` uses for `sdk.get(...)`. A 404 is treated
238
+ * as "already gone" and swallowed; other errors propagate.
239
+ *
240
+ * Used by the rotation runner to remove the prompt's `user_message` so a
241
+ * rotating starting message's prepared conversation opens with the agent's
242
+ * reply.
243
+ *
244
+ * @param lettaAgentId - the agent the message belongs to.
245
+ * @param messageId - the message id (from `listMessages`).
246
+ */
247
+ deleteMessage(lettaAgentId: string, messageId: string): Promise<void>;
248
+ /**
249
+ * Deletes an entire Letta conversation (via `client.conversations.delete`).
250
+ * Best-effort cleanup of a rotating message's previous prepared
251
+ * conversation after a successful rotation produces a fresh one — a 404 is
252
+ * swallowed; other errors propagate to the caller (which logs + continues).
253
+ *
254
+ * @param conversationId - the Letta conversation id to delete.
255
+ */
256
+ deleteConversation(conversationId: string): Promise<void>;
257
+ /**
258
+ * Fetches provider-reported token usage for a Letta run, including
259
+ * prompt-cache hit / write counts. The SDK's `session.stream()`
260
+ * drops `usage_statistics` messages, so we re-fetch via REST after
261
+ * the turn lands; the runner uses this to stamp a usage badge on
262
+ * the last assistant message.
263
+ *
264
+ * Returns `null` when:
265
+ * - the run id is unknown to Letta (404),
266
+ * - the run hasn't emitted a usage_statistics message yet,
267
+ * - the network call fails (best-effort — the badge is a nicety,
268
+ * not load-bearing).
269
+ *
270
+ * @param runId - Letta run id captured from `SDKAssistantMessage.runId`.
271
+ */
272
+ getRunUsageStats(runId: string): Promise<RunUsageStats | null>;
273
+ /**
274
+ * Spawns a Letta Code CLI subprocess and streams a chat turn against
275
+ * the given conversation. Returns a `ChatTurnHandle` the caller
276
+ * drains + cancels + closes.
277
+ *
278
+ * Pre-flight checks (in order, all may throw):
279
+ * 1. **Subprocess throttle.** `SubprocessThrottle.acquire()` runs
280
+ * first — throws `ServerOverloadedError` if RAM is under the
281
+ * threshold or the hard-cap is reached. The chat route catches
282
+ * this and returns HTTP 503 `server_overloaded`.
283
+ * 2. **Session initialization.** `session.initialize()` may throw if
284
+ * the CLI subprocess fails to spawn or can't reach Letta. The
285
+ * lease is released before the throw so the throttle counter
286
+ * doesn't leak.
287
+ *
288
+ * The Letta Code session is configured for the ai-hub use case:
289
+ * - `permissionMode: "bypassPermissions"` — no interactive approvals
290
+ * (we don't expose them to end-users in v1).
291
+ * - `skillSources: []` — no auto-loaded skills (challenge 2 in the
292
+ * migration brief).
293
+ * - `systemInfoReminder: false` — no first-turn environment dump.
294
+ * - `memfsStartup: "skip"` — no git-backed memory filesystem.
295
+ * - `disallowedTools: ["AskUserQuestion", "EnterPlanMode",
296
+ * "ExitPlanMode"]` — tools that require runtime user input.
297
+ *
298
+ * Toolset suppression is handled out-of-band by the
299
+ * `seedAgentToolsetNone` upsert into `~/.letta/settings.json` at
300
+ * agent-registration time.
301
+ *
302
+ * @param opts - see `StreamUserMessageOpts`.
303
+ * @returns a `ChatTurnHandle` the caller drains and closes.
304
+ * @throws `ServerOverloadedError` when the throttle rejects.
305
+ */
306
+ streamUserMessage(opts: StreamUserMessageOpts): Promise<ChatTurnHandle>;
307
+ }
308
+ /** Dependency bundle for `createDefaultLettaClient`. */
309
+ export interface CreateLettaClientDeps {
310
+ /** Drizzle handle. */
311
+ db: DrizzleDB;
312
+ /** Parsed encryption key for decrypting the Letta API key at rest. */
313
+ encryptionKey: Buffer;
314
+ /** Subprocess-spawn throttle (shared across the server instance). */
315
+ subprocessThrottle: SubprocessThrottle;
316
+ /**
317
+ * Env source — used as the fallback when the DB column is empty or
318
+ * whitespace. Production passes `process.env`; tests pass a synthesized
319
+ * record so the env precedence behaviour is exercisable without
320
+ * touching the real environment. Re-read on every `getSdk()` call so a
321
+ * server restart with a different `.env` reflects immediately.
322
+ */
323
+ envSource?: Record<string, string | undefined>;
324
+ /**
325
+ * Override the Letta Client SDK constructor — only used by tests.
326
+ * Production passes the SDK's `Letta` class (or omits to use the
327
+ * default).
328
+ */
329
+ sdkConstructor?: typeof LettaSdkDefault;
330
+ /**
331
+ * Override `resumeSession` from `@letta-ai/letta-code-sdk` — only
332
+ * used by tests, which inject a fake session factory.
333
+ */
334
+ resumeSessionFn?: typeof resumeSession;
335
+ }
336
+ /**
337
+ * Constructs the default `LettaClient` implementation.
338
+ *
339
+ * Reads `admin_setting.letta_base_url` + `letta_api_key_encrypted` on
340
+ * each Letta-Client call (no in-flight polling — fresh-on-demand) and
341
+ * memoizes the underlying SDK instance against `(apiKey, baseURL)` so
342
+ * super-admin connection-settings edits propagate without restart.
343
+ *
344
+ * Throws on the first Letta-Client call if `admin_setting` has no
345
+ * `letta_base_url` or no decryptable API key.
346
+ *
347
+ * @param deps - see `CreateLettaClientDeps`.
348
+ * @returns the project-shaped Letta client.
349
+ *
350
+ * @see SPECIFICATIONS.md §6.4
351
+ * @see SPECIFICATIONS.md §11 — `admin_setting` schema
352
+ */
353
+ export declare function createDefaultLettaClient(deps: CreateLettaClientDeps): LettaClient;
354
+ export type { LettaMessage, LettaSdk } from "./types.js";
355
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/letta/client.ts"],"names":[],"mappings":"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"}