@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,529 @@
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 { eq } from "drizzle-orm";
33
+ import LettaSdkDefault, { NotFoundError, } from "@letta-ai/letta-client";
34
+ import { resumeSession, } from "@letta-ai/letta-code-sdk";
35
+ import { decryptString } from "../auth/encryption.js";
36
+ import { adminSetting } from "../db/schema.js";
37
+ import { seedAgentToolsetNone } from "./settingsFileSeed.js";
38
+ import {} from "./subprocessThrottle.js";
39
+ // Re-export so consumers don't need to know about the throttle module.
40
+ export { ServerOverloadedError, SubprocessThrottle } from "./subprocessThrottle.js";
41
+ /**
42
+ * Thrown when `forkConversation(sourceId)` or `retrieveConversation(id)`
43
+ * resolves to "no such conversation" (Letta 404). The admin agents
44
+ * validator catches this and returns `400 fork_source_not_found` inline
45
+ * on the field; the chat route surfaces it as a 500 (admin-side
46
+ * validation should have caught it before any user-facing session
47
+ * create reached the fork path).
48
+ *
49
+ * @see docs/server/session-sandboxes.md
50
+ */
51
+ export class ForkSourceNotFoundError extends Error {
52
+ conversationId;
53
+ constructor(conversationId) {
54
+ super(`Letta conversation not found: ${conversationId}`);
55
+ this.conversationId = conversationId;
56
+ this.name = "ForkSourceNotFoundError";
57
+ }
58
+ }
59
+ /**
60
+ * Letta Code's bundled tools that are ALWAYS disallowed regardless of
61
+ * whether a per-session sandbox is configured.
62
+ *
63
+ * Includes:
64
+ * - Memory tools (the v1 no-memory stance keeps these forbidden; see
65
+ * docs/admin/agent-management.md).
66
+ * - Sub-agent management (`Task` / `TaskOutput` / `TaskStop` / `TodoWrite`
67
+ * / `Skill`) — not exposed to ai-hub end users.
68
+ * - Interactive tools (`AskUserQuestion` / `EnterPlanMode` /
69
+ * `ExitPlanMode`) — hang the headless code path.
70
+ * - Web tools (`WebFetch` / `WebSearch`) — operator-curated agents
71
+ * should reach the web through ADE-attached MCP tools, not Letta
72
+ * Code's defaults.
73
+ *
74
+ * The filesystem tools (Read / Write / Edit / etc.) live in
75
+ * `FILESYSTEM_TOOLS` below and are disallowed ONLY when no sandbox is
76
+ * configured for the session.
77
+ *
78
+ * @see docs/server/session-sandboxes.md — the disallow-list split (Step 12.5)
79
+ */
80
+ const ALWAYS_DISALLOWED_TOOLS = [
81
+ // Sub-agent + task management
82
+ "Task",
83
+ "TaskOutput",
84
+ "TaskStop",
85
+ "TodoWrite",
86
+ // Skills + slash invocation
87
+ "Skill",
88
+ // Memory (Letta Code's built-in memory file convenience tool) — the v1
89
+ // no-memory stance keeps these forbidden even when a sandbox is enabled.
90
+ "memory",
91
+ "memory_apply_patch",
92
+ "memory_insert",
93
+ "memory_replace",
94
+ "memory_rethink",
95
+ // Interactive tools that require runtime user input
96
+ "AskUserQuestion",
97
+ "EnterPlanMode",
98
+ "ExitPlanMode",
99
+ // Web tools (Letta Code adds these in the Claude toolset; harmless to
100
+ // disallow here if absent; future-proofs against upstream additions)
101
+ "WebFetch",
102
+ "WebSearch",
103
+ ];
104
+ /**
105
+ * Letta Code's bundled filesystem / shell tools — disallowed when the
106
+ * session has NO sandbox configured (no `cwd` to confine them to), and
107
+ * re-enabled when the parent agent's `sandbox_seed_name` is set so the
108
+ * agent can actually use the seeded files (Step 12.5).
109
+ */
110
+ const FILESYSTEM_TOOLS = [
111
+ // File / shell — every preset toolset's core set
112
+ "Read",
113
+ "Write",
114
+ "Edit",
115
+ "ApplyPatch",
116
+ "Bash",
117
+ "Glob",
118
+ "Grep",
119
+ // Snake-case variants from the codex_snake / gemini_snake toolsets
120
+ "read_file_lc",
121
+ "write_file_lc",
122
+ "edit_file_lc",
123
+ "execute_shell_lc",
124
+ ];
125
+ /**
126
+ * Constructs the default `LettaClient` implementation.
127
+ *
128
+ * Reads `admin_setting.letta_base_url` + `letta_api_key_encrypted` on
129
+ * each Letta-Client call (no in-flight polling — fresh-on-demand) and
130
+ * memoizes the underlying SDK instance against `(apiKey, baseURL)` so
131
+ * super-admin connection-settings edits propagate without restart.
132
+ *
133
+ * Throws on the first Letta-Client call if `admin_setting` has no
134
+ * `letta_base_url` or no decryptable API key.
135
+ *
136
+ * @param deps - see `CreateLettaClientDeps`.
137
+ * @returns the project-shaped Letta client.
138
+ *
139
+ * @see SPECIFICATIONS.md §6.4
140
+ * @see SPECIFICATIONS.md §11 — `admin_setting` schema
141
+ */
142
+ export function createDefaultLettaClient(deps) {
143
+ const SdkCtor = deps.sdkConstructor ?? LettaSdkDefault;
144
+ const resume = deps.resumeSessionFn ?? resumeSession;
145
+ let cached = null;
146
+ const envSource = deps.envSource ?? process.env;
147
+ /**
148
+ * Resolves the current `(apiKey, baseURL)` pair and returns a memoized
149
+ * Letta-Client SDK instance.
150
+ *
151
+ * **API key precedence** (per the operator-spec'd model):
152
+ * 1. If `admin_setting.letta_api_key_encrypted` decrypts to a non-empty,
153
+ * non-whitespace string → use that (super-admin set it via the
154
+ * admin panel; DB wins over env).
155
+ * 2. Otherwise → fall back to `env.LETTA_API_KEY` (whitespace-trimmed).
156
+ * 3. Otherwise → throw — neither source has a usable value.
157
+ *
158
+ * Evaluated on every call, so:
159
+ * - A super-admin PATCH to /admin/settings takes effect immediately.
160
+ * - Clearing the value via the admin panel (empty/whitespace) falls
161
+ * back to env on the very next request.
162
+ * - A new `.env` after a restart is reflected immediately when the DB
163
+ * column is empty.
164
+ */
165
+ function resolveApiKey() {
166
+ const settings = deps.db
167
+ .select()
168
+ .from(adminSetting)
169
+ .where(eq(adminSetting.id, 1))
170
+ .get();
171
+ if (settings?.lettaApiKeyEncrypted) {
172
+ const decrypted = decryptString(deps.encryptionKey, settings.lettaApiKeyEncrypted);
173
+ if (decrypted.trim().length > 0) {
174
+ return { apiKey: decrypted, source: "db" };
175
+ }
176
+ }
177
+ const envKey = envSource.LETTA_API_KEY;
178
+ if (envKey && envKey.trim().length > 0) {
179
+ return { apiKey: envKey, source: "env" };
180
+ }
181
+ throw new Error("No Letta API key configured. Set LETTA_API_KEY in .env, OR PATCH it via /admin/settings.");
182
+ }
183
+ function getSdk() {
184
+ const settings = deps.db
185
+ .select()
186
+ .from(adminSetting)
187
+ .where(eq(adminSetting.id, 1))
188
+ .get();
189
+ if (!settings?.lettaBaseUrl) {
190
+ throw new Error("admin_setting.letta_base_url is empty — configure it via /admin/settings or LETTA_BASE_URL.");
191
+ }
192
+ const { apiKey } = resolveApiKey();
193
+ // The Letta Client SDK appends its own `/v1/...` paths, so a
194
+ // `letta_base_url` like `http://localhost:8283/v1` produces
195
+ // double-v1 calls. Strip a trailing `/v1` defensively.
196
+ const baseURL = settings.lettaBaseUrl.replace(/\/v1\/?$/i, "");
197
+ if (cached && cached.apiKey === apiKey && cached.baseURL === baseURL) {
198
+ return cached.sdk;
199
+ }
200
+ const sdk = new SdkCtor({ apiKey, baseURL });
201
+ cached = { apiKey, baseURL, sdk };
202
+ return sdk;
203
+ }
204
+ return {
205
+ async retrieveAgent(lettaAgentId) {
206
+ const sdk = getSdk();
207
+ try {
208
+ const state = await sdk.agents.retrieve(lettaAgentId);
209
+ return { id: state.id, name: state.name, model: state.model ?? "" };
210
+ }
211
+ catch (err) {
212
+ if (err instanceof NotFoundError)
213
+ return null;
214
+ throw err;
215
+ }
216
+ },
217
+ async createConversation(lettaAgentId) {
218
+ const sdk = getSdk();
219
+ const conv = await sdk.conversations.create({ agent_id: lettaAgentId });
220
+ return { id: conv.id };
221
+ },
222
+ async retrieveConversation(conversationId) {
223
+ const sdk = getSdk();
224
+ try {
225
+ const conv = await sdk.conversations.retrieve(conversationId);
226
+ return { id: conv.id, agentId: conv.agent_id };
227
+ }
228
+ catch (err) {
229
+ if (err instanceof NotFoundError)
230
+ return null;
231
+ throw err;
232
+ }
233
+ },
234
+ async forkConversation(sourceConversationId) {
235
+ const sdk = getSdk();
236
+ try {
237
+ // The Letta-Client SDK exposes `fork(conversationId, params?)`.
238
+ // We don't pass a body — defaults are fine for our use case
239
+ // (forked conversation is not hidden, no extra params needed).
240
+ const conv = await sdk.conversations.fork(sourceConversationId);
241
+ return { id: conv.id, agentId: conv.agent_id };
242
+ }
243
+ catch (err) {
244
+ if (err instanceof NotFoundError) {
245
+ throw new ForkSourceNotFoundError(sourceConversationId);
246
+ }
247
+ throw err;
248
+ }
249
+ },
250
+ async listMessages(conversationId) {
251
+ const sdk = getSdk();
252
+ const out = [];
253
+ const page = await sdk.conversations.messages.list(conversationId);
254
+ for await (const msg of page) {
255
+ out.push(msg);
256
+ }
257
+ return out;
258
+ },
259
+ async deleteMessage(lettaAgentId, messageId) {
260
+ const sdk = getSdk();
261
+ try {
262
+ // The typed `conversations.messages` resource is create/list-only;
263
+ // the message-delete capability lives on the agent-scoped REST route.
264
+ // Same raw-HTTP escape hatch `getRunUsageStats` uses for `sdk.get`.
265
+ await sdk.delete(`/v1/agents/${encodeURIComponent(lettaAgentId)}/messages/${encodeURIComponent(messageId)}`);
266
+ }
267
+ catch (err) {
268
+ // Already gone is fine — the goal state (message absent) is reached.
269
+ if (err instanceof NotFoundError)
270
+ return;
271
+ throw err;
272
+ }
273
+ },
274
+ async deleteConversation(conversationId) {
275
+ const sdk = getSdk();
276
+ try {
277
+ await sdk.conversations.delete(conversationId);
278
+ }
279
+ catch (err) {
280
+ if (err instanceof NotFoundError)
281
+ return;
282
+ throw err;
283
+ }
284
+ },
285
+ async getRunUsageStats(runId) {
286
+ const sdk = getSdk();
287
+ // Two endpoints in parallel:
288
+ // - `/v1/runs/{id}/messages` carries persisted assistant
289
+ // messages — we need the LAST one's id to stamp the badge.
290
+ // The `usage_statistics` SDK stream event is NOT persisted
291
+ // here; we used to look for it but it's stream-only.
292
+ // - `/v1/runs/{id}/steps` carries per-LLM-call usage with the
293
+ // full cache breakdown (`cached_input_tokens`,
294
+ // `cache_write_tokens`, `reasoning_tokens`). For multi-step
295
+ // turns we sum across steps; for single-step turns we just
296
+ // read the one row.
297
+ //
298
+ // Best-effort: any failure on either side returns null and the
299
+ // badge just doesn't render. Never blocks the chat turn.
300
+ let messagesRaw;
301
+ let stepsRaw;
302
+ try {
303
+ [messagesRaw, stepsRaw] = await Promise.all([
304
+ sdk.get(`/v1/runs/${runId}/messages`),
305
+ sdk.get(`/v1/runs/${runId}/steps`),
306
+ ]);
307
+ }
308
+ catch {
309
+ return null;
310
+ }
311
+ // Pull the last assistant message id (anchor for the badge).
312
+ let lastAssistantMessageId = null;
313
+ if (Array.isArray(messagesRaw)) {
314
+ for (const item of messagesRaw) {
315
+ if (!item || typeof item !== "object")
316
+ continue;
317
+ const m = item;
318
+ if (m["message_type"] === "assistant_message" && typeof m["id"] === "string") {
319
+ lastAssistantMessageId = m["id"];
320
+ }
321
+ }
322
+ }
323
+ // Sum tokens across steps. Missing fields stay null in the sum
324
+ // (the sum only goes non-null if at least one step reported it),
325
+ // so providers that don't expose cache_write keep it null at the
326
+ // top level rather than silently appearing as 0.
327
+ if (!Array.isArray(stepsRaw))
328
+ return null;
329
+ const sum = {
330
+ promptTokens: null,
331
+ completionTokens: null,
332
+ totalTokens: null,
333
+ cachedInputTokens: null,
334
+ cacheWriteTokens: null,
335
+ reasoningTokens: null,
336
+ contextTokens: null,
337
+ };
338
+ const addInto = (key, v) => {
339
+ if (typeof v !== "number")
340
+ return;
341
+ sum[key] = (sum[key] ?? 0) + v;
342
+ };
343
+ let anyStep = false;
344
+ for (const item of stepsRaw) {
345
+ if (!item || typeof item !== "object")
346
+ continue;
347
+ anyStep = true;
348
+ const s = item;
349
+ addInto("promptTokens", s["prompt_tokens"]);
350
+ addInto("completionTokens", s["completion_tokens"]);
351
+ addInto("totalTokens", s["total_tokens"]);
352
+ addInto("cachedInputTokens", s["cached_input_tokens"]);
353
+ addInto("cacheWriteTokens", s["cache_write_tokens"]);
354
+ addInto("reasoningTokens", s["reasoning_tokens"]);
355
+ }
356
+ if (!anyStep)
357
+ return null;
358
+ return {
359
+ lastAssistantMessageId,
360
+ ...sum,
361
+ };
362
+ },
363
+ async streamUserMessage(opts) {
364
+ // Throttle gate first — synchronous, throws ServerOverloadedError.
365
+ // Caller's chat-route catch turns that into HTTP 503.
366
+ const lease = deps.subprocessThrottle.acquire();
367
+ // Sync `process.env.LETTA_API_KEY` to the currently-resolved value
368
+ // (DB > env precedence — see `resolveApiKey`). The Letta Code
369
+ // subprocess inherits `{...process.env}`, so whatever is in
370
+ // process.env at spawn time is what the CLI sends to Letta. Mutating
371
+ // it here on every spawn means a super-admin's PATCH to
372
+ // /admin/settings takes effect on the very next chat turn without
373
+ // a process restart — matches the same hot-reload behavior the
374
+ // direct-REST `getSdk()` path already had via SDK memoization on
375
+ // the `(apiKey, baseURL)` pair.
376
+ //
377
+ // If resolveApiKey throws (no usable value anywhere), we release
378
+ // the throttle lease before propagating — otherwise the slot would
379
+ // be leaked.
380
+ try {
381
+ const resolved = resolveApiKey();
382
+ process.env.LETTA_API_KEY = resolved.apiKey;
383
+ }
384
+ catch (err) {
385
+ lease.release();
386
+ throw err;
387
+ }
388
+ // Letta Code's CLI reads `LETTA_BASE_URL` from env and appends
389
+ // `/v1/...` to it. If the operator set the env to
390
+ // `http://localhost:8283/v1` (matching the Letta Client SDK's
391
+ // expectation), the CLI produces double-v1 URLs that 404 — the
392
+ // CLI surfaces this as "Failed to connect to Letta server /
393
+ // credentials may be invalid", which is misleading. Strip the
394
+ // trailing `/v1` in process.env on every spawn (idempotent —
395
+ // already-stripped values pass through unchanged). Operators
396
+ // who use the bare-host form aren't affected. (Also done in
397
+ // `bootstrap.ts` at boot for the primary case; this is
398
+ // defense-in-depth.)
399
+ const rawBaseUrl = process.env.LETTA_BASE_URL;
400
+ if (rawBaseUrl) {
401
+ const stripped = rawBaseUrl.replace(/\/v1\/?$/i, "");
402
+ if (stripped !== rawBaseUrl) {
403
+ process.env.LETTA_BASE_URL = stripped;
404
+ }
405
+ }
406
+ // Re-seed `~/.letta/settings.json` with `{toolset: "none"}` for
407
+ // this agent on every spawn. Necessary because concurrent CLI
408
+ // subprocesses race on settings-file writes (each maintains its
409
+ // own in-memory snapshot, writes back on exit, last-writer-wins)
410
+ // and the agent-registration-time seed can be wiped between
411
+ // spawns. Idempotent — when the entry already matches, this is
412
+ // a no-op (doesn't touch the file's mtime). Best-effort: a
413
+ // write failure logs but doesn't block the chat turn (the shim
414
+ // is the primary mechanism; the settings file is defense-in-
415
+ // depth + TUI-compatibility).
416
+ try {
417
+ seedAgentToolsetNone({
418
+ agentId: opts.lettaAgentId,
419
+ lettaBaseUrl: process.env.LETTA_BASE_URL,
420
+ });
421
+ }
422
+ catch {
423
+ // intentionally ignored — see above
424
+ }
425
+ // Point the SDK at our CLI shim. The shim injects `--tools ""`
426
+ // into argv before invoking the real Letta Code CLI, which
427
+ // mimics the TUI `/toolset none` action — both end up with an
428
+ // empty `toolRegistry` so the LLM sees only the agent's
429
+ // ADE-attached tools (no Read/Write/Bash/etc. from Letta
430
+ // Code's bundled presets). See `lettaCliShim.mjs` for the
431
+ // full rationale + traceability to the Letta Code source.
432
+ //
433
+ // This is set once per spawn (cheap — just a process.env write).
434
+ // We use the migration's source path so the shim is in the
435
+ // same repo and ships with ai-hub-server.
436
+ if (process.env.LETTA_CLI_PATH === undefined) {
437
+ const { dirname, join } = await import("node:path");
438
+ const { fileURLToPath } = await import("node:url");
439
+ const here = dirname(fileURLToPath(import.meta.url));
440
+ process.env.LETTA_CLI_PATH = join(here, "lettaCliShim.mjs");
441
+ }
442
+ // We send the raw user message verbatim; the admin's system prompt
443
+ // flows through Letta's normal channel (the agent's persisted
444
+ // `system` field).
445
+ const userContent = opts.userMessage;
446
+ // Step-12.5 — disallow-list composition.
447
+ //
448
+ // When the parent session has a sandbox folder (opts.cwd set), the
449
+ // filesystem tools are RE-ENABLED so the agent can use the seeded
450
+ // files. Without a sandbox, those tools stay disallowed (today's
451
+ // stateless agent shape; regression-locked by a snapshot test).
452
+ //
453
+ // The always-disallowed group (memory / sub-agent / interactive /
454
+ // web) stays disallowed regardless — the v1 no-memory stance is
455
+ // unchanged. See docs/server/session-sandboxes.md.
456
+ const disallowedTools = opts.cwd === undefined
457
+ ? [...ALWAYS_DISALLOWED_TOOLS, ...FILESYSTEM_TOOLS]
458
+ : [...ALWAYS_DISALLOWED_TOOLS];
459
+ let session = null;
460
+ try {
461
+ session = resume(opts.conversationId, {
462
+ permissionMode: "bypassPermissions",
463
+ skillSources: [],
464
+ systemInfoReminder: false,
465
+ memfsStartup: "skip",
466
+ // `disallowedTools` mirrors the effect of TUI `/toolset none` —
467
+ // the persisted-setting approach (`~/.letta/settings.json`) is
468
+ // only consulted by Letta Code's interactive code path, NOT
469
+ // the headless `--input-format stream-json` mode the SDK uses.
470
+ // And `--toolset none` is rejected as a CLI arg in headless
471
+ // mode (only auto/codex/default/gemini accepted there).
472
+ //
473
+ // Adding tools to this list as Letta Code adds them upstream
474
+ // is maintenance debt — grep `ALWAYS_DISALLOWED_TOOLS` /
475
+ // `FILESYSTEM_TOOLS` to find the constants. The longer-term
476
+ // fix is upstream: either accept `--toolset none` in headless
477
+ // mode or expose a `--no-tools` flag. Filed against
478
+ // letta-ai/letta-code (TBD).
479
+ disallowedTools,
480
+ // Step-12.5 — per-session sandbox folder; see opts.cwd JSDoc.
481
+ ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),
482
+ });
483
+ await session.initialize();
484
+ await session.send(userContent);
485
+ }
486
+ catch (err) {
487
+ // Spawn / init / send failure — release lease + tear down the
488
+ // subprocess if we got that far, then re-throw for the caller.
489
+ if (session) {
490
+ try {
491
+ session.close();
492
+ }
493
+ catch {
494
+ // best-effort
495
+ }
496
+ }
497
+ lease.release();
498
+ throw err;
499
+ }
500
+ const activeSession = session;
501
+ let closed = false;
502
+ return {
503
+ events: activeSession.stream(),
504
+ async abort() {
505
+ try {
506
+ await activeSession.abort();
507
+ }
508
+ catch {
509
+ // The CLI may already be tearing down — swallow to keep
510
+ // the cancel route idempotent. `close()` still runs.
511
+ }
512
+ },
513
+ close() {
514
+ if (closed)
515
+ return;
516
+ closed = true;
517
+ try {
518
+ activeSession.close();
519
+ }
520
+ catch {
521
+ // best-effort
522
+ }
523
+ lease.release();
524
+ },
525
+ };
526
+ },
527
+ };
528
+ }
529
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/letta/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,OAAO,eAAe,EAAE,EACtB,aAAa,GACd,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,GAGd,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAGN,MAAM,yBAAyB,CAAC;AAOjC,uEAAuE;AACvE,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEpF;;;;;;;;;GASG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACpB;IAA5B,YAA4B,cAAsB;QAChD,KAAK,CAAC,iCAAiC,cAAc,EAAE,CAAC,CAAC;QAD/B,mBAAc,GAAd,cAAc,CAAQ;QAEhD,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,uBAAuB,GAA0B;IACrD,8BAA8B;IAC9B,MAAM;IACN,YAAY;IACZ,UAAU;IACV,WAAW;IACX,4BAA4B;IAC5B,OAAO;IACP,uEAAuE;IACvE,yEAAyE;IACzE,QAAQ;IACR,oBAAoB;IACpB,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,oDAAoD;IACpD,iBAAiB;IACjB,eAAe;IACf,cAAc;IACd,sEAAsE;IACtE,qEAAqE;IACrE,UAAU;IACV,WAAW;CACZ,CAAC;AAEF;;;;;GAKG;AACH,MAAM,gBAAgB,GAA0B;IAC9C,iDAAiD;IACjD,MAAM;IACN,OAAO;IACP,MAAM;IACN,YAAY;IACZ,MAAM;IACN,MAAM;IACN,MAAM;IACN,mEAAmE;IACnE,cAAc;IACd,eAAe;IACf,cAAc;IACd,kBAAkB;CACnB,CAAC;AAuSF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAA2B;IAE3B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,IAAI,eAAe,CAAC;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,IAAI,aAAa,CAAC;IACrD,IAAI,MAAM,GAEC,IAAI,CAAC;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAK,OAAO,CAAC,GAA0C,CAAC;IAExF;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,aAAa;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE;aACrB,MAAM,EAAE;aACR,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;aAC7B,GAAG,EAAE,CAAC;QACT,IAAI,QAAQ,EAAE,oBAAoB,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;YACnF,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAC7C,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC;QACvC,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC3C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,0FAA0F,CAC3F,CAAC;IACJ,CAAC;IAED,SAAS,MAAM;QACb,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE;aACrB,MAAM,EAAE;aACR,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;aAC7B,GAAG,EAAE,CAAC;QACT,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;QACnC,6DAA6D;QAC7D,4DAA4D;QAC5D,uDAAuD;QACvD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YACrE,OAAO,MAAM,CAAC,GAAG,CAAC;QACpB,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7C,MAAM,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAClC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO;QACL,KAAK,CAAC,aAAa,CAAC,YAAY;YAC9B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;gBACtD,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACtE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,aAAa;oBAAE,OAAO,IAAI,CAAC;gBAC9C,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,kBAAkB,CAAC,YAAY;YACnC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;YACxE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,oBAAoB,CAAC,cAAc;YACvC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAC9D,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,aAAa;oBAAE,OAAO,IAAI,CAAC;gBAC9C,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,gBAAgB,CAAC,oBAAoB;YACzC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,gEAAgE;gBAChE,4DAA4D;gBAC5D,+DAA+D;gBAC/D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBAChE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;oBACjC,MAAM,IAAI,uBAAuB,CAAC,oBAAoB,CAAC,CAAC;gBAC1D,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,cAAc;YAC/B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,MAAM,GAAG,GAAmB,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnE,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBAC7B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,YAAY,EAAE,SAAS;YACzC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,mEAAmE;gBACnE,sEAAsE;gBACtE,oEAAoE;gBACpE,MAAM,GAAG,CAAC,MAAM,CACd,cAAc,kBAAkB,CAAC,YAAY,CAAC,aAAa,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAC3F,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,qEAAqE;gBACrE,IAAI,GAAG,YAAY,aAAa;oBAAE,OAAO;gBACzC,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,kBAAkB,CAAC,cAAc;YACrC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,aAAa;oBAAE,OAAO;gBACzC,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,gBAAgB,CAAC,KAAK;YAC1B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;YACrB,6BAA6B;YAC7B,2DAA2D;YAC3D,+DAA+D;YAC/D,+DAA+D;YAC/D,yDAAyD;YACzD,gEAAgE;YAChE,mDAAmD;YACnD,gEAAgE;YAChE,+DAA+D;YAC/D,wBAAwB;YACxB,EAAE;YACF,+DAA+D;YAC/D,yDAAyD;YACzD,IAAI,WAAoB,CAAC;YACzB,IAAI,QAAiB,CAAC;YACtB,IAAI,CAAC;gBACH,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBAC1C,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,WAAW,CAAC;oBACrC,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,QAAQ,CAAC;iBACnC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YAED,6DAA6D;YAC7D,IAAI,sBAAsB,GAAkB,IAAI,CAAC;YACjD,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC/B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;oBAC/B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;wBAAE,SAAS;oBAChD,MAAM,CAAC,GAAG,IAA+B,CAAC;oBAC1C,IAAI,CAAC,CAAC,cAAc,CAAC,KAAK,mBAAmB,IAAI,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;wBAC7E,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;oBACnC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,+DAA+D;YAC/D,iEAAiE;YACjE,iEAAiE;YACjE,iDAAiD;YACjD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC1C,MAAM,GAAG,GAAG;gBACV,YAAY,EAAE,IAAqB;gBACnC,gBAAgB,EAAE,IAAqB;gBACvC,WAAW,EAAE,IAAqB;gBAClC,iBAAiB,EAAE,IAAqB;gBACxC,gBAAgB,EAAE,IAAqB;gBACvC,eAAe,EAAE,IAAqB;gBACtC,aAAa,EAAE,IAAqB;aACrC,CAAC;YACF,MAAM,OAAO,GAAG,CAAC,GAAqB,EAAE,CAAU,EAAQ,EAAE;gBAC1D,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,OAAO;gBAClC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACjC,CAAC,CAAC;YACF,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,SAAS;gBAChD,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,CAAC,GAAG,IAA+B,CAAC;gBAC1C,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;gBAC5C,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBACpD,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;gBAC1C,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC;gBACvD,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBACrD,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACpD,CAAC;YACD,IAAI,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAC;YAC1B,OAAO;gBACL,sBAAsB;gBACtB,GAAG,GAAG;aACP,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,iBAAiB,CAAC,IAAI;YAC1B,mEAAmE;YACnE,sDAAsD;YACtD,MAAM,KAAK,GAAkB,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC;YAE/D,mEAAmE;YACnE,8DAA8D;YAC9D,4DAA4D;YAC5D,qEAAqE;YACrE,wDAAwD;YACxD,kEAAkE;YAClE,+DAA+D;YAC/D,iEAAiE;YACjE,gCAAgC;YAChC,EAAE;YACF,iEAAiE;YACjE,mEAAmE;YACnE,aAAa;YACb,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC9C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,OAAO,EAAE,CAAC;gBAChB,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,+DAA+D;YAC/D,kDAAkD;YAClD,8DAA8D;YAC9D,+DAA+D;YAC/D,4DAA4D;YAC5D,8DAA8D;YAC9D,6DAA6D;YAC7D,6DAA6D;YAC7D,4DAA4D;YAC5D,uDAAuD;YACvD,qBAAqB;YACrB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;YAC9C,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;gBACrD,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;oBAC5B,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,QAAQ,CAAC;gBACxC,CAAC;YACH,CAAC;YAED,gEAAgE;YAChE,8DAA8D;YAC9D,gEAAgE;YAChE,iEAAiE;YACjE,4DAA4D;YAC5D,+DAA+D;YAC/D,2DAA2D;YAC3D,+DAA+D;YAC/D,6DAA6D;YAC7D,8BAA8B;YAC9B,IAAI,CAAC;gBACH,oBAAoB,CAAC;oBACnB,OAAO,EAAE,IAAI,CAAC,YAAY;oBAC1B,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;iBACzC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,oCAAoC;YACtC,CAAC;YAED,+DAA+D;YAC/D,2DAA2D;YAC3D,8DAA8D;YAC9D,wDAAwD;YACxD,yDAAyD;YACzD,0DAA0D;YAC1D,0DAA0D;YAC1D,EAAE;YACF,iEAAiE;YACjE,2DAA2D;YAC3D,0CAA0C;YAC1C,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;gBAC7C,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;gBACpD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBACrD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;YAC9D,CAAC;YAED,mEAAmE;YACnE,8DAA8D;YAC9D,mBAAmB;YACnB,MAAM,WAAW,GAAW,IAAI,CAAC,WAAW,CAAC;YAE7C,yCAAyC;YACzC,EAAE;YACF,mEAAmE;YACnE,kEAAkE;YAClE,iEAAiE;YACjE,gEAAgE;YAChE,EAAE;YACF,kEAAkE;YAClE,gEAAgE;YAChE,mDAAmD;YACnD,MAAM,eAAe,GACnB,IAAI,CAAC,GAAG,KAAK,SAAS;gBACpB,CAAC,CAAC,CAAC,GAAG,uBAAuB,EAAE,GAAG,gBAAgB,CAAC;gBACnD,CAAC,CAAC,CAAC,GAAG,uBAAuB,CAAC,CAAC;YAEnC,IAAI,OAAO,GAAmB,IAAI,CAAC;YACnC,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE;oBACpC,cAAc,EAAE,mBAAmB;oBACnC,YAAY,EAAE,EAAE;oBAChB,kBAAkB,EAAE,KAAK;oBACzB,YAAY,EAAE,MAAM;oBACpB,gEAAgE;oBAChE,+DAA+D;oBAC/D,4DAA4D;oBAC5D,+DAA+D;oBAC/D,4DAA4D;oBAC5D,wDAAwD;oBACxD,EAAE;oBACF,6DAA6D;oBAC7D,yDAAyD;oBACzD,4DAA4D;oBAC5D,8DAA8D;oBAC9D,oDAAoD;oBACpD,6BAA6B;oBAC7B,eAAe;oBACf,8DAA8D;oBAC9D,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrD,CAAC,CAAC;gBACH,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,8DAA8D;gBAC9D,+DAA+D;gBAC/D,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,CAAC;wBACH,OAAO,CAAC,KAAK,EAAE,CAAC;oBAClB,CAAC;oBAAC,MAAM,CAAC;wBACP,cAAc;oBAChB,CAAC;gBACH,CAAC;gBACD,KAAK,CAAC,OAAO,EAAE,CAAC;gBAChB,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,MAAM,aAAa,GAAG,OAAO,CAAC;YAC9B,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,OAAO;gBACL,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE;gBAC9B,KAAK,CAAC,KAAK;oBACT,IAAI,CAAC;wBACH,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC;oBAC9B,CAAC;oBAAC,MAAM,CAAC;wBACP,wDAAwD;wBACxD,qDAAqD;oBACvD,CAAC;gBACH,CAAC;gBACD,KAAK;oBACH,IAAI,MAAM;wBAAE,OAAO;oBACnB,MAAM,GAAG,IAAI,CAAC;oBACd,IAAI,CAAC;wBACH,aAAa,CAAC,KAAK,EAAE,CAAC;oBACxB,CAAC;oBAAC,MAAM,CAAC;wBACP,cAAc;oBAChB,CAAC;oBACD,KAAK,CAAC,OAAO,EAAE,CAAC;gBAClB,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}