@letta-ai/letta-code 0.25.4 → 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 +1673 -712
- 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`);
|
|
@@ -69921,10 +69931,135 @@ function shouldKeepReasoningPart(part, provider) {
|
|
|
69921
69931
|
return hasAnthropicReasoningMetadata(part);
|
|
69922
69932
|
return true;
|
|
69923
69933
|
}
|
|
69924
|
-
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);
|
|
69925
70060
|
if (provider === "unknown")
|
|
69926
|
-
return
|
|
69927
|
-
return
|
|
70061
|
+
return capabilitySanitizedMessages;
|
|
70062
|
+
return capabilitySanitizedMessages.map((message) => {
|
|
69928
70063
|
const parts = message.parts.filter((part) => shouldKeepReasoningPart(part, provider));
|
|
69929
70064
|
return parts.length === message.parts.length ? message : { ...message, parts };
|
|
69930
70065
|
}).filter((message) => message.role !== "assistant" || message.parts.length > 0);
|
|
@@ -70022,7 +70157,7 @@ class AISDKStreamAdapter {
|
|
|
70022
70157
|
const tools = toToolSet(input.clientTools);
|
|
70023
70158
|
const provider = aiSDKProviderKind(input.agent.model, input.agent.model_settings);
|
|
70024
70159
|
const uiMessages = await validateUIMessages({
|
|
70025
|
-
messages: sanitizeUIMessagesForProvider(input.uiMessages, provider),
|
|
70160
|
+
messages: sanitizeUIMessagesForProvider(input.uiMessages, provider, input.agent),
|
|
70026
70161
|
tools
|
|
70027
70162
|
});
|
|
70028
70163
|
const result = this.runStreamText({
|
|
@@ -70432,6 +70567,7 @@ function normalizeAgentRecord(value, defaultAgentModel) {
|
|
|
70432
70567
|
if (modelSettings.max_tokens === undefined && (typeof legacyLlmConfig.max_tokens === "number" || legacyLlmConfig.max_tokens === null)) {
|
|
70433
70568
|
modelSettings.max_tokens = legacyLlmConfig.max_tokens;
|
|
70434
70569
|
}
|
|
70570
|
+
const compactionSettings = optionalRecordOrNull(value.compaction_settings);
|
|
70435
70571
|
return {
|
|
70436
70572
|
id: value.id,
|
|
70437
70573
|
name: optionalString(value.name) ?? "Letta Code",
|
|
@@ -70439,7 +70575,8 @@ function normalizeAgentRecord(value, defaultAgentModel) {
|
|
|
70439
70575
|
system: optionalString(value.system) ?? "",
|
|
70440
70576
|
tags: isStringArray(value.tags) ? value.tags : [],
|
|
70441
70577
|
model: optionalString(value.model) ?? optionalString(legacyLlmConfig.model) ?? defaultAgentModel,
|
|
70442
|
-
model_settings: modelSettings
|
|
70578
|
+
model_settings: modelSettings,
|
|
70579
|
+
...compactionSettings !== undefined ? { compaction_settings: compactionSettings } : {}
|
|
70443
70580
|
};
|
|
70444
70581
|
}
|
|
70445
70582
|
function projectAgentState(record2, messageIds = [], inContextMessageIds = messageIds, lastRunCompletion) {
|
|
@@ -70455,6 +70592,7 @@ function projectAgentState(record2, messageIds = [], inContextMessageIds = messa
|
|
|
70455
70592
|
tags: record2.tags,
|
|
70456
70593
|
model: record2.model,
|
|
70457
70594
|
model_settings: record2.model_settings,
|
|
70595
|
+
...record2.compaction_settings !== undefined ? { compaction_settings: record2.compaction_settings } : {},
|
|
70458
70596
|
message_ids: messageIds,
|
|
70459
70597
|
in_context_message_ids: inContextMessageIds,
|
|
70460
70598
|
...lastRunCompletion ? { last_run_completion: lastRunCompletion } : {},
|
|
@@ -70483,6 +70621,39 @@ function normalizeContent(content) {
|
|
|
70483
70621
|
function isRecord3(value) {
|
|
70484
70622
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
70485
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
|
+
}
|
|
70486
70657
|
function textFromContent(content) {
|
|
70487
70658
|
if (typeof content === "string")
|
|
70488
70659
|
return content;
|
|
@@ -70714,6 +70885,19 @@ class LocalStore {
|
|
|
70714
70885
|
}
|
|
70715
70886
|
return this.projectAgent(updated);
|
|
70716
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
|
+
}
|
|
70717
70901
|
createAgent(body) {
|
|
70718
70902
|
const agent = this.createAgentRecord(body);
|
|
70719
70903
|
const agentId = agent.id;
|
|
@@ -70951,8 +71135,12 @@ class LocalStore {
|
|
|
70951
71135
|
},
|
|
70952
71136
|
parts: [{ type: "text", text: input.packedSummary }]
|
|
70953
71137
|
};
|
|
70954
|
-
|
|
70955
|
-
|
|
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);
|
|
70956
71144
|
conversation.last_message_at = date5;
|
|
70957
71145
|
conversation.updated_at = date5;
|
|
70958
71146
|
this.conversations.set(key, conversation);
|
|
@@ -70960,7 +71148,7 @@ class LocalStore {
|
|
|
70960
71148
|
this.rebuildMessageIndex();
|
|
70961
71149
|
return {
|
|
70962
71150
|
numMessagesBefore: previousMessages.length,
|
|
70963
|
-
numMessagesAfter:
|
|
71151
|
+
numMessagesAfter: compactedMessages.length,
|
|
70964
71152
|
summaryMessage: cloneLocalMessage(summaryMessage)
|
|
70965
71153
|
};
|
|
70966
71154
|
}
|
|
@@ -71316,6 +71504,11 @@ class LocalStore {
|
|
|
71316
71504
|
parts.push({ type: "text", text: part.text });
|
|
71317
71505
|
continue;
|
|
71318
71506
|
}
|
|
71507
|
+
const filePart = localFilePartFromLegacyImage(part);
|
|
71508
|
+
if (filePart) {
|
|
71509
|
+
parts.push(filePart);
|
|
71510
|
+
continue;
|
|
71511
|
+
}
|
|
71319
71512
|
parts.push(part);
|
|
71320
71513
|
}
|
|
71321
71514
|
return parts.length > 0 ? parts : textContent(textFromContent(content));
|
|
@@ -71352,7 +71545,7 @@ class LocalStore {
|
|
|
71352
71545
|
if (!conversation?.id || !conversation.agent_id)
|
|
71353
71546
|
continue;
|
|
71354
71547
|
const key = this.conversationKey(conversation.id, conversation.agent_id);
|
|
71355
|
-
const localMessages = readJsonlFile(join7(conversationDir, "messages.jsonl"));
|
|
71548
|
+
const localMessages = readJsonlFile(join7(conversationDir, "messages.jsonl")).map(normalizeLocalMessageForAISDK);
|
|
71356
71549
|
const compiledSystemPrompt = readJsonFile(join7(conversationDir, "system-prompt.json"));
|
|
71357
71550
|
const messages = projectLocalMessagesToStoredMessages(localMessages, conversation.agent_id, conversation.id);
|
|
71358
71551
|
this.conversations.set(key, conversation);
|
|
@@ -71903,6 +72096,9 @@ var init_HeadlessBackend = __esm(() => {
|
|
|
71903
72096
|
});
|
|
71904
72097
|
|
|
71905
72098
|
// src/backend/local/compaction.ts
|
|
72099
|
+
function isLocalSlidingWindowCompactionPlanningError(error51) {
|
|
72100
|
+
return error51 instanceof LocalSlidingWindowCompactionPlanningError;
|
|
72101
|
+
}
|
|
71906
72102
|
function isRecord4(value) {
|
|
71907
72103
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
71908
72104
|
}
|
|
@@ -71961,24 +72157,24 @@ ${body}
|
|
|
71961
72157
|
}
|
|
71962
72158
|
return transcript;
|
|
71963
72159
|
}
|
|
71964
|
-
async function runGenerateText(input, transcript) {
|
|
72160
|
+
async function runGenerateText(input, transcript, defaultPrompt) {
|
|
71965
72161
|
const run = input.generateText ?? generateText;
|
|
71966
72162
|
return run({
|
|
71967
72163
|
model: input.createModel?.() ?? createAISDKModelFactoryFromAgent(input.agent.model, input.agent.model_settings, { localProviderAuthStorageDir: input.localProviderAuthStorageDir })(),
|
|
71968
|
-
system: input.prompt ??
|
|
72164
|
+
system: input.prompt ?? defaultPrompt,
|
|
71969
72165
|
prompt: transcript,
|
|
71970
72166
|
providerOptions: buildAISDKProviderOptions(input.agent.model, input.agent.model_settings),
|
|
71971
72167
|
maxRetries: 0,
|
|
71972
72168
|
abortSignal: input.abortSignal
|
|
71973
72169
|
});
|
|
71974
72170
|
}
|
|
71975
|
-
async function
|
|
72171
|
+
async function summarizeLocalMessagesWithPrompt(input, defaultPrompt) {
|
|
71976
72172
|
if (input.messages.length === 0)
|
|
71977
72173
|
return "No prior conversation messages.";
|
|
71978
72174
|
const primaryTranscript = formatLocalMessagesForSummary(input.messages);
|
|
71979
72175
|
let result;
|
|
71980
72176
|
try {
|
|
71981
|
-
result = await runGenerateText(input, primaryTranscript);
|
|
72177
|
+
result = await runGenerateText(input, primaryTranscript, defaultPrompt);
|
|
71982
72178
|
} catch (error51) {
|
|
71983
72179
|
if (!isContextWindowOverflowError(error51))
|
|
71984
72180
|
throw error51;
|
|
@@ -71986,7 +72182,7 @@ async function summarizeLocalMessagesAll(input) {
|
|
|
71986
72182
|
truncationChars: TOOL_TRANSCRIPT_TRUNCATION_CHARS,
|
|
71987
72183
|
maxChars: TRANSCRIPT_FALLBACK_MAX_CHARS
|
|
71988
72184
|
});
|
|
71989
|
-
result = await runGenerateText(input, fallbackTranscript);
|
|
72185
|
+
result = await runGenerateText(input, fallbackTranscript, defaultPrompt);
|
|
71990
72186
|
}
|
|
71991
72187
|
let summary = result.text.trim();
|
|
71992
72188
|
const clipChars = input.clipChars === undefined ? 50000 : input.clipChars;
|
|
@@ -71995,6 +72191,62 @@ async function summarizeLocalMessagesAll(input) {
|
|
|
71995
72191
|
}
|
|
71996
72192
|
return summary;
|
|
71997
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
|
+
}
|
|
71998
72250
|
function estimateLocalMessageTokens(messages) {
|
|
71999
72251
|
const chars = messages.reduce((total, message) => total + JSON.stringify(message).length, 0);
|
|
72000
72252
|
return Math.ceil(chars / 4);
|
|
@@ -72009,12 +72261,18 @@ The following is an in-context recursive summary of the prior messages: ${summar
|
|
|
72009
72261
|
...stats ? { compaction_stats: stats } : {}
|
|
72010
72262
|
});
|
|
72011
72263
|
}
|
|
72012
|
-
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;
|
|
72013
72265
|
var init_compaction = __esm(() => {
|
|
72014
72266
|
init_dist6();
|
|
72015
72267
|
init_AISDKModelFactory();
|
|
72016
72268
|
init_AISDKStreamAdapter();
|
|
72017
72269
|
init_contextWindowOverflow();
|
|
72270
|
+
LocalSlidingWindowCompactionPlanningError = class LocalSlidingWindowCompactionPlanningError extends Error {
|
|
72271
|
+
constructor(message) {
|
|
72272
|
+
super(message);
|
|
72273
|
+
this.name = "LocalSlidingWindowCompactionPlanningError";
|
|
72274
|
+
}
|
|
72275
|
+
};
|
|
72018
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.
|
|
72019
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:
|
|
72020
72278
|
|
|
@@ -72038,6 +72296,24 @@ This summary should be thorough in capturing technical details, code patterns, a
|
|
|
72038
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.
|
|
72039
72297
|
|
|
72040
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.`;
|
|
72041
72317
|
});
|
|
72042
72318
|
|
|
72043
72319
|
// src/backend/local/LocalModelConfig.ts
|
|
@@ -76285,6 +76561,9 @@ __export(exports_modify, {
|
|
|
76285
76561
|
function supportsDistinctAnthropicXHighEffort(modelHandle) {
|
|
76286
76562
|
return modelHandle.includes("claude-opus-4-7");
|
|
76287
76563
|
}
|
|
76564
|
+
function isRecord5(value) {
|
|
76565
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
76566
|
+
}
|
|
76288
76567
|
function buildModelSettings(modelHandle, updateArgs) {
|
|
76289
76568
|
const isOpenAI = modelHandle.startsWith("openai/") || modelHandle.startsWith(`${OPENAI_CODEX_PROVIDER_NAME}/`);
|
|
76290
76569
|
const isAnthropic = modelHandle.startsWith("anthropic/") || modelHandle.startsWith("claude-pro-max/") || modelHandle.startsWith("minimax/");
|
|
@@ -76407,6 +76686,12 @@ function buildModelSettings(modelHandle, updateArgs) {
|
|
|
76407
76686
|
if (typeof updateArgs?.max_output_tokens === "number" && "provider_type" in settings) {
|
|
76408
76687
|
settings.max_output_tokens = updateArgs.max_output_tokens;
|
|
76409
76688
|
}
|
|
76689
|
+
if (isRecord5(updateArgs?.modalities)) {
|
|
76690
|
+
settings.modalities = updateArgs.modalities;
|
|
76691
|
+
}
|
|
76692
|
+
if (isRecord5(updateArgs?.capabilities)) {
|
|
76693
|
+
settings.capabilities = updateArgs.capabilities;
|
|
76694
|
+
}
|
|
76410
76695
|
return settings;
|
|
76411
76696
|
}
|
|
76412
76697
|
async function updateAgentLLMConfig(agentId, modelHandle, updateArgs, options) {
|
|
@@ -78117,6 +78402,95 @@ function createTelegramAdapter(config2) {
|
|
|
78117
78402
|
let botModule = null;
|
|
78118
78403
|
let running = false;
|
|
78119
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
|
+
}
|
|
78120
78494
|
async function ensureModule() {
|
|
78121
78495
|
if (!botModule) {
|
|
78122
78496
|
botModule = await loadGrammyModule();
|
|
@@ -78310,6 +78684,7 @@ function createTelegramAdapter(config2) {
|
|
|
78310
78684
|
clearTimeout(entry.timer);
|
|
78311
78685
|
}
|
|
78312
78686
|
bufferedMediaGroups.clear();
|
|
78687
|
+
clearAllTyping();
|
|
78313
78688
|
if (!running || !bot)
|
|
78314
78689
|
return;
|
|
78315
78690
|
await bot.stop();
|
|
@@ -78335,6 +78710,7 @@ function createTelegramAdapter(config2) {
|
|
|
78335
78710
|
} else {
|
|
78336
78711
|
await telegramBot.api.setMessageReaction(msg.chatId, Number(targetMessageId), []);
|
|
78337
78712
|
}
|
|
78713
|
+
clearTypingForChat(msg.chatId);
|
|
78338
78714
|
return { messageId: targetMessageId };
|
|
78339
78715
|
}
|
|
78340
78716
|
if (msg.mediaPath) {
|
|
@@ -78361,6 +78737,7 @@ function createTelegramAdapter(config2) {
|
|
|
78361
78737
|
return await telegramBot.api.sendDocument(msg.chatId, inputFile, options);
|
|
78362
78738
|
}
|
|
78363
78739
|
})();
|
|
78740
|
+
clearTypingForChat(msg.chatId);
|
|
78364
78741
|
return { messageId: String(result2.message_id) };
|
|
78365
78742
|
}
|
|
78366
78743
|
const opts = {};
|
|
@@ -78373,6 +78750,7 @@ function createTelegramAdapter(config2) {
|
|
|
78373
78750
|
opts.parse_mode = msg.parseMode;
|
|
78374
78751
|
}
|
|
78375
78752
|
const result = await telegramBot.api.sendMessage(msg.chatId, msg.text, opts);
|
|
78753
|
+
clearTypingForChat(msg.chatId);
|
|
78376
78754
|
return { messageId: String(result.message_id) };
|
|
78377
78755
|
},
|
|
78378
78756
|
async sendDirectReply(chatId, text2, options) {
|
|
@@ -78382,12 +78760,29 @@ function createTelegramAdapter(config2) {
|
|
|
78382
78760
|
} : undefined;
|
|
78383
78761
|
await telegramBot.api.sendMessage(chatId, text2, reply_parameters ? { reply_parameters } : {});
|
|
78384
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
|
+
},
|
|
78385
78779
|
async handleControlRequestEvent(event) {
|
|
78386
78780
|
const telegramBot = await ensureBot();
|
|
78387
78781
|
const reply_parameters = event.source.messageId || event.source.threadId ? {
|
|
78388
78782
|
message_id: Number(event.source.threadId ?? event.source.messageId)
|
|
78389
78783
|
} : undefined;
|
|
78390
78784
|
await telegramBot.api.sendMessage(event.source.chatId, formatChannelControlRequestPrompt(event), reply_parameters ? { reply_parameters } : {});
|
|
78785
|
+
clearTypingForChat(event.source.chatId);
|
|
78391
78786
|
},
|
|
78392
78787
|
onMessage: undefined
|
|
78393
78788
|
};
|
|
@@ -78404,9 +78799,11 @@ async function validateTelegramToken(token) {
|
|
|
78404
78799
|
id: info.id
|
|
78405
78800
|
};
|
|
78406
78801
|
}
|
|
78802
|
+
var TELEGRAM_TYPING_REFRESH_MS = 4000, TELEGRAM_TYPING_MAX_MS;
|
|
78407
78803
|
var init_adapter = __esm(() => {
|
|
78408
78804
|
init_media();
|
|
78409
78805
|
init_runtime();
|
|
78806
|
+
TELEGRAM_TYPING_MAX_MS = 5 * 60 * 1000;
|
|
78410
78807
|
});
|
|
78411
78808
|
|
|
78412
78809
|
// src/channels/telegram/messageActions.ts
|
|
@@ -78499,13 +78896,13 @@ function cloneAccount(account) {
|
|
|
78499
78896
|
}
|
|
78500
78897
|
return cloned;
|
|
78501
78898
|
}
|
|
78502
|
-
function
|
|
78899
|
+
function isRecord6(value) {
|
|
78503
78900
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
78504
78901
|
}
|
|
78505
78902
|
function normalizeLoadedAccount(account) {
|
|
78506
78903
|
const next = cloneAccount(account);
|
|
78507
78904
|
if (!isFirstPartyChannelId(next.channel)) {
|
|
78508
|
-
next.config =
|
|
78905
|
+
next.config = isRecord6(next.config) ? { ...next.config } : {};
|
|
78509
78906
|
}
|
|
78510
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")) {
|
|
78511
78908
|
next.displayName = undefined;
|
|
@@ -81006,6 +81403,12 @@ function resolveDiscordReactionEmoji(value) {
|
|
|
81006
81403
|
};
|
|
81007
81404
|
return nameMap[normalized] ?? normalized;
|
|
81008
81405
|
}
|
|
81406
|
+
function buildDiscordIngressMessageKey(accountId, messageId) {
|
|
81407
|
+
if (!isNonEmptyString3(accountId) || !isNonEmptyString3(messageId)) {
|
|
81408
|
+
return null;
|
|
81409
|
+
}
|
|
81410
|
+
return `${accountId}:${messageId}`;
|
|
81411
|
+
}
|
|
81009
81412
|
function buildDiscordReplyOptions(replyToMessageId, channelId) {
|
|
81010
81413
|
const trimmed = replyToMessageId?.trim();
|
|
81011
81414
|
if (!trimmed || trimmed === channelId) {
|
|
@@ -81013,7 +81416,8 @@ function buildDiscordReplyOptions(replyToMessageId, channelId) {
|
|
|
81013
81416
|
}
|
|
81014
81417
|
return {
|
|
81015
81418
|
reply: {
|
|
81016
|
-
messageReference: trimmed
|
|
81419
|
+
messageReference: trimmed,
|
|
81420
|
+
failIfNotExists: false
|
|
81017
81421
|
}
|
|
81018
81422
|
};
|
|
81019
81423
|
}
|
|
@@ -81055,12 +81459,6 @@ function createDiscordAdapter(config2) {
|
|
|
81055
81459
|
const seenIngressMessageKeys = new Map;
|
|
81056
81460
|
const lifecycleStateByMessageKey = new Map;
|
|
81057
81461
|
const lifecycleOperationByMessageKey = new Map;
|
|
81058
|
-
function buildIngressMessageKey(channelId, messageId) {
|
|
81059
|
-
if (!isNonEmptyString3(channelId) || !isNonEmptyString3(messageId)) {
|
|
81060
|
-
return null;
|
|
81061
|
-
}
|
|
81062
|
-
return `${channelId}:${messageId}`;
|
|
81063
|
-
}
|
|
81064
81462
|
function pruneSeenIngressMessageKeys(now2 = Date.now()) {
|
|
81065
81463
|
for (const [key, expiresAt] of seenIngressMessageKeys) {
|
|
81066
81464
|
if (expiresAt <= now2) {
|
|
@@ -81079,8 +81477,8 @@ function createDiscordAdapter(config2) {
|
|
|
81079
81477
|
}
|
|
81080
81478
|
}
|
|
81081
81479
|
}
|
|
81082
|
-
function markIngressMessageSeen(
|
|
81083
|
-
const key =
|
|
81480
|
+
function markIngressMessageSeen(messageId) {
|
|
81481
|
+
const key = buildDiscordIngressMessageKey(config2.accountId, messageId);
|
|
81084
81482
|
if (!key)
|
|
81085
81483
|
return false;
|
|
81086
81484
|
const now2 = Date.now();
|
|
@@ -81270,7 +81668,7 @@ function createDiscordAdapter(config2) {
|
|
|
81270
81668
|
const isThread = isThreadMessage(message);
|
|
81271
81669
|
const wasMentioned = chatType === "channel" && hasBotMention(message);
|
|
81272
81670
|
if (chatType === "direct") {
|
|
81273
|
-
if (markIngressMessageSeen(message.
|
|
81671
|
+
if (markIngressMessageSeen(message.id))
|
|
81274
81672
|
return;
|
|
81275
81673
|
const attachments2 = await collectAttachments(message.attachments, message.channelId);
|
|
81276
81674
|
if (!content && (!attachments2 || attachments2.length === 0))
|
|
@@ -81307,7 +81705,7 @@ function createDiscordAdapter(config2) {
|
|
|
81307
81705
|
allowedChannels: config2.allowedChannels
|
|
81308
81706
|
}))
|
|
81309
81707
|
return;
|
|
81310
|
-
if (markIngressMessageSeen(message.
|
|
81708
|
+
if (markIngressMessageSeen(message.id))
|
|
81311
81709
|
return;
|
|
81312
81710
|
let effectiveChatId = message.channelId;
|
|
81313
81711
|
let effectiveThreadId = isThread ? message.channelId : null;
|
|
@@ -81778,7 +82176,7 @@ __export(exports_pluginRegistry, {
|
|
|
81778
82176
|
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "node:fs";
|
|
81779
82177
|
import { resolve as resolve6, sep } from "node:path";
|
|
81780
82178
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
81781
|
-
function
|
|
82179
|
+
function isRecord7(value) {
|
|
81782
82180
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
81783
82181
|
}
|
|
81784
82182
|
function isValidChannelId(value) {
|
|
@@ -81794,7 +82192,7 @@ function readChannelManifest(channelDir) {
|
|
|
81794
82192
|
}
|
|
81795
82193
|
try {
|
|
81796
82194
|
const parsed = JSON.parse(readFileSync9(manifestPath, "utf-8"));
|
|
81797
|
-
if (!
|
|
82195
|
+
if (!isRecord7(parsed)) {
|
|
81798
82196
|
return null;
|
|
81799
82197
|
}
|
|
81800
82198
|
const id = typeof parsed.id === "string" ? parsed.id.trim() : "";
|
|
@@ -81838,8 +82236,8 @@ function createUserChannelRegistration(manifest) {
|
|
|
81838
82236
|
throw new Error(`Channel plugin "${manifest.id}" entry escapes its directory.`);
|
|
81839
82237
|
}
|
|
81840
82238
|
const loadPromise = import(pathToFileURL2(entryPath).href).then((loaded) => {
|
|
81841
|
-
const exported = (
|
|
81842
|
-
if (!
|
|
82239
|
+
const exported = (isRecord7(loaded) ? loaded.channelPlugin : undefined) ?? (isRecord7(loaded) ? loaded.default : undefined);
|
|
82240
|
+
if (!isRecord7(exported)) {
|
|
81843
82241
|
throw new Error(`Channel plugin "${manifest.id}" must export channelPlugin or default.`);
|
|
81844
82242
|
}
|
|
81845
82243
|
const plugin = exported;
|
|
@@ -82786,6 +83184,9 @@ function buildChannelNotificationXml(msg) {
|
|
|
82786
83184
|
`chat_id="${escapeXmlAttribute(msg.chatId)}"`,
|
|
82787
83185
|
`sender_id="${escapeXmlAttribute(msg.senderId)}"`
|
|
82788
83186
|
];
|
|
83187
|
+
if (msg.accountId) {
|
|
83188
|
+
attrs.push(`account_id="${escapeXmlAttribute(msg.accountId)}"`);
|
|
83189
|
+
}
|
|
82789
83190
|
if (msg.senderName) {
|
|
82790
83191
|
attrs.push(`sender_name="${escapeXmlAttribute(msg.senderName)}"`);
|
|
82791
83192
|
}
|
|
@@ -83146,8 +83547,9 @@ class ChannelRegistry {
|
|
|
83146
83547
|
}
|
|
83147
83548
|
return matches[0] ?? null;
|
|
83148
83549
|
}
|
|
83149
|
-
getRouteForScope(channel, chatId, agentId, conversationId) {
|
|
83150
|
-
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);
|
|
83151
83553
|
if (matches.length !== 1) {
|
|
83152
83554
|
return null;
|
|
83153
83555
|
}
|
|
@@ -83741,6 +84143,7 @@ async function executeSingleDecision(decision, onChunk, options) {
|
|
|
83741
84143
|
toolCallId: decision.approval.toolCallId,
|
|
83742
84144
|
toolContextId: options?.toolContextId,
|
|
83743
84145
|
parentScope: options?.parentScope,
|
|
84146
|
+
channelTurnSources: options?.channelTurnSources,
|
|
83744
84147
|
onOutput: options?.onStreamingOutput ? (chunk, stream) => options.onStreamingOutput?.(decision.approval.toolCallId, chunk, stream === "stderr") : undefined,
|
|
83745
84148
|
onFileWrite: options?.onFileWrite
|
|
83746
84149
|
});
|
|
@@ -90350,8 +90753,7 @@ var init_readOnlyShell = __esm(() => {
|
|
|
90350
90753
|
memory: new Set(["status", "help", "backups", "export", "tokens"]),
|
|
90351
90754
|
memfs: new Set(["status", "help", "backups", "export", "tokens"]),
|
|
90352
90755
|
agents: new Set(["list", "help"]),
|
|
90353
|
-
messages: new Set(["search", "list", "help"])
|
|
90354
|
-
blocks: new Set(["list", "help"])
|
|
90756
|
+
messages: new Set(["search", "list", "help"])
|
|
90355
90757
|
};
|
|
90356
90758
|
SAFE_GH_COMMANDS = {
|
|
90357
90759
|
pr: new Set(["list", "status", "checks", "diff", "view"]),
|
|
@@ -90828,7 +91230,7 @@ async function initSecretsFromServer(agentId, cachedAgent) {
|
|
|
90828
91230
|
setCache(agentId, {});
|
|
90829
91231
|
return;
|
|
90830
91232
|
}
|
|
90831
|
-
const agent = cachedAgent ?? await (
|
|
91233
|
+
const agent = cachedAgent ?? await getBackend().retrieveAgent(agentId, {
|
|
90832
91234
|
include: ["agent.secrets"]
|
|
90833
91235
|
});
|
|
90834
91236
|
const secrets2 = {};
|
|
@@ -90861,6 +91263,9 @@ async function refreshAndListSecrets(agentIdArg) {
|
|
|
90861
91263
|
return Object.keys(cache3).sort().map((key) => ({ key, value: cache3[key] ?? "" }));
|
|
90862
91264
|
}
|
|
90863
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
|
+
}
|
|
90864
91269
|
const agentId = resolveSecretsAgentId(agentIdArg);
|
|
90865
91270
|
if (!agentId) {
|
|
90866
91271
|
throw new Error("No agent context set. Agent ID is required.");
|
|
@@ -90872,8 +91277,7 @@ async function applySecretBatch(options, agentIdArg) {
|
|
|
90872
91277
|
for (const rawKey of options.unset ?? []) {
|
|
90873
91278
|
delete next[rawKey.toUpperCase()];
|
|
90874
91279
|
}
|
|
90875
|
-
|
|
90876
|
-
await client.agents.update(agentId, { secrets: next });
|
|
91280
|
+
await getBackend().updateAgent(agentId, { secrets: next });
|
|
90877
91281
|
setCache(agentId, next);
|
|
90878
91282
|
return Object.keys(next).sort();
|
|
90879
91283
|
}
|
|
@@ -90881,14 +91285,13 @@ async function setSecretOnServer(key, value, agentIdArg) {
|
|
|
90881
91285
|
if (!getBackend().capabilities.serverSecrets) {
|
|
90882
91286
|
throw new Error("Agent secrets are not supported by this backend yet");
|
|
90883
91287
|
}
|
|
90884
|
-
const client = await getClient();
|
|
90885
91288
|
const agentId = resolveSecretsAgentId(agentIdArg);
|
|
90886
91289
|
if (!agentId) {
|
|
90887
91290
|
throw new Error("No agent context set. Agent ID is required.");
|
|
90888
91291
|
}
|
|
90889
91292
|
const secrets2 = { ...loadSecrets(agentId) };
|
|
90890
91293
|
secrets2[key] = value;
|
|
90891
|
-
await
|
|
91294
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
90892
91295
|
setCache(agentId, secrets2);
|
|
90893
91296
|
}
|
|
90894
91297
|
async function deleteSecretOnServer(key, agentIdArg) {
|
|
@@ -90904,8 +91307,7 @@ async function deleteSecretOnServer(key, agentIdArg) {
|
|
|
90904
91307
|
return false;
|
|
90905
91308
|
}
|
|
90906
91309
|
delete secrets2[key];
|
|
90907
|
-
|
|
90908
|
-
await client.agents.update(agentId, { secrets: secrets2 });
|
|
91310
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
90909
91311
|
setCache(agentId, secrets2);
|
|
90910
91312
|
return true;
|
|
90911
91313
|
}
|
|
@@ -90921,7 +91323,6 @@ var SECRETS_CACHE_KEY;
|
|
|
90921
91323
|
var init_secretsStore = __esm(() => {
|
|
90922
91324
|
init_context();
|
|
90923
91325
|
init_backend2();
|
|
90924
|
-
init_client2();
|
|
90925
91326
|
SECRETS_CACHE_KEY = Symbol.for("@letta/secretsCache");
|
|
90926
91327
|
});
|
|
90927
91328
|
|
|
@@ -93695,7 +94096,9 @@ function getShellEnv() {
|
|
|
93695
94096
|
env.LETTA_AGENT_ID = agentId;
|
|
93696
94097
|
env.AGENT_ID = agentId;
|
|
93697
94098
|
try {
|
|
93698
|
-
|
|
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)) {
|
|
93699
94102
|
const memoryDir = resolveScopedMemoryDir({ agentId });
|
|
93700
94103
|
if (!memoryDir) {
|
|
93701
94104
|
throw new Error("Unable to resolve memory directory");
|
|
@@ -93763,6 +94166,7 @@ var init_shellEnv = __esm(() => {
|
|
|
93763
94166
|
init_context();
|
|
93764
94167
|
init_memoryFilesystem();
|
|
93765
94168
|
init_client2();
|
|
94169
|
+
init_paths();
|
|
93766
94170
|
init_runtime_context();
|
|
93767
94171
|
init_settings_manager();
|
|
93768
94172
|
});
|
|
@@ -96883,6 +97287,25 @@ function buildSyntheticChannelRoute(params) {
|
|
|
96883
97287
|
updatedAt: now2
|
|
96884
97288
|
};
|
|
96885
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
|
+
}
|
|
96886
97309
|
async function resolveExplicitMessageChannelContext(params) {
|
|
96887
97310
|
if (params.input.channel !== "slack") {
|
|
96888
97311
|
return `Error: Explicit MessageChannel targets are not supported on ${params.input.channel}.`;
|
|
@@ -96933,9 +97356,14 @@ async function message_channel(args) {
|
|
|
96933
97356
|
try {
|
|
96934
97357
|
let executionContext;
|
|
96935
97358
|
if (input.chatId) {
|
|
96936
|
-
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);
|
|
96937
97365
|
if (!route2) {
|
|
96938
|
-
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.`;
|
|
96939
97367
|
}
|
|
96940
97368
|
const adapter2 = registry2.getAdapter(input.channel, route2.accountId);
|
|
96941
97369
|
if (!adapter2) {
|
|
@@ -110723,6 +111151,12 @@ var init_SearchFileContentGemini2 = __esm(() => {
|
|
|
110723
111151
|
// src/agent/skills.ts
|
|
110724
111152
|
var exports_skills = {};
|
|
110725
111153
|
__export(exports_skills, {
|
|
111154
|
+
isUserInvocableSkill: () => isUserInvocableSkill,
|
|
111155
|
+
isModelInvocableSkill: () => isModelInvocableSkill,
|
|
111156
|
+
getLegacyAgentSkillsDir: () => getLegacyAgentSkillsDir,
|
|
111157
|
+
getFrontmatterStringList: () => getFrontmatterStringList,
|
|
111158
|
+
getFrontmatterString: () => getFrontmatterString,
|
|
111159
|
+
getFrontmatterBoolean: () => getFrontmatterBoolean,
|
|
110726
111160
|
getBundledSkills: () => getBundledSkills,
|
|
110727
111161
|
getAgentSkillsDir: () => getAgentSkillsDir,
|
|
110728
111162
|
formatSkillsAsSystemReminder: () => formatSkillsAsSystemReminder,
|
|
@@ -110745,7 +111179,45 @@ function getBundledSkillsPath() {
|
|
|
110745
111179
|
function compareSkills(a, b) {
|
|
110746
111180
|
return a.id.localeCompare(b.id) || a.source.localeCompare(b.source) || a.path.localeCompare(b.path);
|
|
110747
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
|
+
}
|
|
110748
111217
|
function getAgentSkillsDir(agentId) {
|
|
111218
|
+
return join25(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
111219
|
+
}
|
|
111220
|
+
function getLegacyAgentSkillsDir(agentId) {
|
|
110749
111221
|
return join25(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
|
|
110750
111222
|
}
|
|
110751
111223
|
async function getBundledSkills() {
|
|
@@ -110788,6 +111260,12 @@ async function discoverSkills(projectSkillsPath = join25(process.cwd(), SKILLS_D
|
|
|
110788
111260
|
}
|
|
110789
111261
|
}
|
|
110790
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
|
+
}
|
|
110791
111269
|
const agentSkillsDir = getAgentSkillsDir(agentId);
|
|
110792
111270
|
const agentResult = await discoverSkillsFromDir(agentSkillsDir, "agent");
|
|
110793
111271
|
allErrors.push(...agentResult.errors);
|
|
@@ -110871,7 +111349,7 @@ async function parseSkillFile(filePath, rootPath, source) {
|
|
|
110871
111349
|
const defaultId = dirPath || "root";
|
|
110872
111350
|
const id = (typeof frontmatter.id === "string" ? frontmatter.id : null) || defaultId;
|
|
110873
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());
|
|
110874
|
-
let description =
|
|
111352
|
+
let description = getFrontmatterString(frontmatter, "description") ?? null;
|
|
110875
111353
|
if (!description) {
|
|
110876
111354
|
const firstParagraph = body.trim().split(`
|
|
110877
111355
|
|
|
@@ -110879,30 +111357,31 @@ async function parseSkillFile(filePath, rootPath, source) {
|
|
|
110879
111357
|
description = firstParagraph || "No description available";
|
|
110880
111358
|
}
|
|
110881
111359
|
description = description.trim();
|
|
110882
|
-
|
|
110883
|
-
|
|
110884
|
-
|
|
110885
|
-
|
|
110886
|
-
|
|
110887
|
-
tags = frontmatter.tags;
|
|
110888
|
-
} else if (typeof frontmatter.tags === "string") {
|
|
110889
|
-
tags = [frontmatter.tags];
|
|
110890
|
-
}
|
|
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");
|
|
110891
111365
|
return {
|
|
110892
111366
|
id,
|
|
110893
111367
|
name: name25,
|
|
110894
|
-
description,
|
|
110895
|
-
|
|
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"),
|
|
110896
111375
|
tags,
|
|
110897
111376
|
path: filePath,
|
|
110898
111377
|
source
|
|
110899
111378
|
};
|
|
110900
111379
|
}
|
|
110901
111380
|
function formatSkillsAsSystemReminder(skills) {
|
|
110902
|
-
|
|
111381
|
+
const lines = skills.filter(isModelInvocableSkill).sort(compareSkills).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
111382
|
+
if (lines.length === 0) {
|
|
110903
111383
|
return "";
|
|
110904
111384
|
}
|
|
110905
|
-
const lines = [...skills].sort(compareSkills).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
110906
111385
|
return `<system-reminder>
|
|
110907
111386
|
The following skills are available for use with the Skill tool:
|
|
110908
111387
|
|
|
@@ -110936,6 +111415,15 @@ var init_skillContentRegistry = __esm(() => {
|
|
|
110936
111415
|
});
|
|
110937
111416
|
|
|
110938
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
|
+
});
|
|
110939
111427
|
import { existsSync as existsSync23, readdirSync as readdirSync7 } from "node:fs";
|
|
110940
111428
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
110941
111429
|
import { dirname as dirname12, join as join26 } from "node:path";
|
|
@@ -111020,6 +111508,83 @@ function getResolvedAgentId(args) {
|
|
|
111020
111508
|
return;
|
|
111021
111509
|
}
|
|
111022
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
|
+
}
|
|
111023
111588
|
async function skill(args) {
|
|
111024
111589
|
validateRequiredParams(args, ["skill"], "Skill");
|
|
111025
111590
|
const { skill: skillName, toolCallId } = args;
|
|
@@ -111029,18 +111594,13 @@ async function skill(args) {
|
|
|
111029
111594
|
try {
|
|
111030
111595
|
const agentId = getResolvedAgentId(args);
|
|
111031
111596
|
const skillsDir = await getResolvedSkillsDir();
|
|
111032
|
-
const
|
|
111033
|
-
|
|
111034
|
-
|
|
111035
|
-
|
|
111036
|
-
|
|
111037
|
-
|
|
111038
|
-
` : "";
|
|
111039
|
-
const fullContent = `${dirHeader}${processedContent}`;
|
|
111597
|
+
const fullContent = await loadRenderedSkillContent(skillName, {
|
|
111598
|
+
agentId,
|
|
111599
|
+
skillsDir,
|
|
111600
|
+
args: args.args
|
|
111601
|
+
});
|
|
111040
111602
|
if (toolCallId) {
|
|
111041
|
-
queueSkillContent(toolCallId,
|
|
111042
|
-
${fullContent}
|
|
111043
|
-
</${skillName}>`);
|
|
111603
|
+
queueSkillContent(toolCallId, wrapSkillContent(skillName, fullContent));
|
|
111044
111604
|
}
|
|
111045
111605
|
return { message: `Launching skill: ${skillName}` };
|
|
111046
111606
|
} catch (error51) {
|
|
@@ -111426,18 +111986,21 @@ var init_contextBudget = __esm(() => {
|
|
|
111426
111986
|
// src/agent/subagents/manager.ts
|
|
111427
111987
|
import { spawn as spawn5 } from "node:child_process";
|
|
111428
111988
|
function getModelHandleFromAgent(agent) {
|
|
111989
|
+
const directModel = agent.model;
|
|
111990
|
+
if (directModel?.includes("/")) {
|
|
111991
|
+
return directModel;
|
|
111992
|
+
}
|
|
111429
111993
|
const endpoint = agent.llm_config?.model_endpoint_type;
|
|
111430
111994
|
const model = agent.llm_config?.model;
|
|
111431
111995
|
if (endpoint && model) {
|
|
111432
111996
|
return `${endpoint}/${model}`;
|
|
111433
111997
|
}
|
|
111434
|
-
return model || null;
|
|
111998
|
+
return directModel || model || null;
|
|
111435
111999
|
}
|
|
111436
112000
|
async function getPrimaryAgentModelHandle() {
|
|
111437
112001
|
try {
|
|
111438
112002
|
const agentId = getCurrentAgentId();
|
|
111439
|
-
const
|
|
111440
|
-
const agent = await client.agents.retrieve(agentId);
|
|
112003
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
111441
112004
|
return { handle: getModelHandleFromAgent(agent), agent };
|
|
111442
112005
|
} catch {
|
|
111443
112006
|
return { handle: null, agent: null };
|
|
@@ -111707,6 +112270,8 @@ function resolveSubagentLauncher(cliArgs, options = {}) {
|
|
|
111707
112270
|
function composeSubagentChildEnv(options) {
|
|
111708
112271
|
const {
|
|
111709
112272
|
parentProcessEnv,
|
|
112273
|
+
backendMode,
|
|
112274
|
+
localBackendStorageDir,
|
|
111710
112275
|
parentAgentId,
|
|
111711
112276
|
permissionMode: permissionMode2,
|
|
111712
112277
|
inheritedPrimaryRoot,
|
|
@@ -111720,6 +112285,14 @@ function composeSubagentChildEnv(options) {
|
|
|
111720
112285
|
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
111721
112286
|
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId }
|
|
111722
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
|
+
}
|
|
111723
112296
|
const nextScope = new Set([
|
|
111724
112297
|
...parseScopeList(parentProcessEnv.LETTA_MEMORY_SCOPE),
|
|
111725
112298
|
...cliPermissions.getMemoryScope()
|
|
@@ -111743,6 +112316,12 @@ function composeSubagentChildEnv(options) {
|
|
|
111743
112316
|
}
|
|
111744
112317
|
return childEnv;
|
|
111745
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
|
+
}
|
|
111746
112325
|
function getReflectionStartupNotice() {
|
|
111747
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.]`;
|
|
111748
112327
|
}
|
|
@@ -111805,9 +112384,12 @@ ${userPrompt}`);
|
|
|
111805
112384
|
}
|
|
111806
112385
|
return hardTruncateReflectionPrompt(userPrompt, allowedPromptChars);
|
|
111807
112386
|
}
|
|
111808
|
-
function buildSubagentArgs(type, config2, model, userPrompt, existingAgentId, existingConversationId, maxTurns) {
|
|
112387
|
+
function buildSubagentArgs(type, config2, model, userPrompt, existingAgentId, existingConversationId, maxTurns, options = {}) {
|
|
111809
112388
|
const args = [];
|
|
111810
112389
|
const isDeployingExisting = Boolean(existingAgentId || existingConversationId);
|
|
112390
|
+
if (options.backendMode) {
|
|
112391
|
+
args.push("--backend", options.backendMode);
|
|
112392
|
+
}
|
|
111811
112393
|
if (isDeployingExisting) {
|
|
111812
112394
|
if (existingConversationId) {
|
|
111813
112395
|
args.push("--conv", existingConversationId);
|
|
@@ -111879,7 +112461,9 @@ async function executeSubagent(type, config2, model, userPrompt, baseURL, subage
|
|
|
111879
112461
|
updateSubagent(subagentId, { model });
|
|
111880
112462
|
}
|
|
111881
112463
|
try {
|
|
111882
|
-
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 });
|
|
111883
112467
|
const launcher = resolveSubagentLauncher(cliArgs);
|
|
111884
112468
|
let parentAgentId = parentAgentIdOverride;
|
|
111885
112469
|
if (!parentAgentId) {
|
|
@@ -111893,19 +112477,28 @@ async function executeSubagent(type, config2, model, userPrompt, baseURL, subage
|
|
|
111893
112477
|
const inheritedMemoryRoots = resolveAllowedMemoryRoots({
|
|
111894
112478
|
currentAgentId: parentAgentId ?? null
|
|
111895
112479
|
});
|
|
112480
|
+
const localBackendStorageDir = backendMode === "local" ? getLocalBackendStorageDir2() : null;
|
|
112481
|
+
const inheritedPrimaryRoot = resolveSubagentInheritedPrimaryRoot({
|
|
112482
|
+
backendMode,
|
|
112483
|
+
parentAgentId,
|
|
112484
|
+
inheritedPrimaryRoot: inheritedMemoryRoots.primaryRoot,
|
|
112485
|
+
localBackendStorageDir
|
|
112486
|
+
});
|
|
111896
112487
|
const subagentWorkingDirectory = resolveSubagentWorkingDirectory(process.env, getCurrentWorkingDirectory(), {
|
|
111897
112488
|
subagentType: type,
|
|
111898
112489
|
permissionMode: config2.permissionMode,
|
|
111899
|
-
inheritedPrimaryRoot
|
|
112490
|
+
inheritedPrimaryRoot
|
|
111900
112491
|
});
|
|
111901
112492
|
const childEnv = composeSubagentChildEnv({
|
|
111902
112493
|
parentProcessEnv: {
|
|
111903
112494
|
...process.env,
|
|
111904
112495
|
USER_CWD: subagentWorkingDirectory
|
|
111905
112496
|
},
|
|
112497
|
+
backendMode,
|
|
112498
|
+
localBackendStorageDir,
|
|
111906
112499
|
parentAgentId,
|
|
111907
112500
|
permissionMode: config2.permissionMode,
|
|
111908
|
-
inheritedPrimaryRoot
|
|
112501
|
+
inheritedPrimaryRoot,
|
|
111909
112502
|
inheritedApiKey,
|
|
111910
112503
|
inheritedBaseUrl
|
|
111911
112504
|
});
|
|
@@ -112091,7 +112684,7 @@ async function spawnSubagent(type, prompt, userModel, subagentId, signal, existi
|
|
|
112091
112684
|
let finalPrompt = prompt;
|
|
112092
112685
|
if (isDeployingExisting && resolvedParentAgentId) {
|
|
112093
112686
|
try {
|
|
112094
|
-
const cachedParent = parentAgent ?? await (
|
|
112687
|
+
const cachedParent = parentAgent ?? await getBackend().retrieveAgent(resolvedParentAgentId);
|
|
112095
112688
|
if (forkedContext) {
|
|
112096
112689
|
const systemReminder = buildForkSystemReminder(type);
|
|
112097
112690
|
finalPrompt = systemReminder + prompt;
|
|
@@ -112106,8 +112699,9 @@ async function spawnSubagent(type, prompt, userModel, subagentId, signal, existi
|
|
|
112106
112699
|
}
|
|
112107
112700
|
var BYOK_PROVIDER_TO_BASE;
|
|
112108
112701
|
var init_manager3 = __esm(() => {
|
|
112109
|
-
|
|
112702
|
+
init_backend2();
|
|
112110
112703
|
init_metadata();
|
|
112704
|
+
init_paths();
|
|
112111
112705
|
init_subagentState();
|
|
112112
112706
|
init_constants();
|
|
112113
112707
|
init_cli();
|
|
@@ -112135,22 +112729,6 @@ var init_manager3 = __esm(() => {
|
|
|
112135
112729
|
};
|
|
112136
112730
|
});
|
|
112137
112731
|
|
|
112138
|
-
// src/backend/api/conversations.ts
|
|
112139
|
-
var exports_conversations = {};
|
|
112140
|
-
__export(exports_conversations, {
|
|
112141
|
-
forkConversation: () => forkConversation
|
|
112142
|
-
});
|
|
112143
|
-
async function forkConversation(conversationId, options = {}) {
|
|
112144
|
-
const query = {
|
|
112145
|
-
...options.agentId ? { agent_id: options.agentId } : {},
|
|
112146
|
-
...options.hidden !== undefined ? { hidden: options.hidden } : {}
|
|
112147
|
-
};
|
|
112148
|
-
return apiRequest("POST", `/v1/conversations/${encodeURIComponent(conversationId)}/fork`, undefined, { query });
|
|
112149
|
-
}
|
|
112150
|
-
var init_conversations2 = __esm(() => {
|
|
112151
|
-
init_request();
|
|
112152
|
-
});
|
|
112153
|
-
|
|
112154
112732
|
// src/cli/helpers/messageQueueBridge.ts
|
|
112155
112733
|
function setMessageQueueAdder(fn) {
|
|
112156
112734
|
queueAdder = fn;
|
|
@@ -112568,7 +113146,7 @@ async function task(args) {
|
|
|
112568
113146
|
try {
|
|
112569
113147
|
const parentAgentId = getCurrentAgentId();
|
|
112570
113148
|
const parentConvId = getConversationId() ?? "default";
|
|
112571
|
-
const forkedConv = await forkConversation(parentConvId, {
|
|
113149
|
+
const forkedConv = await getBackend().forkConversation(parentConvId, {
|
|
112572
113150
|
...parentConvId === "default" ? { agentId: parentAgentId } : {},
|
|
112573
113151
|
hidden: true
|
|
112574
113152
|
});
|
|
@@ -112666,7 +113244,7 @@ var init_Task2 = __esm(() => {
|
|
|
112666
113244
|
init_context();
|
|
112667
113245
|
init_subagents();
|
|
112668
113246
|
init_manager3();
|
|
112669
|
-
|
|
113247
|
+
init_backend2();
|
|
112670
113248
|
init_messageQueueBridge();
|
|
112671
113249
|
init_subagentState();
|
|
112672
113250
|
init_hooks();
|
|
@@ -116911,7 +117489,7 @@ function detectSkillScript(command, workingDir) {
|
|
|
116911
117489
|
if (projectSkill) {
|
|
116912
117490
|
return projectSkill;
|
|
116913
117491
|
}
|
|
116914
|
-
const agentRegex = new RegExp(`^${escapeRegex4(normalizedHomeDir)}/\\.letta/agents/[^/]+/skills/(.+?)/scripts/`);
|
|
117492
|
+
const agentRegex = new RegExp(`^${escapeRegex4(normalizedHomeDir)}/\\.letta/agents/[^/]+/(?:memory/)?skills/(.+?)/scripts/`);
|
|
116915
117493
|
const agentSkill = detect("agent-scoped", agentRegex);
|
|
116916
117494
|
if (agentSkill) {
|
|
116917
117495
|
return agentSkill;
|
|
@@ -117784,14 +118362,14 @@ function clipToolReturn(text2, maxLines = 3, maxChars = 300) {
|
|
|
117784
118362
|
}
|
|
117785
118363
|
return clipped;
|
|
117786
118364
|
}
|
|
117787
|
-
function
|
|
118365
|
+
function isRecord8(value) {
|
|
117788
118366
|
return typeof value === "object" && value !== null;
|
|
117789
118367
|
}
|
|
117790
118368
|
function isStringArray2(value) {
|
|
117791
118369
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
117792
118370
|
}
|
|
117793
118371
|
function isMultimodalContent(arr) {
|
|
117794
|
-
return arr.every((item) =>
|
|
118372
|
+
return arr.every((item) => isRecord8(item) && (item.type === "text" || item.type === "image"));
|
|
117795
118373
|
}
|
|
117796
118374
|
function flattenToolResponse(result) {
|
|
117797
118375
|
if (result === null || result === undefined) {
|
|
@@ -117800,7 +118378,7 @@ function flattenToolResponse(result) {
|
|
|
117800
118378
|
if (typeof result === "string") {
|
|
117801
118379
|
return result;
|
|
117802
118380
|
}
|
|
117803
|
-
if (!
|
|
118381
|
+
if (!isRecord8(result)) {
|
|
117804
118382
|
return JSON.stringify(result);
|
|
117805
118383
|
}
|
|
117806
118384
|
if (typeof result.message === "string") {
|
|
@@ -117817,7 +118395,7 @@ function flattenToolResponse(result) {
|
|
|
117817
118395
|
return result.content;
|
|
117818
118396
|
}
|
|
117819
118397
|
if (Array.isArray(result.content)) {
|
|
117820
|
-
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(`
|
|
117821
118399
|
`);
|
|
117822
118400
|
if (textContent2) {
|
|
117823
118401
|
return textContent2;
|
|
@@ -117932,8 +118510,16 @@ async function executeTool2(name25, args, options) {
|
|
|
117932
118510
|
if (internalName === "Skill" && options?.parentScope) {
|
|
117933
118511
|
enhancedArgs = { ...enhancedArgs, parentScope: options.parentScope };
|
|
117934
118512
|
}
|
|
117935
|
-
if (internalName === "MessageChannel"
|
|
117936
|
-
|
|
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
|
+
}
|
|
117937
118523
|
}
|
|
117938
118524
|
const PLAN_MODE_TOOL_NAMES = new Set([
|
|
117939
118525
|
"EnterPlanMode",
|
|
@@ -117960,7 +118546,7 @@ async function executeTool2(name25, args, options) {
|
|
|
117960
118546
|
} catch {}
|
|
117961
118547
|
}
|
|
117962
118548
|
}
|
|
117963
|
-
const recordResult =
|
|
118549
|
+
const recordResult = isRecord8(result) ? result : undefined;
|
|
117964
118550
|
const stdoutValue = recordResult?.stdout;
|
|
117965
118551
|
const stderrValue = recordResult?.stderr;
|
|
117966
118552
|
const stdout = isStringArray2(stdoutValue) ? stdoutValue : undefined;
|
|
@@ -118694,9 +119280,8 @@ async function hydrateMemfsSettingFromAgent(agent) {
|
|
|
118694
119280
|
return enabled;
|
|
118695
119281
|
}
|
|
118696
119282
|
async function isMemfsEnabledOnServer(agentId) {
|
|
118697
|
-
const {
|
|
118698
|
-
const
|
|
118699
|
-
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, {
|
|
118700
119285
|
include: ["agent.tags"]
|
|
118701
119286
|
});
|
|
118702
119287
|
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -118829,7 +119414,8 @@ async function applyMemfsFlags(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
118829
119414
|
const backend = getBackend2();
|
|
118830
119415
|
if (backend.capabilities.localMemfs) {
|
|
118831
119416
|
if (noMemfsFlag) {
|
|
118832
|
-
|
|
119417
|
+
settingsManager2.setMemfsEnabled(agentId, false);
|
|
119418
|
+
return { action: "disabled" };
|
|
118833
119419
|
}
|
|
118834
119420
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
118835
119421
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -119285,7 +119871,7 @@ ${skillsBlock.trimStart()}`;
|
|
|
119285
119871
|
function compileLocalSystemPrompt(options) {
|
|
119286
119872
|
const compiledAt = options.now ?? new Date;
|
|
119287
119873
|
const memoryDir = options.memoryDir ?? getMemoryFilesystemRoot(options.agent.id);
|
|
119288
|
-
const memfs = renderMemfsProjection(memoryDir);
|
|
119874
|
+
const memfs = options.includeMemfs === false ? { content: "", revision: undefined } : renderMemfsProjection(memoryDir);
|
|
119289
119875
|
const metadata = compileMemoryMetadata({
|
|
119290
119876
|
agentId: options.agent.id,
|
|
119291
119877
|
conversationId: options.conversationId,
|
|
@@ -119357,6 +119943,37 @@ function initialMemoryFilesFromCreateBody(body) {
|
|
|
119357
119943
|
}
|
|
119358
119944
|
return [...files.values()].sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
119359
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
|
+
}
|
|
119360
119977
|
function createLocalExecutor(options, onContextWindowOverflow, onContextUsage) {
|
|
119361
119978
|
if (options.executor)
|
|
119362
119979
|
return options.executor;
|
|
@@ -119396,6 +120013,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119396
120013
|
storageDir;
|
|
119397
120014
|
createModel;
|
|
119398
120015
|
generateText;
|
|
120016
|
+
memfsEnabledOverride;
|
|
119399
120017
|
constructor(options) {
|
|
119400
120018
|
const localBackendRef = {};
|
|
119401
120019
|
const modelConfig = resolveLocalModelConfig(options.storageDir);
|
|
@@ -119421,19 +120039,46 @@ var init_LocalBackend = __esm(() => {
|
|
|
119421
120039
|
this.memoryDir = options.memoryDir;
|
|
119422
120040
|
this.createModel = options.createModel;
|
|
119423
120041
|
this.generateText = options.generateText;
|
|
120042
|
+
this.memfsEnabledOverride = options.memfsEnabled;
|
|
119424
120043
|
}
|
|
119425
120044
|
async listModels() {
|
|
119426
120045
|
return listLocalModels(this.storageDir);
|
|
119427
120046
|
}
|
|
119428
120047
|
async createAgent(...args) {
|
|
119429
120048
|
const [body] = args;
|
|
119430
|
-
const
|
|
119431
|
-
|
|
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
|
+
}
|
|
119432
120061
|
await this.compileAndMaybePersistSystemPrompt("default", agent.id, {
|
|
119433
120062
|
dryRun: false
|
|
119434
120063
|
});
|
|
119435
120064
|
return agent;
|
|
119436
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
|
+
}
|
|
119437
120082
|
async createConversation(body) {
|
|
119438
120083
|
const conversation = await super.createConversation(body);
|
|
119439
120084
|
await this.compileAndMaybePersistSystemPrompt(conversation.id, conversation.agent_id, { dryRun: false });
|
|
@@ -119448,7 +120093,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119448
120093
|
async compactConversationMessages(conversationId, body) {
|
|
119449
120094
|
const bodyRecord = body ?? {};
|
|
119450
120095
|
const agentId = typeof bodyRecord.agent_id === "string" && bodyRecord.agent_id.length > 0 ? bodyRecord.agent_id : this.store.resolveAgentIdForConversation(conversationId);
|
|
119451
|
-
const result = await this.
|
|
120096
|
+
const result = await this.compactLocalConversation(conversationId, agentId, "manual", body);
|
|
119452
120097
|
return {
|
|
119453
120098
|
num_messages_before: result.numMessagesBefore,
|
|
119454
120099
|
num_messages_after: result.numMessagesAfter,
|
|
@@ -119463,6 +120108,9 @@ var init_LocalBackend = __esm(() => {
|
|
|
119463
120108
|
memoryDirForAgent(agentId) {
|
|
119464
120109
|
return this.memoryDir ?? getLocalBackendMemoryFilesystemRoot(agentId, this.storageDir);
|
|
119465
120110
|
}
|
|
120111
|
+
isLocalMemfsEnabled() {
|
|
120112
|
+
return this.memfsEnabledOverride ?? !isLocalBackendNoMemfsEnvEnabled();
|
|
120113
|
+
}
|
|
119466
120114
|
async ensureLocalMemoryRepo(agentId, files = [], authorName) {
|
|
119467
120115
|
await initializeLocalMemoryRepo({
|
|
119468
120116
|
memoryDir: this.memoryDirForAgent(agentId),
|
|
@@ -119472,9 +120120,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119472
120120
|
});
|
|
119473
120121
|
}
|
|
119474
120122
|
async compactAfterContextOverflow(input, _error) {
|
|
119475
|
-
const result = await this.
|
|
119476
|
-
compaction_settings: { mode: "all" }
|
|
119477
|
-
});
|
|
120123
|
+
const result = await this.compactLocalConversation(input.conversationId, input.agentId, "context_window_overflow");
|
|
119478
120124
|
return {
|
|
119479
120125
|
uiMessages: this.store.listLocalMessages(input.conversationId, input.agentId),
|
|
119480
120126
|
summary: result.summary,
|
|
@@ -119487,9 +120133,7 @@ var init_LocalBackend = __esm(() => {
|
|
|
119487
120133
|
if (contextTokens === undefined || contextWindow === undefined || contextTokens <= contextWindow) {
|
|
119488
120134
|
return null;
|
|
119489
120135
|
}
|
|
119490
|
-
const result = await this.
|
|
119491
|
-
compaction_settings: { mode: "all" }
|
|
119492
|
-
});
|
|
120136
|
+
const result = await this.compactLocalConversation(input.conversationId, input.agentId, "context_window_limit");
|
|
119493
120137
|
return {
|
|
119494
120138
|
uiMessages: this.store.listLocalMessages(input.conversationId, input.agentId),
|
|
119495
120139
|
summary: result.summary,
|
|
@@ -119508,24 +120152,55 @@ var init_LocalBackend = __esm(() => {
|
|
|
119508
120152
|
const agent = this.store.retrieveAgentRecord(agentId);
|
|
119509
120153
|
return typeof agent.model_settings.context_window_limit === "number" ? agent.model_settings.context_window_limit : undefined;
|
|
119510
120154
|
}
|
|
119511
|
-
|
|
119512
|
-
const
|
|
119513
|
-
const
|
|
119514
|
-
if (
|
|
119515
|
-
|
|
119516
|
-
}
|
|
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) {
|
|
119517
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) {
|
|
119518
120195
|
const messages = this.store.listLocalMessages(conversationId, agentId);
|
|
119519
120196
|
const contextTokensBefore = estimateLocalMessageTokens(messages);
|
|
119520
|
-
const prompt = typeof settings?.prompt === "string" ? settings.prompt : null;
|
|
119521
|
-
const clipChars = typeof settings?.clip_chars === "number" || settings?.clip_chars === null ? settings.clip_chars : undefined;
|
|
119522
120197
|
const summary = await summarizeLocalMessagesAll({
|
|
119523
120198
|
agent,
|
|
119524
120199
|
messages,
|
|
119525
120200
|
createModel: this.createModel,
|
|
119526
120201
|
generateText: this.generateText,
|
|
119527
|
-
prompt,
|
|
119528
|
-
clipChars,
|
|
120202
|
+
prompt: settings.prompt,
|
|
120203
|
+
clipChars: settings.clipChars,
|
|
119529
120204
|
localProviderAuthStorageDir: this.storageDir
|
|
119530
120205
|
});
|
|
119531
120206
|
const stats = {
|
|
@@ -119550,10 +120225,51 @@ var init_LocalBackend = __esm(() => {
|
|
|
119550
120225
|
stats
|
|
119551
120226
|
};
|
|
119552
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
|
+
}
|
|
119553
120268
|
async getOrCompileSystemPrompt(conversationId, agentId, agent = this.store.retrieveAgentRecord(agentId), previousMessageCount = 0) {
|
|
119554
120269
|
const existing = this.store.getCompiledSystemPrompt(conversationId, agentId);
|
|
119555
|
-
const
|
|
119556
|
-
|
|
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)) {
|
|
119557
120273
|
return existing;
|
|
119558
120274
|
}
|
|
119559
120275
|
return this.compileAndMaybePersistSystemPrompt(conversationId, agentId, {
|
|
@@ -119563,7 +120279,10 @@ var init_LocalBackend = __esm(() => {
|
|
|
119563
120279
|
}
|
|
119564
120280
|
async compileAndMaybePersistSystemPrompt(conversationId, agentId, options) {
|
|
119565
120281
|
const agent = this.store.retrieveAgentRecord(agentId);
|
|
119566
|
-
|
|
120282
|
+
const memfsEnabled = this.isLocalMemfsEnabled();
|
|
120283
|
+
if (memfsEnabled) {
|
|
120284
|
+
await this.ensureLocalMemoryRepo(agentId, [], agent.name);
|
|
120285
|
+
}
|
|
119567
120286
|
const previousMessageCount = options.previousMessageCount ?? this.store.listConversationMessages(conversationId, {
|
|
119568
120287
|
agent_id: agentId,
|
|
119569
120288
|
order: "asc"
|
|
@@ -119572,7 +120291,8 @@ var init_LocalBackend = __esm(() => {
|
|
|
119572
120291
|
agent,
|
|
119573
120292
|
conversationId,
|
|
119574
120293
|
previousMessageCount,
|
|
119575
|
-
memoryDir: this.memoryDirForAgent(agentId)
|
|
120294
|
+
memoryDir: memfsEnabled ? this.memoryDirForAgent(agentId) : undefined,
|
|
120295
|
+
includeMemfs: memfsEnabled
|
|
119576
120296
|
});
|
|
119577
120297
|
if (!options.dryRun) {
|
|
119578
120298
|
this.store.setCompiledSystemPrompt(conversationId, agentId, compiled);
|
|
@@ -119582,6 +120302,22 @@ var init_LocalBackend = __esm(() => {
|
|
|
119582
120302
|
};
|
|
119583
120303
|
});
|
|
119584
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
|
+
|
|
119585
120321
|
// src/backend/backend.ts
|
|
119586
120322
|
import { homedir as homedir19 } from "node:os";
|
|
119587
120323
|
|
|
@@ -119728,6 +120464,7 @@ function getBackend() {
|
|
|
119728
120464
|
}
|
|
119729
120465
|
function configureBackendMode(mode) {
|
|
119730
120466
|
configuredBackendMode = mode;
|
|
120467
|
+
process.env[LOCAL_BACKEND_EXPERIMENTAL_ENV] = mode === "local" ? "1" : "0";
|
|
119731
120468
|
backend = createBackendForMode(mode);
|
|
119732
120469
|
}
|
|
119733
120470
|
function isLocalBackendEnabled() {
|
|
@@ -143963,7 +144700,10 @@ function getTerminalTheme() {
|
|
|
143963
144700
|
cachedTheme = detectTerminalThemeSync();
|
|
143964
144701
|
return cachedTheme;
|
|
143965
144702
|
}
|
|
143966
|
-
|
|
144703
|
+
function getTerminalBackgroundColor() {
|
|
144704
|
+
return cachedBackground;
|
|
144705
|
+
}
|
|
144706
|
+
var cachedTheme = null, cachedBackground = null;
|
|
143967
144707
|
|
|
143968
144708
|
// src/cli/components/colors.ts
|
|
143969
144709
|
function parseHex(hex3) {
|
|
@@ -143974,6 +144714,26 @@ function parseHex(hex3) {
|
|
|
143974
144714
|
b: parseInt(h.slice(4, 6), 16)
|
|
143975
144715
|
};
|
|
143976
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
|
+
}
|
|
143977
144737
|
function hexToBgAnsi(hex3) {
|
|
143978
144738
|
const { r, g, b } = parseHex(hex3);
|
|
143979
144739
|
return `\x1B[48;2;${r};${g};${b}m`;
|
|
@@ -144146,9 +144906,8 @@ var init_colors = __esm(() => {
|
|
|
144146
144906
|
return getTerminalTheme() === "light" ? _colors.shellSyntaxLight : _colors.shellSyntaxDark;
|
|
144147
144907
|
},
|
|
144148
144908
|
get userMessage() {
|
|
144149
|
-
const theme = getTerminalTheme();
|
|
144150
144909
|
return {
|
|
144151
|
-
background:
|
|
144910
|
+
background: getCodexUserMessageBackground(),
|
|
144152
144911
|
text: undefined
|
|
144153
144912
|
};
|
|
144154
144913
|
}
|
|
@@ -146702,7 +147461,7 @@ var init_accountConfig3 = __esm(() => {
|
|
|
146702
147461
|
});
|
|
146703
147462
|
|
|
146704
147463
|
// src/channels/accountConfig.ts
|
|
146705
|
-
function
|
|
147464
|
+
function isRecord11(value) {
|
|
146706
147465
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
146707
147466
|
}
|
|
146708
147467
|
function getChannelAccountConfigAdapter(channelId) {
|
|
@@ -146713,7 +147472,7 @@ function getChannelPluginConfig(input, key = "config") {
|
|
|
146713
147472
|
if (value === undefined) {
|
|
146714
147473
|
return {};
|
|
146715
147474
|
}
|
|
146716
|
-
return
|
|
147475
|
+
return isRecord11(value) ? value : null;
|
|
146717
147476
|
}
|
|
146718
147477
|
function isValidChannelPluginConfigPayload(channelId, input, key = "config") {
|
|
146719
147478
|
const config2 = getChannelPluginConfig(input, key);
|
|
@@ -152919,6 +153678,13 @@ var init_approval_result_normalization = __esm(() => {
|
|
|
152919
153678
|
});
|
|
152920
153679
|
|
|
152921
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
|
+
});
|
|
152922
153688
|
import { existsSync as existsSync32, readdirSync as readdirSync11, realpathSync as realpathSync3, statSync as statSync8 } from "node:fs";
|
|
152923
153689
|
import { join as join34 } from "node:path";
|
|
152924
153690
|
function getCache2() {
|
|
@@ -153013,6 +153779,17 @@ function cloneResult(result) {
|
|
|
153013
153779
|
errors: result.errors.map((e) => ({ ...e }))
|
|
153014
153780
|
};
|
|
153015
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
|
+
}
|
|
153016
153793
|
function getMemorySkillsDirs2(agentId) {
|
|
153017
153794
|
const dirs = new Set;
|
|
153018
153795
|
const scopedMemoryDir = resolveScopedMemoryDir({ agentId });
|
|
@@ -153068,56 +153845,28 @@ function resolveSkillDiscoveryContext(options) {
|
|
|
153068
153845
|
function getPrimaryProjectSkillsDirectory() {
|
|
153069
153846
|
return join34(process.cwd(), ".agents", "skills");
|
|
153070
153847
|
}
|
|
153071
|
-
async function
|
|
153072
|
-
const { legacySkillsDirectory, skillSources } = resolveSkillDiscoveryContext(options);
|
|
153848
|
+
async function collectClientSideSkills(options) {
|
|
153073
153849
|
const discoverSkillsFn = options.discoverSkillsFn ?? discoverSkills;
|
|
153074
|
-
const useCache = !options.discoverSkillsFn;
|
|
153075
|
-
const cwd2 = process.cwd();
|
|
153076
|
-
const primaryProjectSkillsDirectory = getPrimaryProjectSkillsDirectory();
|
|
153077
|
-
const memorySkillsDirs = getMemorySkillsDirs2(options.agentId);
|
|
153078
|
-
const cacheComponents = {
|
|
153079
|
-
agentId: options.agentId,
|
|
153080
|
-
skillSources,
|
|
153081
|
-
cwd: cwd2,
|
|
153082
|
-
legacySkillsDirectory,
|
|
153083
|
-
primaryProjectSkillsDirectory,
|
|
153084
|
-
memorySkillsDirs,
|
|
153085
|
-
skillRootRevisions: getSkillRootRevisions({
|
|
153086
|
-
agentId: options.agentId,
|
|
153087
|
-
skillSources,
|
|
153088
|
-
legacySkillsDirectory,
|
|
153089
|
-
primaryProjectSkillsDirectory,
|
|
153090
|
-
memorySkillsDirs
|
|
153091
|
-
})
|
|
153092
|
-
};
|
|
153093
|
-
const cacheKey = computeCacheKey(cacheComponents);
|
|
153094
|
-
if (useCache) {
|
|
153095
|
-
const cache5 = getCache2();
|
|
153096
|
-
const cached2 = cache5.get(cacheKey);
|
|
153097
|
-
if (cached2) {
|
|
153098
|
-
return cloneResult(cached2.result);
|
|
153099
|
-
}
|
|
153100
|
-
}
|
|
153101
153850
|
const skillsById = new Map;
|
|
153102
153851
|
const errors4 = [];
|
|
153103
|
-
const nonProjectSources = skillSources
|
|
153852
|
+
const nonProjectSources = options.skillSources?.filter((source) => source !== "project") ?? [];
|
|
153104
153853
|
const discoveryRuns = [];
|
|
153105
153854
|
if (nonProjectSources.length > 0) {
|
|
153106
153855
|
discoveryRuns.push({
|
|
153107
|
-
path: primaryProjectSkillsDirectory,
|
|
153856
|
+
path: options.primaryProjectSkillsDirectory,
|
|
153108
153857
|
sources: nonProjectSources
|
|
153109
153858
|
});
|
|
153110
153859
|
}
|
|
153111
|
-
const includeProjectSource = skillSources
|
|
153112
|
-
if (includeProjectSource && legacySkillsDirectory !== primaryProjectSkillsDirectory) {
|
|
153860
|
+
const includeProjectSource = options.skillSources?.includes("project") ?? false;
|
|
153861
|
+
if (includeProjectSource && options.legacySkillsDirectory !== options.primaryProjectSkillsDirectory) {
|
|
153113
153862
|
discoveryRuns.push({
|
|
153114
|
-
path: legacySkillsDirectory,
|
|
153863
|
+
path: options.legacySkillsDirectory,
|
|
153115
153864
|
sources: ["project"]
|
|
153116
153865
|
});
|
|
153117
153866
|
}
|
|
153118
153867
|
if (includeProjectSource) {
|
|
153119
153868
|
discoveryRuns.push({
|
|
153120
|
-
path: primaryProjectSkillsDirectory,
|
|
153869
|
+
path: options.primaryProjectSkillsDirectory,
|
|
153121
153870
|
sources: ["project"]
|
|
153122
153871
|
});
|
|
153123
153872
|
}
|
|
@@ -153135,7 +153884,7 @@ async function buildClientSkillsPayload(options = {}) {
|
|
|
153135
153884
|
errors4.push({ path: run.path, message });
|
|
153136
153885
|
}
|
|
153137
153886
|
}
|
|
153138
|
-
if (skillSources
|
|
153887
|
+
if ((options.skillSources?.length ?? 0) > 0) {
|
|
153139
153888
|
const memoryDiscovery = await discoverMemorySkills(options.agentId);
|
|
153140
153889
|
errors4.push(...memoryDiscovery.errors);
|
|
153141
153890
|
for (const skill2 of memoryDiscovery.skills) {
|
|
@@ -153146,7 +153895,59 @@ async function buildClientSkillsPayload(options = {}) {
|
|
|
153146
153895
|
skillsById.set(skill2.id, skill2);
|
|
153147
153896
|
}
|
|
153148
153897
|
}
|
|
153149
|
-
|
|
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);
|
|
153150
153951
|
if (errors4.length > 0) {
|
|
153151
153952
|
const summarizedErrors = errors4.map((error51) => `${error51.path}: ${error51.message}`);
|
|
153152
153953
|
options.logger?.(`Failed to build some client_skills entries: ${summarizedErrors.join("; ")}`);
|
|
@@ -154033,7 +154834,7 @@ function markIncompleteToolsAsCancelled(b, setInterruptedFlag = true, reason = "
|
|
|
154033
154834
|
}
|
|
154034
154835
|
return anyToolsCancelled;
|
|
154035
154836
|
}
|
|
154036
|
-
function
|
|
154837
|
+
function isRecord12(v) {
|
|
154037
154838
|
return v !== null && typeof v === "object";
|
|
154038
154839
|
}
|
|
154039
154840
|
function getStringProp(obj, key) {
|
|
@@ -154044,9 +154845,9 @@ function extractTextPart(v) {
|
|
|
154044
154845
|
if (typeof v === "string")
|
|
154045
154846
|
return v;
|
|
154046
154847
|
if (Array.isArray(v)) {
|
|
154047
|
-
return v.map((p) =>
|
|
154848
|
+
return v.map((p) => isRecord12(p) ? getStringProp(p, "text") ?? "" : "").join("");
|
|
154048
154849
|
}
|
|
154049
|
-
if (
|
|
154850
|
+
if (isRecord12(v)) {
|
|
154050
154851
|
return getStringProp(v, "text") ?? getStringProp(v, "delta") ?? "";
|
|
154051
154852
|
}
|
|
154052
154853
|
return "";
|
|
@@ -155966,13 +156767,13 @@ function buildAgentInfo(options) {
|
|
|
155966
156767
|
}
|
|
155967
156768
|
const showMemoryDir = (() => {
|
|
155968
156769
|
try {
|
|
155969
|
-
return settingsManager.isMemfsEnabled(agentInfo.id);
|
|
156770
|
+
return isLocalBackendEnvEnabled() || settingsManager.isMemfsEnabled(agentInfo.id);
|
|
155970
156771
|
} catch {
|
|
155971
156772
|
return false;
|
|
155972
156773
|
}
|
|
155973
156774
|
})();
|
|
155974
156775
|
const memoryDirLine = showMemoryDir ? `
|
|
155975
|
-
- **Memory directory (also stored in \`MEMORY_DIR\` env var)**: \`${
|
|
156776
|
+
- **Memory directory (also stored in \`MEMORY_DIR\` env var)**: \`${getScopedMemoryFilesystemRoot(agentInfo.id)}\`` : "";
|
|
155976
156777
|
const convLine = conversationId ? `
|
|
155977
156778
|
- **Conversation ID (also stored in \`CONVERSATION_ID\` env var)**: ${conversationId}` : "";
|
|
155978
156779
|
return `${SYSTEM_REMINDER_OPEN} This is an automated message providing information about you.
|
|
@@ -155987,6 +156788,7 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
155987
156788
|
}
|
|
155988
156789
|
var init_agentInfo = __esm(() => {
|
|
155989
156790
|
init_memoryFilesystem();
|
|
156791
|
+
init_paths();
|
|
155990
156792
|
init_constants();
|
|
155991
156793
|
init_settings_manager();
|
|
155992
156794
|
});
|
|
@@ -158169,6 +158971,9 @@ function getApprovalToolCallDesyncErrorText(errorInfo) {
|
|
|
158169
158971
|
}
|
|
158170
158972
|
return null;
|
|
158171
158973
|
}
|
|
158974
|
+
function isBackendNotFoundError(error51) {
|
|
158975
|
+
return error51 instanceof APIError2 && (error51.status === 404 || error51.status === 422) || error51 instanceof Error && error51.name === "LocalBackendNotFoundError";
|
|
158976
|
+
}
|
|
158172
158977
|
function shouldAttemptPostStopApprovalRecovery(params) {
|
|
158173
158978
|
const approvalDesyncDetected = isApprovalToolCallDesyncError(params.runErrorDetail) || isApprovalToolCallDesyncError(params.latestErrorText) || isApprovalToolCallDesyncError(params.fallbackError);
|
|
158174
158979
|
return shouldAttemptApprovalRecovery({
|
|
@@ -158300,12 +159105,12 @@ async function debugLogApprovalResumeState(runtime, params) {
|
|
|
158300
159105
|
return;
|
|
158301
159106
|
}
|
|
158302
159107
|
try {
|
|
158303
|
-
const
|
|
158304
|
-
const agent = await
|
|
159108
|
+
const backend4 = getBackend();
|
|
159109
|
+
const agent = await backend4.retrieveAgent(params.agentId);
|
|
158305
159110
|
const isExplicitConversation = params.conversationId.length > 0 && params.conversationId !== "default";
|
|
158306
|
-
const lastInContextId = isExplicitConversation ? (await
|
|
158307
|
-
const lastInContextMessages = lastInContextId ? await
|
|
158308
|
-
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, {
|
|
158309
159114
|
includeMessageHistory: false
|
|
158310
159115
|
});
|
|
158311
159116
|
console.log("[Listen][DEBUG] Post-approval continuation resume snapshot", JSON.stringify({
|
|
@@ -158348,12 +159153,12 @@ async function recoverApprovalStateForSync(runtime, scope) {
|
|
|
158348
159153
|
clearRecoveredApprovalState(runtime);
|
|
158349
159154
|
return;
|
|
158350
159155
|
}
|
|
158351
|
-
const
|
|
159156
|
+
const backend4 = getBackend();
|
|
158352
159157
|
let agent;
|
|
158353
159158
|
try {
|
|
158354
|
-
agent = await
|
|
159159
|
+
agent = await backend4.retrieveAgent(scope.agent_id);
|
|
158355
159160
|
} catch (error51) {
|
|
158356
|
-
if (
|
|
159161
|
+
if (isBackendNotFoundError(error51)) {
|
|
158357
159162
|
clearRecoveredApprovalState(runtime);
|
|
158358
159163
|
return;
|
|
158359
159164
|
}
|
|
@@ -158361,11 +159166,11 @@ async function recoverApprovalStateForSync(runtime, scope) {
|
|
|
158361
159166
|
}
|
|
158362
159167
|
let resumeData;
|
|
158363
159168
|
try {
|
|
158364
|
-
resumeData = await
|
|
159169
|
+
resumeData = await getResumeDataFromBackend2(agent, scope.conversation_id, {
|
|
158365
159170
|
includeMessageHistory: false
|
|
158366
159171
|
});
|
|
158367
159172
|
} catch (error51) {
|
|
158368
|
-
if (
|
|
159173
|
+
if (isBackendNotFoundError(error51)) {
|
|
158369
159174
|
clearRecoveredApprovalState(runtime);
|
|
158370
159175
|
return;
|
|
158371
159176
|
}
|
|
@@ -158521,7 +159326,8 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
158521
159326
|
parentScope: recovered.agentId && recovered.conversationId ? {
|
|
158522
159327
|
agentId: recovered.agentId,
|
|
158523
159328
|
conversationId: recovered.conversationId
|
|
158524
|
-
} : undefined
|
|
159329
|
+
} : undefined,
|
|
159330
|
+
channelTurnSources: runtime.activeChannelTurnSources ?? undefined
|
|
158525
159331
|
});
|
|
158526
159332
|
} finally {
|
|
158527
159333
|
emitToolExecutionOutput.flush();
|
|
@@ -158579,7 +159385,6 @@ var init_recovery = __esm(async () => {
|
|
|
158579
159385
|
init_check_approval();
|
|
158580
159386
|
init_turn_recovery_policy();
|
|
158581
159387
|
init_backend2();
|
|
158582
|
-
init_client2();
|
|
158583
159388
|
init_formatDenial();
|
|
158584
159389
|
init_interactivePolicy();
|
|
158585
159390
|
init_constants2();
|
|
@@ -158631,16 +159436,19 @@ function markAwaitingAcceptedApprovalContinuationRunId(runtime, input) {
|
|
|
158631
159436
|
runtime.activeRunId = null;
|
|
158632
159437
|
}
|
|
158633
159438
|
}
|
|
159439
|
+
function isBackendNotFoundError2(err) {
|
|
159440
|
+
return err instanceof APIError2 && (err.status === 404 || err.status === 422) || err instanceof Error && err.name === "LocalBackendNotFoundError";
|
|
159441
|
+
}
|
|
158634
159442
|
async function resolveStaleApprovals(runtime, socket, abortSignal, deps = {}) {
|
|
158635
159443
|
if (!runtime.agentId)
|
|
158636
159444
|
return null;
|
|
158637
|
-
const getResumeDataImpl = deps.getResumeData ??
|
|
158638
|
-
const
|
|
159445
|
+
const getResumeDataImpl = deps.getResumeData ?? getResumeDataFromBackend2;
|
|
159446
|
+
const backend4 = getBackend();
|
|
158639
159447
|
let agent;
|
|
158640
159448
|
try {
|
|
158641
|
-
agent = await
|
|
159449
|
+
agent = await backend4.retrieveAgent(runtime.agentId);
|
|
158642
159450
|
} catch (err) {
|
|
158643
|
-
if (
|
|
159451
|
+
if (isBackendNotFoundError2(err)) {
|
|
158644
159452
|
return null;
|
|
158645
159453
|
}
|
|
158646
159454
|
throw err;
|
|
@@ -158648,11 +159456,11 @@ async function resolveStaleApprovals(runtime, socket, abortSignal, deps = {}) {
|
|
|
158648
159456
|
const requestedConversationId = runtime.conversationId !== "default" ? runtime.conversationId : undefined;
|
|
158649
159457
|
let resumeData;
|
|
158650
159458
|
try {
|
|
158651
|
-
resumeData = await getResumeDataImpl(
|
|
159459
|
+
resumeData = await getResumeDataImpl(agent, requestedConversationId, {
|
|
158652
159460
|
includeMessageHistory: false
|
|
158653
159461
|
});
|
|
158654
159462
|
} catch (err) {
|
|
158655
|
-
if (
|
|
159463
|
+
if (isBackendNotFoundError2(err)) {
|
|
158656
159464
|
return null;
|
|
158657
159465
|
}
|
|
158658
159466
|
throw err;
|
|
@@ -159018,7 +159826,6 @@ var init_send = __esm(async () => {
|
|
|
159018
159826
|
init_check_approval();
|
|
159019
159827
|
init_turn_recovery_policy();
|
|
159020
159828
|
init_backend2();
|
|
159021
|
-
init_client2();
|
|
159022
159829
|
init_errorFormatter();
|
|
159023
159830
|
init_streamAbortRelay();
|
|
159024
159831
|
init_constants2();
|
|
@@ -160773,7 +161580,7 @@ function formatArgsDisplay(argsJson, toolName) {
|
|
|
160773
161580
|
try {
|
|
160774
161581
|
if (argsJson?.trim()) {
|
|
160775
161582
|
const p = JSON.parse(argsJson);
|
|
160776
|
-
if (
|
|
161583
|
+
if (isRecord13(p)) {
|
|
160777
161584
|
const clone2 = { ...p };
|
|
160778
161585
|
if ("request_heartbeat" in clone2)
|
|
160779
161586
|
delete clone2.request_heartbeat;
|
|
@@ -160894,7 +161701,7 @@ function formatArgsDisplay(argsJson, toolName) {
|
|
|
160894
161701
|
}
|
|
160895
161702
|
return { display, parsed, shellSemantic };
|
|
160896
161703
|
}
|
|
160897
|
-
var
|
|
161704
|
+
var isRecord13 = (v) => typeof v === "object" && v !== null;
|
|
160898
161705
|
var init_formatArgsDisplay = __esm(async () => {
|
|
160899
161706
|
init_shellSemanticDisplay();
|
|
160900
161707
|
await init_toolNameMapping();
|
|
@@ -161391,6 +162198,7 @@ async function handleApprovalStop(params) {
|
|
|
161391
162198
|
onStreamingOutput: emitToolExecutionOutput,
|
|
161392
162199
|
workingDirectory: turnWorkingDirectory,
|
|
161393
162200
|
parentScope: agentId && conversationId ? { agentId, conversationId } : undefined,
|
|
162201
|
+
channelTurnSources: runtime.activeChannelTurnSources ?? undefined,
|
|
161394
162202
|
onFileWrite
|
|
161395
162203
|
});
|
|
161396
162204
|
} finally {
|
|
@@ -161516,9 +162324,8 @@ var init_turn_approval = __esm(async () => {
|
|
|
161516
162324
|
|
|
161517
162325
|
// src/websocket/listener/memfs-sync.ts
|
|
161518
162326
|
async function syncMemfsForAgent(agentId) {
|
|
161519
|
-
const {
|
|
161520
|
-
const
|
|
161521
|
-
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);
|
|
161522
162329
|
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
161523
162330
|
if (!agent.tags?.includes(GIT_MEMORY_ENABLED_TAG2)) {
|
|
161524
162331
|
debugLog("memfs-sync", `Agent ${agentId} does not have memfs tag, skipping`);
|
|
@@ -161555,8 +162362,7 @@ function getAgentMetadataPromise(listener, agentId) {
|
|
|
161555
162362
|
return listener.agentMetadataByAgent.get(agentId) ?? null;
|
|
161556
162363
|
}
|
|
161557
162364
|
async function fetchListenerAgentMetadata(agentId) {
|
|
161558
|
-
const
|
|
161559
|
-
const agent = await client.agents.retrieve(agentId);
|
|
162365
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
161560
162366
|
return {
|
|
161561
162367
|
name: agent.name ?? null,
|
|
161562
162368
|
description: agent.description ?? null,
|
|
@@ -161609,7 +162415,7 @@ function clearListenerWarmState(listener) {
|
|
|
161609
162415
|
}
|
|
161610
162416
|
var defaultWarmupDeps, warmupDeps;
|
|
161611
162417
|
var init_warmup = __esm(() => {
|
|
161612
|
-
|
|
162418
|
+
init_backend2();
|
|
161613
162419
|
init_debug();
|
|
161614
162420
|
init_memfs_sync();
|
|
161615
162421
|
init_secrets_sync();
|
|
@@ -161666,8 +162472,7 @@ function buildMaybeLaunchReflectionSubagent(params) {
|
|
|
161666
162472
|
let systemPrompt = cachedAgent?.system ?? undefined;
|
|
161667
162473
|
if (!systemPrompt) {
|
|
161668
162474
|
try {
|
|
161669
|
-
const
|
|
161670
|
-
const agent = await client.agents.retrieve(agentId);
|
|
162475
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
161671
162476
|
systemPrompt = agent.system ?? undefined;
|
|
161672
162477
|
} catch {
|
|
161673
162478
|
debugLog("memory", "Failed to fetch agent system prompt for reflection payload");
|
|
@@ -161844,8 +162649,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
161844
162649
|
syncReminderStateFromContextTracker(runtime.reminderState, runtime.contextTracker);
|
|
161845
162650
|
if (agentId) {
|
|
161846
162651
|
try {
|
|
161847
|
-
|
|
161848
|
-
cachedAgent = await client.agents.retrieve(agentId);
|
|
162652
|
+
cachedAgent = await getBackend().retrieveAgent(agentId);
|
|
161849
162653
|
} catch {}
|
|
161850
162654
|
}
|
|
161851
162655
|
if (!runtime.reminderState.hasSentAgentInfo && cachedAgent) {
|
|
@@ -162059,9 +162863,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
162059
162863
|
conversationId
|
|
162060
162864
|
});
|
|
162061
162865
|
try {
|
|
162062
|
-
const
|
|
162063
|
-
const
|
|
162064
|
-
const { pendingApprovals: existingApprovals } = await getResumeData(client, agent, requestedConversationId);
|
|
162866
|
+
const agent = await getBackend().retrieveAgent(agentId || "");
|
|
162867
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, requestedConversationId);
|
|
162065
162868
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
|
|
162066
162869
|
} catch {
|
|
162067
162870
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -162345,7 +163148,7 @@ var init_turn = __esm(async () => {
|
|
|
162345
163148
|
init_context();
|
|
162346
163149
|
init_memoryFilesystem();
|
|
162347
163150
|
init_turn_recovery_policy();
|
|
162348
|
-
|
|
163151
|
+
init_backend2();
|
|
162349
163152
|
init_errorFormatter();
|
|
162350
163153
|
init_memoryReminder();
|
|
162351
163154
|
init_memorySubagentCompletion();
|
|
@@ -162452,17 +163255,19 @@ function emitSlashCommandEnd(socket, runtime, scope, fields) {
|
|
|
162452
163255
|
emitCanonicalMessageDelta(socket, runtime, endDelta, scope);
|
|
162453
163256
|
}
|
|
162454
163257
|
async function handleClearCommand(_socket, conversationRuntime, opts) {
|
|
162455
|
-
const
|
|
163258
|
+
const backend4 = getBackend();
|
|
162456
163259
|
const agentId = conversationRuntime.agentId;
|
|
162457
163260
|
if (!agentId) {
|
|
162458
163261
|
throw new Error("No agent ID available for /clear command");
|
|
162459
163262
|
}
|
|
162460
|
-
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();
|
|
162461
163266
|
await client.agents.messages.reset(agentId, {
|
|
162462
163267
|
add_default_initial_messages: false
|
|
162463
163268
|
});
|
|
162464
163269
|
}
|
|
162465
|
-
const conversation = await
|
|
163270
|
+
const conversation = await backend4.createConversation({
|
|
162466
163271
|
agent_id: agentId,
|
|
162467
163272
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
162468
163273
|
});
|
|
@@ -162660,7 +163465,7 @@ var init_commands = __esm(async () => {
|
|
|
162660
163465
|
init_memory();
|
|
162661
163466
|
init_memoryFilesystem();
|
|
162662
163467
|
init_promptAssets();
|
|
162663
|
-
|
|
163468
|
+
init_backend2();
|
|
162664
163469
|
init_initCommand();
|
|
162665
163470
|
init_constants();
|
|
162666
163471
|
init_settings_manager();
|
|
@@ -164043,6 +164848,16 @@ function isExecuteCommandCommand(value) {
|
|
|
164043
164848
|
const hasValidArgs = c.args === undefined || typeof c.args === "string";
|
|
164044
164849
|
return c.type === "execute_command" && typeof c.command_id === "string" && typeof c.request_id === "string" && isRuntimeScope(c.runtime) && hasValidArgs;
|
|
164045
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
|
+
}
|
|
164046
164861
|
function parseServerMessage(data) {
|
|
164047
164862
|
try {
|
|
164048
164863
|
const raw = typeof data === "string" ? data : data.toString();
|
|
@@ -165538,11 +166353,12 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165538
166353
|
const buffer = encoding === "base64" ? Buffer.from(parsed.content, "base64") : Buffer.from(parsed.content, "utf-8");
|
|
165539
166354
|
await mkdir9(dirname20(absolutePath), { recursive: true });
|
|
165540
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;
|
|
165541
166359
|
let agentName = parsed.agent_id;
|
|
165542
166360
|
try {
|
|
165543
|
-
const
|
|
165544
|
-
const client = await getClient2();
|
|
165545
|
-
const agent = await client.agents.retrieve(parsed.agent_id);
|
|
166361
|
+
const agent = await backend4.retrieveAgent(parsed.agent_id);
|
|
165546
166362
|
if (agent.name && agent.name.trim().length > 0) {
|
|
165547
166363
|
agentName = agent.name.trim();
|
|
165548
166364
|
}
|
|
@@ -165558,6 +166374,7 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165558
166374
|
authorName: agentName,
|
|
165559
166375
|
authorEmail: `${parsed.agent_id}@letta.com`
|
|
165560
166376
|
},
|
|
166377
|
+
...memorySyncMode ? { syncMode: memorySyncMode } : {},
|
|
165561
166378
|
replay: async () => {
|
|
165562
166379
|
await mkdir9(dirname20(absolutePath), { recursive: true });
|
|
165563
166380
|
await writeFile11(absolutePath, buffer);
|
|
@@ -165652,11 +166469,12 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165652
166469
|
}, "listener_delete_memory_file_send_failed", "listener_delete_memory_file");
|
|
165653
166470
|
return;
|
|
165654
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;
|
|
165655
166475
|
let agentName = parsed.agent_id;
|
|
165656
166476
|
try {
|
|
165657
|
-
const
|
|
165658
|
-
const client = await getClient2();
|
|
165659
|
-
const agent = await client.agents.retrieve(parsed.agent_id);
|
|
166477
|
+
const agent = await backend4.retrieveAgent(parsed.agent_id);
|
|
165660
166478
|
if (agent.name && agent.name.trim().length > 0) {
|
|
165661
166479
|
agentName = agent.name.trim();
|
|
165662
166480
|
}
|
|
@@ -165671,6 +166489,7 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
165671
166489
|
authorName: agentName,
|
|
165672
166490
|
authorEmail: `${parsed.agent_id}@letta.com`
|
|
165673
166491
|
},
|
|
166492
|
+
...memorySyncMode ? { syncMode: memorySyncMode } : {},
|
|
165674
166493
|
replay: async () => {
|
|
165675
166494
|
await removeIfPresent();
|
|
165676
166495
|
return [pathspec];
|
|
@@ -168200,6 +169019,11 @@ function createListenerMessageHandler(params) {
|
|
|
168200
169019
|
const raw = data.toString();
|
|
168201
169020
|
let parsedScope = null;
|
|
168202
169021
|
try {
|
|
169022
|
+
const lifecycleMessage = parseServerLifecycleMessage(data);
|
|
169023
|
+
if (lifecycleMessage) {
|
|
169024
|
+
safeEmitWsEvent("recv", "lifecycle", lifecycleMessage);
|
|
169025
|
+
return;
|
|
169026
|
+
}
|
|
168203
169027
|
const parsed = parseServerMessage(data);
|
|
168204
169028
|
parsedScope = getParsedRuntimeScope(parsed);
|
|
168205
169029
|
if (parsed) {
|
|
@@ -169521,6 +170345,178 @@ var init_listen_client = __esm(async () => {
|
|
|
169521
170345
|
await init_client4();
|
|
169522
170346
|
});
|
|
169523
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
|
+
|
|
169524
170520
|
// src/utils/debug.ts
|
|
169525
170521
|
var exports_debug2 = {};
|
|
169526
170522
|
__export(exports_debug2, {
|
|
@@ -169662,6 +170658,12 @@ var init_version2 = __esm(() => {
|
|
|
169662
170658
|
// src/agent/skills.ts
|
|
169663
170659
|
var exports_skills2 = {};
|
|
169664
170660
|
__export(exports_skills2, {
|
|
170661
|
+
isUserInvocableSkill: () => isUserInvocableSkill2,
|
|
170662
|
+
isModelInvocableSkill: () => isModelInvocableSkill2,
|
|
170663
|
+
getLegacyAgentSkillsDir: () => getLegacyAgentSkillsDir2,
|
|
170664
|
+
getFrontmatterStringList: () => getFrontmatterStringList2,
|
|
170665
|
+
getFrontmatterString: () => getFrontmatterString2,
|
|
170666
|
+
getFrontmatterBoolean: () => getFrontmatterBoolean2,
|
|
169665
170667
|
getBundledSkills: () => getBundledSkills2,
|
|
169666
170668
|
getAgentSkillsDir: () => getAgentSkillsDir2,
|
|
169667
170669
|
formatSkillsAsSystemReminder: () => formatSkillsAsSystemReminder2,
|
|
@@ -169684,7 +170686,45 @@ function getBundledSkillsPath2() {
|
|
|
169684
170686
|
function compareSkills2(a, b) {
|
|
169685
170687
|
return a.id.localeCompare(b.id) || a.source.localeCompare(b.source) || a.path.localeCompare(b.path);
|
|
169686
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
|
+
}
|
|
169687
170724
|
function getAgentSkillsDir2(agentId) {
|
|
170725
|
+
return join42(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
170726
|
+
}
|
|
170727
|
+
function getLegacyAgentSkillsDir2(agentId) {
|
|
169688
170728
|
return join42(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
|
|
169689
170729
|
}
|
|
169690
170730
|
async function getBundledSkills2() {
|
|
@@ -169727,6 +170767,12 @@ async function discoverSkills2(projectSkillsPath = join42(process.cwd(), SKILLS_
|
|
|
169727
170767
|
}
|
|
169728
170768
|
}
|
|
169729
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
|
+
}
|
|
169730
170776
|
const agentSkillsDir = getAgentSkillsDir2(agentId);
|
|
169731
170777
|
const agentResult = await discoverSkillsFromDir2(agentSkillsDir, "agent");
|
|
169732
170778
|
allErrors.push(...agentResult.errors);
|
|
@@ -169810,7 +170856,7 @@ async function parseSkillFile2(filePath, rootPath, source) {
|
|
|
169810
170856
|
const defaultId = dirPath || "root";
|
|
169811
170857
|
const id = (typeof frontmatter.id === "string" ? frontmatter.id : null) || defaultId;
|
|
169812
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());
|
|
169813
|
-
let description =
|
|
170859
|
+
let description = getFrontmatterString2(frontmatter, "description") ?? null;
|
|
169814
170860
|
if (!description) {
|
|
169815
170861
|
const firstParagraph = body.trim().split(`
|
|
169816
170862
|
|
|
@@ -169818,30 +170864,31 @@ async function parseSkillFile2(filePath, rootPath, source) {
|
|
|
169818
170864
|
description = firstParagraph || "No description available";
|
|
169819
170865
|
}
|
|
169820
170866
|
description = description.trim();
|
|
169821
|
-
|
|
169822
|
-
|
|
169823
|
-
|
|
169824
|
-
|
|
169825
|
-
|
|
169826
|
-
tags = frontmatter.tags;
|
|
169827
|
-
} else if (typeof frontmatter.tags === "string") {
|
|
169828
|
-
tags = [frontmatter.tags];
|
|
169829
|
-
}
|
|
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");
|
|
169830
170872
|
return {
|
|
169831
170873
|
id,
|
|
169832
170874
|
name: name25,
|
|
169833
|
-
description,
|
|
169834
|
-
|
|
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"),
|
|
169835
170882
|
tags,
|
|
169836
170883
|
path: filePath,
|
|
169837
170884
|
source
|
|
169838
170885
|
};
|
|
169839
170886
|
}
|
|
169840
170887
|
function formatSkillsAsSystemReminder2(skills) {
|
|
169841
|
-
|
|
170888
|
+
const lines = skills.filter(isModelInvocableSkill2).sort(compareSkills2).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
170889
|
+
if (lines.length === 0) {
|
|
169842
170890
|
return "";
|
|
169843
170891
|
}
|
|
169844
|
-
const lines = [...skills].sort(compareSkills2).map((s) => `- ${s.id} (${s.source}): ${s.description}`);
|
|
169845
170892
|
return `<system-reminder>
|
|
169846
170893
|
The following skills are available for use with the Skill tool:
|
|
169847
170894
|
|
|
@@ -169906,6 +170953,7 @@ __export(exports_terminalTheme, {
|
|
|
169906
170953
|
parseHexComponent: () => parseHexComponent,
|
|
169907
170954
|
initTerminalTheme: () => initTerminalTheme,
|
|
169908
170955
|
getTerminalTheme: () => getTerminalTheme2,
|
|
170956
|
+
getTerminalBackgroundColor: () => getTerminalBackgroundColor2,
|
|
169909
170957
|
detectTerminalThemeSync: () => detectTerminalThemeSync2,
|
|
169910
170958
|
detectTerminalThemeAsync: () => detectTerminalThemeAsync,
|
|
169911
170959
|
calculateLuminance: () => calculateLuminance
|
|
@@ -169980,6 +171028,7 @@ function calculateLuminance(r, g, b) {
|
|
|
169980
171028
|
async function detectTerminalThemeAsync() {
|
|
169981
171029
|
const bg = await queryTerminalBackground(100);
|
|
169982
171030
|
if (bg) {
|
|
171031
|
+
cachedBackground2 = bg;
|
|
169983
171032
|
const luminance = calculateLuminance(bg.r, bg.g, bg.b);
|
|
169984
171033
|
return luminance > 0.4 ? "light" : "dark";
|
|
169985
171034
|
}
|
|
@@ -170008,11 +171057,14 @@ function getTerminalTheme2() {
|
|
|
170008
171057
|
cachedTheme2 = detectTerminalThemeSync2();
|
|
170009
171058
|
return cachedTheme2;
|
|
170010
171059
|
}
|
|
171060
|
+
function getTerminalBackgroundColor2() {
|
|
171061
|
+
return cachedBackground2;
|
|
171062
|
+
}
|
|
170011
171063
|
async function initTerminalTheme() {
|
|
170012
171064
|
cachedTheme2 = await detectTerminalThemeAsync();
|
|
170013
171065
|
return cachedTheme2;
|
|
170014
171066
|
}
|
|
170015
|
-
var cachedTheme2 = null;
|
|
171067
|
+
var cachedTheme2 = null, cachedBackground2 = null;
|
|
170016
171068
|
|
|
170017
171069
|
// src/agent/bootstrap-tools.ts
|
|
170018
171070
|
var exports_bootstrap_tools = {};
|
|
@@ -172207,15 +173259,19 @@ In headless mode, use:
|
|
|
172207
173259
|
const skillSourcesRaw = values["skill-sources"];
|
|
172208
173260
|
const memfsFlag = values.memfs;
|
|
172209
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
|
+
}
|
|
172210
173266
|
const memfsStartupRaw = values["memfs-startup"];
|
|
172211
173267
|
const memfsStartupPolicy = memfsStartupRaw === "background" || memfsStartupRaw === "skip" ? memfsStartupRaw : "blocking";
|
|
172212
|
-
const requestedMemoryPromptMode = memfsFlag ? "memfs" : noMemfsFlag ? "standard" : undefined;
|
|
173268
|
+
const requestedMemoryPromptMode = memfsFlag ? "memfs" : noMemfsFlag || localNoMemfsRequested ? "standard" : undefined;
|
|
172213
173269
|
if (memfsFlag && !backend4.capabilities.remoteMemfs) {
|
|
172214
173270
|
trackHeadlessBoundaryError("headless_memfs_unsupported_backend", "MemFS requires a backend with remote MemFS support", "headless_startup_memfs_flags");
|
|
172215
173271
|
console.error("Error: --memfs is not supported by this backend yet");
|
|
172216
173272
|
process.exit(1);
|
|
172217
173273
|
}
|
|
172218
|
-
const shouldAutoEnableMemfsForNewAgent = !memfsFlag && !noMemfsFlag;
|
|
173274
|
+
const shouldAutoEnableMemfsForNewAgent = !memfsFlag && !noMemfsFlag && !localNoMemfsRequested;
|
|
172219
173275
|
const fromAfFile = resolveImportFlagAlias2({
|
|
172220
173276
|
importFlagValue: values.import,
|
|
172221
173277
|
fromAfFlagValue: values["from-af"]
|
|
@@ -172495,7 +173551,7 @@ In headless mode, use:
|
|
|
172495
173551
|
if (!agent && forceNew) {
|
|
172496
173552
|
const { isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
172497
173553
|
const willAutoEnableMemfs = backend4.capabilities.remoteMemfs && shouldAutoEnableMemfsForNewAgent && await isLettaCloud2();
|
|
172498
|
-
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);
|
|
172499
173555
|
const personalityOptions = personality ? await buildCreateAgentOptionsForPersonality2({
|
|
172500
173556
|
personalityId: personality,
|
|
172501
173557
|
model,
|
|
@@ -172597,12 +173653,8 @@ In headless mode, use:
|
|
|
172597
173653
|
const secretsInitPromise = secretsAgentId ? Promise.resolve().then(() => (init_secretsStore(), exports_secretsStore)).then(({ initSecretsFromServer: initSecretsFromServer2 }) => initSecretsFromServer2(secretsAgentId, agent ?? undefined)) : Promise.resolve();
|
|
172598
173654
|
if (!backend4.capabilities.remoteMemfs) {
|
|
172599
173655
|
if (backend4.capabilities.localMemfs) {
|
|
172600
|
-
|
|
172601
|
-
|
|
172602
|
-
process.exit(1);
|
|
172603
|
-
}
|
|
172604
|
-
settingsManager.setMemfsEnabled(agent.id, true);
|
|
172605
|
-
} else if (noMemfsFlag) {
|
|
173656
|
+
settingsManager.setMemfsEnabled(agent.id, !localNoMemfsRequested);
|
|
173657
|
+
} else if (noMemfsFlag || localNoMemfsRequested) {
|
|
172606
173658
|
settingsManager.setMemfsEnabled(agent.id, false);
|
|
172607
173659
|
}
|
|
172608
173660
|
} else if (memfsStartupPolicy === "skip") {
|
|
@@ -174578,6 +175630,7 @@ var init_headless = __esm(async () => {
|
|
|
174578
175630
|
init_personality();
|
|
174579
175631
|
init_skillSources();
|
|
174580
175632
|
init_backend2();
|
|
175633
|
+
init_paths();
|
|
174581
175634
|
init_errorFormatter();
|
|
174582
175635
|
init_memoryReminder();
|
|
174583
175636
|
init_messageQueueBridge();
|
|
@@ -175420,8 +176473,7 @@ async function handleProfileSave(ctx, msg, profileName) {
|
|
|
175420
176473
|
const cmdId = addCommandResult2(ctx.buffersRef, ctx.refreshDerived, msg, `Saving profile "${profileName}"...`, false, "running");
|
|
175421
176474
|
ctx.setCommandRunning(true);
|
|
175422
176475
|
try {
|
|
175423
|
-
|
|
175424
|
-
await client.agents.update(ctx.agentId, { name: profileName });
|
|
176476
|
+
await getBackend().updateAgent(ctx.agentId, { name: profileName });
|
|
175425
176477
|
ctx.updateAgentName(profileName);
|
|
175426
176478
|
settingsManager.saveProfile(profileName, ctx.agentId);
|
|
175427
176479
|
updateCommandResult2(ctx.buffersRef, ctx.refreshDerived, cmdId, msg, `Pinned "${profileName}" locally and globally.`, true);
|
|
@@ -175503,9 +176555,7 @@ async function handlePin(ctx, msg, argsStr) {
|
|
|
175503
176555
|
const globalPinned = settingsManager.getGlobalPinnedAgents();
|
|
175504
176556
|
if (name25 && name25 !== ctx.agentName) {
|
|
175505
176557
|
try {
|
|
175506
|
-
|
|
175507
|
-
const client = await getClient2();
|
|
175508
|
-
await client.agents.update(ctx.agentId, { name: name25 });
|
|
176558
|
+
await getBackend().updateAgent(ctx.agentId, { name: name25 });
|
|
175509
176559
|
ctx.updateAgentName(name25);
|
|
175510
176560
|
} catch (error51) {
|
|
175511
176561
|
addCommandResult2(ctx.buffersRef, ctx.refreshDerived, msg, `Failed to rename agent: ${error51}`, false);
|
|
@@ -175552,7 +176602,7 @@ function handleUnpin(ctx, msg, argsStr) {
|
|
|
175552
176602
|
}
|
|
175553
176603
|
var activeCommandId2 = null;
|
|
175554
176604
|
var init_profile = __esm(() => {
|
|
175555
|
-
|
|
176605
|
+
init_backend2();
|
|
175556
176606
|
init_settings_manager();
|
|
175557
176607
|
init_errorFormatter();
|
|
175558
176608
|
});
|
|
@@ -190710,7 +191760,7 @@ function highlightCode(code, language) {
|
|
|
190710
191760
|
}
|
|
190711
191761
|
return lines;
|
|
190712
191762
|
}
|
|
190713
|
-
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;
|
|
190714
191764
|
var init_SyntaxHighlightedCommand = __esm(async () => {
|
|
190715
191765
|
init_lowlight();
|
|
190716
191766
|
init_colors();
|
|
@@ -190811,9 +191861,13 @@ var init_SyntaxHighlightedCommand = __esm(async () => {
|
|
|
190811
191861
|
const lineKey = spans.map((s) => s.text).join("");
|
|
190812
191862
|
return /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Box_default, {
|
|
190813
191863
|
children: [
|
|
190814
|
-
showPrompt ? /* @__PURE__ */ jsx_dev_runtime12.jsxDEV(
|
|
190815
|
-
|
|
190816
|
-
|
|
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
|
|
190817
191871
|
}, undefined, false, undefined, this) : null,
|
|
190818
191872
|
/* @__PURE__ */ jsx_dev_runtime12.jsxDEV(Text2, {
|
|
190819
191873
|
color: palette.text,
|
|
@@ -199525,6 +200579,7 @@ function boxBottom(width) {
|
|
|
199525
200579
|
}
|
|
199526
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;
|
|
199527
200581
|
var init_HooksManager = __esm(async () => {
|
|
200582
|
+
init_backend2();
|
|
199528
200583
|
init_types3();
|
|
199529
200584
|
init_writer();
|
|
199530
200585
|
init_settings_manager();
|
|
@@ -199597,6 +200652,9 @@ var init_HooksManager = __esm(async () => {
|
|
|
199597
200652
|
return;
|
|
199598
200653
|
const fetchAgentTools = async () => {
|
|
199599
200654
|
try {
|
|
200655
|
+
if (!getBackend().capabilities.serverSideToolManagement) {
|
|
200656
|
+
return;
|
|
200657
|
+
}
|
|
199600
200658
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
199601
200659
|
const client = await getClient2();
|
|
199602
200660
|
const toolsPage = await client.agents.tools.list(agentId, {
|
|
@@ -202384,6 +203442,7 @@ function SlashCommandAutocomplete({
|
|
|
202384
203442
|
}) {
|
|
202385
203443
|
const columns = useTerminalWidth();
|
|
202386
203444
|
const [customCommands, setCustomCommands] = import_react72.useState([]);
|
|
203445
|
+
const [skillCommands, setSkillCommands] = import_react72.useState([]);
|
|
202387
203446
|
import_react72.useEffect(() => {
|
|
202388
203447
|
Promise.resolve().then(() => (init_custom(), exports_custom)).then(({ getCustomCommands: getCustomCommands2 }) => {
|
|
202389
203448
|
getCustomCommands2().then((customs) => {
|
|
@@ -202396,6 +203455,35 @@ function SlashCommandAutocomplete({
|
|
|
202396
203455
|
});
|
|
202397
203456
|
});
|
|
202398
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]);
|
|
202399
203487
|
const allCommands = import_react72.useMemo(() => {
|
|
202400
203488
|
let builtins = _allCommands;
|
|
202401
203489
|
if (agentId) {
|
|
@@ -202419,8 +203507,13 @@ function SlashCommandAutocomplete({
|
|
|
202419
203507
|
builtins = _allCommands;
|
|
202420
203508
|
}
|
|
202421
203509
|
}
|
|
202422
|
-
|
|
202423
|
-
|
|
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]);
|
|
202424
203517
|
const queryInfo = import_react72.useMemo(() => extractSearchQuery2(currentInput, cursorPosition), [currentInput, cursorPosition]);
|
|
202425
203518
|
const { matches, showNoMatches, hideAutocomplete } = import_react72.useMemo(() => {
|
|
202426
203519
|
if (!queryInfo) {
|
|
@@ -209433,8 +210526,7 @@ function MemoryTabViewer({
|
|
|
209433
210526
|
import_react81.useEffect(() => {
|
|
209434
210527
|
const fetchBlocks = async () => {
|
|
209435
210528
|
try {
|
|
209436
|
-
const
|
|
209437
|
-
const agent = await client.agents.retrieve(agentId, {
|
|
210529
|
+
const agent = await getBackend().retrieveAgent(agentId, {
|
|
209438
210530
|
include: ["agent.blocks"]
|
|
209439
210531
|
});
|
|
209440
210532
|
setFreshBlocks(agent.memory?.blocks || []);
|
|
@@ -209711,7 +210803,7 @@ function MemoryTabViewer({
|
|
|
209711
210803
|
}
|
|
209712
210804
|
var import_react81, jsx_dev_runtime58, SOLID_LINE21 = "─", VISIBLE_LINES = 12;
|
|
209713
210805
|
var init_MemoryTabViewer = __esm(async () => {
|
|
209714
|
-
|
|
210806
|
+
init_backend2();
|
|
209715
210807
|
init_debug();
|
|
209716
210808
|
init_useTerminalWidth();
|
|
209717
210809
|
init_colors();
|
|
@@ -209725,24 +210817,13 @@ var init_MemoryTabViewer = __esm(async () => {
|
|
|
209725
210817
|
jsx_dev_runtime58 = __toESM(require_jsx_dev_runtime(), 1);
|
|
209726
210818
|
});
|
|
209727
210819
|
|
|
209728
|
-
// src/backend/api/search.ts
|
|
209729
|
-
async function warmSearchCache(body) {
|
|
209730
|
-
return apiRequest("POST", "/v1/_internal_search/cache-warm", body);
|
|
209731
|
-
}
|
|
209732
|
-
async function searchMessages(body) {
|
|
209733
|
-
return apiRequest("POST", "/v1/messages/search", body);
|
|
209734
|
-
}
|
|
209735
|
-
var init_search = __esm(() => {
|
|
209736
|
-
init_request();
|
|
209737
|
-
});
|
|
209738
|
-
|
|
209739
210820
|
// src/cli/components/MessageSearch.tsx
|
|
209740
210821
|
async function warmMessageSearchCache() {
|
|
209741
210822
|
const body = {
|
|
209742
210823
|
collection: "messages",
|
|
209743
210824
|
scope: {}
|
|
209744
210825
|
};
|
|
209745
|
-
return
|
|
210826
|
+
return warmMessageSearchCacheForBackend(body);
|
|
209746
210827
|
}
|
|
209747
210828
|
function isSearchRangeAvailable(range2, options) {
|
|
209748
210829
|
if (range2 === "agent")
|
|
@@ -209881,7 +210962,7 @@ function MessageSearch({
|
|
|
209881
210962
|
} else if (range2 === "conv" && conversationId) {
|
|
209882
210963
|
body.conversation_id = conversationId;
|
|
209883
210964
|
}
|
|
209884
|
-
return
|
|
210965
|
+
return searchMessagesForBackend(body);
|
|
209885
210966
|
}, [agentId, conversationId]);
|
|
209886
210967
|
const fetchAndCacheSearchResults = import_react82.useCallback(async (query, mode, range2) => {
|
|
209887
210968
|
const cacheKey = getCacheKey(query, mode, range2);
|
|
@@ -210354,7 +211435,7 @@ function MessageSearch({
|
|
|
210354
211435
|
}
|
|
210355
211436
|
var import_react82, jsx_dev_runtime59, SOLID_LINE22 = "─", VISIBLE_ITEMS = 5, SEARCH_LIMIT = 100, SEARCH_MODES, SEARCH_RANGES;
|
|
210356
211437
|
var init_MessageSearch = __esm(async () => {
|
|
210357
|
-
|
|
211438
|
+
init_messageSearch();
|
|
210358
211439
|
init_useTerminalWidth();
|
|
210359
211440
|
init_colors();
|
|
210360
211441
|
await __promiseAll([
|
|
@@ -212682,7 +213763,7 @@ function getTabDescription(tab2, agentId) {
|
|
|
212682
213763
|
case "project":
|
|
212683
213764
|
return ".skills/";
|
|
212684
213765
|
case "agent":
|
|
212685
|
-
return `~/.letta/agents/${shortId}/skills/`;
|
|
213766
|
+
return `~/.letta/agents/${shortId}/memory/skills/`;
|
|
212686
213767
|
case "global":
|
|
212687
213768
|
return "~/.letta/skills/";
|
|
212688
213769
|
case "bundled":
|
|
@@ -212722,7 +213803,7 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
212722
213803
|
}
|
|
212723
213804
|
return grouped;
|
|
212724
213805
|
}, [skills]);
|
|
212725
|
-
const availableTabs = import_react91.useMemo(() => TAB_ORDER
|
|
213806
|
+
const availableTabs = import_react91.useMemo(() => [...TAB_ORDER], []);
|
|
212726
213807
|
const [activeTab, setActiveTab] = import_react91.useState(null);
|
|
212727
213808
|
import_react91.useEffect(() => {
|
|
212728
213809
|
if (!loading && availableTabs.length > 0 && activeTab === null) {
|
|
@@ -212876,13 +213957,20 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
212876
213957
|
}, undefined, false, undefined, this) : null
|
|
212877
213958
|
]
|
|
212878
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),
|
|
212879
213967
|
/* @__PURE__ */ jsx_dev_runtime68.jsxDEV(Box_default, {
|
|
212880
213968
|
marginTop: 1,
|
|
212881
213969
|
children: /* @__PURE__ */ jsx_dev_runtime68.jsxDEV(Text2, {
|
|
212882
213970
|
dimColor: true,
|
|
212883
213971
|
children: [
|
|
212884
213972
|
" ",
|
|
212885
|
-
|
|
213973
|
+
"↑↓ scroll · ←→/Tab switch · Esc to close"
|
|
212886
213974
|
]
|
|
212887
213975
|
}, undefined, true, undefined, this)
|
|
212888
213976
|
}, undefined, false, undefined, this)
|
|
@@ -215187,7 +216275,7 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215187
216275
|
let shellCommand = null;
|
|
215188
216276
|
let shellSemanticKind = null;
|
|
215189
216277
|
if (!isQuestionTool(rawName)) {
|
|
215190
|
-
const
|
|
216278
|
+
const parseArgs9 = () => {
|
|
215191
216279
|
if (!argsText.trim()) {
|
|
215192
216280
|
return { formatted: null, parseable: true };
|
|
215193
216281
|
}
|
|
@@ -215198,7 +216286,7 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215198
216286
|
return { formatted: null, parseable: false };
|
|
215199
216287
|
}
|
|
215200
216288
|
};
|
|
215201
|
-
const { formatted, parseable } =
|
|
216289
|
+
const { formatted, parseable } = parseArgs9();
|
|
215202
216290
|
const argsComplete = parseable || line.phase === "running" || line.phase === "finished" || !isStreaming;
|
|
215203
216291
|
if (!argsComplete) {
|
|
215204
216292
|
args = "(…)";
|
|
@@ -215311,13 +216399,13 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215311
216399
|
}, undefined, true, undefined, this);
|
|
215312
216400
|
}
|
|
215313
216401
|
const displayResultText = clipToolReturn(extractedText).replace(/\n+$/, "");
|
|
215314
|
-
const
|
|
216402
|
+
const isRecord14 = (v) => typeof v === "object" && v !== null;
|
|
215315
216403
|
if (isTodoTool(rawName, displayName) && line.resultOk !== false && line.argsText) {
|
|
215316
216404
|
try {
|
|
215317
216405
|
const parsedArgs = JSON.parse(line.argsText);
|
|
215318
216406
|
if (parsedArgs.todos && Array.isArray(parsedArgs.todos)) {
|
|
215319
216407
|
const safeTodos = parsedArgs.todos.map((t, i) => {
|
|
215320
|
-
const rec =
|
|
216408
|
+
const rec = isRecord14(t) ? t : {};
|
|
215321
216409
|
const status = rec.status === "completed" ? "completed" : rec.status === "in_progress" ? "in_progress" : "pending";
|
|
215322
216410
|
const id = typeof rec.id === "string" ? rec.id : String(i);
|
|
215323
216411
|
const content = typeof rec.content === "string" ? rec.content : typeof rec.description === "string" ? rec.description : JSON.stringify(t);
|
|
@@ -215335,7 +216423,7 @@ var init_ToolCallMessageRich = __esm(async () => {
|
|
|
215335
216423
|
const parsedArgs = JSON.parse(line.argsText);
|
|
215336
216424
|
if (parsedArgs.plan && Array.isArray(parsedArgs.plan)) {
|
|
215337
216425
|
const safePlan = parsedArgs.plan.map((item) => {
|
|
215338
|
-
const rec =
|
|
216426
|
+
const rec = isRecord14(item) ? item : {};
|
|
215339
216427
|
const status = rec.status === "completed" ? "completed" : rec.status === "in_progress" ? "in_progress" : "pending";
|
|
215340
216428
|
const step = typeof rec.step === "string" ? rec.step : JSON.stringify(item);
|
|
215341
216429
|
return { step, status };
|
|
@@ -216152,6 +217240,27 @@ var init_TrajectorySummary = __esm(async () => {
|
|
|
216152
217240
|
});
|
|
216153
217241
|
|
|
216154
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
|
+
}
|
|
216155
217264
|
function wordWrap(text2, width) {
|
|
216156
217265
|
if (width <= 0)
|
|
216157
217266
|
return [text2];
|
|
@@ -216163,7 +217272,7 @@ function wordWrap(text2, width) {
|
|
|
216163
217272
|
current = word;
|
|
216164
217273
|
} else {
|
|
216165
217274
|
const candidate = `${current} ${word}`;
|
|
216166
|
-
if (
|
|
217275
|
+
if (inkStringWidth(candidate) <= width) {
|
|
216167
217276
|
current = candidate;
|
|
216168
217277
|
} else {
|
|
216169
217278
|
lines.push(current);
|
|
@@ -216211,7 +217320,11 @@ function splitSystemReminderBlocks(text2) {
|
|
|
216211
217320
|
}
|
|
216212
217321
|
return blocks;
|
|
216213
217322
|
}
|
|
216214
|
-
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) {
|
|
216215
217328
|
const inputLines = text2.split(`
|
|
216216
217329
|
`);
|
|
216217
217330
|
const outputLines = [];
|
|
@@ -216227,34 +217340,39 @@ function renderBlock(text2, contentWidth, columns, highlighted, colorAnsi, promp
|
|
|
216227
217340
|
}
|
|
216228
217341
|
if (outputLines.length === 0)
|
|
216229
217342
|
return [];
|
|
216230
|
-
const
|
|
216231
|
-
return outputLines.map((ol, i) => {
|
|
217343
|
+
const renderedLines = outputLines.map((ol, i) => {
|
|
216232
217344
|
const prefix = i === 0 ? promptPrefix : continuationPrefix;
|
|
217345
|
+
const content = `${prefix}${ol}`;
|
|
216233
217346
|
if (!highlighted) {
|
|
216234
|
-
return
|
|
216235
|
-
}
|
|
216236
|
-
const content = i === 0 ? `${promptPrefix.slice(0, -1)}${colorAnsi} ${ol}` : `${prefix}${ol}`;
|
|
216237
|
-
const visWidth = stringWidth(content);
|
|
216238
|
-
if (isSingleLine) {
|
|
216239
|
-
return `${colorAnsi}${content}${" ".repeat(COMPACT_PAD)}\x1B[0m`;
|
|
217347
|
+
return { text: content, highlighted: false };
|
|
216240
217348
|
}
|
|
216241
|
-
|
|
216242
|
-
return `${colorAnsi}${content}${" ".repeat(pad)}\x1B[0m`;
|
|
217349
|
+
return { text: padToColumns(content, columns), highlighted: true };
|
|
216243
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];
|
|
216244
217359
|
}
|
|
216245
|
-
var import_react101, jsx_dev_runtime81,
|
|
217360
|
+
var import_react101, jsx_dev_runtime81, UserMessage;
|
|
216246
217361
|
var init_UserMessageRich = __esm(async () => {
|
|
216247
|
-
init_string_width();
|
|
216248
217362
|
init_constants();
|
|
216249
217363
|
init_useTerminalWidth();
|
|
216250
217364
|
init_colors();
|
|
216251
|
-
await
|
|
217365
|
+
await __promiseAll([
|
|
217366
|
+
init_build2(),
|
|
217367
|
+
init_Text2()
|
|
217368
|
+
]);
|
|
216252
217369
|
import_react101 = __toESM(require_react(), 1);
|
|
216253
217370
|
jsx_dev_runtime81 = __toESM(require_jsx_dev_runtime(), 1);
|
|
216254
217371
|
UserMessage = import_react101.memo(({ line, prompt }) => {
|
|
216255
|
-
const
|
|
217372
|
+
const trackedColumns2 = useTerminalWidth();
|
|
217373
|
+
const columns = getCurrentStdoutColumns() ?? trackedColumns2;
|
|
216256
217374
|
const promptPrefix = `${prompt || ">"} `;
|
|
216257
|
-
const prefixWidth =
|
|
217375
|
+
const prefixWidth = inkStringWidth(promptPrefix);
|
|
216258
217376
|
const continuationPrefix = " ".repeat(prefixWidth);
|
|
216259
217377
|
const contentWidth = Math.max(1, columns - prefixWidth);
|
|
216260
217378
|
const cleanedText = extractTaskNotificationsForDisplay(line.text).cleanedText;
|
|
@@ -216263,23 +217381,25 @@ var init_UserMessageRich = __esm(async () => {
|
|
|
216263
217381
|
return null;
|
|
216264
217382
|
}
|
|
216265
217383
|
const { background, text: textColor } = colors.userMessage;
|
|
216266
|
-
const bgAnsi = hexToBgAnsi(background);
|
|
216267
|
-
const fgAnsi = textColor ? hexToFgAnsi(textColor) : "";
|
|
216268
|
-
const colorAnsi = bgAnsi + fgAnsi;
|
|
216269
217384
|
const blocks = splitSystemReminderBlocks(displayText);
|
|
216270
217385
|
const allLines = [];
|
|
216271
217386
|
for (const block of blocks) {
|
|
216272
217387
|
if (!block.text.trim())
|
|
216273
217388
|
continue;
|
|
216274
217389
|
if (allLines.length > 0) {
|
|
216275
|
-
allLines.push("");
|
|
217390
|
+
allLines.push({ text: "", highlighted: false });
|
|
216276
217391
|
}
|
|
216277
|
-
const blockLines = renderBlock(block.text, contentWidth, columns, !block.isSystemReminder,
|
|
217392
|
+
const blockLines = renderBlock(block.text, contentWidth, columns, !block.isSystemReminder, promptPrefix, continuationPrefix);
|
|
216278
217393
|
allLines.push(...blockLines);
|
|
216279
217394
|
}
|
|
216280
|
-
return /* @__PURE__ */ jsx_dev_runtime81.jsxDEV(
|
|
216281
|
-
|
|
216282
|
-
|
|
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))
|
|
216283
217403
|
}, undefined, false, undefined, this);
|
|
216284
217404
|
});
|
|
216285
217405
|
UserMessage.displayName = "UserMessage";
|
|
@@ -217761,7 +218881,7 @@ function updateCommandResult3(buffersRef, refreshDerived, cmdId, input, output,
|
|
|
217761
218881
|
buffersRef.current.byId.set(cmdId, line);
|
|
217762
218882
|
refreshDerived();
|
|
217763
218883
|
}
|
|
217764
|
-
function
|
|
218884
|
+
function parseArgs9(msg) {
|
|
217765
218885
|
return msg.trim().split(/\s+/).filter(Boolean);
|
|
217766
218886
|
}
|
|
217767
218887
|
function formatConnectUsage() {
|
|
@@ -217961,7 +219081,7 @@ ${formatBedrockUsage2()}`, false);
|
|
|
217961
219081
|
}
|
|
217962
219082
|
}
|
|
217963
219083
|
async function handleConnect(ctx, msg) {
|
|
217964
|
-
const parts =
|
|
219084
|
+
const parts = parseArgs9(msg);
|
|
217965
219085
|
const providerToken = parts[1];
|
|
217966
219086
|
if (!providerToken) {
|
|
217967
219087
|
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, formatConnectUsage(), false);
|
|
@@ -218077,7 +219197,7 @@ The '${CLAUDE_PROVIDER_NAME}' provider does not exist in your Letta account.`, f
|
|
|
218077
219197
|
}
|
|
218078
219198
|
}
|
|
218079
219199
|
async function handleDisconnect(ctx, msg) {
|
|
218080
|
-
const parts =
|
|
219200
|
+
const parts = parseArgs9(msg);
|
|
218081
219201
|
const providerToken = parts[1]?.toLowerCase();
|
|
218082
219202
|
if (providerToken === "help") {
|
|
218083
219203
|
addCommandResult3(ctx.buffersRef, ctx.refreshDerived, msg, formatDisconnectHelp(), true);
|
|
@@ -220379,9 +221499,8 @@ function App2({
|
|
|
220379
221499
|
return;
|
|
220380
221500
|
}
|
|
220381
221501
|
try {
|
|
220382
|
-
const client = await getClient();
|
|
220383
221502
|
debugLog("conversations", `retrieve(${conversationId}) [syncConversationModel]`);
|
|
220384
|
-
const conversation = await
|
|
221503
|
+
const conversation = await getBackend().retrieveConversation(conversationId);
|
|
220385
221504
|
if (cancelled)
|
|
220386
221505
|
return;
|
|
220387
221506
|
const conversationModel = conversation.model;
|
|
@@ -220813,9 +221932,8 @@ ${newState.originalPrompt}`,
|
|
|
220813
221932
|
})) {
|
|
220814
221933
|
llmApiErrorRetriesRef.current += 1;
|
|
220815
221934
|
try {
|
|
220816
|
-
const
|
|
220817
|
-
const
|
|
220818
|
-
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);
|
|
220819
221937
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
|
|
220820
221938
|
} catch {
|
|
220821
221939
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -220964,9 +222082,8 @@ ${newState.originalPrompt}`,
|
|
|
220964
222082
|
if (hasApprovalInPayload2) {
|
|
220965
222083
|
if (isInvalidToolCallIdsError(errorDetail)) {
|
|
220966
222084
|
try {
|
|
220967
|
-
const
|
|
220968
|
-
const
|
|
220969
|
-
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);
|
|
220970
222087
|
if (serverApprovals && serverApprovals.length > 0) {
|
|
220971
222088
|
const userMessage = currentInput.find((item) => item?.type === "message");
|
|
220972
222089
|
if (userMessage && "content" in userMessage) {
|
|
@@ -221013,7 +222130,7 @@ ${newState.originalPrompt}`,
|
|
|
221013
222130
|
}
|
|
221014
222131
|
const syncAgentState = async () => {
|
|
221015
222132
|
try {
|
|
221016
|
-
const agent = prefetchedAgent ?? await (
|
|
222133
|
+
const agent = prefetchedAgent ?? await getBackend().retrieveAgent(agentIdRef.current);
|
|
221017
222134
|
const currentModel = llmConfigRef.current?.model;
|
|
221018
222135
|
const currentEndpoint = llmConfigRef.current?.model_endpoint_type;
|
|
221019
222136
|
const currentEffort = llmConfigRef.current?.reasoning_effort;
|
|
@@ -221174,8 +222291,7 @@ ${feedback}
|
|
|
221174
222291
|
if (!conversationTitle) {
|
|
221175
222292
|
isAutoConversationTitleInFlightRef.current = false;
|
|
221176
222293
|
} else {
|
|
221177
|
-
|
|
221178
|
-
client.conversations.update(conversationIdRef.current, {
|
|
222294
|
+
getBackend().updateConversation(conversationIdRef.current, {
|
|
221179
222295
|
summary: conversationTitle
|
|
221180
222296
|
}).then(() => {
|
|
221181
222297
|
shouldAutoGenerateConversationTitleRef.current = false;
|
|
@@ -221593,9 +222709,8 @@ ${feedback}
|
|
|
221593
222709
|
const invalidIdsDetected = isInvalidToolCallIdsError(detailFromRun) || isInvalidToolCallIdsError(latestErrorText);
|
|
221594
222710
|
if (hasApprovalInPayload && invalidIdsDetected) {
|
|
221595
222711
|
try {
|
|
221596
|
-
const
|
|
221597
|
-
const
|
|
221598
|
-
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);
|
|
221599
222714
|
if (serverApprovals && serverApprovals.length > 0) {
|
|
221600
222715
|
const userMessage = currentInput.find((item) => item?.type === "message");
|
|
221601
222716
|
if (userMessage && "content" in userMessage) {
|
|
@@ -221638,9 +222753,8 @@ ${feedback}
|
|
|
221638
222753
|
})) {
|
|
221639
222754
|
llmApiErrorRetriesRef.current += 1;
|
|
221640
222755
|
try {
|
|
221641
|
-
const
|
|
221642
|
-
const
|
|
221643
|
-
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);
|
|
221644
222758
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
|
|
221645
222759
|
} catch {
|
|
221646
222760
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -222273,7 +223387,7 @@ ${feedback}
|
|
|
222273
223387
|
setBtwState({ status: "forking", question });
|
|
222274
223388
|
try {
|
|
222275
223389
|
const isDefault = conversationIdRef.current === "default";
|
|
222276
|
-
const forked = await forkConversation(conversationIdRef.current, {
|
|
223390
|
+
const forked = await getBackend().forkConversation(conversationIdRef.current, {
|
|
222277
223391
|
...isDefault ? { agentId } : {}
|
|
222278
223392
|
});
|
|
222279
223393
|
debugLog("btw", "forked conversationId=%s", forked.id);
|
|
@@ -222314,14 +223428,13 @@ ${feedback}
|
|
|
222314
223428
|
})) {
|
|
222315
223429
|
approvalRecoveryRetries += 1;
|
|
222316
223430
|
try {
|
|
222317
|
-
const client = await getClient();
|
|
222318
223431
|
const currentAgentId = agentIdRef.current ?? agentId;
|
|
222319
223432
|
if (!currentAgentId) {
|
|
222320
223433
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
222321
223434
|
continue;
|
|
222322
223435
|
}
|
|
222323
|
-
const agent = await
|
|
222324
|
-
const { pendingApprovals: existingApprovals } = await
|
|
223436
|
+
const agent = await getBackend().retrieveAgent(currentAgentId);
|
|
223437
|
+
const { pendingApprovals: existingApprovals } = await getResumeDataFromBackend2(agent, forked.id);
|
|
222325
223438
|
currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], STALE_APPROVAL_RECOVERY_DENIAL_REASON);
|
|
222326
223439
|
} catch {
|
|
222327
223440
|
currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
|
|
@@ -222378,8 +223491,7 @@ ${feedback}
|
|
|
222378
223491
|
if (!agentState) {
|
|
222379
223492
|
throw new Error("Agent state not available");
|
|
222380
223493
|
}
|
|
222381
|
-
const
|
|
222382
|
-
const resumeData = await getResumeData(client, agentState, conversationId2);
|
|
223494
|
+
const resumeData = await getResumeDataFromBackend2(agentState, conversationId2);
|
|
222383
223495
|
await maybeCarryOverActiveConversationModel(conversationId2);
|
|
222384
223496
|
setConversationIdAndRef(conversationId2);
|
|
222385
223497
|
setConversationAutoTitleEligibility(false);
|
|
@@ -222482,8 +223594,7 @@ ${feedback}
|
|
|
222482
223594
|
const cmd = overlayCommand ?? commandRunner.start("/agents", "Switching agent...");
|
|
222483
223595
|
cmd.update({ output: "Switching agent...", phase: "running" });
|
|
222484
223596
|
try {
|
|
222485
|
-
const
|
|
222486
|
-
const agent = await client.agents.retrieve(targetAgentId);
|
|
223597
|
+
const agent = await getBackend().retrieveAgent(targetAgentId);
|
|
222487
223598
|
const targetConversationId = opts?.conversationId ?? "default";
|
|
222488
223599
|
await updateProjectSettings({ lastAgent: targetAgentId });
|
|
222489
223600
|
settingsManager.persistSession(targetAgentId, targetConversationId);
|
|
@@ -222572,8 +223683,7 @@ ${feedback}
|
|
|
222572
223683
|
const isSelfHosted = !getServerUrl().includes("api.letta.com");
|
|
222573
223684
|
if (isSelfHosted) {
|
|
222574
223685
|
try {
|
|
222575
|
-
const
|
|
222576
|
-
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");
|
|
222577
223687
|
effectiveModel = selectDefaultAgentModel({
|
|
222578
223688
|
preferredModel: effectiveModel,
|
|
222579
223689
|
isSelfHosted: true,
|
|
@@ -222769,9 +223879,8 @@ ${expanded.command}` : expanded.command;
|
|
|
222769
223879
|
return { blocked: false };
|
|
222770
223880
|
}
|
|
222771
223881
|
try {
|
|
222772
|
-
const
|
|
222773
|
-
const
|
|
222774
|
-
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);
|
|
222775
223884
|
if (!existingApprovals || existingApprovals.length === 0) {
|
|
222776
223885
|
setNeedsEagerApprovalCheck(false);
|
|
222777
223886
|
return { blocked: false };
|
|
@@ -222935,6 +224044,11 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
222935
224044
|
return { submitted: true };
|
|
222936
224045
|
}
|
|
222937
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
|
+
}
|
|
222938
224052
|
startOverlayCommand("install-github-app", "/install-github-app", "Opening GitHub App installer...", "GitHub App installer dismissed");
|
|
222939
224053
|
setActiveOverlay("install-github-app");
|
|
222940
224054
|
return { submitted: true };
|
|
@@ -223038,6 +224152,11 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
223038
224152
|
};
|
|
223039
224153
|
const afterMcp = msg.trim().slice(4).trim();
|
|
223040
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
|
+
}
|
|
223041
224160
|
if (!firstWord) {
|
|
223042
224161
|
startOverlayCommand("mcp", "/mcp", "Opening MCP server manager...", "MCP dialog dismissed");
|
|
223043
224162
|
setActiveOverlay("mcp");
|
|
@@ -223552,8 +224671,8 @@ Type your task to begin the loop.`, true);
|
|
|
223552
224671
|
setCommandRunning(true);
|
|
223553
224672
|
await runEndHooks();
|
|
223554
224673
|
try {
|
|
223555
|
-
const
|
|
223556
|
-
const conversation = await
|
|
224674
|
+
const backend4 = getBackend();
|
|
224675
|
+
const conversation = await backend4.createConversation({
|
|
223557
224676
|
agent_id: agentId,
|
|
223558
224677
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS],
|
|
223559
224678
|
...conversationName && { summary: conversationName }
|
|
@@ -223593,13 +224712,13 @@ Type your task to begin the loop.`, true);
|
|
|
223593
224712
|
setCommandRunning(true);
|
|
223594
224713
|
await runEndHooks();
|
|
223595
224714
|
try {
|
|
223596
|
-
const client = await getClient();
|
|
223597
224715
|
const isDefault = conversationIdRef.current === "default";
|
|
223598
|
-
const
|
|
224716
|
+
const backend4 = getBackend();
|
|
224717
|
+
const forked = await backend4.forkConversation(conversationIdRef.current, {
|
|
223599
224718
|
...isDefault ? { agentId } : {}
|
|
223600
224719
|
});
|
|
223601
224720
|
if (conversationSummary) {
|
|
223602
|
-
await
|
|
224721
|
+
await backend4.updateConversation(forked.id, {
|
|
223603
224722
|
summary: conversationSummary
|
|
223604
224723
|
});
|
|
223605
224724
|
}
|
|
@@ -223648,13 +224767,14 @@ Type your task to begin the loop.`, true);
|
|
|
223648
224767
|
setCommandRunning(true);
|
|
223649
224768
|
await runEndHooks();
|
|
223650
224769
|
try {
|
|
223651
|
-
const
|
|
223652
|
-
if (conversationIdRef.current === "default") {
|
|
224770
|
+
const backend4 = getBackend();
|
|
224771
|
+
if (conversationIdRef.current === "default" && !backend4.capabilities.localModelCatalog) {
|
|
224772
|
+
const client = await getClient();
|
|
223653
224773
|
await client.agents.messages.reset(agentId, {
|
|
223654
224774
|
add_default_initial_messages: false
|
|
223655
224775
|
});
|
|
223656
224776
|
}
|
|
223657
|
-
const conversation = await
|
|
224777
|
+
const conversation = await backend4.createConversation({
|
|
223658
224778
|
agent_id: agentId,
|
|
223659
224779
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
223660
224780
|
});
|
|
@@ -223801,20 +224921,20 @@ Type your task to begin the loop.`, true);
|
|
|
223801
224921
|
});
|
|
223802
224922
|
setCommandRunning(true);
|
|
223803
224923
|
try {
|
|
223804
|
-
const
|
|
224924
|
+
const backend4 = getBackend();
|
|
223805
224925
|
if (shouldAutoGenerate) {
|
|
223806
224926
|
const conversationTitle = await generateConversationTitle();
|
|
223807
224927
|
if (!conversationTitle) {
|
|
223808
224928
|
cmd.fail("No conversation content available to generate a title");
|
|
223809
224929
|
return { submitted: true };
|
|
223810
224930
|
}
|
|
223811
|
-
await
|
|
224931
|
+
await backend4.updateConversation(conversationId, {
|
|
223812
224932
|
summary: conversationTitle
|
|
223813
224933
|
});
|
|
223814
224934
|
setConversationAutoTitleEligibility(false);
|
|
223815
224935
|
cmd.finish(`Conversation title set to "${conversationTitle}"`, true);
|
|
223816
224936
|
} else {
|
|
223817
|
-
await
|
|
224937
|
+
await backend4.updateConversation(conversationId, {
|
|
223818
224938
|
summary: newValue
|
|
223819
224939
|
});
|
|
223820
224940
|
setConversationAutoTitleEligibility(false);
|
|
@@ -223839,8 +224959,9 @@ Type your task to begin the loop.`, true);
|
|
|
223839
224959
|
});
|
|
223840
224960
|
setCommandRunning(true);
|
|
223841
224961
|
try {
|
|
223842
|
-
|
|
223843
|
-
|
|
224962
|
+
await getBackend().updateAgent(agentId, {
|
|
224963
|
+
name: newValue
|
|
224964
|
+
});
|
|
223844
224965
|
updateAgentName(newValue);
|
|
223845
224966
|
cmd.agentHint = `Your name is now "${newValue}" — acknowledge this and save your new name to memory.`;
|
|
223846
224967
|
cmd.finish(`Agent renamed to "${newValue}"`, true);
|
|
@@ -223877,10 +224998,11 @@ Type your task to begin the loop.`, true);
|
|
|
223877
224998
|
cmd.update({ output: "Updating description...", phase: "running" });
|
|
223878
224999
|
setCommandRunning(true);
|
|
223879
225000
|
try {
|
|
223880
|
-
|
|
223881
|
-
await client.agents.update(agentId, {
|
|
225001
|
+
await getBackend().updateAgent(agentId, {
|
|
223882
225002
|
description: newDescription
|
|
223883
225003
|
});
|
|
225004
|
+
setAgentState((prev) => prev ? { ...prev, description: newDescription } : prev);
|
|
225005
|
+
setAgentDescription(newDescription);
|
|
223884
225006
|
cmd.finish(`Description updated to "${newDescription}"`, true);
|
|
223885
225007
|
} catch (error51) {
|
|
223886
225008
|
const errorDetails = formatErrorDetails2(error51, agentId);
|
|
@@ -223923,8 +225045,7 @@ Type your task to begin the loop.`, true);
|
|
|
223923
225045
|
setCommandRunning(true);
|
|
223924
225046
|
try {
|
|
223925
225047
|
if (agentState) {
|
|
223926
|
-
const
|
|
223927
|
-
const resumeData = await getResumeData(client, agentState, targetConvId);
|
|
225048
|
+
const resumeData = await getResumeDataFromBackend2(agentState, targetConvId);
|
|
223928
225049
|
setConversationIdAndRef(targetConvId);
|
|
223929
225050
|
setConversationAutoTitleEligibility(false);
|
|
223930
225051
|
pendingConversationSwitchRef.current = {
|
|
@@ -224198,6 +225319,10 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
|
|
|
224198
225319
|
}
|
|
224199
225320
|
if (msg.trim() === "/export" || msg.trim() === "/download") {
|
|
224200
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
|
+
}
|
|
224201
225326
|
setCommandRunning(true);
|
|
224202
225327
|
try {
|
|
224203
225328
|
const client = await getClient();
|
|
@@ -224484,8 +225609,7 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
224484
225609
|
const reflectionConversationId = conversationIdRef.current;
|
|
224485
225610
|
let systemPrompt;
|
|
224486
225611
|
try {
|
|
224487
|
-
const
|
|
224488
|
-
const agent = await client.agents.retrieve(agentId);
|
|
225612
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
224489
225613
|
systemPrompt = agent.system ?? undefined;
|
|
224490
225614
|
} catch {}
|
|
224491
225615
|
const autoPayload = await buildAutoReflectionPayload(agentId, reflectionConversationId, systemPrompt);
|
|
@@ -224752,6 +225876,48 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
224752
225876
|
if (registryCmd) {
|
|
224753
225877
|
registryCmd.fail(`Unknown command: ${registryCommandName}`);
|
|
224754
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
|
+
}
|
|
224755
225921
|
} else {
|
|
224756
225922
|
if (registryCmd) {
|
|
224757
225923
|
registryCmd.finish(result.output, result.success);
|
|
@@ -224842,8 +226008,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
224842
226008
|
const reflectionConversationId = conversationIdRef.current;
|
|
224843
226009
|
let systemPrompt;
|
|
224844
226010
|
try {
|
|
224845
|
-
const
|
|
224846
|
-
const agent = await client.agents.retrieve(agentId);
|
|
226011
|
+
const agent = await getBackend().retrieveAgent(agentId);
|
|
224847
226012
|
systemPrompt = agent.system ?? undefined;
|
|
224848
226013
|
} catch {}
|
|
224849
226014
|
const autoPayload = await buildAutoReflectionPayload(agentId, reflectionConversationId, systemPrompt);
|
|
@@ -224972,9 +226137,8 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
224972
226137
|
buffersRef.current.order.push(eagerStatusId);
|
|
224973
226138
|
refreshDerived();
|
|
224974
226139
|
try {
|
|
224975
|
-
const
|
|
224976
|
-
const
|
|
224977
|
-
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);
|
|
224978
226142
|
buffersRef.current.byId.delete(eagerStatusId);
|
|
224979
226143
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== eagerStatusId);
|
|
224980
226144
|
if (userCancelledRef.current || abortControllerRef.current?.signal.aborted) {
|
|
@@ -225933,16 +227097,17 @@ ${guidance}`);
|
|
|
225933
227097
|
phase: "running"
|
|
225934
227098
|
});
|
|
225935
227099
|
try {
|
|
225936
|
-
const client = await getClient();
|
|
225937
227100
|
const existing = agentState?.compaction_settings;
|
|
225938
227101
|
const existingModel = existing?.model?.trim();
|
|
225939
|
-
|
|
225940
|
-
|
|
225941
|
-
|
|
225942
|
-
|
|
225943
|
-
|
|
225944
|
-
|
|
227102
|
+
const nextCompactionSettings = {
|
|
227103
|
+
...existing,
|
|
227104
|
+
model: existingModel || DEFAULT_SUMMARIZATION_MODEL,
|
|
227105
|
+
mode
|
|
227106
|
+
};
|
|
227107
|
+
await getBackend().updateAgent(agentId, {
|
|
227108
|
+
compaction_settings: nextCompactionSettings
|
|
225945
227109
|
});
|
|
227110
|
+
setAgentState((prev) => prev ? { ...prev, compaction_settings: nextCompactionSettings } : prev);
|
|
225946
227111
|
cmd.finish(`Updated compaction mode to: ${mode}`, true);
|
|
225947
227112
|
} catch (error51) {
|
|
225948
227113
|
const errorDetails = formatErrorDetails2(error51, agentId);
|
|
@@ -226094,9 +227259,8 @@ ${guidance}`);
|
|
|
226094
227259
|
if (action.conversationId === conversationId) {
|
|
226095
227260
|
cmd.finish("Already on this conversation", true);
|
|
226096
227261
|
} else {
|
|
226097
|
-
const client = await getClient();
|
|
226098
227262
|
if (agentState) {
|
|
226099
|
-
const resumeData = await
|
|
227263
|
+
const resumeData = await getResumeDataFromBackend2(agentState, action.conversationId);
|
|
226100
227264
|
setConversationIdAndRef(action.conversationId);
|
|
226101
227265
|
setConversationAutoTitleEligibility(false);
|
|
226102
227266
|
pendingConversationSwitchRef.current = {
|
|
@@ -227407,8 +228571,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
227407
228571
|
});
|
|
227408
228572
|
try {
|
|
227409
228573
|
if (agentState) {
|
|
227410
|
-
const
|
|
227411
|
-
const resumeData = await getResumeData(client, agentState, convId);
|
|
228574
|
+
const resumeData = await getResumeDataFromBackend2(agentState, convId);
|
|
227412
228575
|
setConversationIdAndRef(convId);
|
|
227413
228576
|
setConversationAutoTitleEligibility(false);
|
|
227414
228577
|
pendingConversationSwitchRef.current = {
|
|
@@ -227513,8 +228676,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
227513
228676
|
phase: "running"
|
|
227514
228677
|
});
|
|
227515
228678
|
try {
|
|
227516
|
-
const
|
|
227517
|
-
const conversation = await client.conversations.create({
|
|
228679
|
+
const conversation = await getBackend().createConversation({
|
|
227518
228680
|
agent_id: agentId,
|
|
227519
228681
|
isolated_block_labels: [...ISOLATED_BLOCK_LABELS]
|
|
227520
228682
|
});
|
|
@@ -227602,8 +228764,7 @@ If using apply_patch, use this exact relative patch path: ${applyPatchRelativePa
|
|
|
227602
228764
|
});
|
|
227603
228765
|
try {
|
|
227604
228766
|
if (agentState) {
|
|
227605
|
-
const
|
|
227606
|
-
const resumeData = await getResumeData(client, agentState, actualTargetConv);
|
|
228767
|
+
const resumeData = await getResumeDataFromBackend2(agentState, actualTargetConv);
|
|
227607
228768
|
setConversationIdAndRef(actualTargetConv);
|
|
227608
228769
|
setConversationAutoTitleEligibility(false);
|
|
227609
228770
|
pendingConversationSwitchRef.current = {
|
|
@@ -227759,9 +228920,10 @@ Open /mcp to attach or detach tools for this server.`, true);
|
|
|
227759
228920
|
phase: "running"
|
|
227760
228921
|
});
|
|
227761
228922
|
try {
|
|
227762
|
-
const client = await getClient();
|
|
227763
228923
|
if (newName && newName !== agentName) {
|
|
227764
|
-
await
|
|
228924
|
+
await getBackend().updateAgent(agentId, {
|
|
228925
|
+
name: newName
|
|
228926
|
+
});
|
|
227765
228927
|
updateAgentName(newName);
|
|
227766
228928
|
}
|
|
227767
228929
|
if (pinDialogLocal) {
|
|
@@ -227809,7 +228971,6 @@ var init_App2 = __esm(async () => {
|
|
|
227809
228971
|
init_backend2();
|
|
227810
228972
|
init_agents5();
|
|
227811
228973
|
init_client2();
|
|
227812
|
-
init_conversations2();
|
|
227813
228974
|
init_metadata();
|
|
227814
228975
|
init_constants();
|
|
227815
228976
|
init_manager();
|
|
@@ -229146,9 +230307,8 @@ async function hydrateMemfsSettingFromAgent2(agent) {
|
|
|
229146
230307
|
return enabled;
|
|
229147
230308
|
}
|
|
229148
230309
|
async function isMemfsEnabledOnServer2(agentId) {
|
|
229149
|
-
const {
|
|
229150
|
-
const
|
|
229151
|
-
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, {
|
|
229152
230312
|
include: ["agent.tags"]
|
|
229153
230313
|
});
|
|
229154
230314
|
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -229281,7 +230441,8 @@ async function applyMemfsFlags2(agentId, memfsFlag, noMemfsFlag, options) {
|
|
|
229281
230441
|
const backend4 = getBackend2();
|
|
229282
230442
|
if (backend4.capabilities.localMemfs) {
|
|
229283
230443
|
if (noMemfsFlag) {
|
|
229284
|
-
|
|
230444
|
+
settingsManager3.setMemfsEnabled(agentId, false);
|
|
230445
|
+
return { action: "disabled" };
|
|
229285
230446
|
}
|
|
229286
230447
|
const memoryDir = getScopedMemoryFilesystemRoot2(agentId);
|
|
229287
230448
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memoryGit(), exports_memoryGit));
|
|
@@ -229458,7 +230619,7 @@ async function initSecretsFromServer2(agentId, cachedAgent) {
|
|
|
229458
230619
|
setCache2(agentId, {});
|
|
229459
230620
|
return;
|
|
229460
230621
|
}
|
|
229461
|
-
const agent = cachedAgent ?? await (
|
|
230622
|
+
const agent = cachedAgent ?? await getBackend().retrieveAgent(agentId, {
|
|
229462
230623
|
include: ["agent.secrets"]
|
|
229463
230624
|
});
|
|
229464
230625
|
const secrets2 = {};
|
|
@@ -229491,6 +230652,9 @@ async function refreshAndListSecrets2(agentIdArg) {
|
|
|
229491
230652
|
return Object.keys(cache5).sort().map((key) => ({ key, value: cache5[key] ?? "" }));
|
|
229492
230653
|
}
|
|
229493
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
|
+
}
|
|
229494
230658
|
const agentId = resolveSecretsAgentId2(agentIdArg);
|
|
229495
230659
|
if (!agentId) {
|
|
229496
230660
|
throw new Error("No agent context set. Agent ID is required.");
|
|
@@ -229502,8 +230666,7 @@ async function applySecretBatch2(options, agentIdArg) {
|
|
|
229502
230666
|
for (const rawKey of options.unset ?? []) {
|
|
229503
230667
|
delete next[rawKey.toUpperCase()];
|
|
229504
230668
|
}
|
|
229505
|
-
|
|
229506
|
-
await client.agents.update(agentId, { secrets: next });
|
|
230669
|
+
await getBackend().updateAgent(agentId, { secrets: next });
|
|
229507
230670
|
setCache2(agentId, next);
|
|
229508
230671
|
return Object.keys(next).sort();
|
|
229509
230672
|
}
|
|
@@ -229511,14 +230674,13 @@ async function setSecretOnServer2(key, value, agentIdArg) {
|
|
|
229511
230674
|
if (!getBackend().capabilities.serverSecrets) {
|
|
229512
230675
|
throw new Error("Agent secrets are not supported by this backend yet");
|
|
229513
230676
|
}
|
|
229514
|
-
const client = await getClient();
|
|
229515
230677
|
const agentId = resolveSecretsAgentId2(agentIdArg);
|
|
229516
230678
|
if (!agentId) {
|
|
229517
230679
|
throw new Error("No agent context set. Agent ID is required.");
|
|
229518
230680
|
}
|
|
229519
230681
|
const secrets2 = { ...loadSecrets2(agentId) };
|
|
229520
230682
|
secrets2[key] = value;
|
|
229521
|
-
await
|
|
230683
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
229522
230684
|
setCache2(agentId, secrets2);
|
|
229523
230685
|
}
|
|
229524
230686
|
async function deleteSecretOnServer2(key, agentIdArg) {
|
|
@@ -229534,8 +230696,7 @@ async function deleteSecretOnServer2(key, agentIdArg) {
|
|
|
229534
230696
|
return false;
|
|
229535
230697
|
}
|
|
229536
230698
|
delete secrets2[key];
|
|
229537
|
-
|
|
229538
|
-
await client.agents.update(agentId, { secrets: secrets2 });
|
|
230699
|
+
await getBackend().updateAgent(agentId, { secrets: secrets2 });
|
|
229539
230700
|
setCache2(agentId, secrets2);
|
|
229540
230701
|
return true;
|
|
229541
230702
|
}
|
|
@@ -229551,7 +230712,6 @@ var SECRETS_CACHE_KEY2;
|
|
|
229551
230712
|
var init_secretsStore2 = __esm(() => {
|
|
229552
230713
|
init_context();
|
|
229553
230714
|
init_backend2();
|
|
229554
|
-
init_client2();
|
|
229555
230715
|
SECRETS_CACHE_KEY2 = Symbol.for("@letta/secretsCache");
|
|
229556
230716
|
});
|
|
229557
230717
|
|
|
@@ -230084,6 +231244,9 @@ init_available_models();
|
|
|
230084
231244
|
function supportsDistinctAnthropicXHighEffort2(modelHandle) {
|
|
230085
231245
|
return modelHandle.includes("claude-opus-4-7");
|
|
230086
231246
|
}
|
|
231247
|
+
function isRecord10(value) {
|
|
231248
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
231249
|
+
}
|
|
230087
231250
|
function buildModelSettings2(modelHandle, updateArgs) {
|
|
230088
231251
|
const isOpenAI = modelHandle.startsWith("openai/") || modelHandle.startsWith(`${OPENAI_CODEX_PROVIDER_NAME}/`);
|
|
230089
231252
|
const isAnthropic = modelHandle.startsWith("anthropic/") || modelHandle.startsWith("claude-pro-max/") || modelHandle.startsWith("minimax/");
|
|
@@ -230206,6 +231369,12 @@ function buildModelSettings2(modelHandle, updateArgs) {
|
|
|
230206
231369
|
if (typeof updateArgs?.max_output_tokens === "number" && "provider_type" in settings) {
|
|
230207
231370
|
settings.max_output_tokens = updateArgs.max_output_tokens;
|
|
230208
231371
|
}
|
|
231372
|
+
if (isRecord10(updateArgs?.modalities)) {
|
|
231373
|
+
settings.modalities = updateArgs.modalities;
|
|
231374
|
+
}
|
|
231375
|
+
if (isRecord10(updateArgs?.capabilities)) {
|
|
231376
|
+
settings.capabilities = updateArgs.capabilities;
|
|
231377
|
+
}
|
|
230209
231378
|
return settings;
|
|
230210
231379
|
}
|
|
230211
231380
|
async function updateAgentLLMConfig2(agentId, modelHandle, updateArgs, options) {
|
|
@@ -230529,6 +231698,15 @@ async function getBillingTier2() {
|
|
|
230529
231698
|
}
|
|
230530
231699
|
}
|
|
230531
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
|
+
|
|
230532
231710
|
// src/cli/args.ts
|
|
230533
231711
|
import { parseArgs } from "node:util";
|
|
230534
231712
|
var CLI_FLAG_CATALOG = {
|
|
@@ -232866,7 +234044,7 @@ function validateRegistryHandleOrThrow(handle) {
|
|
|
232866
234044
|
// src/cli/subcommands/agents.ts
|
|
232867
234045
|
init_create();
|
|
232868
234046
|
init_personality();
|
|
232869
|
-
|
|
234047
|
+
init_backend2();
|
|
232870
234048
|
init_settings_manager();
|
|
232871
234049
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
232872
234050
|
function printUsage() {
|
|
@@ -233000,8 +234178,7 @@ async function runCreateAction(values) {
|
|
|
233000
234178
|
if (values.pinned) {
|
|
233001
234179
|
settingsManager.pinGlobal(agentId);
|
|
233002
234180
|
}
|
|
233003
|
-
const
|
|
233004
|
-
const updatedAgent = await client.agents.retrieve(agentId);
|
|
234181
|
+
const updatedAgent = await getBackend().retrieveAgent(agentId);
|
|
233005
234182
|
console.log(JSON.stringify(updatedAgent, null, 2));
|
|
233006
234183
|
return 0;
|
|
233007
234184
|
} catch (error51) {
|
|
@@ -233031,8 +234208,7 @@ async function runListAction(values) {
|
|
|
233031
234208
|
params.include = ["agent.blocks"];
|
|
233032
234209
|
}
|
|
233033
234210
|
try {
|
|
233034
|
-
const
|
|
233035
|
-
const result = await client.agents.list(params);
|
|
234211
|
+
const result = await getBackend().listAgents(params);
|
|
233036
234212
|
console.log(JSON.stringify(result, null, 2));
|
|
233037
234213
|
return 0;
|
|
233038
234214
|
} catch (error51) {
|
|
@@ -233041,234 +234217,6 @@ async function runListAction(values) {
|
|
|
233041
234217
|
}
|
|
233042
234218
|
}
|
|
233043
234219
|
|
|
233044
|
-
// src/cli/subcommands/blocks.ts
|
|
233045
|
-
init_client2();
|
|
233046
|
-
init_settings_manager();
|
|
233047
|
-
import { parseArgs as parseArgs3 } from "node:util";
|
|
233048
|
-
function printUsage2() {
|
|
233049
|
-
console.log(`
|
|
233050
|
-
Usage:
|
|
233051
|
-
letta blocks list --agent <id> [--limit <n>]
|
|
233052
|
-
letta blocks copy --block-id <id> [--label <new-label>] [--agent <id>] [--override]
|
|
233053
|
-
letta blocks attach --block-id <id> [--agent <id>] [--read-only] [--override]
|
|
233054
|
-
|
|
233055
|
-
Notes:
|
|
233056
|
-
- Output is JSON only.
|
|
233057
|
-
- Uses CLI auth; override with LETTA_API_KEY/LETTA_BASE_URL if needed.
|
|
233058
|
-
- Default target agent for copy/attach is LETTA_AGENT_ID.
|
|
233059
|
-
`.trim());
|
|
233060
|
-
}
|
|
233061
|
-
function parseLimit2(value, fallback) {
|
|
233062
|
-
if (typeof value !== "string" || value.length === 0)
|
|
233063
|
-
return fallback;
|
|
233064
|
-
const parsed = Number.parseInt(value, 10);
|
|
233065
|
-
return Number.isNaN(parsed) ? fallback : parsed;
|
|
233066
|
-
}
|
|
233067
|
-
function getAgentId2(agentFromArgs, agentIdFromArgs) {
|
|
233068
|
-
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
233069
|
-
}
|
|
233070
|
-
var BLOCKS_OPTIONS = {
|
|
233071
|
-
help: { type: "boolean", short: "h" },
|
|
233072
|
-
agent: { type: "string" },
|
|
233073
|
-
"agent-id": { type: "string" },
|
|
233074
|
-
limit: { type: "string" },
|
|
233075
|
-
"block-id": { type: "string" },
|
|
233076
|
-
label: { type: "string" },
|
|
233077
|
-
override: { type: "boolean" },
|
|
233078
|
-
"read-only": { type: "boolean" }
|
|
233079
|
-
};
|
|
233080
|
-
function parseBlocksArgs(argv) {
|
|
233081
|
-
return parseArgs3({
|
|
233082
|
-
args: argv,
|
|
233083
|
-
options: BLOCKS_OPTIONS,
|
|
233084
|
-
strict: true,
|
|
233085
|
-
allowPositionals: true
|
|
233086
|
-
});
|
|
233087
|
-
}
|
|
233088
|
-
async function copyBlock(client, blockId, options) {
|
|
233089
|
-
const currentAgentId = getAgentId2(options?.targetAgentId);
|
|
233090
|
-
if (!currentAgentId) {
|
|
233091
|
-
throw new Error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
233092
|
-
}
|
|
233093
|
-
let detachedBlock;
|
|
233094
|
-
const sourceBlock = await client.blocks.retrieve(blockId);
|
|
233095
|
-
const targetLabel = options?.labelOverride || sourceBlock.label || "migrated-block";
|
|
233096
|
-
if (options?.override) {
|
|
233097
|
-
const currentBlocksResponse = await client.agents.blocks.list(currentAgentId);
|
|
233098
|
-
const currentBlocks = Array.isArray(currentBlocksResponse) ? currentBlocksResponse : currentBlocksResponse.items || [];
|
|
233099
|
-
const conflictingBlock = currentBlocks.find((b) => b.label === targetLabel);
|
|
233100
|
-
if (conflictingBlock) {
|
|
233101
|
-
console.error(`Detaching existing block with label "${targetLabel}" (${conflictingBlock.id})...`);
|
|
233102
|
-
detachedBlock = conflictingBlock;
|
|
233103
|
-
try {
|
|
233104
|
-
await client.agents.blocks.detach(conflictingBlock.id, {
|
|
233105
|
-
agent_id: currentAgentId
|
|
233106
|
-
});
|
|
233107
|
-
} catch (detachError) {
|
|
233108
|
-
throw new Error(`Failed to detach existing block "${targetLabel}": ${detachError instanceof Error ? detachError.message : String(detachError)}`);
|
|
233109
|
-
}
|
|
233110
|
-
}
|
|
233111
|
-
}
|
|
233112
|
-
let newBlock;
|
|
233113
|
-
try {
|
|
233114
|
-
newBlock = await client.blocks.create({
|
|
233115
|
-
label: targetLabel,
|
|
233116
|
-
value: sourceBlock.value,
|
|
233117
|
-
description: sourceBlock.description || undefined,
|
|
233118
|
-
limit: sourceBlock.limit
|
|
233119
|
-
});
|
|
233120
|
-
} catch (createError) {
|
|
233121
|
-
if (detachedBlock) {
|
|
233122
|
-
console.error(`Create failed, reattaching original block "${detachedBlock.label}"...`);
|
|
233123
|
-
try {
|
|
233124
|
-
await client.agents.blocks.attach(detachedBlock.id, {
|
|
233125
|
-
agent_id: currentAgentId
|
|
233126
|
-
});
|
|
233127
|
-
console.error("Original block reattached successfully.");
|
|
233128
|
-
} catch {
|
|
233129
|
-
console.error(`WARNING: Failed to reattach original block! Block ID: ${detachedBlock.id}`);
|
|
233130
|
-
}
|
|
233131
|
-
}
|
|
233132
|
-
throw createError;
|
|
233133
|
-
}
|
|
233134
|
-
let attachResult;
|
|
233135
|
-
try {
|
|
233136
|
-
attachResult = await client.agents.blocks.attach(newBlock.id, {
|
|
233137
|
-
agent_id: currentAgentId
|
|
233138
|
-
});
|
|
233139
|
-
} catch (attachError) {
|
|
233140
|
-
if (detachedBlock) {
|
|
233141
|
-
console.error(`Attach failed, reattaching original block "${detachedBlock.label}"...`);
|
|
233142
|
-
try {
|
|
233143
|
-
await client.agents.blocks.attach(detachedBlock.id, {
|
|
233144
|
-
agent_id: currentAgentId
|
|
233145
|
-
});
|
|
233146
|
-
console.error("Original block reattached successfully.");
|
|
233147
|
-
} catch {
|
|
233148
|
-
console.error(`WARNING: Failed to reattach original block! Block ID: ${detachedBlock.id}`);
|
|
233149
|
-
}
|
|
233150
|
-
}
|
|
233151
|
-
throw attachError;
|
|
233152
|
-
}
|
|
233153
|
-
return { sourceBlock, newBlock, attachResult, detachedBlock };
|
|
233154
|
-
}
|
|
233155
|
-
async function attachBlock(client, blockId, options) {
|
|
233156
|
-
const currentAgentId = getAgentId2(options?.targetAgentId);
|
|
233157
|
-
if (!currentAgentId) {
|
|
233158
|
-
throw new Error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
233159
|
-
}
|
|
233160
|
-
let detachedBlock;
|
|
233161
|
-
if (options?.override) {
|
|
233162
|
-
const sourceBlock = await client.blocks.retrieve(blockId);
|
|
233163
|
-
const sourceLabel = sourceBlock.label;
|
|
233164
|
-
const currentBlocksResponse = await client.agents.blocks.list(currentAgentId);
|
|
233165
|
-
const currentBlocks = Array.isArray(currentBlocksResponse) ? currentBlocksResponse : currentBlocksResponse.items || [];
|
|
233166
|
-
const conflictingBlock = currentBlocks.find((b) => b.label === sourceLabel);
|
|
233167
|
-
if (conflictingBlock) {
|
|
233168
|
-
console.error(`Detaching existing block with label "${sourceLabel}" (${conflictingBlock.id})...`);
|
|
233169
|
-
detachedBlock = conflictingBlock;
|
|
233170
|
-
try {
|
|
233171
|
-
await client.agents.blocks.detach(conflictingBlock.id, {
|
|
233172
|
-
agent_id: currentAgentId
|
|
233173
|
-
});
|
|
233174
|
-
} catch (detachError) {
|
|
233175
|
-
throw new Error(`Failed to detach existing block "${sourceLabel}": ${detachError instanceof Error ? detachError.message : String(detachError)}`);
|
|
233176
|
-
}
|
|
233177
|
-
}
|
|
233178
|
-
}
|
|
233179
|
-
let attachResult;
|
|
233180
|
-
try {
|
|
233181
|
-
attachResult = await client.agents.blocks.attach(blockId, {
|
|
233182
|
-
agent_id: currentAgentId
|
|
233183
|
-
});
|
|
233184
|
-
} catch (attachError) {
|
|
233185
|
-
if (detachedBlock) {
|
|
233186
|
-
console.error(`Attach failed, reattaching original block "${detachedBlock.label}"...`);
|
|
233187
|
-
try {
|
|
233188
|
-
await client.agents.blocks.attach(detachedBlock.id, {
|
|
233189
|
-
agent_id: currentAgentId
|
|
233190
|
-
});
|
|
233191
|
-
console.error("Original block reattached successfully.");
|
|
233192
|
-
} catch {
|
|
233193
|
-
console.error(`WARNING: Failed to reattach original block! Block ID: ${detachedBlock.id}`);
|
|
233194
|
-
}
|
|
233195
|
-
}
|
|
233196
|
-
throw attachError;
|
|
233197
|
-
}
|
|
233198
|
-
if (options?.readOnly) {
|
|
233199
|
-
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.");
|
|
233200
|
-
}
|
|
233201
|
-
return { attachResult, detachedBlock };
|
|
233202
|
-
}
|
|
233203
|
-
async function runBlocksSubcommand(argv) {
|
|
233204
|
-
let parsed;
|
|
233205
|
-
try {
|
|
233206
|
-
parsed = parseBlocksArgs(argv);
|
|
233207
|
-
} catch (error51) {
|
|
233208
|
-
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
233209
|
-
console.error(`Error: ${message}`);
|
|
233210
|
-
printUsage2();
|
|
233211
|
-
return 1;
|
|
233212
|
-
}
|
|
233213
|
-
const [action] = parsed.positionals;
|
|
233214
|
-
if (parsed.values.help || !action || action === "help") {
|
|
233215
|
-
printUsage2();
|
|
233216
|
-
return 0;
|
|
233217
|
-
}
|
|
233218
|
-
try {
|
|
233219
|
-
await settingsManager.initialize();
|
|
233220
|
-
const client = await getClient();
|
|
233221
|
-
if (action === "list") {
|
|
233222
|
-
const agentId = parsed.values.agent || parsed.values["agent-id"] || "";
|
|
233223
|
-
if (!agentId || typeof agentId !== "string") {
|
|
233224
|
-
console.error("Missing required --agent <id>.");
|
|
233225
|
-
return 1;
|
|
233226
|
-
}
|
|
233227
|
-
const result = await client.agents.blocks.list(agentId, {
|
|
233228
|
-
limit: parseLimit2(parsed.values.limit, 1000)
|
|
233229
|
-
});
|
|
233230
|
-
console.log(JSON.stringify(result, null, 2));
|
|
233231
|
-
return 0;
|
|
233232
|
-
}
|
|
233233
|
-
if (action === "copy") {
|
|
233234
|
-
const blockId = parsed.values["block-id"];
|
|
233235
|
-
if (!blockId || typeof blockId !== "string") {
|
|
233236
|
-
console.error("Missing required --block-id <id>.");
|
|
233237
|
-
return 1;
|
|
233238
|
-
}
|
|
233239
|
-
const agentId = getAgentId2(parsed.values.agent, parsed.values["agent-id"]);
|
|
233240
|
-
const result = await copyBlock(client, blockId, {
|
|
233241
|
-
labelOverride: typeof parsed.values.label === "string" ? parsed.values.label : undefined,
|
|
233242
|
-
targetAgentId: agentId,
|
|
233243
|
-
override: parsed.values.override === true
|
|
233244
|
-
});
|
|
233245
|
-
console.log(JSON.stringify(result, null, 2));
|
|
233246
|
-
return 0;
|
|
233247
|
-
}
|
|
233248
|
-
if (action === "attach") {
|
|
233249
|
-
const blockId = parsed.values["block-id"];
|
|
233250
|
-
if (!blockId || typeof blockId !== "string") {
|
|
233251
|
-
console.error("Missing required --block-id <id>.");
|
|
233252
|
-
return 1;
|
|
233253
|
-
}
|
|
233254
|
-
const agentId = getAgentId2(parsed.values.agent, parsed.values["agent-id"]);
|
|
233255
|
-
const result = await attachBlock(client, blockId, {
|
|
233256
|
-
readOnly: parsed.values["read-only"] === true,
|
|
233257
|
-
override: parsed.values.override === true,
|
|
233258
|
-
targetAgentId: agentId
|
|
233259
|
-
});
|
|
233260
|
-
console.log(JSON.stringify(result, null, 2));
|
|
233261
|
-
return 0;
|
|
233262
|
-
}
|
|
233263
|
-
} catch (error51) {
|
|
233264
|
-
console.error(error51 instanceof Error ? error51.message : String(error51));
|
|
233265
|
-
return 1;
|
|
233266
|
-
}
|
|
233267
|
-
console.error(`Unknown action: ${action}`);
|
|
233268
|
-
printUsage2();
|
|
233269
|
-
return 1;
|
|
233270
|
-
}
|
|
233271
|
-
|
|
233272
234220
|
// src/cli/subcommands/channels.ts
|
|
233273
234221
|
init_accounts();
|
|
233274
234222
|
init_pairing();
|
|
@@ -233277,8 +234225,8 @@ init_registry();
|
|
|
233277
234225
|
init_routing();
|
|
233278
234226
|
init_runtimeDeps();
|
|
233279
234227
|
await init_service();
|
|
233280
|
-
import { parseArgs as
|
|
233281
|
-
function
|
|
234228
|
+
import { parseArgs as parseArgs3 } from "node:util";
|
|
234229
|
+
function printUsage2() {
|
|
233282
234230
|
console.log(`
|
|
233283
234231
|
Usage:
|
|
233284
234232
|
letta channels install <channel> Install channel runtime dependencies
|
|
@@ -233342,14 +234290,14 @@ var CHANNELS_OPTIONS = {
|
|
|
233342
234290
|
code: { type: "string" }
|
|
233343
234291
|
};
|
|
233344
234292
|
function parseChannelsArgs(argv) {
|
|
233345
|
-
return
|
|
234293
|
+
return parseArgs3({
|
|
233346
234294
|
args: argv,
|
|
233347
234295
|
options: CHANNELS_OPTIONS,
|
|
233348
234296
|
strict: true,
|
|
233349
234297
|
allowPositionals: true
|
|
233350
234298
|
});
|
|
233351
234299
|
}
|
|
233352
|
-
function
|
|
234300
|
+
function getAgentId2(fromArgs) {
|
|
233353
234301
|
return fromArgs || process.env.LETTA_AGENT_ID || "";
|
|
233354
234302
|
}
|
|
233355
234303
|
function getConversationId2(fromArgs) {
|
|
@@ -233486,7 +234434,7 @@ function handleRouteAdd(values) {
|
|
|
233486
234434
|
const channelId = values.channel;
|
|
233487
234435
|
const accountId = values["account-id"];
|
|
233488
234436
|
const chatId = values["chat-id"];
|
|
233489
|
-
const agentId =
|
|
234437
|
+
const agentId = getAgentId2(values.agent);
|
|
233490
234438
|
const conversationId = getConversationId2(values.conversation);
|
|
233491
234439
|
if (!channelId) {
|
|
233492
234440
|
console.error("Error: --channel is required.");
|
|
@@ -233574,7 +234522,7 @@ async function handlePair(values) {
|
|
|
233574
234522
|
const channelId = values.channel;
|
|
233575
234523
|
const accountId = values["account-id"];
|
|
233576
234524
|
const code = values.code;
|
|
233577
|
-
const agentId =
|
|
234525
|
+
const agentId = getAgentId2(values.agent);
|
|
233578
234526
|
const conversationId = getConversationId2(values.conversation);
|
|
233579
234527
|
if (!channelId) {
|
|
233580
234528
|
console.error("Error: --channel is required.");
|
|
@@ -233605,7 +234553,7 @@ async function handlePair(values) {
|
|
|
233605
234553
|
function handleBind(values) {
|
|
233606
234554
|
const channelId = values.channel;
|
|
233607
234555
|
const accountId = values["account-id"];
|
|
233608
|
-
const agentId =
|
|
234556
|
+
const agentId = getAgentId2(values.agent);
|
|
233609
234557
|
if (!channelId) {
|
|
233610
234558
|
console.error("Error: --channel is required.");
|
|
233611
234559
|
return 1;
|
|
@@ -233645,7 +234593,7 @@ function handleBind(values) {
|
|
|
233645
234593
|
async function runChannelsSubcommand(argv) {
|
|
233646
234594
|
const { values, positionals } = parseChannelsArgs(argv);
|
|
233647
234595
|
if (values.help) {
|
|
233648
|
-
|
|
234596
|
+
printUsage2();
|
|
233649
234597
|
return 0;
|
|
233650
234598
|
}
|
|
233651
234599
|
const [action, ...rest] = positionals;
|
|
@@ -233688,7 +234636,7 @@ async function runChannelsSubcommand(argv) {
|
|
|
233688
234636
|
return await handlePair(values);
|
|
233689
234637
|
default:
|
|
233690
234638
|
if (!action) {
|
|
233691
|
-
|
|
234639
|
+
printUsage2();
|
|
233692
234640
|
return 0;
|
|
233693
234641
|
}
|
|
233694
234642
|
console.error(`Unknown channels action: "${action}". Use: install, configure, status, route, bind, pair`);
|
|
@@ -233703,7 +234651,7 @@ init_connect_normalize();
|
|
|
233703
234651
|
init_connect_oauth_core();
|
|
233704
234652
|
import { createInterface as createInterface4 } from "node:readline/promises";
|
|
233705
234653
|
import { Writable } from "node:stream";
|
|
233706
|
-
import { parseArgs as
|
|
234654
|
+
import { parseArgs as parseArgs4 } from "node:util";
|
|
233707
234655
|
var CONNECT_OPTIONS = {
|
|
233708
234656
|
help: { type: "boolean", short: "h" },
|
|
233709
234657
|
"api-key": { type: "string" },
|
|
@@ -233794,7 +234742,7 @@ async function runConnectSubcommand(argv, deps = {}) {
|
|
|
233794
234742
|
const io = { ...DEFAULT_DEPS2, ...deps };
|
|
233795
234743
|
let parsed;
|
|
233796
234744
|
try {
|
|
233797
|
-
parsed =
|
|
234745
|
+
parsed = parseArgs4({
|
|
233798
234746
|
args: argv,
|
|
233799
234747
|
options: CONNECT_OPTIONS,
|
|
233800
234748
|
strict: true,
|
|
@@ -233903,8 +234851,8 @@ async function runConnectSubcommand(argv, deps = {}) {
|
|
|
233903
234851
|
|
|
233904
234852
|
// src/cli/subcommands/cron.ts
|
|
233905
234853
|
init_cron();
|
|
233906
|
-
import { parseArgs as
|
|
233907
|
-
function
|
|
234854
|
+
import { parseArgs as parseArgs5 } from "node:util";
|
|
234855
|
+
function printUsage3() {
|
|
233908
234856
|
console.log(`
|
|
233909
234857
|
Usage:
|
|
233910
234858
|
letta cron add --prompt <text> --every <interval> [options]
|
|
@@ -233948,14 +234896,14 @@ var CRON_OPTIONS = {
|
|
|
233948
234896
|
all: { type: "boolean" }
|
|
233949
234897
|
};
|
|
233950
234898
|
function parseCronArgs(argv) {
|
|
233951
|
-
return
|
|
234899
|
+
return parseArgs5({
|
|
233952
234900
|
args: argv,
|
|
233953
234901
|
options: CRON_OPTIONS,
|
|
233954
234902
|
strict: true,
|
|
233955
234903
|
allowPositionals: true
|
|
233956
234904
|
});
|
|
233957
234905
|
}
|
|
233958
|
-
function
|
|
234906
|
+
function getAgentId3(fromArgs) {
|
|
233959
234907
|
return fromArgs || process.env.LETTA_AGENT_ID || "";
|
|
233960
234908
|
}
|
|
233961
234909
|
function getConversationId3(fromArgs) {
|
|
@@ -233977,7 +234925,7 @@ function handleAdd(values) {
|
|
|
233977
234925
|
console.error("Error: --prompt is required.");
|
|
233978
234926
|
return 1;
|
|
233979
234927
|
}
|
|
233980
|
-
const agentId =
|
|
234928
|
+
const agentId = getAgentId3(values.agent);
|
|
233981
234929
|
if (!agentId) {
|
|
233982
234930
|
console.error("Error: --agent or LETTA_AGENT_ID required.");
|
|
233983
234931
|
return 1;
|
|
@@ -234098,7 +235046,7 @@ function handleGet(positionals) {
|
|
|
234098
235046
|
}
|
|
234099
235047
|
function handleDelete(values, positionals) {
|
|
234100
235048
|
if (values.all) {
|
|
234101
|
-
const agentId =
|
|
235049
|
+
const agentId = getAgentId3(values.agent);
|
|
234102
235050
|
if (!agentId) {
|
|
234103
235051
|
console.error("Error: --agent or LETTA_AGENT_ID required with --all.");
|
|
234104
235052
|
return 1;
|
|
@@ -234126,12 +235074,12 @@ async function runCronSubcommand(argv) {
|
|
|
234126
235074
|
parsed = parseCronArgs(argv);
|
|
234127
235075
|
} catch (err) {
|
|
234128
235076
|
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
234129
|
-
|
|
235077
|
+
printUsage3();
|
|
234130
235078
|
return 1;
|
|
234131
235079
|
}
|
|
234132
235080
|
const [action] = parsed.positionals;
|
|
234133
235081
|
if (parsed.values.help || !action || action === "help") {
|
|
234134
|
-
|
|
235082
|
+
printUsage3();
|
|
234135
235083
|
return 0;
|
|
234136
235084
|
}
|
|
234137
235085
|
switch (action) {
|
|
@@ -234145,7 +235093,7 @@ async function runCronSubcommand(argv) {
|
|
|
234145
235093
|
return handleDelete(parsed.values, parsed.positionals);
|
|
234146
235094
|
default:
|
|
234147
235095
|
console.error(`Unknown action: ${action}`);
|
|
234148
|
-
|
|
235096
|
+
printUsage3();
|
|
234149
235097
|
return 1;
|
|
234150
235098
|
}
|
|
234151
235099
|
}
|
|
@@ -234160,7 +235108,7 @@ await __promiseAll([
|
|
|
234160
235108
|
]);
|
|
234161
235109
|
var import_react30 = __toESM(require_react(), 1);
|
|
234162
235110
|
import { hostname as hostname4 } from "node:os";
|
|
234163
|
-
import { parseArgs as
|
|
235111
|
+
import { parseArgs as parseArgs6 } from "node:util";
|
|
234164
235112
|
|
|
234165
235113
|
// src/websocket/listen-log.ts
|
|
234166
235114
|
import {
|
|
@@ -234479,7 +235427,7 @@ async function resolveListenerRegistrationOptions(deviceId, connectionName) {
|
|
|
234479
235427
|
};
|
|
234480
235428
|
}
|
|
234481
235429
|
async function runListenSubcommand(argv) {
|
|
234482
|
-
const { values } =
|
|
235430
|
+
const { values } = parseArgs6({
|
|
234483
235431
|
args: argv,
|
|
234484
235432
|
options: {
|
|
234485
235433
|
"env-name": { type: "string" },
|
|
@@ -234815,7 +235763,7 @@ import { cpSync, existsSync as existsSync35, mkdirSync as mkdirSync25, rmSync as
|
|
|
234815
235763
|
import { readdir as readdir7 } from "node:fs/promises";
|
|
234816
235764
|
import { homedir as homedir26 } from "node:os";
|
|
234817
235765
|
import { join as join38 } from "node:path";
|
|
234818
|
-
import { parseArgs as
|
|
235766
|
+
import { parseArgs as parseArgs7 } from "node:util";
|
|
234819
235767
|
|
|
234820
235768
|
// src/cli/subcommands/memoryTokens.ts
|
|
234821
235769
|
init_systemPromptSize();
|
|
@@ -234896,7 +235844,7 @@ async function runMemoryTokensAction(options) {
|
|
|
234896
235844
|
}
|
|
234897
235845
|
|
|
234898
235846
|
// src/cli/subcommands/memory.ts
|
|
234899
|
-
function
|
|
235847
|
+
function printUsage4() {
|
|
234900
235848
|
console.log(`
|
|
234901
235849
|
Usage:
|
|
234902
235850
|
letta memory status [--agent <id>]
|
|
@@ -234925,7 +235873,7 @@ Examples:
|
|
|
234925
235873
|
letta memory tokens --memory-dir ~/.letta/agents/agent-123/memory --format json
|
|
234926
235874
|
`.trim());
|
|
234927
235875
|
}
|
|
234928
|
-
function
|
|
235876
|
+
function getAgentId4(agentFromArgs, agentIdFromArgs) {
|
|
234929
235877
|
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
234930
235878
|
}
|
|
234931
235879
|
var MEMORY_OPTIONS = {
|
|
@@ -234941,7 +235889,7 @@ var MEMORY_OPTIONS = {
|
|
|
234941
235889
|
quiet: { type: "boolean" }
|
|
234942
235890
|
};
|
|
234943
235891
|
function parseMemoryArgs(argv) {
|
|
234944
|
-
return
|
|
235892
|
+
return parseArgs7({
|
|
234945
235893
|
args: argv,
|
|
234946
235894
|
options: MEMORY_OPTIONS,
|
|
234947
235895
|
strict: true,
|
|
@@ -235002,15 +235950,15 @@ async function runMemorySubcommand(argv) {
|
|
|
235002
235950
|
} catch (error51) {
|
|
235003
235951
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
235004
235952
|
console.error(`Error: ${message}`);
|
|
235005
|
-
|
|
235953
|
+
printUsage4();
|
|
235006
235954
|
return 1;
|
|
235007
235955
|
}
|
|
235008
235956
|
const [action] = parsed.positionals;
|
|
235009
235957
|
if (parsed.values.help || !action || action === "help") {
|
|
235010
|
-
|
|
235958
|
+
printUsage4();
|
|
235011
235959
|
return 0;
|
|
235012
235960
|
}
|
|
235013
|
-
const agentId =
|
|
235961
|
+
const agentId = getAgentId4(parsed.values.agent, parsed.values["agent-id"]);
|
|
235014
235962
|
if (action === "tokens") {
|
|
235015
235963
|
return runMemoryTokensAction({
|
|
235016
235964
|
memoryDir: parsed.values["memory-dir"],
|
|
@@ -235143,17 +236091,18 @@ async function runMemorySubcommand(argv) {
|
|
|
235143
236091
|
return 1;
|
|
235144
236092
|
}
|
|
235145
236093
|
console.error(`Unknown action: ${action}`);
|
|
235146
|
-
|
|
236094
|
+
printUsage4();
|
|
235147
236095
|
return 1;
|
|
235148
236096
|
}
|
|
235149
236097
|
|
|
235150
236098
|
// src/cli/subcommands/messages.ts
|
|
235151
|
-
|
|
236099
|
+
init_backend2();
|
|
236100
|
+
init_messageSearch();
|
|
235152
236101
|
init_settings_manager();
|
|
235153
236102
|
import { writeFile as writeFile11 } from "node:fs/promises";
|
|
235154
236103
|
import { resolve as resolve33 } from "node:path";
|
|
235155
|
-
import { parseArgs as
|
|
235156
|
-
function
|
|
236104
|
+
import { parseArgs as parseArgs8 } from "node:util";
|
|
236105
|
+
function printUsage5() {
|
|
235157
236106
|
console.log(`
|
|
235158
236107
|
Usage:
|
|
235159
236108
|
letta messages search --query <text> [options]
|
|
@@ -235196,7 +236145,7 @@ Notes:
|
|
|
235196
236145
|
- For agent-to-agent messaging, use: letta -p --from-agent <sender-id> --agent <target-id> "message"
|
|
235197
236146
|
`.trim());
|
|
235198
236147
|
}
|
|
235199
|
-
function
|
|
236148
|
+
function parseLimit2(value, fallback) {
|
|
235200
236149
|
if (typeof value !== "string" || value.length === 0)
|
|
235201
236150
|
return fallback;
|
|
235202
236151
|
const parsed = Number.parseInt(value, 10);
|
|
@@ -235216,9 +236165,23 @@ function parseOrder(value) {
|
|
|
235216
236165
|
}
|
|
235217
236166
|
return;
|
|
235218
236167
|
}
|
|
235219
|
-
function
|
|
236168
|
+
function getAgentId5(agentFromArgs, agentIdFromArgs) {
|
|
235220
236169
|
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
|
|
235221
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
|
+
}
|
|
235222
236185
|
var MESSAGES_OPTIONS = {
|
|
235223
236186
|
help: { type: "boolean", short: "h" },
|
|
235224
236187
|
query: { type: "string" },
|
|
@@ -235239,7 +236202,7 @@ var MESSAGES_OPTIONS = {
|
|
|
235239
236202
|
output: { type: "string" }
|
|
235240
236203
|
};
|
|
235241
236204
|
function parseMessagesArgs(argv) {
|
|
235242
|
-
return
|
|
236205
|
+
return parseArgs8({
|
|
235243
236206
|
args: argv,
|
|
235244
236207
|
options: MESSAGES_OPTIONS,
|
|
235245
236208
|
strict: true,
|
|
@@ -235253,17 +236216,17 @@ async function runMessagesSubcommand(argv) {
|
|
|
235253
236216
|
} catch (error51) {
|
|
235254
236217
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
235255
236218
|
console.error(`Error: ${message}`);
|
|
235256
|
-
|
|
236219
|
+
printUsage5();
|
|
235257
236220
|
return 1;
|
|
235258
236221
|
}
|
|
235259
236222
|
const [action] = parsed.positionals;
|
|
235260
236223
|
if (parsed.values.help || !action || action === "help") {
|
|
235261
|
-
|
|
236224
|
+
printUsage5();
|
|
235262
236225
|
return 0;
|
|
235263
236226
|
}
|
|
235264
236227
|
try {
|
|
235265
236228
|
await settingsManager.initialize();
|
|
235266
|
-
const
|
|
236229
|
+
const backend4 = getBackend();
|
|
235267
236230
|
const renderText = (value) => {
|
|
235268
236231
|
if (typeof value === "string")
|
|
235269
236232
|
return value;
|
|
@@ -235347,13 +236310,13 @@ async function runMessagesSubcommand(argv) {
|
|
|
235347
236310
|
const seenIds = new Set;
|
|
235348
236311
|
let cursorBefore;
|
|
235349
236312
|
for (let pageIndex = 0;pageIndex < maxPages; pageIndex += 1) {
|
|
235350
|
-
const page = await
|
|
236313
|
+
const page = await backend4.listConversationMessages(conversationId, {
|
|
235351
236314
|
limit: pageLimit,
|
|
235352
236315
|
order: "desc",
|
|
235353
236316
|
...conversationId === "default" && agentIdForDefault ? { agent_id: agentIdForDefault } : {},
|
|
235354
236317
|
...cursorBefore ? { before: cursorBefore } : {}
|
|
235355
236318
|
});
|
|
235356
|
-
const items = page
|
|
236319
|
+
const items = pageItems2(page);
|
|
235357
236320
|
if (items.length === 0) {
|
|
235358
236321
|
break;
|
|
235359
236322
|
}
|
|
@@ -235380,24 +236343,24 @@ async function runMessagesSubcommand(argv) {
|
|
|
235380
236343
|
return 1;
|
|
235381
236344
|
}
|
|
235382
236345
|
const allAgents = parsed.values["all-agents"] ?? false;
|
|
235383
|
-
const agentId =
|
|
236346
|
+
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
235384
236347
|
if (!allAgents && !agentId) {
|
|
235385
236348
|
console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
235386
236349
|
return 1;
|
|
235387
236350
|
}
|
|
235388
|
-
const result = await
|
|
236351
|
+
const result = await searchMessagesForBackend({
|
|
235389
236352
|
query,
|
|
235390
236353
|
agent_id: allAgents ? undefined : agentId,
|
|
235391
236354
|
search_mode: parseMode(parsed.values.mode) ?? "hybrid",
|
|
235392
236355
|
start_date: parsed.values["start-date"],
|
|
235393
236356
|
end_date: parsed.values["end-date"],
|
|
235394
|
-
limit:
|
|
236357
|
+
limit: parseLimit2(parsed.values.limit, 10)
|
|
235395
236358
|
});
|
|
235396
236359
|
console.log(JSON.stringify(result, null, 2));
|
|
235397
236360
|
return 0;
|
|
235398
236361
|
}
|
|
235399
236362
|
if (action === "list") {
|
|
235400
|
-
const agentId =
|
|
236363
|
+
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
235401
236364
|
if (!agentId) {
|
|
235402
236365
|
console.error("Missing agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.");
|
|
235403
236366
|
return 1;
|
|
@@ -235408,14 +236371,14 @@ async function runMessagesSubcommand(argv) {
|
|
|
235408
236371
|
console.error(`Invalid --order "${orderRaw}". Use "asc" or "desc".`);
|
|
235409
236372
|
return 1;
|
|
235410
236373
|
}
|
|
235411
|
-
const response = await
|
|
236374
|
+
const response = await backend4.listAgentMessages(agentId, {
|
|
235412
236375
|
conversation_id: "default",
|
|
235413
|
-
limit:
|
|
236376
|
+
limit: parseLimit2(parsed.values.limit, 20),
|
|
235414
236377
|
after: parsed.values.after,
|
|
235415
236378
|
before: parsed.values.before,
|
|
235416
236379
|
order
|
|
235417
236380
|
});
|
|
235418
|
-
const messages = response
|
|
236381
|
+
const messages = pageItems2(response);
|
|
235419
236382
|
const startDate = parsed.values["start-date"];
|
|
235420
236383
|
const endDate = parsed.values["end-date"];
|
|
235421
236384
|
let filtered = messages;
|
|
@@ -235443,13 +236406,13 @@ async function runMessagesSubcommand(argv) {
|
|
|
235443
236406
|
console.error("Missing conversation id. Pass --conversation <id> or --conversation-id <id>.");
|
|
235444
236407
|
return 1;
|
|
235445
236408
|
}
|
|
235446
|
-
const agentId =
|
|
236409
|
+
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
235447
236410
|
if (conversationId === "default" && !agentId) {
|
|
235448
236411
|
console.error('Conversation "default" requires an agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.');
|
|
235449
236412
|
return 1;
|
|
235450
236413
|
}
|
|
235451
|
-
const pageLimit = Math.max(1,
|
|
235452
|
-
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));
|
|
235453
236416
|
const outputPathRaw = parsed.values.out || parsed.values.output;
|
|
235454
236417
|
const messages = await fetchConversationMessages(conversationId, agentId || undefined, pageLimit, maxPages);
|
|
235455
236418
|
const transcript = messages.flatMap((msg) => formatEntry(msg)).join(`
|
|
@@ -235480,7 +236443,7 @@ async function runMessagesSubcommand(argv) {
|
|
|
235480
236443
|
return 1;
|
|
235481
236444
|
}
|
|
235482
236445
|
console.error(`Unknown action: ${action}`);
|
|
235483
|
-
|
|
236446
|
+
printUsage5();
|
|
235484
236447
|
return 1;
|
|
235485
236448
|
}
|
|
235486
236449
|
|
|
@@ -235498,8 +236461,6 @@ async function runSubcommand(argv) {
|
|
|
235498
236461
|
return runAgentsSubcommand(rest);
|
|
235499
236462
|
case "messages":
|
|
235500
236463
|
return runMessagesSubcommand(rest);
|
|
235501
|
-
case "blocks":
|
|
235502
|
-
return runBlocksSubcommand(rest);
|
|
235503
236464
|
case "server":
|
|
235504
236465
|
case "remote":
|
|
235505
236466
|
return runListenSubcommand(rest);
|
|
@@ -237720,7 +238681,6 @@ USAGE
|
|
|
237720
238681
|
letta memory ... Memory filesystem subcommands
|
|
237721
238682
|
letta agents ... Agents subcommands (JSON-only)
|
|
237722
238683
|
letta messages ... Messages subcommands (JSON-only)
|
|
237723
|
-
letta blocks ... Blocks subcommands (JSON-only)
|
|
237724
238684
|
letta connect ... Connect providers from terminal
|
|
237725
238685
|
|
|
237726
238686
|
OPTIONS
|
|
@@ -237740,9 +238700,6 @@ SUBCOMMANDS
|
|
|
237740
238700
|
letta messages search --query <text> [--all-agents]
|
|
237741
238701
|
letta messages list [--agent <id>]
|
|
237742
238702
|
letta messages transcript --conversation <id> [--out <path>]
|
|
237743
|
-
letta blocks list --agent <id>
|
|
237744
|
-
letta blocks copy --block-id <id> [--label <label>] [--agent <id>] [--override]
|
|
237745
|
-
letta blocks attach --block-id <id> [--agent <id>] [--read-only] [--override]
|
|
237746
238703
|
letta connect <provider> [options]
|
|
237747
238704
|
|
|
237748
238705
|
BEHAVIOR
|
|
@@ -238031,8 +238988,13 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
238031
238988
|
const skillsDirectory = values.skills ?? undefined;
|
|
238032
238989
|
const memfsFlag = values.memfs;
|
|
238033
238990
|
const noMemfsFlag = values["no-memfs"];
|
|
238034
|
-
const
|
|
238035
|
-
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;
|
|
238036
238998
|
const noSkillsFlag = values["no-skills"];
|
|
238037
238999
|
const noBundledSkillsFlag = values["no-bundled-skills"];
|
|
238038
239000
|
const skillSourcesRaw = values["skill-sources"];
|
|
@@ -238783,7 +239745,7 @@ Error: ${message}`);
|
|
|
238783
239745
|
}
|
|
238784
239746
|
const { isLettaCloud: isLettaCloud3 } = await Promise.resolve().then(() => (init_memoryFilesystem2(), exports_memoryFilesystem2));
|
|
238785
239747
|
const willAutoEnableMemfs = shouldAutoEnableMemfsForNewAgent && await isLettaCloud3();
|
|
238786
|
-
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);
|
|
238787
239749
|
const personalityOptions = personality ? await buildCreateAgentOptionsForPersonality({
|
|
238788
239750
|
personalityId: personality,
|
|
238789
239751
|
model: effectiveModel
|
|
@@ -238845,16 +239807,15 @@ Error: ${message}`);
|
|
|
238845
239807
|
skipPromptUpdate: shouldCreateNew
|
|
238846
239808
|
})) : Promise.resolve().then(() => {
|
|
238847
239809
|
if (backend4.capabilities.localMemfs) {
|
|
238848
|
-
|
|
238849
|
-
|
|
238850
|
-
|
|
238851
|
-
|
|
238852
|
-
return { action: "enabled" };
|
|
239810
|
+
settingsManager2.setMemfsEnabled(agentId2, !localNoMemfsRequested);
|
|
239811
|
+
return {
|
|
239812
|
+
action: localNoMemfsRequested ? "disabled" : "enabled"
|
|
239813
|
+
};
|
|
238853
239814
|
}
|
|
238854
239815
|
if (memfsFlag) {
|
|
238855
239816
|
throw new Error("MemFS is not supported by the active backend.");
|
|
238856
239817
|
}
|
|
238857
|
-
if (noMemfsFlag) {
|
|
239818
|
+
if (noMemfsFlag || localNoMemfsRequested) {
|
|
238858
239819
|
settingsManager2.setMemfsEnabled(agentId2, false);
|
|
238859
239820
|
}
|
|
238860
239821
|
return null;
|
|
@@ -239146,4 +240107,4 @@ Error during initialization: ${message}`);
|
|
|
239146
240107
|
}
|
|
239147
240108
|
main();
|
|
239148
240109
|
|
|
239149
|
-
//# debugId=
|
|
240110
|
+
//# debugId=3EDFF39471E7DC8264756E2164756E21
|