@letta-ai/letta-agent-sdk 0.6.2 → 0.6.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.
package/dist/index.js CHANGED
@@ -9514,6 +9514,9 @@ class RemoteClientSessionCore {
9514
9514
  initializePromise = null;
9515
9515
  removeMessageHandler = null;
9516
9516
  detachTransportDisconnect = null;
9517
+ idleTransportDisconnected = false;
9518
+ transportRecoveryPromise = null;
9519
+ transportDisconnectGeneration = 0;
9517
9520
  turns;
9518
9521
  toolNames;
9519
9522
  deviceStatusListeners = new Set;
@@ -9603,16 +9606,24 @@ class RemoteClientSessionCore {
9603
9606
  this.initialized = false;
9604
9607
  }
9605
9608
  async send(message) {
9609
+ if (this.closed)
9610
+ throw new Error("Session is closed");
9606
9611
  if (!this.initialized) {
9607
9612
  await this.initialize();
9608
9613
  }
9614
+ await this.recoverIdleTransportIfNeeded();
9609
9615
  if (!this.controller || !this.runtime) {
9610
9616
  throw new Error("Session is not initialized");
9611
9617
  }
9612
9618
  await this.beforeTurn();
9613
- const turn = this.turns.trackSentTurn(this.runtime);
9619
+ const controller = this.controller;
9620
+ const runtime = this.runtime;
9621
+ if (!controller || !runtime) {
9622
+ throw new Error("Session transport disconnected before the turn was sent");
9623
+ }
9624
+ const turn = this.turns.trackSentTurn(runtime);
9614
9625
  try {
9615
- this.controller.sendTurnMessage(this.runtime, message, {
9626
+ controller.sendTurnMessage(runtime, message, {
9616
9627
  clientMessageId: turn.clientMessageId
9617
9628
  });
9618
9629
  } catch (error) {
@@ -9887,6 +9898,7 @@ class RemoteClientSessionCore {
9887
9898
  this.deviceStatusListeners.clear();
9888
9899
  this.controller?.close();
9889
9900
  this.controller = null;
9901
+ this.idleTransportDisconnected = false;
9890
9902
  this.onCoreClose();
9891
9903
  }
9892
9904
  get agentId() {
@@ -9939,15 +9951,78 @@ class RemoteClientSessionCore {
9939
9951
  }, { predicate: (message) => message.type === "update_toolset_response" });
9940
9952
  ensureSuccess(response, "Failed to update toolset");
9941
9953
  }
9942
- watchTransportDisconnect(client) {
9954
+ watchTransportDisconnect(client, options = {}) {
9943
9955
  this.detachTransportDisconnect?.();
9944
9956
  this.detachTransportDisconnect = client.onDisconnect(() => {
9945
9957
  if (this.closed)
9946
9958
  return;
9959
+ this.transportDisconnectGeneration += 1;
9960
+ if (options.recoverWhenIdle && !this.turns.hasInFlightTurn()) {
9961
+ this.detachTransportDisconnect?.();
9962
+ this.detachTransportDisconnect = null;
9963
+ this.removeMessageHandler?.();
9964
+ this.removeMessageHandler = null;
9965
+ this.controller?.close();
9966
+ this.controller = null;
9967
+ const error = new Error(`${this.label} connection closed before send`);
9968
+ for (const cancel of [...this.deviceStatusRefreshCancels])
9969
+ cancel(error);
9970
+ this.deviceStatusRefreshCancels.clear();
9971
+ this.onIdleTransportDisconnect();
9972
+ this.idleTransportDisconnected = true;
9973
+ return;
9974
+ }
9947
9975
  this.turns.closeWithError(`The ${this.label} connection closed unexpectedly; resume the conversation to continue.`);
9948
9976
  this.close();
9949
9977
  });
9950
9978
  }
9979
+ async recoverIdleTransportIfNeeded() {
9980
+ if (!this.idleTransportDisconnected)
9981
+ return;
9982
+ if (this.transportRecoveryPromise) {
9983
+ await this.transportRecoveryPromise;
9984
+ return;
9985
+ }
9986
+ const runtime = this.runtime;
9987
+ if (!runtime)
9988
+ throw new Error("Session transport disconnected without a runtime");
9989
+ const generation = this.transportDisconnectGeneration;
9990
+ const recovery = this.recoverIdleTransport(runtime).then(async (init) => {
9991
+ if (this.closed || generation !== this.transportDisconnectGeneration) {
9992
+ init.controller.close();
9993
+ this.onRecoveredTransportDiscarded();
9994
+ throw new Error(`${this.label} connection closed during recovery`);
9995
+ }
9996
+ if (init.runtime.agent_id !== runtime.agent_id || init.runtime.conversation_id !== runtime.conversation_id) {
9997
+ init.controller.close();
9998
+ this.onRecoveredTransportDiscarded();
9999
+ throw new Error(`${this.label} transport recovered a different runtime`);
10000
+ }
10001
+ this.controller = init.controller;
10002
+ this.runtime = init.runtime;
10003
+ this._modelSettings = init.modelSettings ?? this._modelSettings;
10004
+ if (typeof init.model === "string" && init.model)
10005
+ this._model = init.model;
10006
+ if (init.tools !== undefined)
10007
+ this.toolNames = init.tools;
10008
+ this.removeMessageHandler = this.controller.onMessage((message) => {
10009
+ if (this.runtime)
10010
+ this.turns.handleProtocolMessage(message, this.runtime);
10011
+ });
10012
+ this.idleTransportDisconnected = false;
10013
+ await this.afterRuntimeInitialized();
10014
+ }).finally(() => {
10015
+ if (this.transportRecoveryPromise === recovery)
10016
+ this.transportRecoveryPromise = null;
10017
+ });
10018
+ this.transportRecoveryPromise = recovery;
10019
+ await recovery;
10020
+ }
10021
+ async recoverIdleTransport(_runtime) {
10022
+ throw new Error(`${this.label} sessions do not support idle transport recovery`);
10023
+ }
10024
+ onIdleTransportDisconnect() {}
10025
+ onRecoveredTransportDiscarded() {}
9951
10026
  async afterRuntimeInitialized() {}
9952
10027
  async beforeTurn() {}
9953
10028
  onCoreClose() {}
@@ -10691,6 +10766,132 @@ class CloudManagementTransport {
10691
10766
  }
10692
10767
  }
10693
10768
 
10769
+ // src/remote.ts
10770
+ function ensureOnline(environment, target) {
10771
+ if (!environment.connectionId) {
10772
+ const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
10773
+ throw new Error(`Computer is offline: ${label}`);
10774
+ }
10775
+ return {
10776
+ connectionId: environment.connectionId,
10777
+ environment,
10778
+ target
10779
+ };
10780
+ }
10781
+
10782
+ class RemoteEnvironmentClient {
10783
+ client;
10784
+ constructor(options = {}, client = createCloudClient({
10785
+ backend: "cloud",
10786
+ apiBaseUrl: options.baseUrl,
10787
+ apiKey: options.apiKey,
10788
+ headers: options.headers,
10789
+ fetch: options.fetch
10790
+ })) {
10791
+ this.client = client;
10792
+ }
10793
+ async listEnvironments(options = {}) {
10794
+ return await this.client.environments.list({
10795
+ after: options.after,
10796
+ limit: options.limit === undefined ? undefined : String(options.limit),
10797
+ onlineOnly: options.onlineOnly === undefined ? undefined : String(options.onlineOnly)
10798
+ });
10799
+ }
10800
+ async getEnvironmentByDeviceId(deviceId) {
10801
+ return await this.client.environments.retrieve(deviceId);
10802
+ }
10803
+ async resolveEnvironment(target) {
10804
+ if ("connectionId" in target) {
10805
+ return { connectionId: target.connectionId, target };
10806
+ }
10807
+ if ("deviceId" in target) {
10808
+ return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
10809
+ }
10810
+ const connections = [];
10811
+ let after;
10812
+ do {
10813
+ const page = await this.listEnvironments({ limit: 100, after });
10814
+ connections.push(...page.connections);
10815
+ if (!page.hasNextPage || page.connections.length === 0)
10816
+ break;
10817
+ after = page.connections.at(-1)?.id;
10818
+ } while (after !== undefined);
10819
+ if ("environmentId" in target) {
10820
+ const match = connections.find((env) => env.id === target.environmentId);
10821
+ if (!match) {
10822
+ throw new Error(`Remote environment not found: ${target.environmentId}`);
10823
+ }
10824
+ return ensureOnline(match, target);
10825
+ }
10826
+ const matches = connections.filter((env) => env.connectionName === target.connectionName);
10827
+ if (matches.length === 0) {
10828
+ throw new Error(`Computer not found: ${target.connectionName}`);
10829
+ }
10830
+ const onlineMatches = matches.filter((environment) => environment.connectionId !== null);
10831
+ if (onlineMatches.length === 0) {
10832
+ throw new Error(`Computer is offline: ${target.connectionName}`);
10833
+ }
10834
+ if (onlineMatches.length > 1) {
10835
+ const candidates = onlineMatches.map((environment) => `${environment.connectionName} (${environment.deviceId}, online)`).join(", ");
10836
+ throw new Error(`Computer name is ambiguous: ${target.connectionName}. Matches: ${candidates}. Select one by deviceId.`);
10837
+ }
10838
+ return ensureOnline(onlineMatches[0], target);
10839
+ }
10840
+ }
10841
+
10842
+ // src/computers.ts
10843
+ function selectorToRemoteTarget(selector) {
10844
+ if (typeof selector === "string")
10845
+ return { connectionName: selector };
10846
+ if ("name" in selector)
10847
+ return { connectionName: selector.name };
10848
+ if ("id" in selector)
10849
+ return { environmentId: selector.id };
10850
+ if ("connectionId" in selector) {
10851
+ return { connectionId: selector.connectionId };
10852
+ }
10853
+ return { deviceId: selector.deviceId };
10854
+ }
10855
+ function toComputer(environment) {
10856
+ return {
10857
+ id: environment.id,
10858
+ deviceId: environment.deviceId,
10859
+ connectionId: environment.connectionId,
10860
+ name: environment.connectionName,
10861
+ status: environment.connectionId ? "online" : "offline",
10862
+ connectedAt: environment.connectedAt,
10863
+ lastSeenAt: environment.lastSeenAt,
10864
+ metadata: environment.metadata
10865
+ };
10866
+ }
10867
+
10868
+ class ComputersClientImpl {
10869
+ environments;
10870
+ constructor(client) {
10871
+ this.environments = new RemoteEnvironmentClient({}, client);
10872
+ }
10873
+ async list(options = {}) {
10874
+ const result = await this.environments.listEnvironments(options);
10875
+ return {
10876
+ computers: result.connections.map(toComputer),
10877
+ hasNextPage: result.hasNextPage
10878
+ };
10879
+ }
10880
+ async get(deviceId) {
10881
+ if (typeof deviceId !== "string" || deviceId.trim().length === 0) {
10882
+ throw new Error("Invalid deviceId. Expected a non-empty string.");
10883
+ }
10884
+ return toComputer(await this.environments.getEnvironmentByDeviceId(deviceId));
10885
+ }
10886
+ async resolve(selector) {
10887
+ const result = await this.environments.resolveEnvironment(selectorToRemoteTarget(selector));
10888
+ return {
10889
+ connectionId: result.connectionId,
10890
+ computer: result.environment ? toComputer(result.environment) : undefined
10891
+ };
10892
+ }
10893
+ }
10894
+
10694
10895
  // src/cloud-status-transport.ts
10695
10896
  var CONNECTING = 0;
10696
10897
  var OPEN = 1;
@@ -10907,66 +11108,6 @@ function createCloudStatusTransportConstructor(options) {
10907
11108
  };
10908
11109
  }
10909
11110
 
10910
- // src/remote.ts
10911
- function ensureOnline(environment, target) {
10912
- if (!environment.connectionId) {
10913
- const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
10914
- throw new Error(`Remote environment is offline: ${label}`);
10915
- }
10916
- return {
10917
- connectionId: environment.connectionId,
10918
- environment,
10919
- target
10920
- };
10921
- }
10922
-
10923
- class RemoteEnvironmentClient {
10924
- client;
10925
- constructor(options = {}, client = createCloudClient({
10926
- backend: "cloud",
10927
- apiBaseUrl: options.baseUrl,
10928
- apiKey: options.apiKey,
10929
- headers: options.headers,
10930
- fetch: options.fetch
10931
- })) {
10932
- this.client = client;
10933
- }
10934
- async listEnvironments() {
10935
- return await this.client.environments.list();
10936
- }
10937
- async getEnvironmentByDeviceId(deviceId) {
10938
- return await this.client.environments.retrieve(deviceId);
10939
- }
10940
- async resolveEnvironment(target) {
10941
- if ("connectionId" in target) {
10942
- return { connectionId: target.connectionId, target };
10943
- }
10944
- if ("deviceId" in target) {
10945
- return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
10946
- }
10947
- const { connections } = await this.listEnvironments();
10948
- if ("environmentId" in target) {
10949
- const match2 = connections.find((env) => env.id === target.environmentId);
10950
- if (!match2) {
10951
- throw new Error(`Remote environment not found: ${target.environmentId}`);
10952
- }
10953
- return ensureOnline(match2, target);
10954
- }
10955
- const matches = connections.filter((env) => env.connectionName === target.connectionName);
10956
- if (matches.length === 0) {
10957
- throw new Error(`Remote environment not found: ${target.connectionName}`);
10958
- }
10959
- if (matches.length > 1) {
10960
- throw new Error(`Remote environment name is ambiguous: ${target.connectionName}`);
10961
- }
10962
- const match = matches[0];
10963
- if (!match) {
10964
- throw new Error(`Remote environment not found: ${target.connectionName}`);
10965
- }
10966
- return ensureOnline(match, target);
10967
- }
10968
- }
10969
-
10970
11111
  // src/cloud-sandbox.ts
10971
11112
  var MIN_TTL_MINUTES = 1;
10972
11113
  var MAX_TTL_MINUTES = 60;
@@ -11065,8 +11206,12 @@ function validatePositiveInteger3(value, name) {
11065
11206
  function validateCloudClientOptions(options) {
11066
11207
  validatePositiveInteger3(options.requestTimeoutMs, "requestTimeoutMs");
11067
11208
  validateCloudSandboxOptions(options.sandbox, "sandbox");
11068
- if (options.environment !== undefined && options.sandbox !== undefined) {
11069
- throw new Error("Letta Cloud sessions cannot specify both environment and sandbox options.");
11209
+ if (options.computer !== undefined && options.environment !== undefined) {
11210
+ throw new Error("Letta Cloud clients cannot specify both computer and deprecated environment.");
11211
+ }
11212
+ if ((options.computer !== undefined || options.environment !== undefined) && options.sandbox !== undefined) {
11213
+ const field = options.computer !== undefined ? "computer" : "environment";
11214
+ throw new Error(`Letta Cloud sessions cannot specify both ${field} and sandbox options.`);
11070
11215
  }
11071
11216
  if (options.webSocketAuth !== undefined && options.webSocketAuth !== "header" && options.webSocketAuth !== "query") {
11072
11217
  throw new Error("Invalid webSocketAuth. Valid values: header, query.");
@@ -11183,12 +11328,30 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11183
11328
  throw error;
11184
11329
  });
11185
11330
  this.connectionId = connection.connectionId;
11331
+ const options = this.currentOptions();
11332
+ this.mcpBridge = await connectMcpServers("mcpServers" in options ? options.mcpServers : undefined, {
11333
+ cwd: options.cwd,
11334
+ reservedToolNames: this.externalTools.keys()
11335
+ });
11336
+ for (const tool of this.mcpBridge.tools) {
11337
+ this.externalTools.set(tool.name, tool);
11338
+ }
11339
+ try {
11340
+ return await this.openCloudTransport(resolved.runtime, connection.connectionId);
11341
+ } catch (error) {
11342
+ await this.closeMcpBridge();
11343
+ await this.cleanupManagedSandbox();
11344
+ await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
11345
+ throw error;
11346
+ }
11347
+ }
11348
+ async openCloudTransport(runtime, connectionId) {
11186
11349
  const apiKey = getCloudApiKey(this.cloudOptions);
11187
11350
  const url = buildCloudStatusWebSocketUrl({
11188
11351
  apiBaseUrl: this.cloudOptions.apiBaseUrl,
11189
- connectionId: connection.connectionId,
11190
- agentId: resolved.runtime.agent_id,
11191
- conversationId: resolved.runtime.conversation_id,
11352
+ connectionId,
11353
+ agentId: runtime.agent_id,
11354
+ conversationId: runtime.conversation_id,
11192
11355
  apiKey,
11193
11356
  authMode: this.cloudOptions.webSocketAuth ?? "header"
11194
11357
  });
@@ -11199,33 +11362,19 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11199
11362
  WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
11200
11363
  ...(this.cloudOptions.webSocketAuth ?? "header") === "header" ? { headers: cloudWebSocketHeaders(this.cloudOptions) } : {},
11201
11364
  pingIntervalMs: this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
11202
- runtime: resolved.runtime
11365
+ runtime
11203
11366
  }),
11204
11367
  requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS
11205
11368
  }));
11206
11369
  const options = this.currentOptions();
11207
- this.mcpBridge = await connectMcpServers("mcpServers" in options ? options.mcpServers : undefined, {
11208
- cwd: options.cwd,
11209
- reservedToolNames: this.externalTools.keys()
11210
- });
11211
- for (const tool of this.mcpBridge.tools) {
11212
- this.externalTools.set(tool.name, tool);
11213
- }
11214
- this.removeControlRequestHandler = registerAppServerControlRequestHandler({
11215
- client,
11216
- getRuntime: () => this.runtime,
11217
- getOptions: () => this.currentOptions()
11218
- });
11219
- if (this.externalTools.size > 0) {
11220
- this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
11221
- }
11370
+ this.installTransportHandlers(client);
11222
11371
  try {
11223
11372
  await client.connect();
11224
- const response = await this.startCloudRuntime(client, resolved.runtime);
11373
+ const response = await this.startCloudRuntime(client, runtime);
11225
11374
  if (!response.success || !response.runtime) {
11226
11375
  throw new Error(response.error ?? "Failed to start Cloud status runtime");
11227
11376
  }
11228
- this.watchTransportDisconnect(client);
11377
+ this.watchTransportDisconnect(client, { recoverWhenIdle: true });
11229
11378
  const tools = agentToolNames(response.agent);
11230
11379
  const skillSources = options.skillSources;
11231
11380
  const clientToolset = "toolset" in options ? options.toolset : undefined;
@@ -11243,17 +11392,51 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11243
11392
  ...skillSources !== undefined ? { skillSources: [...skillSources] } : {}
11244
11393
  };
11245
11394
  } catch (error) {
11246
- this.removeExternalToolHandler?.();
11247
- this.removeExternalToolHandler = null;
11248
- this.removeControlRequestHandler?.();
11249
- this.removeControlRequestHandler = null;
11250
- await this.closeMcpBridge();
11395
+ this.cleanupTransportHandlers();
11251
11396
  client.close();
11252
- await this.cleanupManagedSandbox();
11253
- await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
11254
11397
  throw error;
11255
11398
  }
11256
11399
  }
11400
+ installTransportHandlers(client) {
11401
+ this.cleanupTransportHandlers();
11402
+ this.removeControlRequestHandler = registerAppServerControlRequestHandler({
11403
+ client,
11404
+ getRuntime: () => this.runtime,
11405
+ getOptions: () => this.currentOptions()
11406
+ });
11407
+ if (this.externalTools.size > 0) {
11408
+ this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
11409
+ }
11410
+ }
11411
+ cleanupTransportHandlers() {
11412
+ this.removeExternalToolHandler?.();
11413
+ this.removeExternalToolHandler = null;
11414
+ this.removeControlRequestHandler?.();
11415
+ this.removeControlRequestHandler = null;
11416
+ }
11417
+ async recoverIdleTransport(runtime) {
11418
+ const connection = await this.resolveRecoveryConnection(runtime);
11419
+ this.connectionId = connection.connectionId;
11420
+ return this.openCloudTransport(runtime, connection.connectionId);
11421
+ }
11422
+ async resolveRecoveryConnection(runtime) {
11423
+ const sandbox = this.managedSandbox;
11424
+ if (sandbox) {
11425
+ await this.refreshManagedSandbox(sandbox);
11426
+ return this.waitForManagedSandboxConnection(sandbox);
11427
+ }
11428
+ const environment = this.effectiveEnvironment();
11429
+ if (!environment) {
11430
+ throw new Error("Cloud idle transport recovery lost its execution target");
11431
+ }
11432
+ return this.resolveExplicitConnection(environment);
11433
+ }
11434
+ onIdleTransportDisconnect() {
11435
+ this.cleanupTransportHandlers();
11436
+ }
11437
+ onRecoveredTransportDiscarded() {
11438
+ this.cleanupTransportHandlers();
11439
+ }
11257
11440
  async startCloudRuntime(client, runtime) {
11258
11441
  const options = this.currentOptions();
11259
11442
  const command = {
@@ -11296,10 +11479,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11296
11479
  await this.refreshManagedSandbox(sandbox);
11297
11480
  }
11298
11481
  onCoreClose() {
11299
- this.removeExternalToolHandler?.();
11300
- this.removeExternalToolHandler = null;
11301
- this.removeControlRequestHandler?.();
11302
- this.removeControlRequestHandler = null;
11482
+ this.cleanupTransportHandlers();
11303
11483
  this.mcpCleanup = this.closeMcpBridge();
11304
11484
  this.cleanupManagedSandbox();
11305
11485
  if (this.runtime?.agent_id) {
@@ -11623,8 +11803,8 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11623
11803
  return new RemoteEnvironmentClient({}, this.apiClient);
11624
11804
  }
11625
11805
  effectiveEnvironment() {
11626
- const modeEnvironment = this.mode.kind === "session" ? this.mode.options.environment : undefined;
11627
- return modeEnvironment ?? this.cloudOptions.environment;
11806
+ const modeComputer = this.mode.kind === "session" ? this.mode.options.computer ?? this.mode.options.environment : undefined;
11807
+ return modeComputer ?? this.cloudOptions.computer ?? this.cloudOptions.environment;
11628
11808
  }
11629
11809
  effectiveSandboxOptions() {
11630
11810
  const modeSandbox = this.mode.kind === "session" ? this.mode.options.sandbox : undefined;
@@ -11924,14 +12104,17 @@ var VALID_BACKENDS = new Set([
11924
12104
  function isLettaCodeBackend(value) {
11925
12105
  return VALID_BACKENDS.has(value);
11926
12106
  }
11927
- function getOptionsEnvironment(options) {
11928
- if ("environment" in options) {
11929
- return options.environment;
12107
+ function getOptionsComputer(options) {
12108
+ if (!("computer" in options) && !("environment" in options))
12109
+ return;
12110
+ if (options.computer !== undefined && options.environment !== undefined) {
12111
+ throw new Error('Specify either "computer" or deprecated "environment", not both.');
11930
12112
  }
11931
- return;
12113
+ return options.computer ?? options.environment;
11932
12114
  }
11933
12115
  function stripCloudExecutionOptions(options) {
11934
12116
  const sessionOptions = { ...options };
12117
+ delete sessionOptions.computer;
11935
12118
  delete sessionOptions.environment;
11936
12119
  delete sessionOptions.sandbox;
11937
12120
  delete sessionOptions.filesystemConfinement;
@@ -11949,12 +12132,14 @@ function looksLikeConversationId(id) {
11949
12132
 
11950
12133
  class LettaAgentClientBase {
11951
12134
  backend;
12135
+ computer;
11952
12136
  environment;
11953
12137
  agents;
11954
12138
  conversations;
11955
12139
  models;
11956
12140
  options;
11957
12141
  repositoriesClient = null;
12142
+ computersClient = null;
11958
12143
  agentRepositoriesClient = null;
11959
12144
  cloudClient = null;
11960
12145
  managementTransport = null;
@@ -11964,16 +12149,19 @@ class LettaAgentClientBase {
11964
12149
  throw new Error(`Invalid Letta Code backend '${String(backend)}'. Valid values: local, remote, cloud.`);
11965
12150
  }
11966
12151
  this.backend = backend;
11967
- this.environment = getOptionsEnvironment(options);
12152
+ this.computer = getOptionsComputer(options);
12153
+ this.environment = this.computer;
11968
12154
  this.options = options;
11969
12155
  this.agents = createAgentsClient(() => this.getManagementTransport(), () => this.getAgentRepositoriesClient());
11970
12156
  this.conversations = createConversationsClient(() => this.getManagementTransport());
11971
12157
  this.models = createModelsClient(() => this.getManagementTransport());
11972
- if (this.backend === "local" && this.environment !== undefined) {
11973
- throw new Error('LettaAgentClient environment is only valid with backend: "cloud".');
12158
+ if (this.backend === "local" && this.computer !== undefined) {
12159
+ const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
12160
+ throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud".`);
11974
12161
  }
11975
- if (this.backend === "remote" && this.environment !== undefined) {
11976
- throw new Error('LettaAgentClient environment is only valid with backend: "cloud"; remote url selects the app-server runtime.');
12162
+ if (this.backend === "remote" && this.computer !== undefined) {
12163
+ const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
12164
+ throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud"; remote url selects the app-server runtime.`);
11977
12165
  }
11978
12166
  if (this.backend !== "cloud" && options.sandbox !== undefined) {
11979
12167
  throw new Error('LettaAgentClient sandbox options are only valid with backend: "cloud".');
@@ -12007,6 +12195,9 @@ class LettaAgentClientBase {
12007
12195
  get repositories() {
12008
12196
  return this.getRepositoriesClient();
12009
12197
  }
12198
+ get computers() {
12199
+ return this.getComputersClient();
12200
+ }
12010
12201
  async createAgent(options = {}) {
12011
12202
  if (hasCreateAgentEnvironment(options)) {
12012
12203
  throw new Error("createAgent() does not accept environment. Set a client default or pass environment to resumeSession()/createSession().");
@@ -12096,13 +12287,17 @@ class LettaAgentClientBase {
12096
12287
  }
12097
12288
  }
12098
12289
  assertSessionBackend(action, options) {
12290
+ if (options.computer !== undefined && options.environment !== undefined) {
12291
+ throw new Error(`${action}() cannot specify both computer and deprecated environment.`);
12292
+ }
12099
12293
  if (options.filesystemConfinement !== undefined && options.filesystemConfinement !== "memory") {
12100
12294
  throw new Error(`Invalid filesystemConfinement '${String(options.filesystemConfinement)}'. Valid value: memory.`);
12101
12295
  }
12102
- const effectiveEnvironment = options.environment ?? this.environment;
12296
+ const effectiveComputer = options.computer ?? options.environment ?? this.computer;
12103
12297
  if (this.backend === "local") {
12104
- if (effectiveEnvironment !== undefined) {
12105
- throw new Error(`${action}() environment overrides are only valid with backend: "cloud".`);
12298
+ if (effectiveComputer !== undefined) {
12299
+ const field = options.computer !== undefined ? "computer" : "environment";
12300
+ throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud".`);
12106
12301
  }
12107
12302
  if (options.sandbox !== undefined) {
12108
12303
  throw new Error(`${action}() sandbox options are only valid with backend: "cloud".`);
@@ -12122,8 +12317,9 @@ class LettaAgentClientBase {
12122
12317
  if (options.filesystemConfinement !== undefined) {
12123
12318
  throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
12124
12319
  }
12125
- if (options.environment !== undefined) {
12126
- throw new Error(`${action}() environment overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
12320
+ if (options.computer !== undefined || options.environment !== undefined) {
12321
+ const field = options.computer !== undefined ? "computer" : "environment";
12322
+ throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
12127
12323
  }
12128
12324
  if (options.sandbox !== undefined) {
12129
12325
  throw new Error(`${action}() sandbox options are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
@@ -12138,11 +12334,13 @@ class LettaAgentClientBase {
12138
12334
  throw new Error(`${action}() filesystemConfinement is only supported with backend: "local".`);
12139
12335
  }
12140
12336
  const cloudOptions = this.cloudOptions();
12141
- if (cloudOptions.environment !== undefined && options.sandbox !== undefined) {
12142
- throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default environment.`);
12337
+ if (this.computer !== undefined && options.sandbox !== undefined) {
12338
+ const field = cloudOptions.computer !== undefined ? "computer" : "environment";
12339
+ throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default ${field}.`);
12143
12340
  }
12144
- if (cloudOptions.sandbox !== undefined && options.environment !== undefined) {
12145
- throw new Error(`Letta Cloud ${action}() cannot specify an environment when the client has default sandbox options.`);
12341
+ if (cloudOptions.sandbox !== undefined && (options.computer !== undefined || options.environment !== undefined)) {
12342
+ const field = options.computer !== undefined ? "a computer" : "an environment";
12343
+ throw new Error(`Letta Cloud ${action}() cannot specify ${field} when the client has default sandbox options.`);
12146
12344
  }
12147
12345
  assertCloudSessionOptionsSupported(action, options);
12148
12346
  return;
@@ -12173,6 +12371,13 @@ class LettaAgentClientBase {
12173
12371
  appServerSessionOptions() {
12174
12372
  return this.remoteOptions();
12175
12373
  }
12374
+ getComputersClient() {
12375
+ if (this.backend !== "cloud") {
12376
+ throw new Error('client.computers is only available with backend: "cloud".');
12377
+ }
12378
+ this.computersClient ??= new ComputersClientImpl(this.getCloudClient());
12379
+ return this.computersClient;
12380
+ }
12176
12381
  getRepositoriesClient() {
12177
12382
  if (this.backend !== "cloud") {
12178
12383
  throw new Error('client.repositories is only available with backend: "cloud".');
@@ -29929,4 +30134,4 @@ export {
29929
30134
  CloudManagedSandboxExpiredError
29930
30135
  };
29931
30136
 
29932
- //# debugId=9E741E442389C4A864756E2164756E21
30137
+ //# debugId=C079C2D0B42E0C4F64756E2164756E21