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

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 (70) hide show
  1. package/AGENTS.md +44 -0
  2. package/README.md +29 -0
  3. package/dist/app-server-management.d.ts +3 -48
  4. package/dist/app-server-management.d.ts.map +1 -1
  5. package/dist/app-server-session.d.ts +0 -6
  6. package/dist/app-server-session.d.ts.map +1 -1
  7. package/dist/client-base.d.ts +7 -15
  8. package/dist/client-base.d.ts.map +1 -1
  9. package/dist/client-entry.js +979 -1010
  10. package/dist/client-entry.js.map +15 -11
  11. package/dist/client.d.ts +3 -3
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/cloud-sandbox.d.ts +33 -0
  14. package/dist/cloud-sandbox.d.ts.map +1 -0
  15. package/dist/cloud-session.d.ts.map +1 -1
  16. package/dist/cloud-status-transport.d.ts +53 -0
  17. package/dist/cloud-status-transport.d.ts.map +1 -0
  18. package/dist/index.d.ts +7 -16
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3242 -4298
  21. package/dist/index.js.map +20 -17
  22. package/dist/local-app-server-session.d.ts +1 -1
  23. package/dist/local-app-server-session.d.ts.map +1 -1
  24. package/dist/local-app-server.d.ts +11 -0
  25. package/dist/local-app-server.d.ts.map +1 -1
  26. package/dist/management.d.ts +0 -7
  27. package/dist/management.d.ts.map +1 -1
  28. package/dist/remote-client-session-core.d.ts +6 -93
  29. package/dist/remote-client-session-core.d.ts.map +1 -1
  30. package/dist/remote-session-protocol.d.ts +132 -0
  31. package/dist/remote-session-protocol.d.ts.map +1 -0
  32. package/dist/remote-turn-coordinator.d.ts +49 -0
  33. package/dist/remote-turn-coordinator.d.ts.map +1 -0
  34. package/dist/types.d.ts +59 -86
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/validation.d.ts.map +1 -1
  37. package/package.json +6 -3
  38. package/src/app-server-management.ts +405 -0
  39. package/src/app-server-session.ts +916 -0
  40. package/src/cli-resolver.ts +46 -0
  41. package/src/client-base.ts +456 -0
  42. package/src/client-entry.ts +31 -0
  43. package/src/client.ts +99 -0
  44. package/src/cloud-management.ts +360 -0
  45. package/src/cloud-sandbox.ts +117 -0
  46. package/src/cloud-session.ts +1055 -0
  47. package/src/cloud-status-transport.ts +305 -0
  48. package/src/index.ts +422 -0
  49. package/src/interactiveToolPolicy.ts +62 -0
  50. package/src/local-app-server-session.ts +49 -0
  51. package/src/local-app-server.ts +231 -0
  52. package/src/management-types.ts +133 -0
  53. package/src/management.ts +199 -0
  54. package/src/remote-client-session-core.ts +786 -0
  55. package/src/remote-session-protocol.ts +674 -0
  56. package/src/remote-turn-coordinator.ts +523 -0
  57. package/src/remote.ts +177 -0
  58. package/src/repositories.ts +340 -0
  59. package/src/request-ids.ts +33 -0
  60. package/src/stream-events.ts +88 -0
  61. package/src/tool-helpers.ts +147 -0
  62. package/src/types.ts +1281 -0
  63. package/src/validation.ts +238 -0
  64. package/src/websocket.ts +22 -0
  65. package/dist/protocol.d.ts +0 -205
  66. package/dist/protocol.d.ts.map +0 -1
  67. package/dist/session.d.ts +0 -155
  68. package/dist/session.d.ts.map +0 -1
  69. package/dist/transport.d.ts +0 -53
  70. package/dist/transport.d.ts.map +0 -1
@@ -0,0 +1,46 @@
1
+ import { existsSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const require = createRequire(import.meta.url);
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
+ /**
11
+ * Resolve the Letta Code CLI entrypoint used by SDK-owned transports.
12
+ *
13
+ * Resolution order intentionally matches the historical subprocess transport:
14
+ * explicit LETTA_CLI_PATH first, then the installed @letta-ai/letta-code package,
15
+ * then local development fallbacks.
16
+ */
17
+ export function findLettaCli(): string {
18
+ const envPath = process.env.LETTA_CLI_PATH;
19
+ if (envPath && existsSync(envPath)) {
20
+ return envPath;
21
+ }
22
+
23
+ try {
24
+ return require.resolve("@letta-ai/letta-code");
25
+ } catch {
26
+ // Fall through to local development paths.
27
+ }
28
+
29
+ const localPaths = [
30
+ join(__dirname, "..", "node_modules", "@letta-ai", "letta-code", "letta.js"),
31
+ join(__dirname, "../../@letta-ai/letta-code/letta.js"),
32
+ join(__dirname, "../../../letta-code-prod/letta.js"),
33
+ join(__dirname, "../../../letta-code/letta.js"),
34
+ join(__dirname, "..", "..", "letta-code", "letta.js"),
35
+ ];
36
+
37
+ for (const path of localPaths) {
38
+ if (existsSync(path)) {
39
+ return path;
40
+ }
41
+ }
42
+
43
+ throw new Error(
44
+ "Could not find Letta Code CLI. Set LETTA_CLI_PATH environment variable or install @letta-ai/letta-code.",
45
+ );
46
+ }
@@ -0,0 +1,456 @@
1
+ import { RepositoriesClient } from "./repositories.js";
2
+ import { AppServerManagementTransport } from "./app-server-management.js";
3
+ import {
4
+ AppServerSession,
5
+ type AppServerSessionOptions,
6
+ } from "./app-server-session.js";
7
+ import { CloudManagementTransport } from "./cloud-management.js";
8
+ import {
9
+ CloudEnvironmentSession,
10
+ assertCloudSessionOptionsSupported,
11
+ createCloudAgent,
12
+ validateCloudClientOptions,
13
+ } from "./cloud-session.js";
14
+ import {
15
+ createAgentsClient,
16
+ createConversationsClient,
17
+ createModelsClient,
18
+ type ManagementTransport,
19
+ } from "./management.js";
20
+ import type {
21
+ AgentsClient,
22
+ ConversationsClient,
23
+ ModelsClient,
24
+ } from "./management-types.js";
25
+ import type {
26
+ CreateAgentOptions,
27
+ CreateSessionOptions,
28
+ LettaCodeBackend,
29
+ LettaCodeClientOptions,
30
+ LettaCodeClientSessionOptions,
31
+ LettaCodeEnvironment,
32
+ LettaCodeRemoteClientOptions,
33
+ LettaCodeLocalClientOptions,
34
+ LettaCodeCloudClientOptions,
35
+ LettaCodeSession,
36
+ SDKResultMessage,
37
+ SendMessage,
38
+ } from "./types.js";
39
+ import {
40
+ validateCreateAgentOptions,
41
+ validateCreateSessionOptions,
42
+ } from "./validation.js";
43
+
44
+ const VALID_BACKENDS = new Set<LettaCodeBackend>([
45
+ "local",
46
+ "remote",
47
+ "cloud",
48
+ ]);
49
+
50
+ function isLettaCodeBackend(value: string): value is LettaCodeBackend {
51
+ return VALID_BACKENDS.has(value as LettaCodeBackend);
52
+ }
53
+
54
+ function getOptionsEnvironment(
55
+ options: LettaCodeClientOptions,
56
+ ): LettaCodeEnvironment | undefined {
57
+ if ("environment" in options) {
58
+ return options.environment;
59
+ }
60
+ return undefined;
61
+ }
62
+
63
+ function stripCloudExecutionOptions(
64
+ options: LettaCodeClientSessionOptions,
65
+ ): CreateSessionOptions {
66
+ const sessionOptions = { ...options };
67
+ delete sessionOptions.environment;
68
+ delete sessionOptions.sandbox;
69
+ delete sessionOptions.filesystemConfinement;
70
+ return sessionOptions;
71
+ }
72
+
73
+ function hasRepositoryResources(options: LettaCodeClientSessionOptions): boolean {
74
+ return options.resources !== undefined && options.resources.length > 0;
75
+ }
76
+
77
+ function hasCreateAgentEnvironment(options: CreateAgentOptions): boolean {
78
+ return "environment" in (options as Record<string, unknown>);
79
+ }
80
+
81
+ function looksLikeConversationId(id: string): boolean {
82
+ return id.startsWith("conv-") || id.startsWith("local-conv-");
83
+ }
84
+
85
+ type TurnSession = LettaCodeSession & {
86
+ runTurn(message: SendMessage): Promise<SDKResultMessage>;
87
+ };
88
+
89
+ /**
90
+ * Top-level Letta Agent SDK client.
91
+ *
92
+ * `backend` selects how the SDK reaches or runs the Letta Code harness.
93
+ * `local` spawns an SDK-owned Letta Code app-server and speaks the websocket
94
+ * protocol.
95
+ * `remote` connects to a user-managed Letta Code app-server websocket endpoint.
96
+ * `cloud` uses agents hosted on Letta Cloud, with an explicit remote
97
+ * environment or SDK-managed sandbox.
98
+ */
99
+ export class LettaAgentClientBase {
100
+ readonly backend: LettaCodeBackend;
101
+ readonly environment: LettaCodeEnvironment | undefined;
102
+ readonly agents: AgentsClient;
103
+ readonly conversations: ConversationsClient;
104
+ readonly models: ModelsClient;
105
+ protected readonly options: LettaCodeClientOptions;
106
+ private repositoriesClient: RepositoriesClient | null = null;
107
+ private managementTransport: ManagementTransport | null = null;
108
+
109
+ constructor(options: LettaCodeClientOptions = {}) {
110
+ const backend = options.backend ?? "local";
111
+ if (!isLettaCodeBackend(backend)) {
112
+ throw new Error(
113
+ `Invalid Letta Code backend '${String(backend)}'. Valid values: local, remote, cloud.`,
114
+ );
115
+ }
116
+
117
+ this.backend = backend;
118
+ this.environment = getOptionsEnvironment(options);
119
+ this.options = options;
120
+ this.agents = createAgentsClient(() => this.getManagementTransport());
121
+ this.conversations = createConversationsClient(
122
+ () => this.getManagementTransport(),
123
+ );
124
+ this.models = createModelsClient(() => this.getManagementTransport());
125
+
126
+ if (this.backend === "local" && this.environment !== undefined) {
127
+ throw new Error(
128
+ 'LettaAgentClient environment is only valid with backend: "cloud".',
129
+ );
130
+ }
131
+ if (this.backend === "remote" && this.environment !== undefined) {
132
+ throw new Error(
133
+ 'LettaAgentClient environment is only valid with backend: "cloud"; remote url selects the app-server runtime.',
134
+ );
135
+ }
136
+ if (this.backend !== "cloud" && (options as { sandbox?: unknown }).sandbox !== undefined) {
137
+ throw new Error('LettaAgentClient sandbox options are only valid with backend: "cloud".');
138
+ }
139
+
140
+ if (this.backend === "local") {
141
+ const localOptions = options as LettaCodeLocalClientOptions;
142
+ if ("transport" in localOptions) {
143
+ throw new Error(
144
+ 'Local transport selection has been removed. The local backend always uses the app-server protocol.',
145
+ );
146
+ }
147
+ const requestTimeoutMs = localOptions.appServer?.requestTimeoutMs;
148
+ if (
149
+ requestTimeoutMs !== undefined &&
150
+ (!Number.isInteger(requestTimeoutMs) || requestTimeoutMs <= 0)
151
+ ) {
152
+ throw new Error("Invalid appServer.requestTimeoutMs. Expected a positive integer.");
153
+ }
154
+ const startupTimeoutMs = localOptions.appServer?.startupTimeoutMs;
155
+ if (
156
+ startupTimeoutMs !== undefined &&
157
+ (!Number.isInteger(startupTimeoutMs) || startupTimeoutMs <= 0)
158
+ ) {
159
+ throw new Error("Invalid appServer.startupTimeoutMs. Expected a positive integer.");
160
+ }
161
+ }
162
+
163
+ if (this.backend === "remote") {
164
+ if (!("url" in options) || typeof options.url !== "string" || options.url.length === 0) {
165
+ throw new Error("LettaAgentClient remote backend requires a non-empty url.");
166
+ }
167
+ if (
168
+ options.requestTimeoutMs !== undefined &&
169
+ (!Number.isInteger(options.requestTimeoutMs) || options.requestTimeoutMs <= 0)
170
+ ) {
171
+ throw new Error("Invalid requestTimeoutMs. Expected a positive integer.");
172
+ }
173
+ }
174
+
175
+ if (this.backend === "cloud") {
176
+ validateCloudClientOptions(options as LettaCodeCloudClientOptions);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Create a new Letta Code agent with a default conversation.
182
+ *
183
+ * Environment/device selection is intentionally not part of the agent payload;
184
+ * it belongs to the client/session execution context.
185
+ */
186
+ get repositories(): RepositoriesClient {
187
+ return this.getRepositoriesClient();
188
+ }
189
+
190
+ async createAgent(options: CreateAgentOptions = {}): Promise<string> {
191
+ if (hasCreateAgentEnvironment(options)) {
192
+ throw new Error(
193
+ "createAgent() does not accept environment. Set a client default or pass environment to resumeSession()/createSession().",
194
+ );
195
+ }
196
+
197
+ validateCreateAgentOptions(options);
198
+
199
+ if (this.backend === "remote") {
200
+ const session = new AppServerSession(this.appServerSessionOptions(), {
201
+ kind: "create-agent",
202
+ options,
203
+ });
204
+ const initMsg = await session.initialize();
205
+ session.close();
206
+ return initMsg.agentId;
207
+ }
208
+ if (this.backend === "cloud") {
209
+ return createCloudAgent(this.cloudOptions(), options);
210
+ }
211
+ return this.createLocalAgent(options);
212
+ }
213
+
214
+ /**
215
+ * Create a new conversation/session.
216
+ *
217
+ * The app-server protocol requires an explicit agent id.
218
+ */
219
+ createSession(
220
+ agentId: string,
221
+ options: LettaCodeClientSessionOptions = {},
222
+ ): LettaCodeSession {
223
+ if (typeof agentId !== "string" || agentId.length === 0) {
224
+ throw new Error("createSession() requires a non-empty agent id.");
225
+ }
226
+ const sessionOptions = stripCloudExecutionOptions(options);
227
+ validateCreateSessionOptions(sessionOptions);
228
+ this.assertSessionBackend("createSession", options);
229
+
230
+ if (this.backend === "remote") {
231
+ return new AppServerSession(this.appServerSessionOptions(), {
232
+ kind: "session",
233
+ agentId,
234
+ newConversation: true,
235
+ options,
236
+ });
237
+ }
238
+ if (this.backend === "cloud") {
239
+ return new CloudEnvironmentSession(this.cloudOptions(), {
240
+ kind: "session",
241
+ agentId,
242
+ newConversation: true,
243
+ options,
244
+ });
245
+ }
246
+ return this.createLocalSession(agentId, options);
247
+ }
248
+
249
+ /**
250
+ * Resume an existing agent default conversation or a specific conversation.
251
+ *
252
+ * `options.environment` overrides the client's default execution target for
253
+ * Letta Cloud sessions. Remote app-server URLs already select the runtime.
254
+ */
255
+ resumeSession(
256
+ id: string,
257
+ options: LettaCodeClientSessionOptions = {},
258
+ ): LettaCodeSession {
259
+ const sessionOptions = stripCloudExecutionOptions(options);
260
+ validateCreateSessionOptions(sessionOptions);
261
+ this.assertSessionBackend("resumeSession", options);
262
+
263
+ if (this.backend === "remote") {
264
+ if (looksLikeConversationId(id)) {
265
+ return new AppServerSession(this.appServerSessionOptions(), {
266
+ kind: "session",
267
+ conversationId: id,
268
+ options,
269
+ });
270
+ }
271
+ return new AppServerSession(this.appServerSessionOptions(), {
272
+ kind: "session",
273
+ agentId: id,
274
+ defaultConversation: true,
275
+ options,
276
+ });
277
+ }
278
+ if (this.backend === "cloud") {
279
+ if (looksLikeConversationId(id)) {
280
+ return new CloudEnvironmentSession(this.cloudOptions(), {
281
+ kind: "session",
282
+ conversationId: id,
283
+ options,
284
+ });
285
+ }
286
+ return new CloudEnvironmentSession(this.cloudOptions(), {
287
+ kind: "session",
288
+ agentId: id,
289
+ defaultConversation: true,
290
+ options,
291
+ });
292
+ }
293
+ return this.resumeLocalSession(id, options);
294
+ }
295
+
296
+ /** One-shot prompt convenience helper using a new conversation. */
297
+ async prompt(
298
+ message: SendMessage,
299
+ agentId: string,
300
+ options: LettaCodeClientSessionOptions = {},
301
+ ): Promise<SDKResultMessage> {
302
+ const session = this.createSession(agentId, options);
303
+
304
+ try {
305
+ return await (session as TurnSession).runTurn(message);
306
+ } finally {
307
+ session.close();
308
+ }
309
+ }
310
+
311
+ private assertSessionBackend(
312
+ action: string,
313
+ options: LettaCodeClientSessionOptions,
314
+ ): void {
315
+ if (
316
+ options.filesystemConfinement !== undefined &&
317
+ options.filesystemConfinement !== "memory"
318
+ ) {
319
+ throw new Error(
320
+ `Invalid filesystemConfinement '${String(options.filesystemConfinement)}'. Valid value: memory.`,
321
+ );
322
+ }
323
+ const effectiveEnvironment = options.environment ?? this.environment;
324
+ if (this.backend === "local") {
325
+ if (effectiveEnvironment !== undefined) {
326
+ throw new Error(
327
+ `${action}() environment overrides are only valid with backend: "cloud".`,
328
+ );
329
+ }
330
+ if (options.sandbox !== undefined) {
331
+ throw new Error(`${action}() sandbox options are only valid with backend: "cloud".`);
332
+ }
333
+ if (hasRepositoryResources(options)) {
334
+ throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
335
+ }
336
+ if (options.filesystemConfinement !== undefined) {
337
+ const localOptions = this.options as LettaCodeLocalClientOptions;
338
+ if (localOptions.appServer?.url !== undefined) {
339
+ throw new Error(
340
+ `${action}() filesystemConfinement requires an SDK-owned local app-server process.`,
341
+ );
342
+ }
343
+ }
344
+ return;
345
+ }
346
+
347
+ if (this.backend === "remote") {
348
+ if (options.filesystemConfinement !== undefined) {
349
+ throw new Error(
350
+ `${action}() filesystemConfinement requires an SDK-owned local app-server process.`,
351
+ );
352
+ }
353
+ if (options.environment !== undefined) {
354
+ throw new Error(
355
+ `${action}() environment overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`,
356
+ );
357
+ }
358
+ if (options.sandbox !== undefined) {
359
+ throw new Error(`${action}() sandbox options are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
360
+ }
361
+ if (hasRepositoryResources(options)) {
362
+ throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
363
+ }
364
+ return;
365
+ }
366
+ if (this.backend === "cloud") {
367
+ if (options.filesystemConfinement !== undefined) {
368
+ throw new Error(
369
+ `${action}() filesystemConfinement is only supported with backend: "local".`,
370
+ );
371
+ }
372
+ const cloudOptions = this.cloudOptions();
373
+ if (cloudOptions.environment !== undefined && options.sandbox !== undefined) {
374
+ throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default environment.`);
375
+ }
376
+ if (cloudOptions.sandbox !== undefined && options.environment !== undefined) {
377
+ throw new Error(`Letta Cloud ${action}() cannot specify an environment when the client has default sandbox options.`);
378
+ }
379
+ assertCloudSessionOptionsSupported(action, options);
380
+ return;
381
+ }
382
+ throw new Error(
383
+ `LettaAgentClient backend '${this.backend}' is not implemented yet. ${action} currently supports backend 'local' only.`,
384
+ );
385
+ }
386
+
387
+ protected createLocalAgent(_options: CreateAgentOptions): Promise<string> {
388
+ throw this.localBackendUnavailableError();
389
+ }
390
+
391
+ protected createLocalSession(
392
+ _agentId: string,
393
+ _options: LettaCodeClientSessionOptions,
394
+ ): LettaCodeSession {
395
+ throw this.localBackendUnavailableError();
396
+ }
397
+
398
+ protected resumeLocalSession(
399
+ _id: string,
400
+ _options: LettaCodeClientSessionOptions,
401
+ ): LettaCodeSession {
402
+ throw this.localBackendUnavailableError();
403
+ }
404
+
405
+ protected localBackendUnavailableError(): Error {
406
+ return new Error(
407
+ 'The portable "@letta-ai/letta-agent-sdk/client" entry point supports backend: "remote" and backend: "cloud" only. Import from "@letta-ai/letta-agent-sdk" for local execution.',
408
+ );
409
+ }
410
+
411
+ protected createLocalManagementTransport(): ManagementTransport {
412
+ throw this.localBackendUnavailableError();
413
+ }
414
+
415
+ private remoteOptions(): LettaCodeRemoteClientOptions {
416
+ if (this.backend !== "remote") {
417
+ throw new Error("Remote options requested for non-remote backend.");
418
+ }
419
+ return this.options as LettaCodeRemoteClientOptions;
420
+ }
421
+
422
+ private appServerSessionOptions(): AppServerSessionOptions {
423
+ return this.remoteOptions();
424
+ }
425
+
426
+ private getRepositoriesClient(): RepositoriesClient {
427
+ if (this.backend !== "cloud") {
428
+ throw new Error('client.repositories is only available with backend: "cloud".');
429
+ }
430
+ this.repositoriesClient ??= new RepositoriesClient(this.cloudOptions());
431
+ return this.repositoriesClient;
432
+ }
433
+
434
+ private getManagementTransport(): ManagementTransport {
435
+ if (this.managementTransport) return this.managementTransport;
436
+ if (this.backend === "remote") {
437
+ this.managementTransport = new AppServerManagementTransport(
438
+ this.remoteOptions(),
439
+ );
440
+ } else if (this.backend === "cloud") {
441
+ this.managementTransport = new CloudManagementTransport(
442
+ this.cloudOptions(),
443
+ );
444
+ } else {
445
+ this.managementTransport = this.createLocalManagementTransport();
446
+ }
447
+ return this.managementTransport;
448
+ }
449
+
450
+ private cloudOptions(): LettaCodeCloudClientOptions {
451
+ if (this.backend !== "cloud") {
452
+ throw new Error('Letta Cloud options requested for non-"cloud" backend.');
453
+ }
454
+ return this.options as LettaCodeCloudClientOptions;
455
+ }
456
+ }
@@ -0,0 +1,31 @@
1
+ import { LettaAgentClientBase } from "./client-base.js";
2
+ import type {
3
+ LettaCodeCloudClientOptions,
4
+ LettaCodeRemoteClientOptions,
5
+ } from "./types.js";
6
+
7
+ export type PortableLettaAgentClientOptions =
8
+ | LettaCodeRemoteClientOptions
9
+ | LettaCodeCloudClientOptions;
10
+
11
+ /**
12
+ * Portable Letta Agent SDK client for browsers and React Native.
13
+ *
14
+ * This entry point intentionally excludes local process execution. Use the
15
+ * package root from Node.js when `backend: "local"` is required.
16
+ */
17
+ export class LettaAgentClient extends LettaAgentClientBase {
18
+ constructor(options: PortableLettaAgentClientOptions) {
19
+ super(options);
20
+ if (this.backend === "local") {
21
+ throw this.localBackendUnavailableError();
22
+ }
23
+ }
24
+ }
25
+
26
+ export { CloudManagedSandboxExpiredError } from "./cloud-session.js";
27
+ export { RepositoriesClient } from "./repositories.js";
28
+ export type * from "./management-types.js";
29
+ export { extractStreamTextDelta } from "./stream-events.js";
30
+ export { createReactNativeWebSocketConstructor } from "./websocket.js";
31
+ export type * from "./types.js";
package/src/client.ts ADDED
@@ -0,0 +1,99 @@
1
+ import { LettaAgentClientBase } from "./client-base.js";
2
+ import { AppServerManagementTransport } from "./app-server-management.js";
3
+ import type { ManagementTransport } from "./management.js";
4
+ import { createLocalAppServerSession } from "./local-app-server-session.js";
5
+ import { startLocalAppServer } from "./local-app-server.js";
6
+ import type {
7
+ CreateAgentOptions,
8
+ LettaCodeClientSessionOptions,
9
+ LettaCodeLocalClientOptions,
10
+ LettaCodeSession,
11
+ } from "./types.js";
12
+
13
+ export class LettaAgentClient extends LettaAgentClientBase {
14
+ protected override createLocalManagementTransport(): ManagementTransport {
15
+ const localOptions = (
16
+ this.options as LettaCodeLocalClientOptions
17
+ ).appServer;
18
+ return new AppServerManagementTransport({
19
+ ...(localOptions?.url !== undefined
20
+ ? { url: localOptions.url }
21
+ : {
22
+ connect: () =>
23
+ startLocalAppServer({
24
+ listen: localOptions?.listen,
25
+ backend: localOptions?.harnessBackend ?? "local",
26
+ startupTimeoutMs: localOptions?.startupTimeoutMs,
27
+ }),
28
+ }),
29
+ ...(localOptions?.WebSocket !== undefined
30
+ ? { WebSocket: localOptions.WebSocket }
31
+ : {}),
32
+ ...(localOptions?.requestTimeoutMs !== undefined
33
+ ? { requestTimeoutMs: localOptions.requestTimeoutMs }
34
+ : {}),
35
+ });
36
+ }
37
+
38
+ protected override async createLocalAgent(
39
+ options: CreateAgentOptions,
40
+ ): Promise<string> {
41
+ const localOptions = this.options as LettaCodeLocalClientOptions;
42
+ const session = createLocalAppServerSession(
43
+ localOptions.appServer,
44
+ {
45
+ kind: "create-agent",
46
+ options,
47
+ },
48
+ );
49
+ const initMsg = await session.initialize();
50
+ session.close();
51
+ return initMsg.agentId;
52
+ }
53
+
54
+ protected override createLocalSession(
55
+ agentId: string,
56
+ options: LettaCodeClientSessionOptions,
57
+ ): LettaCodeSession {
58
+ const localOptions = this.options as LettaCodeLocalClientOptions;
59
+ return createLocalAppServerSession(
60
+ localOptions.appServer,
61
+ {
62
+ kind: "session",
63
+ agentId,
64
+ newConversation: true,
65
+ options,
66
+ },
67
+ );
68
+ }
69
+
70
+ protected override resumeLocalSession(
71
+ id: string,
72
+ options: LettaCodeClientSessionOptions,
73
+ ): LettaCodeSession {
74
+ const localOptions = this.options as LettaCodeLocalClientOptions;
75
+ if (looksLikeConversationId(id)) {
76
+ return createLocalAppServerSession(
77
+ localOptions.appServer,
78
+ {
79
+ kind: "session",
80
+ conversationId: id,
81
+ options,
82
+ },
83
+ );
84
+ }
85
+ return createLocalAppServerSession(
86
+ localOptions.appServer,
87
+ {
88
+ kind: "session",
89
+ agentId: id,
90
+ defaultConversation: true,
91
+ options,
92
+ },
93
+ );
94
+ }
95
+ }
96
+
97
+ function looksLikeConversationId(id: string): boolean {
98
+ return id.startsWith("conv-") || id.startsWith("local-conv-");
99
+ }