@letta-ai/letta-code 0.21.13 → 0.21.14
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/letta.js +148 -26
- package/package.json +1 -1
package/letta.js
CHANGED
|
@@ -3269,7 +3269,7 @@ var package_default;
|
|
|
3269
3269
|
var init_package = __esm(() => {
|
|
3270
3270
|
package_default = {
|
|
3271
3271
|
name: "@letta-ai/letta-code",
|
|
3272
|
-
version: "0.21.
|
|
3272
|
+
version: "0.21.14",
|
|
3273
3273
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3274
3274
|
type: "module",
|
|
3275
3275
|
bin: {
|
|
@@ -74338,6 +74338,84 @@ var init_check_approval = __esm(() => {
|
|
|
74338
74338
|
];
|
|
74339
74339
|
});
|
|
74340
74340
|
|
|
74341
|
+
// src/utils/createRelayedAbortController.ts
|
|
74342
|
+
function createRelayedAbortController(parentSignal) {
|
|
74343
|
+
const controller = new AbortController;
|
|
74344
|
+
if (!parentSignal) {
|
|
74345
|
+
return {
|
|
74346
|
+
controller,
|
|
74347
|
+
signal: controller.signal,
|
|
74348
|
+
cleanup: () => {}
|
|
74349
|
+
};
|
|
74350
|
+
}
|
|
74351
|
+
if (parentSignal.aborted) {
|
|
74352
|
+
controller.abort(parentSignal.reason);
|
|
74353
|
+
return {
|
|
74354
|
+
controller,
|
|
74355
|
+
signal: controller.signal,
|
|
74356
|
+
cleanup: () => {}
|
|
74357
|
+
};
|
|
74358
|
+
}
|
|
74359
|
+
const relayAbort = () => {
|
|
74360
|
+
controller.abort(parentSignal.reason);
|
|
74361
|
+
};
|
|
74362
|
+
parentSignal.addEventListener("abort", relayAbort, { once: true });
|
|
74363
|
+
return {
|
|
74364
|
+
controller,
|
|
74365
|
+
signal: controller.signal,
|
|
74366
|
+
cleanup: () => {
|
|
74367
|
+
parentSignal.removeEventListener("abort", relayAbort);
|
|
74368
|
+
}
|
|
74369
|
+
};
|
|
74370
|
+
}
|
|
74371
|
+
|
|
74372
|
+
// src/utils/streamAbortRelay.ts
|
|
74373
|
+
function composeCleanups(first, second) {
|
|
74374
|
+
let cleaned = false;
|
|
74375
|
+
return () => {
|
|
74376
|
+
if (cleaned) {
|
|
74377
|
+
return;
|
|
74378
|
+
}
|
|
74379
|
+
cleaned = true;
|
|
74380
|
+
first();
|
|
74381
|
+
second();
|
|
74382
|
+
};
|
|
74383
|
+
}
|
|
74384
|
+
function createStreamAbortRelay(parentSignal) {
|
|
74385
|
+
if (!parentSignal) {
|
|
74386
|
+
return null;
|
|
74387
|
+
}
|
|
74388
|
+
const requestAbort = createRelayedAbortController(parentSignal);
|
|
74389
|
+
let cleaned = false;
|
|
74390
|
+
const cleanup = () => {
|
|
74391
|
+
if (cleaned) {
|
|
74392
|
+
return;
|
|
74393
|
+
}
|
|
74394
|
+
cleaned = true;
|
|
74395
|
+
requestAbort.cleanup();
|
|
74396
|
+
};
|
|
74397
|
+
return {
|
|
74398
|
+
signal: requestAbort.signal,
|
|
74399
|
+
attach(stream2) {
|
|
74400
|
+
const existingCleanup = streamAbortRelayCleanupByStream.get(stream2);
|
|
74401
|
+
streamAbortRelayCleanupByStream.set(stream2, existingCleanup ? composeCleanups(existingCleanup, cleanup) : cleanup);
|
|
74402
|
+
},
|
|
74403
|
+
cleanup
|
|
74404
|
+
};
|
|
74405
|
+
}
|
|
74406
|
+
function cleanupStreamAbortRelay(stream2) {
|
|
74407
|
+
const cleanup = streamAbortRelayCleanupByStream.get(stream2);
|
|
74408
|
+
if (!cleanup) {
|
|
74409
|
+
return;
|
|
74410
|
+
}
|
|
74411
|
+
streamAbortRelayCleanupByStream.delete(stream2);
|
|
74412
|
+
cleanup();
|
|
74413
|
+
}
|
|
74414
|
+
var streamAbortRelayCleanupByStream;
|
|
74415
|
+
var init_streamAbortRelay = __esm(() => {
|
|
74416
|
+
streamAbortRelayCleanupByStream = new WeakMap;
|
|
74417
|
+
});
|
|
74418
|
+
|
|
74341
74419
|
// src/agent/approval-result-normalization.ts
|
|
74342
74420
|
function normalizeToolReturnText(value) {
|
|
74343
74421
|
if (typeof value === "string")
|
|
@@ -74582,19 +74660,23 @@ async function sendMessageStream(conversationId, messages, opts = { streamTokens
|
|
|
74582
74660
|
const firstOtid = messages[0]?.otid;
|
|
74583
74661
|
debugLog("send-message-stream", "request_start conversation_id=%s agent_id=%s messages=%s otid=%s stream_tokens=%s background=%s max_retries=%s", resolvedConversationId, opts.agentId ?? "none", messageSummary || "(empty)", firstOtid ?? "none", opts.streamTokens ?? true, opts.background ?? true, requestOptions.maxRetries ?? "default");
|
|
74584
74662
|
let stream2;
|
|
74663
|
+
const abortRelay = createStreamAbortRelay(requestOptions.signal);
|
|
74585
74664
|
try {
|
|
74586
74665
|
stream2 = await client.conversations.messages.create(resolvedConversationId, requestBody, {
|
|
74587
74666
|
...requestOptions,
|
|
74667
|
+
...abortRelay ? { signal: abortRelay.signal } : {},
|
|
74588
74668
|
headers: {
|
|
74589
74669
|
...requestOptions.headers ?? {},
|
|
74590
74670
|
...extraHeaders
|
|
74591
74671
|
}
|
|
74592
74672
|
});
|
|
74593
74673
|
} catch (error) {
|
|
74674
|
+
abortRelay?.cleanup();
|
|
74594
74675
|
debugWarn("send-message-stream", "request_error conversation_id=%s otid=%s status=%s error=%s", resolvedConversationId, firstOtid ?? "none", error?.status ?? "none", error instanceof Error ? error.message : String(error));
|
|
74595
74676
|
throw error;
|
|
74596
74677
|
}
|
|
74597
74678
|
debugLog("send-message-stream", "request_ok conversation_id=%s otid=%s", resolvedConversationId, firstOtid ?? "none");
|
|
74679
|
+
abortRelay?.attach(stream2);
|
|
74598
74680
|
if (requestStartTime !== undefined) {
|
|
74599
74681
|
streamRequestStartTimes.set(stream2, requestStartTime);
|
|
74600
74682
|
}
|
|
@@ -74611,6 +74693,7 @@ async function sendMessageStream(conversationId, messages, opts = { streamTokens
|
|
|
74611
74693
|
var streamRequestStartTimes, streamToolContextIds, streamRequestContexts;
|
|
74612
74694
|
var init_message = __esm(async () => {
|
|
74613
74695
|
init_debug();
|
|
74696
|
+
init_streamAbortRelay();
|
|
74614
74697
|
init_timing();
|
|
74615
74698
|
init_approval_result_normalization();
|
|
74616
74699
|
init_clientSkills();
|
|
@@ -76701,6 +76784,7 @@ async function drainStream(stream2, buffers, refresh, abortSignal, onFirstMessag
|
|
|
76701
76784
|
if (abortSignal) {
|
|
76702
76785
|
abortSignal.removeEventListener("abort", abortHandler);
|
|
76703
76786
|
}
|
|
76787
|
+
cleanupStreamAbortRelay(stream2);
|
|
76704
76788
|
clearLastSDKDiagnostic();
|
|
76705
76789
|
}
|
|
76706
76790
|
if (!stopReason && streamProcessor.stopReason) {
|
|
@@ -76792,15 +76876,23 @@ async function drainStreamWithResume(stream2, buffers, refresh, abortSignal, onF
|
|
|
76792
76876
|
const client = await lazyClient();
|
|
76793
76877
|
buffers.commitGeneration = (buffers.commitGeneration || 0) + 1;
|
|
76794
76878
|
buffers.interrupted = false;
|
|
76795
|
-
const
|
|
76796
|
-
|
|
76797
|
-
|
|
76798
|
-
|
|
76799
|
-
|
|
76800
|
-
|
|
76801
|
-
|
|
76802
|
-
|
|
76803
|
-
|
|
76879
|
+
const resumeAbortRelay = createStreamAbortRelay(abortSignal);
|
|
76880
|
+
let resumeStream;
|
|
76881
|
+
try {
|
|
76882
|
+
resumeStream = runIdSource === "otid" && streamOtid && streamRequestContext ? await client.conversations.messages.stream(streamRequestContext.resolvedConversationId, {
|
|
76883
|
+
agent_id: streamRequestContext.conversationId === "default" ? streamRequestContext.agentId ?? undefined : undefined,
|
|
76884
|
+
otid: streamOtid,
|
|
76885
|
+
starting_after: result.lastSeqId ?? 0,
|
|
76886
|
+
batch_size: 1000
|
|
76887
|
+
}, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined) : await client.runs.messages.stream(runIdToResume, {
|
|
76888
|
+
starting_after: result.lastSeqId ?? 0,
|
|
76889
|
+
batch_size: 1000
|
|
76890
|
+
}, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined);
|
|
76891
|
+
} catch (resumeError) {
|
|
76892
|
+
resumeAbortRelay?.cleanup();
|
|
76893
|
+
throw resumeError;
|
|
76894
|
+
}
|
|
76895
|
+
resumeAbortRelay?.attach(resumeStream);
|
|
76804
76896
|
const resumeResult = await drainStream(resumeStream, buffers, refresh, abortSignal, undefined, onChunkProcessed, contextTracker, seenSeqIdThreshold, true);
|
|
76805
76897
|
if (resumeResult.stopReason !== "error") {
|
|
76806
76898
|
debugWarn("stream", "[MID-STREAM RESUME] ✅ Success (runId=%s, stopReason=%s)", runIdToResume, resumeResult.stopReason);
|
|
@@ -76865,6 +76957,7 @@ var FALLBACK_RUN_DISCOVERY_TIMEOUT_MS = 5000;
|
|
|
76865
76957
|
var init_stream = __esm(async () => {
|
|
76866
76958
|
init_error();
|
|
76867
76959
|
init_debug();
|
|
76960
|
+
init_streamAbortRelay();
|
|
76868
76961
|
init_timing();
|
|
76869
76962
|
init_chunkLog();
|
|
76870
76963
|
await __promiseAll([
|
|
@@ -80804,15 +80897,23 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
80804
80897
|
try {
|
|
80805
80898
|
const client = await getClient();
|
|
80806
80899
|
const messageOtid = messages.map((item) => item.otid).find((value) => typeof value === "string");
|
|
80900
|
+
const resumeAbortRelay = createStreamAbortRelay(abortSignal);
|
|
80807
80901
|
if (abortSignal?.aborted) {
|
|
80808
80902
|
throw new Error("Cancelled by user");
|
|
80809
80903
|
}
|
|
80810
|
-
|
|
80811
|
-
|
|
80812
|
-
|
|
80813
|
-
|
|
80814
|
-
|
|
80815
|
-
|
|
80904
|
+
try {
|
|
80905
|
+
const resumeStream = await client.conversations.messages.stream(conversationId, {
|
|
80906
|
+
agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
|
|
80907
|
+
otid: messageOtid ?? undefined,
|
|
80908
|
+
starting_after: 0,
|
|
80909
|
+
batch_size: 1000
|
|
80910
|
+
}, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined);
|
|
80911
|
+
resumeAbortRelay?.attach(resumeStream);
|
|
80912
|
+
return resumeStream;
|
|
80913
|
+
} catch (resumeError) {
|
|
80914
|
+
resumeAbortRelay?.cleanup();
|
|
80915
|
+
throw resumeError;
|
|
80916
|
+
}
|
|
80816
80917
|
} catch (resumeError) {
|
|
80817
80918
|
if (abortSignal?.aborted) {
|
|
80818
80919
|
throw new Error("Cancelled by user");
|
|
@@ -80927,15 +81028,23 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
80927
81028
|
try {
|
|
80928
81029
|
const client = await getClient();
|
|
80929
81030
|
const messageOtid = messages.map((item) => item.otid).find((value) => typeof value === "string");
|
|
81031
|
+
const resumeAbortRelay = createStreamAbortRelay(abortSignal);
|
|
80930
81032
|
if (abortSignal?.aborted) {
|
|
80931
81033
|
throw new Error("Cancelled by user");
|
|
80932
81034
|
}
|
|
80933
|
-
|
|
80934
|
-
|
|
80935
|
-
|
|
80936
|
-
|
|
80937
|
-
|
|
80938
|
-
|
|
81035
|
+
try {
|
|
81036
|
+
const resumeStream = await client.conversations.messages.stream(conversationId, {
|
|
81037
|
+
agent_id: conversationId === "default" ? runtime.agentId ?? undefined : undefined,
|
|
81038
|
+
otid: messageOtid ?? undefined,
|
|
81039
|
+
starting_after: 0,
|
|
81040
|
+
batch_size: 1000
|
|
81041
|
+
}, resumeAbortRelay ? { signal: resumeAbortRelay.signal } : undefined);
|
|
81042
|
+
resumeAbortRelay?.attach(resumeStream);
|
|
81043
|
+
return resumeStream;
|
|
81044
|
+
} catch (resumeError) {
|
|
81045
|
+
resumeAbortRelay?.cleanup();
|
|
81046
|
+
throw resumeError;
|
|
81047
|
+
}
|
|
80939
81048
|
} catch (resumeError) {
|
|
80940
81049
|
if (abortSignal?.aborted) {
|
|
80941
81050
|
throw new Error("Cancelled by user");
|
|
@@ -80965,6 +81074,7 @@ var init_send = __esm(async () => {
|
|
|
80965
81074
|
init_errorFormatter();
|
|
80966
81075
|
init_diffPreview();
|
|
80967
81076
|
init_interactivePolicy();
|
|
81077
|
+
init_streamAbortRelay();
|
|
80968
81078
|
init_constants2();
|
|
80969
81079
|
init_cwd();
|
|
80970
81080
|
init_permissionMode();
|
|
@@ -83809,6 +83919,19 @@ function runDetachedListenerTask(commandName, task2) {
|
|
|
83809
83919
|
}
|
|
83810
83920
|
});
|
|
83811
83921
|
}
|
|
83922
|
+
async function replaySyncStateForRuntime(listenerRuntime, socket, scope, opts) {
|
|
83923
|
+
const syncScopedRuntime = getOrCreateScopedRuntime(listenerRuntime, scope.agent_id, scope.conversation_id);
|
|
83924
|
+
const recoverFn = opts?.recoverApprovalStateForSync ?? recoverApprovalStateForSync;
|
|
83925
|
+
try {
|
|
83926
|
+
await recoverFn(syncScopedRuntime, scope);
|
|
83927
|
+
} catch (error) {
|
|
83928
|
+
trackListenerError("listener_sync_recovery_failed", error, "listener_sync_recovery");
|
|
83929
|
+
if (isDebugEnabled()) {
|
|
83930
|
+
console.warn("[Listen] Sync approval recovery failed:", error);
|
|
83931
|
+
}
|
|
83932
|
+
}
|
|
83933
|
+
emitStateSync(socket, listenerRuntime, scope);
|
|
83934
|
+
}
|
|
83812
83935
|
function getParsedRuntimeScope(parsed) {
|
|
83813
83936
|
if (!parsed || typeof parsed !== "object" || !("runtime" in parsed)) {
|
|
83814
83937
|
return null;
|
|
@@ -84944,9 +85067,7 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
84944
85067
|
console.log(`[Listen V2] Dropping sync: runtime mismatch or closed`);
|
|
84945
85068
|
return;
|
|
84946
85069
|
}
|
|
84947
|
-
|
|
84948
|
-
await recoverApprovalStateForSync(syncScopedRuntime, parsed.runtime);
|
|
84949
|
-
emitStateSync(socket, runtime, parsed.runtime);
|
|
85070
|
+
await replaySyncStateForRuntime(runtime, socket, parsed.runtime);
|
|
84950
85071
|
return;
|
|
84951
85072
|
}
|
|
84952
85073
|
if (parsed.type === "input") {
|
|
@@ -85911,6 +86032,7 @@ var init_client4 = __esm(async () => {
|
|
|
85911
86032
|
handleCreateAgentCommand,
|
|
85912
86033
|
handleReflectionSettingsCommand,
|
|
85913
86034
|
scheduleQueuePump,
|
|
86035
|
+
replaySyncStateForRuntime,
|
|
85914
86036
|
recoverApprovalStateForSync,
|
|
85915
86037
|
clearRecoveredApprovalStateForScope: (runtime, scope) => clearRecoveredApprovalStateForScope(asListenerRuntimeForTests(runtime), scope),
|
|
85916
86038
|
emitStateSync
|
|
@@ -153424,4 +153546,4 @@ Error during initialization: ${message}`);
|
|
|
153424
153546
|
}
|
|
153425
153547
|
main();
|
|
153426
153548
|
|
|
153427
|
-
//# debugId=
|
|
153549
|
+
//# debugId=DEDBAA251791817164756E2164756E21
|