@letta-ai/letta-agent-sdk 0.7.7 → 0.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-agent-sdk",
3
- "version": "0.7.7",
3
+ "version": "0.7.8",
4
4
  "packageManager": "bun@1.3.0",
5
5
  "description": "SDK for programmatic control of Letta agents",
6
6
  "type": "module",
@@ -66,6 +66,7 @@ const DEFAULT_SANDBOX_READY_TIMEOUT_MS = 120_000;
66
66
  const DEFAULT_SANDBOX_READY_POLL_INTERVAL_MS = 1_000;
67
67
  const DEFAULT_REPOSITORY_ATTACH_TIMEOUT_MS = 10_000;
68
68
  const DEFAULT_REPOSITORY_ATTACH_POLL_INTERVAL_MS = 250;
69
+ const INITIAL_CLOUD_TRANSPORT_ATTEMPTS = 2;
69
70
  const SDK_AGENT_ORIGIN = "@letta-ai/letta-agent-sdk";
70
71
 
71
72
  type CloudRuntimeStartResponse = ProtocolMessage & {
@@ -404,34 +405,10 @@ export class CloudEnvironmentSession extends RemoteClientSessionCore {
404
405
  runtime: RuntimeScope,
405
406
  connectionId: string,
406
407
  ): Promise<RuntimeSessionInit> {
407
- const apiKey = getCloudApiKey(this.cloudOptions);
408
- const url = buildCloudStatusWebSocketUrl({
409
- apiBaseUrl: this.cloudOptions.apiBaseUrl,
410
- connectionId,
411
- agentId: runtime.agent_id,
412
- conversationId: runtime.conversation_id,
413
- apiKey,
414
- authMode: this.cloudOptions.webSocketAuth ?? "header",
415
- });
416
- const client = applyUniqueRequestIds(createAppServerClient({
417
- url,
418
- WebSocket: createCloudStatusTransportConstructor({
419
- url,
420
- WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
421
- ...((this.cloudOptions.webSocketAuth ?? "header") === "header"
422
- ? { headers: cloudWebSocketHeaders(this.cloudOptions) }
423
- : {}),
424
- pingIntervalMs:
425
- this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
426
- runtime,
427
- }),
428
- requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS,
429
- }));
408
+ const client = await this.connectCloudTransport(runtime, connectionId);
430
409
  const options = this.currentOptions();
431
- this.installTransportHandlers(client);
432
410
 
433
411
  try {
434
- await client.connect();
435
412
  const response = await this.startCloudRuntime(client, runtime);
436
413
  if (!response.success || !response.runtime) {
437
414
  throw new Error(response.error ?? "Failed to start Cloud status runtime");
@@ -473,6 +450,84 @@ export class CloudEnvironmentSession extends RemoteClientSessionCore {
473
450
  }
474
451
  }
475
452
 
453
+ private createCloudTransportClient(
454
+ runtime: RuntimeScope,
455
+ connectionId: string,
456
+ ): AppServerClient {
457
+ const apiKey = getCloudApiKey(this.cloudOptions);
458
+ const url = buildCloudStatusWebSocketUrl({
459
+ apiBaseUrl: this.cloudOptions.apiBaseUrl,
460
+ connectionId,
461
+ agentId: runtime.agent_id,
462
+ conversationId: runtime.conversation_id,
463
+ apiKey,
464
+ authMode: this.cloudOptions.webSocketAuth ?? "header",
465
+ });
466
+ return applyUniqueRequestIds(createAppServerClient({
467
+ url,
468
+ WebSocket: createCloudStatusTransportConstructor({
469
+ url,
470
+ WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
471
+ ...((this.cloudOptions.webSocketAuth ?? "header") === "header"
472
+ ? { headers: cloudWebSocketHeaders(this.cloudOptions) }
473
+ : {}),
474
+ pingIntervalMs:
475
+ this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
476
+ runtime,
477
+ }),
478
+ requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS,
479
+ }));
480
+ }
481
+
482
+ private async connectCloudTransport(
483
+ runtime: RuntimeScope,
484
+ initialConnectionId: string,
485
+ ): Promise<AppServerClient> {
486
+ let connectionId = initialConnectionId;
487
+ let lastError: unknown;
488
+
489
+ for (let attempt = 0; attempt < INITIAL_CLOUD_TRANSPORT_ATTEMPTS; attempt++) {
490
+ const client = this.createCloudTransportClient(runtime, connectionId);
491
+ this.installTransportHandlers(client);
492
+
493
+ try {
494
+ await client.connect();
495
+ this.connectionId = connectionId;
496
+ return client;
497
+ } catch (error) {
498
+ lastError = error;
499
+ console.warn(
500
+ JSON.stringify({
501
+ event: "cloud_status_transport_connection_failed",
502
+ attempt: attempt + 1,
503
+ max_attempts: INITIAL_CLOUD_TRANSPORT_ATTEMPTS,
504
+ will_retry:
505
+ attempt + 1 < INITIAL_CLOUD_TRANSPORT_ATTEMPTS,
506
+ connection_id: connectionId,
507
+ agent_id: runtime.agent_id,
508
+ conversation_id: runtime.conversation_id,
509
+ error_name: error instanceof Error ? error.name : null,
510
+ error_message:
511
+ error instanceof Error ? error.message : String(error),
512
+ }),
513
+ );
514
+ this.cleanupTransportHandlers();
515
+ client.close();
516
+ }
517
+
518
+ if (attempt + 1 < INITIAL_CLOUD_TRANSPORT_ATTEMPTS) {
519
+ const resolved = await this.resolveRecoveryConnection(runtime);
520
+ connectionId = resolved.connectionId;
521
+ }
522
+ }
523
+
524
+ const detail = lastError instanceof Error ? lastError.message : String(lastError);
525
+ throw new Error(
526
+ `Cloud status WebSocket failed to open for connection ${connectionId}: ${detail}`,
527
+ { cause: lastError },
528
+ );
529
+ }
530
+
476
531
  private installTransportHandlers(client: AppServerClient): void {
477
532
  this.cleanupTransportHandlers();
478
533
  this.removeControlRequestHandler = registerAppServerControlRequestHandler({