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

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/README.md CHANGED
@@ -44,12 +44,6 @@ for await (const message of session.stream()) {
44
44
  }
45
45
  ```
46
46
 
47
- Assistant and reasoning messages are incremental text fragments. Reconcile
48
- fragments by `type` and `otid` when `otid` is available; `uuid` is a legacy
49
- transport identifier and is not a portable lineage key. After reconnecting,
50
- use `(runId, seqId)` to suppress replayed fragments. Sequence IDs are scoped to
51
- their run and must not be compared across runs.
52
-
53
47
  An agent is the persistent entity with memory. A conversation is a thread on that agent. A session is the active connection used to send messages, stream events, execute tools, and handle approvals.
54
48
 
55
49
  - `createSession(agentId)` starts a new conversation.
@@ -86,7 +80,8 @@ approvals when a mobile or web client returns to the foreground:
86
80
  ```ts
87
81
  const status = await session.getDeviceStatus();
88
82
  // status.permissionMode, status.workingDirectory, status.isOnline,
89
- // status.isProcessing, status.pendingControlRequests, status.raw
83
+ // status.isProcessing, status.memoryDirectory,
84
+ // status.pendingControlRequests, status.raw
90
85
 
91
86
  const unsubscribe = session.onDeviceStatus((status) => {
92
87
  // Called for every device-status update pushed by the runtime.
@@ -5987,6 +5987,7 @@ function toSessionDeviceStatus(status) {
5987
5987
  isProcessing: status.is_processing,
5988
5988
  permissionMode,
5989
5989
  workingDirectory: status.current_working_directory,
5990
+ memoryDirectory: typeof status.memory_directory === "string" ? status.memory_directory : null,
5990
5991
  pendingControlRequests: pendingControlRequests(status),
5991
5992
  raw: { ...status }
5992
5993
  };
@@ -8298,6 +8299,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8298
8299
  sandboxRefreshInFlight = null;
8299
8300
  sandboxLifecycleClosing = false;
8300
8301
  attachedRepositoryIds = new Set;
8302
+ repositoryIdsRequiringCleanupRecompile = new Set;
8301
8303
  cloudMode;
8302
8304
  constructor(cloudOptions, mode) {
8303
8305
  super(mode, {
@@ -8311,7 +8313,10 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8311
8313
  }
8312
8314
  async initializeRuntimeController() {
8313
8315
  const resolved = await this.resolveRuntime();
8314
- const connection = await this.resolveConnectionForRuntime(resolved.runtime);
8316
+ const connection = await this.resolveConnectionForRuntime(resolved.runtime).catch(async (error) => {
8317
+ await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
8318
+ throw error;
8319
+ });
8315
8320
  this.connectionId = connection.connectionId;
8316
8321
  const apiKey = getCloudApiKey2(this.cloudOptions);
8317
8322
  const url = buildCloudStatusWebSocketUrl({
@@ -8366,7 +8371,7 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8366
8371
  this.removeControlRequestHandler = null;
8367
8372
  client.close();
8368
8373
  await this.cleanupManagedSandbox();
8369
- await this.cleanupSessionRepositories(resolved.runtime.agent_id);
8374
+ await this.cleanupSessionRepositories(resolved.runtime.agent_id, resolved.runtime.conversation_id);
8370
8375
  throw error;
8371
8376
  }
8372
8377
  }
@@ -8417,8 +8422,9 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8417
8422
  this.removeControlRequestHandler?.();
8418
8423
  this.removeControlRequestHandler = null;
8419
8424
  this.cleanupManagedSandbox();
8420
- if (this.runtime?.agent_id)
8421
- this.cleanupSessionRepositories(this.runtime.agent_id);
8425
+ if (this.runtime?.agent_id) {
8426
+ this.cleanupSessionRepositories(this.runtime.agent_id, this.runtime.conversation_id);
8427
+ }
8422
8428
  }
8423
8429
  async resolveRuntime() {
8424
8430
  let agentId = this.cloudMode.agentId;
@@ -8433,22 +8439,30 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8433
8439
  if (!agentId) {
8434
8440
  throw new Error("Letta Cloud createSession()/resumeSession() requires an agent id or conversation id.");
8435
8441
  }
8436
- await this.attachSessionRepositories(agentId);
8437
- if (this.cloudMode.newConversation) {
8438
- const conversation = await this.createConversation(agentId);
8439
- conversationId = conversation.id;
8440
- } else if (this.cloudMode.defaultConversation) {
8441
- conversationId = "default";
8442
- }
8443
- if (!conversationId) {
8444
- throw new Error("Letta Cloud createSession()/resumeSession() requires an agent id or conversation id.");
8442
+ const shouldRecompileRepositories = await this.attachSessionRepositories(agentId);
8443
+ try {
8444
+ if (this.cloudMode.newConversation) {
8445
+ const conversation = await this.createConversation(agentId);
8446
+ conversationId = conversation.id;
8447
+ } else if (this.cloudMode.defaultConversation) {
8448
+ conversationId = "default";
8449
+ }
8450
+ if (!conversationId) {
8451
+ throw new Error("Letta Cloud createSession()/resumeSession() requires an agent id or conversation id.");
8452
+ }
8453
+ if (shouldRecompileRepositories) {
8454
+ await this.recompileSystemPrompt(agentId, conversationId);
8455
+ }
8456
+ return { runtime: { agent_id: agentId, conversation_id: conversationId } };
8457
+ } catch (error) {
8458
+ await this.cleanupSessionRepositories(agentId, conversationId);
8459
+ throw error;
8445
8460
  }
8446
- return { runtime: { agent_id: agentId, conversation_id: conversationId } };
8447
8461
  }
8448
8462
  async attachSessionRepositories(agentId) {
8449
8463
  const resources = this.repositoryResources();
8450
8464
  if (resources.length === 0)
8451
- return;
8465
+ return false;
8452
8466
  const existing = await this.listAgentRepositories(agentId);
8453
8467
  const existingIds = new Set(existing.map((repository) => repository.id));
8454
8468
  try {
@@ -8464,15 +8478,42 @@ class CloudEnvironmentSession extends RemoteClientSessionCore {
8464
8478
  await this.cleanupSessionRepositories(agentId);
8465
8479
  throw error;
8466
8480
  }
8481
+ const shouldRecompile = resources.some((resource) => resource.recompile !== false);
8482
+ this.repositoryIdsRequiringCleanupRecompile = new Set(resources.filter((resource) => resource.recompile !== false && this.attachedRepositoryIds.has(resource.repositoryId)).map((resource) => resource.repositoryId));
8483
+ return shouldRecompile;
8467
8484
  }
8468
- async cleanupSessionRepositories(agentId) {
8485
+ async cleanupSessionRepositories(agentId, conversationId) {
8469
8486
  const repositoryIds = [...this.attachedRepositoryIds];
8487
+ const repositoryIdsRequiringRecompile = this.repositoryIdsRequiringCleanupRecompile;
8470
8488
  this.attachedRepositoryIds.clear();
8471
- await Promise.all(repositoryIds.map(async (repositoryId) => {
8489
+ this.repositoryIdsRequiringCleanupRecompile = new Set;
8490
+ const recompileAfterDetach = await Promise.all(repositoryIds.map(async (repositoryId) => {
8472
8491
  try {
8473
8492
  await this.unlinkAgentRepository(agentId, repositoryId);
8474
- } catch {}
8493
+ return repositoryIdsRequiringRecompile.has(repositoryId);
8494
+ } catch {
8495
+ return false;
8496
+ }
8475
8497
  }));
8498
+ if (recompileAfterDetach.some(Boolean)) {
8499
+ try {
8500
+ await this.recompileSystemPrompt(agentId, conversationId);
8501
+ } catch {}
8502
+ }
8503
+ }
8504
+ async recompileSystemPrompt(agentId, conversationId) {
8505
+ const fetchImpl = getFetch3(this.cloudOptions.fetch);
8506
+ const baseUrl = normalizeCloudApiBaseUrl2(this.cloudOptions.apiBaseUrl);
8507
+ const usesAgentPrompt = !conversationId || conversationId === "default";
8508
+ const path = usesAgentPrompt ? `/v1/agents/${encodeURIComponent(agentId)}/recompile` : `/v1/conversations/${encodeURIComponent(conversationId)}/recompile`;
8509
+ const url = `${baseUrl}${path}`;
8510
+ const response = await fetchImpl(url, {
8511
+ method: "POST",
8512
+ headers: cloudHeaders2(this.cloudOptions),
8513
+ body: JSON.stringify(usesAgentPrompt ? {} : { agent_id: agentId })
8514
+ });
8515
+ const body = await parseJsonResponse3(response);
8516
+ assertOkResponse2(response, body, "Cloud recompile system prompt", url);
8476
8517
  }
8477
8518
  repositoryResources() {
8478
8519
  const resources = this.cloudMode.options.resources ?? [];
@@ -9388,4 +9429,4 @@ export {
9388
9429
  CloudManagedSandboxExpiredError
9389
9430
  };
9390
9431
 
9391
- //# debugId=AAFE1DD6848E90C364756E2164756E21
9432
+ //# debugId=C4A49597208F4A6464756E2164756E21