@letta-ai/letta-code 0.25.3 → 0.25.5
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 +1704 -718
- package/package.json +1 -1
- package/skills/acquiring-skills/SKILL.md +5 -5
- package/skills/migrating-memory/SKILL.md +3 -32
package/letta.js
CHANGED
|
@@ -3143,7 +3143,7 @@ var package_default;
|
|
|
3143
3143
|
var init_package = __esm(() => {
|
|
3144
3144
|
package_default = {
|
|
3145
3145
|
name: "@letta-ai/letta-code",
|
|
3146
|
-
version: "0.25.
|
|
3146
|
+
version: "0.25.5",
|
|
3147
3147
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3148
3148
|
type: "module",
|
|
3149
3149
|
bin: {
|
|
@@ -5756,13 +5756,16 @@ function isTruthyEnv(value) {
|
|
|
5756
5756
|
function isLocalBackendEnvEnabled(env = process.env) {
|
|
5757
5757
|
return isTruthyEnv(env[LOCAL_BACKEND_EXPERIMENTAL_ENV]);
|
|
5758
5758
|
}
|
|
5759
|
+
function isLocalBackendNoMemfsEnvEnabled(env = process.env) {
|
|
5760
|
+
return isTruthyEnv(env[LOCAL_BACKEND_NO_MEMFS_ENV]);
|
|
5761
|
+
}
|
|
5759
5762
|
function getLocalBackendStorageDir(homeDir = homedir3()) {
|
|
5760
5763
|
return process.env[LOCAL_BACKEND_DIR_ENV] ?? join3(homeDir, ".letta", "lc-local-backend");
|
|
5761
5764
|
}
|
|
5762
5765
|
function getLocalBackendMemoryFilesystemRoot(agentId, storageDir = getLocalBackendStorageDir()) {
|
|
5763
5766
|
return join3(storageDir, "memfs", agentId, "memory");
|
|
5764
5767
|
}
|
|
5765
|
-
var LOCAL_BACKEND_DIR_ENV = "LETTA_LOCAL_BACKEND_DIR", LOCAL_BACKEND_EXPERIMENTAL_ENV = "LETTA_LOCAL_BACKEND_EXPERIMENTAL";
|
|
5768
|
+
var LOCAL_BACKEND_DIR_ENV = "LETTA_LOCAL_BACKEND_DIR", LOCAL_BACKEND_EXPERIMENTAL_ENV = "LETTA_LOCAL_BACKEND_EXPERIMENTAL", LOCAL_BACKEND_NO_MEMFS_ENV = "LETTA_LOCAL_BACKEND_NO_MEMFS";
|
|
5766
5769
|
var init_paths = () => {};
|
|
5767
5770
|
|
|
5768
5771
|
// src/agent/memoryGit.ts
|
|
@@ -5918,6 +5921,11 @@ function getMemoryRemoteUrl(agentId) {
|
|
|
5918
5921
|
return getGitRemoteUrl(agentId);
|
|
5919
5922
|
}
|
|
5920
5923
|
async function getAuthToken() {
|
|
5924
|
+
const { getBackend } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
5925
|
+
const backend = getBackend();
|
|
5926
|
+
if (backend.capabilities.localMemfs && !backend.capabilities.remoteMemfs) {
|
|
5927
|
+
return "";
|
|
5928
|
+
}
|
|
5921
5929
|
const client = await getClient();
|
|
5922
5930
|
return client._options?.apiKey ?? "";
|
|
5923
5931
|
}
|
|
@@ -5969,7 +5977,7 @@ async function runGit(cwd, args, token) {
|
|
|
5969
5977
|
const result = await execFile("git", allArgs, {
|
|
5970
5978
|
cwd,
|
|
5971
5979
|
env: buildNonInteractiveGitEnv(),
|
|
5972
|
-
maxBuffer:
|
|
5980
|
+
maxBuffer: 10485760,
|
|
5973
5981
|
timeout: 60000
|
|
5974
5982
|
});
|
|
5975
5983
|
return {
|
|
@@ -6101,9 +6109,9 @@ async function unsetLocalGitConfig(dir, key) {
|
|
|
6101
6109
|
async function fetchAgentDisplayName(agentId) {
|
|
6102
6110
|
let timeout;
|
|
6103
6111
|
try {
|
|
6104
|
-
const
|
|
6112
|
+
const { getBackend } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
6105
6113
|
const agent = await Promise.race([
|
|
6106
|
-
|
|
6114
|
+
getBackend().retrieveAgent(agentId),
|
|
6107
6115
|
new Promise((resolve2) => {
|
|
6108
6116
|
timeout = setTimeout(() => resolve2(null), AGENT_DISPLAY_NAME_TIMEOUT_MS);
|
|
6109
6117
|
})
|
|
@@ -6714,12 +6722,13 @@ async function getMemoryGitStatus(agentId) {
|
|
|
6714
6722
|
};
|
|
6715
6723
|
}
|
|
6716
6724
|
async function addGitMemoryTag(agentId, prefetchedAgent) {
|
|
6717
|
-
const client = await getClient();
|
|
6718
6725
|
try {
|
|
6719
|
-
const
|
|
6726
|
+
const { getBackend } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
6727
|
+
const backend = getBackend();
|
|
6728
|
+
const agent = prefetchedAgent ?? await backend.retrieveAgent(agentId);
|
|
6720
6729
|
const tags = agent.tags || [];
|
|
6721
6730
|
if (!tags.includes(GIT_MEMORY_ENABLED_TAG)) {
|
|
6722
|
-
await
|
|
6731
|
+
await backend.updateAgent(agentId, {
|
|
6723
6732
|
tags: [...tags, GIT_MEMORY_ENABLED_TAG]
|
|
6724
6733
|
});
|
|
6725
6734
|
debugLog("memfs-git", `Added ${GIT_MEMORY_ENABLED_TAG} tag`);
|
|
@@ -6729,12 +6738,13 @@ async function addGitMemoryTag(agentId, prefetchedAgent) {
|
|
|
6729
6738
|
}
|
|
6730
6739
|
}
|
|
6731
6740
|
async function removeGitMemoryTag(agentId) {
|
|
6732
|
-
const client = await getClient();
|
|
6733
6741
|
try {
|
|
6734
|
-
const
|
|
6742
|
+
const { getBackend } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
6743
|
+
const backend = getBackend();
|
|
6744
|
+
const agent = await backend.retrieveAgent(agentId);
|
|
6735
6745
|
const tags = agent.tags || [];
|
|
6736
6746
|
if (tags.includes(GIT_MEMORY_ENABLED_TAG)) {
|
|
6737
|
-
await
|
|
6747
|
+
await backend.updateAgent(agentId, {
|
|
6738
6748
|
tags: tags.filter((t) => t !== GIT_MEMORY_ENABLED_TAG)
|
|
6739
6749
|
});
|
|
6740
6750
|
debugLog("memfs-git", `Removed ${GIT_MEMORY_ENABLED_TAG} tag`);
|
|
@@ -64368,6 +64378,8 @@ function createChatGPTFetch(options) {
|
|
|
64368
64378
|
const auth = await getFreshAuth(options.storageDir);
|
|
64369
64379
|
next.headers.delete("authorization");
|
|
64370
64380
|
next.headers.set("authorization", `Bearer ${auth.access}`);
|
|
64381
|
+
next.headers.set("OpenAI-Beta", "responses=v1");
|
|
64382
|
+
next.headers.set("OpenAI-Originator", "codex");
|
|
64371
64383
|
if (auth.accountId) {
|
|
64372
64384
|
next.headers.set("ChatGPT-Account-Id", auth.accountId);
|
|
64373
64385
|
}
|
|
@@ -69891,6 +69903,9 @@ function anthropicThinking(value, modelHandle) {
|
|
|
69891
69903
|
function aiSDKProviderKind(modelHandle, modelSettings) {
|
|
69892
69904
|
return aiSDKProviderKindFromModel(modelHandle, modelSettings);
|
|
69893
69905
|
}
|
|
69906
|
+
function isChatGPTOAuthModel(modelHandle, modelSettings) {
|
|
69907
|
+
return modelHandle.startsWith("chatgpt-plus-pro/") || stringValue(modelSettings.provider_type) === "chatgpt_oauth";
|
|
69908
|
+
}
|
|
69894
69909
|
function partProviderMetadata(part) {
|
|
69895
69910
|
if (!isRecord2(part))
|
|
69896
69911
|
return;
|
|
@@ -69916,22 +69931,153 @@ function shouldKeepReasoningPart(part, provider) {
|
|
|
69916
69931
|
return hasAnthropicReasoningMetadata(part);
|
|
69917
69932
|
return true;
|
|
69918
69933
|
}
|
|
69919
|
-
function
|
|
69934
|
+
function stringArray(value) {
|
|
69935
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : undefined;
|
|
69936
|
+
}
|
|
69937
|
+
function mimeToModality(mime) {
|
|
69938
|
+
if (mime.startsWith("image/"))
|
|
69939
|
+
return "image";
|
|
69940
|
+
if (mime.startsWith("audio/"))
|
|
69941
|
+
return "audio";
|
|
69942
|
+
if (mime.startsWith("video/"))
|
|
69943
|
+
return "video";
|
|
69944
|
+
if (mime === "application/pdf")
|
|
69945
|
+
return "pdf";
|
|
69946
|
+
return;
|
|
69947
|
+
}
|
|
69948
|
+
function modalitiesFromModelSettings(modelSettings) {
|
|
69949
|
+
const modalities = isRecord2(modelSettings.modalities) ? modelSettings.modalities : undefined;
|
|
69950
|
+
const input = stringArray(modalities?.input);
|
|
69951
|
+
if (!input)
|
|
69952
|
+
return;
|
|
69953
|
+
return new Set(input.filter((entry) => ["text", "image", "audio", "video", "pdf"].includes(entry)));
|
|
69954
|
+
}
|
|
69955
|
+
function capabilitiesFromModelSettings(modelSettings) {
|
|
69956
|
+
const capabilities = isRecord2(modelSettings.capabilities) ? modelSettings.capabilities : undefined;
|
|
69957
|
+
const input = isRecord2(capabilities?.input) ? capabilities.input : undefined;
|
|
69958
|
+
if (!input)
|
|
69959
|
+
return;
|
|
69960
|
+
const supported = new Set(["text"]);
|
|
69961
|
+
for (const modality of ["image", "audio", "video", "pdf"]) {
|
|
69962
|
+
if (input[modality] === true)
|
|
69963
|
+
supported.add(modality);
|
|
69964
|
+
}
|
|
69965
|
+
return supported;
|
|
69966
|
+
}
|
|
69967
|
+
function knownModelInputModalities(modelHandle, modelSettings) {
|
|
69968
|
+
const explicitModalities = modalitiesFromModelSettings(modelSettings);
|
|
69969
|
+
if (explicitModalities)
|
|
69970
|
+
return explicitModalities;
|
|
69971
|
+
const explicitCapabilities = capabilitiesFromModelSettings(modelSettings);
|
|
69972
|
+
if (explicitCapabilities)
|
|
69973
|
+
return explicitCapabilities;
|
|
69974
|
+
const handle = modelHandle.toLowerCase();
|
|
69975
|
+
const supported = new Set(["text"]);
|
|
69976
|
+
if (handle.startsWith("anthropic/") || handle.startsWith("claude-pro-max/") || handle.startsWith("bedrock/") || handle.startsWith("google_ai/") || handle.startsWith("google_vertex/") || handle.includes("gemini") || handle.includes("claude") || handle.includes("gpt-4o") || handle.includes("gpt-4.1") || handle.includes("gpt-5") || handle.includes("o3") || handle.includes("o4") || handle.includes("vision") || handle.includes("qwen-vl") || handle.includes("qwen2-vl") || handle.includes("qwen2.5-vl") || handle.includes("qwen3-vl") || handle.includes("llava") || handle.includes("bakllava") || handle.includes("moondream")) {
|
|
69977
|
+
supported.add("image");
|
|
69978
|
+
}
|
|
69979
|
+
return supported;
|
|
69980
|
+
}
|
|
69981
|
+
function modelSupportsInputModality(modelHandle, modelSettings, modality) {
|
|
69982
|
+
if (modality === "text")
|
|
69983
|
+
return true;
|
|
69984
|
+
return knownModelInputModalities(modelHandle, modelSettings).has(modality);
|
|
69985
|
+
}
|
|
69986
|
+
function isEmptyBase64DataUrl(data) {
|
|
69987
|
+
if (typeof data !== "string" || !data.startsWith("data:"))
|
|
69988
|
+
return false;
|
|
69989
|
+
const match = data.match(/^data:([^;]+);base64,(.*)$/);
|
|
69990
|
+
return Boolean(match && (!match[2] || match[2].length === 0));
|
|
69991
|
+
}
|
|
69992
|
+
function filePartMediaType(part) {
|
|
69993
|
+
if (typeof part.mediaType === "string")
|
|
69994
|
+
return part.mediaType;
|
|
69995
|
+
if (typeof part.mime === "string")
|
|
69996
|
+
return part.mime;
|
|
69997
|
+
return;
|
|
69998
|
+
}
|
|
69999
|
+
function imagePartMediaType(part) {
|
|
70000
|
+
if (typeof part.image === "string" && part.image.startsWith("data:")) {
|
|
70001
|
+
return part.image.split(";")[0]?.replace("data:", "");
|
|
70002
|
+
}
|
|
70003
|
+
if (isRecord2(part.source) && typeof part.source.media_type === "string") {
|
|
70004
|
+
return part.source.media_type;
|
|
70005
|
+
}
|
|
70006
|
+
return;
|
|
70007
|
+
}
|
|
70008
|
+
function partFilename(part) {
|
|
70009
|
+
return stringValue(part.filename) ?? stringValue(part.name);
|
|
70010
|
+
}
|
|
70011
|
+
function replaceUnsupportedInputPart(part, agent) {
|
|
70012
|
+
if (!isRecord2(part))
|
|
70013
|
+
return part;
|
|
70014
|
+
const record2 = part;
|
|
70015
|
+
const partType = typeof record2.type === "string" ? record2.type : undefined;
|
|
70016
|
+
if (partType !== "file" && partType !== "image") {
|
|
70017
|
+
return part;
|
|
70018
|
+
}
|
|
70019
|
+
if (partType === "image" && isEmptyBase64DataUrl(record2.image)) {
|
|
70020
|
+
return {
|
|
70021
|
+
type: "text",
|
|
70022
|
+
text: "ERROR: Image file is empty or corrupted. Please provide a valid image."
|
|
70023
|
+
};
|
|
70024
|
+
}
|
|
70025
|
+
const mime = partType === "image" ? imagePartMediaType(record2) : filePartMediaType(record2);
|
|
70026
|
+
if (!mime)
|
|
70027
|
+
return part;
|
|
70028
|
+
const modality = mimeToModality(mime);
|
|
70029
|
+
if (!modality)
|
|
70030
|
+
return part;
|
|
70031
|
+
if (modelSupportsInputModality(agent.model, agent.model_settings, modality)) {
|
|
70032
|
+
return part;
|
|
70033
|
+
}
|
|
70034
|
+
const name25 = partFilename(record2);
|
|
70035
|
+
return {
|
|
70036
|
+
type: "text",
|
|
70037
|
+
text: `ERROR: Cannot read ${name25 ? `"${name25}"` : modality} (this model does not support ${modality} input). Inform the user.`
|
|
70038
|
+
};
|
|
70039
|
+
}
|
|
70040
|
+
function replaceUnsupportedInputParts(messages, agent) {
|
|
70041
|
+
let didChange = false;
|
|
70042
|
+
const transformed = messages.map((message) => {
|
|
70043
|
+
if (message.role !== "user")
|
|
70044
|
+
return message;
|
|
70045
|
+
let messageDidChange = false;
|
|
70046
|
+
const parts = message.parts.map((part) => {
|
|
70047
|
+
const replacement = replaceUnsupportedInputPart(part, agent);
|
|
70048
|
+
if (replacement !== part) {
|
|
70049
|
+
didChange = true;
|
|
70050
|
+
messageDidChange = true;
|
|
70051
|
+
}
|
|
70052
|
+
return replacement;
|
|
70053
|
+
});
|
|
70054
|
+
return messageDidChange ? { ...message, parts } : message;
|
|
70055
|
+
});
|
|
70056
|
+
return didChange ? transformed : messages;
|
|
70057
|
+
}
|
|
70058
|
+
function sanitizeUIMessagesForProvider(messages, provider, agent) {
|
|
70059
|
+
const capabilitySanitizedMessages = replaceUnsupportedInputParts(messages, agent);
|
|
69920
70060
|
if (provider === "unknown")
|
|
69921
|
-
return
|
|
69922
|
-
return
|
|
70061
|
+
return capabilitySanitizedMessages;
|
|
70062
|
+
return capabilitySanitizedMessages.map((message) => {
|
|
69923
70063
|
const parts = message.parts.filter((part) => shouldKeepReasoningPart(part, provider));
|
|
69924
70064
|
return parts.length === message.parts.length ? message : { ...message, parts };
|
|
69925
70065
|
}).filter((message) => message.role !== "assistant" || message.parts.length > 0);
|
|
69926
70066
|
}
|
|
69927
|
-
function buildAISDKProviderOptions(modelHandle, modelSettings) {
|
|
70067
|
+
function buildAISDKProviderOptions(modelHandle, modelSettings, options = {}) {
|
|
69928
70068
|
const provider = aiSDKProviderKind(modelHandle, modelSettings);
|
|
69929
70069
|
if (provider === "openai") {
|
|
70070
|
+
const chatgptOAuth = isChatGPTOAuthModel(modelHandle, modelSettings);
|
|
69930
70071
|
const reasoning = isRecord2(modelSettings.reasoning) ? modelSettings.reasoning : undefined;
|
|
69931
70072
|
const reasoningEffort = openAIReasoningEffort(reasoning?.reasoning_effort ?? modelSettings.reasoning_effort);
|
|
69932
70073
|
const textVerbosity = openAITextVerbosity(modelSettings.verbosity);
|
|
69933
70074
|
const parallelToolCalls = boolValue(modelSettings.parallel_tool_calls);
|
|
69934
70075
|
const openai2 = {
|
|
70076
|
+
...chatgptOAuth ? {
|
|
70077
|
+
instructions: options.systemPrompt,
|
|
70078
|
+
store: false,
|
|
70079
|
+
systemMessageMode: "remove"
|
|
70080
|
+
} : {},
|
|
69935
70081
|
...reasoningEffort !== undefined ? { reasoningEffort } : {},
|
|
69936
70082
|
...textVerbosity !== undefined ? { textVerbosity } : {},
|
|
69937
70083
|
...parallelToolCalls !== undefined ? { parallelToolCalls } : {}
|
|
@@ -70011,15 +70157,15 @@ class AISDKStreamAdapter {
|
|
|
70011
70157
|
const tools = toToolSet(input.clientTools);
|
|
70012
70158
|
const provider = aiSDKProviderKind(input.agent.model, input.agent.model_settings);
|
|
70013
70159
|
const uiMessages = await validateUIMessages({
|
|
70014
|
-
messages: sanitizeUIMessagesForProvider(input.uiMessages, provider),
|
|
70160
|
+
messages: sanitizeUIMessagesForProvider(input.uiMessages, provider, input.agent),
|
|
70015
70161
|
tools
|
|
70016
70162
|
});
|
|
70017
70163
|
const result = this.runStreamText({
|
|
70018
70164
|
model: this.createModel?.() ?? createAISDKModelFactoryFromAgent(input.agent.model, input.agent.model_settings, { localProviderAuthStorageDir: this.localProviderAuthStorageDir })(),
|
|
70019
|
-
system: input.systemPrompt ?? input.agent.system,
|
|
70165
|
+
system: provider === "openai" && isChatGPTOAuthModel(input.agent.model, input.agent.model_settings) ? undefined : input.systemPrompt ?? input.agent.system,
|
|
70020
70166
|
messages: await convertToModelMessages(uiMessages, { tools }),
|
|
70021
70167
|
tools,
|
|
70022
|
-
providerOptions: buildAISDKProviderOptions(input.agent.model, input.agent.model_settings),
|
|
70168
|
+
providerOptions: buildAISDKProviderOptions(input.agent.model, input.agent.model_settings, { systemPrompt: input.systemPrompt ?? input.agent.system }),
|
|
70023
70169
|
maxRetries: 0,
|
|
70024
70170
|
abortSignal: this.abortSignal
|
|
70025
70171
|
});
|
|
@@ -70421,6 +70567,7 @@ function normalizeAgentRecord(value, defaultAgentModel) {
|
|
|
70421
70567
|
if (modelSettings.max_tokens === undefined && (typeof legacyLlmConfig.max_tokens === "number" || legacyLlmConfig.max_tokens === null)) {
|
|
70422
70568
|
modelSettings.max_tokens = legacyLlmConfig.max_tokens;
|
|
70423
70569
|
}
|
|
70570
|
+
const compactionSettings = optionalRecordOrNull(value.compaction_settings);
|
|
70424
70571
|
return {
|
|
70425
70572
|
id: value.id,
|
|
70426
70573
|
name: optionalString(value.name) ?? "Letta Code",
|
|
@@ -70428,7 +70575,8 @@ function normalizeAgentRecord(value, defaultAgentModel) {
|
|
|
70428
70575
|
system: optionalString(value.system) ?? "",
|
|
70429
70576
|
tags: isStringArray(value.tags) ? value.tags : [],
|
|
70430
70577
|
model: optionalString(value.model) ?? optionalString(legacyLlmConfig.model) ?? defaultAgentModel,
|
|
70431
|
-
model_settings: modelSettings
|
|
70578
|
+
model_settings: modelSettings,
|
|
70579
|
+
...compactionSettings !== undefined ? { compaction_settings: compactionSettings } : {}
|
|
70432
70580
|
};
|
|
70433
70581
|
}
|
|
70434
70582
|
function projectAgentState(record2, messageIds = [], inContextMessageIds = messageIds, lastRunCompletion) {
|
|
@@ -70444,6 +70592,7 @@ function projectAgentState(record2, messageIds = [], inContextMessageIds = messa
|
|
|
70444
70592
|
tags: record2.tags,
|
|
70445
70593
|
model: record2.model,
|
|
70446
70594
|
model_settings: record2.model_settings,
|
|
70595
|
+
...record2.compaction_settings !== undefined ? { compaction_settings: record2.compaction_settings } : {},
|
|
70447
70596
|
message_ids: messageIds,
|
|
70448
70597
|
in_context_message_ids: inContextMessageIds,
|
|
70449
70598
|
...lastRunCompletion ? { last_run_completion: lastRunCompletion } : {},
|
|
@@ -70472,6 +70621,39 @@ function normalizeContent(content) {
|
|
|
70472
70621
|
function isRecord3(value) {
|
|
70473
70622
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
70474
70623
|
}
|
|
70624
|
+
function localFilePartFromLegacyImage(part) {
|
|
70625
|
+
if (part.type !== "image" || !isRecord3(part.source)) {
|
|
70626
|
+
return null;
|
|
70627
|
+
}
|
|
70628
|
+
const source = part.source;
|
|
70629
|
+
if (source.type !== "base64") {
|
|
70630
|
+
return null;
|
|
70631
|
+
}
|
|
70632
|
+
const mediaType = source.media_type;
|
|
70633
|
+
const data = source.data;
|
|
70634
|
+
if (typeof mediaType !== "string" || typeof data !== "string") {
|
|
70635
|
+
return null;
|
|
70636
|
+
}
|
|
70637
|
+
return {
|
|
70638
|
+
type: "file",
|
|
70639
|
+
mediaType,
|
|
70640
|
+
url: `data:${mediaType};base64,${data}`
|
|
70641
|
+
};
|
|
70642
|
+
}
|
|
70643
|
+
function normalizeLocalMessageForAISDK(message) {
|
|
70644
|
+
let didChange = false;
|
|
70645
|
+
const parts = message.parts.map((part) => {
|
|
70646
|
+
if (isRecord3(part)) {
|
|
70647
|
+
const filePart = localFilePartFromLegacyImage(part);
|
|
70648
|
+
if (filePart) {
|
|
70649
|
+
didChange = true;
|
|
70650
|
+
return filePart;
|
|
70651
|
+
}
|
|
70652
|
+
}
|
|
70653
|
+
return part;
|
|
70654
|
+
});
|
|
70655
|
+
return didChange ? { ...message, parts } : message;
|
|
70656
|
+
}
|
|
70475
70657
|
function textFromContent(content) {
|
|
70476
70658
|
if (typeof content === "string")
|
|
70477
70659
|
return content;
|
|
@@ -70703,6 +70885,19 @@ class LocalStore {
|
|
|
70703
70885
|
}
|
|
70704
70886
|
return this.projectAgent(updated);
|
|
70705
70887
|
}
|
|
70888
|
+
setAgentCompactionSettings(agentId, settings) {
|
|
70889
|
+
const existing = this.agents.get(agentId);
|
|
70890
|
+
if (!existing) {
|
|
70891
|
+
throw new LocalBackendNotFoundError("Agent", agentId);
|
|
70892
|
+
}
|
|
70893
|
+
const updated = {
|
|
70894
|
+
...existing,
|
|
70895
|
+
compaction_settings: settings === null ? null : { ...settings }
|
|
70896
|
+
};
|
|
70897
|
+
this.agents.set(agentId, updated);
|
|
70898
|
+
this.persistAgent(agentId);
|
|
70899
|
+
return this.projectAgent(updated);
|
|
70900
|
+
}
|
|
70706
70901
|
createAgent(body) {
|
|
70707
70902
|
const agent = this.createAgentRecord(body);
|
|
70708
70903
|
const agentId = agent.id;
|
|
@@ -70940,8 +71135,12 @@ class LocalStore {
|
|
|
70940
71135
|
},
|
|
70941
71136
|
parts: [{ type: "text", text: input.packedSummary }]
|
|
70942
71137
|
};
|
|
70943
|
-
|
|
70944
|
-
|
|
71138
|
+
const compactedMessages = [
|
|
71139
|
+
summaryMessage,
|
|
71140
|
+
...(input.remainingMessages ?? []).map(cloneLocalMessage)
|
|
71141
|
+
];
|
|
71142
|
+
this.localMessagesByConversationKey.set(key, compactedMessages);
|
|
71143
|
+
conversation.in_context_message_ids = compactedMessages.map((message) => message.id);
|
|
70945
71144
|
conversation.last_message_at = date5;
|
|
70946
71145
|
conversation.updated_at = date5;
|
|
70947
71146
|
this.conversations.set(key, conversation);
|
|
@@ -70949,7 +71148,7 @@ class LocalStore {
|
|
|
70949
71148
|
this.rebuildMessageIndex();
|
|
70950
71149
|
return {
|
|
70951
71150
|
numMessagesBefore: previousMessages.length,
|
|
70952
|
-
numMessagesAfter:
|
|
71151
|
+
numMessagesAfter: compactedMessages.length,
|
|
70953
71152
|
summaryMessage: cloneLocalMessage(summaryMessage)
|
|
70954
71153
|
};
|
|
70955
71154
|
}
|
|
@@ -71305,6 +71504,11 @@ class LocalStore {
|
|
|
71305
71504
|
parts.push({ type: "text", text: part.text });
|
|
71306
71505
|
continue;
|
|
71307
71506
|
}
|
|
71507
|
+
const filePart = localFilePartFromLegacyImage(part);
|
|
71508
|
+
if (filePart) {
|
|
71509
|
+
parts.push(filePart);
|
|
71510
|
+
continue;
|
|
71511
|
+
}
|
|
71308
71512
|
parts.push(part);
|
|
71309
71513
|
}
|
|
71310
71514
|
return parts.length > 0 ? parts : textContent(textFromContent(content));
|
|
@@ -71341,7 +71545,7 @@ class LocalStore {
|
|
|
71341
71545
|
if (!conversation?.id || !conversation.agent_id)
|
|
71342
71546
|
continue;
|
|
71343
71547
|
const key = this.conversationKey(conversation.id, conversation.agent_id);
|
|
71344
|
-
const localMessages = readJsonlFile(join7(conversationDir, "messages.jsonl"));
|
|
71548
|
+
const localMessages = readJsonlFile(join7(conversationDir, "messages.jsonl")).map(normalizeLocalMessageForAISDK);
|
|
71345
71549
|
const compiledSystemPrompt = readJsonFile(join7(conversationDir, "system-prompt.json"));
|
|
71346
71550
|
const messages = projectLocalMessagesToStoredMessages(localMessages, conversation.agent_id, conversation.id);
|
|
71347
71551
|
this.conversations.set(key, conversation);
|
|
@@ -71892,6 +72096,9 @@ var init_HeadlessBackend = __esm(() => {
|
|
|
71892
72096
|
});
|
|
71893
72097
|
|
|
71894
72098
|
// src/backend/local/compaction.ts
|
|
72099
|
+
function isLocalSlidingWindowCompactionPlanningError(error51) {
|
|
72100
|
+
return error51 instanceof LocalSlidingWindowCompactionPlanningError;
|
|
72101
|
+
}
|
|
71895
72102
|
function isRecord4(value) {
|
|
71896
72103
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
71897
72104
|
}
|
|
@@ -71950,24 +72157,24 @@ ${body}
|
|
|
71950
72157
|
}
|
|
71951
72158
|
return transcript;
|
|
71952
72159
|
}
|
|
71953
|
-
async function runGenerateText(input, transcript) {
|
|
72160
|
+
async function runGenerateText(input, transcript, defaultPrompt) {
|
|
71954
72161
|
const run = input.generateText ?? generateText;
|
|
71955
72162
|
return run({
|
|
71956
72163
|
model: input.createModel?.() ?? createAISDKModelFactoryFromAgent(input.agent.model, input.agent.model_settings, { localProviderAuthStorageDir: input.localProviderAuthStorageDir })(),
|
|
71957
|
-
system: input.prompt ??
|
|
72164
|
+
system: input.prompt ?? defaultPrompt,
|
|
71958
72165
|
prompt: transcript,
|
|
71959
72166
|
providerOptions: buildAISDKProviderOptions(input.agent.model, input.agent.model_settings),
|
|
71960
72167
|
maxRetries: 0,
|
|
71961
72168
|
abortSignal: input.abortSignal
|
|
71962
72169
|
});
|
|
71963
72170
|
}
|
|
71964
|
-
async function
|
|
72171
|
+
async function summarizeLocalMessagesWithPrompt(input, defaultPrompt) {
|
|
71965
72172
|
if (input.messages.length === 0)
|
|
71966
72173
|
return "No prior conversation messages.";
|
|
71967
72174
|
const primaryTranscript = formatLocalMessagesForSummary(input.messages);
|
|
71968
72175
|
let result;
|
|
71969
72176
|
try {
|
|
71970
|
-
result = await runGenerateText(input, primaryTranscript);
|
|
72177
|
+
result = await runGenerateText(input, primaryTranscript, defaultPrompt);
|
|
71971
72178
|
} catch (error51) {
|
|
71972
72179
|
if (!isContextWindowOverflowError(error51))
|
|
71973
72180
|
throw error51;
|
|
@@ -71975,7 +72182,7 @@ async function summarizeLocalMessagesAll(input) {
|
|
|
71975
72182
|
truncationChars: TOOL_TRANSCRIPT_TRUNCATION_CHARS,
|
|
71976
72183
|
maxChars: TRANSCRIPT_FALLBACK_MAX_CHARS
|
|
71977
72184
|
});
|
|
71978
|
-
result = await runGenerateText(input, fallbackTranscript);
|
|
72185
|
+
result = await runGenerateText(input, fallbackTranscript, defaultPrompt);
|
|
71979
72186
|
}
|
|
71980
72187
|
let summary = result.text.trim();
|
|
71981
72188
|
const clipChars = input.clipChars === undefined ? 50000 : input.clipChars;
|
|
@@ -71984,6 +72191,62 @@ async function summarizeLocalMessagesAll(input) {
|
|
|
71984
72191
|
}
|
|
71985
72192
|
return summary;
|
|
71986
72193
|
}
|
|
72194
|
+
async function summarizeLocalMessagesAll(input) {
|
|
72195
|
+
return summarizeLocalMessagesWithPrompt(input, LOCAL_ALL_COMPACTION_PROMPT);
|
|
72196
|
+
}
|
|
72197
|
+
function isSettledLocalToolState2(state) {
|
|
72198
|
+
return state === "output-available" || state === "output-error" || state === "output-denied";
|
|
72199
|
+
}
|
|
72200
|
+
function hasPendingLocalToolPart(message) {
|
|
72201
|
+
return message.parts.some((part) => {
|
|
72202
|
+
if (!isRecord4(part))
|
|
72203
|
+
return false;
|
|
72204
|
+
const partRecord = part;
|
|
72205
|
+
return typeof partRecord.type === "string" && partRecord.type.startsWith("tool-") && !isSettledLocalToolState2(partRecord.state);
|
|
72206
|
+
});
|
|
72207
|
+
}
|
|
72208
|
+
function normalizedSlidingWindowPercentage(value) {
|
|
72209
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
72210
|
+
return LOCAL_DEFAULT_SLIDING_WINDOW_PERCENTAGE;
|
|
72211
|
+
}
|
|
72212
|
+
if (value <= 0)
|
|
72213
|
+
return 0.1;
|
|
72214
|
+
if (value > 1)
|
|
72215
|
+
return 1;
|
|
72216
|
+
return value;
|
|
72217
|
+
}
|
|
72218
|
+
function isValidSlidingWindowCutoff(messages, index, maximumCutoffIndex) {
|
|
72219
|
+
const message = messages[index];
|
|
72220
|
+
return message?.role === "assistant" && index > 1 && index < maximumCutoffIndex;
|
|
72221
|
+
}
|
|
72222
|
+
function planLocalSlidingWindowCompaction(messages, options = {}) {
|
|
72223
|
+
if (messages.length < 4) {
|
|
72224
|
+
throw new LocalSlidingWindowCompactionPlanningError("Not enough messages for sliding window compaction.");
|
|
72225
|
+
}
|
|
72226
|
+
const percentage = normalizedSlidingWindowPercentage(options.slidingWindowPercentage);
|
|
72227
|
+
const lastMessage = messages.at(-1);
|
|
72228
|
+
const maximumCutoffIndex = lastMessage && hasPendingLocalToolPart(lastMessage) ? messages.length - 2 : messages.length - 1;
|
|
72229
|
+
const goalTokens = typeof options.contextWindow === "number" && Number.isFinite(options.contextWindow) ? (1 - percentage) * options.contextWindow : undefined;
|
|
72230
|
+
for (let evictionPercentage = percentage;evictionPercentage < 1; evictionPercentage += 0.1) {
|
|
72231
|
+
const messageCutoffIndex = Math.min(Math.round(evictionPercentage * messages.length), messages.length - 1);
|
|
72232
|
+
const cutoffIndex = [...Array(messageCutoffIndex + 1).keys()].reverse().find((index) => isValidSlidingWindowCutoff(messages, index, maximumCutoffIndex));
|
|
72233
|
+
if (cutoffIndex === undefined)
|
|
72234
|
+
continue;
|
|
72235
|
+
const messagesToKeep = messages.slice(cutoffIndex);
|
|
72236
|
+
if (goalTokens !== undefined && estimateLocalMessageTokens(messagesToKeep) >= goalTokens) {
|
|
72237
|
+
continue;
|
|
72238
|
+
}
|
|
72239
|
+
return {
|
|
72240
|
+
messagesToSummarize: messages.slice(0, cutoffIndex),
|
|
72241
|
+
messagesToKeep,
|
|
72242
|
+
cutoffIndex
|
|
72243
|
+
};
|
|
72244
|
+
}
|
|
72245
|
+
throw new LocalSlidingWindowCompactionPlanningError("No assistant message found for sliding window compaction.");
|
|
72246
|
+
}
|
|
72247
|
+
async function summarizeLocalMessagesSlidingWindow(input) {
|
|
72248
|
+
return summarizeLocalMessagesWithPrompt(input, LOCAL_SLIDING_WINDOW_COMPACTION_PROMPT);
|
|
72249
|
+
}
|
|
71987
72250
|
function estimateLocalMessageTokens(messages) {
|
|
71988
72251
|
const chars = messages.reduce((total, message) => total + JSON.stringify(message).length, 0);
|
|
71989
72252
|
return Math.ceil(chars / 4);
|
|
@@ -71998,12 +72261,18 @@ The following is an in-context recursive summary of the prior messages: ${summar
|
|
|
71998
72261
|
...stats ? { compaction_stats: stats } : {}
|
|
71999
72262
|
});
|
|
72000
72263
|
}
|
|
72001
|
-
var ALL_WORD_LIMIT = 500, SUMMARY_TRUNCATION_SUFFIX = "... [summary truncated to fit]", TOOL_TRANSCRIPT_TRUNCATION_CHARS = 4000, TRANSCRIPT_FALLBACK_MAX_CHARS = 120000, LOCAL_ALL_COMPACTION_PROMPT;
|
|
72264
|
+
var ALL_WORD_LIMIT = 500, SLIDING_WORD_LIMIT = 300, SUMMARY_TRUNCATION_SUFFIX = "... [summary truncated to fit]", TOOL_TRANSCRIPT_TRUNCATION_CHARS = 4000, TRANSCRIPT_FALLBACK_MAX_CHARS = 120000, LOCAL_DEFAULT_COMPACTION_MODE = "sliding_window", LOCAL_DEFAULT_SLIDING_WINDOW_PERCENTAGE = 0.3, LocalSlidingWindowCompactionPlanningError, LOCAL_ALL_COMPACTION_PROMPT, LOCAL_SLIDING_WINDOW_COMPACTION_PROMPT;
|
|
72002
72265
|
var init_compaction = __esm(() => {
|
|
72003
72266
|
init_dist6();
|
|
72004
72267
|
init_AISDKModelFactory();
|
|
72005
72268
|
init_AISDKStreamAdapter();
|
|
72006
72269
|
init_contextWindowOverflow();
|
|
72270
|
+
LocalSlidingWindowCompactionPlanningError = class LocalSlidingWindowCompactionPlanningError extends Error {
|
|
72271
|
+
constructor(message) {
|
|
72272
|
+
super(message);
|
|
72273
|
+
this.name = "LocalSlidingWindowCompactionPlanningError";
|
|
72274
|
+
}
|
|
72275
|
+
};
|
|
72007
72276
|
LOCAL_ALL_COMPACTION_PROMPT = `Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
|
|
72008
72277
|
This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context. Your summary should include the following sections:
|
|
72009
72278
|
|
|
@@ -72027,6 +72296,24 @@ This summary should be thorough in capturing technical details, code patterns, a
|
|
|
72027
72296
|
Write in first person as a factual record of what occurred. Be concise but thorough - the goal is to preserve enough context that the recent messages make sense and important information isn't lost to prevent duplicate work or repeated mistakes.
|
|
72028
72297
|
|
|
72029
72298
|
Keep your summary under ${ALL_WORD_LIMIT} words. Only output the summary.`;
|
|
72299
|
+
LOCAL_SLIDING_WINDOW_COMPACTION_PROMPT = `The following messages are being evicted from the BEGINNING of your context window. Write a detailed summary that captures what happened in these messages to appear BEFORE the remaining recent messages in context, providing background for what comes after. Include the following sections:
|
|
72300
|
+
|
|
72301
|
+
1.**High level goals**: What is the high level goal and ongoing task? Capture the user's explicit requests and intent in detail. If there is an existing summary in the transcript, make sure to take it into consideration to continue tracking the higher level goals and long-term progress.
|
|
72302
|
+
|
|
72303
|
+
2. **What happened**: The conversations, tasks, and exchanges that took place. What did the user ask for? What did you do? How did things progress? If there is a previous summary being evicted, please extract a concise version of the critical info from it.
|
|
72304
|
+
|
|
72305
|
+
3. **Important details**: Enumerate specific files and code sections examined, modified, or created, as well as important plan files, GitHub issues/PR links, and Linear ticket IDs. For each item, include why it matters and any relevant names, data, configs, or facts discussed.
|
|
72306
|
+
- **Preserve identifiers verbatim** (plan filename/path, exact URL, issue/PR number, ticket ID); do not paraphrase or truncate.
|
|
72307
|
+
- **Preserve referenced identifiers unless explicitly resolved**: Keep exact URLs/IDs from the conversation unless there is clear evidence they are no longer relevant.
|
|
72308
|
+
- Do not omit details likely to be referenced later.
|
|
72309
|
+
|
|
72310
|
+
4. **Errors and fixes**: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received and record verbatim if useful.
|
|
72311
|
+
|
|
72312
|
+
5. **Lookup hints**: For any detailed content (long lists, extensive data, specific conversations) that couldn't fit in the summary, note the topic and key terms that could be used to find it in message history later.
|
|
72313
|
+
|
|
72314
|
+
Write in first person as a factual record of what occurred. Be thorough and detailed - the goal is to preserve enough context that the recent messages make sense and important information isn't lost to prevent duplicate work or repeated mistakes.
|
|
72315
|
+
|
|
72316
|
+
Keep your summary under ${SLIDING_WORD_LIMIT} words. Only output the summary.`;
|
|
72030
72317
|
});
|
|
72031
72318
|
|
|
72032
72319
|
// src/backend/local/LocalModelConfig.ts
|
|
@@ -76274,6 +76561,9 @@ __export(exports_modify, {
|
|
|
76274
76561
|
function supportsDistinctAnthropicXHighEffort(modelHandle) {
|
|
76275
76562
|
return modelHandle.includes("claude-opus-4-7");
|
|
76276
76563
|
}
|
|
76564
|
+
function isRecord5(value) {
|
|
76565
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
76566
|
+
}
|
|
76277
76567
|
function buildModelSettings(modelHandle, updateArgs) {
|
|
76278
76568
|
const isOpenAI = modelHandle.startsWith("openai/") || modelHandle.startsWith(`${OPENAI_CODEX_PROVIDER_NAME}/`);
|
|
76279
76569
|
const isAnthropic = modelHandle.startsWith("anthropic/") || modelHandle.startsWith("claude-pro-max/") || modelHandle.startsWith("minimax/");
|
|
@@ -76396,6 +76686,12 @@ function buildModelSettings(modelHandle, updateArgs) {
|
|
|
76396
76686
|
if (typeof updateArgs?.max_output_tokens === "number" && "provider_type" in settings) {
|
|
76397
76687
|
settings.max_output_tokens = updateArgs.max_output_tokens;
|
|
76398
76688
|
}
|
|
76689
|
+
if (isRecord5(updateArgs?.modalities)) {
|
|
76690
|
+
settings.modalities = updateArgs.modalities;
|
|
76691
|
+
}
|
|
76692
|
+
if (isRecord5(updateArgs?.capabilities)) {
|
|
76693
|
+
settings.capabilities = updateArgs.capabilities;
|
|
76694
|
+
}
|
|
76399
76695
|
return settings;
|
|
76400
76696
|
}
|
|
76401
76697
|
async function updateAgentLLMConfig(agentId, modelHandle, updateArgs, options) {
|
|
@@ -78106,6 +78402,95 @@ function createTelegramAdapter(config2) {
|
|
|
78106
78402
|
let botModule = null;
|
|
78107
78403
|
let running = false;
|
|
78108
78404
|
const bufferedMediaGroups = new Map;
|
|
78405
|
+
const typingByChatId = new Map;
|
|
78406
|
+
async function sendTypingAction(chatId) {
|
|
78407
|
+
if (!running)
|
|
78408
|
+
return;
|
|
78409
|
+
try {
|
|
78410
|
+
const telegramBot = await ensureBot();
|
|
78411
|
+
await telegramBot.api.sendChatAction(chatId, "typing");
|
|
78412
|
+
} catch (error51) {
|
|
78413
|
+
console.warn(`[Telegram] Failed to send typing action for chat ${chatId}:`, error51 instanceof Error ? error51.message : error51);
|
|
78414
|
+
}
|
|
78415
|
+
}
|
|
78416
|
+
function getTypingSourceKey(source) {
|
|
78417
|
+
const chatId = getTypingChatId(source);
|
|
78418
|
+
if (!chatId)
|
|
78419
|
+
return null;
|
|
78420
|
+
return [
|
|
78421
|
+
source.accountId ?? "",
|
|
78422
|
+
chatId,
|
|
78423
|
+
source.threadId ?? "",
|
|
78424
|
+
source.messageId ?? "",
|
|
78425
|
+
source.agentId,
|
|
78426
|
+
source.conversationId
|
|
78427
|
+
].join(":");
|
|
78428
|
+
}
|
|
78429
|
+
function startTypingForSource(source) {
|
|
78430
|
+
const chatId = getTypingChatId(source);
|
|
78431
|
+
const sourceKey = getTypingSourceKey(source);
|
|
78432
|
+
if (!chatId || !sourceKey)
|
|
78433
|
+
return;
|
|
78434
|
+
const existing = typingByChatId.get(chatId);
|
|
78435
|
+
if (existing) {
|
|
78436
|
+
existing.sourceKeys.add(sourceKey);
|
|
78437
|
+
return;
|
|
78438
|
+
}
|
|
78439
|
+
sendTypingAction(chatId);
|
|
78440
|
+
const timer = setInterval(() => {
|
|
78441
|
+
sendTypingAction(chatId);
|
|
78442
|
+
}, TELEGRAM_TYPING_REFRESH_MS);
|
|
78443
|
+
const timeout = setTimeout(() => {
|
|
78444
|
+
clearTypingForChat(chatId);
|
|
78445
|
+
}, TELEGRAM_TYPING_MAX_MS);
|
|
78446
|
+
if (typeof timer.unref === "function") {
|
|
78447
|
+
timer.unref?.();
|
|
78448
|
+
}
|
|
78449
|
+
if (typeof timeout.unref === "function") {
|
|
78450
|
+
timeout.unref?.();
|
|
78451
|
+
}
|
|
78452
|
+
typingByChatId.set(chatId, {
|
|
78453
|
+
sourceKeys: new Set([sourceKey]),
|
|
78454
|
+
timer,
|
|
78455
|
+
timeout
|
|
78456
|
+
});
|
|
78457
|
+
}
|
|
78458
|
+
function stopTypingForSource(source) {
|
|
78459
|
+
const chatId = getTypingChatId(source);
|
|
78460
|
+
const sourceKey = getTypingSourceKey(source);
|
|
78461
|
+
if (!chatId || !sourceKey)
|
|
78462
|
+
return;
|
|
78463
|
+
const entry = typingByChatId.get(chatId);
|
|
78464
|
+
if (!entry)
|
|
78465
|
+
return;
|
|
78466
|
+
entry.sourceKeys.delete(sourceKey);
|
|
78467
|
+
if (entry.sourceKeys.size === 0) {
|
|
78468
|
+
clearTypingForChat(chatId);
|
|
78469
|
+
}
|
|
78470
|
+
}
|
|
78471
|
+
function clearTypingForChat(chatId) {
|
|
78472
|
+
const entry = typingByChatId.get(chatId);
|
|
78473
|
+
if (!entry)
|
|
78474
|
+
return;
|
|
78475
|
+
clearInterval(entry.timer);
|
|
78476
|
+
clearTimeout(entry.timeout);
|
|
78477
|
+
typingByChatId.delete(chatId);
|
|
78478
|
+
}
|
|
78479
|
+
function clearAllTyping() {
|
|
78480
|
+
for (const entry of typingByChatId.values()) {
|
|
78481
|
+
clearInterval(entry.timer);
|
|
78482
|
+
clearTimeout(entry.timeout);
|
|
78483
|
+
}
|
|
78484
|
+
typingByChatId.clear();
|
|
78485
|
+
}
|
|
78486
|
+
function getTypingChatId(source) {
|
|
78487
|
+
if (source.channel !== "telegram")
|
|
78488
|
+
return null;
|
|
78489
|
+
const chatId = source.chatId;
|
|
78490
|
+
if (typeof chatId !== "string" || chatId.length === 0)
|
|
78491
|
+
return null;
|
|
78492
|
+
return chatId;
|
|
78493
|
+
}
|
|
78109
78494
|
async function ensureModule() {
|
|
78110
78495
|
if (!botModule) {
|
|
78111
78496
|
botModule = await loadGrammyModule();
|
|
@@ -78299,6 +78684,7 @@ function createTelegramAdapter(config2) {
|
|
|
78299
78684
|
clearTimeout(entry.timer);
|
|
78300
78685
|
}
|
|
78301
78686
|
bufferedMediaGroups.clear();
|
|
78687
|
+
clearAllTyping();
|
|
78302
78688
|
if (!running || !bot)
|
|
78303
78689
|
return;
|
|
78304
78690
|
await bot.stop();
|
|
@@ -78324,6 +78710,7 @@ function createTelegramAdapter(config2) {
|
|
|
78324
78710
|
} else {
|
|
78325
78711
|
await telegramBot.api.setMessageReaction(msg.chatId, Number(targetMessageId), []);
|
|
78326
78712
|
}
|
|
78713
|
+
clearTypingForChat(msg.chatId);
|
|
78327
78714
|
return { messageId: targetMessageId };
|
|
78328
78715
|
}
|
|
78329
78716
|
if (msg.mediaPath) {
|
|
@@ -78350,6 +78737,7 @@ function createTelegramAdapter(config2) {
|
|
|
78350
78737
|
return await telegramBot.api.sendDocument(msg.chatId, inputFile, options);
|
|
78351
78738
|
}
|
|
78352
78739
|
})();
|
|
78740
|
+
clearTypingForChat(msg.chatId);
|
|
78353
78741
|
return { messageId: String(result2.message_id) };
|
|
78354
78742
|
}
|
|
78355
78743
|
const opts = {};
|
|
@@ -78362,6 +78750,7 @@ function createTelegramAdapter(config2) {
|
|
|
78362
78750
|
opts.parse_mode = msg.parseMode;
|
|
78363
78751
|
}
|
|
78364
78752
|
const result = await telegramBot.api.sendMessage(msg.chatId, msg.text, opts);
|
|
78753
|
+
clearTypingForChat(msg.chatId);
|
|
78365
78754
|
return { messageId: String(result.message_id) };
|
|
78366
78755
|
},
|
|
78367
78756
|
async sendDirectReply(chatId, text2, options) {
|
|
@@ -78371,12 +78760,29 @@ function createTelegramAdapter(config2) {
|
|
|
78371
78760
|
} : undefined;
|
|
78372
78761
|
await telegramBot.api.sendMessage(chatId, text2, reply_parameters ? { reply_parameters } : {});
|
|
78373
78762
|
},
|
|
78763
|
+
async handleTurnLifecycleEvent(event) {
|
|
78764
|
+
if (!running)
|
|
78765
|
+
return;
|
|
78766
|
+
if (event.type === "queued") {
|
|
78767
|
+
return;
|
|
78768
|
+
}
|
|
78769
|
+
if (event.type === "processing") {
|
|
78770
|
+
for (const source of event.sources) {
|
|
78771
|
+
startTypingForSource(source);
|
|
78772
|
+
}
|
|
78773
|
+
return;
|
|
78774
|
+
}
|
|
78775
|
+
for (const source of event.sources) {
|
|
78776
|
+
stopTypingForSource(source);
|
|
78777
|
+
}
|
|
78778
|
+
},
|
|
78374
78779
|
async handleControlRequestEvent(event) {
|
|
78375
78780
|
const telegramBot = await ensureBot();
|
|
78376
78781
|
const reply_parameters = event.source.messageId || event.source.threadId ? {
|
|
78377
78782
|
message_id: Number(event.source.threadId ?? event.source.messageId)
|
|
78378
78783
|
} : undefined;
|
|
78379
78784
|
await telegramBot.api.sendMessage(event.source.chatId, formatChannelControlRequestPrompt(event), reply_parameters ? { reply_parameters } : {});
|
|
78785
|
+
clearTypingForChat(event.source.chatId);
|
|
78380
78786
|
},
|
|
78381
78787
|
onMessage: undefined
|
|
78382
78788
|
};
|
|
@@ -78393,9 +78799,11 @@ async function validateTelegramToken(token) {
|
|
|
78393
78799
|
id: info.id
|
|
78394
78800
|
};
|
|
78395
78801
|
}
|
|
78802
|
+
var TELEGRAM_TYPING_REFRESH_MS = 4000, TELEGRAM_TYPING_MAX_MS;
|
|
78396
78803
|
var init_adapter = __esm(() => {
|
|
78397
78804
|
init_media();
|
|
78398
78805
|
init_runtime();
|
|
78806
|
+
TELEGRAM_TYPING_MAX_MS = 5 * 60 * 1000;
|
|
78399
78807
|
});
|
|
78400
78808
|
|
|
78401
78809
|
// src/channels/telegram/messageActions.ts
|
|
@@ -78488,13 +78896,13 @@ function cloneAccount(account) {
|
|
|
78488
78896
|
}
|
|
78489
78897
|
return cloned;
|
|
78490
78898
|
}
|
|
78491
|
-
function
|
|
78899
|
+
function isRecord6(value) {
|
|
78492
78900
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
78493
78901
|
}
|
|
78494
78902
|
function normalizeLoadedAccount(account) {
|
|
78495
78903
|
const next = cloneAccount(account);
|
|
78496
78904
|
if (!isFirstPartyChannelId(next.channel)) {
|
|
78497
|
-
next.config =
|
|
78905
|
+
next.config = isRecord6(next.config) ? { ...next.config } : {};
|
|
78498
78906
|
}
|
|
78499
78907
|
if (isTelegramChannelAccount(next) && (next.displayName === "Telegram bot" || next.displayName === "Migrated Telegram bot") || isSlackChannelAccount(next) && (next.displayName === "Slack app" || next.displayName === "Migrated Slack app") || isDiscordChannelAccount(next) && (next.displayName === "Discord bot" || next.displayName === "Migrated Discord bot")) {
|
|
78500
78908
|
next.displayName = undefined;
|
|
@@ -80995,6 +81403,12 @@ function resolveDiscordReactionEmoji(value) {
|
|
|
80995
81403
|
};
|
|
80996
81404
|
return nameMap[normalized] ?? normalized;
|
|
80997
81405
|
}
|
|
81406
|
+
function buildDiscordIngressMessageKey(accountId, messageId) {
|
|
81407
|
+
if (!isNonEmptyString3(accountId) || !isNonEmptyString3(messageId)) {
|
|
81408
|
+
return null;
|
|
81409
|
+
}
|
|
81410
|
+
return `${accountId}:${messageId}`;
|
|
81411
|
+
}
|
|
80998
81412
|
function buildDiscordReplyOptions(replyToMessageId, channelId) {
|
|
80999
81413
|
const trimmed = replyToMessageId?.trim();
|
|
81000
81414
|
if (!trimmed || trimmed === channelId) {
|
|
@@ -81002,7 +81416,8 @@ function buildDiscordReplyOptions(replyToMessageId, channelId) {
|
|
|
81002
81416
|
}
|
|
81003
81417
|
return {
|
|
81004
81418
|
reply: {
|
|
81005
|
-
messageReference: trimmed
|
|
81419
|
+
messageReference: trimmed,
|
|
81420
|
+
failIfNotExists: false
|
|
81006
81421
|
}
|
|
81007
81422
|
};
|
|
81008
81423
|
}
|
|
@@ -81044,12 +81459,6 @@ function createDiscordAdapter(config2) {
|
|
|
81044
81459
|
const seenIngressMessageKeys = new Map;
|
|
81045
81460
|
const lifecycleStateByMessageKey = new Map;
|
|
81046
81461
|
const lifecycleOperationByMessageKey = new Map;
|
|
81047
|
-
function buildIngressMessageKey(channelId, messageId) {
|
|
81048
|
-
if (!isNonEmptyString3(channelId) || !isNonEmptyString3(messageId)) {
|
|
81049
|
-
return null;
|
|
81050
|
-
}
|
|
81051
|
-
return `${channelId}:${messageId}`;
|
|
81052
|
-
}
|
|
81053
81462
|
function pruneSeenIngressMessageKeys(now2 = Date.now()) {
|
|
81054
81463
|
for (const [key, expiresAt] of seenIngressMessageKeys) {
|
|
81055
81464
|
if (expiresAt <= now2) {
|
|
@@ -81068,8 +81477,8 @@ function createDiscordAdapter(config2) {
|
|
|
81068
81477
|
}
|
|
81069
81478
|
}
|
|
81070
81479
|
}
|
|
81071
|
-
function markIngressMessageSeen(
|
|
81072
|
-
const key =
|
|
81480
|
+
function markIngressMessageSeen(messageId) {
|
|
81481
|
+
const key = buildDiscordIngressMessageKey(config2.accountId, messageId);
|
|
81073
81482
|
if (!key)
|
|
81074
81483
|
return false;
|
|
81075
81484
|
const now2 = Date.now();
|
|
@@ -81259,7 +81668,7 @@ function createDiscordAdapter(config2) {
|
|
|
81259
81668
|
const isThread = isThreadMessage(message);
|
|
81260
81669
|
const wasMentioned = chatType === "channel" && hasBotMention(message);
|
|
81261
81670
|
if (chatType === "direct") {
|
|
81262
|
-
if (markIngressMessageSeen(message.
|
|
81671
|
+
if (markIngressMessageSeen(message.id))
|
|
81263
81672
|
return;
|
|
81264
81673
|
const attachments2 = await collectAttachments(message.attachments, message.channelId);
|
|
81265
81674
|
if (!content && (!attachments2 || attachments2.length === 0))
|
|
@@ -81296,7 +81705,7 @@ function createDiscordAdapter(config2) {
|
|
|
81296
81705
|
allowedChannels: config2.allowedChannels
|
|
81297
81706
|
}))
|
|
81298
81707
|
return;
|
|
81299
|
-
if (markIngressMessageSeen(message.
|
|
81708
|
+
if (markIngressMessageSeen(message.id))
|
|
81300
81709
|
return;
|
|
81301
81710
|
let effectiveChatId = message.channelId;
|
|
81302
81711
|
let effectiveThreadId = isThread ? message.channelId : null;
|
|
@@ -81767,7 +82176,7 @@ __export(exports_pluginRegistry, {
|
|
|
81767
82176
|
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "node:fs";
|
|
81768
82177
|
import { resolve as resolve6, sep } from "node:path";
|
|
81769
82178
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
81770
|
-
function
|
|
82179
|
+
function isRecord7(value) {
|
|
81771
82180
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
81772
82181
|
}
|
|
81773
82182
|
function isValidChannelId(value) {
|
|
@@ -81783,7 +82192,7 @@ function readChannelManifest(channelDir) {
|
|
|
81783
82192
|
}
|
|
81784
82193
|
try {
|
|
81785
82194
|
const parsed = JSON.parse(readFileSync9(manifestPath, "utf-8"));
|
|
81786
|
-
if (!
|
|
82195
|
+
if (!isRecord7(parsed)) {
|
|
81787
82196
|
return null;
|
|
81788
82197
|
}
|
|
81789
82198
|
const id = typeof parsed.id === "string" ? parsed.id.trim() : "";
|
|
@@ -81827,8 +82236,8 @@ function createUserChannelRegistration(manifest) {
|
|
|
81827
82236
|
throw new Error(`Channel plugin "${manifest.id}" entry escapes its directory.`);
|
|
81828
82237
|
}
|
|
81829
82238
|
const loadPromise = import(pathToFileURL2(entryPath).href).then((loaded) => {
|
|
81830
|
-
const exported = (
|
|
81831
|
-
if (!
|
|
82239
|
+
const exported = (isRecord7(loaded) ? loaded.channelPlugin : undefined) ?? (isRecord7(loaded) ? loaded.default : undefined);
|
|
82240
|
+
if (!isRecord7(exported)) {
|
|
81832
82241
|
throw new Error(`Channel plugin "${manifest.id}" must export channelPlugin or default.`);
|
|
81833
82242
|
}
|
|
81834
82243
|
const plugin = exported;
|
|
@@ -82775,6 +83184,9 @@ function buildChannelNotificationXml(msg) {
|
|
|
82775
83184
|
`chat_id="${escapeXmlAttribute(msg.chatId)}"`,
|
|
82776
83185
|
`sender_id="${escapeXmlAttribute(msg.senderId)}"`
|
|
82777
83186
|
];
|
|
83187
|
+
if (msg.accountId) {
|
|
83188
|
+
attrs.push(`account_id="${escapeXmlAttribute(msg.accountId)}"`);
|
|
83189
|
+
}
|
|
82778
83190
|
if (msg.senderName) {
|
|
82779
83191
|
attrs.push(`sender_name="${escapeXmlAttribute(msg.senderName)}"`);
|
|
82780
83192
|
}
|
|
@@ -83135,8 +83547,9 @@ class ChannelRegistry {
|
|
|
83135
83547
|
}
|
|
83136
83548
|
return matches[0] ?? null;
|
|
83137
83549
|
}
|
|
83138
|
-
getRouteForScope(channel, chatId, agentId, conversationId) {
|
|
83139
|
-
const
|
|
83550
|
+
getRouteForScope(channel, chatId, agentId, conversationId, accountId) {
|
|
83551
|
+
const normalizedAccountId = accountId?.trim();
|
|
83552
|
+
const matches = getRoutesForChannel(channel).filter((route) => route.chatId === chatId && route.agentId === agentId && route.conversationId === conversationId && (!normalizedAccountId || (route.accountId ?? LEGACY_CHANNEL_ACCOUNT_ID) === normalizedAccountId) && route.enabled);
|
|
83140
83553
|
if (matches.length !== 1) {
|
|
83141
83554
|
return null;
|
|
83142
83555
|
}
|
|
@@ -83730,6 +84143,7 @@ async function executeSingleDecision(decision, onChunk, options) {
|
|
|
83730
84143
|
toolCallId: decision.approval.toolCallId,
|
|
83731
84144
|
toolContextId: options?.toolContextId,
|
|
83732
84145
|
parentScope: options?.parentScope,
|
|
84146
|
+
channelTurnSources: options?.channelTurnSources,
|
|
83733
84147
|
onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined,
|
|
83734
84148
|
onFileWrite: options?.onFileWrite
|
|
83735
84149
|
});
|
|
@@ -90339,8 +90753,7 @@ var init_readOnlyShell = __esm(() => {
|
|
|
90339
90753
|
memory: new Set(["status", "help", "backups", "export", "tokens"]),
|
|
90340
90754
|
memfs: new Set(["status", "help", "backups", "export", "tokens"]),
|
|
90341
90755
|
agents: new Set(["list", "help"]),
|
|
90342
|
-
messages: new Set(["search", "list", "help"])
|
|
90343
|
-
blocks: new Set(["list", "help"])
|
|
90756
|
+
messages: new Set(["search", "list", "help"])
|
|
90344
90757
|
};
|
|
90345
90758
|
SAFE_GH_COMMANDS = {
|
|
90346
90759
|
pr: new Set(["list", "status", "checks", "diff", "view"]),
|
|
@@ -90817,7 +91230,7 @@ async function initSecretsFromServer(agentId, cachedAgent) {
|
|
|
90817
91230
|
setCache(agentId, {});
|
|
90818
91231
|
return;
|
|
90819
91232
|
}
|
|
90820
|
-
const agent = cachedAgent ?? await (
|
|
91233
|
+
const agent = cachedAgent ?? await getBackend().retrieveAgent(agentId, {
|
|
90821
91234
|
include: ["agent.secrets"]
|
|
90822
91235
|
});
|
|
90823
91236
|
const secrets2 = {};
|
|
@@ -90850,6 +91263,9 @@ async function refreshAndListSecrets(agentIdArg) {
|
|
|
90850
91263
|
return Object.keys(cache3).sort().map((key) => ({ key, value: cache3[key] ?? "" }));
|
|
90851
91264
|
}
|
|
90852
91265
|
async function applySecretBatch(options, agentIdArg) {
|
|
91266
|
+
if (!getBackend().capabilities.serverSecrets) {
|
|
91267
|
+
throw new Error("Agent secrets are not supported by this backend yet");
|
|
91268
|
+
}
|
|
90853
91269
|
const agentId = resolveSecretsAgentId(agentIdArg);
|
|
90854
91270
|
if (!agentId) {
|
|
90855
91271
|
throw new Error("No agent context set. Agent ID is required.");
|
|
@@ -90861,8 +91277,7 @@ async function applySecretBatch(options, agentIdArg) {
|
|
|
90861
91277
|
for (const rawKey of options.unset ?? []) {
|
|
90862
91278
|
delete next[rawKey.toUpperCase()];
|
|
90863
91279
|
}
|
|
90864
|
-
|
|
90865
|
-
await client.agents.update(agentId, { secrets: next });
|
|
91280
|
+
await getBackend().updateAgent(agentId, { secrets: next });
|
|
90866
91281
|
setCache(agentId, next);
|
|
90867
91282
|
return Object.keys(next).sort();
|
|
90868
91283
|
}
|
|
@@ -90870,14 +91285,13 @@ async function setSecretOnServer(key, value, agentIdArg) {
|
|
|
90870
91285
|
if (!getBackend().capabilities.serverSecrets) {
|
|
90871
91286
|
throw new Error("Agent secrets are not supported by this backend yet");
|
|
90872
91287
|
}
|
|
90873
|
-
const client = await getClient();
|
|
90874
91288
|
const agentId = resolveSecretsAgentId(agentIdArg);
|
|
90875
91289
|
if (!agentId) {
|
|
90876
91290
|
throw new Error("No agent context set. Agent ID is required.");
|
|
90877
91291
|
}
|
|
90878
91292
|
const secrets2 = { ...loadSecrets(agentId) };
|
|
90879
91293
|
secrets2[key] = value;
|
|
90880
|
-
await
|
|
91294
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
90881
91295
|
setCache(agentId, secrets2);
|
|
90882
91296
|
}
|
|
90883
91297
|
async function deleteSecretOnServer(key, agentIdArg) {
|
|
@@ -90893,8 +91307,7 @@ async function deleteSecretOnServer(key, agentIdArg) {
|
|
|
90893
91307
|
return false;
|
|
90894
91308
|
}
|
|
90895
91309
|
delete secrets2[key];
|
|
90896
|
-
|
|
90897
|
-
await client.agents.update(agentId, { secrets: secrets2 });
|
|
91310
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
90898
91311
|
setCache(agentId, secrets2);
|
|
90899
91312
|
return true;
|
|
90900
91313
|
}
|
|
@@ -90910,7 +91323,6 @@ var SECRETS_CACHE_KEY;
|
|
|
90910
91323
|
var init_secretsStore = __esm(() => {
|
|
90911
91324
|
init_context();
|
|
90912
91325
|
init_backend2();
|
|
90913
|
-
init_client2();
|
|
90914
91326
|
SECRETS_CACHE_KEY = Symbol.for("@letta/secretsCache");
|
|
90915
91327
|
});
|
|
90916
91328
|
|
|
@@ -93684,7 +94096,9 @@ function getShellEnv() {
|
|
|
93684
94096
|
env.LETTA_AGENT_ID = agentId;
|
|
93685
94097
|
env.AGENT_ID = agentId;
|
|
93686
94098
|
try {
|
|
93687
|
-
|
|
94099
|
+
const localBackendNoMemfs = isLocalBackendNoMemfsEnvEnabled();
|
|
94100
|
+
const localBackendEnabled = process.env.LETTA_LOCAL_BACKEND_EXPERIMENTAL === "1" || process.env.LETTA_LOCAL_BACKEND_EXPERIMENTAL?.toLowerCase() === "true";
|
|
94101
|
+
if (!localBackendNoMemfs && (settingsManager.isMemfsEnabled(agentId) || localBackendEnabled)) {
|
|
93688
94102
|
const memoryDir = resolveScopedMemoryDir({ agentId });
|
|
93689
94103
|
if (!memoryDir) {
|
|
93690
94104
|
throw new Error("Unable to resolve memory directory");
|
|
@@ -93752,6 +94166,7 @@ var init_shellEnv = __esm(() => {
|
|
|
93752
94166
|
init_context();
|
|
93753
94167
|
init_memoryFilesystem();
|
|
93754
94168
|
init_client2();
|
|
94169
|
+
init_paths();
|
|
93755
94170
|
init_runtime_context();
|
|
93756
94171
|
init_settings_manager();
|
|
93757
94172
|
});
|
|
@@ -96872,6 +97287,25 @@ function buildSyntheticChannelRoute(params) {
|
|
|
96872
97287
|
updatedAt: now2
|
|
96873
97288
|
};
|
|
96874
97289
|
}
|
|
97290
|
+
function inferAccountIdFromChannelTurnSources(params) {
|
|
97291
|
+
const chatId = params.input.chatId;
|
|
97292
|
+
if (!chatId) {
|
|
97293
|
+
return;
|
|
97294
|
+
}
|
|
97295
|
+
const accountIds = new Set;
|
|
97296
|
+
for (const source of params.channelTurnSources ?? []) {
|
|
97297
|
+
if (source.channel !== params.input.channel || source.chatId !== chatId || source.agentId !== params.scope.agentId || source.conversationId !== params.scope.conversationId) {
|
|
97298
|
+
continue;
|
|
97299
|
+
}
|
|
97300
|
+
if (params.input.threadId !== undefined && (source.threadId ?? null) !== (params.input.threadId ?? null)) {
|
|
97301
|
+
continue;
|
|
97302
|
+
}
|
|
97303
|
+
if (source.accountId?.trim()) {
|
|
97304
|
+
accountIds.add(source.accountId.trim());
|
|
97305
|
+
}
|
|
97306
|
+
}
|
|
97307
|
+
return accountIds.size === 1 ? [...accountIds][0] : undefined;
|
|
97308
|
+
}
|
|
96875
97309
|
async function resolveExplicitMessageChannelContext(params) {
|
|
96876
97310
|
if (params.input.channel !== "slack") {
|
|
96877
97311
|
return `Error: Explicit MessageChannel targets are not supported on ${params.input.channel}.`;
|
|
@@ -96922,9 +97356,14 @@ async function message_channel(args) {
|
|
|
96922
97356
|
try {
|
|
96923
97357
|
let executionContext;
|
|
96924
97358
|
if (input.chatId) {
|
|
96925
|
-
const
|
|
97359
|
+
const resolvedAccountId = input.accountId ?? inferAccountIdFromChannelTurnSources({
|
|
97360
|
+
input,
|
|
97361
|
+
scope,
|
|
97362
|
+
channelTurnSources: args.channelTurnSources
|
|
97363
|
+
});
|
|
97364
|
+
const route2 = registry2.getRouteForScope(input.channel, input.chatId, scope.agentId, scope.conversationId, resolvedAccountId);
|
|
96926
97365
|
if (!route2) {
|
|
96927
|
-
return `Error: No route for chat_id "${input.chatId}" on "${input.channel}" for this agent/conversation.`;
|
|
97366
|
+
return resolvedAccountId ? `Error: No route for chat_id "${input.chatId}" on "${input.channel}" account "${resolvedAccountId}" for this agent/conversation.` : `Error: No route for chat_id "${input.chatId}" on "${input.channel}" for this agent/conversation. If multiple channel accounts can receive this chat, pass accountId (from the channel notification's account_id) to disambiguate.`;
|
|
96928
97367
|
}
|
|
96929
97368
|
const adapter2 = registry2.getAdapter(input.channel, route2.accountId);
|
|
96930
97369
|
if (!adapter2) {
|
|
@@ -110712,6 +111151,12 @@ var init_SearchFileContentGemini2 = __esm(() => {
|
|
|
110712
111151
|
// src/agent/skills.ts
|
|
110713
111152
|
var exports_skills = {};
|
|
110714
111153
|
__export(exports_skills, {
|
|
111154
|
+
isUserInvocableSkill: () => isUserInvocableSkill,
|
|
111155
|
+
isModelInvocableSkill: () => isModelInvocableSkill,
|
|
111156
|
+
getLegacyAgentSkillsDir: () => getLegacyAgentSkillsDir,
|
|
111157
|
+
getFrontmatterStringList: () => getFrontmatterStringList,
|
|
111158
|
+
getFrontmatterString: () => getFrontmatterString,
|
|
111159
|
+
getFrontmatterBoolean: () => getFrontmatterBoolean,
|
|
110715
111160
|
getBundledSkills: () => getBundledSkills,
|
|
110716
111161
|
getAgentSkillsDir: () => getAgentSkillsDir,
|
|
110717
111162
|
formatSkillsAsSystemReminder: () => formatSkillsAsSystemReminder,
|
|
@@ -110734,7 +111179,45 @@ function getBundledSkillsPath() {
|
|
|
110734
111179
|
function compareSkills(a, b) {
|
|
110735
111180
|
return a.id.localeCompare(b.id) || a.source.localeCompare(b.source) || a.path.localeCompare(b.path);
|
|
110736
111181
|
}
|
|
111182
|
+
function stripSurroundingQuotes(value) {
|
|
111183
|
+
const trimmed = value.trim();
|
|
111184
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
111185
|
+
return trimmed.slice(1, -1);
|
|
111186
|
+
}
|
|
111187
|
+
return trimmed;
|
|
111188
|
+
}
|
|
111189
|
+
function getFrontmatterString(frontmatter, key) {
|
|
111190
|
+
const value = frontmatter[key];
|
|
111191
|
+
return typeof value === "string" ? stripSurroundingQuotes(value) : undefined;
|
|
111192
|
+
}
|
|
111193
|
+
function getFrontmatterStringList(frontmatter, key) {
|
|
111194
|
+
const value = frontmatter[key];
|
|
111195
|
+
if (Array.isArray(value)) {
|
|
111196
|
+
return value.map(stripSurroundingQuotes).filter((item) => item.length > 0);
|
|
111197
|
+
}
|
|
111198
|
+
if (typeof value === "string") {
|
|
111199
|
+
return stripSurroundingQuotes(value).split(/\s+/).map((item) => item.trim()).filter((item) => item.length > 0);
|
|
111200
|
+
}
|
|
111201
|
+
return;
|
|
111202
|
+
}
|
|
111203
|
+
function getFrontmatterBoolean(frontmatter, key) {
|
|
111204
|
+
const value = getFrontmatterString(frontmatter, key)?.toLowerCase();
|
|
111205
|
+
if (value === "true")
|
|
111206
|
+
return true;
|
|
111207
|
+
if (value === "false")
|
|
111208
|
+
return false;
|
|
111209
|
+
return;
|
|
111210
|
+
}
|
|
111211
|
+
function isModelInvocableSkill(skill) {
|
|
111212
|
+
return skill.disableModelInvocation !== true;
|
|
111213
|
+
}
|
|
111214
|
+
function isUserInvocableSkill(skill) {
|
|
111215
|
+
return skill.userInvocable !== false;
|
|
111216
|
+
}
|
|
110737
111217
|
function getAgentSkillsDir(agentId) {
|
|
111218
|
+
return join25(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
111219
|
+
}
|
|
111220
|
+
function getLegacyAgentSkillsDir(agentId) {
|
|
110738
111221
|
return join25(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
|
|
110739
111222
|
}
|
|
110740
111223
|
async function getBundledSkills() {
|
|
@@ -110777,6 +111260,12 @@ async function discoverSkills(projectSkillsPath = join25(process.cwd(), SKILLS_D
|
|
|
110777
111260
|
}
|
|
110778
111261
|
}
|
|
110779
111262
|
if (agentId && includeSource("agent")) {
|
|
111263
|
+
const legacyDir = getLegacyAgentSkillsDir(agentId);
|
|
111264
|
+
const legacyResult = await discoverSkillsFromDir(legacyDir, "agent");
|
|
111265
|
+
allErrors.push(...legacyResult.errors);
|
|
111266
|
+
for (const skill of legacyResult.skills) {
|
|
111267
|
+
skillsById.set(skill.id, skill);
|
|
111268
|
+
}
|
|
110780
111269
|
const agentSkillsDir = getAgentSkillsDir(agentId);
|
|
110781
111270
|
const agentResult = await discoverSkillsFromDir(agentSkillsDir, "agent");
|
|
110782
111271
|
allErrors.push(...agentResult.errors);
|
|
@@ -110860,7 +111349,7 @@ async function parseSkillFile(filePath, rootPath, source) {
|
|
|
110860
111349
|
const defaultId = dirPath || "root";
|
|
110861
111350
|
const id = (typeof frontmatter.id === "string" ? frontmatter.id : null) || defaultId;
|
|
110862
111351
|
const name25 = (typeof frontmatter.name === "string" ? frontmatter.name : null) || (typeof frontmatter.title === "string" ? frontmatter.title : null) || (id.split("/").pop() ?? "").replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
|
|
110863
|
-
let description =
|
|
111352
|
+
let description = getFrontmatterString(frontmatter, "description") ?? null;
|
|
110864
111353
|
if (!description) {
|
|
110865
111354
|
const firstParagraph = body.trim().split(`
|
|
110866
111355
|
|
|
@@ -110868,30 +111357,31 @@ async function parseSkillFile(filePath, rootPath, source) {
|
|
|
110868
111357
|
description = firstParagraph || "No description available";
|
|
110869
111358
|
}
|
|
110870
111359
|
description = description.trim();
|
|
110871
|
-
|
|
110872
|
-
|
|
110873
|
-
|
|
110874
|
-
|
|
110875
|
-
|
|
110876
|
-
tags = frontmatter.tags;
|
|
110877
|
-
} else if (typeof frontmatter.tags === "string") {
|
|
110878
|
-
tags = [frontmatter.tags];
|
|
110879
|
-
}
|
|
111360
|
+
const whenToUse = getFrontmatterString(frontmatter, "when_to_use")?.trim();
|
|
111361
|
+
const modelDescription = whenToUse ? `${description}
|
|
111362
|
+
|
|
111363
|
+
When to use: ${whenToUse}` : description;
|
|
111364
|
+
const tags = getFrontmatterStringList(frontmatter, "tags");
|
|
110880
111365
|
return {
|
|
110881
111366
|
id,
|
|
110882
111367
|
name: name25,
|
|
110883
|
-
description,
|
|
110884
|
-
|
|
111368
|
+
description: modelDescription,
|
|
111369
|
+
whenToUse,
|
|
111370
|
+
argumentHint: getFrontmatterString(frontmatter, "argument-hint"),
|
|
111371
|
+
arguments: getFrontmatterStringList(frontmatter, "arguments"),
|
|
111372
|
+
disableModelInvocation: getFrontmatterBoolean(frontmatter, "disable-model-invocation") ?? false,
|
|
111373
|
+
userInvocable: getFrontmatterBoolean(frontmatter, "user-invocable") ?? true,
|
|
111374
|
+
category: getFrontmatterString(frontmatter, "category"),
|
|
110885
111375
|
tags,
|
|
110886
111376
|
path: filePath,
|
|
110887
111377
|
source
|
|
110888
111378
|
};
|
|
110889
111379
|
}
|
|
110890
111380
|
function formatSkillsAsSystemReminder(skills) {
|
|
110891
|
-
|
|
111381
|
+
const lines = skills.filter(isModelInvocableSkill).sort(compareSkills).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
111382
|
+
if (lines.length === 0) {
|
|
110892
111383
|
return "";
|
|
110893
111384
|
}
|
|
110894
|
-
const lines = [...skills].sort(compareSkills).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
110895
111385
|
return `<system-reminder>
|
|
110896
111386
|
The following skills are available for use with the Skill tool:
|
|
110897
111387
|
|
|
@@ -110925,6 +111415,15 @@ var init_skillContentRegistry = __esm(() => {
|
|
|
110925
111415
|
});
|
|
110926
111416
|
|
|
110927
111417
|
// src/tools/impl/Skill.ts
|
|
111418
|
+
var exports_Skill = {};
|
|
111419
|
+
__export(exports_Skill, {
|
|
111420
|
+
wrapSkillContent: () => wrapSkillContent,
|
|
111421
|
+
skill: () => skill,
|
|
111422
|
+
renderSkillContent: () => renderSkillContent,
|
|
111423
|
+
readSkillContent: () => readSkillContent,
|
|
111424
|
+
loadRenderedSkillContent: () => loadRenderedSkillContent,
|
|
111425
|
+
getResolvedSkillsDir: () => getResolvedSkillsDir
|
|
111426
|
+
});
|
|
110928
111427
|
import { existsSync as existsSync23, readdirSync as readdirSync7 } from "node:fs";
|
|
110929
111428
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
110930
111429
|
import { dirname as dirname12, join as join26 } from "node:path";
|
|
@@ -111009,6 +111508,83 @@ function getResolvedAgentId(args) {
|
|
|
111009
111508
|
return;
|
|
111010
111509
|
}
|
|
111011
111510
|
}
|
|
111511
|
+
function splitSkillArguments(args) {
|
|
111512
|
+
const parts = [];
|
|
111513
|
+
const pattern = /"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|\S+/g;
|
|
111514
|
+
for (const match2 of args.matchAll(pattern)) {
|
|
111515
|
+
const raw = match2[1] ?? match2[2] ?? match2[0];
|
|
111516
|
+
parts.push(raw.replace(/\\(["'\\])/g, "$1"));
|
|
111517
|
+
}
|
|
111518
|
+
return parts;
|
|
111519
|
+
}
|
|
111520
|
+
function substituteSkillArguments(content, args, argumentNames) {
|
|
111521
|
+
const rawArgs = args?.trim() ?? "";
|
|
111522
|
+
if (!rawArgs) {
|
|
111523
|
+
return content;
|
|
111524
|
+
}
|
|
111525
|
+
const argParts = splitSkillArguments(rawArgs);
|
|
111526
|
+
let result = content;
|
|
111527
|
+
let substituted = false;
|
|
111528
|
+
result = result.replace(/\$ARGUMENTS\[(\d+)\]/g, (_match, index) => {
|
|
111529
|
+
substituted = true;
|
|
111530
|
+
return argParts[Number(index)] ?? "";
|
|
111531
|
+
});
|
|
111532
|
+
result = result.replace(/\$ARGUMENTS/g, () => {
|
|
111533
|
+
substituted = true;
|
|
111534
|
+
return rawArgs;
|
|
111535
|
+
});
|
|
111536
|
+
result = result.replace(/\$(\d+)\b/g, (_match, index) => {
|
|
111537
|
+
substituted = true;
|
|
111538
|
+
return argParts[Number(index)] ?? "";
|
|
111539
|
+
});
|
|
111540
|
+
for (const [index, name25] of (argumentNames ?? []).entries()) {
|
|
111541
|
+
const escapedName = name25.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
111542
|
+
const namePattern = new RegExp(`\\$${escapedName}\\b`, "g");
|
|
111543
|
+
result = result.replace(namePattern, () => {
|
|
111544
|
+
substituted = true;
|
|
111545
|
+
return argParts[index] ?? "";
|
|
111546
|
+
});
|
|
111547
|
+
}
|
|
111548
|
+
if (!substituted) {
|
|
111549
|
+
result = `${result.trimEnd()}
|
|
111550
|
+
|
|
111551
|
+
ARGUMENTS: ${rawArgs}`;
|
|
111552
|
+
}
|
|
111553
|
+
return result;
|
|
111554
|
+
}
|
|
111555
|
+
function renderSkillContent(skillName, skillContent, skillPath, options = {}) {
|
|
111556
|
+
const { frontmatter } = parseFrontmatter(skillContent);
|
|
111557
|
+
if (!options.allowDisabledModelInvocation && getFrontmatterBoolean(frontmatter, "disable-model-invocation") === true) {
|
|
111558
|
+
throw new Error(`Skill "${skillName}" is marked disable-model-invocation and can only be invoked directly by the user.`);
|
|
111559
|
+
}
|
|
111560
|
+
const skillDir = dirname12(skillPath);
|
|
111561
|
+
const hasExtras = hasAdditionalFiles(skillPath);
|
|
111562
|
+
const argumentNames = getFrontmatterStringList(frontmatter, "arguments");
|
|
111563
|
+
const withSkillDir = skillContent.replace(/<SKILL_DIR>/g, skillDir).replace(/\$\{CLAUDE_SKILL_DIR\}/g, skillDir);
|
|
111564
|
+
const withArguments = substituteSkillArguments(withSkillDir, options.args, argumentNames);
|
|
111565
|
+
const dirHeader = hasExtras ? `# Skill Directory: ${skillDir}
|
|
111566
|
+
|
|
111567
|
+
` : "";
|
|
111568
|
+
return `${dirHeader}${withArguments}`;
|
|
111569
|
+
}
|
|
111570
|
+
async function loadRenderedSkillContent(skillName, options = {}) {
|
|
111571
|
+
const skillsDir = options.skillsDir ?? await getResolvedSkillsDir();
|
|
111572
|
+
const { content: skillContent, path: skillPath } = await readSkillContent(skillName, skillsDir, options.agentId);
|
|
111573
|
+
return renderSkillContent(skillName, skillContent, skillPath, options);
|
|
111574
|
+
}
|
|
111575
|
+
function escapeXmlAttribute2(value) {
|
|
111576
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
111577
|
+
}
|
|
111578
|
+
function wrapSkillContent(skillName, content) {
|
|
111579
|
+
if (/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(skillName)) {
|
|
111580
|
+
return `<${skillName}>
|
|
111581
|
+
${content}
|
|
111582
|
+
</${skillName}>`;
|
|
111583
|
+
}
|
|
111584
|
+
return `<skill name="${escapeXmlAttribute2(skillName)}">
|
|
111585
|
+
${content}
|
|
111586
|
+
</skill>`;
|
|
111587
|
+
}
|
|
111012
111588
|
async function skill(args) {
|
|
111013
111589
|
validateRequiredParams(args, ["skill"], "Skill");
|
|
111014
111590
|
const { skill: skillName, toolCallId } = args;
|
|
@@ -111018,18 +111594,13 @@ async function skill(args) {
|
|
|
111018
111594
|
try {
|
|
111019
111595
|
const agentId = getResolvedAgentId(args);
|
|
111020
111596
|
const skillsDir = await getResolvedSkillsDir();
|
|
111021
|
-
const
|
|
111022
|
-
|
|
111023
|
-
|
|
111024
|
-
|
|
111025
|
-
|
|
111026
|
-
|
|
111027
|
-
` : "";
|
|
111028
|
-
const fullContent = `${dirHeader}${processedContent}`;
|
|
111597
|
+
const fullContent = await loadRenderedSkillContent(skillName, {
|
|
111598
|
+
agentId,
|
|
111599
|
+
skillsDir,
|
|
111600
|
+
args: args.args
|
|
111601
|
+
});
|
|
111029
111602
|
if (toolCallId) {
|
|
111030
|
-
queueSkillContent(toolCallId,
|
|
111031
|
-
${fullContent}
|
|
111032
|
-
</${skillName}>`);
|
|
111603
|
+
queueSkillContent(toolCallId, wrapSkillContent(skillName, fullContent));
|
|
111033
111604
|
}
|
|
111034
111605
|
return { message: `Launching skill: ${skillName}` };
|
|
111035
111606
|
} catch (error51) {
|
|
@@ -111415,18 +111986,21 @@ var init_contextBudget = __esm(() => {
|
|
|
111415
111986
|
// src/agent/subagents/manager.ts
|
|
111416
111987
|
import { spawn as spawn5 } from "node:child_process";
|
|
111417
111988
|
function getModelHandleFromAgent(agent) {
|
|
111989
|
+
const directModel = agent.model;
|
|
111990
|
+
if (directModel?.includes("/")) {
|
|
111991
|
+
return directModel;
|
|
111992
|
+
}
|
|
111418
111993
|
const endpoint = agent.llm_config?.model_endpoint_type;
|
|
111419
111994
|
const model = agent.llm_config?.model;
|
|
111420
111995
|
if (endpoint && model) {
|
|
111421
111996
|
return `${endpoint}/${model}`;
|
|
111422
111997
|
}
|
|
111423
|
-
return model || null;
|
|
111998
|
+
return directModel || model || null;
|
|
111424
111999
|
}
|
|
111425
112000
|
async function getPrimaryAgentModelHandle() {
|
|
111426
112001
|
try {
|
|
111427
112002
|
const agentId = getCurrentAgentId();
|
|
111428
|
-
const
|
|
111429
|
-
const agent = await client.agents.retrieve(agentId);
|
|
112003
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
111430
112004
|
return { handle: getModelHandleFromAgent(agent), agent };
|
|
111431
112005
|
} catch {
|
|
111432
112006
|
return { handle: null, agent: null };
|
|
@@ -111696,6 +112270,8 @@ function resolveSubagentLauncher(cliArgs, options = {}) {
|
|
|
111696
112270
|
function composeSubagentChildEnv(options) {
|
|
111697
112271
|
const {
|
|
111698
112272
|
parentProcessEnv,
|
|
112273
|
+
backendMode,
|
|
112274
|
+
localBackendStorageDir,
|
|
111699
112275
|
parentAgentId,
|
|
111700
112276
|
permissionMode: permissionMode2,
|
|
111701
112277
|
inheritedPrimaryRoot,
|
|
@@ -111709,6 +112285,14 @@ function composeSubagentChildEnv(options) {
|
|
|
111709
112285
|
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
111710
112286
|
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId }
|
|
111711
112287
|
};
|
|
112288
|
+
if (backendMode === "local") {
|
|
112289
|
+
childEnv.LETTA_LOCAL_BACKEND_EXPERIMENTAL = "1";
|
|
112290
|
+
if (localBackendStorageDir) {
|
|
112291
|
+
childEnv.LETTA_LOCAL_BACKEND_DIR = localBackendStorageDir;
|
|
112292
|
+
}
|
|
112293
|
+
} else if (backendMode === "api") {
|
|
112294
|
+
childEnv.LETTA_LOCAL_BACKEND_EXPERIMENTAL = "0";
|
|
112295
|
+
}
|
|
111712
112296
|
const nextScope = new Set([
|
|
111713
112297
|
...parseScopeList(parentProcessEnv.LETTA_MEMORY_SCOPE),
|
|
111714
112298
|
...cliPermissions.getMemoryScope()
|
|
@@ -111732,6 +112316,12 @@ function composeSubagentChildEnv(options) {
|
|
|
111732
112316
|
}
|
|
111733
112317
|
return childEnv;
|
|
111734
112318
|
}
|
|
112319
|
+
function resolveSubagentInheritedPrimaryRoot(options) {
|
|
112320
|
+
if (options.backendMode === "local" && options.parentAgentId) {
|
|
112321
|
+
return getLocalBackendMemoryFilesystemRoot(options.parentAgentId, options.localBackendStorageDir ?? getLocalBackendStorageDir2());
|
|
112322
|
+
}
|
|
112323
|
+
return options.inheritedPrimaryRoot;
|
|
112324
|
+
}
|
|
111735
112325
|
function getReflectionStartupNotice() {
|
|
111736
112326
|
return `[Reflection startup context truncated: system prompt + initial message are capped at ~${REFLECTION_STARTUP_CONTEXT_TOKEN_LIMIT.toLocaleString()} estimated tokens. Some parent memory preview content was omitted; read files directly from MEMORY_DIR if needed.]`;
|
|
111737
112327
|
}
|
|
@@ -111794,9 +112384,12 @@ ${userPrompt}`);
|
|
|
111794
112384
|
}
|
|
111795
112385
|
return hardTruncateReflectionPrompt(userPrompt, allowedPromptChars);
|
|
111796
112386
|
}
|
|
111797
|
-
function buildSubagentArgs(type, config2, model, userPrompt, existingAgentId, existingConversationId, maxTurns) {
|
|
112387
|
+
function buildSubagentArgs(type, config2, model, userPrompt, existingAgentId, existingConversationId, maxTurns, options = {}) {
|
|
111798
112388
|
const args = [];
|
|
111799
112389
|
const isDeployingExisting = Boolean(existingAgentId || existingConversationId);
|
|
112390
|
+
if (options.backendMode) {
|
|
112391
|
+
args.push("--backend", options.backendMode);
|
|
112392
|
+
}
|
|
111800
112393
|
if (isDeployingExisting) {
|
|
111801
112394
|
if (existingConversationId) {
|
|
111802
112395
|
args.push("--conv", existingConversationId);
|
|
@@ -111868,7 +112461,9 @@ async function executeSubagent(type, config2, model, userPrompt, baseURL, subage
|
|
|
111868
112461
|
updateSubagent(subagentId, { model });
|
|
111869
112462
|
}
|
|
111870
112463
|
try {
|
|
111871
|
-
const
|
|
112464
|
+
const activeBackend = getBackend();
|
|
112465
|
+
const backendMode = activeBackend.capabilities.localMemfs ? "local" : "api";
|
|
112466
|
+
const cliArgs = buildSubagentArgs(type, config2, model, userPrompt, existingAgentId, existingConversationId, maxTurns, { backendMode });
|
|
111872
112467
|
const launcher = resolveSubagentLauncher(cliArgs);
|
|
111873
112468
|
let parentAgentId = parentAgentIdOverride;
|
|
111874
112469
|
if (!parentAgentId) {
|
|
@@ -111882,19 +112477,28 @@ async function executeSubagent(type, config2, model, userPrompt, baseURL, subage
|
|
|
111882
112477
|
const inheritedMemoryRoots = resolveAllowedMemoryRoots({
|
|
111883
112478
|
currentAgentId: parentAgentId ?? null
|
|
111884
112479
|
});
|
|
112480
|
+
const localBackendStorageDir = backendMode === "local" ? getLocalBackendStorageDir2() : null;
|
|
112481
|
+
const inheritedPrimaryRoot = resolveSubagentInheritedPrimaryRoot({
|
|
112482
|
+
backendMode,
|
|
112483
|
+
parentAgentId,
|
|
112484
|
+
inheritedPrimaryRoot: inheritedMemoryRoots.primaryRoot,
|
|
112485
|
+
localBackendStorageDir
|
|
112486
|
+
});
|
|
111885
112487
|
const subagentWorkingDirectory = resolveSubagentWorkingDirectory(process.env, getCurrentWorkingDirectory(), {
|
|
111886
112488
|
subagentType: type,
|
|
111887
112489
|
permissionMode: config2.permissionMode,
|
|
111888
|
-
inheritedPrimaryRoot
|
|
112490
|
+
inheritedPrimaryRoot
|
|
111889
112491
|
});
|
|
111890
112492
|
const childEnv = composeSubagentChildEnv({
|
|
111891
112493
|
parentProcessEnv: {
|
|
111892
112494
|
...process.env,
|
|
111893
112495
|
USER_CWD: subagentWorkingDirectory
|
|
111894
112496
|
},
|
|
112497
|
+
backendMode,
|
|
112498
|
+
localBackendStorageDir,
|
|
111895
112499
|
parentAgentId,
|
|
111896
112500
|
permissionMode: config2.permissionMode,
|
|
111897
|
-
inheritedPrimaryRoot
|
|
112501
|
+
inheritedPrimaryRoot,
|
|
111898
112502
|
inheritedApiKey,
|
|
111899
112503
|
inheritedBaseUrl
|
|
111900
112504
|
});
|
|
@@ -112080,7 +112684,7 @@ async function spawnSubagent(type, prompt, userModel, subagentId, signal, existi
|
|
|
112080
112684
|
let finalPrompt = prompt;
|
|
112081
112685
|
if (isDeployingExisting && resolvedParentAgentId) {
|
|
112082
112686
|
try {
|
|
112083
|
-
const cachedParent = parentAgent ?? await (
|
|
112687
|
+
const cachedParent = parentAgent ?? await getBackend().retrieveAgent(resolvedParentAgentId);
|
|
112084
112688
|
if (forkedContext) {
|
|
112085
112689
|
const systemReminder = buildForkSystemReminder(type);
|
|
112086
112690
|
finalPrompt = systemReminder + prompt;
|
|
@@ -112095,8 +112699,9 @@ async function spawnSubagent(type, prompt, userModel, subagentId, signal, existi
|
|
|
112095
112699
|
}
|
|
112096
112700
|
var BYOK_PROVIDER_TO_BASE;
|
|
112097
112701
|
var init_manager3 = __esm(() => {
|
|
112098
|
-
|
|
112702
|
+
init_backend2();
|
|
112099
112703
|
init_metadata();
|
|
112704
|
+
init_paths();
|
|
112100
112705
|
init_subagentState();
|
|
112101
112706
|
init_constants();
|
|
112102
112707
|
init_cli();
|
|
@@ -112124,22 +112729,6 @@ var init_manager3 = __esm(() => {
|
|
|
112124
112729
|
};
|
|
112125
112730
|
});
|
|
112126
112731
|
|
|
112127
|
-
// src/backend/api/conversations.ts
|
|
112128
|
-
var exports_conversations = {};
|
|
112129
|
-
__export(exports_conversations, {
|
|
112130
|
-
forkConversation: () => forkConversation
|
|
112131
|
-
});
|
|
112132
|
-
async function forkConversation(conversationId, options = {}) {
|
|
112133
|
-
const query = {
|
|
112134
|
-
...options.agentId ? { agent_id: options.agentId } : {},
|
|
112135
|
-
...options.hidden !== undefined ? { hidden: options.hidden } : {}
|
|
112136
|
-
};
|
|
112137
|
-
return apiRequest("POST", `/v1/conversations/${encodeURIComponent(conversationId)}/fork`, undefined, { query });
|
|
112138
|
-
}
|
|
112139
|
-
var init_conversations2 = __esm(() => {
|
|
112140
|
-
init_request();
|
|
112141
|
-
});
|
|
112142
|
-
|
|
112143
112732
|
// src/cli/helpers/messageQueueBridge.ts
|
|
112144
112733
|
function setMessageQueueAdder(fn) {
|
|
112145
112734
|
queueAdder = fn;
|
|
@@ -112557,7 +113146,7 @@ async function task(args) {
|
|
|
112557
113146
|
try {
|
|
112558
113147
|
const parentAgentId = getCurrentAgentId();
|
|
112559
113148
|
const parentConvId = getConversationId() ?? "default";
|
|
112560
|
-
const forkedConv = await forkConversation(parentConvId, {
|
|
113149
|
+
const forkedConv = await getBackend().forkConversation(parentConvId, {
|
|
112561
113150
|
...parentConvId === "default" ? { agentId: parentAgentId } : {},
|
|
112562
113151
|
hidden: true
|
|
112563
113152
|
});
|
|
@@ -112655,7 +113244,7 @@ var init_Task2 = __esm(() => {
|
|
|
112655
113244
|
init_context();
|
|
112656
113245
|
init_subagents();
|
|
112657
113246
|
init_manager3();
|
|
112658
|
-
|
|
113247
|
+
init_backend2();
|
|
112659
113248
|
init_messageQueueBridge();
|
|
112660
113249
|
init_subagentState();
|
|
112661
113250
|
init_hooks();
|
|
@@ -116900,7 +117489,7 @@ function detectSkillScript(command, workingDir) {
|
|
|
116900
117489
|
if (projectSkill) {
|
|
116901
117490
|
return projectSkill;
|
|
116902
117491
|
}
|
|
116903
|
-
const agentRegex = new RegExp(`^${escapeRegex4(normalizedHomeDir)}/\\.letta/agents/[^/]+/skills/(.+?)/scripts/`);
|
|
117492
|
+
const agentRegex = new RegExp(`^${escapeRegex4(normalizedHomeDir)}/\\.letta/agents/[^/]+/(?:memory/)?skills/(.+?)/scripts/`);
|
|
116904
117493
|
const agentSkill = detect("agent-scoped", agentRegex);
|
|
116905
117494
|
if (agentSkill) {
|
|
116906
117495
|
return agentSkill;
|
|
@@ -117773,14 +118362,14 @@ function clipToolReturn(text2, maxLines = 3, maxChars = 300) {
|
|
|
117773
118362
|
}
|
|
117774
118363
|
return clipped;
|
|
117775
118364
|
}
|
|
117776
|
-
function
|
|
118365
|
+
function isRecord8(value) {
|
|
117777
118366
|
return typeof value === "object" && value !== null;
|
|
117778
118367
|
}
|
|
117779
118368
|
function isStringArray2(value) {
|
|
117780
118369
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
117781
118370
|
}
|
|
117782
118371
|
function isMultimodalContent(arr) {
|
|
117783
|
-
return arr.every((item) =>
|
|
118372
|
+
return arr.every((item) => isRecord8(item) && (item.type === "text" || item.type === "image"));
|
|
117784
118373
|
}
|
|
117785
118374
|
function flattenToolResponse(result) {
|
|
117786
118375
|
if (result === null || result === undefined) {
|
|
@@ -117789,7 +118378,7 @@ function flattenToolResponse(result) {
|
|
|
117789
118378
|
if (typeof result === "string") {
|
|
117790
118379
|
return result;
|
|
117791
118380
|
}
|
|
117792
|
-
if (!
|
|
118381
|
+
if (!isRecord8(result)) {
|
|
117793
118382
|
return JSON.stringify(result);
|
|
117794
118383
|
}
|
|
117795
118384
|
if (typeof result.message === "string") {
|
|
@@ -117806,7 +118395,7 @@ function flattenToolResponse(result) {
|
|
|
117806
118395
|
return result.content;
|
|
117807
118396
|
}
|
|
117808
118397
|
if (Array.isArray(result.content)) {
|
|
117809
|
-
const textContent2 = result.content.filter((item) =>
|
|
118398
|
+
const textContent2 = result.content.filter((item) => isRecord8(item) && item.type === "text" && typeof item.text === "string").map((item) => item.text).join(`
|
|
117810
118399
|
`);
|
|
117811
118400
|
if (textContent2) {
|
|
117812
118401
|
return textContent2;
|
|
@@ -117921,8 +118510,16 @@ async function executeTool2(name25, args, options) {
|
|
|
117921
118510
|
if (internalName === "Skill" && options?.parentScope) {
|
|
117922
118511
|
enhancedArgs = { ...enhancedArgs, parentScope: options.parentScope };
|
|
117923
118512
|
}
|
|
117924
|
-
if (internalName === "MessageChannel"
|
|
117925
|
-
|
|
118513
|
+
if (internalName === "MessageChannel") {
|
|
118514
|
+
if (options?.parentScope) {
|
|
118515
|
+
enhancedArgs = { ...enhancedArgs, parentScope: options.parentScope };
|
|
118516
|
+
}
|
|
118517
|
+
if (options?.channelTurnSources?.length) {
|
|
118518
|
+
enhancedArgs = {
|
|
118519
|
+
...enhancedArgs,
|
|
118520
|
+
channelTurnSources: options.channelTurnSources
|
|
118521
|
+
};
|
|
118522
|
+
}
|
|
117926
118523
|
}
|
|
117927
118524
|
const PLAN_MODE_TOOL_NAMES = new Set([
|
|
117928
118525
|
"EnterPlanMode",
|
|
@@ -117949,7 +118546,7 @@ async function executeTool2(name25, args, options) {
|
|
|
117949
118546
|
} catch {}
|
|
117950
118547
|
}
|
|
117951
118548
|
}
|
|
117952
|
-
const recordResult =
|
|
118549
|
+
const recordResult = isRecord8(result) ? result : undefined;
|
|
117953
118550
|
const stdoutValue = recordResult?.stdout;
|
|
117954
118551
|
const stderrValue = recordResult?.stderr;
|
|
117955
118552
|
const stdout = isStringArray2(stdoutValue) ? stdoutValue : undefined;
|
|
@@ -118683,9 +119280,8 @@ async function hydrateMemfsSettingFromAgent(agent) {
|
|
|
118683
119280
|
return enabled;
|
|
118684
119281
|
}
|
|
118685
119282
|
async function isMemfsEnabledOnServer(agentId) {
|
|
118686
|
-
const {
|
|
118687
|
-
const
|
|
118688
|
-
const agent = await client.agents.retrieve(agentId, {
|
|
119283
|
+
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
119284
|
+
const agent = await getBackend2().retrieveAgent(agentId, {
|
|
118689
119285
|
include: ["agent.tags"]
|
|
118690
119286
|
});
|
|
118691
119287
|
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -118818,7 +119414,8 @@ async function applyMemfsFlags(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
118818
119414
|
const backend = getBackend2();
|
|
118819
119415
|
if (backend.capabilities.localMemfs) {
|
|
118820
119416
|
if (noMemfsFlag) {
|
|
118821
|
-
|
|
119417
|
+
settingsManager2.setMemfsEnabled(agentId, false);
|
|
119418
|
+
return { action: "disabled" };
|
|
118822
119419
|
}
|
|
118823
119420
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
118824
119421
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -119274,7 +119871,7 @@ ${skillsBlock.trimStart()}`;
|
|
|
119274
119871
|
function compileLocalSystemPrompt(options) {
|
|
119275
119872
|
const compiledAt = options.now ?? new Date;
|
|
119276
119873
|
const memoryDir = options.memoryDir ?? getMemoryFilesystemRoot(options.agent.id);
|
|
119277
|
-
const memfs = renderMemfsProjection(memoryDir);
|
|
119874
|
+
const memfs = options.includeMemfs === false ? { content: "", revision: undefined } : renderMemfsProjection(memoryDir);
|
|
119278
119875
|
const metadata = compileMemoryMetadata({
|
|
119279
119876
|
agentId: options.agent.id,
|
|
119280
119877
|
conversationId: options.conversationId,
|
|
@@ -119346,6 +119943,37 @@ function initialMemoryFilesFromCreateBody(body) {
|
|
|
119346
119943
|
}
|
|
119347
119944
|
return [...files.values()].sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
119348
119945
|
}
|
|
119946
|
+
function isRecord9(value) {
|
|
119947
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
119948
|
+
}
|
|
119949
|
+
function compactionSettingsRecord(value) {
|
|
119950
|
+
if (value === null)
|
|
119951
|
+
return null;
|
|
119952
|
+
return isRecord9(value) ? { ...value } : undefined;
|
|
119953
|
+
}
|
|
119954
|
+
function hasOwn2(record2, key) {
|
|
119955
|
+
return Object.hasOwn(record2, key);
|
|
119956
|
+
}
|
|
119957
|
+
function localCompactionMode(value) {
|
|
119958
|
+
if (value === "all" || value === "sliding_window")
|
|
119959
|
+
return value;
|
|
119960
|
+
return;
|
|
119961
|
+
}
|
|
119962
|
+
function validateLocalCompactionSettingsRecord(settings) {
|
|
119963
|
+
if (settings.mode === undefined || settings.mode === null)
|
|
119964
|
+
return;
|
|
119965
|
+
if (!localCompactionMode(settings.mode)) {
|
|
119966
|
+
throw new Error(`Local backend compaction currently supports only modes "all" and "sliding_window" (received "${String(settings.mode)}").`);
|
|
119967
|
+
}
|
|
119968
|
+
}
|
|
119969
|
+
function localCompactionSettingsForStorage(settings) {
|
|
119970
|
+
if (settings === undefined || settings === null)
|
|
119971
|
+
return settings;
|
|
119972
|
+
const hasLocalSetting = hasOwn2(settings, "mode") || hasOwn2(settings, "prompt") || hasOwn2(settings, "clip_chars") || hasOwn2(settings, "sliding_window_percentage");
|
|
119973
|
+
if (!hasLocalSetting)
|
|
119974
|
+
return;
|
|
119975
|
+
return { ...settings };
|
|
119976
|
+
}
|
|
119349
119977
|
function createLocalExecutor(options, onContextWindowOverflow, onContextUsage) {
|
|
119350
119978
|
if (options.executor)
|
|
119351
119979
|
return options.executor;
|
|
@@ -119385,6 +120013,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119385
120013
|
storageDir;
|
|
119386
120014
|
createModel;
|
|
119387
120015
|
generateText;
|
|
120016
|
+
memfsEnabledOverride;
|
|
119388
120017
|
constructor(options) {
|
|
119389
120018
|
const localBackendRef = {};
|
|
119390
120019
|
const modelConfig = resolveLocalModelConfig(options.storageDir);
|
|
@@ -119410,19 +120039,46 @@ var init_LocalBackend = __esm(() => {
|
|
|
119410
120039
|
this.memoryDir = options.memoryDir;
|
|
119411
120040
|
this.createModel = options.createModel;
|
|
119412
120041
|
this.generateText = options.generateText;
|
|
120042
|
+
this.memfsEnabledOverride = options.memfsEnabled;
|
|
119413
120043
|
}
|
|
119414
120044
|
async listModels() {
|
|
119415
120045
|
return listLocalModels(this.storageDir);
|
|
119416
120046
|
}
|
|
119417
120047
|
async createAgent(...args) {
|
|
119418
120048
|
const [body] = args;
|
|
119419
|
-
const
|
|
119420
|
-
|
|
120049
|
+
const requestedCompactionSettings = compactionSettingsRecord(body.compaction_settings);
|
|
120050
|
+
if (requestedCompactionSettings !== undefined && requestedCompactionSettings !== null) {
|
|
120051
|
+
validateLocalCompactionSettingsRecord(requestedCompactionSettings);
|
|
120052
|
+
}
|
|
120053
|
+
const compactionSettingsForStorage = localCompactionSettingsForStorage(requestedCompactionSettings);
|
|
120054
|
+
let agent = await super.createAgent(...args);
|
|
120055
|
+
if (compactionSettingsForStorage !== undefined) {
|
|
120056
|
+
agent = this.store.setAgentCompactionSettings(agent.id, compactionSettingsForStorage);
|
|
120057
|
+
}
|
|
120058
|
+
if (this.isLocalMemfsEnabled()) {
|
|
120059
|
+
await this.ensureLocalMemoryRepo(agent.id, initialMemoryFilesFromCreateBody(body), agent.name ?? undefined);
|
|
120060
|
+
}
|
|
119421
120061
|
await this.compileAndMaybePersistSystemPrompt("default", agent.id, {
|
|
119422
120062
|
dryRun: false
|
|
119423
120063
|
});
|
|
119424
120064
|
return agent;
|
|
119425
120065
|
}
|
|
120066
|
+
async updateAgent(...args) {
|
|
120067
|
+
const [agentId, body] = args;
|
|
120068
|
+
const bodyRecord = body;
|
|
120069
|
+
const settings = hasOwn2(bodyRecord, "compaction_settings") ? compactionSettingsRecord(bodyRecord.compaction_settings) : undefined;
|
|
120070
|
+
if (settings !== undefined && settings !== null) {
|
|
120071
|
+
validateLocalCompactionSettingsRecord(settings);
|
|
120072
|
+
}
|
|
120073
|
+
const compactionSettingsForStorage = localCompactionSettingsForStorage(settings);
|
|
120074
|
+
let agent = await super.updateAgent(...args);
|
|
120075
|
+
if (hasOwn2(bodyRecord, "compaction_settings")) {
|
|
120076
|
+
if (compactionSettingsForStorage !== undefined) {
|
|
120077
|
+
agent = this.store.setAgentCompactionSettings(agentId, compactionSettingsForStorage);
|
|
120078
|
+
}
|
|
120079
|
+
}
|
|
120080
|
+
return agent;
|
|
120081
|
+
}
|
|
119426
120082
|
async createConversation(body) {
|
|
119427
120083
|
const conversation = await super.createConversation(body);
|
|
119428
120084
|
await this.compileAndMaybePersistSystemPrompt(conversation.id, conversation.agent_id, { dryRun: false });
|
|
@@ -119437,7 +120093,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119437
120093
|
async compactConversationMessages(conversationId, body) {
|
|
119438
120094
|
const bodyRecord = body ?? {};
|
|
119439
120095
|
const agentId = typeof bodyRecord.agent_id === "string" && bodyRecord.agent_id.length > 0 ? bodyRecord.agent_id : this.store.resolveAgentIdForConversation(conversationId);
|
|
119440
|
-
const result = await this.
|
|
120096
|
+
const result = await this.compactLocalConversation(conversationId, agentId, "manual", body);
|
|
119441
120097
|
return {
|
|
119442
120098
|
num_messages_before: result.numMessagesBefore,
|
|
119443
120099
|
num_messages_after: result.numMessagesAfter,
|
|
@@ -119452,6 +120108,9 @@ var init_LocalBackend = __esm(() => {
|
|
|
119452
120108
|
memoryDirForAgent(agentId) {
|
|
119453
120109
|
return this.memoryDir ?? getLocalBackendMemoryFilesystemRoot(agentId, this.storageDir);
|
|
119454
120110
|
}
|
|
120111
|
+
isLocalMemfsEnabled() {
|
|
120112
|
+
return this.memfsEnabledOverride ?? !isLocalBackendNoMemfsEnvEnabled();
|
|
120113
|
+
}
|
|
119455
120114
|
async ensureLocalMemoryRepo(agentId, files = [], authorName) {
|
|
119456
120115
|
await initializeLocalMemoryRepo({
|
|
119457
120116
|
memoryDir: this.memoryDirForAgent(agentId),
|
|
@@ -119461,9 +120120,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119461
120120
|
});
|
|
119462
120121
|
}
|
|
119463
120122
|
async compactAfterContextOverflow(input, _error) {
|
|
119464
|
-
const result = await this.
|
|
119465
|
-
compaction_settings: { mode: "all" }
|
|
119466
|
-
});
|
|
120123
|
+
const result = await this.compactLocalConversation(input.conversationId, input.agentId, "context_window_overflow");
|
|
119467
120124
|
return {
|
|
119468
120125
|
uiMessages: this.store.listLocalMessages(input.conversationId, input.agentId),
|
|
119469
120126
|
summary: result.summary,
|
|
@@ -119476,9 +120133,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119476
120133
|
if (contextTokens === undefined || contextWindow === undefined || contextTokens <= contextWindow) {
|
|
119477
120134
|
return null;
|
|
119478
120135
|
}
|
|
119479
|
-
const result = await this.
|
|
119480
|
-
compaction_settings: { mode: "all" }
|
|
119481
|
-
});
|
|
120136
|
+
const result = await this.compactLocalConversation(input.conversationId, input.agentId, "context_window_limit");
|
|
119482
120137
|
return {
|
|
119483
120138
|
uiMessages: this.store.listLocalMessages(input.conversationId, input.agentId),
|
|
119484
120139
|
summary: result.summary,
|
|
@@ -119497,24 +120152,55 @@ var init_LocalBackend = __esm(() => {
|
|
|
119497
120152
|
const agent = this.store.retrieveAgentRecord(agentId);
|
|
119498
120153
|
return typeof agent.model_settings.context_window_limit === "number" ? agent.model_settings.context_window_limit : undefined;
|
|
119499
120154
|
}
|
|
119500
|
-
|
|
119501
|
-
const
|
|
119502
|
-
const
|
|
119503
|
-
if (
|
|
119504
|
-
|
|
119505
|
-
}
|
|
120155
|
+
resolveCompactionSettings(agent, body) {
|
|
120156
|
+
const bodyRecord = body ?? {};
|
|
120157
|
+
const requestSettings = compactionSettingsRecord(bodyRecord.compaction_settings);
|
|
120158
|
+
if (requestSettings !== undefined && requestSettings !== null) {
|
|
120159
|
+
validateLocalCompactionSettingsRecord(requestSettings);
|
|
120160
|
+
}
|
|
120161
|
+
const agentSettings = compactionSettingsRecord(agent.compaction_settings);
|
|
120162
|
+
const baseSettings = agentSettings && agentSettings !== null ? agentSettings : {};
|
|
120163
|
+
const mergedSettings = requestSettings && requestSettings !== null ? { ...baseSettings, ...requestSettings } : baseSettings;
|
|
120164
|
+
const requestChangedMode = requestSettings !== undefined && requestSettings !== null && hasOwn2(requestSettings, "mode");
|
|
120165
|
+
const requestChangedPrompt = requestSettings !== undefined && requestSettings !== null && hasOwn2(requestSettings, "prompt");
|
|
120166
|
+
if (requestChangedMode && !requestChangedPrompt && agentSettings && agentSettings !== null && agentSettings.mode !== requestSettings.mode) {
|
|
120167
|
+
delete mergedSettings.prompt;
|
|
120168
|
+
}
|
|
120169
|
+
const mode = localCompactionMode(mergedSettings.mode) ?? LOCAL_DEFAULT_COMPACTION_MODE;
|
|
120170
|
+
return {
|
|
120171
|
+
mode,
|
|
120172
|
+
prompt: typeof mergedSettings.prompt === "string" || mergedSettings.prompt === null ? mergedSettings.prompt : undefined,
|
|
120173
|
+
clipChars: typeof mergedSettings.clip_chars === "number" || mergedSettings.clip_chars === null ? mergedSettings.clip_chars : undefined,
|
|
120174
|
+
slidingWindowPercentage: typeof mergedSettings.sliding_window_percentage === "number" ? mergedSettings.sliding_window_percentage : LOCAL_DEFAULT_SLIDING_WINDOW_PERCENTAGE
|
|
120175
|
+
};
|
|
120176
|
+
}
|
|
120177
|
+
async compactLocalConversation(conversationId, agentId, trigger, body) {
|
|
119506
120178
|
const agent = this.store.retrieveAgentRecord(agentId);
|
|
120179
|
+
const settings = this.resolveCompactionSettings(agent, body);
|
|
120180
|
+
if (settings.mode === "sliding_window") {
|
|
120181
|
+
try {
|
|
120182
|
+
return await this.compactLocalConversationSlidingWindow(conversationId, agentId, agent, trigger, settings);
|
|
120183
|
+
} catch (error51) {
|
|
120184
|
+
if (!isLocalSlidingWindowCompactionPlanningError(error51))
|
|
120185
|
+
throw error51;
|
|
120186
|
+
}
|
|
120187
|
+
}
|
|
120188
|
+
return this.compactLocalConversationAll(conversationId, agentId, agent, trigger, {
|
|
120189
|
+
...settings,
|
|
120190
|
+
mode: "all",
|
|
120191
|
+
prompt: settings.mode === "all" ? settings.prompt : undefined
|
|
120192
|
+
});
|
|
120193
|
+
}
|
|
120194
|
+
async compactLocalConversationAll(conversationId, agentId, agent, trigger, settings) {
|
|
119507
120195
|
const messages = this.store.listLocalMessages(conversationId, agentId);
|
|
119508
120196
|
const contextTokensBefore = estimateLocalMessageTokens(messages);
|
|
119509
|
-
const prompt = typeof settings?.prompt === "string" ? settings.prompt : null;
|
|
119510
|
-
const clipChars = typeof settings?.clip_chars === "number" || settings?.clip_chars === null ? settings.clip_chars : undefined;
|
|
119511
120197
|
const summary = await summarizeLocalMessagesAll({
|
|
119512
120198
|
agent,
|
|
119513
120199
|
messages,
|
|
119514
120200
|
createModel: this.createModel,
|
|
119515
120201
|
generateText: this.generateText,
|
|
119516
|
-
prompt,
|
|
119517
|
-
clipChars,
|
|
120202
|
+
prompt: settings.prompt,
|
|
120203
|
+
clipChars: settings.clipChars,
|
|
119518
120204
|
localProviderAuthStorageDir: this.storageDir
|
|
119519
120205
|
});
|
|
119520
120206
|
const stats = {
|
|
@@ -119539,10 +120225,51 @@ var init_LocalBackend = __esm(() => {
|
|
|
119539
120225
|
stats
|
|
119540
120226
|
};
|
|
119541
120227
|
}
|
|
120228
|
+
async compactLocalConversationSlidingWindow(conversationId, agentId, agent, trigger, settings) {
|
|
120229
|
+
const messages = this.store.listLocalMessages(conversationId, agentId);
|
|
120230
|
+
const contextWindow = this.effectiveContextWindow(conversationId, agentId);
|
|
120231
|
+
const plan = planLocalSlidingWindowCompaction(messages, {
|
|
120232
|
+
slidingWindowPercentage: settings.slidingWindowPercentage,
|
|
120233
|
+
contextWindow
|
|
120234
|
+
});
|
|
120235
|
+
const summary = await summarizeLocalMessagesSlidingWindow({
|
|
120236
|
+
agent,
|
|
120237
|
+
messages: plan.messagesToSummarize,
|
|
120238
|
+
createModel: this.createModel,
|
|
120239
|
+
generateText: this.generateText,
|
|
120240
|
+
prompt: settings.prompt,
|
|
120241
|
+
clipChars: settings.clipChars,
|
|
120242
|
+
localProviderAuthStorageDir: this.storageDir
|
|
120243
|
+
});
|
|
120244
|
+
const contextTokensAfter = Math.ceil(summary.length / 4) + estimateLocalMessageTokens(plan.messagesToKeep);
|
|
120245
|
+
const stats = {
|
|
120246
|
+
trigger,
|
|
120247
|
+
context_tokens_before: estimateLocalMessageTokens(messages),
|
|
120248
|
+
context_tokens_after: contextTokensAfter,
|
|
120249
|
+
context_window: contextWindow,
|
|
120250
|
+
messages_count_before: messages.length,
|
|
120251
|
+
messages_count_after: 1 + plan.messagesToKeep.length
|
|
120252
|
+
};
|
|
120253
|
+
const storeResult = this.store.compactConversationAll({
|
|
120254
|
+
conversationId,
|
|
120255
|
+
agentId,
|
|
120256
|
+
summary,
|
|
120257
|
+
packedSummary: packageLocalSummaryMessage(summary, stats),
|
|
120258
|
+
stats,
|
|
120259
|
+
remainingMessages: plan.messagesToKeep
|
|
120260
|
+
});
|
|
120261
|
+
return {
|
|
120262
|
+
numMessagesBefore: storeResult.numMessagesBefore,
|
|
120263
|
+
numMessagesAfter: storeResult.numMessagesAfter,
|
|
120264
|
+
summary,
|
|
120265
|
+
stats
|
|
120266
|
+
};
|
|
120267
|
+
}
|
|
119542
120268
|
async getOrCompileSystemPrompt(conversationId, agentId, agent = this.store.retrieveAgentRecord(agentId), previousMessageCount = 0) {
|
|
119543
120269
|
const existing = this.store.getCompiledSystemPrompt(conversationId, agentId);
|
|
119544
|
-
const
|
|
119545
|
-
|
|
120270
|
+
const memfsEnabled = this.isLocalMemfsEnabled();
|
|
120271
|
+
const memfsRevision = memfsEnabled ? await getMemoryHeadRevision(this.memoryDirForAgent(agentId)) : undefined;
|
|
120272
|
+
if (existing?.rawSystemHash === hashRawSystemPrompt(agent.system) && (memfsEnabled ? memfsRevision !== null && existing.memfsRevision === memfsRevision : existing.memfsRevision === undefined)) {
|
|
119546
120273
|
return existing;
|
|
119547
120274
|
}
|
|
119548
120275
|
return this.compileAndMaybePersistSystemPrompt(conversationId, agentId, {
|
|
@@ -119552,7 +120279,10 @@ var init_LocalBackend = __esm(() => {
|
|
|
119552
120279
|
}
|
|
119553
120280
|
async compileAndMaybePersistSystemPrompt(conversationId, agentId, options) {
|
|
119554
120281
|
const agent = this.store.retrieveAgentRecord(agentId);
|
|
119555
|
-
|
|
120282
|
+
const memfsEnabled = this.isLocalMemfsEnabled();
|
|
120283
|
+
if (memfsEnabled) {
|
|
120284
|
+
await this.ensureLocalMemoryRepo(agentId, [], agent.name);
|
|
120285
|
+
}
|
|
119556
120286
|
const previousMessageCount = options.previousMessageCount ?? this.store.listConversationMessages(conversationId, {
|
|
119557
120287
|
agent_id: agentId,
|
|
119558
120288
|
order: "asc"
|
|
@@ -119561,7 +120291,8 @@ var init_LocalBackend = __esm(() => {
|
|
|
119561
120291
|
agent,
|
|
119562
120292
|
conversationId,
|
|
119563
120293
|
previousMessageCount,
|
|
119564
|
-
memoryDir: this.memoryDirForAgent(agentId)
|
|
120294
|
+
memoryDir: memfsEnabled ? this.memoryDirForAgent(agentId) : undefined,
|
|
120295
|
+
includeMemfs: memfsEnabled
|
|
119565
120296
|
});
|
|
119566
120297
|
if (!options.dryRun) {
|
|
119567
120298
|
this.store.setCompiledSystemPrompt(conversationId, agentId, compiled);
|
|
@@ -119571,6 +120302,22 @@ var init_LocalBackend = __esm(() => {
|
|
|
119571
120302
|
};
|
|
119572
120303
|
});
|
|
119573
120304
|
|
|
120305
|
+
// src/backend/api/conversations.ts
|
|
120306
|
+
var exports_conversations = {};
|
|
120307
|
+
__export(exports_conversations, {
|
|
120308
|
+
forkConversation: () => forkConversation
|
|
120309
|
+
});
|
|
120310
|
+
async function forkConversation(conversationId, options = {}) {
|
|
120311
|
+
const query = {
|
|
120312
|
+
...options.agentId ? { agent_id: options.agentId } : {},
|
|
120313
|
+
...options.hidden !== undefined ? { hidden: options.hidden } : {}
|
|
120314
|
+
};
|
|
120315
|
+
return apiRequest("POST", `/v1/conversations/${encodeURIComponent(conversationId)}/fork`, undefined, { query });
|
|
120316
|
+
}
|
|
120317
|
+
var init_conversations2 = __esm(() => {
|
|
120318
|
+
init_request();
|
|
120319
|
+
});
|
|
120320
|
+
|
|
119574
120321
|
// src/backend/backend.ts
|
|
119575
120322
|
import { homedir as homedir19 } from "node:os";
|
|
119576
120323
|
|
|
@@ -119717,6 +120464,7 @@ function getBackend() {
|
|
|
119717
120464
|
}
|
|
119718
120465
|
function configureBackendMode(mode) {
|
|
119719
120466
|
configuredBackendMode = mode;
|
|
120467
|
+
process.env[LOCAL_BACKEND_EXPERIMENTAL_ENV] = mode === "local" ? "1" : "0";
|
|
119720
120468
|
backend = createBackendForMode(mode);
|
|
119721
120469
|
}
|
|
119722
120470
|
function isLocalBackendEnabled() {
|
|
@@ -143952,7 +144700,10 @@ function getTerminalTheme() {
|
|
|
143952
144700
|
cachedTheme = detectTerminalThemeSync();
|
|
143953
144701
|
return cachedTheme;
|
|
143954
144702
|
}
|
|
143955
|
-
|
|
144703
|
+
function getTerminalBackgroundColor() {
|
|
144704
|
+
return cachedBackground;
|
|
144705
|
+
}
|
|
144706
|
+
var cachedTheme = null, cachedBackground = null;
|
|
143956
144707
|
|
|
143957
144708
|
// src/cli/components/colors.ts
|
|
143958
144709
|
function parseHex(hex3) {
|
|
@@ -143963,6 +144714,26 @@ function parseHex(hex3) {
|
|
|
143963
144714
|
b: parseInt(h.slice(4, 6), 16)
|
|
143964
144715
|
};
|
|
143965
144716
|
}
|
|
144717
|
+
function rgbToHex({ r, g, b }) {
|
|
144718
|
+
const toHex = (value) => value.toString(16).padStart(2, "0");
|
|
144719
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
144720
|
+
}
|
|
144721
|
+
function isLightRgb({ r, g, b }) {
|
|
144722
|
+
return 0.299 * r + 0.587 * g + 0.114 * b > 128;
|
|
144723
|
+
}
|
|
144724
|
+
function blendRgb(fg, bg, alpha) {
|
|
144725
|
+
return {
|
|
144726
|
+
r: Math.floor(fg.r * alpha + bg.r * (1 - alpha)),
|
|
144727
|
+
g: Math.floor(fg.g * alpha + bg.g * (1 - alpha)),
|
|
144728
|
+
b: Math.floor(fg.b * alpha + bg.b * (1 - alpha))
|
|
144729
|
+
};
|
|
144730
|
+
}
|
|
144731
|
+
function getCodexUserMessageBackground() {
|
|
144732
|
+
const theme = getTerminalTheme();
|
|
144733
|
+
const terminalBg = getTerminalBackgroundColor() ?? (theme === "light" ? { r: 255, g: 255, b: 255 } : { r: 0, g: 0, b: 0 });
|
|
144734
|
+
const overlay = isLightRgb(terminalBg) ? { color: { r: 0, g: 0, b: 0 }, alpha: 0.04 } : { color: { r: 255, g: 255, b: 255 }, alpha: 0.12 };
|
|
144735
|
+
return rgbToHex(blendRgb(overlay.color, terminalBg, overlay.alpha));
|
|
144736
|
+
}
|
|
143966
144737
|
function hexToBgAnsi(hex3) {
|
|
143967
144738
|
const { r, g, b } = parseHex(hex3);
|
|
143968
144739
|
return `\x1B[48;2;${r};${g};${b}m`;
|
|
@@ -144135,9 +144906,8 @@ var init_colors = __esm(() => {
|
|
|
144135
144906
|
return getTerminalTheme() === "light" ? _colors.shellSyntaxLight : _colors.shellSyntaxDark;
|
|
144136
144907
|
},
|
|
144137
144908
|
get userMessage() {
|
|
144138
|
-
const theme = getTerminalTheme();
|
|
144139
144909
|
return {
|
|
144140
|
-
background:
|
|
144910
|
+
background: getCodexUserMessageBackground(),
|
|
144141
144911
|
text: undefined
|
|
144142
144912
|
};
|
|
144143
144913
|
}
|
|
@@ -145758,6 +146528,8 @@ function toTildePath(absolutePath) {
|
|
|
145758
146528
|
return absolutePath;
|
|
145759
146529
|
}
|
|
145760
146530
|
function getInitialAuthMethod() {
|
|
146531
|
+
if (isLocalBackendEnabled())
|
|
146532
|
+
return "local";
|
|
145761
146533
|
if (process.env.LETTA_BASE_URL)
|
|
145762
146534
|
return "url";
|
|
145763
146535
|
if (process.env.LETTA_API_KEY)
|
|
@@ -145765,6 +146537,8 @@ function getInitialAuthMethod() {
|
|
|
145765
146537
|
return null;
|
|
145766
146538
|
}
|
|
145767
146539
|
async function getAuthMethod() {
|
|
146540
|
+
if (isLocalBackendEnabled())
|
|
146541
|
+
return "local";
|
|
145768
146542
|
if (process.env.LETTA_BASE_URL) {
|
|
145769
146543
|
return "url";
|
|
145770
146544
|
}
|
|
@@ -145800,7 +146574,7 @@ function WelcomeScreen({
|
|
|
145800
146574
|
getAuthMethod().then(setAuthMethod);
|
|
145801
146575
|
}
|
|
145802
146576
|
}, [initialAuth]);
|
|
145803
|
-
const authDisplay = authMethod === "url" ? process.env.LETTA_BASE_URL || "Custom URL" : authMethod === "api-key" ? "API key auth" : "OAuth";
|
|
146577
|
+
const authDisplay = authMethod === "local" ? "Local" : authMethod === "url" ? process.env.LETTA_BASE_URL || "Custom URL" : authMethod === "api-key" ? "API key auth" : "OAuth";
|
|
145804
146578
|
const memfsEnabled = agentState?.id ? settingsManager.isMemfsEnabled(agentState.id) : true;
|
|
145805
146579
|
return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
|
|
145806
146580
|
flexDirection: "row",
|
|
@@ -145870,6 +146644,7 @@ function getLoadingMessage(loadingState, continueSession) {
|
|
|
145870
146644
|
var import_react25, jsx_dev_runtime6;
|
|
145871
146645
|
var init_WelcomeScreen = __esm(async () => {
|
|
145872
146646
|
init_model();
|
|
146647
|
+
init_backend2();
|
|
145873
146648
|
init_settings_manager();
|
|
145874
146649
|
init_version();
|
|
145875
146650
|
init_useTerminalWidth();
|
|
@@ -146686,7 +147461,7 @@ var init_accountConfig3 = __esm(() => {
|
|
|
146686
147461
|
});
|
|
146687
147462
|
|
|
146688
147463
|
// src/channels/accountConfig.ts
|
|
146689
|
-
function
|
|
147464
|
+
function isRecord11(value) {
|
|
146690
147465
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
146691
147466
|
}
|
|
146692
147467
|
function getChannelAccountConfigAdapter(channelId) {
|
|
@@ -146697,7 +147472,7 @@ function getChannelPluginConfig(input, key = "config") {
|
|
|
146697
147472
|
if (value === undefined) {
|
|
146698
147473
|
return {};
|
|
146699
147474
|
}
|
|
146700
|
-
return
|
|
147475
|
+
return isRecord11(value) ? value : null;
|
|
146701
147476
|
}
|
|
146702
147477
|
function isValidChannelPluginConfigPayload(channelId, input, key = "config") {
|
|
146703
147478
|
const config2 = getChannelPluginConfig(input, key);
|
|
@@ -152028,6 +152803,15 @@ function shouldRetryRunMetadataError(errorType, detail) {
|
|
|
152028
152803
|
return true;
|
|
152029
152804
|
return retryable429Detail || retryableDetail;
|
|
152030
152805
|
}
|
|
152806
|
+
function normalizeStreamErrorTypeToStopReason(errorType) {
|
|
152807
|
+
if (errorType === "llm_error" || errorType === "llm_api_error") {
|
|
152808
|
+
return "llm_api_error";
|
|
152809
|
+
}
|
|
152810
|
+
if (errorType === "internal_error" || errorType === "stream_incomplete") {
|
|
152811
|
+
return "error";
|
|
152812
|
+
}
|
|
152813
|
+
return "error";
|
|
152814
|
+
}
|
|
152031
152815
|
function isEmptyResponseRetryable(errorType, detail, emptyResponseRetries, maxEmptyResponseRetries) {
|
|
152032
152816
|
if (emptyResponseRetries >= maxEmptyResponseRetries)
|
|
152033
152817
|
return false;
|
|
@@ -152894,6 +153678,13 @@ var init_approval_result_normalization = __esm(() => {
|
|
|
152894
153678
|
});
|
|
152895
153679
|
|
|
152896
153680
|
// src/agent/clientSkills.ts
|
|
153681
|
+
var exports_clientSkills = {};
|
|
153682
|
+
__export(exports_clientSkills, {
|
|
153683
|
+
invalidateClientSkillsPayloadCacheForAgent: () => invalidateClientSkillsPayloadCacheForAgent,
|
|
153684
|
+
invalidateClientSkillsPayloadCache: () => invalidateClientSkillsPayloadCache,
|
|
153685
|
+
discoverClientSideSkills: () => discoverClientSideSkills,
|
|
153686
|
+
buildClientSkillsPayload: () => buildClientSkillsPayload
|
|
153687
|
+
});
|
|
152897
153688
|
import { existsSync as existsSync32, readdirSync as readdirSync11, realpathSync as realpathSync3, statSync as statSync8 } from "node:fs";
|
|
152898
153689
|
import { join as join34 } from "node:path";
|
|
152899
153690
|
function getCache2() {
|
|
@@ -152988,6 +153779,17 @@ function cloneResult(result) {
|
|
|
152988
153779
|
errors: result.errors.map((e) => ({ ...e }))
|
|
152989
153780
|
};
|
|
152990
153781
|
}
|
|
153782
|
+
function invalidateClientSkillsPayloadCache() {
|
|
153783
|
+
getCache2().clear();
|
|
153784
|
+
}
|
|
153785
|
+
function invalidateClientSkillsPayloadCacheForAgent(agentId) {
|
|
153786
|
+
const cache5 = getCache2();
|
|
153787
|
+
for (const [k, entry] of cache5) {
|
|
153788
|
+
if (entry.key.startsWith(`${agentId}|`) || k.startsWith(`${agentId}|`)) {
|
|
153789
|
+
cache5.delete(k);
|
|
153790
|
+
}
|
|
153791
|
+
}
|
|
153792
|
+
}
|
|
152991
153793
|
function getMemorySkillsDirs2(agentId) {
|
|
152992
153794
|
const dirs = new Set;
|
|
152993
153795
|
const scopedMemoryDir = resolveScopedMemoryDir({ agentId });
|
|
@@ -153043,56 +153845,28 @@ function resolveSkillDiscoveryContext(options) {
|
|
|
153043
153845
|
function getPrimaryProjectSkillsDirectory() {
|
|
153044
153846
|
return join34(process.cwd(), ".agents", "skills");
|
|
153045
153847
|
}
|
|
153046
|
-
async function
|
|
153047
|
-
const { legacySkillsDirectory, skillSources } = resolveSkillDiscoveryContext(options);
|
|
153848
|
+
async function collectClientSideSkills(options) {
|
|
153048
153849
|
const discoverSkillsFn = options.discoverSkillsFn ?? discoverSkills;
|
|
153049
|
-
const useCache = !options.discoverSkillsFn;
|
|
153050
|
-
const cwd2 = process.cwd();
|
|
153051
|
-
const primaryProjectSkillsDirectory = getPrimaryProjectSkillsDirectory();
|
|
153052
|
-
const memorySkillsDirs = getMemorySkillsDirs2(options.agentId);
|
|
153053
|
-
const cacheComponents = {
|
|
153054
|
-
agentId: options.agentId,
|
|
153055
|
-
skillSources,
|
|
153056
|
-
cwd: cwd2,
|
|
153057
|
-
legacySkillsDirectory,
|
|
153058
|
-
primaryProjectSkillsDirectory,
|
|
153059
|
-
memorySkillsDirs,
|
|
153060
|
-
skillRootRevisions: getSkillRootRevisions({
|
|
153061
|
-
agentId: options.agentId,
|
|
153062
|
-
skillSources,
|
|
153063
|
-
legacySkillsDirectory,
|
|
153064
|
-
primaryProjectSkillsDirectory,
|
|
153065
|
-
memorySkillsDirs
|
|
153066
|
-
})
|
|
153067
|
-
};
|
|
153068
|
-
const cacheKey = computeCacheKey(cacheComponents);
|
|
153069
|
-
if (useCache) {
|
|
153070
|
-
const cache5 = getCache2();
|
|
153071
|
-
const cached2 = cache5.get(cacheKey);
|
|
153072
|
-
if (cached2) {
|
|
153073
|
-
return cloneResult(cached2.result);
|
|
153074
|
-
}
|
|
153075
|
-
}
|
|
153076
153850
|
const skillsById = new Map;
|
|
153077
153851
|
const errors4 = [];
|
|
153078
|
-
const nonProjectSources = skillSources
|
|
153852
|
+
const nonProjectSources = options.skillSources?.filter((source) => source !== "project") ?? [];
|
|
153079
153853
|
const discoveryRuns = [];
|
|
153080
153854
|
if (nonProjectSources.length > 0) {
|
|
153081
153855
|
discoveryRuns.push({
|
|
153082
|
-
path: primaryProjectSkillsDirectory,
|
|
153856
|
+
path: options.primaryProjectSkillsDirectory,
|
|
153083
153857
|
sources: nonProjectSources
|
|
153084
153858
|
});
|
|
153085
153859
|
}
|
|
153086
|
-
const includeProjectSource = skillSources
|
|
153087
|
-
if (includeProjectSource && legacySkillsDirectory !== primaryProjectSkillsDirectory) {
|
|
153860
|
+
const includeProjectSource = options.skillSources?.includes("project") ?? false;
|
|
153861
|
+
if (includeProjectSource && options.legacySkillsDirectory !== options.primaryProjectSkillsDirectory) {
|
|
153088
153862
|
discoveryRuns.push({
|
|
153089
|
-
path: legacySkillsDirectory,
|
|
153863
|
+
path: options.legacySkillsDirectory,
|
|
153090
153864
|
sources: ["project"]
|
|
153091
153865
|
});
|
|
153092
153866
|
}
|
|
153093
153867
|
if (includeProjectSource) {
|
|
153094
153868
|
discoveryRuns.push({
|
|
153095
|
-
path: primaryProjectSkillsDirectory,
|
|
153869
|
+
path: options.primaryProjectSkillsDirectory,
|
|
153096
153870
|
sources: ["project"]
|
|
153097
153871
|
});
|
|
153098
153872
|
}
|
|
@@ -153110,7 +153884,7 @@ async function buildClientSkillsPayload(options = {}) {
|
|
|
153110
153884
|
errors4.push({ path: run.path, message });
|
|
153111
153885
|
}
|
|
153112
153886
|
}
|
|
153113
|
-
if (skillSources
|
|
153887
|
+
if ((options.skillSources?.length ?? 0) > 0) {
|
|
153114
153888
|
const memoryDiscovery = await discoverMemorySkills(options.agentId);
|
|
153115
153889
|
errors4.push(...memoryDiscovery.errors);
|
|
153116
153890
|
for (const skill2 of memoryDiscovery.skills) {
|
|
@@ -153121,7 +153895,59 @@ async function buildClientSkillsPayload(options = {}) {
|
|
|
153121
153895
|
skillsById.set(skill2.id, skill2);
|
|
153122
153896
|
}
|
|
153123
153897
|
}
|
|
153124
|
-
|
|
153898
|
+
return {
|
|
153899
|
+
skills: [...skillsById.values()].sort(compareSkills),
|
|
153900
|
+
errors: errors4
|
|
153901
|
+
};
|
|
153902
|
+
}
|
|
153903
|
+
async function discoverClientSideSkills(options = {}) {
|
|
153904
|
+
const { legacySkillsDirectory, skillSources } = resolveSkillDiscoveryContext(options);
|
|
153905
|
+
return collectClientSideSkills({
|
|
153906
|
+
...options,
|
|
153907
|
+
legacySkillsDirectory,
|
|
153908
|
+
skillSources,
|
|
153909
|
+
primaryProjectSkillsDirectory: getPrimaryProjectSkillsDirectory()
|
|
153910
|
+
});
|
|
153911
|
+
}
|
|
153912
|
+
async function buildClientSkillsPayload(options = {}) {
|
|
153913
|
+
const { legacySkillsDirectory, skillSources } = resolveSkillDiscoveryContext(options);
|
|
153914
|
+
const discoverSkillsFn = options.discoverSkillsFn ?? discoverSkills;
|
|
153915
|
+
const useCache = !options.discoverSkillsFn;
|
|
153916
|
+
const cwd2 = process.cwd();
|
|
153917
|
+
const primaryProjectSkillsDirectory = getPrimaryProjectSkillsDirectory();
|
|
153918
|
+
const memorySkillsDirs = getMemorySkillsDirs2(options.agentId);
|
|
153919
|
+
const cacheComponents = {
|
|
153920
|
+
agentId: options.agentId,
|
|
153921
|
+
skillSources,
|
|
153922
|
+
cwd: cwd2,
|
|
153923
|
+
legacySkillsDirectory,
|
|
153924
|
+
primaryProjectSkillsDirectory,
|
|
153925
|
+
memorySkillsDirs,
|
|
153926
|
+
skillRootRevisions: getSkillRootRevisions({
|
|
153927
|
+
agentId: options.agentId,
|
|
153928
|
+
skillSources,
|
|
153929
|
+
legacySkillsDirectory,
|
|
153930
|
+
primaryProjectSkillsDirectory,
|
|
153931
|
+
memorySkillsDirs
|
|
153932
|
+
})
|
|
153933
|
+
};
|
|
153934
|
+
const cacheKey = computeCacheKey(cacheComponents);
|
|
153935
|
+
if (useCache) {
|
|
153936
|
+
const cache5 = getCache2();
|
|
153937
|
+
const cached2 = cache5.get(cacheKey);
|
|
153938
|
+
if (cached2) {
|
|
153939
|
+
return cloneResult(cached2.result);
|
|
153940
|
+
}
|
|
153941
|
+
}
|
|
153942
|
+
const discovery = await collectClientSideSkills({
|
|
153943
|
+
...options,
|
|
153944
|
+
legacySkillsDirectory,
|
|
153945
|
+
skillSources,
|
|
153946
|
+
primaryProjectSkillsDirectory,
|
|
153947
|
+
discoverSkillsFn
|
|
153948
|
+
});
|
|
153949
|
+
const errors4 = discovery.errors;
|
|
153950
|
+
const sortedSkills = discovery.skills.filter(isModelInvocableSkill);
|
|
153125
153951
|
if (errors4.length > 0) {
|
|
153126
153952
|
const summarizedErrors = errors4.map((error51) => `${error51.path}: ${error51.message}`);
|
|
153127
153953
|
options.logger?.(`Failed to build some client_skills entries: ${summarizedErrors.join("; ")}`);
|
|
@@ -154008,7 +154834,7 @@ function markIncompleteToolsAsCancelled(b, setInterruptedFlag = true, reason = "
|
|
|
154008
154834
|
}
|
|
154009
154835
|
return anyToolsCancelled;
|
|
154010
154836
|
}
|
|
154011
|
-
function
|
|
154837
|
+
function isRecord12(v) {
|
|
154012
154838
|
return v !== null && typeof v === "object";
|
|
154013
154839
|
}
|
|
154014
154840
|
function getStringProp(obj, key) {
|
|
@@ -154019,9 +154845,9 @@ function extractTextPart(v) {
|
|
|
154019
154845
|
if (typeof v === "string")
|
|
154020
154846
|
return v;
|
|
154021
154847
|
if (Array.isArray(v)) {
|
|
154022
|
-
return v.map((p) =>
|
|
154848
|
+
return v.map((p) => isRecord12(p) ? getStringProp(p, "text") ?? "" : "").join("");
|
|
154023
154849
|
}
|
|
154024
|
-
if (
|
|
154850
|
+
if (isRecord12(v)) {
|
|
154025
154851
|
return getStringProp(v, "text") ?? getStringProp(v, "delta") ?? "";
|
|
154026
154852
|
}
|
|
154027
154853
|
return "";
|
|
@@ -155941,13 +156767,13 @@ function buildAgentInfo(options) {
|
|
|
155941
156767
|
}
|
|
155942
156768
|
const showMemoryDir = (() => {
|
|
155943
156769
|
try {
|
|
155944
|
-
return settingsManager.isMemfsEnabled(agentInfo.id);
|
|
156770
|
+
return isLocalBackendEnvEnabled() || settingsManager.isMemfsEnabled(agentInfo.id);
|
|
155945
156771
|
} catch {
|
|
155946
156772
|
return false;
|
|
155947
156773
|
}
|
|
155948
156774
|
})();
|
|
155949
156775
|
const memoryDirLine = showMemoryDir ? `
|
|
155950
|
-
- **Memory directory (also stored in \`MEMORY_DIR\` env var)**: \`${
|
|
156776
|
+
- **Memory directory (also stored in \`MEMORY_DIR\` env var)**: \`${getScopedMemoryFilesystemRoot(agentInfo.id)}\`` : "";
|
|
155951
156777
|
const convLine = conversationId ? `
|
|
155952
156778
|
- **Conversation ID (also stored in \`CONVERSATION_ID\` env var)**: ${conversationId}` : "";
|
|
155953
156779
|
return `${SYSTEM_REMINDER_OPEN} This is an automated message providing information about you.
|
|
@@ -155962,6 +156788,7 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
155962
156788
|
}
|
|
155963
156789
|
var init_agentInfo = __esm(() => {
|
|
155964
156790
|
init_memoryFilesystem();
|
|
156791
|
+
init_paths();
|
|
155965
156792
|
init_constants();
|
|
155966
156793
|
init_settings_manager();
|
|
155967
156794
|
});
|
|
@@ -158144,6 +158971,9 @@ function getApprovalToolCallDesyncErrorText(errorInfo) {
|
|
|
158144
158971
|
}
|
|
158145
158972
|
return null;
|
|
158146
158973
|
}
|
|
158974
|
+
function isBackendNotFoundError(error51) {
|
|
158975
|
+
return error51 instanceof APIError2 && (error51.status === 404 || error51.status === 422) || error51 instanceof Error && error51.name === "LocalBackendNotFoundError";
|
|
158976
|
+
}
|
|
158147
158977
|
function shouldAttemptPostStopApprovalRecovery(params) {
|
|
158148
158978
|
const approvalDesyncDetected = isApprovalToolCallDesyncError(params.runErrorDetail) || isApprovalToolCallDesyncError(params.latestErrorText) || isApprovalToolCallDesyncError(params.fallbackError);
|
|
158149
158979
|
return shouldAttemptApprovalRecovery({
|
|
@@ -158201,7 +159031,7 @@ async function drainRecoveryStreamWithEmission(recoveryStream, socket, runtime,
|
|
|
158201
159031
|
if (errorInfo) {
|
|
158202
159032
|
emitLoopErrorNotice(socket, runtime, {
|
|
158203
159033
|
message: errorInfo.message || "Stream error",
|
|
158204
|
-
stopReason: errorInfo.error_type
|
|
159034
|
+
stopReason: normalizeStreamErrorTypeToStopReason(errorInfo.error_type),
|
|
158205
159035
|
isTerminal: false,
|
|
158206
159036
|
runId: runtime.activeRunId || errorInfo.run_id,
|
|
158207
159037
|
agentId: params.agentId ?? undefined,
|
|
@@ -158275,12 +159105,12 @@ async function debugLogApprovalResumeState(runtime, params) {
|
|
|
158275
159105
|
return;
|
|
158276
159106
|
}
|
|
158277
159107
|
try {
|
|
158278
|
-
const
|
|
158279
|
-
const agent = await
|
|
159108
|
+
const backend4 = getBackend();
|
|
159109
|
+
const agent = await backend4.retrieveAgent(params.agentId);
|
|
158280
159110
|
const isExplicitConversation = params.conversationId.length > 0 && params.conversationId !== "default";
|
|
158281
|
-
const lastInContextId = isExplicitConversation ? (await
|
|
158282
|
-
const lastInContextMessages = lastInContextId ? await
|
|
158283
|
-
const resumeData = await
|
|
159111
|
+
const lastInContextId = isExplicitConversation ? (await backend4.retrieveConversation(params.conversationId)).in_context_message_ids?.at(-1) ?? null : agent.message_ids?.at(-1) ?? null;
|
|
159112
|
+
const lastInContextMessages = lastInContextId ? await backend4.retrieveMessage(lastInContextId) : [];
|
|
159113
|
+
const resumeData = await getResumeDataFromBackend2(agent, params.conversationId, {
|
|
158284
159114
|
includeMessageHistory: false
|
|
158285
159115
|
});
|
|
158286
159116
|
console.log("[Listen][DEBUG] Post-approval continuation resume snapshot", JSON.stringify({
|
|
@@ -158323,12 +159153,12 @@ async function recoverApprovalStateForSync(runtime, scope) {
|
|
|
158323
159153
|
clearRecoveredApprovalState(runtime);
|
|
158324
159154
|
return;
|
|
158325
159155
|
}
|
|
158326
|
-
const
|
|
159156
|
+
const backend4 = getBackend();
|
|
158327
159157
|
let agent;
|
|
158328
159158
|
try {
|
|
158329
|
-
agent = await
|
|
159159
|
+
agent = await backend4.retrieveAgent(scope.agent_id);
|
|
158330
159160
|
} catch (error51) {
|
|
158331
|
-
if (
|
|
159161
|
+
if (isBackendNotFoundError(error51)) {
|
|
158332
159162
|
clearRecoveredApprovalState(runtime);
|
|
158333
159163
|
return;
|
|
158334
159164
|
}
|
|
@@ -158336,11 +159166,11 @@ async function recoverApprovalStateForSync(runtime, scope) {
|
|
|
158336
159166
|
}
|
|
158337
159167
|
let resumeData;
|
|
158338
159168
|
try {
|
|
158339
|
-
resumeData = await
|
|
159169
|
+
resumeData = await getResumeDataFromBackend2(agent, scope.conversation_id, {
|
|
158340
159170
|
includeMessageHistory: false
|
|
158341
159171
|
});
|
|
158342
159172
|
} catch (error51) {
|
|
158343
|
-
if (
|
|
159173
|
+
if (isBackendNotFoundError(error51)) {
|
|
158344
159174
|
clearRecoveredApprovalState(runtime);
|
|
158345
159175
|
return;
|
|
158346
159176
|
}
|
|
@@ -158496,7 +159326,8 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
158496
159326
|
parentScope: recovered.agentId && recovered.conversationId ? {
|
|
158497
159327
|
agentId: recovered.agentId,
|
|
158498
159328
|
conversationId: recovered.conversationId
|
|
158499
|
-
} : undefined
|
|
159329
|
+
} : undefined,
|
|
159330
|
+
channelTurnSources: runtime.activeChannelTurnSources ?? undefined
|
|
158500
159331
|
});
|
|
158501
159332
|
} finally {
|
|
158502
159333
|
emitToolExecutionOutput.flush();
|
|
@@ -158554,7 +159385,6 @@ var init_recovery = __esm(async () => {
|
|
|
158554
159385
|
init_check_approval();
|
|
158555
159386
|
init_turn_recovery_policy();
|
|
158556
159387
|
init_backend2();
|
|
158557
|
-
init_client2();
|
|
158558
159388
|
init_formatDenial();
|
|
158559
159389
|
init_interactivePolicy();
|
|
158560
159390
|
init_constants2();
|
|
@@ -158606,16 +159436,19 @@ function markAwaitingAcceptedApprovalContinuationRunId(runtime, input) {
|
|
|
158606
159436
|
runtime.activeRunId = null;
|
|
158607
159437
|
}
|
|
158608
159438
|
}
|
|
159439
|
+
function isBackendNotFoundError2(err) {
|
|
159440
|
+
return err instanceof APIError2 && (err.status === 404 || err.status === 422) || err instanceof Error && err.name === "LocalBackendNotFoundError";
|
|
159441
|
+
}
|
|
158609
159442
|
async function resolveStaleApprovals(runtime, socket, abortSignal, deps = {}) {
|
|
158610
159443
|
if (!runtime.agentId)
|
|
158611
159444
|
return null;
|
|
158612
|
-
const getResumeDataImpl = deps.getResumeData ??
|
|
158613
|
-
const
|
|
159445
|
+
const getResumeDataImpl = deps.getResumeData ?? getResumeDataFromBackend2;
|
|
159446
|
+
const backend4 = getBackend();
|
|
158614
159447
|
let agent;
|
|
158615
159448
|
try {
|
|
158616
|
-
agent = await
|
|
159449
|
+
agent = await backend4.retrieveAgent(runtime.agentId);
|
|
158617
159450
|
} catch (err) {
|
|
158618
|
-
if (
|
|
159451
|
+
if (isBackendNotFoundError2(err)) {
|
|
158619
159452
|
return null;
|
|
158620
159453
|
}
|
|
158621
159454
|
throw err;
|
|
@@ -158623,11 +159456,11 @@ async function resolveStaleApprovals(runtime, socket, abortSignal, deps = {}) {
|
|
|
158623
159456
|
const requestedConversationId = runtime.conversationId !== "default" ? runtime.conversationId : undefined;
|
|
158624
159457
|
let resumeData;
|
|
158625
159458
|
try {
|
|
158626
|
-
resumeData = await getResumeDataImpl(
|
|
159459
|
+
resumeData = await getResumeDataImpl(agent, requestedConversationId, {
|
|
158627
159460
|
includeMessageHistory: false
|
|
158628
159461
|
});
|
|
158629
159462
|
} catch (err) {
|
|
158630
|
-
if (
|
|
159463
|
+
if (isBackendNotFoundError2(err)) {
|
|
158631
159464
|
return null;
|
|
158632
159465
|
}
|
|
158633
159466
|
throw err;
|
|
@@ -158993,7 +159826,6 @@ var init_send = __esm(async () => {
|
|
|
158993
159826
|
init_check_approval();
|
|
158994
159827
|
init_turn_recovery_policy();
|
|
158995
159828
|
init_backend2();
|
|
158996
|
-
init_client2();
|
|
158997
159829
|
init_errorFormatter();
|
|
158998
159830
|
init_streamAbortRelay();
|
|
158999
159831
|
init_constants2();
|
|
@@ -160748,7 +161580,7 @@ function formatArgsDisplay(argsJson, toolName) {
|
|
|
160748
161580
|
try {
|
|
160749
161581
|
if (argsJson?.trim()) {
|
|
160750
161582
|
const p = JSON.parse(argsJson);
|
|
160751
|
-
if (
|
|
161583
|
+
if (isRecord13(p)) {
|
|
160752
161584
|
const clone2 = { ...p };
|
|
160753
161585
|
if ("request_heartbeat" in clone2)
|
|
160754
161586
|
delete clone2.request_heartbeat;
|
|
@@ -160869,7 +161701,7 @@ function formatArgsDisplay(argsJson, toolName) {
|
|
|
160869
161701
|
}
|
|
160870
161702
|
return { display, parsed, shellSemantic };
|
|
160871
161703
|
}
|
|
160872
|
-
var
|
|
161704
|
+
var isRecord13 = (v) => typeof v === "object" && v !== null;
|
|
160873
161705
|
var init_formatArgsDisplay = __esm(async () => {
|
|
160874
161706
|
init_shellSemanticDisplay();
|
|
160875
161707
|
await init_toolNameMapping();
|
|
@@ -161366,6 +162198,7 @@ async function handleApprovalStop(params) {
|
|
|
161366
162198
|
onStreamingOutput: emitToolExecutionOutput,
|
|
161367
162199
|
workingDirectory: turnWorkingDirectory,
|
|
161368
162200
|
parentScope: agentId && conversationId ? { agentId, conversationId } : undefined,
|
|
162201
|
+
channelTurnSources: runtime.activeChannelTurnSources ?? undefined,
|
|
161369
162202
|
onFileWrite
|
|
161370
162203
|
});
|
|
161371
162204
|
} finally {
|
|
@@ -161491,9 +162324,8 @@ var init_turn_approval = __esm(async () => {
|
|
|
161491
162324
|
|
|
161492
162325
|
// src/websocket/listener/memfs-sync.ts
|
|
161493
162326
|
async function syncMemfsForAgent(agentId) {
|
|
161494
|
-
const {
|
|
161495
|
-
const
|
|
161496
|
-
const agent = await client.agents.retrieve(agentId);
|
|
162327
|
+
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
162328
|
+
const agent = await getBackend2().retrieveAgent(agentId);
|
|
161497
162329
|
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
161498
162330
|
if (!agent.tags?.includes(GIT_MEMORY_ENABLED_TAG2)) {
|
|
161499
162331
|
debugLog("memfs-sync", `Agent ${agentId} does not have memfs tag, skipping`);
|
|
@@ -161530,8 +162362,7 @@ function getAgentMetadataPromise(listener, agentId) {
|
|
|
161530
162362
|
return listener.agentMetadataByAgent.get(agentId) ?? null;
|
|
161531
162363
|
}
|
|
161532
162364
|
async function fetchListenerAgentMetadata(agentId) {
|
|
161533
|
-
const
|
|
161534
|
-
const agent = await client.agents.retrieve(agentId);
|
|
162365
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
161535
162366
|
return {
|
|
161536
162367
|
name: agent.name ?? null,
|
|
161537
162368
|
description: agent.description ?? null,
|
|
@@ -161584,7 +162415,7 @@ function clearListenerWarmState(listener) {
|
|
|
161584
162415
|
}
|
|
161585
162416
|
var defaultWarmupDeps, warmupDeps;
|
|
161586
162417
|
var init_warmup = __esm(() => {
|
|
161587
|
-
|
|
162418
|
+
init_backend2();
|
|
161588
162419
|
init_debug();
|
|
161589
162420
|
init_memfs_sync();
|
|
161590
162421
|
init_secrets_sync();
|
|
@@ -161641,8 +162472,7 @@ function buildMaybeLaunchReflectionSubagent(params) {
|
|
|
161641
162472
|
let systemPrompt = cachedAgent?.system ?? undefined;
|
|
161642
162473
|
if (!systemPrompt) {
|
|
161643
162474
|
try {
|
|
161644
|
-
const
|
|
161645
|
-
const agent = await client.agents.retrieve(agentId);
|
|
162475
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
161646
162476
|
systemPrompt = agent.system ?? undefined;
|
|
161647
162477
|
} catch {
|
|
161648
162478
|
debugLog("memory", "Failed to fetch agent system prompt for reflection payload");
|
|
@@ -161819,8 +162649,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
161819
162649
|
syncReminderStateFromContextTracker(runtime.reminderState, runtime.contextTracker);
|
|
161820
162650
|
if (agentId) {
|
|
161821
162651
|
try {
|
|
161822
|
-
|
|
161823
|
-
cachedAgent = await client.agents.retrieve(agentId);
|
|
162652
|
+
cachedAgent = await getBackend().retrieveAgent(agentId);
|
|
161824
162653
|
} catch {}
|
|
161825
162654
|
}
|
|
161826
162655
|
if (!runtime.reminderState.hasSentAgentInfo && cachedAgent) {
|
|
@@ -161943,7 +162772,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
161943
162772
|
if (!recoverableApprovalErrorText) {
|
|
161944
162773
|
emitLoopErrorNotice(socket, runtime, {
|
|
161945
162774
|
message: errorInfo.message || "Stream error",
|
|
161946
|
-
stopReason: errorInfo.error_type
|
|
162775
|
+
stopReason: normalizeStreamErrorTypeToStopReason(errorInfo.error_type),
|
|
161947
162776
|
isTerminal: false,
|
|
161948
162777
|
runId: runId || errorInfo.run_id,
|
|
161949
162778
|
agentId,
|
|
@@ -162034,9 +162863,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
162034
162863
|
conversationId
|
|
162035
162864
|
});
|
|
162036
162865
|
try {
|
|
162037
|
-
const
|
|
162038
|
-
const
|
|
162039
|
-
const { pendingApprovals: existingApprovals } = await getResumeData(client, agent, requestedConversationId);
|
|
162866
|
+
const agent = await getBackend().retrieveAgent(agentId || "");
|
|
162867
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, requestedConversationId);
|
|
162040
162868
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
|
|
162041
162869
|
} catch {
|
|
162042
162870
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -162320,7 +163148,7 @@ var init_turn = __esm(async () => {
|
|
|
162320
163148
|
init_context();
|
|
162321
163149
|
init_memoryFilesystem();
|
|
162322
163150
|
init_turn_recovery_policy();
|
|
162323
|
-
|
|
163151
|
+
init_backend2();
|
|
162324
163152
|
init_errorFormatter();
|
|
162325
163153
|
init_memoryReminder();
|
|
162326
163154
|
init_memorySubagentCompletion();
|
|
@@ -162427,17 +163255,19 @@ function emitSlashCommandEnd(socket, runtime, scope, fields) {
|
|
|
162427
163255
|
emitCanonicalMessageDelta(socket, runtime, endDelta, scope);
|
|
162428
163256
|
}
|
|
162429
163257
|
async function handleClearCommand(_socket, conversationRuntime, opts) {
|
|
162430
|
-
const
|
|
163258
|
+
const backend4 = getBackend();
|
|
162431
163259
|
const agentId = conversationRuntime.agentId;
|
|
162432
163260
|
if (!agentId) {
|
|
162433
163261
|
throw new Error("No agent ID available for /clear command");
|
|
162434
163262
|
}
|
|
162435
|
-
if (conversationRuntime.conversationId === "default") {
|
|
163263
|
+
if (conversationRuntime.conversationId === "default" && !backend4.capabilities.localModelCatalog) {
|
|
163264
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
163265
|
+
const client = await getClient2();
|
|
162436
163266
|
await client.agents.messages.reset(agentId, {
|
|
162437
163267
|
add_default_initial_messages: false
|
|
162438
163268
|
});
|
|
162439
163269
|
}
|
|
162440
|
-
const conversation = await
|
|
163270
|
+
const conversation = await backend4.createConversation({
|
|
162441
163271
|
agent_id: agentId,
|
|
162442
163272
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
162443
163273
|
});
|
|
@@ -162635,7 +163465,7 @@ var init_commands = __esm(async () => {
|
|
|
162635
163465
|
init_memory();
|
|
162636
163466
|
init_memoryFilesystem();
|
|
162637
163467
|
init_promptAssets();
|
|
162638
|
-
|
|
163468
|
+
init_backend2();
|
|
162639
163469
|
init_initCommand();
|
|
162640
163470
|
init_constants();
|
|
162641
163471
|
init_settings_manager();
|
|
@@ -164018,6 +164848,16 @@ function isExecuteCommandCommand(value) {
|
|
|
164018
164848
|
const hasValidArgs = c.args === undefined || typeof c.args === "string";
|
|
164019
164849
|
return c.type === "execute_command" && typeof c.command_id === "string" && typeof c.request_id === "string" && isRuntimeScope(c.runtime) && hasValidArgs;
|
|
164020
164850
|
}
|
|
164851
|
+
function parseServerLifecycleMessage(data) {
|
|
164852
|
+
try {
|
|
164853
|
+
const raw = typeof data === "string" ? data : data.toString();
|
|
164854
|
+
const parsed = JSON.parse(raw);
|
|
164855
|
+
if (parsed && typeof parsed === "object" && parsed.type === "pong") {
|
|
164856
|
+
return { type: "pong" };
|
|
164857
|
+
}
|
|
164858
|
+
} catch {}
|
|
164859
|
+
return null;
|
|
164860
|
+
}
|
|
164021
164861
|
function parseServerMessage(data) {
|
|
164022
164862
|
try {
|
|
164023
164863
|
const raw = typeof data === "string" ? data : data.toString();
|
|
@@ -165513,11 +166353,12 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165513
166353
|
const buffer = encoding === "base64" ? Buffer.from(parsed.content, "base64") : Buffer.from(parsed.content, "utf-8");
|
|
165514
166354
|
await mkdir9(dirname20(absolutePath), { recursive: true });
|
|
165515
166355
|
await writeFile11(absolutePath, buffer);
|
|
166356
|
+
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
166357
|
+
const backend4 = getBackend2();
|
|
166358
|
+
const memorySyncMode = backend4.capabilities.localMemfs && !backend4.capabilities.remoteMemfs ? "local" : undefined;
|
|
165516
166359
|
let agentName = parsed.agent_id;
|
|
165517
166360
|
try {
|
|
165518
|
-
const
|
|
165519
|
-
const client = await getClient2();
|
|
165520
|
-
const agent = await client.agents.retrieve(parsed.agent_id);
|
|
166361
|
+
const agent = await backend4.retrieveAgent(parsed.agent_id);
|
|
165521
166362
|
if (agent.name && agent.name.trim().length > 0) {
|
|
165522
166363
|
agentName = agent.name.trim();
|
|
165523
166364
|
}
|
|
@@ -165533,6 +166374,7 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165533
166374
|
authorName: agentName,
|
|
165534
166375
|
authorEmail: `${parsed.agent_id}@letta.com`
|
|
165535
166376
|
},
|
|
166377
|
+
...memorySyncMode ? { syncMode: memorySyncMode } : {},
|
|
165536
166378
|
replay: async () => {
|
|
165537
166379
|
await mkdir9(dirname20(absolutePath), { recursive: true });
|
|
165538
166380
|
await writeFile11(absolutePath, buffer);
|
|
@@ -165627,11 +166469,12 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165627
166469
|
}, "listener_delete_memory_file_send_failed", "listener_delete_memory_file");
|
|
165628
166470
|
return;
|
|
165629
166471
|
}
|
|
166472
|
+
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
166473
|
+
const backend4 = getBackend2();
|
|
166474
|
+
const memorySyncMode = backend4.capabilities.localMemfs && !backend4.capabilities.remoteMemfs ? "local" : undefined;
|
|
165630
166475
|
let agentName = parsed.agent_id;
|
|
165631
166476
|
try {
|
|
165632
|
-
const
|
|
165633
|
-
const client = await getClient2();
|
|
165634
|
-
const agent = await client.agents.retrieve(parsed.agent_id);
|
|
166477
|
+
const agent = await backend4.retrieveAgent(parsed.agent_id);
|
|
165635
166478
|
if (agent.name && agent.name.trim().length > 0) {
|
|
165636
166479
|
agentName = agent.name.trim();
|
|
165637
166480
|
}
|
|
@@ -165646,6 +166489,7 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165646
166489
|
authorName: agentName,
|
|
165647
166490
|
authorEmail: `${parsed.agent_id}@letta.com`
|
|
165648
166491
|
},
|
|
166492
|
+
...memorySyncMode ? { syncMode: memorySyncMode } : {},
|
|
165649
166493
|
replay: async () => {
|
|
165650
166494
|
await removeIfPresent();
|
|
165651
166495
|
return [pathspec];
|
|
@@ -168175,6 +169019,11 @@ function createListenerMessageHandler(params) {
|
|
|
168175
169019
|
const raw = data.toString();
|
|
168176
169020
|
let parsedScope = null;
|
|
168177
169021
|
try {
|
|
169022
|
+
const lifecycleMessage = parseServerLifecycleMessage(data);
|
|
169023
|
+
if (lifecycleMessage) {
|
|
169024
|
+
safeEmitWsEvent("recv", "lifecycle", lifecycleMessage);
|
|
169025
|
+
return;
|
|
169026
|
+
}
|
|
168178
169027
|
const parsed = parseServerMessage(data);
|
|
168179
169028
|
parsedScope = getParsedRuntimeScope(parsed);
|
|
168180
169029
|
if (parsed) {
|
|
@@ -169496,6 +170345,178 @@ var init_listen_client = __esm(async () => {
|
|
|
169496
170345
|
await init_client4();
|
|
169497
170346
|
});
|
|
169498
170347
|
|
|
170348
|
+
// src/backend/api/search.ts
|
|
170349
|
+
async function warmSearchCache(body) {
|
|
170350
|
+
return apiRequest("POST", "/v1/_internal_search/cache-warm", body);
|
|
170351
|
+
}
|
|
170352
|
+
async function searchMessages(body) {
|
|
170353
|
+
return apiRequest("POST", "/v1/messages/search", body);
|
|
170354
|
+
}
|
|
170355
|
+
var init_search = __esm(() => {
|
|
170356
|
+
init_request();
|
|
170357
|
+
});
|
|
170358
|
+
|
|
170359
|
+
// src/backend/messageSearch.ts
|
|
170360
|
+
function pageItems(page) {
|
|
170361
|
+
if (Array.isArray(page))
|
|
170362
|
+
return page;
|
|
170363
|
+
if (page && typeof page === "object") {
|
|
170364
|
+
const maybePage = page;
|
|
170365
|
+
if (typeof maybePage.getPaginatedItems === "function") {
|
|
170366
|
+
return maybePage.getPaginatedItems();
|
|
170367
|
+
}
|
|
170368
|
+
if (Array.isArray(maybePage.items)) {
|
|
170369
|
+
return maybePage.items;
|
|
170370
|
+
}
|
|
170371
|
+
}
|
|
170372
|
+
return [];
|
|
170373
|
+
}
|
|
170374
|
+
function textFromContent2(content) {
|
|
170375
|
+
if (typeof content === "string")
|
|
170376
|
+
return content;
|
|
170377
|
+
if (!Array.isArray(content))
|
|
170378
|
+
return "";
|
|
170379
|
+
return content.map((part) => {
|
|
170380
|
+
if (part && typeof part === "object" && "text" in part && typeof part.text === "string") {
|
|
170381
|
+
return part.text;
|
|
170382
|
+
}
|
|
170383
|
+
return "";
|
|
170384
|
+
}).filter(Boolean).join(`
|
|
170385
|
+
`);
|
|
170386
|
+
}
|
|
170387
|
+
function stringifySearchValue(value) {
|
|
170388
|
+
if (typeof value === "string")
|
|
170389
|
+
return value;
|
|
170390
|
+
if (value === null || value === undefined)
|
|
170391
|
+
return "";
|
|
170392
|
+
try {
|
|
170393
|
+
return JSON.stringify(value);
|
|
170394
|
+
} catch {
|
|
170395
|
+
return String(value);
|
|
170396
|
+
}
|
|
170397
|
+
}
|
|
170398
|
+
function searchableText(message) {
|
|
170399
|
+
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : message.tool_call ? [message.tool_call] : [];
|
|
170400
|
+
return [
|
|
170401
|
+
message.message_type,
|
|
170402
|
+
textFromContent2(message.content),
|
|
170403
|
+
message.reasoning,
|
|
170404
|
+
message.summary,
|
|
170405
|
+
...toolCalls.flatMap((call) => [call.name, call.arguments]),
|
|
170406
|
+
stringifySearchValue(message.tool_return),
|
|
170407
|
+
stringifySearchValue(message.func_response)
|
|
170408
|
+
].filter((part) => typeof part === "string" && part.length > 0).join(`
|
|
170409
|
+
`);
|
|
170410
|
+
}
|
|
170411
|
+
function matchesQuery(message, query) {
|
|
170412
|
+
const terms = query.toLowerCase().split(/\s+/).map((term) => term.trim()).filter(Boolean);
|
|
170413
|
+
if (terms.length === 0)
|
|
170414
|
+
return false;
|
|
170415
|
+
const haystack = searchableText(message).toLowerCase();
|
|
170416
|
+
return terms.every((term) => haystack.includes(term));
|
|
170417
|
+
}
|
|
170418
|
+
function withinDateRange(message, startDate, endDate) {
|
|
170419
|
+
if (!startDate && !endDate)
|
|
170420
|
+
return true;
|
|
170421
|
+
if (!message.date)
|
|
170422
|
+
return true;
|
|
170423
|
+
const time3 = new Date(message.date).getTime();
|
|
170424
|
+
if (Number.isNaN(time3))
|
|
170425
|
+
return true;
|
|
170426
|
+
const startTime = startDate ? new Date(startDate).getTime() : 0;
|
|
170427
|
+
const endTime = endDate ? new Date(endDate).getTime() : Number.POSITIVE_INFINITY;
|
|
170428
|
+
return time3 >= startTime && time3 <= endTime;
|
|
170429
|
+
}
|
|
170430
|
+
function toSearchResult(message) {
|
|
170431
|
+
const createdAt = message.date ?? new Date(0).toISOString();
|
|
170432
|
+
return {
|
|
170433
|
+
...message,
|
|
170434
|
+
message_id: message.id ?? `${message.agent_id ?? "local"}:${createdAt}`,
|
|
170435
|
+
created_at: createdAt,
|
|
170436
|
+
agent_id: message.agent_id ?? null,
|
|
170437
|
+
conversation_id: message.conversation_id ?? null
|
|
170438
|
+
};
|
|
170439
|
+
}
|
|
170440
|
+
async function localConversationMessages(backend4, conversationId, agentId) {
|
|
170441
|
+
try {
|
|
170442
|
+
const page = await backend4.listConversationMessages(conversationId, {
|
|
170443
|
+
limit: LOCAL_SEARCH_SCAN_LIMIT,
|
|
170444
|
+
order: "desc",
|
|
170445
|
+
...agentId ? { agent_id: agentId } : {}
|
|
170446
|
+
});
|
|
170447
|
+
return pageItems(page);
|
|
170448
|
+
} catch {
|
|
170449
|
+
return [];
|
|
170450
|
+
}
|
|
170451
|
+
}
|
|
170452
|
+
async function localAgentMessages(backend4, agentId) {
|
|
170453
|
+
const messages = [
|
|
170454
|
+
...await localConversationMessages(backend4, "default", agentId)
|
|
170455
|
+
];
|
|
170456
|
+
try {
|
|
170457
|
+
const conversationsPage = await backend4.listConversations({
|
|
170458
|
+
agent_id: agentId,
|
|
170459
|
+
limit: LOCAL_SEARCH_SCAN_LIMIT
|
|
170460
|
+
});
|
|
170461
|
+
const conversations = pageItems(conversationsPage);
|
|
170462
|
+
for (const conversation of conversations) {
|
|
170463
|
+
if (!conversation.id || conversation.id === "default")
|
|
170464
|
+
continue;
|
|
170465
|
+
messages.push(...await localConversationMessages(backend4, conversation.id, agentId));
|
|
170466
|
+
}
|
|
170467
|
+
} catch {}
|
|
170468
|
+
return messages;
|
|
170469
|
+
}
|
|
170470
|
+
async function localSearchMessages(backend4, body) {
|
|
170471
|
+
const query = typeof body.query === "string" ? body.query.trim() : "";
|
|
170472
|
+
if (!query)
|
|
170473
|
+
return [];
|
|
170474
|
+
const limit2 = typeof body.limit === "number" ? body.limit : 100;
|
|
170475
|
+
const agentId = typeof body.agent_id === "string" ? body.agent_id : undefined;
|
|
170476
|
+
const conversationId = typeof body.conversation_id === "string" ? body.conversation_id : undefined;
|
|
170477
|
+
const startDate = typeof body.start_date === "string" ? body.start_date : undefined;
|
|
170478
|
+
const endDate = typeof body.end_date === "string" ? body.end_date : undefined;
|
|
170479
|
+
let messages = [];
|
|
170480
|
+
if (conversationId) {
|
|
170481
|
+
messages = await localConversationMessages(backend4, conversationId, agentId);
|
|
170482
|
+
} else if (agentId) {
|
|
170483
|
+
messages = await localAgentMessages(backend4, agentId);
|
|
170484
|
+
} else {
|
|
170485
|
+
const agentsPage = await backend4.listAgents({
|
|
170486
|
+
limit: LOCAL_SEARCH_SCAN_LIMIT
|
|
170487
|
+
});
|
|
170488
|
+
const agents = pageItems(agentsPage);
|
|
170489
|
+
for (const agent of agents) {
|
|
170490
|
+
messages.push(...await localAgentMessages(backend4, agent.id));
|
|
170491
|
+
}
|
|
170492
|
+
}
|
|
170493
|
+
return messages.filter((message) => matchesQuery(message, query)).filter((message) => withinDateRange(message, startDate, endDate)).sort((a, b) => (b.date ?? "").localeCompare(a.date ?? "")).slice(0, limit2).map(toSearchResult);
|
|
170494
|
+
}
|
|
170495
|
+
async function searchMessagesForBackend(body, backend4 = getBackend()) {
|
|
170496
|
+
if (backend4.capabilities.localModelCatalog) {
|
|
170497
|
+
return await localSearchMessages(backend4, body);
|
|
170498
|
+
}
|
|
170499
|
+
return searchMessages({
|
|
170500
|
+
...body,
|
|
170501
|
+
search_mode: body.search_mode === "vector" || body.search_mode === "fts" || body.search_mode === "hybrid" ? body.search_mode : body.search_mode
|
|
170502
|
+
});
|
|
170503
|
+
}
|
|
170504
|
+
async function warmMessageSearchCacheForBackend(body, backend4 = getBackend()) {
|
|
170505
|
+
if (backend4.capabilities.localModelCatalog) {
|
|
170506
|
+
return {
|
|
170507
|
+
collection: body.collection ?? "messages",
|
|
170508
|
+
status: "local-backend-noop",
|
|
170509
|
+
warmed: false
|
|
170510
|
+
};
|
|
170511
|
+
}
|
|
170512
|
+
return warmSearchCache(body);
|
|
170513
|
+
}
|
|
170514
|
+
var LOCAL_SEARCH_SCAN_LIMIT = 1000;
|
|
170515
|
+
var init_messageSearch = __esm(() => {
|
|
170516
|
+
init_search();
|
|
170517
|
+
init_backend();
|
|
170518
|
+
});
|
|
170519
|
+
|
|
169499
170520
|
// src/utils/debug.ts
|
|
169500
170521
|
var exports_debug2 = {};
|
|
169501
170522
|
__export(exports_debug2, {
|
|
@@ -169637,6 +170658,12 @@ var init_version2 = __esm(() => {
|
|
|
169637
170658
|
// src/agent/skills.ts
|
|
169638
170659
|
var exports_skills2 = {};
|
|
169639
170660
|
__export(exports_skills2, {
|
|
170661
|
+
isUserInvocableSkill: () => isUserInvocableSkill2,
|
|
170662
|
+
isModelInvocableSkill: () => isModelInvocableSkill2,
|
|
170663
|
+
getLegacyAgentSkillsDir: () => getLegacyAgentSkillsDir2,
|
|
170664
|
+
getFrontmatterStringList: () => getFrontmatterStringList2,
|
|
170665
|
+
getFrontmatterString: () => getFrontmatterString2,
|
|
170666
|
+
getFrontmatterBoolean: () => getFrontmatterBoolean2,
|
|
169640
170667
|
getBundledSkills: () => getBundledSkills2,
|
|
169641
170668
|
getAgentSkillsDir: () => getAgentSkillsDir2,
|
|
169642
170669
|
formatSkillsAsSystemReminder: () => formatSkillsAsSystemReminder2,
|
|
@@ -169659,7 +170686,45 @@ function getBundledSkillsPath2() {
|
|
|
169659
170686
|
function compareSkills2(a, b) {
|
|
169660
170687
|
return a.id.localeCompare(b.id) || a.source.localeCompare(b.source) || a.path.localeCompare(b.path);
|
|
169661
170688
|
}
|
|
170689
|
+
function stripSurroundingQuotes2(value) {
|
|
170690
|
+
const trimmed = value.trim();
|
|
170691
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
170692
|
+
return trimmed.slice(1, -1);
|
|
170693
|
+
}
|
|
170694
|
+
return trimmed;
|
|
170695
|
+
}
|
|
170696
|
+
function getFrontmatterString2(frontmatter, key) {
|
|
170697
|
+
const value = frontmatter[key];
|
|
170698
|
+
return typeof value === "string" ? stripSurroundingQuotes2(value) : undefined;
|
|
170699
|
+
}
|
|
170700
|
+
function getFrontmatterStringList2(frontmatter, key) {
|
|
170701
|
+
const value = frontmatter[key];
|
|
170702
|
+
if (Array.isArray(value)) {
|
|
170703
|
+
return value.map(stripSurroundingQuotes2).filter((item) => item.length > 0);
|
|
170704
|
+
}
|
|
170705
|
+
if (typeof value === "string") {
|
|
170706
|
+
return stripSurroundingQuotes2(value).split(/\s+/).map((item) => item.trim()).filter((item) => item.length > 0);
|
|
170707
|
+
}
|
|
170708
|
+
return;
|
|
170709
|
+
}
|
|
170710
|
+
function getFrontmatterBoolean2(frontmatter, key) {
|
|
170711
|
+
const value = getFrontmatterString2(frontmatter, key)?.toLowerCase();
|
|
170712
|
+
if (value === "true")
|
|
170713
|
+
return true;
|
|
170714
|
+
if (value === "false")
|
|
170715
|
+
return false;
|
|
170716
|
+
return;
|
|
170717
|
+
}
|
|
170718
|
+
function isModelInvocableSkill2(skill2) {
|
|
170719
|
+
return skill2.disableModelInvocation !== true;
|
|
170720
|
+
}
|
|
170721
|
+
function isUserInvocableSkill2(skill2) {
|
|
170722
|
+
return skill2.userInvocable !== false;
|
|
170723
|
+
}
|
|
169662
170724
|
function getAgentSkillsDir2(agentId) {
|
|
170725
|
+
return join42(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
170726
|
+
}
|
|
170727
|
+
function getLegacyAgentSkillsDir2(agentId) {
|
|
169663
170728
|
return join42(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
|
|
169664
170729
|
}
|
|
169665
170730
|
async function getBundledSkills2() {
|
|
@@ -169702,6 +170767,12 @@ async function discoverSkills2(projectSkillsPath = join42(process.cwd(), SKILLS_
|
|
|
169702
170767
|
}
|
|
169703
170768
|
}
|
|
169704
170769
|
if (agentId && includeSource("agent")) {
|
|
170770
|
+
const legacyDir = getLegacyAgentSkillsDir2(agentId);
|
|
170771
|
+
const legacyResult = await discoverSkillsFromDir2(legacyDir, "agent");
|
|
170772
|
+
allErrors.push(...legacyResult.errors);
|
|
170773
|
+
for (const skill2 of legacyResult.skills) {
|
|
170774
|
+
skillsById.set(skill2.id, skill2);
|
|
170775
|
+
}
|
|
169705
170776
|
const agentSkillsDir = getAgentSkillsDir2(agentId);
|
|
169706
170777
|
const agentResult = await discoverSkillsFromDir2(agentSkillsDir, "agent");
|
|
169707
170778
|
allErrors.push(...agentResult.errors);
|
|
@@ -169785,7 +170856,7 @@ async function parseSkillFile2(filePath, rootPath, source) {
|
|
|
169785
170856
|
const defaultId = dirPath || "root";
|
|
169786
170857
|
const id = (typeof frontmatter.id === "string" ? frontmatter.id : null) || defaultId;
|
|
169787
170858
|
const name25 = (typeof frontmatter.name === "string" ? frontmatter.name : null) || (typeof frontmatter.title === "string" ? frontmatter.title : null) || (id.split("/").pop() ?? "").replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
|
|
169788
|
-
let description =
|
|
170859
|
+
let description = getFrontmatterString2(frontmatter, "description") ?? null;
|
|
169789
170860
|
if (!description) {
|
|
169790
170861
|
const firstParagraph = body.trim().split(`
|
|
169791
170862
|
|
|
@@ -169793,30 +170864,31 @@ async function parseSkillFile2(filePath, rootPath, source) {
|
|
|
169793
170864
|
description = firstParagraph || "No description available";
|
|
169794
170865
|
}
|
|
169795
170866
|
description = description.trim();
|
|
169796
|
-
|
|
169797
|
-
|
|
169798
|
-
|
|
169799
|
-
|
|
169800
|
-
|
|
169801
|
-
tags = frontmatter.tags;
|
|
169802
|
-
} else if (typeof frontmatter.tags === "string") {
|
|
169803
|
-
tags = [frontmatter.tags];
|
|
169804
|
-
}
|
|
170867
|
+
const whenToUse = getFrontmatterString2(frontmatter, "when_to_use")?.trim();
|
|
170868
|
+
const modelDescription = whenToUse ? `${description}
|
|
170869
|
+
|
|
170870
|
+
When to use: ${whenToUse}` : description;
|
|
170871
|
+
const tags = getFrontmatterStringList2(frontmatter, "tags");
|
|
169805
170872
|
return {
|
|
169806
170873
|
id,
|
|
169807
170874
|
name: name25,
|
|
169808
|
-
description,
|
|
169809
|
-
|
|
170875
|
+
description: modelDescription,
|
|
170876
|
+
whenToUse,
|
|
170877
|
+
argumentHint: getFrontmatterString2(frontmatter, "argument-hint"),
|
|
170878
|
+
arguments: getFrontmatterStringList2(frontmatter, "arguments"),
|
|
170879
|
+
disableModelInvocation: getFrontmatterBoolean2(frontmatter, "disable-model-invocation") ?? false,
|
|
170880
|
+
userInvocable: getFrontmatterBoolean2(frontmatter, "user-invocable") ?? true,
|
|
170881
|
+
category: getFrontmatterString2(frontmatter, "category"),
|
|
169810
170882
|
tags,
|
|
169811
170883
|
path: filePath,
|
|
169812
170884
|
source
|
|
169813
170885
|
};
|
|
169814
170886
|
}
|
|
169815
170887
|
function formatSkillsAsSystemReminder2(skills) {
|
|
169816
|
-
|
|
170888
|
+
const lines = skills.filter(isModelInvocableSkill2).sort(compareSkills2).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
170889
|
+
if (lines.length === 0) {
|
|
169817
170890
|
return "";
|
|
169818
170891
|
}
|
|
169819
|
-
const lines = [...skills].sort(compareSkills2).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
169820
170892
|
return `<system-reminder>
|
|
169821
170893
|
The following skills are available for use with the Skill tool:
|
|
169822
170894
|
|
|
@@ -169881,6 +170953,7 @@ __export(exports_terminalTheme, {
|
|
|
169881
170953
|
parseHexComponent: () => parseHexComponent,
|
|
169882
170954
|
initTerminalTheme: () => initTerminalTheme,
|
|
169883
170955
|
getTerminalTheme: () => getTerminalTheme2,
|
|
170956
|
+
getTerminalBackgroundColor: () => getTerminalBackgroundColor2,
|
|
169884
170957
|
detectTerminalThemeSync: () => detectTerminalThemeSync2,
|
|
169885
170958
|
detectTerminalThemeAsync: () => detectTerminalThemeAsync,
|
|
169886
170959
|
calculateLuminance: () => calculateLuminance
|
|
@@ -169955,6 +171028,7 @@ function calculateLuminance(r, g, b) {
|
|
|
169955
171028
|
async function detectTerminalThemeAsync() {
|
|
169956
171029
|
const bg = await queryTerminalBackground(100);
|
|
169957
171030
|
if (bg) {
|
|
171031
|
+
cachedBackground2 = bg;
|
|
169958
171032
|
const luminance = calculateLuminance(bg.r, bg.g, bg.b);
|
|
169959
171033
|
return luminance > 0.4 ? "light" : "dark";
|
|
169960
171034
|
}
|
|
@@ -169983,11 +171057,14 @@ function getTerminalTheme2() {
|
|
|
169983
171057
|
cachedTheme2 = detectTerminalThemeSync2();
|
|
169984
171058
|
return cachedTheme2;
|
|
169985
171059
|
}
|
|
171060
|
+
function getTerminalBackgroundColor2() {
|
|
171061
|
+
return cachedBackground2;
|
|
171062
|
+
}
|
|
169986
171063
|
async function initTerminalTheme() {
|
|
169987
171064
|
cachedTheme2 = await detectTerminalThemeAsync();
|
|
169988
171065
|
return cachedTheme2;
|
|
169989
171066
|
}
|
|
169990
|
-
var cachedTheme2 = null;
|
|
171067
|
+
var cachedTheme2 = null, cachedBackground2 = null;
|
|
169991
171068
|
|
|
169992
171069
|
// src/agent/bootstrap-tools.ts
|
|
169993
171070
|
var exports_bootstrap_tools = {};
|
|
@@ -172182,15 +173259,19 @@ In headless mode, use:
|
|
|
172182
173259
|
const skillSourcesRaw = values["skill-sources"];
|
|
172183
173260
|
const memfsFlag = values.memfs;
|
|
172184
173261
|
const noMemfsFlag = values["no-memfs"];
|
|
173262
|
+
const localNoMemfsRequested = Boolean(backend4.capabilities.localMemfs && (noMemfsFlag || isLocalBackendNoMemfsEnvEnabled()));
|
|
173263
|
+
if (localNoMemfsRequested) {
|
|
173264
|
+
process.env[LOCAL_BACKEND_NO_MEMFS_ENV] = "1";
|
|
173265
|
+
}
|
|
172185
173266
|
const memfsStartupRaw = values["memfs-startup"];
|
|
172186
173267
|
const memfsStartupPolicy = memfsStartupRaw === "background" || memfsStartupRaw === "skip" ? memfsStartupRaw : "blocking";
|
|
172187
|
-
const requestedMemoryPromptMode = memfsFlag ? "memfs" : noMemfsFlag ? "standard" : undefined;
|
|
173268
|
+
const requestedMemoryPromptMode = memfsFlag ? "memfs" : noMemfsFlag || localNoMemfsRequested ? "standard" : undefined;
|
|
172188
173269
|
if (memfsFlag && !backend4.capabilities.remoteMemfs) {
|
|
172189
173270
|
trackHeadlessBoundaryError("headless_memfs_unsupported_backend", "MemFS requires a backend with remote MemFS support", "headless_startup_memfs_flags");
|
|
172190
173271
|
console.error("Error: --memfs is not supported by this backend yet");
|
|
172191
173272
|
process.exit(1);
|
|
172192
173273
|
}
|
|
172193
|
-
const shouldAutoEnableMemfsForNewAgent = !memfsFlag && !noMemfsFlag;
|
|
173274
|
+
const shouldAutoEnableMemfsForNewAgent = !memfsFlag && !noMemfsFlag && !localNoMemfsRequested;
|
|
172194
173275
|
const fromAfFile = resolveImportFlagAlias2({
|
|
172195
173276
|
importFlagValue: values.import,
|
|
172196
173277
|
fromAfFlagValue: values["from-af"]
|
|
@@ -172470,7 +173551,7 @@ In headless mode, use:
|
|
|
172470
173551
|
if (!agent && forceNew) {
|
|
172471
173552
|
const { isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
172472
173553
|
const willAutoEnableMemfs = backend4.capabilities.remoteMemfs && shouldAutoEnableMemfsForNewAgent && await isLettaCloud2();
|
|
172473
|
-
const effectiveMemoryMode = backend4.capabilities.localMemfs ? "local-memfs" : requestedMemoryPromptMode ?? (willAutoEnableMemfs ? "memfs" : undefined);
|
|
173554
|
+
const effectiveMemoryMode = backend4.capabilities.localMemfs ? localNoMemfsRequested ? "standard" : "local-memfs" : requestedMemoryPromptMode ?? (willAutoEnableMemfs ? "memfs" : undefined);
|
|
172474
173555
|
const personalityOptions = personality ? await buildCreateAgentOptionsForPersonality2({
|
|
172475
173556
|
personalityId: personality,
|
|
172476
173557
|
model,
|
|
@@ -172572,12 +173653,8 @@ In headless mode, use:
|
|
|
172572
173653
|
const secretsInitPromise = secretsAgentId ? Promise.resolve().then(() => (init_secretsStore(), exports_secretsStore)).then(({ initSecretsFromServer: initSecretsFromServer2 }) => initSecretsFromServer2(secretsAgentId, agent ?? undefined)) : Promise.resolve();
|
|
172573
173654
|
if (!backend4.capabilities.remoteMemfs) {
|
|
172574
173655
|
if (backend4.capabilities.localMemfs) {
|
|
172575
|
-
|
|
172576
|
-
|
|
172577
|
-
process.exit(1);
|
|
172578
|
-
}
|
|
172579
|
-
settingsManager.setMemfsEnabled(agent.id, true);
|
|
172580
|
-
} else if (noMemfsFlag) {
|
|
173656
|
+
settingsManager.setMemfsEnabled(agent.id, !localNoMemfsRequested);
|
|
173657
|
+
} else if (noMemfsFlag || localNoMemfsRequested) {
|
|
172581
173658
|
settingsManager.setMemfsEnabled(agent.id, false);
|
|
172582
173659
|
}
|
|
172583
173660
|
} else if (memfsStartupPolicy === "skip") {
|
|
@@ -174553,6 +175630,7 @@ var init_headless = __esm(async () => {
|
|
|
174553
175630
|
init_personality();
|
|
174554
175631
|
init_skillSources();
|
|
174555
175632
|
init_backend2();
|
|
175633
|
+
init_paths();
|
|
174556
175634
|
init_errorFormatter();
|
|
174557
175635
|
init_memoryReminder();
|
|
174558
175636
|
init_messageQueueBridge();
|
|
@@ -175395,8 +176473,7 @@ async function handleProfileSave(ctx, msg, profileName) {
|
|
|
175395
176473
|
const cmdId = addCommandResult2(ctx.buffersRef, ctx.refreshDerived, msg, `Saving profile "${profileName}"...`, false, "running");
|
|
175396
176474
|
ctx.setCommandRunning(true);
|
|
175397
176475
|
try {
|
|
175398
|
-
|
|
175399
|
-
await client.agents.update(ctx.agentId, { name: profileName });
|
|
176476
|
+
await getBackend().updateAgent(ctx.agentId, { name: profileName });
|
|
175400
176477
|
ctx.updateAgentName(profileName);
|
|
175401
176478
|
settingsManager.saveProfile(profileName, ctx.agentId);
|
|
175402
176479
|
updateCommandResult2(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `Pinned "${profileName}" locally and globally.`, true);
|
|
@@ -175478,9 +176555,7 @@ async function handlePin(ctx, msg, argsStr) {
|
|
|
175478
176555
|
const globalPinned = settingsManager.getGlobalPinnedAgents();
|
|
175479
176556
|
if (name25 && name25 !== ctx.agentName) {
|
|
175480
176557
|
try {
|
|
175481
|
-
|
|
175482
|
-
const client = await getClient2();
|
|
175483
|
-
await client.agents.update(ctx.agentId, { name: name25 });
|
|
176558
|
+
await getBackend().updateAgent(ctx.agentId, { name: name25 });
|
|
175484
176559
|
ctx.updateAgentName(name25);
|
|
175485
176560
|
} catch (error51) {
|
|
175486
176561
|
addCommandResult2(ctx.buffersRef, ctx.refreshDerived, msg, `Failed to rename agent: ${error51}`, false);
|
|
@@ -175527,7 +176602,7 @@ function handleUnpin(ctx, msg, argsStr) {
|
|
|
175527
176602
|
}
|
|
175528
176603
|
var activeCommandId2 = null;
|
|
175529
176604
|
var init_profile = __esm(() => {
|
|
175530
|
-
|
|
176605
|
+
init_backend2();
|
|
175531
176606
|
init_settings_manager();
|
|
175532
176607
|
init_errorFormatter();
|
|
175533
176608
|
});
|
|
@@ -190685,7 +191760,7 @@ function highlightCode(code, language) {
|
|
|
190685
191760
|
}
|
|
190686
191761
|
return lines;
|
|
190687
191762
|
}
|
|
190688
|
-
var import_react34, jsx_dev_runtime12, lowlight, BASH_LANGUAGE = "bash",
|
|
191763
|
+
var import_react34, jsx_dev_runtime12, lowlight, BASH_LANGUAGE = "bash", FIRST_LINE_PROMPT = "$", PROMPT_COLUMN_WIDTH = 2, EXT_TO_LANG, HEREDOC_RE, REDIRECT_FILE_RE, SyntaxHighlightedCommand;
|
|
190689
191764
|
var init_SyntaxHighlightedCommand = __esm(async () => {
|
|
190690
191765
|
init_lowlight();
|
|
190691
191766
|
init_colors();
|
|
@@ -190786,9 +191861,13 @@ var init_SyntaxHighlightedCommand = __esm(async () => {
|
|
|
190786
191861
|
const lineKey = spans.map((s) => s.text).join("");
|
|
190787
191862
|
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
190788
191863
|
children: [
|
|
190789
|
-
showPrompt ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(
|
|
190790
|
-
|
|
190791
|
-
|
|
191864
|
+
showPrompt ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
191865
|
+
width: PROMPT_COLUMN_WIDTH,
|
|
191866
|
+
flexShrink: 0,
|
|
191867
|
+
children: lineIdx === 0 ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text2, {
|
|
191868
|
+
color: palette.prompt,
|
|
191869
|
+
children: FIRST_LINE_PROMPT
|
|
191870
|
+
}, undefined, false, undefined, this) : null
|
|
190792
191871
|
}, undefined, false, undefined, this) : null,
|
|
190793
191872
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text2, {
|
|
190794
191873
|
color: palette.text,
|
|
@@ -199500,6 +200579,7 @@ function boxBottom(width) {
|
|
|
199500
200579
|
}
|
|
199501
200580
|
var import_react67, jsx_dev_runtime44, BOX_TOP_LEFT = "╭", BOX_TOP_RIGHT = "╮", BOX_BOTTOM_LEFT = "╰", BOX_BOTTOM_RIGHT = "╯", BOX_HORIZONTAL = "─", BOX_VERTICAL = "│", HOOK_EVENTS, FALLBACK_TOOL_NAMES, SAVE_LOCATIONS, HooksManager;
|
|
199502
200581
|
var init_HooksManager = __esm(async () => {
|
|
200582
|
+
init_backend2();
|
|
199503
200583
|
init_types3();
|
|
199504
200584
|
init_writer();
|
|
199505
200585
|
init_settings_manager();
|
|
@@ -199572,6 +200652,9 @@ var init_HooksManager = __esm(async () => {
|
|
|
199572
200652
|
return;
|
|
199573
200653
|
const fetchAgentTools = async () => {
|
|
199574
200654
|
try {
|
|
200655
|
+
if (!getBackend().capabilities.serverSideToolManagement) {
|
|
200656
|
+
return;
|
|
200657
|
+
}
|
|
199575
200658
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
199576
200659
|
const client = await getClient2();
|
|
199577
200660
|
const toolsPage = await client.agents.tools.list(agentId, {
|
|
@@ -202359,6 +203442,7 @@ function SlashCommandAutocomplete({
|
|
|
202359
203442
|
}) {
|
|
202360
203443
|
const columns = useTerminalWidth();
|
|
202361
203444
|
const [customCommands, setCustomCommands] = import_react72.useState([]);
|
|
203445
|
+
const [skillCommands, setSkillCommands] = import_react72.useState([]);
|
|
202362
203446
|
import_react72.useEffect(() => {
|
|
202363
203447
|
Promise.resolve().then(() => (init_custom(), exports_custom)).then(({ getCustomCommands: getCustomCommands2 }) => {
|
|
202364
203448
|
getCustomCommands2().then((customs) => {
|
|
@@ -202371,6 +203455,35 @@ function SlashCommandAutocomplete({
|
|
|
202371
203455
|
});
|
|
202372
203456
|
});
|
|
202373
203457
|
}, []);
|
|
203458
|
+
import_react72.useEffect(() => {
|
|
203459
|
+
let cancelled = false;
|
|
203460
|
+
(async () => {
|
|
203461
|
+
try {
|
|
203462
|
+
const { discoverClientSideSkills: discoverClientSideSkills2 } = await Promise.resolve().then(() => (init_clientSkills(), exports_clientSkills));
|
|
203463
|
+
const { getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
203464
|
+
const { isUserInvocableSkill: isUserInvocableSkill3 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
|
|
203465
|
+
const discovery = await discoverClientSideSkills2({
|
|
203466
|
+
agentId,
|
|
203467
|
+
skillSources: getSkillSources2()
|
|
203468
|
+
});
|
|
203469
|
+
if (cancelled)
|
|
203470
|
+
return;
|
|
203471
|
+
const matches2 = discovery.skills.filter(isUserInvocableSkill3).map((skill2) => ({
|
|
203472
|
+
cmd: `/${skill2.id}`,
|
|
203473
|
+
desc: `${skill2.description}${skill2.argumentHint ? ` ${skill2.argumentHint}` : ""} (${skill2.source} skill)`,
|
|
203474
|
+
order: 300
|
|
203475
|
+
}));
|
|
203476
|
+
setSkillCommands(matches2);
|
|
203477
|
+
} catch {
|
|
203478
|
+
if (!cancelled) {
|
|
203479
|
+
setSkillCommands([]);
|
|
203480
|
+
}
|
|
203481
|
+
}
|
|
203482
|
+
})();
|
|
203483
|
+
return () => {
|
|
203484
|
+
cancelled = true;
|
|
203485
|
+
};
|
|
203486
|
+
}, [agentId]);
|
|
202374
203487
|
const allCommands = import_react72.useMemo(() => {
|
|
202375
203488
|
let builtins = _allCommands;
|
|
202376
203489
|
if (agentId) {
|
|
@@ -202394,8 +203507,13 @@ function SlashCommandAutocomplete({
|
|
|
202394
203507
|
builtins = _allCommands;
|
|
202395
203508
|
}
|
|
202396
203509
|
}
|
|
202397
|
-
|
|
202398
|
-
|
|
203510
|
+
const reservedCommands = new Set([
|
|
203511
|
+
...builtins.map((cmd) => cmd.cmd),
|
|
203512
|
+
...customCommands.map((cmd) => cmd.cmd)
|
|
203513
|
+
]);
|
|
203514
|
+
const visibleSkillCommands = skillCommands.filter((cmd) => !reservedCommands.has(cmd.cmd));
|
|
203515
|
+
return [...builtins, ...customCommands, ...visibleSkillCommands].sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
203516
|
+
}, [agentId, workingDirectory, customCommands, skillCommands]);
|
|
202399
203517
|
const queryInfo = import_react72.useMemo(() => extractSearchQuery2(currentInput, cursorPosition), [currentInput, cursorPosition]);
|
|
202400
203518
|
const { matches, showNoMatches, hideAutocomplete } = import_react72.useMemo(() => {
|
|
202401
203519
|
if (!queryInfo) {
|
|
@@ -209408,8 +210526,7 @@ function MemoryTabViewer({
|
|
|
209408
210526
|
import_react81.useEffect(() => {
|
|
209409
210527
|
const fetchBlocks = async () => {
|
|
209410
210528
|
try {
|
|
209411
|
-
const
|
|
209412
|
-
const agent = await client.agents.retrieve(agentId, {
|
|
210529
|
+
const agent = await getBackend().retrieveAgent(agentId, {
|
|
209413
210530
|
include: ["agent.blocks"]
|
|
209414
210531
|
});
|
|
209415
210532
|
setFreshBlocks(agent.memory?.blocks || []);
|
|
@@ -209686,7 +210803,7 @@ function MemoryTabViewer({
|
|
|
209686
210803
|
}
|
|
209687
210804
|
var import_react81, jsx_dev_runtime58, SOLID_LINE21 = "─", VISIBLE_LINES = 12;
|
|
209688
210805
|
var init_MemoryTabViewer = __esm(async () => {
|
|
209689
|
-
|
|
210806
|
+
init_backend2();
|
|
209690
210807
|
init_debug();
|
|
209691
210808
|
init_useTerminalWidth();
|
|
209692
210809
|
init_colors();
|
|
@@ -209700,24 +210817,13 @@ var init_MemoryTabViewer = __esm(async () => {
|
|
|
209700
210817
|
jsx_dev_runtime58 = __toESM(require_jsx_dev_runtime(), 1);
|
|
209701
210818
|
});
|
|
209702
210819
|
|
|
209703
|
-
// src/backend/api/search.ts
|
|
209704
|
-
async function warmSearchCache(body) {
|
|
209705
|
-
return apiRequest("POST", "/v1/_internal_search/cache-warm", body);
|
|
209706
|
-
}
|
|
209707
|
-
async function searchMessages(body) {
|
|
209708
|
-
return apiRequest("POST", "/v1/messages/search", body);
|
|
209709
|
-
}
|
|
209710
|
-
var init_search = __esm(() => {
|
|
209711
|
-
init_request();
|
|
209712
|
-
});
|
|
209713
|
-
|
|
209714
210820
|
// src/cli/components/MessageSearch.tsx
|
|
209715
210821
|
async function warmMessageSearchCache() {
|
|
209716
210822
|
const body = {
|
|
209717
210823
|
collection: "messages",
|
|
209718
210824
|
scope: {}
|
|
209719
210825
|
};
|
|
209720
|
-
return
|
|
210826
|
+
return warmMessageSearchCacheForBackend(body);
|
|
209721
210827
|
}
|
|
209722
210828
|
function isSearchRangeAvailable(range2, options) {
|
|
209723
210829
|
if (range2 === "agent")
|
|
@@ -209856,7 +210962,7 @@ function MessageSearch({
|
|
|
209856
210962
|
} else if (range2 === "conv" && conversationId) {
|
|
209857
210963
|
body.conversation_id = conversationId;
|
|
209858
210964
|
}
|
|
209859
|
-
return
|
|
210965
|
+
return searchMessagesForBackend(body);
|
|
209860
210966
|
}, [agentId, conversationId]);
|
|
209861
210967
|
const fetchAndCacheSearchResults = import_react82.useCallback(async (query, mode, range2) => {
|
|
209862
210968
|
const cacheKey = getCacheKey(query, mode, range2);
|
|
@@ -210329,7 +211435,7 @@ function MessageSearch({
|
|
|
210329
211435
|
}
|
|
210330
211436
|
var import_react82, jsx_dev_runtime59, SOLID_LINE22 = "─", VISIBLE_ITEMS = 5, SEARCH_LIMIT = 100, SEARCH_MODES, SEARCH_RANGES;
|
|
210331
211437
|
var init_MessageSearch = __esm(async () => {
|
|
210332
|
-
|
|
211438
|
+
init_messageSearch();
|
|
210333
211439
|
init_useTerminalWidth();
|
|
210334
211440
|
init_colors();
|
|
210335
211441
|
await __promiseAll([
|
|
@@ -212657,7 +213763,7 @@ function getTabDescription(tab2, agentId) {
|
|
|
212657
213763
|
case "project":
|
|
212658
213764
|
return ".skills/";
|
|
212659
213765
|
case "agent":
|
|
212660
|
-
return `~/.letta/agents/${shortId}/skills/`;
|
|
213766
|
+
return `~/.letta/agents/${shortId}/memory/skills/`;
|
|
212661
213767
|
case "global":
|
|
212662
213768
|
return "~/.letta/skills/";
|
|
212663
213769
|
case "bundled":
|
|
@@ -212697,7 +213803,7 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
212697
213803
|
}
|
|
212698
213804
|
return grouped;
|
|
212699
213805
|
}, [skills]);
|
|
212700
|
-
const availableTabs = import_react91.useMemo(() => TAB_ORDER
|
|
213806
|
+
const availableTabs = import_react91.useMemo(() => [...TAB_ORDER], []);
|
|
212701
213807
|
const [activeTab, setActiveTab] = import_react91.useState(null);
|
|
212702
213808
|
import_react91.useEffect(() => {
|
|
212703
213809
|
if (!loading && availableTabs.length > 0 && activeTab === null) {
|
|
@@ -212851,13 +213957,20 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
212851
213957
|
}, undefined, false, undefined, this) : null
|
|
212852
213958
|
]
|
|
212853
213959
|
}, undefined, true, undefined, this),
|
|
213960
|
+
!loading && activeTab && currentSkills.length === 0 && /* @__PURE__ */ jsx_dev_runtime68.jsxDEV(Box_default, {
|
|
213961
|
+
paddingLeft: 2,
|
|
213962
|
+
children: /* @__PURE__ */ jsx_dev_runtime68.jsxDEV(Text2, {
|
|
213963
|
+
dimColor: true,
|
|
213964
|
+
children: "No skills in this location"
|
|
213965
|
+
}, undefined, false, undefined, this)
|
|
213966
|
+
}, undefined, false, undefined, this),
|
|
212854
213967
|
/* @__PURE__ */ jsx_dev_runtime68.jsxDEV(Box_default, {
|
|
212855
213968
|
marginTop: 1,
|
|
212856
213969
|
children: /* @__PURE__ */ jsx_dev_runtime68.jsxDEV(Text2, {
|
|
212857
213970
|
dimColor: true,
|
|
212858
213971
|
children: [
|
|
212859
213972
|
" ",
|
|
212860
|
-
|
|
213973
|
+
"↑↓ scroll · ←→/Tab switch · Esc to close"
|
|
212861
213974
|
]
|
|
212862
213975
|
}, undefined, true, undefined, this)
|
|
212863
213976
|
}, undefined, false, undefined, this)
|
|
@@ -215162,7 +216275,7 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215162
216275
|
let shellCommand = null;
|
|
215163
216276
|
let shellSemanticKind = null;
|
|
215164
216277
|
if (!isQuestionTool(rawName)) {
|
|
215165
|
-
const
|
|
216278
|
+
const parseArgs9 = () => {
|
|
215166
216279
|
if (!argsText.trim()) {
|
|
215167
216280
|
return { formatted: null, parseable: true };
|
|
215168
216281
|
}
|
|
@@ -215173,7 +216286,7 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215173
216286
|
return { formatted: null, parseable: false };
|
|
215174
216287
|
}
|
|
215175
216288
|
};
|
|
215176
|
-
const { formatted, parseable } =
|
|
216289
|
+
const { formatted, parseable } = parseArgs9();
|
|
215177
216290
|
const argsComplete = parseable || line.phase === "running" || line.phase === "finished" || !isStreaming;
|
|
215178
216291
|
if (!argsComplete) {
|
|
215179
216292
|
args = "(…)";
|
|
@@ -215286,13 +216399,13 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215286
216399
|
}, undefined, true, undefined, this);
|
|
215287
216400
|
}
|
|
215288
216401
|
const displayResultText = clipToolReturn(extractedText).replace(/\n+$/, "");
|
|
215289
|
-
const
|
|
216402
|
+
const isRecord14 = (v) => typeof v === "object" && v !== null;
|
|
215290
216403
|
if (isTodoTool(rawName, displayName) && line.resultOk !== false && line.argsText) {
|
|
215291
216404
|
try {
|
|
215292
216405
|
const parsedArgs = JSON.parse(line.argsText);
|
|
215293
216406
|
if (parsedArgs.todos && Array.isArray(parsedArgs.todos)) {
|
|
215294
216407
|
const safeTodos = parsedArgs.todos.map((t, i) => {
|
|
215295
|
-
const rec =
|
|
216408
|
+
const rec = isRecord14(t) ? t : {};
|
|
215296
216409
|
const status = rec.status === "completed" ? "completed" : rec.status === "in_progress" ? "in_progress" : "pending";
|
|
215297
216410
|
const id = typeof rec.id === "string" ? rec.id : String(i);
|
|
215298
216411
|
const content = typeof rec.content === "string" ? rec.content : typeof rec.description === "string" ? rec.description : JSON.stringify(t);
|
|
@@ -215310,7 +216423,7 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215310
216423
|
const parsedArgs = JSON.parse(line.argsText);
|
|
215311
216424
|
if (parsedArgs.plan && Array.isArray(parsedArgs.plan)) {
|
|
215312
216425
|
const safePlan = parsedArgs.plan.map((item) => {
|
|
215313
|
-
const rec =
|
|
216426
|
+
const rec = isRecord14(item) ? item : {};
|
|
215314
216427
|
const status = rec.status === "completed" ? "completed" : rec.status === "in_progress" ? "in_progress" : "pending";
|
|
215315
216428
|
const step = typeof rec.step === "string" ? rec.step : JSON.stringify(item);
|
|
215316
216429
|
return { step, status };
|
|
@@ -216127,6 +217240,27 @@ var init_TrajectorySummary = __esm(async () => {
|
|
|
216127
217240
|
});
|
|
216128
217241
|
|
|
216129
217242
|
// src/cli/components/UserMessageRich.tsx
|
|
217243
|
+
function getCurrentStdoutColumns() {
|
|
217244
|
+
if (typeof process === "undefined")
|
|
217245
|
+
return null;
|
|
217246
|
+
const columns = process.stdout?.columns;
|
|
217247
|
+
return typeof columns === "number" && columns > 0 ? columns : null;
|
|
217248
|
+
}
|
|
217249
|
+
function isInkFullWidthCodePoint(codePoint) {
|
|
217250
|
+
return codePoint >= 4352 && (codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || 11904 <= codePoint && codePoint <= 12871 && codePoint !== 12351 || 12880 <= codePoint && codePoint <= 19903 || 19968 <= codePoint && codePoint <= 42182 || 43360 <= codePoint && codePoint <= 43388 || 44032 <= codePoint && codePoint <= 55203 || 63744 <= codePoint && codePoint <= 64255 || 65040 <= codePoint && codePoint <= 65049 || 65072 <= codePoint && codePoint <= 65131 || 65281 <= codePoint && codePoint <= 65376 || 65504 <= codePoint && codePoint <= 65510 || 110592 <= codePoint && codePoint <= 110593 || 127488 <= codePoint && codePoint <= 127569 || 131072 <= codePoint && codePoint <= 262141);
|
|
217251
|
+
}
|
|
217252
|
+
function inkStringWidth(text2) {
|
|
217253
|
+
let width = 0;
|
|
217254
|
+
for (let index = 0;index < text2.length; ) {
|
|
217255
|
+
const codePoint = text2.codePointAt(index);
|
|
217256
|
+
if (codePoint === undefined)
|
|
217257
|
+
break;
|
|
217258
|
+
const character = String.fromCodePoint(codePoint);
|
|
217259
|
+
width += isInkFullWidthCodePoint(codePoint) || character.length > 1 ? 2 : 1;
|
|
217260
|
+
index += character.length;
|
|
217261
|
+
}
|
|
217262
|
+
return width;
|
|
217263
|
+
}
|
|
216130
217264
|
function wordWrap(text2, width) {
|
|
216131
217265
|
if (width <= 0)
|
|
216132
217266
|
return [text2];
|
|
@@ -216138,7 +217272,7 @@ function wordWrap(text2, width) {
|
|
|
216138
217272
|
current = word;
|
|
216139
217273
|
} else {
|
|
216140
217274
|
const candidate = `${current} ${word}`;
|
|
216141
|
-
if (
|
|
217275
|
+
if (inkStringWidth(candidate) <= width) {
|
|
216142
217276
|
current = candidate;
|
|
216143
217277
|
} else {
|
|
216144
217278
|
lines.push(current);
|
|
@@ -216186,7 +217320,11 @@ function splitSystemReminderBlocks(text2) {
|
|
|
216186
217320
|
}
|
|
216187
217321
|
return blocks;
|
|
216188
217322
|
}
|
|
216189
|
-
function
|
|
217323
|
+
function padToColumns(text2, columns) {
|
|
217324
|
+
const pad = Math.max(0, columns - inkStringWidth(text2));
|
|
217325
|
+
return `${text2}${" ".repeat(pad)}`;
|
|
217326
|
+
}
|
|
217327
|
+
function renderBlock(text2, contentWidth, columns, highlighted, promptPrefix, continuationPrefix) {
|
|
216190
217328
|
const inputLines = text2.split(`
|
|
216191
217329
|
`);
|
|
216192
217330
|
const outputLines = [];
|
|
@@ -216202,34 +217340,39 @@ function renderBlock(text2, contentWidth, columns, highlighted, colorAnsi, promp
|
|
|
216202
217340
|
}
|
|
216203
217341
|
if (outputLines.length === 0)
|
|
216204
217342
|
return [];
|
|
216205
|
-
const
|
|
216206
|
-
return outputLines.map((ol, i) => {
|
|
217343
|
+
const renderedLines = outputLines.map((ol, i) => {
|
|
216207
217344
|
const prefix = i === 0 ? promptPrefix : continuationPrefix;
|
|
217345
|
+
const content = `${prefix}${ol}`;
|
|
216208
217346
|
if (!highlighted) {
|
|
216209
|
-
return
|
|
216210
|
-
}
|
|
216211
|
-
const content = i === 0 ? `${promptPrefix.slice(0, -1)}${colorAnsi} ${ol}` : `${prefix}${ol}`;
|
|
216212
|
-
const visWidth = stringWidth(content);
|
|
216213
|
-
if (isSingleLine) {
|
|
216214
|
-
return `${colorAnsi}${content}${" ".repeat(COMPACT_PAD)}\x1B[0m`;
|
|
217347
|
+
return { text: content, highlighted: false };
|
|
216215
217348
|
}
|
|
216216
|
-
|
|
216217
|
-
return `${colorAnsi}${content}${" ".repeat(pad)}\x1B[0m`;
|
|
217349
|
+
return { text: padToColumns(content, columns), highlighted: true };
|
|
216218
217350
|
});
|
|
217351
|
+
if (!highlighted) {
|
|
217352
|
+
return renderedLines;
|
|
217353
|
+
}
|
|
217354
|
+
const blankLine = {
|
|
217355
|
+
text: " ".repeat(Math.max(0, columns)),
|
|
217356
|
+
highlighted: true
|
|
217357
|
+
};
|
|
217358
|
+
return [blankLine, ...renderedLines, blankLine];
|
|
216219
217359
|
}
|
|
216220
|
-
var import_react101, jsx_dev_runtime81,
|
|
217360
|
+
var import_react101, jsx_dev_runtime81, UserMessage;
|
|
216221
217361
|
var init_UserMessageRich = __esm(async () => {
|
|
216222
|
-
init_string_width();
|
|
216223
217362
|
init_constants();
|
|
216224
217363
|
init_useTerminalWidth();
|
|
216225
217364
|
init_colors();
|
|
216226
|
-
await
|
|
217365
|
+
await __promiseAll([
|
|
217366
|
+
init_build2(),
|
|
217367
|
+
init_Text2()
|
|
217368
|
+
]);
|
|
216227
217369
|
import_react101 = __toESM(require_react(), 1);
|
|
216228
217370
|
jsx_dev_runtime81 = __toESM(require_jsx_dev_runtime(), 1);
|
|
216229
217371
|
UserMessage = import_react101.memo(({ line, prompt }) => {
|
|
216230
|
-
const
|
|
217372
|
+
const trackedColumns2 = useTerminalWidth();
|
|
217373
|
+
const columns = getCurrentStdoutColumns() ?? trackedColumns2;
|
|
216231
217374
|
const promptPrefix = `${prompt || ">"} `;
|
|
216232
|
-
const prefixWidth =
|
|
217375
|
+
const prefixWidth = inkStringWidth(promptPrefix);
|
|
216233
217376
|
const continuationPrefix = " ".repeat(prefixWidth);
|
|
216234
217377
|
const contentWidth = Math.max(1, columns - prefixWidth);
|
|
216235
217378
|
const cleanedText = extractTaskNotificationsForDisplay(line.text).cleanedText;
|
|
@@ -216238,23 +217381,25 @@ var init_UserMessageRich = __esm(async () => {
|
|
|
216238
217381
|
return null;
|
|
216239
217382
|
}
|
|
216240
217383
|
const { background, text: textColor } = colors.userMessage;
|
|
216241
|
-
const bgAnsi = hexToBgAnsi(background);
|
|
216242
|
-
const fgAnsi = textColor ? hexToFgAnsi(textColor) : "";
|
|
216243
|
-
const colorAnsi = bgAnsi + fgAnsi;
|
|
216244
217384
|
const blocks = splitSystemReminderBlocks(displayText);
|
|
216245
217385
|
const allLines = [];
|
|
216246
217386
|
for (const block of blocks) {
|
|
216247
217387
|
if (!block.text.trim())
|
|
216248
217388
|
continue;
|
|
216249
217389
|
if (allLines.length > 0) {
|
|
216250
|
-
allLines.push("");
|
|
217390
|
+
allLines.push({ text: "", highlighted: false });
|
|
216251
217391
|
}
|
|
216252
|
-
const blockLines = renderBlock(block.text, contentWidth, columns, !block.isSystemReminder,
|
|
217392
|
+
const blockLines = renderBlock(block.text, contentWidth, columns, !block.isSystemReminder, promptPrefix, continuationPrefix);
|
|
216253
217393
|
allLines.push(...blockLines);
|
|
216254
217394
|
}
|
|
216255
|
-
return /* @__PURE__ */ jsx_dev_runtime81.jsxDEV(
|
|
216256
|
-
|
|
216257
|
-
|
|
217395
|
+
return /* @__PURE__ */ jsx_dev_runtime81.jsxDEV(Box_default, {
|
|
217396
|
+
flexDirection: "column",
|
|
217397
|
+
children: allLines.map((line2, index) => /* @__PURE__ */ jsx_dev_runtime81.jsxDEV(Text2, {
|
|
217398
|
+
backgroundColor: line2.highlighted ? background : undefined,
|
|
217399
|
+
color: line2.highlighted ? textColor : undefined,
|
|
217400
|
+
wrap: line2.highlighted ? "end" : "wrap",
|
|
217401
|
+
children: line2.text
|
|
217402
|
+
}, index, false, undefined, this))
|
|
216258
217403
|
}, undefined, false, undefined, this);
|
|
216259
217404
|
});
|
|
216260
217405
|
UserMessage.displayName = "UserMessage";
|
|
@@ -217736,7 +218881,7 @@ function updateCommandResult3(buffersRef, refreshDerived, cmdId, input, output,
|
|
|
217736
218881
|
buffersRef.current.byId.set(cmdId, line);
|
|
217737
218882
|
refreshDerived();
|
|
217738
218883
|
}
|
|
217739
|
-
function
|
|
218884
|
+
function parseArgs9(msg) {
|
|
217740
218885
|
return msg.trim().split(/\s+/).filter(Boolean);
|
|
217741
218886
|
}
|
|
217742
218887
|
function formatConnectUsage() {
|
|
@@ -217936,7 +219081,7 @@ ${formatBedrockUsage2()}`, false);
|
|
|
217936
219081
|
}
|
|
217937
219082
|
}
|
|
217938
219083
|
async function handleConnect(ctx, msg) {
|
|
217939
|
-
const parts =
|
|
219084
|
+
const parts = parseArgs9(msg);
|
|
217940
219085
|
const providerToken = parts[1];
|
|
217941
219086
|
if (!providerToken) {
|
|
217942
219087
|
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, formatConnectUsage(), false);
|
|
@@ -218052,7 +219197,7 @@ The '${CLAUDE_PROVIDER_NAME}' provider does not exist in your Letta account.`, f
|
|
|
218052
219197
|
}
|
|
218053
219198
|
}
|
|
218054
219199
|
async function handleDisconnect(ctx, msg) {
|
|
218055
|
-
const parts =
|
|
219200
|
+
const parts = parseArgs9(msg);
|
|
218056
219201
|
const providerToken = parts[1]?.toLowerCase();
|
|
218057
219202
|
if (providerToken === "help") {
|
|
218058
219203
|
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, formatDisconnectHelp(), true);
|
|
@@ -220354,9 +221499,8 @@ function App2({
|
|
|
220354
221499
|
return;
|
|
220355
221500
|
}
|
|
220356
221501
|
try {
|
|
220357
|
-
const client = await getClient();
|
|
220358
221502
|
debugLog("conversations", `retrieve(${conversationId}) [syncConversationModel]`);
|
|
220359
|
-
const conversation = await
|
|
221503
|
+
const conversation = await getBackend().retrieveConversation(conversationId);
|
|
220360
221504
|
if (cancelled)
|
|
220361
221505
|
return;
|
|
220362
221506
|
const conversationModel = conversation.model;
|
|
@@ -220788,9 +221932,8 @@ ${newState.originalPrompt}`,
|
|
|
220788
221932
|
})) {
|
|
220789
221933
|
llmApiErrorRetriesRef.current += 1;
|
|
220790
221934
|
try {
|
|
220791
|
-
const
|
|
220792
|
-
const
|
|
220793
|
-
const { pendingApprovals: existingApprovals } = await getResumeData(client, agent, conversationIdRef.current);
|
|
221935
|
+
const agent = await getBackend().retrieveAgent(agentIdRef.current);
|
|
221936
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, conversationIdRef.current);
|
|
220794
221937
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
|
|
220795
221938
|
} catch {
|
|
220796
221939
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -220939,9 +222082,8 @@ ${newState.originalPrompt}`,
|
|
|
220939
222082
|
if (hasApprovalInPayload2) {
|
|
220940
222083
|
if (isInvalidToolCallIdsError(errorDetail)) {
|
|
220941
222084
|
try {
|
|
220942
|
-
const
|
|
220943
|
-
const
|
|
220944
|
-
const { pendingApprovals: serverApprovals } = await getResumeData(client, agent, conversationIdRef.current);
|
|
222085
|
+
const agent = await getBackend().retrieveAgent(agentIdRef.current);
|
|
222086
|
+
const { pendingApprovals: serverApprovals } = await getResumeDataFromBackend2(agent, conversationIdRef.current);
|
|
220945
222087
|
if (serverApprovals && serverApprovals.length > 0) {
|
|
220946
222088
|
const userMessage = currentInput.find((item) => item?.type === "message");
|
|
220947
222089
|
if (userMessage && "content" in userMessage) {
|
|
@@ -220988,7 +222130,7 @@ ${newState.originalPrompt}`,
|
|
|
220988
222130
|
}
|
|
220989
222131
|
const syncAgentState = async () => {
|
|
220990
222132
|
try {
|
|
220991
|
-
const agent = prefetchedAgent ?? await (
|
|
222133
|
+
const agent = prefetchedAgent ?? await getBackend().retrieveAgent(agentIdRef.current);
|
|
220992
222134
|
const currentModel = llmConfigRef.current?.model;
|
|
220993
222135
|
const currentEndpoint = llmConfigRef.current?.model_endpoint_type;
|
|
220994
222136
|
const currentEffort = llmConfigRef.current?.reasoning_effort;
|
|
@@ -221149,8 +222291,7 @@ ${feedback}
|
|
|
221149
222291
|
if (!conversationTitle) {
|
|
221150
222292
|
isAutoConversationTitleInFlightRef.current = false;
|
|
221151
222293
|
} else {
|
|
221152
|
-
|
|
221153
|
-
client.conversations.update(conversationIdRef.current, {
|
|
222294
|
+
getBackend().updateConversation(conversationIdRef.current, {
|
|
221154
222295
|
summary: conversationTitle
|
|
221155
222296
|
}).then(() => {
|
|
221156
222297
|
shouldAutoGenerateConversationTitleRef.current = false;
|
|
@@ -221568,9 +222709,8 @@ ${feedback}
|
|
|
221568
222709
|
const invalidIdsDetected = isInvalidToolCallIdsError(detailFromRun) || isInvalidToolCallIdsError(latestErrorText);
|
|
221569
222710
|
if (hasApprovalInPayload && invalidIdsDetected) {
|
|
221570
222711
|
try {
|
|
221571
|
-
const
|
|
221572
|
-
const
|
|
221573
|
-
const { pendingApprovals: serverApprovals } = await getResumeData(client, agent, conversationIdRef.current);
|
|
222712
|
+
const agent = await getBackend().retrieveAgent(agentIdRef.current);
|
|
222713
|
+
const { pendingApprovals: serverApprovals } = await getResumeDataFromBackend2(agent, conversationIdRef.current);
|
|
221574
222714
|
if (serverApprovals && serverApprovals.length > 0) {
|
|
221575
222715
|
const userMessage = currentInput.find((item) => item?.type === "message");
|
|
221576
222716
|
if (userMessage && "content" in userMessage) {
|
|
@@ -221613,9 +222753,8 @@ ${feedback}
|
|
|
221613
222753
|
})) {
|
|
221614
222754
|
llmApiErrorRetriesRef.current += 1;
|
|
221615
222755
|
try {
|
|
221616
|
-
const
|
|
221617
|
-
const
|
|
221618
|
-
const { pendingApprovals: existingApprovals } = await getResumeData(client, agent, conversationIdRef.current);
|
|
222756
|
+
const agent = await getBackend().retrieveAgent(agentIdRef.current);
|
|
222757
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, conversationIdRef.current);
|
|
221619
222758
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
|
|
221620
222759
|
} catch {
|
|
221621
222760
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -222248,7 +223387,7 @@ ${feedback}
|
|
|
222248
223387
|
setBtwState({ status: "forking", question });
|
|
222249
223388
|
try {
|
|
222250
223389
|
const isDefault = conversationIdRef.current === "default";
|
|
222251
|
-
const forked = await forkConversation(conversationIdRef.current, {
|
|
223390
|
+
const forked = await getBackend().forkConversation(conversationIdRef.current, {
|
|
222252
223391
|
...isDefault ? { agentId } : {}
|
|
222253
223392
|
});
|
|
222254
223393
|
debugLog("btw", "forked conversationId=%s", forked.id);
|
|
@@ -222289,14 +223428,13 @@ ${feedback}
|
|
|
222289
223428
|
})) {
|
|
222290
223429
|
approvalRecoveryRetries += 1;
|
|
222291
223430
|
try {
|
|
222292
|
-
const client = await getClient();
|
|
222293
223431
|
const currentAgentId = agentIdRef.current ?? agentId;
|
|
222294
223432
|
if (!currentAgentId) {
|
|
222295
223433
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
222296
223434
|
continue;
|
|
222297
223435
|
}
|
|
222298
|
-
const agent = await
|
|
222299
|
-
const { pendingApprovals: existingApprovals } = await
|
|
223436
|
+
const agent = await getBackend().retrieveAgent(currentAgentId);
|
|
223437
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, forked.id);
|
|
222300
223438
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], STALE_APPROVAL_RECOVERY_DENIAL_REASON);
|
|
222301
223439
|
} catch {
|
|
222302
223440
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -222353,8 +223491,7 @@ ${feedback}
|
|
|
222353
223491
|
if (!agentState) {
|
|
222354
223492
|
throw new Error("Agent state not available");
|
|
222355
223493
|
}
|
|
222356
|
-
const
|
|
222357
|
-
const resumeData = await getResumeData(client, agentState, conversationId2);
|
|
223494
|
+
const resumeData = await getResumeDataFromBackend2(agentState, conversationId2);
|
|
222358
223495
|
await maybeCarryOverActiveConversationModel(conversationId2);
|
|
222359
223496
|
setConversationIdAndRef(conversationId2);
|
|
222360
223497
|
setConversationAutoTitleEligibility(false);
|
|
@@ -222457,8 +223594,7 @@ ${feedback}
|
|
|
222457
223594
|
const cmd = overlayCommand ?? commandRunner.start("/agents", "Switching agent...");
|
|
222458
223595
|
cmd.update({ output: "Switching agent...", phase: "running" });
|
|
222459
223596
|
try {
|
|
222460
|
-
const
|
|
222461
|
-
const agent = await client.agents.retrieve(targetAgentId);
|
|
223597
|
+
const agent = await getBackend().retrieveAgent(targetAgentId);
|
|
222462
223598
|
const targetConversationId = opts?.conversationId ?? "default";
|
|
222463
223599
|
await updateProjectSettings({ lastAgent: targetAgentId });
|
|
222464
223600
|
settingsManager.persistSession(targetAgentId, targetConversationId);
|
|
@@ -222547,8 +223683,7 @@ ${feedback}
|
|
|
222547
223683
|
const isSelfHosted = !getServerUrl().includes("api.letta.com");
|
|
222548
223684
|
if (isSelfHosted) {
|
|
222549
223685
|
try {
|
|
222550
|
-
const
|
|
222551
|
-
const availableHandles = (await client.models.list()).map((model) => model.handle).filter((handle) => typeof handle === "string");
|
|
223686
|
+
const availableHandles = (await backend4.listModels()).map((model) => model.handle).filter((handle) => typeof handle === "string");
|
|
222552
223687
|
effectiveModel = selectDefaultAgentModel({
|
|
222553
223688
|
preferredModel: effectiveModel,
|
|
222554
223689
|
isSelfHosted: true,
|
|
@@ -222744,9 +223879,8 @@ ${expanded.command}` : expanded.command;
|
|
|
222744
223879
|
return { blocked: false };
|
|
222745
223880
|
}
|
|
222746
223881
|
try {
|
|
222747
|
-
const
|
|
222748
|
-
const
|
|
222749
|
-
const { pendingApprovals: existingApprovals } = await getResumeData(client, agent, conversationIdRef.current);
|
|
223882
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
223883
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, conversationIdRef.current);
|
|
222750
223884
|
if (!existingApprovals || existingApprovals.length === 0) {
|
|
222751
223885
|
setNeedsEagerApprovalCheck(false);
|
|
222752
223886
|
return { blocked: false };
|
|
@@ -222910,6 +224044,11 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
222910
224044
|
return { submitted: true };
|
|
222911
224045
|
}
|
|
222912
224046
|
if (trimmed === "/install-github-app") {
|
|
224047
|
+
if (getBackend().capabilities.localModelCatalog) {
|
|
224048
|
+
const cmd = commandRunner.start(trimmed, "Checking GitHub App installer support...");
|
|
224049
|
+
cmd.fail("GitHub App installation is not supported by the local backend.");
|
|
224050
|
+
return { submitted: true };
|
|
224051
|
+
}
|
|
222913
224052
|
startOverlayCommand("install-github-app", "/install-github-app", "Opening GitHub App installer...", "GitHub App installer dismissed");
|
|
222914
224053
|
setActiveOverlay("install-github-app");
|
|
222915
224054
|
return { submitted: true };
|
|
@@ -223013,6 +224152,11 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
223013
224152
|
};
|
|
223014
224153
|
const afterMcp = msg.trim().slice(4).trim();
|
|
223015
224154
|
const firstWord = afterMcp.split(/\s+/)[0]?.toLowerCase();
|
|
224155
|
+
if (firstWord !== "help" && !getBackend().capabilities.serverSideToolManagement) {
|
|
224156
|
+
const cmd = commandRunner.start(msg, "Checking MCP support...");
|
|
224157
|
+
cmd.fail("MCP server management is not supported by the local backend yet.");
|
|
224158
|
+
return { submitted: true };
|
|
224159
|
+
}
|
|
223016
224160
|
if (!firstWord) {
|
|
223017
224161
|
startOverlayCommand("mcp", "/mcp", "Opening MCP server manager...", "MCP dialog dismissed");
|
|
223018
224162
|
setActiveOverlay("mcp");
|
|
@@ -223527,8 +224671,8 @@ Type your task to begin the loop.`, true);
|
|
|
223527
224671
|
setCommandRunning(true);
|
|
223528
224672
|
await runEndHooks();
|
|
223529
224673
|
try {
|
|
223530
|
-
const
|
|
223531
|
-
const conversation = await
|
|
224674
|
+
const backend4 = getBackend();
|
|
224675
|
+
const conversation = await backend4.createConversation({
|
|
223532
224676
|
agent_id: agentId,
|
|
223533
224677
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS],
|
|
223534
224678
|
...conversationName && { summary: conversationName }
|
|
@@ -223568,13 +224712,13 @@ Type your task to begin the loop.`, true);
|
|
|
223568
224712
|
setCommandRunning(true);
|
|
223569
224713
|
await runEndHooks();
|
|
223570
224714
|
try {
|
|
223571
|
-
const client = await getClient();
|
|
223572
224715
|
const isDefault = conversationIdRef.current === "default";
|
|
223573
|
-
const
|
|
224716
|
+
const backend4 = getBackend();
|
|
224717
|
+
const forked = await backend4.forkConversation(conversationIdRef.current, {
|
|
223574
224718
|
...isDefault ? { agentId } : {}
|
|
223575
224719
|
});
|
|
223576
224720
|
if (conversationSummary) {
|
|
223577
|
-
await
|
|
224721
|
+
await backend4.updateConversation(forked.id, {
|
|
223578
224722
|
summary: conversationSummary
|
|
223579
224723
|
});
|
|
223580
224724
|
}
|
|
@@ -223623,13 +224767,14 @@ Type your task to begin the loop.`, true);
|
|
|
223623
224767
|
setCommandRunning(true);
|
|
223624
224768
|
await runEndHooks();
|
|
223625
224769
|
try {
|
|
223626
|
-
const
|
|
223627
|
-
if (conversationIdRef.current === "default") {
|
|
224770
|
+
const backend4 = getBackend();
|
|
224771
|
+
if (conversationIdRef.current === "default" && !backend4.capabilities.localModelCatalog) {
|
|
224772
|
+
const client = await getClient();
|
|
223628
224773
|
await client.agents.messages.reset(agentId, {
|
|
223629
224774
|
add_default_initial_messages: false
|
|
223630
224775
|
});
|
|
223631
224776
|
}
|
|
223632
|
-
const conversation = await
|
|
224777
|
+
const conversation = await backend4.createConversation({
|
|
223633
224778
|
agent_id: agentId,
|
|
223634
224779
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
223635
224780
|
});
|
|
@@ -223776,20 +224921,20 @@ Type your task to begin the loop.`, true);
|
|
|
223776
224921
|
});
|
|
223777
224922
|
setCommandRunning(true);
|
|
223778
224923
|
try {
|
|
223779
|
-
const
|
|
224924
|
+
const backend4 = getBackend();
|
|
223780
224925
|
if (shouldAutoGenerate) {
|
|
223781
224926
|
const conversationTitle = await generateConversationTitle();
|
|
223782
224927
|
if (!conversationTitle) {
|
|
223783
224928
|
cmd.fail("No conversation content available to generate a title");
|
|
223784
224929
|
return { submitted: true };
|
|
223785
224930
|
}
|
|
223786
|
-
await
|
|
224931
|
+
await backend4.updateConversation(conversationId, {
|
|
223787
224932
|
summary: conversationTitle
|
|
223788
224933
|
});
|
|
223789
224934
|
setConversationAutoTitleEligibility(false);
|
|
223790
224935
|
cmd.finish(`Conversation title set to "${conversationTitle}"`, true);
|
|
223791
224936
|
} else {
|
|
223792
|
-
await
|
|
224937
|
+
await backend4.updateConversation(conversationId, {
|
|
223793
224938
|
summary: newValue
|
|
223794
224939
|
});
|
|
223795
224940
|
setConversationAutoTitleEligibility(false);
|
|
@@ -223814,8 +224959,9 @@ Type your task to begin the loop.`, true);
|
|
|
223814
224959
|
});
|
|
223815
224960
|
setCommandRunning(true);
|
|
223816
224961
|
try {
|
|
223817
|
-
|
|
223818
|
-
|
|
224962
|
+
await getBackend().updateAgent(agentId, {
|
|
224963
|
+
name: newValue
|
|
224964
|
+
});
|
|
223819
224965
|
updateAgentName(newValue);
|
|
223820
224966
|
cmd.agentHint = `Your name is now "${newValue}" — acknowledge this and save your new name to memory.`;
|
|
223821
224967
|
cmd.finish(`Agent renamed to "${newValue}"`, true);
|
|
@@ -223852,10 +224998,11 @@ Type your task to begin the loop.`, true);
|
|
|
223852
224998
|
cmd.update({ output: "Updating description...", phase: "running" });
|
|
223853
224999
|
setCommandRunning(true);
|
|
223854
225000
|
try {
|
|
223855
|
-
|
|
223856
|
-
await client.agents.update(agentId, {
|
|
225001
|
+
await getBackend().updateAgent(agentId, {
|
|
223857
225002
|
description: newDescription
|
|
223858
225003
|
});
|
|
225004
|
+
setAgentState((prev) => prev ? { ...prev, description: newDescription } : prev);
|
|
225005
|
+
setAgentDescription(newDescription);
|
|
223859
225006
|
cmd.finish(`Description updated to "${newDescription}"`, true);
|
|
223860
225007
|
} catch (error51) {
|
|
223861
225008
|
const errorDetails = formatErrorDetails2(error51, agentId);
|
|
@@ -223898,8 +225045,7 @@ Type your task to begin the loop.`, true);
|
|
|
223898
225045
|
setCommandRunning(true);
|
|
223899
225046
|
try {
|
|
223900
225047
|
if (agentState) {
|
|
223901
|
-
const
|
|
223902
|
-
const resumeData = await getResumeData(client, agentState, targetConvId);
|
|
225048
|
+
const resumeData = await getResumeDataFromBackend2(agentState, targetConvId);
|
|
223903
225049
|
setConversationIdAndRef(targetConvId);
|
|
223904
225050
|
setConversationAutoTitleEligibility(false);
|
|
223905
225051
|
pendingConversationSwitchRef.current = {
|
|
@@ -224173,6 +225319,10 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
224173
225319
|
}
|
|
224174
225320
|
if (msg.trim() === "/export" || msg.trim() === "/download") {
|
|
224175
225321
|
const cmd = commandRunner.start(msg.trim(), "Exporting agent file...");
|
|
225322
|
+
if (!getBackend().capabilities.agentFileImportExport) {
|
|
225323
|
+
cmd.fail("AgentFile export is not supported by the local backend yet.");
|
|
225324
|
+
return { submitted: true };
|
|
225325
|
+
}
|
|
224176
225326
|
setCommandRunning(true);
|
|
224177
225327
|
try {
|
|
224178
225328
|
const client = await getClient();
|
|
@@ -224459,8 +225609,7 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
224459
225609
|
const reflectionConversationId = conversationIdRef.current;
|
|
224460
225610
|
let systemPrompt;
|
|
224461
225611
|
try {
|
|
224462
|
-
const
|
|
224463
|
-
const agent = await client.agents.retrieve(agentId);
|
|
225612
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
224464
225613
|
systemPrompt = agent.system ?? undefined;
|
|
224465
225614
|
} catch {}
|
|
224466
225615
|
const autoPayload = await buildAutoReflectionPayload(agentId, reflectionConversationId, systemPrompt);
|
|
@@ -224727,6 +225876,48 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
224727
225876
|
if (registryCmd) {
|
|
224728
225877
|
registryCmd.fail(`Unknown command: ${registryCommandName}`);
|
|
224729
225878
|
}
|
|
225879
|
+
const skillCommandName = registryCommandName.slice(1);
|
|
225880
|
+
const { discoverClientSideSkills: discoverClientSideSkills2 } = await Promise.resolve().then(() => (init_clientSkills(), exports_clientSkills));
|
|
225881
|
+
const { getSkillSources: getSkillSources3 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
225882
|
+
const { isUserInvocableSkill: isUserInvocableSkill3 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
|
|
225883
|
+
const skillDiscovery = await discoverClientSideSkills2({
|
|
225884
|
+
agentId,
|
|
225885
|
+
skillSources: getSkillSources3()
|
|
225886
|
+
});
|
|
225887
|
+
const matchedSkill = skillDiscovery.skills.find((skill2) => skill2.id === skillCommandName && isUserInvocableSkill3(skill2));
|
|
225888
|
+
if (matchedSkill) {
|
|
225889
|
+
const cmd = commandRunner.start(trimmed, `Running /${matchedSkill.id}...`);
|
|
225890
|
+
const approvalCheck = await checkPendingApprovalsForSlashCommand();
|
|
225891
|
+
if (approvalCheck.blocked) {
|
|
225892
|
+
cmd.fail(`Pending approval(s). Resolve approvals before running /${matchedSkill.id}.`);
|
|
225893
|
+
return { submitted: false };
|
|
225894
|
+
}
|
|
225895
|
+
const args = trimmed.slice(`/${matchedSkill.id}`.length).trim();
|
|
225896
|
+
setCommandRunning(true);
|
|
225897
|
+
try {
|
|
225898
|
+
const { loadRenderedSkillContent: loadRenderedSkillContent2, wrapSkillContent: wrapSkillContent2 } = await Promise.resolve().then(() => (init_Skill2(), exports_Skill));
|
|
225899
|
+
const skillContent = await loadRenderedSkillContent2(matchedSkill.id, {
|
|
225900
|
+
agentId,
|
|
225901
|
+
args,
|
|
225902
|
+
allowDisabledModelInvocation: true
|
|
225903
|
+
});
|
|
225904
|
+
cmd.finish("Running skill...", true);
|
|
225905
|
+
await processConversationWithQueuedApprovals([
|
|
225906
|
+
{
|
|
225907
|
+
type: "message",
|
|
225908
|
+
role: "user",
|
|
225909
|
+
content: buildTextParts(wrapSkillContent2(matchedSkill.id, skillContent)),
|
|
225910
|
+
otid: randomUUID18()
|
|
225911
|
+
}
|
|
225912
|
+
]);
|
|
225913
|
+
} catch (error51) {
|
|
225914
|
+
const errorDetails = formatErrorDetails2(error51, agentId);
|
|
225915
|
+
cmd.fail(`Failed to run skill: ${errorDetails}`);
|
|
225916
|
+
} finally {
|
|
225917
|
+
setCommandRunning(false);
|
|
225918
|
+
}
|
|
225919
|
+
return { submitted: true };
|
|
225920
|
+
}
|
|
224730
225921
|
} else {
|
|
224731
225922
|
if (registryCmd) {
|
|
224732
225923
|
registryCmd.finish(result.output, result.success);
|
|
@@ -224817,8 +226008,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
224817
226008
|
const reflectionConversationId = conversationIdRef.current;
|
|
224818
226009
|
let systemPrompt;
|
|
224819
226010
|
try {
|
|
224820
|
-
const
|
|
224821
|
-
const agent = await client.agents.retrieve(agentId);
|
|
226011
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
224822
226012
|
systemPrompt = agent.system ?? undefined;
|
|
224823
226013
|
} catch {}
|
|
224824
226014
|
const autoPayload = await buildAutoReflectionPayload(agentId, reflectionConversationId, systemPrompt);
|
|
@@ -224947,9 +226137,8 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
224947
226137
|
buffersRef.current.order.push(eagerStatusId);
|
|
224948
226138
|
refreshDerived();
|
|
224949
226139
|
try {
|
|
224950
|
-
const
|
|
224951
|
-
const
|
|
224952
|
-
const { pendingApprovals: existingApprovals } = await getResumeData(client, agent, conversationIdRef.current);
|
|
226140
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
226141
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, conversationIdRef.current);
|
|
224953
226142
|
buffersRef.current.byId.delete(eagerStatusId);
|
|
224954
226143
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== eagerStatusId);
|
|
224955
226144
|
if (userCancelledRef.current || abortControllerRef.current?.signal.aborted) {
|
|
@@ -225908,16 +227097,17 @@ ${guidance}`);
|
|
|
225908
227097
|
phase: "running"
|
|
225909
227098
|
});
|
|
225910
227099
|
try {
|
|
225911
|
-
const client = await getClient();
|
|
225912
227100
|
const existing = agentState?.compaction_settings;
|
|
225913
227101
|
const existingModel = existing?.model?.trim();
|
|
225914
|
-
|
|
225915
|
-
|
|
225916
|
-
|
|
225917
|
-
|
|
225918
|
-
|
|
225919
|
-
|
|
227102
|
+
const nextCompactionSettings = {
|
|
227103
|
+
...existing,
|
|
227104
|
+
model: existingModel || DEFAULT_SUMMARIZATION_MODEL,
|
|
227105
|
+
mode
|
|
227106
|
+
};
|
|
227107
|
+
await getBackend().updateAgent(agentId, {
|
|
227108
|
+
compaction_settings: nextCompactionSettings
|
|
225920
227109
|
});
|
|
227110
|
+
setAgentState((prev) => prev ? { ...prev, compaction_settings: nextCompactionSettings } : prev);
|
|
225921
227111
|
cmd.finish(`Updated compaction mode to: ${mode}`, true);
|
|
225922
227112
|
} catch (error51) {
|
|
225923
227113
|
const errorDetails = formatErrorDetails2(error51, agentId);
|
|
@@ -226069,9 +227259,8 @@ ${guidance}`);
|
|
|
226069
227259
|
if (action.conversationId === conversationId) {
|
|
226070
227260
|
cmd.finish("Already on this conversation", true);
|
|
226071
227261
|
} else {
|
|
226072
|
-
const client = await getClient();
|
|
226073
227262
|
if (agentState) {
|
|
226074
|
-
const resumeData = await
|
|
227263
|
+
const resumeData = await getResumeDataFromBackend2(agentState, action.conversationId);
|
|
226075
227264
|
setConversationIdAndRef(action.conversationId);
|
|
226076
227265
|
setConversationAutoTitleEligibility(false);
|
|
226077
227266
|
pendingConversationSwitchRef.current = {
|
|
@@ -227382,8 +228571,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
227382
228571
|
});
|
|
227383
228572
|
try {
|
|
227384
228573
|
if (agentState) {
|
|
227385
|
-
const
|
|
227386
|
-
const resumeData = await getResumeData(client, agentState, convId);
|
|
228574
|
+
const resumeData = await getResumeDataFromBackend2(agentState, convId);
|
|
227387
228575
|
setConversationIdAndRef(convId);
|
|
227388
228576
|
setConversationAutoTitleEligibility(false);
|
|
227389
228577
|
pendingConversationSwitchRef.current = {
|
|
@@ -227488,8 +228676,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
227488
228676
|
phase: "running"
|
|
227489
228677
|
});
|
|
227490
228678
|
try {
|
|
227491
|
-
const
|
|
227492
|
-
const conversation = await client.conversations.create({
|
|
228679
|
+
const conversation = await getBackend().createConversation({
|
|
227493
228680
|
agent_id: agentId,
|
|
227494
228681
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
227495
228682
|
});
|
|
@@ -227577,8 +228764,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
227577
228764
|
});
|
|
227578
228765
|
try {
|
|
227579
228766
|
if (agentState) {
|
|
227580
|
-
const
|
|
227581
|
-
const resumeData = await getResumeData(client, agentState, actualTargetConv);
|
|
228767
|
+
const resumeData = await getResumeDataFromBackend2(agentState, actualTargetConv);
|
|
227582
228768
|
setConversationIdAndRef(actualTargetConv);
|
|
227583
228769
|
setConversationAutoTitleEligibility(false);
|
|
227584
228770
|
pendingConversationSwitchRef.current = {
|
|
@@ -227734,9 +228920,10 @@ Open /mcp to attach or detach tools for this server.`, true);
|
|
|
227734
228920
|
phase: "running"
|
|
227735
228921
|
});
|
|
227736
228922
|
try {
|
|
227737
|
-
const client = await getClient();
|
|
227738
228923
|
if (newName && newName !== agentName) {
|
|
227739
|
-
await
|
|
228924
|
+
await getBackend().updateAgent(agentId, {
|
|
228925
|
+
name: newName
|
|
228926
|
+
});
|
|
227740
228927
|
updateAgentName(newName);
|
|
227741
228928
|
}
|
|
227742
228929
|
if (pinDialogLocal) {
|
|
@@ -227784,7 +228971,6 @@ var init_App2 = __esm(async () => {
|
|
|
227784
228971
|
init_backend2();
|
|
227785
228972
|
init_agents5();
|
|
227786
228973
|
init_client2();
|
|
227787
|
-
init_conversations2();
|
|
227788
228974
|
init_metadata();
|
|
227789
228975
|
init_constants();
|
|
227790
228976
|
init_manager();
|
|
@@ -229121,9 +230307,8 @@ async function hydrateMemfsSettingFromAgent2(agent) {
|
|
|
229121
230307
|
return enabled;
|
|
229122
230308
|
}
|
|
229123
230309
|
async function isMemfsEnabledOnServer2(agentId) {
|
|
229124
|
-
const {
|
|
229125
|
-
const
|
|
229126
|
-
const agent = await client.agents.retrieve(agentId, {
|
|
230310
|
+
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
230311
|
+
const agent = await getBackend2().retrieveAgent(agentId, {
|
|
229127
230312
|
include: ["agent.tags"]
|
|
229128
230313
|
});
|
|
229129
230314
|
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -229256,7 +230441,8 @@ async function applyMemfsFlags2(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
229256
230441
|
const backend4 = getBackend2();
|
|
229257
230442
|
if (backend4.capabilities.localMemfs) {
|
|
229258
230443
|
if (noMemfsFlag) {
|
|
229259
|
-
|
|
230444
|
+
settingsManager3.setMemfsEnabled(agentId, false);
|
|
230445
|
+
return { action: "disabled" };
|
|
229260
230446
|
}
|
|
229261
230447
|
const memoryDir = getScopedMemoryFilesystemRoot2(agentId);
|
|
229262
230448
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -229433,7 +230619,7 @@ async function initSecretsFromServer2(agentId, cachedAgent) {
|
|
|
229433
230619
|
setCache2(agentId, {});
|
|
229434
230620
|
return;
|
|
229435
230621
|
}
|
|
229436
|
-
const agent = cachedAgent ?? await (
|
|
230622
|
+
const agent = cachedAgent ?? await getBackend().retrieveAgent(agentId, {
|
|
229437
230623
|
include: ["agent.secrets"]
|
|
229438
230624
|
});
|
|
229439
230625
|
const secrets2 = {};
|
|
@@ -229466,6 +230652,9 @@ async function refreshAndListSecrets2(agentIdArg) {
|
|
|
229466
230652
|
return Object.keys(cache5).sort().map((key) => ({ key, value: cache5[key] ?? "" }));
|
|
229467
230653
|
}
|
|
229468
230654
|
async function applySecretBatch2(options, agentIdArg) {
|
|
230655
|
+
if (!getBackend().capabilities.serverSecrets) {
|
|
230656
|
+
throw new Error("Agent secrets are not supported by this backend yet");
|
|
230657
|
+
}
|
|
229469
230658
|
const agentId = resolveSecretsAgentId2(agentIdArg);
|
|
229470
230659
|
if (!agentId) {
|
|
229471
230660
|
throw new Error("No agent context set. Agent ID is required.");
|
|
@@ -229477,8 +230666,7 @@ async function applySecretBatch2(options, agentIdArg) {
|
|
|
229477
230666
|
for (const rawKey of options.unset ?? []) {
|
|
229478
230667
|
delete next[rawKey.toUpperCase()];
|
|
229479
230668
|
}
|
|
229480
|
-
|
|
229481
|
-
await client.agents.update(agentId, { secrets: next });
|
|
230669
|
+
await getBackend().updateAgent(agentId, { secrets: next });
|
|
229482
230670
|
setCache2(agentId, next);
|
|
229483
230671
|
return Object.keys(next).sort();
|
|
229484
230672
|
}
|
|
@@ -229486,14 +230674,13 @@ async function setSecretOnServer2(key, value, agentIdArg) {
|
|
|
229486
230674
|
if (!getBackend().capabilities.serverSecrets) {
|
|
229487
230675
|
throw new Error("Agent secrets are not supported by this backend yet");
|
|
229488
230676
|
}
|
|
229489
|
-
const client = await getClient();
|
|
229490
230677
|
const agentId = resolveSecretsAgentId2(agentIdArg);
|
|
229491
230678
|
if (!agentId) {
|
|
229492
230679
|
throw new Error("No agent context set. Agent ID is required.");
|
|
229493
230680
|
}
|
|
229494
230681
|
const secrets2 = { ...loadSecrets2(agentId) };
|
|
229495
230682
|
secrets2[key] = value;
|
|
229496
|
-
await
|
|
230683
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
229497
230684
|
setCache2(agentId, secrets2);
|
|
229498
230685
|
}
|
|
229499
230686
|
async function deleteSecretOnServer2(key, agentIdArg) {
|
|
@@ -229509,8 +230696,7 @@ async function deleteSecretOnServer2(key, agentIdArg) {
|
|
|
229509
230696
|
return false;
|
|
229510
230697
|
}
|
|
229511
230698
|
delete secrets2[key];
|
|
229512
|
-
|
|
229513
|
-
await client.agents.update(agentId, { secrets: secrets2 });
|
|
230699
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
229514
230700
|
setCache2(agentId, secrets2);
|
|
229515
230701
|
return true;
|
|
229516
230702
|
}
|
|
@@ -229526,7 +230712,6 @@ var SECRETS_CACHE_KEY2;
|
|
|
229526
230712
|
var init_secretsStore2 = __esm(() => {
|
|
229527
230713
|
init_context();
|
|
229528
230714
|
init_backend2();
|
|
229529
|
-
init_client2();
|
|
229530
230715
|
SECRETS_CACHE_KEY2 = Symbol.for("@letta/secretsCache");
|
|
229531
230716
|
});
|
|
229532
230717
|
|
|
@@ -230059,6 +231244,9 @@ init_available_models();
|
|
|
230059
231244
|
function supportsDistinctAnthropicXHighEffort2(modelHandle) {
|
|
230060
231245
|
return modelHandle.includes("claude-opus-4-7");
|
|
230061
231246
|
}
|
|
231247
|
+
function isRecord10(value) {
|
|
231248
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
231249
|
+
}
|
|
230062
231250
|
function buildModelSettings2(modelHandle, updateArgs) {
|
|
230063
231251
|
const isOpenAI = modelHandle.startsWith("openai/") || modelHandle.startsWith(`${OPENAI_CODEX_PROVIDER_NAME}/`);
|
|
230064
231252
|
const isAnthropic = modelHandle.startsWith("anthropic/") || modelHandle.startsWith("claude-pro-max/") || modelHandle.startsWith("minimax/");
|
|
@@ -230181,6 +231369,12 @@ function buildModelSettings2(modelHandle, updateArgs) {
|
|
|
230181
231369
|
if (typeof updateArgs?.max_output_tokens === "number" && "provider_type" in settings) {
|
|
230182
231370
|
settings.max_output_tokens = updateArgs.max_output_tokens;
|
|
230183
231371
|
}
|
|
231372
|
+
if (isRecord10(updateArgs?.modalities)) {
|
|
231373
|
+
settings.modalities = updateArgs.modalities;
|
|
231374
|
+
}
|
|
231375
|
+
if (isRecord10(updateArgs?.capabilities)) {
|
|
231376
|
+
settings.capabilities = updateArgs.capabilities;
|
|
231377
|
+
}
|
|
230184
231378
|
return settings;
|
|
230185
231379
|
}
|
|
230186
231380
|
async function updateAgentLLMConfig2(agentId, modelHandle, updateArgs, options) {
|
|
@@ -230504,6 +231698,15 @@ async function getBillingTier2() {
|
|
|
230504
231698
|
}
|
|
230505
231699
|
}
|
|
230506
231700
|
|
|
231701
|
+
// src/backend/local/paths.ts
|
|
231702
|
+
var LOCAL_BACKEND_NO_MEMFS_ENV2 = "LETTA_LOCAL_BACKEND_NO_MEMFS";
|
|
231703
|
+
function isTruthyEnv3(value) {
|
|
231704
|
+
return value === "1" || value?.toLowerCase() === "true";
|
|
231705
|
+
}
|
|
231706
|
+
function isLocalBackendNoMemfsEnvEnabled2(env = process.env) {
|
|
231707
|
+
return isTruthyEnv3(env[LOCAL_BACKEND_NO_MEMFS_ENV2]);
|
|
231708
|
+
}
|
|
231709
|
+
|
|
230507
231710
|
// src/cli/args.ts
|
|
230508
231711
|
import { parseArgs } from "node:util";
|
|
230509
231712
|
var CLI_FLAG_CATALOG = {
|
|
@@ -232841,7 +234044,7 @@ function validateRegistryHandleOrThrow(handle) {
|
|
|
232841
234044
|
// src/cli/subcommands/agents.ts
|
|
232842
234045
|
init_create();
|
|
232843
234046
|
init_personality();
|
|
232844
|
-
|
|
234047
|
+
init_backend2();
|
|
232845
234048
|
init_settings_manager();
|
|
232846
234049
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
232847
234050
|
function printUsage() {
|
|
@@ -232975,8 +234178,7 @@ async function runCreateAction(values) {
|
|
|
232975
234178
|
if (values.pinned) {
|
|
232976
234179
|
settingsManager.pinGlobal(agentId);
|
|
232977
234180
|
}
|
|
232978
|
-
const
|
|
232979
|
-
const updatedAgent = await client.agents.retrieve(agentId);
|
|
234181
|
+
const updatedAgent = await getBackend().retrieveAgent(agentId);
|
|
232980
234182
|
console.log(JSON.stringify(updatedAgent, null, 2));
|
|
232981
234183
|
return 0;
|
|
232982
234184
|
} catch (error51) {
|
|
@@ -233006,8 +234208,7 @@ async function runListAction(values) {
|
|
|
233006
234208
|
params.include = ["agent.blocks"];
|
|
233007
234209
|
}
|
|
233008
234210
|
try {
|
|
233009
|
-
const
|
|
233010
|
-
const result = await client.agents.list(params);
|
|
234211
|
+
const result = await getBackend().listAgents(params);
|
|
233011
234212
|
console.log(JSON.stringify(result, null, 2));
|
|
233012
234213
|
return 0;
|
|
233013
234214
|
} catch (error51) {
|
|
@@ -233016,234 +234217,6 @@ async function runListAction(values) {
|
|
|
233016
234217
|
}
|
|
233017
234218
|
}
|
|
233018
234219
|
|
|
233019
|
-
// src/cli/subcommands/blocks.ts
|
|
233020
|
-
init_client2();
|
|
233021
|
-
init_settings_manager();
|
|
233022
|
-
import { parseArgs as parseArgs3 } from "node:util";
|
|
233023
|
-
function printUsage2() {
|
|
233024
|
-
console.log(`
|
|
233025
|
-
Usage:
|
|
233026
|
-
letta blocks list --agent <id> [--limit <n>]
|
|
233027
|
-
letta blocks copy --block-id <id> [--label <new-label>] [--agent <id>] [--override]
|
|
233028
|
-
letta blocks attach --block-id <id> [--agent <id>] [--read-only] [--override]
|
|
233029
|
-
|
|
233030
|
-
Notes:
|
|
233031
|
-
- Output is JSON only.
|
|
233032
|
-
- Uses CLI auth; override with LETTA_API_KEY/LETTA_BASE_URL if needed.
|
|
233033
|
-
- Default target agent for copy/attach is LETTA_AGENT_ID.
|
|
233034
|
-
`.trim());
|
|
233035
|
-
}
|
|
233036
|
-
function parseLimit2(value, fallback) {
|
|
233037
|
-
if (typeof value !== "string" || value.length === 0)
|
|
233038
|
-
return fallback;
|
|
233039
|
-
const parsed = Number.parseInt(value, 10);
|
|
233040
|
-
return Number.isNaN(parsed) ? fallback : parsed;
|
|
233041
|
-
}
|
|
233042
|
-
function getAgentId2(agentFromArgs, agentIdFromArgs) {
|
|
233043
|
-
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
233044
|
-
}
|
|
233045
|
-
var BLOCKS_OPTIONS = {
|
|
233046
|
-
help: { type: "boolean", short: "h" },
|
|
233047
|
-
agent: { type: "string" },
|
|
233048
|
-
"agent-id": { type: "string" },
|
|
233049
|
-
limit: { type: "string" },
|
|
233050
|
-
"block-id": { type: "string" },
|
|
233051
|
-
label: { type: "string" },
|
|
233052
|
-
override: { type: "boolean" },
|
|
233053
|
-
"read-only": { type: "boolean" }
|
|
233054
|
-
};
|
|
233055
|
-
function parseBlocksArgs(argv) {
|
|
233056
|
-
return parseArgs3({
|
|
233057
|
-
args: argv,
|
|
233058
|
-
options: BLOCKS_OPTIONS,
|
|
233059
|
-
strict: true,
|
|
233060
|
-
allowPositionals: true
|
|
233061
|
-
});
|
|
233062
|
-
}
|
|
233063
|
-
async function copyBlock(client, blockId, options) {
|
|
233064
|
-
const currentAgentId = getAgentId2(options?.targetAgentId);
|
|
233065
|
-
if (!currentAgentId) {
|
|
233066
|
-
throw new Error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
233067
|
-
}
|
|
233068
|
-
let detachedBlock;
|
|
233069
|
-
const sourceBlock = await client.blocks.retrieve(blockId);
|
|
233070
|
-
const targetLabel = options?.labelOverride || sourceBlock.label || "migrated-block";
|
|
233071
|
-
if (options?.override) {
|
|
233072
|
-
const currentBlocksResponse = await client.agents.blocks.list(currentAgentId);
|
|
233073
|
-
const currentBlocks = Array.isArray(currentBlocksResponse) ? currentBlocksResponse : currentBlocksResponse.items || [];
|
|
233074
|
-
const conflictingBlock = currentBlocks.find((b) => b.label === targetLabel);
|
|
233075
|
-
if (conflictingBlock) {
|
|
233076
|
-
console.error(`Detaching existing block with label "${targetLabel}" (${conflictingBlock.id})...`);
|
|
233077
|
-
detachedBlock = conflictingBlock;
|
|
233078
|
-
try {
|
|
233079
|
-
await client.agents.blocks.detach(conflictingBlock.id, {
|
|
233080
|
-
agent_id: currentAgentId
|
|
233081
|
-
});
|
|
233082
|
-
} catch (detachError) {
|
|
233083
|
-
throw new Error(`Failed to detach existing block "${targetLabel}": ${detachError instanceof Error ? detachError.message : String(detachError)}`);
|
|
233084
|
-
}
|
|
233085
|
-
}
|
|
233086
|
-
}
|
|
233087
|
-
let newBlock;
|
|
233088
|
-
try {
|
|
233089
|
-
newBlock = await client.blocks.create({
|
|
233090
|
-
label: targetLabel,
|
|
233091
|
-
value: sourceBlock.value,
|
|
233092
|
-
description: sourceBlock.description || undefined,
|
|
233093
|
-
limit: sourceBlock.limit
|
|
233094
|
-
});
|
|
233095
|
-
} catch (createError) {
|
|
233096
|
-
if (detachedBlock) {
|
|
233097
|
-
console.error(`Create failed, reattaching original block "${detachedBlock.label}"...`);
|
|
233098
|
-
try {
|
|
233099
|
-
await client.agents.blocks.attach(detachedBlock.id, {
|
|
233100
|
-
agent_id: currentAgentId
|
|
233101
|
-
});
|
|
233102
|
-
console.error("Original block reattached successfully.");
|
|
233103
|
-
} catch {
|
|
233104
|
-
console.error(`WARNING: Failed to reattach original block! Block ID: ${detachedBlock.id}`);
|
|
233105
|
-
}
|
|
233106
|
-
}
|
|
233107
|
-
throw createError;
|
|
233108
|
-
}
|
|
233109
|
-
let attachResult;
|
|
233110
|
-
try {
|
|
233111
|
-
attachResult = await client.agents.blocks.attach(newBlock.id, {
|
|
233112
|
-
agent_id: currentAgentId
|
|
233113
|
-
});
|
|
233114
|
-
} catch (attachError) {
|
|
233115
|
-
if (detachedBlock) {
|
|
233116
|
-
console.error(`Attach failed, reattaching original block "${detachedBlock.label}"...`);
|
|
233117
|
-
try {
|
|
233118
|
-
await client.agents.blocks.attach(detachedBlock.id, {
|
|
233119
|
-
agent_id: currentAgentId
|
|
233120
|
-
});
|
|
233121
|
-
console.error("Original block reattached successfully.");
|
|
233122
|
-
} catch {
|
|
233123
|
-
console.error(`WARNING: Failed to reattach original block! Block ID: ${detachedBlock.id}`);
|
|
233124
|
-
}
|
|
233125
|
-
}
|
|
233126
|
-
throw attachError;
|
|
233127
|
-
}
|
|
233128
|
-
return { sourceBlock, newBlock, attachResult, detachedBlock };
|
|
233129
|
-
}
|
|
233130
|
-
async function attachBlock(client, blockId, options) {
|
|
233131
|
-
const currentAgentId = getAgentId2(options?.targetAgentId);
|
|
233132
|
-
if (!currentAgentId) {
|
|
233133
|
-
throw new Error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
233134
|
-
}
|
|
233135
|
-
let detachedBlock;
|
|
233136
|
-
if (options?.override) {
|
|
233137
|
-
const sourceBlock = await client.blocks.retrieve(blockId);
|
|
233138
|
-
const sourceLabel = sourceBlock.label;
|
|
233139
|
-
const currentBlocksResponse = await client.agents.blocks.list(currentAgentId);
|
|
233140
|
-
const currentBlocks = Array.isArray(currentBlocksResponse) ? currentBlocksResponse : currentBlocksResponse.items || [];
|
|
233141
|
-
const conflictingBlock = currentBlocks.find((b) => b.label === sourceLabel);
|
|
233142
|
-
if (conflictingBlock) {
|
|
233143
|
-
console.error(`Detaching existing block with label "${sourceLabel}" (${conflictingBlock.id})...`);
|
|
233144
|
-
detachedBlock = conflictingBlock;
|
|
233145
|
-
try {
|
|
233146
|
-
await client.agents.blocks.detach(conflictingBlock.id, {
|
|
233147
|
-
agent_id: currentAgentId
|
|
233148
|
-
});
|
|
233149
|
-
} catch (detachError) {
|
|
233150
|
-
throw new Error(`Failed to detach existing block "${sourceLabel}": ${detachError instanceof Error ? detachError.message : String(detachError)}`);
|
|
233151
|
-
}
|
|
233152
|
-
}
|
|
233153
|
-
}
|
|
233154
|
-
let attachResult;
|
|
233155
|
-
try {
|
|
233156
|
-
attachResult = await client.agents.blocks.attach(blockId, {
|
|
233157
|
-
agent_id: currentAgentId
|
|
233158
|
-
});
|
|
233159
|
-
} catch (attachError) {
|
|
233160
|
-
if (detachedBlock) {
|
|
233161
|
-
console.error(`Attach failed, reattaching original block "${detachedBlock.label}"...`);
|
|
233162
|
-
try {
|
|
233163
|
-
await client.agents.blocks.attach(detachedBlock.id, {
|
|
233164
|
-
agent_id: currentAgentId
|
|
233165
|
-
});
|
|
233166
|
-
console.error("Original block reattached successfully.");
|
|
233167
|
-
} catch {
|
|
233168
|
-
console.error(`WARNING: Failed to reattach original block! Block ID: ${detachedBlock.id}`);
|
|
233169
|
-
}
|
|
233170
|
-
}
|
|
233171
|
-
throw attachError;
|
|
233172
|
-
}
|
|
233173
|
-
if (options?.readOnly) {
|
|
233174
|
-
console.warn("Note: read_only flag is set on the block itself, not per-agent. " + "Use the block update API to set read_only if needed.");
|
|
233175
|
-
}
|
|
233176
|
-
return { attachResult, detachedBlock };
|
|
233177
|
-
}
|
|
233178
|
-
async function runBlocksSubcommand(argv) {
|
|
233179
|
-
let parsed;
|
|
233180
|
-
try {
|
|
233181
|
-
parsed = parseBlocksArgs(argv);
|
|
233182
|
-
} catch (error51) {
|
|
233183
|
-
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
233184
|
-
console.error(`Error: ${message}`);
|
|
233185
|
-
printUsage2();
|
|
233186
|
-
return 1;
|
|
233187
|
-
}
|
|
233188
|
-
const [action] = parsed.positionals;
|
|
233189
|
-
if (parsed.values.help || !action || action === "help") {
|
|
233190
|
-
printUsage2();
|
|
233191
|
-
return 0;
|
|
233192
|
-
}
|
|
233193
|
-
try {
|
|
233194
|
-
await settingsManager.initialize();
|
|
233195
|
-
const client = await getClient();
|
|
233196
|
-
if (action === "list") {
|
|
233197
|
-
const agentId = parsed.values.agent || parsed.values["agent-id"] || "";
|
|
233198
|
-
if (!agentId || typeof agentId !== "string") {
|
|
233199
|
-
console.error("Missing required --agent <id>.");
|
|
233200
|
-
return 1;
|
|
233201
|
-
}
|
|
233202
|
-
const result = await client.agents.blocks.list(agentId, {
|
|
233203
|
-
limit: parseLimit2(parsed.values.limit, 1000)
|
|
233204
|
-
});
|
|
233205
|
-
console.log(JSON.stringify(result, null, 2));
|
|
233206
|
-
return 0;
|
|
233207
|
-
}
|
|
233208
|
-
if (action === "copy") {
|
|
233209
|
-
const blockId = parsed.values["block-id"];
|
|
233210
|
-
if (!blockId || typeof blockId !== "string") {
|
|
233211
|
-
console.error("Missing required --block-id <id>.");
|
|
233212
|
-
return 1;
|
|
233213
|
-
}
|
|
233214
|
-
const agentId = getAgentId2(parsed.values.agent, parsed.values["agent-id"]);
|
|
233215
|
-
const result = await copyBlock(client, blockId, {
|
|
233216
|
-
labelOverride: typeof parsed.values.label === "string" ? parsed.values.label : undefined,
|
|
233217
|
-
targetAgentId: agentId,
|
|
233218
|
-
override: parsed.values.override === true
|
|
233219
|
-
});
|
|
233220
|
-
console.log(JSON.stringify(result, null, 2));
|
|
233221
|
-
return 0;
|
|
233222
|
-
}
|
|
233223
|
-
if (action === "attach") {
|
|
233224
|
-
const blockId = parsed.values["block-id"];
|
|
233225
|
-
if (!blockId || typeof blockId !== "string") {
|
|
233226
|
-
console.error("Missing required --block-id <id>.");
|
|
233227
|
-
return 1;
|
|
233228
|
-
}
|
|
233229
|
-
const agentId = getAgentId2(parsed.values.agent, parsed.values["agent-id"]);
|
|
233230
|
-
const result = await attachBlock(client, blockId, {
|
|
233231
|
-
readOnly: parsed.values["read-only"] === true,
|
|
233232
|
-
override: parsed.values.override === true,
|
|
233233
|
-
targetAgentId: agentId
|
|
233234
|
-
});
|
|
233235
|
-
console.log(JSON.stringify(result, null, 2));
|
|
233236
|
-
return 0;
|
|
233237
|
-
}
|
|
233238
|
-
} catch (error51) {
|
|
233239
|
-
console.error(error51 instanceof Error ? error51.message : String(error51));
|
|
233240
|
-
return 1;
|
|
233241
|
-
}
|
|
233242
|
-
console.error(`Unknown action: ${action}`);
|
|
233243
|
-
printUsage2();
|
|
233244
|
-
return 1;
|
|
233245
|
-
}
|
|
233246
|
-
|
|
233247
234220
|
// src/cli/subcommands/channels.ts
|
|
233248
234221
|
init_accounts();
|
|
233249
234222
|
init_pairing();
|
|
@@ -233252,8 +234225,8 @@ init_registry();
|
|
|
233252
234225
|
init_routing();
|
|
233253
234226
|
init_runtimeDeps();
|
|
233254
234227
|
await init_service();
|
|
233255
|
-
import { parseArgs as
|
|
233256
|
-
function
|
|
234228
|
+
import { parseArgs as parseArgs3 } from "node:util";
|
|
234229
|
+
function printUsage2() {
|
|
233257
234230
|
console.log(`
|
|
233258
234231
|
Usage:
|
|
233259
234232
|
letta channels install <channel> Install channel runtime dependencies
|
|
@@ -233317,14 +234290,14 @@ var CHANNELS_OPTIONS = {
|
|
|
233317
234290
|
code: { type: "string" }
|
|
233318
234291
|
};
|
|
233319
234292
|
function parseChannelsArgs(argv) {
|
|
233320
|
-
return
|
|
234293
|
+
return parseArgs3({
|
|
233321
234294
|
args: argv,
|
|
233322
234295
|
options: CHANNELS_OPTIONS,
|
|
233323
234296
|
strict: true,
|
|
233324
234297
|
allowPositionals: true
|
|
233325
234298
|
});
|
|
233326
234299
|
}
|
|
233327
|
-
function
|
|
234300
|
+
function getAgentId2(fromArgs) {
|
|
233328
234301
|
return fromArgs || process.env.LETTA_AGENT_ID || "";
|
|
233329
234302
|
}
|
|
233330
234303
|
function getConversationId2(fromArgs) {
|
|
@@ -233461,7 +234434,7 @@ function handleRouteAdd(values) {
|
|
|
233461
234434
|
const channelId = values.channel;
|
|
233462
234435
|
const accountId = values["account-id"];
|
|
233463
234436
|
const chatId = values["chat-id"];
|
|
233464
|
-
const agentId =
|
|
234437
|
+
const agentId = getAgentId2(values.agent);
|
|
233465
234438
|
const conversationId = getConversationId2(values.conversation);
|
|
233466
234439
|
if (!channelId) {
|
|
233467
234440
|
console.error("Error: --channel is required.");
|
|
@@ -233549,7 +234522,7 @@ async function handlePair(values) {
|
|
|
233549
234522
|
const channelId = values.channel;
|
|
233550
234523
|
const accountId = values["account-id"];
|
|
233551
234524
|
const code = values.code;
|
|
233552
|
-
const agentId =
|
|
234525
|
+
const agentId = getAgentId2(values.agent);
|
|
233553
234526
|
const conversationId = getConversationId2(values.conversation);
|
|
233554
234527
|
if (!channelId) {
|
|
233555
234528
|
console.error("Error: --channel is required.");
|
|
@@ -233580,7 +234553,7 @@ async function handlePair(values) {
|
|
|
233580
234553
|
function handleBind(values) {
|
|
233581
234554
|
const channelId = values.channel;
|
|
233582
234555
|
const accountId = values["account-id"];
|
|
233583
|
-
const agentId =
|
|
234556
|
+
const agentId = getAgentId2(values.agent);
|
|
233584
234557
|
if (!channelId) {
|
|
233585
234558
|
console.error("Error: --channel is required.");
|
|
233586
234559
|
return 1;
|
|
@@ -233620,7 +234593,7 @@ function handleBind(values) {
|
|
|
233620
234593
|
async function runChannelsSubcommand(argv) {
|
|
233621
234594
|
const { values, positionals } = parseChannelsArgs(argv);
|
|
233622
234595
|
if (values.help) {
|
|
233623
|
-
|
|
234596
|
+
printUsage2();
|
|
233624
234597
|
return 0;
|
|
233625
234598
|
}
|
|
233626
234599
|
const [action, ...rest] = positionals;
|
|
@@ -233663,7 +234636,7 @@ async function runChannelsSubcommand(argv) {
|
|
|
233663
234636
|
return await handlePair(values);
|
|
233664
234637
|
default:
|
|
233665
234638
|
if (!action) {
|
|
233666
|
-
|
|
234639
|
+
printUsage2();
|
|
233667
234640
|
return 0;
|
|
233668
234641
|
}
|
|
233669
234642
|
console.error(`Unknown channels action: "${action}". Use: install, configure, status, route, bind, pair`);
|
|
@@ -233678,7 +234651,7 @@ init_connect_normalize();
|
|
|
233678
234651
|
init_connect_oauth_core();
|
|
233679
234652
|
import { createInterface as createInterface4 } from "node:readline/promises";
|
|
233680
234653
|
import { Writable } from "node:stream";
|
|
233681
|
-
import { parseArgs as
|
|
234654
|
+
import { parseArgs as parseArgs4 } from "node:util";
|
|
233682
234655
|
var CONNECT_OPTIONS = {
|
|
233683
234656
|
help: { type: "boolean", short: "h" },
|
|
233684
234657
|
"api-key": { type: "string" },
|
|
@@ -233769,7 +234742,7 @@ async function runConnectSubcommand(argv, deps = {}) {
|
|
|
233769
234742
|
const io = { ...DEFAULT_DEPS2, ...deps };
|
|
233770
234743
|
let parsed;
|
|
233771
234744
|
try {
|
|
233772
|
-
parsed =
|
|
234745
|
+
parsed = parseArgs4({
|
|
233773
234746
|
args: argv,
|
|
233774
234747
|
options: CONNECT_OPTIONS,
|
|
233775
234748
|
strict: true,
|
|
@@ -233878,8 +234851,8 @@ async function runConnectSubcommand(argv, deps = {}) {
|
|
|
233878
234851
|
|
|
233879
234852
|
// src/cli/subcommands/cron.ts
|
|
233880
234853
|
init_cron();
|
|
233881
|
-
import { parseArgs as
|
|
233882
|
-
function
|
|
234854
|
+
import { parseArgs as parseArgs5 } from "node:util";
|
|
234855
|
+
function printUsage3() {
|
|
233883
234856
|
console.log(`
|
|
233884
234857
|
Usage:
|
|
233885
234858
|
letta cron add --prompt <text> --every <interval> [options]
|
|
@@ -233923,14 +234896,14 @@ var CRON_OPTIONS = {
|
|
|
233923
234896
|
all: { type: "boolean" }
|
|
233924
234897
|
};
|
|
233925
234898
|
function parseCronArgs(argv) {
|
|
233926
|
-
return
|
|
234899
|
+
return parseArgs5({
|
|
233927
234900
|
args: argv,
|
|
233928
234901
|
options: CRON_OPTIONS,
|
|
233929
234902
|
strict: true,
|
|
233930
234903
|
allowPositionals: true
|
|
233931
234904
|
});
|
|
233932
234905
|
}
|
|
233933
|
-
function
|
|
234906
|
+
function getAgentId3(fromArgs) {
|
|
233934
234907
|
return fromArgs || process.env.LETTA_AGENT_ID || "";
|
|
233935
234908
|
}
|
|
233936
234909
|
function getConversationId3(fromArgs) {
|
|
@@ -233952,7 +234925,7 @@ function handleAdd(values) {
|
|
|
233952
234925
|
console.error("Error: --prompt is required.");
|
|
233953
234926
|
return 1;
|
|
233954
234927
|
}
|
|
233955
|
-
const agentId =
|
|
234928
|
+
const agentId = getAgentId3(values.agent);
|
|
233956
234929
|
if (!agentId) {
|
|
233957
234930
|
console.error("Error: --agent or LETTA_AGENT_ID required.");
|
|
233958
234931
|
return 1;
|
|
@@ -234073,7 +235046,7 @@ function handleGet(positionals) {
|
|
|
234073
235046
|
}
|
|
234074
235047
|
function handleDelete(values, positionals) {
|
|
234075
235048
|
if (values.all) {
|
|
234076
|
-
const agentId =
|
|
235049
|
+
const agentId = getAgentId3(values.agent);
|
|
234077
235050
|
if (!agentId) {
|
|
234078
235051
|
console.error("Error: --agent or LETTA_AGENT_ID required with --all.");
|
|
234079
235052
|
return 1;
|
|
@@ -234101,12 +235074,12 @@ async function runCronSubcommand(argv) {
|
|
|
234101
235074
|
parsed = parseCronArgs(argv);
|
|
234102
235075
|
} catch (err) {
|
|
234103
235076
|
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
234104
|
-
|
|
235077
|
+
printUsage3();
|
|
234105
235078
|
return 1;
|
|
234106
235079
|
}
|
|
234107
235080
|
const [action] = parsed.positionals;
|
|
234108
235081
|
if (parsed.values.help || !action || action === "help") {
|
|
234109
|
-
|
|
235082
|
+
printUsage3();
|
|
234110
235083
|
return 0;
|
|
234111
235084
|
}
|
|
234112
235085
|
switch (action) {
|
|
@@ -234120,7 +235093,7 @@ async function runCronSubcommand(argv) {
|
|
|
234120
235093
|
return handleDelete(parsed.values, parsed.positionals);
|
|
234121
235094
|
default:
|
|
234122
235095
|
console.error(`Unknown action: ${action}`);
|
|
234123
|
-
|
|
235096
|
+
printUsage3();
|
|
234124
235097
|
return 1;
|
|
234125
235098
|
}
|
|
234126
235099
|
}
|
|
@@ -234135,7 +235108,7 @@ await __promiseAll([
|
|
|
234135
235108
|
]);
|
|
234136
235109
|
var import_react30 = __toESM(require_react(), 1);
|
|
234137
235110
|
import { hostname as hostname4 } from "node:os";
|
|
234138
|
-
import { parseArgs as
|
|
235111
|
+
import { parseArgs as parseArgs6 } from "node:util";
|
|
234139
235112
|
|
|
234140
235113
|
// src/websocket/listen-log.ts
|
|
234141
235114
|
import {
|
|
@@ -234454,7 +235427,7 @@ async function resolveListenerRegistrationOptions(deviceId, connectionName) {
|
|
|
234454
235427
|
};
|
|
234455
235428
|
}
|
|
234456
235429
|
async function runListenSubcommand(argv) {
|
|
234457
|
-
const { values } =
|
|
235430
|
+
const { values } = parseArgs6({
|
|
234458
235431
|
args: argv,
|
|
234459
235432
|
options: {
|
|
234460
235433
|
"env-name": { type: "string" },
|
|
@@ -234790,7 +235763,7 @@ import { cpSync, existsSync as existsSync35, mkdirSync as mkdirSync25, rmSync as
|
|
|
234790
235763
|
import { readdir as readdir7 } from "node:fs/promises";
|
|
234791
235764
|
import { homedir as homedir26 } from "node:os";
|
|
234792
235765
|
import { join as join38 } from "node:path";
|
|
234793
|
-
import { parseArgs as
|
|
235766
|
+
import { parseArgs as parseArgs7 } from "node:util";
|
|
234794
235767
|
|
|
234795
235768
|
// src/cli/subcommands/memoryTokens.ts
|
|
234796
235769
|
init_systemPromptSize();
|
|
@@ -234871,7 +235844,7 @@ async function runMemoryTokensAction(options) {
|
|
|
234871
235844
|
}
|
|
234872
235845
|
|
|
234873
235846
|
// src/cli/subcommands/memory.ts
|
|
234874
|
-
function
|
|
235847
|
+
function printUsage4() {
|
|
234875
235848
|
console.log(`
|
|
234876
235849
|
Usage:
|
|
234877
235850
|
letta memory status [--agent <id>]
|
|
@@ -234900,7 +235873,7 @@ Examples:
|
|
|
234900
235873
|
letta memory tokens --memory-dir ~/.letta/agents/agent-123/memory --format json
|
|
234901
235874
|
`.trim());
|
|
234902
235875
|
}
|
|
234903
|
-
function
|
|
235876
|
+
function getAgentId4(agentFromArgs, agentIdFromArgs) {
|
|
234904
235877
|
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
234905
235878
|
}
|
|
234906
235879
|
var MEMORY_OPTIONS = {
|
|
@@ -234916,7 +235889,7 @@ var MEMORY_OPTIONS = {
|
|
|
234916
235889
|
quiet: { type: "boolean" }
|
|
234917
235890
|
};
|
|
234918
235891
|
function parseMemoryArgs(argv) {
|
|
234919
|
-
return
|
|
235892
|
+
return parseArgs7({
|
|
234920
235893
|
args: argv,
|
|
234921
235894
|
options: MEMORY_OPTIONS,
|
|
234922
235895
|
strict: true,
|
|
@@ -234977,15 +235950,15 @@ async function runMemorySubcommand(argv) {
|
|
|
234977
235950
|
} catch (error51) {
|
|
234978
235951
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
234979
235952
|
console.error(`Error: ${message}`);
|
|
234980
|
-
|
|
235953
|
+
printUsage4();
|
|
234981
235954
|
return 1;
|
|
234982
235955
|
}
|
|
234983
235956
|
const [action] = parsed.positionals;
|
|
234984
235957
|
if (parsed.values.help || !action || action === "help") {
|
|
234985
|
-
|
|
235958
|
+
printUsage4();
|
|
234986
235959
|
return 0;
|
|
234987
235960
|
}
|
|
234988
|
-
const agentId =
|
|
235961
|
+
const agentId = getAgentId4(parsed.values.agent, parsed.values["agent-id"]);
|
|
234989
235962
|
if (action === "tokens") {
|
|
234990
235963
|
return runMemoryTokensAction({
|
|
234991
235964
|
memoryDir: parsed.values["memory-dir"],
|
|
@@ -235118,17 +236091,18 @@ async function runMemorySubcommand(argv) {
|
|
|
235118
236091
|
return 1;
|
|
235119
236092
|
}
|
|
235120
236093
|
console.error(`Unknown action: ${action}`);
|
|
235121
|
-
|
|
236094
|
+
printUsage4();
|
|
235122
236095
|
return 1;
|
|
235123
236096
|
}
|
|
235124
236097
|
|
|
235125
236098
|
// src/cli/subcommands/messages.ts
|
|
235126
|
-
|
|
236099
|
+
init_backend2();
|
|
236100
|
+
init_messageSearch();
|
|
235127
236101
|
init_settings_manager();
|
|
235128
236102
|
import { writeFile as writeFile11 } from "node:fs/promises";
|
|
235129
236103
|
import { resolve as resolve33 } from "node:path";
|
|
235130
|
-
import { parseArgs as
|
|
235131
|
-
function
|
|
236104
|
+
import { parseArgs as parseArgs8 } from "node:util";
|
|
236105
|
+
function printUsage5() {
|
|
235132
236106
|
console.log(`
|
|
235133
236107
|
Usage:
|
|
235134
236108
|
letta messages search --query <text> [options]
|
|
@@ -235171,7 +236145,7 @@ Notes:
|
|
|
235171
236145
|
- For agent-to-agent messaging, use: letta -p --from-agent <sender-id> --agent <target-id> "message"
|
|
235172
236146
|
`.trim());
|
|
235173
236147
|
}
|
|
235174
|
-
function
|
|
236148
|
+
function parseLimit2(value, fallback) {
|
|
235175
236149
|
if (typeof value !== "string" || value.length === 0)
|
|
235176
236150
|
return fallback;
|
|
235177
236151
|
const parsed = Number.parseInt(value, 10);
|
|
@@ -235191,9 +236165,23 @@ function parseOrder(value) {
|
|
|
235191
236165
|
}
|
|
235192
236166
|
return;
|
|
235193
236167
|
}
|
|
235194
|
-
function
|
|
236168
|
+
function getAgentId5(agentFromArgs, agentIdFromArgs) {
|
|
235195
236169
|
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
235196
236170
|
}
|
|
236171
|
+
function pageItems2(page) {
|
|
236172
|
+
if (Array.isArray(page))
|
|
236173
|
+
return page;
|
|
236174
|
+
if (page && typeof page === "object") {
|
|
236175
|
+
const maybePage = page;
|
|
236176
|
+
if (typeof maybePage.getPaginatedItems === "function") {
|
|
236177
|
+
return maybePage.getPaginatedItems();
|
|
236178
|
+
}
|
|
236179
|
+
if (Array.isArray(maybePage.items)) {
|
|
236180
|
+
return maybePage.items;
|
|
236181
|
+
}
|
|
236182
|
+
}
|
|
236183
|
+
return [];
|
|
236184
|
+
}
|
|
235197
236185
|
var MESSAGES_OPTIONS = {
|
|
235198
236186
|
help: { type: "boolean", short: "h" },
|
|
235199
236187
|
query: { type: "string" },
|
|
@@ -235214,7 +236202,7 @@ var MESSAGES_OPTIONS = {
|
|
|
235214
236202
|
output: { type: "string" }
|
|
235215
236203
|
};
|
|
235216
236204
|
function parseMessagesArgs(argv) {
|
|
235217
|
-
return
|
|
236205
|
+
return parseArgs8({
|
|
235218
236206
|
args: argv,
|
|
235219
236207
|
options: MESSAGES_OPTIONS,
|
|
235220
236208
|
strict: true,
|
|
@@ -235228,17 +236216,17 @@ async function runMessagesSubcommand(argv) {
|
|
|
235228
236216
|
} catch (error51) {
|
|
235229
236217
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
235230
236218
|
console.error(`Error: ${message}`);
|
|
235231
|
-
|
|
236219
|
+
printUsage5();
|
|
235232
236220
|
return 1;
|
|
235233
236221
|
}
|
|
235234
236222
|
const [action] = parsed.positionals;
|
|
235235
236223
|
if (parsed.values.help || !action || action === "help") {
|
|
235236
|
-
|
|
236224
|
+
printUsage5();
|
|
235237
236225
|
return 0;
|
|
235238
236226
|
}
|
|
235239
236227
|
try {
|
|
235240
236228
|
await settingsManager.initialize();
|
|
235241
|
-
const
|
|
236229
|
+
const backend4 = getBackend();
|
|
235242
236230
|
const renderText = (value) => {
|
|
235243
236231
|
if (typeof value === "string")
|
|
235244
236232
|
return value;
|
|
@@ -235322,13 +236310,13 @@ async function runMessagesSubcommand(argv) {
|
|
|
235322
236310
|
const seenIds = new Set;
|
|
235323
236311
|
let cursorBefore;
|
|
235324
236312
|
for (let pageIndex = 0;pageIndex < maxPages; pageIndex += 1) {
|
|
235325
|
-
const page = await
|
|
236313
|
+
const page = await backend4.listConversationMessages(conversationId, {
|
|
235326
236314
|
limit: pageLimit,
|
|
235327
236315
|
order: "desc",
|
|
235328
236316
|
...conversationId === "default" && agentIdForDefault ? { agent_id: agentIdForDefault } : {},
|
|
235329
236317
|
...cursorBefore ? { before: cursorBefore } : {}
|
|
235330
236318
|
});
|
|
235331
|
-
const items = page
|
|
236319
|
+
const items = pageItems2(page);
|
|
235332
236320
|
if (items.length === 0) {
|
|
235333
236321
|
break;
|
|
235334
236322
|
}
|
|
@@ -235355,24 +236343,24 @@ async function runMessagesSubcommand(argv) {
|
|
|
235355
236343
|
return 1;
|
|
235356
236344
|
}
|
|
235357
236345
|
const allAgents = parsed.values["all-agents"] ?? false;
|
|
235358
|
-
const agentId =
|
|
236346
|
+
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
235359
236347
|
if (!allAgents && !agentId) {
|
|
235360
236348
|
console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
235361
236349
|
return 1;
|
|
235362
236350
|
}
|
|
235363
|
-
const result = await
|
|
236351
|
+
const result = await searchMessagesForBackend({
|
|
235364
236352
|
query,
|
|
235365
236353
|
agent_id: allAgents ? undefined : agentId,
|
|
235366
236354
|
search_mode: parseMode(parsed.values.mode) ?? "hybrid",
|
|
235367
236355
|
start_date: parsed.values["start-date"],
|
|
235368
236356
|
end_date: parsed.values["end-date"],
|
|
235369
|
-
limit:
|
|
236357
|
+
limit: parseLimit2(parsed.values.limit, 10)
|
|
235370
236358
|
});
|
|
235371
236359
|
console.log(JSON.stringify(result, null, 2));
|
|
235372
236360
|
return 0;
|
|
235373
236361
|
}
|
|
235374
236362
|
if (action === "list") {
|
|
235375
|
-
const agentId =
|
|
236363
|
+
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
235376
236364
|
if (!agentId) {
|
|
235377
236365
|
console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
235378
236366
|
return 1;
|
|
@@ -235383,14 +236371,14 @@ async function runMessagesSubcommand(argv) {
|
|
|
235383
236371
|
console.error(`Invalid --order "${orderRaw}". Use "asc" or "desc".`);
|
|
235384
236372
|
return 1;
|
|
235385
236373
|
}
|
|
235386
|
-
const response = await
|
|
236374
|
+
const response = await backend4.listAgentMessages(agentId, {
|
|
235387
236375
|
conversation_id: "default",
|
|
235388
|
-
limit:
|
|
236376
|
+
limit: parseLimit2(parsed.values.limit, 20),
|
|
235389
236377
|
after: parsed.values.after,
|
|
235390
236378
|
before: parsed.values.before,
|
|
235391
236379
|
order
|
|
235392
236380
|
});
|
|
235393
|
-
const messages = response
|
|
236381
|
+
const messages = pageItems2(response);
|
|
235394
236382
|
const startDate = parsed.values["start-date"];
|
|
235395
236383
|
const endDate = parsed.values["end-date"];
|
|
235396
236384
|
let filtered = messages;
|
|
@@ -235418,13 +236406,13 @@ async function runMessagesSubcommand(argv) {
|
|
|
235418
236406
|
console.error("Missing conversation id. Pass --conversation <id> or --conversation-id <id>.");
|
|
235419
236407
|
return 1;
|
|
235420
236408
|
}
|
|
235421
|
-
const agentId =
|
|
236409
|
+
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
235422
236410
|
if (conversationId === "default" && !agentId) {
|
|
235423
236411
|
console.error('Conversation "default" requires an agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.');
|
|
235424
236412
|
return 1;
|
|
235425
236413
|
}
|
|
235426
|
-
const pageLimit = Math.max(1,
|
|
235427
|
-
const maxPages = Math.max(1,
|
|
236414
|
+
const pageLimit = Math.max(1, parseLimit2(parsed.values.limit, 100));
|
|
236415
|
+
const maxPages = Math.max(1, parseLimit2(parsed.values["max-pages"], 200));
|
|
235428
236416
|
const outputPathRaw = parsed.values.out || parsed.values.output;
|
|
235429
236417
|
const messages = await fetchConversationMessages(conversationId, agentId || undefined, pageLimit, maxPages);
|
|
235430
236418
|
const transcript = messages.flatMap((msg) => formatEntry(msg)).join(`
|
|
@@ -235455,7 +236443,7 @@ async function runMessagesSubcommand(argv) {
|
|
|
235455
236443
|
return 1;
|
|
235456
236444
|
}
|
|
235457
236445
|
console.error(`Unknown action: ${action}`);
|
|
235458
|
-
|
|
236446
|
+
printUsage5();
|
|
235459
236447
|
return 1;
|
|
235460
236448
|
}
|
|
235461
236449
|
|
|
@@ -235473,8 +236461,6 @@ async function runSubcommand(argv) {
|
|
|
235473
236461
|
return runAgentsSubcommand(rest);
|
|
235474
236462
|
case "messages":
|
|
235475
236463
|
return runMessagesSubcommand(rest);
|
|
235476
|
-
case "blocks":
|
|
235477
|
-
return runBlocksSubcommand(rest);
|
|
235478
236464
|
case "server":
|
|
235479
236465
|
case "remote":
|
|
235480
236466
|
return runListenSubcommand(rest);
|
|
@@ -237695,7 +238681,6 @@ USAGE
|
|
|
237695
238681
|
letta memory ... Memory filesystem subcommands
|
|
237696
238682
|
letta agents ... Agents subcommands (JSON-only)
|
|
237697
238683
|
letta messages ... Messages subcommands (JSON-only)
|
|
237698
|
-
letta blocks ... Blocks subcommands (JSON-only)
|
|
237699
238684
|
letta connect ... Connect providers from terminal
|
|
237700
238685
|
|
|
237701
238686
|
OPTIONS
|
|
@@ -237715,9 +238700,6 @@ SUBCOMMANDS
|
|
|
237715
238700
|
letta messages search --query <text> [--all-agents]
|
|
237716
238701
|
letta messages list [--agent <id>]
|
|
237717
238702
|
letta messages transcript --conversation <id> [--out <path>]
|
|
237718
|
-
letta blocks list --agent <id>
|
|
237719
|
-
letta blocks copy --block-id <id> [--label <label>] [--agent <id>] [--override]
|
|
237720
|
-
letta blocks attach --block-id <id> [--agent <id>] [--read-only] [--override]
|
|
237721
238703
|
letta connect <provider> [options]
|
|
237722
238704
|
|
|
237723
238705
|
BEHAVIOR
|
|
@@ -238006,8 +238988,13 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
238006
238988
|
const skillsDirectory = values.skills ?? undefined;
|
|
238007
238989
|
const memfsFlag = values.memfs;
|
|
238008
238990
|
const noMemfsFlag = values["no-memfs"];
|
|
238009
|
-
const
|
|
238010
|
-
const
|
|
238991
|
+
const startupBackend = getBackend();
|
|
238992
|
+
const localNoMemfsRequested = Boolean(startupBackend.capabilities.localMemfs && (noMemfsFlag || isLocalBackendNoMemfsEnvEnabled2()));
|
|
238993
|
+
if (localNoMemfsRequested) {
|
|
238994
|
+
process.env[LOCAL_BACKEND_NO_MEMFS_ENV2] = "1";
|
|
238995
|
+
}
|
|
238996
|
+
const requestedMemoryPromptMode = memfsFlag ? "memfs" : noMemfsFlag || localNoMemfsRequested ? "standard" : undefined;
|
|
238997
|
+
const shouldAutoEnableMemfsForNewAgent = !memfsFlag && !noMemfsFlag && !localNoMemfsRequested;
|
|
238011
238998
|
const noSkillsFlag = values["no-skills"];
|
|
238012
238999
|
const noBundledSkillsFlag = values["no-bundled-skills"];
|
|
238013
239000
|
const skillSourcesRaw = values["skill-sources"];
|
|
@@ -238758,7 +239745,7 @@ Error: ${message}`);
|
|
|
238758
239745
|
}
|
|
238759
239746
|
const { isLettaCloud: isLettaCloud3 } = await Promise.resolve().then(() => (init_memoryFilesystem2(), exports_memoryFilesystem2));
|
|
238760
239747
|
const willAutoEnableMemfs = shouldAutoEnableMemfsForNewAgent && await isLettaCloud3();
|
|
238761
|
-
const effectiveMemoryMode = backend4.capabilities.localMemfs ? "local-memfs" : requestedMemoryPromptMode ?? (willAutoEnableMemfs ? "memfs" : undefined);
|
|
239748
|
+
const effectiveMemoryMode = backend4.capabilities.localMemfs ? localNoMemfsRequested ? "standard" : "local-memfs" : requestedMemoryPromptMode ?? (willAutoEnableMemfs ? "memfs" : undefined);
|
|
238762
239749
|
const personalityOptions = personality ? await buildCreateAgentOptionsForPersonality({
|
|
238763
239750
|
personalityId: personality,
|
|
238764
239751
|
model: effectiveModel
|
|
@@ -238820,16 +239807,15 @@ Error: ${message}`);
|
|
|
238820
239807
|
skipPromptUpdate: shouldCreateNew
|
|
238821
239808
|
})) : Promise.resolve().then(() => {
|
|
238822
239809
|
if (backend4.capabilities.localMemfs) {
|
|
238823
|
-
|
|
238824
|
-
|
|
238825
|
-
|
|
238826
|
-
|
|
238827
|
-
return { action: "enabled" };
|
|
239810
|
+
settingsManager2.setMemfsEnabled(agentId2, !localNoMemfsRequested);
|
|
239811
|
+
return {
|
|
239812
|
+
action: localNoMemfsRequested ? "disabled" : "enabled"
|
|
239813
|
+
};
|
|
238828
239814
|
}
|
|
238829
239815
|
if (memfsFlag) {
|
|
238830
239816
|
throw new Error("MemFS is not supported by the active backend.");
|
|
238831
239817
|
}
|
|
238832
|
-
if (noMemfsFlag) {
|
|
239818
|
+
if (noMemfsFlag || localNoMemfsRequested) {
|
|
238833
239819
|
settingsManager2.setMemfsEnabled(agentId2, false);
|
|
238834
239820
|
}
|
|
238835
239821
|
return null;
|
|
@@ -239121,4 +240107,4 @@ Error during initialization: ${message}`);
|
|
|
239121
240107
|
}
|
|
239122
240108
|
main();
|
|
239123
240109
|
|
|
239124
|
-
//# debugId=
|
|
240110
|
+
//# debugId=3EDFF39471E7DC8264756E2164756E21
|