@letta-ai/letta-agent-sdk 0.3.2 → 0.3.3

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 (49) hide show
  1. package/AGENTS.md +47 -0
  2. package/README.md +17 -0
  3. package/dist/client-entry.js +800 -732
  4. package/dist/client-entry.js.map +8 -5
  5. package/dist/cloud-sandbox.d.ts +33 -0
  6. package/dist/cloud-sandbox.d.ts.map +1 -0
  7. package/dist/cloud-session.d.ts.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +799 -732
  11. package/dist/index.js.map +9 -6
  12. package/dist/remote-client-session-core.d.ts +6 -93
  13. package/dist/remote-client-session-core.d.ts.map +1 -1
  14. package/dist/remote-session-protocol.d.ts +130 -0
  15. package/dist/remote-session-protocol.d.ts.map +1 -0
  16. package/dist/remote-turn-coordinator.d.ts +49 -0
  17. package/dist/remote-turn-coordinator.d.ts.map +1 -0
  18. package/dist/types.d.ts +2 -20
  19. package/dist/types.d.ts.map +1 -1
  20. package/package.json +5 -2
  21. package/src/app-server-management.ts +641 -0
  22. package/src/app-server-session.ts +948 -0
  23. package/src/cli-resolver.ts +46 -0
  24. package/src/client-base.ts +482 -0
  25. package/src/client-entry.ts +31 -0
  26. package/src/client.ts +138 -0
  27. package/src/cloud-management.ts +360 -0
  28. package/src/cloud-sandbox.ts +117 -0
  29. package/src/cloud-session.ts +1313 -0
  30. package/src/index.ts +440 -0
  31. package/src/interactiveToolPolicy.ts +62 -0
  32. package/src/local-app-server-session.ts +39 -0
  33. package/src/local-app-server.ts +137 -0
  34. package/src/management-types.ts +133 -0
  35. package/src/management.ts +206 -0
  36. package/src/protocol.ts +249 -0
  37. package/src/remote-client-session-core.ts +786 -0
  38. package/src/remote-session-protocol.ts +660 -0
  39. package/src/remote-turn-coordinator.ts +505 -0
  40. package/src/remote.ts +177 -0
  41. package/src/repositories.ts +340 -0
  42. package/src/request-ids.ts +33 -0
  43. package/src/session.ts +1638 -0
  44. package/src/stream-events.ts +88 -0
  45. package/src/tool-helpers.ts +147 -0
  46. package/src/transport.ts +484 -0
  47. package/src/types.ts +1328 -0
  48. package/src/validation.ts +223 -0
  49. package/src/websocket.ts +22 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * SDK Validation
3
+ *
4
+ * Validates user-provided options before spawning the CLI.
5
+ */
6
+
7
+ import type {
8
+ CreateSessionOptions,
9
+ CreateAgentOptions,
10
+ MemoryItem,
11
+ CreateBlock,
12
+ SystemPromptPreset,
13
+ SkillSource,
14
+ DreamingOptions,
15
+ } from "./types.js";
16
+
17
+ const VALID_SKILL_SOURCES: SkillSource[] = [
18
+ "bundled",
19
+ "global",
20
+ "agent",
21
+ "project",
22
+ ];
23
+
24
+ const VALID_REASONING_EFFORTS = [
25
+ "none",
26
+ "minimal",
27
+ "low",
28
+ "medium",
29
+ "high",
30
+ "xhigh",
31
+ ] as const;
32
+
33
+ /**
34
+ * Extract block labels from memory items.
35
+ */
36
+ function getBlockLabels(memory: MemoryItem[]): string[] {
37
+ return memory
38
+ .map((item) => {
39
+ if (typeof item === "string") return item; // preset name
40
+ if ("label" in item) return (item as CreateBlock).label; // CreateBlock
41
+ return null; // blockId - no label to check
42
+ })
43
+ .filter((label): label is string => label !== null);
44
+ }
45
+
46
+ function validateApprovalRecoveryOptions(options: CreateSessionOptions): void {
47
+ if (
48
+ options.maxApprovalRecoveryAttempts !== undefined &&
49
+ (!Number.isInteger(options.maxApprovalRecoveryAttempts) ||
50
+ options.maxApprovalRecoveryAttempts < 0)
51
+ ) {
52
+ throw new Error(
53
+ "Invalid maxApprovalRecoveryAttempts. Expected a non-negative integer."
54
+ );
55
+ }
56
+
57
+ if (
58
+ options.approvalRecoveryTimeoutMs !== undefined &&
59
+ (!Number.isInteger(options.approvalRecoveryTimeoutMs) ||
60
+ options.approvalRecoveryTimeoutMs <= 0)
61
+ ) {
62
+ throw new Error(
63
+ "Invalid approvalRecoveryTimeoutMs. Expected a positive integer."
64
+ );
65
+ }
66
+ }
67
+
68
+ function validateRemovedSessionOptions(options: CreateSessionOptions): void {
69
+ if ((options as { memfsStartup?: unknown }).memfsStartup !== undefined) {
70
+ throw new Error(
71
+ "memfsStartup is not supported by the SDK.",
72
+ );
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Validate systemPrompt preset value.
78
+ */
79
+ function validateSystemPromptPreset(preset: string): void {
80
+ const validPresets = [
81
+ "default",
82
+ "letta-claude",
83
+ "letta-codex",
84
+ "letta-gemini",
85
+ "claude",
86
+ "codex",
87
+ "gemini",
88
+ ];
89
+ if (!validPresets.includes(preset)) {
90
+ throw new Error(
91
+ `Invalid system prompt preset '${preset}'. ` +
92
+ `Valid presets: ${validPresets.join(", ")}`
93
+ );
94
+ }
95
+ }
96
+
97
+ function validateSkillSources(sources: SkillSource[] | undefined): void {
98
+ if (sources === undefined) {
99
+ return;
100
+ }
101
+
102
+ for (const source of sources) {
103
+ if (!VALID_SKILL_SOURCES.includes(source)) {
104
+ throw new Error(
105
+ `Invalid skill source '${source}'. Valid values: ${VALID_SKILL_SOURCES.join(", ")}`
106
+ );
107
+ }
108
+ }
109
+ }
110
+
111
+ function validateDreamingOptions(dreaming: DreamingOptions | undefined): void {
112
+ if (dreaming === undefined) {
113
+ return;
114
+ }
115
+
116
+ if (
117
+ dreaming.trigger !== undefined &&
118
+ !["off", "step-count", "compaction-event"].includes(dreaming.trigger)
119
+ ) {
120
+ throw new Error(
121
+ `Invalid dreaming.trigger '${String(dreaming.trigger)}'. Valid values: off, step-count, compaction-event`
122
+ );
123
+ }
124
+
125
+ if (
126
+ dreaming.behavior !== undefined &&
127
+ !["reminder", "auto-launch"].includes(dreaming.behavior)
128
+ ) {
129
+ throw new Error(
130
+ `Invalid dreaming.behavior '${String(dreaming.behavior)}'. Valid values: reminder, auto-launch`
131
+ );
132
+ }
133
+
134
+ if (
135
+ dreaming.stepCount !== undefined &&
136
+ (!Number.isInteger(dreaming.stepCount) || dreaming.stepCount <= 0)
137
+ ) {
138
+ throw new Error(
139
+ "Invalid dreaming.stepCount. Expected a positive integer."
140
+ );
141
+ }
142
+ }
143
+
144
+ function validateReasoningEffort(value: unknown): void {
145
+ if (value === undefined) return;
146
+ if (
147
+ typeof value !== "string" ||
148
+ !VALID_REASONING_EFFORTS.includes(value as (typeof VALID_REASONING_EFFORTS)[number])
149
+ ) {
150
+ throw new Error(
151
+ `Invalid reasoningEffort '${String(value)}'. Valid values: ${VALID_REASONING_EFFORTS.join(", ")}`
152
+ );
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Validate CreateSessionOptions (used by createSession and resumeSession).
158
+ */
159
+ export function validateCreateSessionOptions(options: CreateSessionOptions): void {
160
+ // Validate systemPrompt preset if provided
161
+ if (options.systemPrompt !== undefined) {
162
+ validateSystemPromptPreset(options.systemPrompt);
163
+ }
164
+
165
+ validateSkillSources(options.skillSources);
166
+ validateReasoningEffort(options.reasoningEffort);
167
+ validateDreamingOptions(options.dreaming);
168
+ validateApprovalRecoveryOptions(options);
169
+ validateRemovedSessionOptions(options);
170
+ }
171
+
172
+ /**
173
+ * Validate CreateAgentOptions (used by createAgent).
174
+ */
175
+ export function validateCreateAgentOptions(options: CreateAgentOptions): void {
176
+ // Validate memory/persona consistency
177
+ if (options.memory !== undefined) {
178
+ const blockLabels = getBlockLabels(options.memory);
179
+
180
+ if (options.persona !== undefined && !blockLabels.includes("persona")) {
181
+ throw new Error(
182
+ "Cannot set 'persona' value - block not included in 'memory'. " +
183
+ "Either add 'persona' to memory array or remove the persona option."
184
+ );
185
+ }
186
+
187
+ if (options.human !== undefined && !blockLabels.includes("human")) {
188
+ throw new Error(
189
+ "Cannot set 'human' value - block not included in 'memory'. " +
190
+ "Either add 'human' to memory array or remove the human option."
191
+ );
192
+ }
193
+ }
194
+
195
+ // Validate systemPrompt preset if provided as preset object
196
+ if (
197
+ options.systemPrompt !== undefined &&
198
+ typeof options.systemPrompt === "object"
199
+ ) {
200
+ validateSystemPromptPreset(options.systemPrompt.preset);
201
+ } else if (
202
+ options.systemPrompt !== undefined &&
203
+ typeof options.systemPrompt === "string"
204
+ ) {
205
+ // Check if it's a preset name (if so, validate it)
206
+ const validPresets = [
207
+ "default",
208
+ "letta-claude",
209
+ "letta-codex",
210
+ "letta-gemini",
211
+ "claude",
212
+ "codex",
213
+ "gemini",
214
+ ] as const;
215
+ if (validPresets.includes(options.systemPrompt as SystemPromptPreset)) {
216
+ validateSystemPromptPreset(options.systemPrompt);
217
+ }
218
+ // If not a preset, it's a custom string - no validation needed
219
+ }
220
+
221
+ validateSkillSources(options.skillSources);
222
+ validateDreamingOptions(options.dreaming);
223
+ }
@@ -0,0 +1,22 @@
1
+ import type {
2
+ LettaCodeReactNativeSocketConstructor,
3
+ LettaCodeSocketConstructor,
4
+ LettaCodeSocketOptions,
5
+ } from "./types.js";
6
+
7
+ /**
8
+ * Adapt React Native's three-argument WebSocket constructor to the SDK's
9
+ * Node-compatible constructor shape. This is only needed when a remote
10
+ * app-server authenticates its websocket upgrade with headers. Cloud clients
11
+ * should prefer `webSocketAuth: "query"`.
12
+ */
13
+ export function createReactNativeWebSocketConstructor(
14
+ WebSocket: LettaCodeReactNativeSocketConstructor,
15
+ ): LettaCodeSocketConstructor {
16
+ class ReactNativeWebSocketAdapter {
17
+ constructor(url: string, options?: LettaCodeSocketOptions) {
18
+ return new WebSocket(url, undefined, options);
19
+ }
20
+ }
21
+ return ReactNativeWebSocketAdapter as unknown as LettaCodeSocketConstructor;
22
+ }