@letta-ai/letta-agent-sdk 0.6.3 → 0.7.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.
@@ -55,6 +55,8 @@ export type RuntimeTurnResult = {
55
55
 
56
56
  export type RuntimeSendTurnOptions = {
57
57
  clientMessageId: string;
58
+ /** Caller-supplied OTID for the user message, when one was provided. */
59
+ otid?: string;
58
60
  };
59
61
 
60
62
  export type RuntimeRequestOptions = {
@@ -128,6 +130,8 @@ export type TurnTracker = {
128
130
  id: number;
129
131
  runtime: RuntimeScope;
130
132
  clientMessageId: string;
133
+ /** Caller-supplied OTID for this turn's user message, when one was provided. */
134
+ otid?: string;
131
135
  queuedAt: number;
132
136
  startedAt: number;
133
137
  assistantText: string;
@@ -677,3 +681,23 @@ export function toSessionDeviceStatus(
677
681
  export function normalizeSendMessage(message: SendMessage): string | MessageContentItem[] {
678
682
  return message;
679
683
  }
684
+
685
+ /**
686
+ * Validate a caller-supplied OTID. Empty/whitespace-only values would silently
687
+ * defeat correlation, so they are rejected instead of being dropped.
688
+ */
689
+ export function normalizeCallerOtid(otid: string | undefined): string | undefined {
690
+ if (otid === undefined) return undefined;
691
+ if (typeof otid !== "string" || otid.trim() === "") {
692
+ throw new Error("send() otid must be a non-empty string");
693
+ }
694
+ return otid;
695
+ }
696
+
697
+ /** Wire correlation options for a tracked turn. */
698
+ export function turnSendOptions(turn: TurnTracker): RuntimeSendTurnOptions {
699
+ return {
700
+ clientMessageId: turn.clientMessageId,
701
+ ...(turn.otid !== undefined ? { otid: turn.otid } : {}),
702
+ };
703
+ }
@@ -15,6 +15,7 @@ import {
15
15
  isApprovalConflictSignal,
16
16
  loopStatusRunIds,
17
17
  loopStatusValue,
18
+ normalizeCallerOtid,
18
19
  queueItems,
19
20
  sameRuntime,
20
21
  streamDeltaMessageType,
@@ -76,11 +77,19 @@ export class RemoteTurnCoordinator {
76
77
  return this.activeTurn !== null || this.pendingTurns.length > 0;
77
78
  }
78
79
 
79
- trackSentTurn(runtime: RuntimeScope): TurnTracker {
80
+ /**
81
+ * Start tracking a turn. A caller-supplied OTID doubles as the turn's
82
+ * `clientMessageId` so queue updates carry the same correlation id the
83
+ * persisted message will; otherwise the SDK mints one.
84
+ */
85
+ trackSentTurn(runtime: RuntimeScope, callerOtid?: string): TurnTracker {
86
+ const otid = normalizeCallerOtid(callerOtid);
80
87
  const turn: TurnTracker = {
81
88
  id: ++this.nextTurnId,
82
89
  runtime,
83
- clientMessageId: `sdk-message-${Date.now()}-${++this.clientMessageCounter}`,
90
+ ...(otid !== undefined ? { otid } : {}),
91
+ clientMessageId:
92
+ otid ?? `sdk-message-${Date.now()}-${++this.clientMessageCounter}`,
84
93
  queuedAt: Date.now(),
85
94
  startedAt: 0,
86
95
  assistantText: "",