@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.
- package/dist/auth/argon2.d.ts +72 -0
- package/dist/auth/argon2.d.ts.map +1 -0
- package/dist/auth/argon2.js +145 -0
- package/dist/auth/argon2.js.map +1 -0
- package/dist/auth/encryption.d.ts +52 -0
- package/dist/auth/encryption.d.ts.map +1 -0
- package/dist/auth/encryption.js +98 -0
- package/dist/auth/encryption.js.map +1 -0
- package/dist/auth/jwt.d.ts +133 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +147 -0
- package/dist/auth/jwt.js.map +1 -0
- package/dist/auth/middleware.d.ts +101 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +161 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/passwordPolicy.d.ts +72 -0
- package/dist/auth/passwordPolicy.d.ts.map +1 -0
- package/dist/auth/passwordPolicy.js +88 -0
- package/dist/auth/passwordPolicy.js.map +1 -0
- package/dist/auth/roleRules.d.ts +200 -0
- package/dist/auth/roleRules.d.ts.map +1 -0
- package/dist/auth/roleRules.js +365 -0
- package/dist/auth/roleRules.js.map +1 -0
- package/dist/auth/userView.d.ts +55 -0
- package/dist/auth/userView.d.ts.map +1 -0
- package/dist/auth/userView.js +77 -0
- package/dist/auth/userView.js.map +1 -0
- package/dist/bootstrap.d.ts +104 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +160 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/db/connection.d.ts +39 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +62 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/migrate.d.ts +31 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +197 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/schema.d.ts +1902 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +662 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/seed.d.ts +92 -0
- package/dist/db/seed.d.ts.map +1 -0
- package/dist/db/seed.js +160 -0
- package/dist/db/seed.js.map +1 -0
- package/dist/handlers/fetch.d.ts +89 -0
- package/dist/handlers/fetch.d.ts.map +1 -0
- package/dist/handlers/fetch.js +173 -0
- package/dist/handlers/fetch.js.map +1 -0
- package/dist/handlers/nextjs.d.ts +40 -0
- package/dist/handlers/nextjs.d.ts.map +1 -0
- package/dist/handlers/nextjs.js +42 -0
- package/dist/handlers/nextjs.js.map +1 -0
- package/dist/handlers/responses.d.ts +46 -0
- package/dist/handlers/responses.d.ts.map +1 -0
- package/dist/handlers/responses.js +74 -0
- package/dist/handlers/responses.js.map +1 -0
- package/dist/handlers/routeTable.d.ts +21 -0
- package/dist/handlers/routeTable.d.ts.map +1 -0
- package/dist/handlers/routeTable.js +133 -0
- package/dist/handlers/routeTable.js.map +1 -0
- package/dist/handlers/router.d.ts +37 -0
- package/dist/handlers/router.d.ts.map +1 -0
- package/dist/handlers/router.js +82 -0
- package/dist/handlers/router.js.map +1 -0
- package/dist/handlers/sse.d.ts +38 -0
- package/dist/handlers/sse.d.ts.map +1 -0
- package/dist/handlers/sse.js +52 -0
- package/dist/handlers/sse.js.map +1 -0
- package/dist/handlers/types.d.ts +96 -0
- package/dist/handlers/types.d.ts.map +1 -0
- package/dist/handlers/types.js +14 -0
- package/dist/handlers/types.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/letta/client.d.ts +355 -0
- package/dist/letta/client.d.ts.map +1 -0
- package/dist/letta/client.js +529 -0
- package/dist/letta/client.js.map +1 -0
- package/dist/letta/eventTranslator.d.ts +166 -0
- package/dist/letta/eventTranslator.d.ts.map +1 -0
- package/dist/letta/eventTranslator.js +532 -0
- package/dist/letta/eventTranslator.js.map +1 -0
- package/dist/letta/index.d.ts +13 -0
- package/dist/letta/index.d.ts.map +1 -0
- package/dist/letta/index.js +12 -0
- package/dist/letta/index.js.map +1 -0
- package/dist/letta/modelSettings.d.ts +176 -0
- package/dist/letta/modelSettings.d.ts.map +1 -0
- package/dist/letta/modelSettings.js +314 -0
- package/dist/letta/modelSettings.js.map +1 -0
- package/dist/letta/promptWrapping.d.ts +141 -0
- package/dist/letta/promptWrapping.d.ts.map +1 -0
- package/dist/letta/promptWrapping.js +213 -0
- package/dist/letta/promptWrapping.js.map +1 -0
- package/dist/letta/sandbox.d.ts +100 -0
- package/dist/letta/sandbox.d.ts.map +1 -0
- package/dist/letta/sandbox.js +151 -0
- package/dist/letta/sandbox.js.map +1 -0
- package/dist/letta/settingsFileSeed.d.ts +146 -0
- package/dist/letta/settingsFileSeed.d.ts.map +1 -0
- package/dist/letta/settingsFileSeed.js +177 -0
- package/dist/letta/settingsFileSeed.js.map +1 -0
- package/dist/letta/subprocessThrottle.d.ts +151 -0
- package/dist/letta/subprocessThrottle.d.ts.map +1 -0
- package/dist/letta/subprocessThrottle.js +195 -0
- package/dist/letta/subprocessThrottle.js.map +1 -0
- package/dist/letta/tpmRecovery.d.ts +202 -0
- package/dist/letta/tpmRecovery.d.ts.map +1 -0
- package/dist/letta/tpmRecovery.js +314 -0
- package/dist/letta/tpmRecovery.js.map +1 -0
- package/dist/letta/types.d.ts +54 -0
- package/dist/letta/types.d.ts.map +1 -0
- package/dist/letta/types.js +16 -0
- package/dist/letta/types.js.map +1 -0
- package/dist/observability/logger.d.ts +48 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +81 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +53 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +92 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/routes/admin/agents.d.ts +63 -0
- package/dist/routes/admin/agents.d.ts.map +1 -0
- package/dist/routes/admin/agents.js +461 -0
- package/dist/routes/admin/agents.js.map +1 -0
- package/dist/routes/admin/rotatingMessages.d.ts +51 -0
- package/dist/routes/admin/rotatingMessages.d.ts.map +1 -0
- package/dist/routes/admin/rotatingMessages.js +292 -0
- package/dist/routes/admin/rotatingMessages.js.map +1 -0
- package/dist/routes/admin/sessions.d.ts +61 -0
- package/dist/routes/admin/sessions.d.ts.map +1 -0
- package/dist/routes/admin/sessions.js +232 -0
- package/dist/routes/admin/sessions.js.map +1 -0
- package/dist/routes/admin/settings.d.ts +110 -0
- package/dist/routes/admin/settings.d.ts.map +1 -0
- package/dist/routes/admin/settings.js +401 -0
- package/dist/routes/admin/settings.js.map +1 -0
- package/dist/routes/admin/users.d.ts +115 -0
- package/dist/routes/admin/users.d.ts.map +1 -0
- package/dist/routes/admin/users.js +374 -0
- package/dist/routes/admin/users.js.map +1 -0
- package/dist/routes/agents.d.ts +30 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +55 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/auth.d.ts +121 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +422 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/chat.d.ts +97 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +484 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/featureToggles.d.ts +34 -0
- package/dist/routes/featureToggles.d.ts.map +1 -0
- package/dist/routes/featureToggles.js +47 -0
- package/dist/routes/featureToggles.js.map +1 -0
- package/dist/routes/health.d.ts +24 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +37 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/metrics.d.ts +35 -0
- package/dist/routes/metrics.d.ts.map +1 -0
- package/dist/routes/metrics.js +106 -0
- package/dist/routes/metrics.js.map +1 -0
- package/dist/routes/sessions.d.ts +161 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +1501 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/stubs.d.ts +25 -0
- package/dist/routes/stubs.d.ts.map +1 -0
- package/dist/routes/stubs.js +25 -0
- package/dist/routes/stubs.js.map +1 -0
- package/dist/state/cron.d.ts +58 -0
- package/dist/state/cron.d.ts.map +1 -0
- package/dist/state/cron.js +160 -0
- package/dist/state/cron.js.map +1 -0
- package/dist/state/rotationRunner.d.ts +96 -0
- package/dist/state/rotationRunner.d.ts.map +1 -0
- package/dist/state/rotationRunner.js +246 -0
- package/dist/state/rotationRunner.js.map +1 -0
- package/dist/state/rotationScheduler.d.ts +76 -0
- package/dist/state/rotationScheduler.d.ts.map +1 -0
- package/dist/state/rotationScheduler.js +124 -0
- package/dist/state/rotationScheduler.js.map +1 -0
- package/dist/state/turnRegistry.d.ts +95 -0
- package/dist/state/turnRegistry.d.ts.map +1 -0
- package/dist/state/turnRegistry.js +149 -0
- package/dist/state/turnRegistry.js.map +1 -0
- package/dist/state/turnRunner.d.ts +134 -0
- package/dist/state/turnRunner.d.ts.map +1 -0
- package/dist/state/turnRunner.js +476 -0
- package/dist/state/turnRunner.js.map +1 -0
- package/package.json +47 -0
- package/src/auth/argon2.ts +152 -0
- package/src/auth/encryption.ts +110 -0
- package/src/auth/jwt.ts +217 -0
- package/src/auth/middleware.ts +250 -0
- package/src/auth/passwordPolicy.ts +99 -0
- package/src/auth/roleRules.ts +497 -0
- package/src/auth/userView.ts +88 -0
- package/src/bootstrap.ts +254 -0
- package/src/db/connection.ts +75 -0
- package/src/db/migrate.ts +212 -0
- package/src/db/schema.ts +750 -0
- package/src/db/seed.ts +236 -0
- package/src/handlers/fetch.ts +251 -0
- package/src/handlers/nextjs.ts +49 -0
- package/src/handlers/responses.ts +95 -0
- package/src/handlers/routeTable.ts +188 -0
- package/src/handlers/router.ts +96 -0
- package/src/handlers/sse.ts +55 -0
- package/src/handlers/types.ts +104 -0
- package/src/index.ts +60 -0
- package/src/letta/client.ts +860 -0
- package/src/letta/eventTranslator.ts +667 -0
- package/src/letta/index.ts +46 -0
- package/src/letta/lettaCliShim.mjs +40 -0
- package/src/letta/sandbox.ts +167 -0
- package/src/letta/settingsFileSeed.ts +254 -0
- package/src/letta/subprocessThrottle.ts +251 -0
- package/src/letta/types.ts +65 -0
- package/src/observability/logger.ts +103 -0
- package/src/observability/metrics.ts +114 -0
- package/src/routes/admin/agents.ts +574 -0
- package/src/routes/admin/rotatingMessages.ts +351 -0
- package/src/routes/admin/sessions.ts +283 -0
- package/src/routes/admin/settings.ts +463 -0
- package/src/routes/admin/users.ts +455 -0
- package/src/routes/agents.ts +66 -0
- package/src/routes/auth.ts +513 -0
- package/src/routes/chat.ts +534 -0
- package/src/routes/featureToggles.ts +52 -0
- package/src/routes/health.ts +44 -0
- package/src/routes/metrics.ts +111 -0
- package/src/routes/sessions.ts +1878 -0
- package/src/state/cron.ts +179 -0
- package/src/state/rotationRunner.ts +326 -0
- package/src/state/rotationScheduler.ts +164 -0
- package/src/state/turnRegistry.ts +210 -0
- package/src/state/turnRunner.ts +588 -0
package/dist/index.d.ts
ADDED
|
@@ -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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,eAEN,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EACb,KAAK,UAAU,EAEhB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEpF;;;;;;;;;GASG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aACpB,cAAc,EAAE,MAAM;gBAAtB,cAAc,EAAE,MAAM;CAInD;AA0ED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;OAeG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAClC;;;;OAIG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;OASG;IACH,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAC3C,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,2EAA2E;QAC3E,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC,CAAC;IACV;;;;;;;OAOG;IACH,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE;;;;;;;;;;;;;OAaG;IACH,oBAAoB,CAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACnD;;;;;;;;;;;;;;;;;OAiBG;IACH,gBAAgB,CACd,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C;;;;;;;OAOG;IACH,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3E;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE;;;;;;;OAOG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACzE;AAMD,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IACpC,sBAAsB;IACtB,EAAE,EAAE,SAAS,CAAC;IACd,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,kBAAkB,EAAE,kBAAkB,CAAC;IACvC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,eAAe,CAAC;IACxC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,aAAa,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,qBAAqB,GAC1B,WAAW,CA2Yb;AAMD,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|