@letta-ai/letta-agent-sdk 0.3.3 → 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 (55) hide show
  1. package/AGENTS.md +0 -3
  2. package/README.md +12 -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 +369 -468
  10. package/dist/client-entry.js.map +13 -12
  11. package/dist/client.d.ts +3 -3
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/cloud-session.d.ts.map +1 -1
  14. package/dist/cloud-status-transport.d.ts +53 -0
  15. package/dist/cloud-status-transport.d.ts.map +1 -0
  16. package/dist/index.d.ts +7 -16
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +896 -2019
  19. package/dist/index.js.map +18 -18
  20. package/dist/local-app-server-session.d.ts +1 -1
  21. package/dist/local-app-server-session.d.ts.map +1 -1
  22. package/dist/local-app-server.d.ts +11 -0
  23. package/dist/local-app-server.d.ts.map +1 -1
  24. package/dist/management.d.ts +0 -7
  25. package/dist/management.d.ts.map +1 -1
  26. package/dist/remote-session-protocol.d.ts +2 -0
  27. package/dist/remote-session-protocol.d.ts.map +1 -1
  28. package/dist/remote-turn-coordinator.d.ts.map +1 -1
  29. package/dist/types.d.ts +57 -66
  30. package/dist/types.d.ts.map +1 -1
  31. package/dist/validation.d.ts.map +1 -1
  32. package/package.json +2 -2
  33. package/src/app-server-management.ts +20 -256
  34. package/src/app-server-session.ts +0 -32
  35. package/src/client-base.ts +47 -73
  36. package/src/client.ts +31 -70
  37. package/src/cloud-session.ts +9 -267
  38. package/src/cloud-status-transport.ts +305 -0
  39. package/src/index.ts +11 -29
  40. package/src/local-app-server-session.ts +13 -3
  41. package/src/local-app-server.ts +97 -3
  42. package/src/management.ts +0 -7
  43. package/src/remote-session-protocol.ts +14 -0
  44. package/src/remote-turn-coordinator.ts +20 -2
  45. package/src/types.ts +64 -111
  46. package/src/validation.ts +21 -6
  47. package/dist/protocol.d.ts +0 -205
  48. package/dist/protocol.d.ts.map +0 -1
  49. package/dist/session.d.ts +0 -155
  50. package/dist/session.d.ts.map +0 -1
  51. package/dist/transport.d.ts +0 -53
  52. package/dist/transport.d.ts.map +0 -1
  53. package/src/protocol.ts +0 -249
  54. package/src/session.ts +0 -1638
  55. package/src/transport.ts +0 -484
@@ -2,7 +2,6 @@ import { RepositoriesClient } from "./repositories.js";
2
2
  import { AppServerManagementTransport } from "./app-server-management.js";
3
3
  import {
4
4
  AppServerSession,
5
- assertRemoteSessionOptionsSupported,
6
5
  type AppServerSessionOptions,
7
6
  } from "./app-server-session.js";
8
7
  import { CloudManagementTransport } from "./cloud-management.js";
@@ -67,6 +66,7 @@ function stripCloudExecutionOptions(
67
66
  const sessionOptions = { ...options };
68
67
  delete sessionOptions.environment;
69
68
  delete sessionOptions.sandbox;
69
+ delete sessionOptions.filesystemConfinement;
70
70
  return sessionOptions;
71
71
  }
72
72
 
@@ -91,7 +91,7 @@ type TurnSession = LettaCodeSession & {
91
91
  *
92
92
  * `backend` selects how the SDK reaches or runs the Letta Code harness.
93
93
  * `local` spawns an SDK-owned Letta Code app-server and speaks the websocket
94
- * protocol by default, with an explicit stdio fallback for legacy flows.
94
+ * protocol.
95
95
  * `remote` connects to a user-managed Letta Code app-server websocket endpoint.
96
96
  * `cloud` uses agents hosted on Letta Cloud, with an explicit remote
97
97
  * environment or SDK-managed sandbox.
@@ -139,12 +139,10 @@ export class LettaAgentClientBase {
139
139
 
140
140
  if (this.backend === "local") {
141
141
  const localOptions = options as LettaCodeLocalClientOptions;
142
- if (
143
- localOptions.transport !== undefined &&
144
- localOptions.transport !== "app-server" &&
145
- localOptions.transport !== "stdio"
146
- ) {
147
- throw new Error("Invalid local transport. Valid values: app-server, stdio.");
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
+ );
148
146
  }
149
147
  const requestTimeoutMs = localOptions.appServer?.requestTimeoutMs;
150
148
  if (
@@ -153,13 +151,6 @@ export class LettaAgentClientBase {
153
151
  ) {
154
152
  throw new Error("Invalid appServer.requestTimeoutMs. Expected a positive integer.");
155
153
  }
156
- const idleLingerMs = localOptions.appServer?.idleLingerMs;
157
- if (
158
- idleLingerMs !== undefined &&
159
- (!Number.isInteger(idleLingerMs) || idleLingerMs < 0)
160
- ) {
161
- throw new Error("Invalid appServer.idleLingerMs. Expected a non-negative integer.");
162
- }
163
154
  const startupTimeoutMs = localOptions.appServer?.startupTimeoutMs;
164
155
  if (
165
156
  startupTimeoutMs !== undefined &&
@@ -179,12 +170,6 @@ export class LettaAgentClientBase {
179
170
  ) {
180
171
  throw new Error("Invalid requestTimeoutMs. Expected a positive integer.");
181
172
  }
182
- if (
183
- options.idleLingerMs !== undefined &&
184
- (!Number.isInteger(options.idleLingerMs) || options.idleLingerMs < 0)
185
- ) {
186
- throw new Error("Invalid idleLingerMs. Expected a non-negative integer.");
187
- }
188
173
  }
189
174
 
190
175
  if (this.backend === "cloud") {
@@ -229,49 +214,36 @@ export class LettaAgentClientBase {
229
214
  /**
230
215
  * Create a new conversation/session.
231
216
  *
232
- * Without an agent id, this uses the default/LRU agent, matching the legacy
233
- * top-level createSession() helper.
217
+ * The app-server protocol requires an explicit agent id.
234
218
  */
235
219
  createSession(
236
- agentIdOrOptions?: string | LettaCodeClientSessionOptions,
220
+ agentId: string,
237
221
  options: LettaCodeClientSessionOptions = {},
238
222
  ): LettaCodeSession {
239
- const agentId =
240
- typeof agentIdOrOptions === "string" ? agentIdOrOptions : undefined;
241
- const resolvedOptions =
242
- typeof agentIdOrOptions === "string" ? options : (agentIdOrOptions ?? {});
243
-
244
- this.assertSessionBackend("createSession", resolvedOptions);
245
- const sessionOptions = stripCloudExecutionOptions(resolvedOptions);
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);
246
227
  validateCreateSessionOptions(sessionOptions);
228
+ this.assertSessionBackend("createSession", options);
247
229
 
248
230
  if (this.backend === "remote") {
249
- if (!agentId) {
250
- throw new Error(
251
- "App-server createSession() requires an agent id. Call createAgent() first or pass an agent id.",
252
- );
253
- }
254
231
  return new AppServerSession(this.appServerSessionOptions(), {
255
232
  kind: "session",
256
233
  agentId,
257
234
  newConversation: true,
258
- options: resolvedOptions,
235
+ options,
259
236
  });
260
237
  }
261
238
  if (this.backend === "cloud") {
262
- if (!agentId) {
263
- throw new Error(
264
- "Letta Cloud createSession() requires an agent id. Call createAgent() first or pass an agent id.",
265
- );
266
- }
267
239
  return new CloudEnvironmentSession(this.cloudOptions(), {
268
240
  kind: "session",
269
241
  agentId,
270
242
  newConversation: true,
271
- options: resolvedOptions,
243
+ options,
272
244
  });
273
245
  }
274
- return this.createLocalSession(agentId, resolvedOptions, sessionOptions);
246
+ return this.createLocalSession(agentId, options);
275
247
  }
276
248
 
277
249
  /**
@@ -284,9 +256,9 @@ export class LettaAgentClientBase {
284
256
  id: string,
285
257
  options: LettaCodeClientSessionOptions = {},
286
258
  ): LettaCodeSession {
287
- this.assertSessionBackend("resumeSession", options);
288
259
  const sessionOptions = stripCloudExecutionOptions(options);
289
260
  validateCreateSessionOptions(sessionOptions);
261
+ this.assertSessionBackend("resumeSession", options);
290
262
 
291
263
  if (this.backend === "remote") {
292
264
  if (looksLikeConversationId(id)) {
@@ -318,18 +290,16 @@ export class LettaAgentClientBase {
318
290
  options,
319
291
  });
320
292
  }
321
- return this.resumeLocalSession(id, options, sessionOptions);
293
+ return this.resumeLocalSession(id, options);
322
294
  }
323
295
 
324
296
  /** One-shot prompt convenience helper using a new conversation. */
325
297
  async prompt(
326
298
  message: SendMessage,
327
- agentId?: string,
299
+ agentId: string,
328
300
  options: LettaCodeClientSessionOptions = {},
329
301
  ): Promise<SDKResultMessage> {
330
- const session = agentId
331
- ? this.createSession(agentId, options)
332
- : this.createSession(options);
302
+ const session = this.createSession(agentId, options);
333
303
 
334
304
  try {
335
305
  return await (session as TurnSession).runTurn(message);
@@ -342,6 +312,14 @@ export class LettaAgentClientBase {
342
312
  action: string,
343
313
  options: LettaCodeClientSessionOptions,
344
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
+ }
345
323
  const effectiveEnvironment = options.environment ?? this.environment;
346
324
  if (this.backend === "local") {
347
325
  if (effectiveEnvironment !== undefined) {
@@ -355,13 +333,23 @@ export class LettaAgentClientBase {
355
333
  if (hasRepositoryResources(options)) {
356
334
  throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
357
335
  }
358
- if (!this.useLegacyLocalStdio()) {
359
- assertRemoteSessionOptionsSupported(action, options);
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
+ }
360
343
  }
361
344
  return;
362
345
  }
363
346
 
364
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
+ }
365
353
  if (options.environment !== undefined) {
366
354
  throw new Error(
367
355
  `${action}() environment overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`,
@@ -373,10 +361,14 @@ export class LettaAgentClientBase {
373
361
  if (hasRepositoryResources(options)) {
374
362
  throw new Error(`${action}() repository resources are only valid with backend: "cloud".`);
375
363
  }
376
- assertRemoteSessionOptionsSupported(action, options);
377
364
  return;
378
365
  }
379
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
+ }
380
372
  const cloudOptions = this.cloudOptions();
381
373
  if (cloudOptions.environment !== undefined && options.sandbox !== undefined) {
382
374
  throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default environment.`);
@@ -392,18 +384,13 @@ export class LettaAgentClientBase {
392
384
  );
393
385
  }
394
386
 
395
- protected useLegacyLocalStdio(): boolean {
396
- return (this.options as LettaCodeLocalClientOptions).transport === "stdio";
397
- }
398
-
399
387
  protected createLocalAgent(_options: CreateAgentOptions): Promise<string> {
400
388
  throw this.localBackendUnavailableError();
401
389
  }
402
390
 
403
391
  protected createLocalSession(
404
- _agentId: string | undefined,
392
+ _agentId: string,
405
393
  _options: LettaCodeClientSessionOptions,
406
- _sessionOptions: CreateSessionOptions,
407
394
  ): LettaCodeSession {
408
395
  throw this.localBackendUnavailableError();
409
396
  }
@@ -411,7 +398,6 @@ export class LettaAgentClientBase {
411
398
  protected resumeLocalSession(
412
399
  _id: string,
413
400
  _options: LettaCodeClientSessionOptions,
414
- _sessionOptions: CreateSessionOptions,
415
401
  ): LettaCodeSession {
416
402
  throw this.localBackendUnavailableError();
417
403
  }
@@ -434,10 +420,7 @@ export class LettaAgentClientBase {
434
420
  }
435
421
 
436
422
  private appServerSessionOptions(): AppServerSessionOptions {
437
- return {
438
- ...this.remoteOptions(),
439
- beforeConnect: () => this.releaseIdleManagementConnection(),
440
- };
423
+ return this.remoteOptions();
441
424
  }
442
425
 
443
426
  private getRepositoriesClient(): RepositoriesClient {
@@ -448,15 +431,6 @@ export class LettaAgentClientBase {
448
431
  return this.repositoriesClient;
449
432
  }
450
433
 
451
- /**
452
- * The app-server accepts a single control client at a time. Before a session
453
- * connects, wait for this client's management work to settle and relinquish
454
- * its pooled connection; management reconnects lazily on its next call.
455
- */
456
- protected async releaseIdleManagementConnection(): Promise<void> {
457
- await this.managementTransport?.releaseIdleConnection?.();
458
- }
459
-
460
434
  private getManagementTransport(): ManagementTransport {
461
435
  if (this.managementTransport) return this.managementTransport;
462
436
  if (this.backend === "remote") {
package/src/client.ts CHANGED
@@ -3,10 +3,8 @@ import { AppServerManagementTransport } from "./app-server-management.js";
3
3
  import type { ManagementTransport } from "./management.js";
4
4
  import { createLocalAppServerSession } from "./local-app-server-session.js";
5
5
  import { startLocalAppServer } from "./local-app-server.js";
6
- import { Session } from "./session.js";
7
6
  import type {
8
7
  CreateAgentOptions,
9
- CreateSessionOptions,
10
8
  LettaCodeClientSessionOptions,
11
9
  LettaCodeLocalClientOptions,
12
10
  LettaCodeSession,
@@ -14,11 +12,6 @@ import type {
14
12
 
15
13
  export class LettaAgentClient extends LettaAgentClientBase {
16
14
  protected override createLocalManagementTransport(): ManagementTransport {
17
- if (this.useLegacyLocalStdio()) {
18
- throw new Error(
19
- 'client.agents and client.conversations require the local "app-server" transport.',
20
- );
21
- }
22
15
  const localOptions = (
23
16
  this.options as LettaCodeLocalClientOptions
24
17
  ).appServer;
@@ -39,97 +32,65 @@ export class LettaAgentClient extends LettaAgentClientBase {
39
32
  ...(localOptions?.requestTimeoutMs !== undefined
40
33
  ? { requestTimeoutMs: localOptions.requestTimeoutMs }
41
34
  : {}),
42
- ...(localOptions?.idleLingerMs !== undefined
43
- ? { idleLingerMs: localOptions.idleLingerMs }
44
- : {}),
45
35
  });
46
36
  }
47
37
 
48
38
  protected override async createLocalAgent(
49
39
  options: CreateAgentOptions,
50
40
  ): Promise<string> {
51
- if (!this.useLegacyLocalStdio()) {
52
- const localOptions = this.options as LettaCodeLocalClientOptions;
53
- const session = createLocalAppServerSession(
54
- localOptions.appServer,
55
- {
56
- kind: "create-agent",
57
- options,
58
- },
59
- () => this.releaseIdleManagementConnection(),
60
- );
61
- const initMsg = await session.initialize();
62
- session.close();
63
- return initMsg.agentId;
64
- }
65
-
66
- const session = new Session({ ...options, createOnly: true });
41
+ const localOptions = this.options as LettaCodeLocalClientOptions;
42
+ const session = createLocalAppServerSession(
43
+ localOptions.appServer,
44
+ {
45
+ kind: "create-agent",
46
+ options,
47
+ },
48
+ );
67
49
  const initMsg = await session.initialize();
68
50
  session.close();
69
51
  return initMsg.agentId;
70
52
  }
71
53
 
72
54
  protected override createLocalSession(
73
- agentId: string | undefined,
55
+ agentId: string,
74
56
  options: LettaCodeClientSessionOptions,
75
- sessionOptions: CreateSessionOptions,
76
57
  ): LettaCodeSession {
77
- if (!this.useLegacyLocalStdio() && agentId) {
78
- const localOptions = this.options as LettaCodeLocalClientOptions;
79
- return createLocalAppServerSession(
80
- localOptions.appServer,
81
- {
82
- kind: "session",
83
- agentId,
84
- newConversation: true,
85
- options,
86
- },
87
- () => this.releaseIdleManagementConnection(),
88
- );
89
- }
90
- if (agentId) {
91
- return new Session({ ...sessionOptions, agentId, newConversation: true });
92
- }
93
- return new Session({ ...sessionOptions, newConversation: true });
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
+ );
94
68
  }
95
69
 
96
70
  protected override resumeLocalSession(
97
71
  id: string,
98
72
  options: LettaCodeClientSessionOptions,
99
- sessionOptions: CreateSessionOptions,
100
73
  ): LettaCodeSession {
101
- if (!this.useLegacyLocalStdio()) {
102
- const localOptions = this.options as LettaCodeLocalClientOptions;
103
- if (looksLikeConversationId(id)) {
104
- return createLocalAppServerSession(
105
- localOptions.appServer,
106
- {
107
- kind: "session",
108
- conversationId: id,
109
- options,
110
- },
111
- () => this.releaseIdleManagementConnection(),
112
- );
113
- }
74
+ const localOptions = this.options as LettaCodeLocalClientOptions;
75
+ if (looksLikeConversationId(id)) {
114
76
  return createLocalAppServerSession(
115
77
  localOptions.appServer,
116
78
  {
117
79
  kind: "session",
118
- agentId: id,
119
- defaultConversation: true,
80
+ conversationId: id,
120
81
  options,
121
82
  },
122
- () => this.releaseIdleManagementConnection(),
123
83
  );
124
84
  }
125
- if (looksLikeConversationId(id)) {
126
- return new Session({ ...sessionOptions, conversationId: id });
127
- }
128
- return new Session({
129
- ...sessionOptions,
130
- agentId: id,
131
- defaultConversation: true,
132
- });
85
+ return createLocalAppServerSession(
86
+ localOptions.appServer,
87
+ {
88
+ kind: "session",
89
+ agentId: id,
90
+ defaultConversation: true,
91
+ options,
92
+ },
93
+ );
133
94
  }
134
95
  }
135
96