@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,176 @@
1
+ /**
2
+ * Provider-specific `model_settings` construction for `agents.update()`.
3
+ *
4
+ * This module is a near-verbatim port of Letta Code CLI's `buildModelSettings2`
5
+ * function (in `@letta-ai/letta-code` v0.19.5, bundled in `letta.js`). The goal
6
+ * is to mirror Letta's own translation from a logical
7
+ * `(modelHandle, updateArgs)` choice to the wire shape the server accepts —
8
+ * so when Letta changes that mapping (new providers, new fields, renamed
9
+ * enums), we copy the diff instead of re-deriving the logic.
10
+ *
11
+ * Provider routing (from CLI source):
12
+ *
13
+ * openai/ | openrouter/ → OpenAIModelSettings
14
+ * anthropic/ | claude-pro-max/ | minimax/ → AnthropicModelSettings
15
+ * zai/ → ZaiModelSettings (no reasoning knobs)
16
+ * google_ai/ → GoogleAIModelSettings
17
+ * google_vertex/ → GoogleVertexModelSettings
18
+ * bedrock/ → BedrockModelSettings
19
+ * <anything else> → OpenAI-shaped fallback
20
+ *
21
+ * Reasoning input: a unified `reasoning_effort` enum
22
+ * `"none" | "minimal" | "low" | "medium" | "high" | "xhigh"`
23
+ * is translated per provider:
24
+ *
25
+ * Anthropic / Bedrock — emits `model_settings.effort` (with `xhigh` mapped
26
+ * to `"max"`). `thinking` is omitted entirely UNLESS the caller also sets
27
+ * `enable_reasoner` or `max_reasoning_tokens` — letting the model handle
28
+ * thinking decisions implicitly (Opus 4.7+ behavior).
29
+ * OpenAI / OpenRouter — emits `model_settings.reasoning.reasoning_effort`,
30
+ * plus optional `verbosity` and `strict`.
31
+ * Google AI / Vertex — emits `thinking_config.thinking_budget` (numeric),
32
+ * not the effort enum.
33
+ * Z.AI — no reasoning surface (CLI exposes none either).
34
+ *
35
+ * Source-of-truth callout: when Letta releases a new CLI version, diff
36
+ * `@letta-ai/letta-code/letta.js → buildModelSettings2` against this file.
37
+ *
38
+ * @see tmp/letta-research/letta-code-sdk — cloned SDK source for inspection
39
+ * @see node_modules/@letta-ai/letta-code/letta.js — CLI bundle (search
40
+ * `function buildModelSettings2`)
41
+ */
42
+ import type { AnthropicModelSettings, BedrockModelSettings, GoogleAIModelSettings, GoogleVertexModelSettings, OpenAIModelSettings, XaiModelSettings } from "@letta-ai/letta-client/resources/agents/agents.js";
43
+ /** Unified reasoning-effort input. Provider mapping happens in `buildModelSettings`.
44
+ *
45
+ * - `"off"` — the unified-UX "no reasoning" tier; for Google maps to budget=0,
46
+ * for Anthropic-shape providers no `effort` field is sent (the agent's
47
+ * `enable_reasoner` flag controls whether reasoning runs at all).
48
+ * - `"none"` / `"minimal"` — OpenAI-only tiers, passed through verbatim.
49
+ * - `"low"` / `"medium"` / `"high"` / `"xhigh"` — universal tiers.
50
+ * Anthropic's `xhigh` is translated to `"max"` at the wire level.
51
+ */
52
+ export type ReasoningEffort = "off" | "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
53
+ /** Verbosity input (used by OpenAI-shape providers — GPT-5.x family). */
54
+ export type Verbosity = "low" | "medium" | "high";
55
+ /**
56
+ * Logical input shape — matches Letta Code's `updateArgs` exactly.
57
+ *
58
+ * The intent: callers describe the AGENT's intended configuration in
59
+ * provider-agnostic terms, and `buildModelSettings()` produces the right
60
+ * `*ModelSettings` discriminated-union member for the wire.
61
+ */
62
+ export interface ModelUpdateArgs {
63
+ reasoning_effort?: ReasoningEffort | null;
64
+ enable_reasoner?: boolean;
65
+ max_reasoning_tokens?: number;
66
+ thinking_budget?: number;
67
+ verbosity?: Verbosity;
68
+ max_output_tokens?: number | null;
69
+ parallel_tool_calls?: boolean;
70
+ strict?: boolean;
71
+ temperature?: number;
72
+ context_window?: number;
73
+ }
74
+ /**
75
+ * Discriminated union — wire-shape returned by `buildModelSettings()`. This is
76
+ * the same union the Letta SDK accepts on `agents.update({ model_settings })`.
77
+ */
78
+ export type ModelSettings = OpenAIModelSettings | AnthropicModelSettings | GoogleAIModelSettings | GoogleVertexModelSettings | BedrockModelSettings | XaiModelSettings | {
79
+ provider_type: "zai";
80
+ parallel_tool_calls?: boolean;
81
+ };
82
+ /**
83
+ * Resolves a model handle's provider family. Matches Letta Code's
84
+ * `startsWith` checks exactly.
85
+ *
86
+ * @param modelHandle — the agent's `model` field (e.g. `"anthropic/claude-opus-4-6"`).
87
+ */
88
+ export declare function getProviderFamily(modelHandle: string): ProviderFamily;
89
+ export type ProviderFamily = "openai" | "anthropic" | "zai" | "google_ai" | "google_vertex" | "bedrock" | "openai_compatible";
90
+ /**
91
+ * The unified UI effort tiers, ordered low → high. `"off"` always maps to a
92
+ * zero / disabled state; the other tiers are proportionally distributed
93
+ * between 0 and the model's max budget for budget-based providers.
94
+ *
95
+ * For enum-based providers (Anthropic, OpenAI), the tier name is passed
96
+ * through directly to the wire field (`effort` / `reasoning_effort`), with
97
+ * Anthropic's `xhigh` → `max` translation handled at the call site.
98
+ */
99
+ export declare const EFFORT_TIERS: readonly ["off", "low", "medium", "high", "xhigh", "max"];
100
+ export type EffortTier = (typeof EFFORT_TIERS)[number];
101
+ /**
102
+ * Maps a unified effort tier + a model handle to a concrete thinking-token
103
+ * budget. Returns `undefined` when the provider doesn't take a numeric budget
104
+ * (the caller should fall back to the enum field instead).
105
+ */
106
+ export declare function effortTierToThinkingBudget(modelHandle: string, tier: EffortTier): number | undefined;
107
+ /**
108
+ * Translates a logical `(modelHandle, args)` selection into the wire-shape
109
+ * `model_settings` object Letta expects on `agents.update()`.
110
+ *
111
+ * **Keep in sync** with Letta Code's `buildModelSettings2` — see file header.
112
+ *
113
+ * @param modelHandle — provider-prefixed handle (e.g. `"anthropic/claude-opus-4-6"`).
114
+ * @param args — logical update arguments (effort, verbosity, budgets, etc.).
115
+ * @returns the right discriminated-union member for the wire.
116
+ */
117
+ export declare function buildModelSettings(modelHandle: string, args: ModelUpdateArgs): ModelSettings;
118
+ /**
119
+ * Describes which reasoning knobs are settable for a given model handle.
120
+ * Drives ai-hub's per-model UI: if `effort` is omitted, no "Reasoning"
121
+ * dropdown is rendered for the agent; if `verbosity` is present, a separate
122
+ * "Verbosity" dropdown is rendered alongside; etc.
123
+ *
124
+ * The enums returned here MIRROR Letta's SDK `*ModelSettings` types — when
125
+ * Letta adds new values (e.g. `"ultra"` to `effort`), we copy the diff and
126
+ * the UI picks it up automatically.
127
+ */
128
+ export interface ReasoningCapabilities {
129
+ /**
130
+ * Unified "Reasoning" dropdown — used for `anthropic/*`, `bedrock/*`, and
131
+ * `google_ai/*` / `google_vertex/*`. The enum is one of:
132
+ *
133
+ * - `["low","medium","high","xhigh","max"]` — Anthropic / Bedrock; passed
134
+ * through to `model_settings.effort` (with `xhigh` → `max` translation).
135
+ * - `["off","low","medium","high","xhigh","max"]` — Google AI / Vertex;
136
+ * the server maps the tier to `thinking_config.thinking_budget` as a
137
+ * fraction of the provider's max budget (see `effortTierToThinkingBudget`).
138
+ * `"off"` means budget=0 (no thinking).
139
+ */
140
+ effort?: {
141
+ enum: ReadonlyArray<EffortTier>;
142
+ };
143
+ /**
144
+ * OpenAI-shape reasoning_effort dropdown. Present for `openai/*`,
145
+ * `openrouter/*`, OpenAI-compatible models. UI label: "Reasoning"
146
+ * (separate from "Verbosity").
147
+ */
148
+ reasoning_effort?: {
149
+ enum: ReadonlyArray<"none" | "minimal" | "low" | "medium" | "high" | "xhigh">;
150
+ };
151
+ /**
152
+ * Verbosity dropdown — GPT-5.x / OpenAI shape. Independent from
153
+ * reasoning_effort, rendered as its own UI control.
154
+ */
155
+ verbosity?: {
156
+ enum: ReadonlyArray<Verbosity>;
157
+ };
158
+ /**
159
+ * Google-style thinking budget (numeric). Rendered as a slider/input.
160
+ * Range hints come from Google docs (1024–24576 typical).
161
+ */
162
+ thinking_budget?: {
163
+ min: number;
164
+ max: number;
165
+ };
166
+ }
167
+ /**
168
+ * Computes per-model reasoning capabilities from the model handle. Provider
169
+ * routing matches `buildModelSettings`; the per-field enums mirror Letta's
170
+ * SDK type definitions.
171
+ *
172
+ * @param modelHandle — provider-prefixed handle.
173
+ * @returns capability descriptor — empty object when no reasoning knobs apply.
174
+ */
175
+ export declare function getReasoningCapabilities(modelHandle: string): ReasoningCapabilities;
176
+ //# sourceMappingURL=modelSettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelSettings.d.ts","sourceRoot":"","sources":["../../src/letta/modelSettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,mDAAmD,CAAC;AAM3D;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GACvB,KAAK,GACL,MAAM,GACN,SAAS,GACT,KAAK,GACL,QAAQ,GACR,MAAM,GACN,OAAO,GACP,KAAK,CAAC;AAEV,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,mBAAmB,GACnB,sBAAsB,GACtB,qBAAqB,GACrB,yBAAyB,GACzB,oBAAoB,GACpB,gBAAgB,GAChB;IAAE,aAAa,EAAE,KAAK,CAAC;IAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAM5D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAoBrE;AAED,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,WAAW,GACX,KAAK,GACL,WAAW,GACX,eAAe,GACf,SAAS,GACT,mBAAmB,CAAC;AAuBxB;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,2DAOf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAgBvD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,GACf,MAAM,GAAG,SAAS,CAMpB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,eAAe,GACpB,aAAa,CAqIf;AAMD;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;KACjC,CAAC;IACF;;;;OAIG;IACH,gBAAgB,CAAC,EAAE;QACjB,IAAI,EAAE,aAAa,CACjB,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CACzD,CAAC;KACH,CAAC;IACF;;;OAGG;IACH,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;KAChC,CAAC;IACF;;;OAGG;IACH,eAAe,CAAC,EAAE;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,GAClB,qBAAqB,CA+BvB"}
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Provider-specific `model_settings` construction for `agents.update()`.
3
+ *
4
+ * This module is a near-verbatim port of Letta Code CLI's `buildModelSettings2`
5
+ * function (in `@letta-ai/letta-code` v0.19.5, bundled in `letta.js`). The goal
6
+ * is to mirror Letta's own translation from a logical
7
+ * `(modelHandle, updateArgs)` choice to the wire shape the server accepts —
8
+ * so when Letta changes that mapping (new providers, new fields, renamed
9
+ * enums), we copy the diff instead of re-deriving the logic.
10
+ *
11
+ * Provider routing (from CLI source):
12
+ *
13
+ * openai/ | openrouter/ → OpenAIModelSettings
14
+ * anthropic/ | claude-pro-max/ | minimax/ → AnthropicModelSettings
15
+ * zai/ → ZaiModelSettings (no reasoning knobs)
16
+ * google_ai/ → GoogleAIModelSettings
17
+ * google_vertex/ → GoogleVertexModelSettings
18
+ * bedrock/ → BedrockModelSettings
19
+ * <anything else> → OpenAI-shaped fallback
20
+ *
21
+ * Reasoning input: a unified `reasoning_effort` enum
22
+ * `"none" | "minimal" | "low" | "medium" | "high" | "xhigh"`
23
+ * is translated per provider:
24
+ *
25
+ * Anthropic / Bedrock — emits `model_settings.effort` (with `xhigh` mapped
26
+ * to `"max"`). `thinking` is omitted entirely UNLESS the caller also sets
27
+ * `enable_reasoner` or `max_reasoning_tokens` — letting the model handle
28
+ * thinking decisions implicitly (Opus 4.7+ behavior).
29
+ * OpenAI / OpenRouter — emits `model_settings.reasoning.reasoning_effort`,
30
+ * plus optional `verbosity` and `strict`.
31
+ * Google AI / Vertex — emits `thinking_config.thinking_budget` (numeric),
32
+ * not the effort enum.
33
+ * Z.AI — no reasoning surface (CLI exposes none either).
34
+ *
35
+ * Source-of-truth callout: when Letta releases a new CLI version, diff
36
+ * `@letta-ai/letta-code/letta.js → buildModelSettings2` against this file.
37
+ *
38
+ * @see tmp/letta-research/letta-code-sdk — cloned SDK source for inspection
39
+ * @see node_modules/@letta-ai/letta-code/letta.js — CLI bundle (search
40
+ * `function buildModelSettings2`)
41
+ */
42
+ /* ────────────────────────────────────────────────────────────────────────── */
43
+ /* Provider routing */
44
+ /* ────────────────────────────────────────────────────────────────────────── */
45
+ /**
46
+ * Resolves a model handle's provider family. Matches Letta Code's
47
+ * `startsWith` checks exactly.
48
+ *
49
+ * @param modelHandle — the agent's `model` field (e.g. `"anthropic/claude-opus-4-6"`).
50
+ */
51
+ export function getProviderFamily(modelHandle) {
52
+ if (modelHandle.startsWith("openai/") ||
53
+ modelHandle.startsWith("openai_codex/") ||
54
+ modelHandle.startsWith("openrouter/")) {
55
+ return "openai";
56
+ }
57
+ if (modelHandle.startsWith("anthropic/") ||
58
+ modelHandle.startsWith("claude-pro-max/") ||
59
+ modelHandle.startsWith("minimax/")) {
60
+ return "anthropic";
61
+ }
62
+ if (modelHandle.startsWith("zai/"))
63
+ return "zai";
64
+ if (modelHandle.startsWith("google_ai/"))
65
+ return "google_ai";
66
+ if (modelHandle.startsWith("google_vertex/"))
67
+ return "google_vertex";
68
+ if (modelHandle.startsWith("bedrock/"))
69
+ return "bedrock";
70
+ return "openai_compatible";
71
+ }
72
+ /* ────────────────────────────────────────────────────────────────────────── */
73
+ /* Thinking-budget normalization — unified effort dropdown across providers */
74
+ /* ────────────────────────────────────────────────────────────────────────── */
75
+ /**
76
+ * Per-provider default for the model's maximum thinking-token budget. Used to
77
+ * translate the unified `effort` tier into a concrete `thinking_budget`
78
+ * number for providers that take a budget (Google AI / Vertex).
79
+ *
80
+ * **Not a hardcoded per-model table** — this is a per-provider ceiling; the
81
+ * model's effective max may be lower (e.g. Gemini 2.5 Flash) but Letta will
82
+ * clamp on its side. A future enhancement could read `Model.max_reasoning_tokens`
83
+ * from `client.models.list()` and override when non-zero, plus expose a
84
+ * per-agent override in admin DB. The current value matches Google's
85
+ * published per-model maxes for Gemini 2.5 Pro / Flash (24576).
86
+ */
87
+ const PROVIDER_THINKING_BUDGET_MAX = {
88
+ google_ai: 24576,
89
+ google_vertex: 24576,
90
+ };
91
+ /**
92
+ * The unified UI effort tiers, ordered low → high. `"off"` always maps to a
93
+ * zero / disabled state; the other tiers are proportionally distributed
94
+ * between 0 and the model's max budget for budget-based providers.
95
+ *
96
+ * For enum-based providers (Anthropic, OpenAI), the tier name is passed
97
+ * through directly to the wire field (`effort` / `reasoning_effort`), with
98
+ * Anthropic's `xhigh` → `max` translation handled at the call site.
99
+ */
100
+ export const EFFORT_TIERS = [
101
+ "off",
102
+ "low",
103
+ "medium",
104
+ "high",
105
+ "xhigh",
106
+ "max",
107
+ ];
108
+ /**
109
+ * Fraction of the model's max thinking budget for each tier, used when
110
+ * translating to a budget-based provider. `"off"` → 0; the other five tiers
111
+ * are linearly distributed up to 1.0 (max = full budget).
112
+ */
113
+ const EFFORT_TIER_FRACTION = {
114
+ off: 0,
115
+ low: 0.2,
116
+ medium: 0.4,
117
+ high: 0.6,
118
+ xhigh: 0.8,
119
+ max: 1.0,
120
+ };
121
+ /**
122
+ * Maps a unified effort tier + a model handle to a concrete thinking-token
123
+ * budget. Returns `undefined` when the provider doesn't take a numeric budget
124
+ * (the caller should fall back to the enum field instead).
125
+ */
126
+ export function effortTierToThinkingBudget(modelHandle, tier) {
127
+ const family = getProviderFamily(modelHandle);
128
+ const max = PROVIDER_THINKING_BUDGET_MAX[family];
129
+ if (max === undefined)
130
+ return undefined;
131
+ const fraction = EFFORT_TIER_FRACTION[tier];
132
+ return Math.round(max * fraction);
133
+ }
134
+ /* ────────────────────────────────────────────────────────────────────────── */
135
+ /* buildModelSettings — port of Letta Code's buildModelSettings2 */
136
+ /* ────────────────────────────────────────────────────────────────────────── */
137
+ /**
138
+ * Translates a logical `(modelHandle, args)` selection into the wire-shape
139
+ * `model_settings` object Letta expects on `agents.update()`.
140
+ *
141
+ * **Keep in sync** with Letta Code's `buildModelSettings2` — see file header.
142
+ *
143
+ * @param modelHandle — provider-prefixed handle (e.g. `"anthropic/claude-opus-4-6"`).
144
+ * @param args — logical update arguments (effort, verbosity, budgets, etc.).
145
+ * @returns the right discriminated-union member for the wire.
146
+ */
147
+ export function buildModelSettings(modelHandle, args) {
148
+ const family = getProviderFamily(modelHandle);
149
+ let settings;
150
+ if (family === "openai") {
151
+ const openaiSettings = {
152
+ provider_type: "openai",
153
+ parallel_tool_calls: true,
154
+ };
155
+ if (args.reasoning_effort) {
156
+ // Translate the unified tier to OpenAI's enum. `"off"` maps to
157
+ // `"none"` (OpenAI's spelling); `"max"` is not in OpenAI's enum, so
158
+ // we clamp to `"xhigh"` (the highest OpenAI tier).
159
+ const e = args.reasoning_effort;
160
+ const openaiEffort = e === "off" ? "none" : e === "max" ? "xhigh" : e;
161
+ openaiSettings.reasoning = { reasoning_effort: openaiEffort };
162
+ }
163
+ if (args.verbosity === "low" ||
164
+ args.verbosity === "medium" ||
165
+ args.verbosity === "high") {
166
+ // SDK type lags wire shape — `verbosity` is real on the server but not
167
+ // declared in `OpenAIModelSettings`. Letta Code sends it identically.
168
+ openaiSettings.verbosity = args.verbosity;
169
+ }
170
+ if (typeof args.strict === "boolean")
171
+ openaiSettings.strict = args.strict;
172
+ settings = openaiSettings;
173
+ }
174
+ else if (family === "anthropic") {
175
+ const anthropicSettings = {
176
+ provider_type: "anthropic",
177
+ parallel_tool_calls: true,
178
+ };
179
+ const e = args.reasoning_effort;
180
+ if (e === "low" || e === "medium" || e === "high" || e === "max") {
181
+ anthropicSettings.effort = e;
182
+ }
183
+ else if (e === "xhigh") {
184
+ anthropicSettings.effort = "max";
185
+ }
186
+ if (args.enable_reasoner !== undefined ||
187
+ typeof args.max_reasoning_tokens === "number") {
188
+ anthropicSettings.thinking = {
189
+ type: args.enable_reasoner === false ? "disabled" : "enabled",
190
+ ...(typeof args.max_reasoning_tokens === "number" && {
191
+ budget_tokens: args.max_reasoning_tokens,
192
+ }),
193
+ };
194
+ }
195
+ if (typeof args.strict === "boolean")
196
+ anthropicSettings.strict = args.strict;
197
+ settings = anthropicSettings;
198
+ }
199
+ else if (family === "zai") {
200
+ settings = { provider_type: "zai", parallel_tool_calls: true };
201
+ }
202
+ else if (family === "google_ai" || family === "google_vertex") {
203
+ const baseSettings = {
204
+ provider_type: family,
205
+ parallel_tool_calls: true,
206
+ };
207
+ // Budget resolution priority:
208
+ // 1. Explicit `thinking_budget` (advanced callers / raw control).
209
+ // 2. Unified `reasoning_effort` tier — translated to a fraction of the
210
+ // provider's max budget. This is the path the UI dropdown takes.
211
+ let resolvedBudget;
212
+ if (args.thinking_budget !== undefined) {
213
+ resolvedBudget = args.thinking_budget;
214
+ }
215
+ else if (args.reasoning_effort) {
216
+ // The unified effort enum includes "off" → budget 0; the conversion
217
+ // is done provider-aware so Anthropic/OpenAI tiers don't accidentally
218
+ // hit this path.
219
+ resolvedBudget = effortTierToThinkingBudget(modelHandle, args.reasoning_effort);
220
+ }
221
+ if (resolvedBudget !== undefined) {
222
+ baseSettings.thinking_config = { thinking_budget: resolvedBudget };
223
+ }
224
+ if (typeof args.temperature === "number") {
225
+ baseSettings.temperature = args.temperature;
226
+ }
227
+ settings = baseSettings;
228
+ }
229
+ else if (family === "bedrock") {
230
+ const bedrockSettings = {
231
+ provider_type: "bedrock",
232
+ parallel_tool_calls: true,
233
+ };
234
+ // SDK type lags wire shape for Bedrock — `effort` and `thinking` are
235
+ // real on the server (CLI sends them) but missing from `BedrockModelSettings`.
236
+ const e = args.reasoning_effort;
237
+ const bs = bedrockSettings;
238
+ if (e === "low" || e === "medium" || e === "high" || e === "max") {
239
+ bs.effort = e;
240
+ }
241
+ else if (e === "xhigh") {
242
+ bs.effort = "max";
243
+ }
244
+ if (args.enable_reasoner !== undefined ||
245
+ typeof args.max_reasoning_tokens === "number") {
246
+ bs.thinking = {
247
+ type: args.enable_reasoner === false ? "disabled" : "enabled",
248
+ ...(typeof args.max_reasoning_tokens === "number" && {
249
+ budget_tokens: args.max_reasoning_tokens,
250
+ }),
251
+ };
252
+ }
253
+ settings = bedrockSettings;
254
+ }
255
+ else {
256
+ // OpenAI-compatible fallback (matches CLI's default branch).
257
+ const fallback = {
258
+ provider_type: "openai",
259
+ parallel_tool_calls: typeof args.parallel_tool_calls === "boolean"
260
+ ? args.parallel_tool_calls
261
+ : true,
262
+ };
263
+ if (typeof args.strict === "boolean")
264
+ fallback.strict = args.strict;
265
+ settings = fallback;
266
+ }
267
+ if (typeof args.max_output_tokens === "number" &&
268
+ "provider_type" in settings) {
269
+ settings.max_output_tokens =
270
+ args.max_output_tokens;
271
+ }
272
+ return settings;
273
+ }
274
+ /**
275
+ * Computes per-model reasoning capabilities from the model handle. Provider
276
+ * routing matches `buildModelSettings`; the per-field enums mirror Letta's
277
+ * SDK type definitions.
278
+ *
279
+ * @param modelHandle — provider-prefixed handle.
280
+ * @returns capability descriptor — empty object when no reasoning knobs apply.
281
+ */
282
+ export function getReasoningCapabilities(modelHandle) {
283
+ const family = getProviderFamily(modelHandle);
284
+ switch (family) {
285
+ case "anthropic":
286
+ case "bedrock":
287
+ return {
288
+ effort: { enum: ["low", "medium", "high", "xhigh", "max"] },
289
+ };
290
+ case "openai":
291
+ case "openai_compatible":
292
+ return {
293
+ reasoning_effort: {
294
+ enum: ["none", "minimal", "low", "medium", "high", "xhigh"],
295
+ },
296
+ verbosity: { enum: ["low", "medium", "high"] },
297
+ };
298
+ case "google_ai":
299
+ case "google_vertex":
300
+ // Unified UX: Google models expose the same "Reasoning" dropdown as
301
+ // Anthropic, with `off` mapped to budget=0 and the other tiers
302
+ // proportionally distributed up to the provider's max budget at
303
+ // request time (see `effortTierToThinkingBudget`). The numeric
304
+ // `thinking_budget` knob is still on the type for advanced wrappers
305
+ // that want raw control, but the default selector renders this
306
+ // dropdown instead.
307
+ return {
308
+ effort: { enum: ["off", "low", "medium", "high", "xhigh", "max"] },
309
+ };
310
+ case "zai":
311
+ return {};
312
+ }
313
+ }
314
+ //# sourceMappingURL=modelSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelSettings.js","sourceRoot":"","sources":["../../src/letta/modelSettings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Recency-bias prompt-injection helpers for `streamUserMessage`.
3
+ *
4
+ * **What this is for.** Letta agents are configured in Letta ADE — a non-AI
5
+ * admin writes a plain system prompt there ("You are a Marketing Campaign
6
+ * Analyst…"). We can't ask that admin to think about prompt-injection
7
+ * safety, boundary tokens, or recency bias. So ai-hub takes the admin's
8
+ * prompt verbatim and, under the hood:
9
+ *
10
+ * 1. Appends a generic block of `CRITICAL SECURITY RULES` that tells the
11
+ * LLM how to treat the boundary-tagged user content (don't follow
12
+ * instructions inside it, don't trust XML tags inside it, etc.).
13
+ * 2. Wraps the combined string in `<system_instructions>…</system_instructions>`.
14
+ * 3. XML-escapes the user's typed input so they can't inject closing tags
15
+ * or fake boundary markers.
16
+ * 4. Wraps the escaped user input in `<user_message boundary="MSG_xxx">…
17
+ * </user_message boundary="MSG_xxx">` with a per-request unique boundary
18
+ * token. The closing tag's `boundary="…"` is unusual but lets the LLM
19
+ * pattern-match the closing tag against the opening one, making fake
20
+ * closing tags inside the user content visibly mismatched.
21
+ * 5. Sends the whole concatenated blob as the *user-role* message to
22
+ * Letta, paired with `override_system: "."` so Letta's compiled system
23
+ * message (which would otherwise carry a `<memory_metadata>` block and
24
+ * other scaffolding) doesn't reach the LLM at all.
25
+ *
26
+ * **Why this works better than a separate system role message.** Empirical
27
+ * finding from a related project: LLMs pay the most attention to the most
28
+ * recent turn and drift away from front-of-conversation instructions as
29
+ * the dialogue grows. Re-injecting the full prompt into every user turn
30
+ * pins the instructions back to the front of attention every time.
31
+ * Precision went from ~50% → ~100% on a goal-adherence task by switching
32
+ * to this pattern.
33
+ *
34
+ * **What ADE admins see.** Nothing different. They write their prompt in
35
+ * Letta ADE the normal way; the wrapping is transparent.
36
+ *
37
+ * **What ai-hub UI viewers see.** Nothing different either — the messages
38
+ * route auto-strips the wrapping at render time (see
39
+ * `routes/sessions.ts` and `db/schema.ts#message_override`), so the chat
40
+ * transcript shows the original user text and admin's prompt cleanly.
41
+ */
42
+ /**
43
+ * Escapes the three XML characters that could let a user break out of the
44
+ * `<user_message>` wrapper or inject lookalike tags:
45
+ *
46
+ * - `&` → `&amp;` (must be first so we don't double-escape the others)
47
+ * - `<` → `&lt;`
48
+ * - `>` → `&gt;`
49
+ *
50
+ * We deliberately do NOT escape quotes — the boundary attribute uses
51
+ * double quotes and we don't include any user-controlled values inside
52
+ * attributes, so single/double quotes inside the content are safe to
53
+ * leave as-is. Keeping quotes unescaped makes the chat UI's reverse
54
+ * (un-escape on display) a no-op for the common case.
55
+ *
56
+ * Idempotent on already-escaped strings? No — `&amp;` would become
57
+ * `&amp;amp;`. Callers must escape exactly once, at the wrap step. The
58
+ * matching `unescapeUserInput` function in `routes/sessions.ts` reverses
59
+ * it for display.
60
+ *
61
+ * @param input - raw user text from the chat request.
62
+ * @returns the same text with `&`, `<`, `>` HTML-entity-escaped.
63
+ */
64
+ export declare function escapeUserInput(input: string): string;
65
+ /**
66
+ * Reverses `escapeUserInput` for chat-UI display. Substitutes the three
67
+ * entities back to their literal characters, in the reverse order so
68
+ * `&amp;lt;` (which a user could conceivably have typed before we
69
+ * escaped) round-trips correctly.
70
+ *
71
+ * @param escaped - text previously produced by `escapeUserInput`.
72
+ * @returns the original text with entities decoded.
73
+ */
74
+ export declare function unescapeUserInput(escaped: string): string;
75
+ /**
76
+ * Generates a fresh per-request boundary token. The format is
77
+ * `MSG_<32-char hex>` — a UUID with the dashes stripped, prefixed for
78
+ * human readability in logs / Letta history.
79
+ *
80
+ * The token is high-entropy by construction (UUIDv4 ≈ 122 bits), so a
81
+ * user who wanted to forge a closing tag with the right boundary value
82
+ * would need to guess it. Combined with the rule that the LLM must
83
+ * treat mismatched closing tags as untrusted, this makes
84
+ * boundary-bypass attacks effectively impossible from inside the chat
85
+ * input.
86
+ *
87
+ * @returns a fresh boundary token like `MSG_3fa395bfc67d4b3d859a71a2ee2774f2`.
88
+ */
89
+ export declare function makeBoundary(): string;
90
+ /** Result of `buildWrappedUserMessage`. */
91
+ export interface WrappedUserMessage {
92
+ /** The fully-assembled string to send as the user-role message to Letta. */
93
+ wrapped: string;
94
+ /** The boundary token used in this wrap — logged for audit / debugging. */
95
+ boundary: string;
96
+ }
97
+ /**
98
+ * Assembles the full wrapped user message:
99
+ *
100
+ * ```
101
+ * <system_instructions>
102
+ * {admin's system prompt verbatim}
103
+ *
104
+ * {generic security rules with {boundary} substituted}
105
+ * </system_instructions>
106
+ *
107
+ * <user_message boundary="MSG_xxx">{escaped user input}</user_message boundary="MSG_xxx">
108
+ * ```
109
+ *
110
+ * Pair the output with `override_system: "."` on the Letta request — that
111
+ * tells Letta to bypass its compiled system message so the LLM only sees
112
+ * this wrapped user content as its turn.
113
+ *
114
+ * @param agentSystemPrompt - the admin-authored prompt from Letta ADE
115
+ * (resolved via `LettaClient.getAgentSystemPrompt`). Inserted verbatim
116
+ * — the admin controls this string. No escaping (it isn't user input).
117
+ * @param userMessage - the raw user message text from the chat request.
118
+ * Escaped before insertion.
119
+ * @returns the wrapped string and the boundary token used.
120
+ */
121
+ export declare function buildWrappedUserMessage(agentSystemPrompt: string, userMessage: string): WrappedUserMessage;
122
+ /**
123
+ * Reverses `buildWrappedUserMessage` for chat-UI display. Returns the
124
+ * un-escaped inner user content, or `null` if the input doesn't match
125
+ * the wrapped shape (so callers can fall through to "display as-is").
126
+ *
127
+ * @param wrapped - the string Letta returned as the user-role message
128
+ * content for a turn we wrapped on send.
129
+ * @returns the original user text, or `null` for non-wrapped content.
130
+ */
131
+ export declare function unwrapUserMessage(wrapped: string): string | null;
132
+ /**
133
+ * Removes Letta's `<memory_metadata>` block from a system-message content
134
+ * string for display purposes. Idempotent on already-clean strings.
135
+ *
136
+ * @param content - the raw `system_message` content from Letta.
137
+ * @returns the same content with the trailing memory_metadata block
138
+ * (and any whitespace separating it from the prompt body) stripped.
139
+ */
140
+ export declare function stripMemoryMetadata(content: string): string;
141
+ //# sourceMappingURL=promptWrapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptWrapping.d.ts","sourceRoot":"","sources":["../../src/letta/promptWrapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AA6BH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKzD;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAMD,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,kBAAkB,CAWpB;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIhE;AAaD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D"}