@letta-ai/letta-agent-sdk 0.8.2 → 0.8.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.
@@ -6614,6 +6614,7 @@ function turnSendOptions(turn) {
6614
6614
 
6615
6615
  // src/remote-turn-coordinator.ts
6616
6616
  var MAX_RECENTLY_SETTLED_RUN_IDS = 256;
6617
+ var TRAILING_USAGE_GRACE_MS = 100;
6617
6618
 
6618
6619
  class RemoteTurnCoordinator {
6619
6620
  label;
@@ -6656,6 +6657,9 @@ class RemoteTurnCoordinator {
6656
6657
  observedTurnEvidence: false,
6657
6658
  observedRequiresApprovalStop: false,
6658
6659
  pendingTerminal: null,
6660
+ pendingTerminalTimeout: null,
6661
+ deferredMessages: [],
6662
+ deferredTurnEvidence: false,
6659
6663
  abortRequested: false,
6660
6664
  timeout: null
6661
6665
  };
@@ -6669,6 +6673,8 @@ class RemoteTurnCoordinator {
6669
6673
  removeTrackedTurn(turn) {
6670
6674
  if (turn.timeout)
6671
6675
  clearTimeout(turn.timeout);
6676
+ if (turn.pendingTerminalTimeout)
6677
+ clearTimeout(turn.pendingTerminalTimeout);
6672
6678
  if (this.activeTurn === turn) {
6673
6679
  this.activeTurn = null;
6674
6680
  return;
@@ -6699,6 +6705,29 @@ class RemoteTurnCoordinator {
6699
6705
  this.enqueue(sdkMessage2);
6700
6706
  return;
6701
6707
  }
6708
+ const deferredDelta = streamDeltaRecord(message);
6709
+ const deferredMessageType = deferredDelta ? streamDeltaMessageType(deferredDelta) : undefined;
6710
+ const trailingUsageTurn = this.activeTurn?.pendingTerminalTimeout ? this.activeTurn : null;
6711
+ if (trailingUsageTurn) {
6712
+ const statusRunIds = message.type === "update_loop_status" ? loopStatusRunIds(message) : [];
6713
+ const belongsToTerminalTurn = message.type === "update_loop_status" && statusRunIds.length > 0 && statusRunIds.every((runId) => trailingUsageTurn.runIds.has(runId));
6714
+ if (belongsToTerminalTurn) {
6715
+ this.handleLoopStatusMessage(message);
6716
+ return;
6717
+ }
6718
+ if (message.type === "update_loop_status" && statusRunIds.length === 0) {
6719
+ trailingUsageTurn.deferredMessages.push(message);
6720
+ return;
6721
+ }
6722
+ const isTurnScoped = deferredDelta !== null && deferredMessageType !== "ping" || message.type === "update_loop_status" || turnFinishedRecord(message) !== null;
6723
+ if (isTurnScoped && deferredMessageType !== "usage_statistics" || deferredMessageType === "usage_statistics" && trailingUsageTurn.deferredTurnEvidence) {
6724
+ trailingUsageTurn.deferredMessages.push(message);
6725
+ if (isTurnScoped && deferredMessageType !== "usage_statistics") {
6726
+ trailingUsageTurn.deferredTurnEvidence = true;
6727
+ }
6728
+ return;
6729
+ }
6730
+ }
6702
6731
  if (message.type === "update_loop_status") {
6703
6732
  this.handleLoopStatusMessage(message);
6704
6733
  return;
@@ -6711,7 +6740,8 @@ class RemoteTurnCoordinator {
6711
6740
  const delta = streamDeltaRecord(message);
6712
6741
  if (!delta)
6713
6742
  return;
6714
- const active = this.activateNextTurnFromProtocol();
6743
+ const messageType = streamDeltaMessageType(delta);
6744
+ const active = messageType === "usage_statistics" || messageType === "stop_reason" ? this.activeTurn : this.activateNextTurnFromProtocol();
6715
6745
  if (active) {
6716
6746
  active.observedTurnEvidence = true;
6717
6747
  const runId = streamDeltaRunId(delta);
@@ -6736,13 +6766,18 @@ class RemoteTurnCoordinator {
6736
6766
  closeWithError(detail) {
6737
6767
  if (this.closed)
6738
6768
  return;
6769
+ let completedCanonicalTurn = false;
6770
+ while (this.activeTurn?.pendingTerminal && this.activeTurn.pendingTerminalTimeout) {
6771
+ this.completeActiveTurn(this.activeTurn.pendingTerminal);
6772
+ completedCanonicalTurn = true;
6773
+ }
6739
6774
  const active = this.activeTurn;
6740
6775
  if (active) {
6741
6776
  this.failTurn(active, detail, {
6742
6777
  errorCode: "stream_closed",
6743
6778
  recoverable: true
6744
6779
  });
6745
- } else {
6780
+ } else if (!completedCanonicalTurn) {
6746
6781
  this.enqueue({
6747
6782
  type: "error",
6748
6783
  message: detail,
@@ -6760,9 +6795,14 @@ class RemoteTurnCoordinator {
6760
6795
  this.closed = true;
6761
6796
  if (this.activeTurn?.timeout)
6762
6797
  clearTimeout(this.activeTurn.timeout);
6798
+ if (this.activeTurn?.pendingTerminalTimeout) {
6799
+ clearTimeout(this.activeTurn.pendingTerminalTimeout);
6800
+ }
6763
6801
  for (const turn of this.pendingTurns) {
6764
6802
  if (turn.timeout)
6765
6803
  clearTimeout(turn.timeout);
6804
+ if (turn.pendingTerminalTimeout)
6805
+ clearTimeout(turn.pendingTerminalTimeout);
6766
6806
  }
6767
6807
  this.activeTurn = null;
6768
6808
  this.pendingTurns.length = 0;
@@ -6818,9 +6858,17 @@ class RemoteTurnCoordinator {
6818
6858
  clearTimeout(active.timeout);
6819
6859
  active.timeout = null;
6820
6860
  }
6861
+ if (active.pendingTerminalTimeout) {
6862
+ clearTimeout(active.pendingTerminalTimeout);
6863
+ active.pendingTerminalTimeout = null;
6864
+ }
6865
+ const deferredMessages = active.deferredMessages.splice(0);
6821
6866
  this.rememberSettledRunIds(active.runIds);
6822
6867
  this.enqueue(this.resultFromTurn(turn, active));
6823
6868
  this.activeTurn = null;
6869
+ for (const message of deferredMessages) {
6870
+ this.handleProtocolMessage(message, active.runtime);
6871
+ }
6824
6872
  }
6825
6873
  rememberSettledRunIds(runIds) {
6826
6874
  for (const runId of runIds) {
@@ -6885,11 +6933,13 @@ class RemoteTurnCoordinator {
6885
6933
  }
6886
6934
  }
6887
6935
  handleTurnFinished(finished) {
6888
- const active = this.activeTurn;
6889
- if (!active || !finished.runId)
6936
+ if (!finished.runId)
6890
6937
  return;
6891
6938
  if (this.settledRunIds.has(finished.runId))
6892
6939
  return;
6940
+ const active = this.activeTurn ?? this.activateNextTurnFromProtocol();
6941
+ if (!active)
6942
+ return;
6893
6943
  if (active.runIds.size > 0 && !active.runIds.has(finished.runId)) {
6894
6944
  return;
6895
6945
  }
@@ -6917,6 +6967,11 @@ class RemoteTurnCoordinator {
6917
6967
  };
6918
6968
  if (active.pendingTerminal) {
6919
6969
  active.pendingTerminal = terminal;
6970
+ if (active.timeout) {
6971
+ clearTimeout(active.timeout);
6972
+ active.timeout = null;
6973
+ }
6974
+ this.schedulePendingTerminal(active);
6920
6975
  return;
6921
6976
  }
6922
6977
  this.completeActiveTurn(terminal);
@@ -6940,7 +6995,9 @@ class RemoteTurnCoordinator {
6940
6995
  return;
6941
6996
  }
6942
6997
  if (messageType === "usage_statistics" && active.pendingTerminal) {
6943
- this.completeActiveTurn(active.pendingTerminal);
6998
+ if (active.pendingTerminalTimeout) {
6999
+ this.completeActiveTurn(active.pendingTerminal);
7000
+ }
6944
7001
  return;
6945
7002
  }
6946
7003
  if (sdkMessage?.type === "error") {
@@ -6954,6 +7011,16 @@ class RemoteTurnCoordinator {
6954
7011
  });
6955
7012
  }
6956
7013
  }
7014
+ schedulePendingTerminal(active) {
7015
+ if (active.pendingTerminalTimeout)
7016
+ return;
7017
+ active.pendingTerminalTimeout = setTimeout(() => {
7018
+ if (this.activeTurn !== active || !active.pendingTerminal)
7019
+ return;
7020
+ this.completeActiveTurn(active.pendingTerminal);
7021
+ }, TRAILING_USAGE_GRACE_MS);
7022
+ active.pendingTerminalTimeout.unref?.();
7023
+ }
6957
7024
  transformStreamDelta(delta) {
6958
7025
  const messageType = typeof delta.message_type === "string" ? delta.message_type : undefined;
6959
7026
  const runId = typeof delta.run_id === "string" ? delta.run_id : undefined;
@@ -8806,6 +8873,7 @@ var MAX_TTL_MINUTES = 60;
8806
8873
  var MAX_GITHUB_REPOSITORIES = 10;
8807
8874
  var GITHUB_OWNER_PATTERN = /^[A-Za-z0-9-]+$/;
8808
8875
  var GITHUB_REPOSITORY_PATTERN = /^[A-Za-z0-9._-]+$/;
8876
+ var GITHUB_COMMIT_PATTERN = /^[0-9a-fA-F]{40}$/;
8809
8877
  function validatePositiveInteger2(value, name) {
8810
8878
  if (value !== undefined && (!Number.isInteger(value) || value <= 0)) {
8811
8879
  throw new Error(`Invalid ${name}. Expected a positive integer.`);
@@ -8840,6 +8908,9 @@ function validateCloudSandboxOptions(options, name) {
8840
8908
  if (typeof repository.repo !== "string" || !GITHUB_REPOSITORY_PATTERN.test(repository.repo)) {
8841
8909
  throw new Error(`Invalid ${name}.githubRepositories[${index}].repo.`);
8842
8910
  }
8911
+ if (repository.commit !== undefined && (typeof repository.commit !== "string" || !GITHUB_COMMIT_PATTERN.test(repository.commit))) {
8912
+ throw new Error(`Invalid ${name}.githubRepositories[${index}].commit. Expected a full Git commit SHA.`);
8913
+ }
8843
8914
  }
8844
8915
  }
8845
8916
  if (options.terminateOnClose !== undefined && typeof options.terminateOnClose !== "boolean") {
@@ -10928,4 +10999,4 @@ export {
10928
10999
  CloudManagedSandboxExpiredError
10929
11000
  };
10930
11001
 
10931
- //# debugId=289B04BD4804EAF864756E2164756E21
11002
+ //# debugId=8CF5733E1C81C02264756E2164756E21