@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.
@@ -9493,6 +9493,9 @@ class RemoteClientSessionCore {
9493
9493
  initializePromise = null;
9494
9494
  removeMessageHandler = null;
9495
9495
  detachTransportDisconnect = null;
9496
+ idleTransportDisconnected = false;
9497
+ transportRecoveryPromise = null;
9498
+ transportDisconnectGeneration = 0;
9496
9499
  turns;
9497
9500
  toolNames;
9498
9501
  deviceStatusListeners = new Set;
@@ -9582,16 +9585,24 @@ class RemoteClientSessionCore {
9582
9585
  this.initialized = false;
9583
9586
  }
9584
9587
  async send(message) {
9588
+ if (this.closed)
9589
+ throw new Error("Session is closed");
9585
9590
  if (!this.initialized) {
9586
9591
  await this.initialize();
9587
9592
  }
9593
+ await this.recoverIdleTransportIfNeeded();
9588
9594
  if (!this.controller || !this.runtime) {
9589
9595
  throw new Error("Session is not initialized");
9590
9596
  }
9591
9597
  await this.beforeTurn();
9592
- const turn = this.turns.trackSentTurn(this.runtime);
9598
+ const controller = this.controller;
9599
+ const runtime = this.runtime;
9600
+ if (!controller || !runtime) {
9601
+ throw new Error("Session transport disconnected before the turn was sent");
9602
+ }
9603
+ const turn = this.turns.trackSentTurn(runtime);
9593
9604
  try {
9594
- this.controller.sendTurnMessage(this.runtime, message, {
9605
+ controller.sendTurnMessage(runtime, message, {
9595
9606
  clientMessageId: turn.clientMessageId
9596
9607
  });
9597
9608
  } catch (error) {
@@ -9866,6 +9877,7 @@ class RemoteClientSessionCore {
9866
9877
  this.deviceStatusListeners.clear();
9867
9878
  this.controller?.close();
9868
9879
  this.controller = null;
9880
+ this.idleTransportDisconnected = false;
9869
9881
  this.onCoreClose();
9870
9882
  }
9871
9883
  get agentId() {
@@ -9918,15 +9930,78 @@ class RemoteClientSessionCore {
9918
9930
  }, { predicate: (message) => message.type === "update_toolset_response" });
9919
9931
  ensureSuccess(response, "Failed to update toolset");
9920
9932
  }
9921
- watchTransportDisconnect(client) {
9933
+ watchTransportDisconnect(client, options = {}) {
9922
9934
  this.detachTransportDisconnect?.();
9923
9935
  this.detachTransportDisconnect = client.onDisconnect(() => {
9924
9936
  if (this.closed)
9925
9937
  return;
9938
+ this.transportDisconnectGeneration += 1;
9939
+ if (options.recoverWhenIdle && !this.turns.hasInFlightTurn()) {
9940
+ this.detachTransportDisconnect?.();
9941
+ this.detachTransportDisconnect = null;
9942
+ this.removeMessageHandler?.();
9943
+ this.removeMessageHandler = null;
9944
+ this.controller?.close();
9945
+ this.controller = null;
9946
+ const error = new Error(`${this.label} connection closed before send`);
9947
+ for (const cancel of [...this.deviceStatusRefreshCancels])
9948
+ cancel(error);
9949
+ this.deviceStatusRefreshCancels.clear();
9950
+ this.onIdleTransportDisconnect();
9951
+ this.idleTransportDisconnected = true;
9952
+ return;
9953
+ }
9926
9954
  this.turns.closeWithError(`The ${this.label} connection closed unexpectedly; resume the conversation to continue.`);
9927
9955
  this.close();
9928
9956
  });
9929
9957
  }
9958
+ async recoverIdleTransportIfNeeded() {
9959
+ if (!this.idleTransportDisconnected)
9960
+ return;
9961
+ if (this.transportRecoveryPromise) {
9962
+ await this.transportRecoveryPromise;
9963
+ return;
9964
+ }
9965
+ const runtime = this.runtime;
9966
+ if (!runtime)
9967
+ throw new Error("Session transport disconnected without a runtime");
9968
+ const generation = this.transportDisconnectGeneration;
9969
+ const recovery = this.recoverIdleTransport(runtime).then(async (init) => {
9970
+ if (this.closed || generation !== this.transportDisconnectGeneration) {
9971
+ init.controller.close();
9972
+ this.onRecoveredTransportDiscarded();
9973
+ throw new Error(`${this.label} connection closed during recovery`);
9974
+ }
9975
+ if (init.runtime.agent_id !== runtime.agent_id || init.runtime.conversation_id !== runtime.conversation_id) {
9976
+ init.controller.close();
9977
+ this.onRecoveredTransportDiscarded();
9978
+ throw new Error(`${this.label} transport recovered a different runtime`);
9979
+ }
9980
+ this.controller = init.controller;
9981
+ this.runtime = init.runtime;
9982
+ this._modelSettings = init.modelSettings ?? this._modelSettings;
9983
+ if (typeof init.model === "string" && init.model)
9984
+ this._model = init.model;
9985
+ if (init.tools !== undefined)
9986
+ this.toolNames = init.tools;
9987
+ this.removeMessageHandler = this.controller.onMessage((message) => {
9988
+ if (this.runtime)
9989
+ this.turns.handleProtocolMessage(message, this.runtime);
9990
+ });
9991
+ this.idleTransportDisconnected = false;
9992
+ await this.afterRuntimeInitialized();
9993
+ }).finally(() => {
9994
+ if (this.transportRecoveryPromise === recovery)
9995
+ this.transportRecoveryPromise = null;
9996
+ });
9997
+ this.transportRecoveryPromise = recovery;
9998
+ await recovery;
9999
+ }
10000
+ async recoverIdleTransport(_runtime) {
10001
+ throw new Error(`${this.label} sessions do not support idle transport recovery`);
10002
+ }
10003
+ onIdleTransportDisconnect() {}
10004
+ onRecoveredTransportDiscarded() {}
9930
10005
  async afterRuntimeInitialized() {}
9931
10006
  async beforeTurn() {}
9932
10007
  onCoreClose() {}
@@ -10670,6 +10745,132 @@ class CloudManagementTransport {
10670
10745
  }
10671
10746
  }
10672
10747
 
10748
+ // src/remote.ts
10749
+ function ensureOnline(environment, target) {
10750
+ if (!environment.connectionId) {
10751
+ const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
10752
+ throw new Error(`Computer is offline: ${label}`);
10753
+ }
10754
+ return {
10755
+ connectionId: environment.connectionId,
10756
+ environment,
10757
+ target
10758
+ };
10759
+ }
10760
+
10761
+ class RemoteEnvironmentClient {
10762
+ client;
10763
+ constructor(options = {}, client = createCloudClient({
10764
+ backend: "cloud",
10765
+ apiBaseUrl: options.baseUrl,
10766
+ apiKey: options.apiKey,
10767
+ headers: options.headers,
10768
+ fetch: options.fetch
10769
+ })) {
10770
+ this.client = client;
10771
+ }
10772
+ async listEnvironments(options = {}) {
10773
+ return await this.client.environments.list({
10774
+ after: options.after,
10775
+ limit: options.limit === undefined ? undefined : String(options.limit),
10776
+ onlineOnly: options.onlineOnly === undefined ? undefined : String(options.onlineOnly)
10777
+ });
10778
+ }
10779
+ async getEnvironmentByDeviceId(deviceId) {
10780
+ return await this.client.environments.retrieve(deviceId);
10781
+ }
10782
+ async resolveEnvironment(target) {
10783
+ if ("connectionId" in target) {
10784
+ return { connectionId: target.connectionId, target };
10785
+ }
10786
+ if ("deviceId" in target) {
10787
+ return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
10788
+ }
10789
+ const connections = [];
10790
+ let after;
10791
+ do {
10792
+ const page = await this.listEnvironments({ limit: 100, after });
10793
+ connections.push(...page.connections);
10794
+ if (!page.hasNextPage || page.connections.length === 0)
10795
+ break;
10796
+ after = page.connections.at(-1)?.id;
10797
+ } while (after !== undefined);
10798
+ if ("environmentId" in target) {
10799
+ const match = connections.find((env) => env.id === target.environmentId);
10800
+ if (!match) {
10801
+ throw new Error(`Remote environment not found: ${target.environmentId}`);
10802
+ }
10803
+ return ensureOnline(match, target);
10804
+ }
10805
+ const matches = connections.filter((env) => env.connectionName === target.connectionName);
10806
+ if (matches.length === 0) {
10807
+ throw new Error(`Computer not found: ${target.connectionName}`);
10808
+ }
10809
+ const onlineMatches = matches.filter((environment) => environment.connectionId !== null);
10810
+ if (onlineMatches.length === 0) {
10811
+ throw new Error(`Computer is offline: ${target.connectionName}`);
10812
+ }
10813
+ if (onlineMatches.length > 1) {
10814
+ const candidates = onlineMatches.map((environment) => `${environment.connectionName} (${environment.deviceId}, online)`).join(", ");
10815
+ throw new Error(`Computer name is ambiguous: ${target.connectionName}. Matches: ${candidates}. Select one by deviceId.`);
10816
+ }
10817
+ return ensureOnline(onlineMatches[0], target);
10818
+ }
10819
+ }
10820
+
10821
+ // src/computers.ts
10822
+ function selectorToRemoteTarget(selector) {
10823
+ if (typeof selector === "string")
10824
+ return { connectionName: selector };
10825
+ if ("name" in selector)
10826
+ return { connectionName: selector.name };
10827
+ if ("id" in selector)
10828
+ return { environmentId: selector.id };
10829
+ if ("connectionId" in selector) {
10830
+ return { connectionId: selector.connectionId };
10831
+ }
10832
+ return { deviceId: selector.deviceId };
10833
+ }
10834
+ function toComputer(environment) {
10835
+ return {
10836
+ id: environment.id,
10837
+ deviceId: environment.deviceId,
10838
+ connectionId: environment.connectionId,
10839
+ name: environment.connectionName,
10840
+ status: environment.connectionId ? "online" : "offline",
10841
+ connectedAt: environment.connectedAt,
10842
+ lastSeenAt: environment.lastSeenAt,
10843
+ metadata: environment.metadata
10844
+ };
10845
+ }
10846
+
10847
+ class ComputersClientImpl {
10848
+ environments;
10849
+ constructor(client) {
10850
+ this.environments = new RemoteEnvironmentClient({}, client);
10851
+ }
10852
+ async list(options = {}) {
10853
+ const result = await this.environments.listEnvironments(options);
10854
+ return {
10855
+ computers: result.connections.map(toComputer),
10856
+ hasNextPage: result.hasNextPage
10857
+ };
10858
+ }
10859
+ async get(deviceId) {
10860
+ if (typeof deviceId !== "string" || deviceId.trim().length === 0) {
10861
+ throw new Error("Invalid deviceId. Expected a non-empty string.");
10862
+ }
10863
+ return toComputer(await this.environments.getEnvironmentByDeviceId(deviceId));
10864
+ }
10865
+ async resolve(selector) {
10866
+ const result = await this.environments.resolveEnvironment(selectorToRemoteTarget(selector));
10867
+ return {
10868
+ connectionId: result.connectionId,
10869
+ computer: result.environment ? toComputer(result.environment) : undefined
10870
+ };
10871
+ }
10872
+ }
10873
+
10673
10874
  // src/cloud-status-transport.ts
10674
10875
  var CONNECTING = 0;
10675
10876
  var OPEN = 1;
@@ -10886,66 +11087,6 @@ function createCloudStatusTransportConstructor(options) {
10886
11087
  };
10887
11088
  }
10888
11089
 
10889
- // src/remote.ts
10890
- function ensureOnline(environment, target) {
10891
- if (!environment.connectionId) {
10892
- const label = "deviceId" in target ? target.deviceId : ("environmentId" in target) ? target.environmentId : ("connectionName" in target) ? target.connectionName : environment.deviceId;
10893
- throw new Error(`Remote environment is offline: ${label}`);
10894
- }
10895
- return {
10896
- connectionId: environment.connectionId,
10897
- environment,
10898
- target
10899
- };
10900
- }
10901
-
10902
- class RemoteEnvironmentClient {
10903
- client;
10904
- constructor(options = {}, client = createCloudClient({
10905
- backend: "cloud",
10906
- apiBaseUrl: options.baseUrl,
10907
- apiKey: options.apiKey,
10908
- headers: options.headers,
10909
- fetch: options.fetch
10910
- })) {
10911
- this.client = client;
10912
- }
10913
- async listEnvironments() {
10914
- return await this.client.environments.list();
10915
- }
10916
- async getEnvironmentByDeviceId(deviceId) {
10917
- return await this.client.environments.retrieve(deviceId);
10918
- }
10919
- async resolveEnvironment(target) {
10920
- if ("connectionId" in target) {
10921
- return { connectionId: target.connectionId, target };
10922
- }
10923
- if ("deviceId" in target) {
10924
- return ensureOnline(await this.getEnvironmentByDeviceId(target.deviceId), target);
10925
- }
10926
- const { connections } = await this.listEnvironments();
10927
- if ("environmentId" in target) {
10928
- const match2 = connections.find((env) => env.id === target.environmentId);
10929
- if (!match2) {
10930
- throw new Error(`Remote environment not found: ${target.environmentId}`);
10931
- }
10932
- return ensureOnline(match2, target);
10933
- }
10934
- const matches = connections.filter((env) => env.connectionName === target.connectionName);
10935
- if (matches.length === 0) {
10936
- throw new Error(`Remote environment not found: ${target.connectionName}`);
10937
- }
10938
- if (matches.length > 1) {
10939
- throw new Error(`Remote environment name is ambiguous: ${target.connectionName}`);
10940
- }
10941
- const match = matches[0];
10942
- if (!match) {
10943
- throw new Error(`Remote environment not found: ${target.connectionName}`);
10944
- }
10945
- return ensureOnline(match, target);
10946
- }
10947
- }
10948
-
10949
11090
  // src/cloud-sandbox.ts
10950
11091
  var MIN_TTL_MINUTES = 1;
10951
11092
  var MAX_TTL_MINUTES = 60;
@@ -11044,8 +11185,12 @@ function validatePositiveInteger3(value, name) {
11044
11185
  function validateCloudClientOptions(options) {
11045
11186
  validatePositiveInteger3(options.requestTimeoutMs, "requestTimeoutMs");
11046
11187
  validateCloudSandboxOptions(options.sandbox, "sandbox");
11047
- if (options.environment !== undefined && options.sandbox !== undefined) {
11048
- throw new Error("Letta Cloud sessions cannot specify both environment and sandbox options.");
11188
+ if (options.computer !== undefined && options.environment !== undefined) {
11189
+ throw new Error("Letta Cloud clients cannot specify both computer and deprecated environment.");
11190
+ }
11191
+ if ((options.computer !== undefined || options.environment !== undefined) && options.sandbox !== undefined) {
11192
+ const field = options.computer !== undefined ? "computer" : "environment";
11193
+ throw new Error(`Letta Cloud sessions cannot specify both ${field} and sandbox options.`);
11049
11194
  }
11050
11195
  if (options.webSocketAuth !== undefined && options.webSocketAuth !== "header" && options.webSocketAuth !== "query") {
11051
11196
  throw new Error("Invalid webSocketAuth. Valid values: header, query.");
@@ -11162,12 +11307,30 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11162
11307
  throw error;
11163
11308
  });
11164
11309
  this.connectionId = connection.connectionId;
11310
+ const options = this.currentOptions();
11311
+ this.mcpBridge = await connectMcpServers("mcpServers" in options ? options.mcpServers : undefined, {
11312
+ cwd: options.cwd,
11313
+ reservedToolNames: this.externalTools.keys()
11314
+ });
11315
+ for (const tool of this.mcpBridge.tools) {
11316
+ this.externalTools.set(tool.name, tool);
11317
+ }
11318
+ try {
11319
+ return await this.openCloudTransport(resolved.runtime, connection.connectionId);
11320
+ } catch (error) {
11321
+ await this.closeMcpBridge();
11322
+ await this.cleanupManagedSandbox();
11323
+ await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
11324
+ throw error;
11325
+ }
11326
+ }
11327
+ async openCloudTransport(runtime, connectionId) {
11165
11328
  const apiKey = getCloudApiKey(this.cloudOptions);
11166
11329
  const url = buildCloudStatusWebSocketUrl({
11167
11330
  apiBaseUrl: this.cloudOptions.apiBaseUrl,
11168
- connectionId: connection.connectionId,
11169
- agentId: resolved.runtime.agent_id,
11170
- conversationId: resolved.runtime.conversation_id,
11331
+ connectionId,
11332
+ agentId: runtime.agent_id,
11333
+ conversationId: runtime.conversation_id,
11171
11334
  apiKey,
11172
11335
  authMode: this.cloudOptions.webSocketAuth ?? "header"
11173
11336
  });
@@ -11178,33 +11341,19 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11178
11341
  WebSocket: getWebSocketConstructor(this.cloudOptions.WebSocket),
11179
11342
  ...(this.cloudOptions.webSocketAuth ?? "header") === "header" ? { headers: cloudWebSocketHeaders(this.cloudOptions) } : {},
11180
11343
  pingIntervalMs: this.cloudOptions.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
11181
- runtime: resolved.runtime
11344
+ runtime
11182
11345
  }),
11183
11346
  requestTimeoutMs: this.cloudOptions.requestTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS
11184
11347
  }));
11185
11348
  const options = this.currentOptions();
11186
- this.mcpBridge = await connectMcpServers("mcpServers" in options ? options.mcpServers : undefined, {
11187
- cwd: options.cwd,
11188
- reservedToolNames: this.externalTools.keys()
11189
- });
11190
- for (const tool of this.mcpBridge.tools) {
11191
- this.externalTools.set(tool.name, tool);
11192
- }
11193
- this.removeControlRequestHandler = registerAppServerControlRequestHandler({
11194
- client,
11195
- getRuntime: () => this.runtime,
11196
- getOptions: () => this.currentOptions()
11197
- });
11198
- if (this.externalTools.size > 0) {
11199
- this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
11200
- }
11349
+ this.installTransportHandlers(client);
11201
11350
  try {
11202
11351
  await client.connect();
11203
- const response = await this.startCloudRuntime(client, resolved.runtime);
11352
+ const response = await this.startCloudRuntime(client, runtime);
11204
11353
  if (!response.success || !response.runtime) {
11205
11354
  throw new Error(response.error ?? "Failed to start Cloud status runtime");
11206
11355
  }
11207
- this.watchTransportDisconnect(client);
11356
+ this.watchTransportDisconnect(client, { recoverWhenIdle: true });
11208
11357
  const tools = agentToolNames(response.agent);
11209
11358
  const skillSources = options.skillSources;
11210
11359
  const clientToolset = "toolset" in options ? options.toolset : undefined;
@@ -11222,17 +11371,51 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11222
11371
  ...skillSources !== undefined ? { skillSources: [...skillSources] } : {}
11223
11372
  };
11224
11373
  } catch (error) {
11225
- this.removeExternalToolHandler?.();
11226
- this.removeExternalToolHandler = null;
11227
- this.removeControlRequestHandler?.();
11228
- this.removeControlRequestHandler = null;
11229
- await this.closeMcpBridge();
11374
+ this.cleanupTransportHandlers();
11230
11375
  client.close();
11231
- await this.cleanupManagedSandbox();
11232
- await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
11233
11376
  throw error;
11234
11377
  }
11235
11378
  }
11379
+ installTransportHandlers(client) {
11380
+ this.cleanupTransportHandlers();
11381
+ this.removeControlRequestHandler = registerAppServerControlRequestHandler({
11382
+ client,
11383
+ getRuntime: () => this.runtime,
11384
+ getOptions: () => this.currentOptions()
11385
+ });
11386
+ if (this.externalTools.size > 0) {
11387
+ this.removeExternalToolHandler = client.onExternalToolCall(createExternalToolCallHandler(this.externalTools));
11388
+ }
11389
+ }
11390
+ cleanupTransportHandlers() {
11391
+ this.removeExternalToolHandler?.();
11392
+ this.removeExternalToolHandler = null;
11393
+ this.removeControlRequestHandler?.();
11394
+ this.removeControlRequestHandler = null;
11395
+ }
11396
+ async recoverIdleTransport(runtime) {
11397
+ const connection = await this.resolveRecoveryConnection(runtime);
11398
+ this.connectionId = connection.connectionId;
11399
+ return this.openCloudTransport(runtime, connection.connectionId);
11400
+ }
11401
+ async resolveRecoveryConnection(runtime) {
11402
+ const sandbox = this.managedSandbox;
11403
+ if (sandbox) {
11404
+ await this.refreshManagedSandbox(sandbox);
11405
+ return this.waitForManagedSandboxConnection(sandbox);
11406
+ }
11407
+ const environment = this.effectiveEnvironment();
11408
+ if (!environment) {
11409
+ throw new Error("Cloud idle transport recovery lost its execution target");
11410
+ }
11411
+ return this.resolveExplicitConnection(environment);
11412
+ }
11413
+ onIdleTransportDisconnect() {
11414
+ this.cleanupTransportHandlers();
11415
+ }
11416
+ onRecoveredTransportDiscarded() {
11417
+ this.cleanupTransportHandlers();
11418
+ }
11236
11419
  async startCloudRuntime(client, runtime) {
11237
11420
  const options = this.currentOptions();
11238
11421
  const command = {
@@ -11275,10 +11458,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11275
11458
  await this.refreshManagedSandbox(sandbox);
11276
11459
  }
11277
11460
  onCoreClose() {
11278
- this.removeExternalToolHandler?.();
11279
- this.removeExternalToolHandler = null;
11280
- this.removeControlRequestHandler?.();
11281
- this.removeControlRequestHandler = null;
11461
+ this.cleanupTransportHandlers();
11282
11462
  this.mcpCleanup = this.closeMcpBridge();
11283
11463
  this.cleanupManagedSandbox();
11284
11464
  if (this.runtime?.agent_id) {
@@ -11602,8 +11782,8 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
11602
11782
  return new RemoteEnvironmentClient({}, this.apiClient);
11603
11783
  }
11604
11784
  effectiveEnvironment() {
11605
- const modeEnvironment = this.mode.kind === "session" ? this.mode.options.environment : undefined;
11606
- return modeEnvironment ?? this.cloudOptions.environment;
11785
+ const modeComputer = this.mode.kind === "session" ? this.mode.options.computer ?? this.mode.options.environment : undefined;
11786
+ return modeComputer ?? this.cloudOptions.computer ?? this.cloudOptions.environment;
11607
11787
  }
11608
11788
  effectiveSandboxOptions() {
11609
11789
  const modeSandbox = this.mode.kind === "session" ? this.mode.options.sandbox : undefined;
@@ -11903,14 +12083,17 @@ var VALID_BACKENDS = new Set([
11903
12083
  function isLettaCodeBackend(value) {
11904
12084
  return VALID_BACKENDS.has(value);
11905
12085
  }
11906
- function getOptionsEnvironment(options) {
11907
- if ("environment" in options) {
11908
- return options.environment;
12086
+ function getOptionsComputer(options) {
12087
+ if (!("computer" in options) && !("environment" in options))
12088
+ return;
12089
+ if (options.computer !== undefined && options.environment !== undefined) {
12090
+ throw new Error('Specify either "computer" or deprecated "environment", not both.');
11909
12091
  }
11910
- return;
12092
+ return options.computer ?? options.environment;
11911
12093
  }
11912
12094
  function stripCloudExecutionOptions(options) {
11913
12095
  const sessionOptions = { ...options };
12096
+ delete sessionOptions.computer;
11914
12097
  delete sessionOptions.environment;
11915
12098
  delete sessionOptions.sandbox;
11916
12099
  delete sessionOptions.filesystemConfinement;
@@ -11928,12 +12111,14 @@ function looksLikeConversationId(id) {
11928
12111
 
11929
12112
  class LettaAgentClientBase {
11930
12113
  backend;
12114
+ computer;
11931
12115
  environment;
11932
12116
  agents;
11933
12117
  conversations;
11934
12118
  models;
11935
12119
  options;
11936
12120
  repositoriesClient = null;
12121
+ computersClient = null;
11937
12122
  agentRepositoriesClient = null;
11938
12123
  cloudClient = null;
11939
12124
  managementTransport = null;
@@ -11943,16 +12128,19 @@ class LettaAgentClientBase {
11943
12128
  throw new Error(`Invalid Letta Code backend '${String(backend)}'. Valid values: local, remote, cloud.`);
11944
12129
  }
11945
12130
  this.backend = backend;
11946
- this.environment = getOptionsEnvironment(options);
12131
+ this.computer = getOptionsComputer(options);
12132
+ this.environment = this.computer;
11947
12133
  this.options = options;
11948
12134
  this.agents = createAgentsClient(() => this.getManagementTransport(), () => this.getAgentRepositoriesClient());
11949
12135
  this.conversations = createConversationsClient(() => this.getManagementTransport());
11950
12136
  this.models = createModelsClient(() => this.getManagementTransport());
11951
- if (this.backend === "local" && this.environment !== undefined) {
11952
- throw new Error('LettaAgentClient environment is only valid with backend: "cloud".');
12137
+ if (this.backend === "local" && this.computer !== undefined) {
12138
+ const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
12139
+ throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud".`);
11953
12140
  }
11954
- if (this.backend === "remote" && this.environment !== undefined) {
11955
- throw new Error('LettaAgentClient environment is only valid with backend: "cloud"; remote url selects the app-server runtime.');
12141
+ if (this.backend === "remote" && this.computer !== undefined) {
12142
+ const field = "computer" in options && options.computer !== undefined ? "computer" : "environment";
12143
+ throw new Error(`LettaAgentClient ${field} is only valid with backend: "cloud"; remote url selects the app-server runtime.`);
11956
12144
  }
11957
12145
  if (this.backend !== "cloud" && options.sandbox !== undefined) {
11958
12146
  throw new Error('LettaAgentClient sandbox options are only valid with backend: "cloud".');
@@ -11986,6 +12174,9 @@ class LettaAgentClientBase {
11986
12174
  get repositories() {
11987
12175
  return this.getRepositoriesClient();
11988
12176
  }
12177
+ get computers() {
12178
+ return this.getComputersClient();
12179
+ }
11989
12180
  async createAgent(options = {}) {
11990
12181
  if (hasCreateAgentEnvironment(options)) {
11991
12182
  throw new Error("createAgent() does not accept environment. Set a client default or pass environment to resumeSession()/createSession().");
@@ -12075,13 +12266,17 @@ class LettaAgentClientBase {
12075
12266
  }
12076
12267
  }
12077
12268
  assertSessionBackend(action, options) {
12269
+ if (options.computer !== undefined && options.environment !== undefined) {
12270
+ throw new Error(`${action}() cannot specify both computer and deprecated environment.`);
12271
+ }
12078
12272
  if (options.filesystemConfinement !== undefined && options.filesystemConfinement !== "memory") {
12079
12273
  throw new Error(`Invalid filesystemConfinement '${String(options.filesystemConfinement)}'. Valid value: memory.`);
12080
12274
  }
12081
- const effectiveEnvironment = options.environment ?? this.environment;
12275
+ const effectiveComputer = options.computer ?? options.environment ?? this.computer;
12082
12276
  if (this.backend === "local") {
12083
- if (effectiveEnvironment !== undefined) {
12084
- throw new Error(`${action}() environment overrides are only valid with backend: "cloud".`);
12277
+ if (effectiveComputer !== undefined) {
12278
+ const field = options.computer !== undefined ? "computer" : "environment";
12279
+ throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud".`);
12085
12280
  }
12086
12281
  if (options.sandbox !== undefined) {
12087
12282
  throw new Error(`${action}() sandbox options are only valid with backend: "cloud".`);
@@ -12101,8 +12296,9 @@ class LettaAgentClientBase {
12101
12296
  if (options.filesystemConfinement !== undefined) {
12102
12297
  throw new Error(`${action}() filesystemConfinement requires an SDK-owned local app-server process.`);
12103
12298
  }
12104
- if (options.environment !== undefined) {
12105
- throw new Error(`${action}() environment overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
12299
+ if (options.computer !== undefined || options.environment !== undefined) {
12300
+ const field = options.computer !== undefined ? "computer" : "environment";
12301
+ throw new Error(`${action}() ${field} overrides are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
12106
12302
  }
12107
12303
  if (options.sandbox !== undefined) {
12108
12304
  throw new Error(`${action}() sandbox options are only valid with backend: "cloud"; remote url selects the app-server runtime.`);
@@ -12117,11 +12313,13 @@ class LettaAgentClientBase {
12117
12313
  throw new Error(`${action}() filesystemConfinement is only supported with backend: "local".`);
12118
12314
  }
12119
12315
  const cloudOptions = this.cloudOptions();
12120
- if (cloudOptions.environment !== undefined && options.sandbox !== undefined) {
12121
- throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default environment.`);
12316
+ if (this.computer !== undefined && options.sandbox !== undefined) {
12317
+ const field = cloudOptions.computer !== undefined ? "computer" : "environment";
12318
+ throw new Error(`Letta Cloud ${action}() cannot specify sandbox options when the client has a default ${field}.`);
12122
12319
  }
12123
- if (cloudOptions.sandbox !== undefined && options.environment !== undefined) {
12124
- throw new Error(`Letta Cloud ${action}() cannot specify an environment when the client has default sandbox options.`);
12320
+ if (cloudOptions.sandbox !== undefined && (options.computer !== undefined || options.environment !== undefined)) {
12321
+ const field = options.computer !== undefined ? "a computer" : "an environment";
12322
+ throw new Error(`Letta Cloud ${action}() cannot specify ${field} when the client has default sandbox options.`);
12125
12323
  }
12126
12324
  assertCloudSessionOptionsSupported(action, options);
12127
12325
  return;
@@ -12152,6 +12350,13 @@ class LettaAgentClientBase {
12152
12350
  appServerSessionOptions() {
12153
12351
  return this.remoteOptions();
12154
12352
  }
12353
+ getComputersClient() {
12354
+ if (this.backend !== "cloud") {
12355
+ throw new Error('client.computers is only available with backend: "cloud".');
12356
+ }
12357
+ this.computersClient ??= new ComputersClientImpl(this.getCloudClient());
12358
+ return this.computersClient;
12359
+ }
12155
12360
  getRepositoriesClient() {
12156
12361
  if (this.backend !== "cloud") {
12157
12362
  throw new Error('client.repositories is only available with backend: "cloud".');
@@ -12287,4 +12492,4 @@ export {
12287
12492
  CloudManagedSandboxExpiredError
12288
12493
  };
12289
12494
 
12290
- //# debugId=B03015C0FF639CFA64756E2164756E21
12495
+ //# debugId=6E490415C5923C8964756E2164756E21