@letta-ai/letta-code 0.30.5 → 0.30.6
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/dist/agent-presets.js +3 -13
- package/dist/agent-presets.js.map +2 -2
- package/dist/channels-slack.js +1 -1
- package/dist/channels-slack.js.map +3 -3
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/types/agent/subagents/manager.d.ts.map +1 -1
- package/dist/types/agent/subagents/subagent-launcher.d.ts +2 -0
- package/dist/types/agent/subagents/subagent-launcher.d.ts.map +1 -1
- package/dist/types/backend/api/client.d.ts +1 -0
- package/dist/types/backend/api/client.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-local-endpoint-provider.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-model-factory.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-models-runtime.d.ts.map +1 -1
- package/dist/types/backend/dev/pi-openai-compatible-provider.d.ts +14 -0
- package/dist/types/backend/dev/pi-openai-compatible-provider.d.ts.map +1 -0
- package/dist/types/backend/dev/pi-provider-registry.d.ts +3 -1
- package/dist/types/backend/dev/pi-provider-registry.d.ts.map +1 -1
- package/dist/types/backend/local/local-provider-auth-store.d.ts +1 -1
- package/dist/types/backend/local/local-provider-auth-store.d.ts.map +1 -1
- package/dist/types/channels/accounts.d.ts.map +1 -1
- package/dist/types/channels/config.d.ts.map +1 -1
- package/dist/types/channels/plugin-types.d.ts +1 -0
- package/dist/types/channels/plugin-types.d.ts.map +1 -1
- package/dist/types/channels/slack/ingress-controller.d.ts.map +1 -1
- package/dist/types/channels/slack/ingress-policy.d.ts +1 -0
- package/dist/types/channels/slack/ingress-policy.d.ts.map +1 -1
- package/dist/types/channels/types.d.ts +2 -0
- package/dist/types/channels/types.d.ts.map +1 -1
- package/dist/types/cli/helpers/error-formatter.d.ts +1 -0
- package/dist/types/cli/helpers/error-formatter.d.ts.map +1 -1
- package/dist/types/providers/byok-providers.d.ts.map +1 -1
- package/dist/types/runtime-context.d.ts +2 -0
- package/dist/types/runtime-context.d.ts.map +1 -1
- package/dist/types/tools/impl/shell-env.d.ts.map +1 -1
- package/dist/types/tools/toolset.d.ts +1 -0
- package/dist/types/tools/toolset.d.ts.map +1 -1
- package/dist/types/websocket/listener/mod-adapter.d.ts +1 -0
- package/dist/types/websocket/listener/mod-adapter.d.ts.map +1 -1
- package/letta.js +429 -197
- package/package.json +1 -1
- package/scripts/check-test-mock-isolation.js +5 -1
- package/scripts/isolated-unit-tests.json +15 -0
- package/scripts/source-file-size-baseline.json +1 -1
- package/skills/scheduling-tasks/SKILL.md +58 -54
package/letta.js
CHANGED
|
@@ -5464,7 +5464,7 @@ var package_default;
|
|
|
5464
5464
|
var init_package = __esm(() => {
|
|
5465
5465
|
package_default = {
|
|
5466
5466
|
name: "@letta-ai/letta-code",
|
|
5467
|
-
version: "0.30.
|
|
5467
|
+
version: "0.30.6",
|
|
5468
5468
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5469
5469
|
type: "module",
|
|
5470
5470
|
packageManager: "bun@1.3.0",
|
|
@@ -5746,6 +5746,7 @@ var init_memfs_git_proxy = __esm(() => {
|
|
|
5746
5746
|
var exports_client = {};
|
|
5747
5747
|
__export(exports_client, {
|
|
5748
5748
|
getServerUrl: () => getServerUrl,
|
|
5749
|
+
getRuntimeEnvironmentDeviceId: () => getRuntimeEnvironmentDeviceId,
|
|
5749
5750
|
getMemfsServerUrl: () => getMemfsServerUrl,
|
|
5750
5751
|
getMemfsGitProxyRewriteConfig: () => getMemfsGitProxyRewriteConfig,
|
|
5751
5752
|
getClientDefaultHeaders: () => getClientDefaultHeaders,
|
|
@@ -7125,12 +7126,7 @@ You **MUST** be proactive in creating crons when work extends beyond the current
|
|
|
7125
7126
|
|
|
7126
7127
|
**Cost**: Self-invocation is critical, but expensive. Default to the longest interval that still serves the user. Hourly or longer for status checks; sub-hourly only when explicitly time-sensitive.
|
|
7127
7128
|
|
|
7128
|
-
|
|
7129
|
-
- One-shot follow-up: \`letta cron add --name <short-name> --description <description> --prompt <future-message> --at "in 30m"\`
|
|
7130
|
-
- Recurring monitoring/heartbeat: \`letta cron add --name <short-name> --description <description> --prompt <future-message> --every "2h"\` or \`--cron "0 9 * * *"\`
|
|
7131
|
-
Always include \`--name\`, \`--description\`, and \`--prompt\`. \`$AGENT_ID\` is automatically injected into the shell environment, and \`letta cron\` uses it by default, so you do not need to specify which agent to invoke unless overriding the current agent intentionally.
|
|
7132
|
-
|
|
7133
|
-
Where crons run: for cloud agents, schedules default to durable Cloud schedules that fire from the cloud and execute in your cloud sandbox — they survive local shutdown, so this is the right default. If the scheduled work must run on a specific computer (e.g. it needs that computer's filesystem or local services), add \`--computer <deviceId>\` (from \`letta environments list\`) to keep the durable Cloud schedule but execute on that computer, with sandbox fallback if it is offline. Use \`--runner local\` only when that fallback is unacceptable; local schedules only fire while a Letta session is running on that computer.
|
|
7129
|
+
The mechanics — flags, where schedules run and execute, timezone handling — live in the scheduling-tasks skill. Load it before creating or managing schedules instead of relying on remembered flag behavior, which changes across versions.
|
|
7134
7130
|
|
|
7135
7131
|
# Harness Architecture
|
|
7136
7132
|
|
|
@@ -7310,12 +7306,7 @@ You **MUST** be proactive in creating crons when work extends beyond the current
|
|
|
7310
7306
|
|
|
7311
7307
|
**Cost**: Self-invocation is critical, but expensive. Default to the longest interval that still serves the user. Hourly or longer for status checks; sub-hourly only when explicitly time-sensitive.
|
|
7312
7308
|
|
|
7313
|
-
|
|
7314
|
-
- One-shot follow-up: \`letta cron add --name <short-name> --description <description> --prompt <future-message> --at "in 30m"\`
|
|
7315
|
-
- Recurring monitoring/heartbeat: \`letta cron add --name <short-name> --description <description> --prompt <future-message> --every "2h"\` or \`--cron "0 9 * * *"\`
|
|
7316
|
-
Always include \`--name\`, \`--description\`, and \`--prompt\`. \`$AGENT_ID\` is automatically injected into the shell environment, and \`letta cron\` uses it by default, so you do not need to specify which agent to invoke unless overriding the current agent intentionally.
|
|
7317
|
-
|
|
7318
|
-
Where crons run: for cloud agents, schedules default to durable Cloud schedules that fire from the cloud and execute in your cloud sandbox — they survive local shutdown, so this is the right default. If the scheduled work must run on a specific computer (e.g. it needs that computer's filesystem or local services), add \`--computer <deviceId>\` (from \`letta environments list\`) to keep the durable Cloud schedule but execute on that computer, with sandbox fallback if it is offline. Use \`--runner local\` only when that fallback is unacceptable; local schedules only fire while a Letta session is running on that computer.
|
|
7309
|
+
The mechanics — flags, where schedules run and execute, timezone handling — live in the scheduling-tasks skill. Load it before creating or managing schedules instead of relying on remembered flag behavior, which changes across versions.
|
|
7319
7310
|
|
|
7320
7311
|
# Harness Architecture
|
|
7321
7312
|
|
|
@@ -139326,7 +139317,7 @@ function isProviderConfigured(provider, localProviderNames) {
|
|
|
139326
139317
|
function listConfiguredPiProviders(localProviderNames) {
|
|
139327
139318
|
return PI_PROVIDER_SPECS.filter((provider) => isProviderConfigured(provider, localProviderNames)).map((provider) => provider.id);
|
|
139328
139319
|
}
|
|
139329
|
-
var LOCAL_CHATGPT_PROVIDER_NAME = "chatgpt-plus-pro", LOCAL_OPENAI_PROVIDER_NAME = "lc-openai", LOCAL_ANTHROPIC_PROVIDER_NAME = "lc-anthropic", LOCAL_OPENROUTER_PROVIDER_NAME = "lc-openrouter", LOCAL_OLLAMA_PROVIDER_NAME = "lc-ollama", LOCAL_OLLAMA_CLOUD_PROVIDER_NAME = "lc-ollama-cloud", LOCAL_LMSTUDIO_PROVIDER_NAME = "lc-lmstudio", LMSTUDIO_OPENAI_PROVIDER_TYPE = "lmstudio_openai", LEGACY_LMSTUDIO_PROVIDER_TYPE = "lmstudio", LOCAL_LLAMA_CPP_PROVIDER_NAME = "lc-llama-cpp", LOCAL_ZAI_PROVIDER_NAME = "lc-zai", LOCAL_ZAI_CODING_PROVIDER_NAME = "lc-zai-coding", LOCAL_MINIMAX_PROVIDER_NAME = "lc-minimax", LOCAL_MOONSHOT_PROVIDER_NAME = "lc-moonshot", LOCAL_KIMI_CODE_PROVIDER_NAME = "lc-kimi-code", LOCAL_GOOGLE_AI_PROVIDER_NAME = "lc-gemini", LOCAL_BEDROCK_PROVIDER_NAME = "lc-bedrock", prefixedCatalogModelHandle = (prefix) => (model) => `${prefix}${model.id}`, PI_PROVIDER_ALIASES, PI_TUI_DEFAULT_MODEL_IDS, PI_TUI_DEFAULTLESS_PROVIDER_IDS, PI_PROVIDER_OVERRIDES, LOCAL_ENDPOINT_PROVIDER_SPECS, PI_PROVIDER_SPECS, SUPPORTED_LOCAL_PROVIDER_TYPES, KNOWN_PI_PROVIDERS, PROVIDER_TYPE_TO_BASE_PROVIDER;
|
|
139320
|
+
var LOCAL_CHATGPT_PROVIDER_NAME = "chatgpt-plus-pro", LOCAL_OPENAI_PROVIDER_NAME = "lc-openai", LOCAL_OPENAI_COMPATIBLE_PROVIDER_NAME = "lc-openai-compatible", OPENAI_COMPATIBLE_PI_PROVIDER_ID = "openai-compatible", LOCAL_ANTHROPIC_PROVIDER_NAME = "lc-anthropic", LOCAL_OPENROUTER_PROVIDER_NAME = "lc-openrouter", LOCAL_OLLAMA_PROVIDER_NAME = "lc-ollama", LOCAL_OLLAMA_CLOUD_PROVIDER_NAME = "lc-ollama-cloud", LOCAL_LMSTUDIO_PROVIDER_NAME = "lc-lmstudio", LMSTUDIO_OPENAI_PROVIDER_TYPE = "lmstudio_openai", LEGACY_LMSTUDIO_PROVIDER_TYPE = "lmstudio", LOCAL_LLAMA_CPP_PROVIDER_NAME = "lc-llama-cpp", LOCAL_ZAI_PROVIDER_NAME = "lc-zai", LOCAL_ZAI_CODING_PROVIDER_NAME = "lc-zai-coding", LOCAL_MINIMAX_PROVIDER_NAME = "lc-minimax", LOCAL_MOONSHOT_PROVIDER_NAME = "lc-moonshot", LOCAL_KIMI_CODE_PROVIDER_NAME = "lc-kimi-code", LOCAL_GOOGLE_AI_PROVIDER_NAME = "lc-gemini", LOCAL_BEDROCK_PROVIDER_NAME = "lc-bedrock", prefixedCatalogModelHandle = (prefix) => (model) => `${prefix}${model.id}`, PI_PROVIDER_ALIASES, PI_TUI_DEFAULT_MODEL_IDS, PI_TUI_DEFAULTLESS_PROVIDER_IDS, PI_PROVIDER_OVERRIDES, LOCAL_ENDPOINT_PROVIDER_SPECS, PI_PROVIDER_SPECS, SUPPORTED_LOCAL_PROVIDER_TYPES, KNOWN_PI_PROVIDERS, PROVIDER_TYPE_TO_BASE_PROVIDER;
|
|
139330
139321
|
var init_pi_provider_registry = __esm(() => {
|
|
139331
139322
|
init_compat2();
|
|
139332
139323
|
init_all();
|
|
@@ -139473,6 +139464,18 @@ var init_pi_provider_registry = __esm(() => {
|
|
|
139473
139464
|
envConfigured: () => hasEnvValue(process.env.OLLAMA_API_KEY),
|
|
139474
139465
|
createCustomModel: true
|
|
139475
139466
|
},
|
|
139467
|
+
{
|
|
139468
|
+
id: OPENAI_COMPATIBLE_PI_PROVIDER_ID,
|
|
139469
|
+
providerTypes: ["openai-compatible"],
|
|
139470
|
+
handlePrefixes: ["openai-compatible/"],
|
|
139471
|
+
localProviderNames: [
|
|
139472
|
+
OPENAI_COMPATIBLE_PI_PROVIDER_ID,
|
|
139473
|
+
LOCAL_OPENAI_COMPATIBLE_PROVIDER_NAME
|
|
139474
|
+
],
|
|
139475
|
+
fallbackApiKey: "not-needed",
|
|
139476
|
+
localModelDiscovery: "openai-compatible",
|
|
139477
|
+
createCustomModel: true
|
|
139478
|
+
},
|
|
139476
139479
|
{
|
|
139477
139480
|
id: "lmstudio",
|
|
139478
139481
|
providerTypes: [
|
|
@@ -139595,6 +139598,10 @@ async function createOrUpdateLocalProvider(input) {
|
|
|
139595
139598
|
}
|
|
139596
139599
|
const file3 = readAuthFile(input.storageDir);
|
|
139597
139600
|
const existing = file3.providers[input.providerName];
|
|
139601
|
+
const baseURL = input.baseURL ?? existing?.base_url;
|
|
139602
|
+
if (input.providerType === OPENAI_COMPATIBLE_PI_PROVIDER_ID && !baseURL?.trim()) {
|
|
139603
|
+
throw new Error("OpenAI-compatible API requires a base URL.");
|
|
139604
|
+
}
|
|
139598
139605
|
const now = new Date().toISOString();
|
|
139599
139606
|
const auth = input.providerType === "chatgpt_oauth" ? parseChatGPTOAuth(input.apiKey) : { type: "api", key: input.apiKey };
|
|
139600
139607
|
const next = {
|
|
@@ -139606,7 +139613,7 @@ async function createOrUpdateLocalProvider(input) {
|
|
|
139606
139613
|
...input.accessKey ? { access_key: input.accessKey } : {},
|
|
139607
139614
|
...input.region ? { region: input.region } : {},
|
|
139608
139615
|
...input.profile ? { profile: input.profile } : {},
|
|
139609
|
-
...
|
|
139616
|
+
...baseURL ? { base_url: baseURL } : {},
|
|
139610
139617
|
...input.timeout !== undefined ? { timeout: input.timeout } : existing?.timeout !== undefined ? { timeout: existing.timeout } : {},
|
|
139611
139618
|
created_at: existing?.created_at ?? now,
|
|
139612
139619
|
updated_at: now
|
|
@@ -140225,6 +140232,20 @@ var init_byok_providers = __esm(() => {
|
|
|
140225
140232
|
providerName: "ollama-cloud",
|
|
140226
140233
|
providerNames: ["ollama-cloud", "lc-ollama-cloud"]
|
|
140227
140234
|
},
|
|
140235
|
+
{
|
|
140236
|
+
id: "openai-compatible",
|
|
140237
|
+
displayName: "OpenAI-compatible API",
|
|
140238
|
+
description: "Connect an OpenAI-compatible Chat Completions endpoint",
|
|
140239
|
+
providerType: "openai-compatible",
|
|
140240
|
+
providerName: "openai-compatible",
|
|
140241
|
+
providerNames: ["openai-compatible", "lc-openai-compatible"],
|
|
140242
|
+
requiresApiKey: false,
|
|
140243
|
+
defaultApiKey: LOCAL_PROVIDER_NO_API_KEY,
|
|
140244
|
+
fields: [
|
|
140245
|
+
{ key: "apiKey", label: "API Key", secret: true, required: false },
|
|
140246
|
+
{ key: "baseUrl", label: "Base URL" }
|
|
140247
|
+
]
|
|
140248
|
+
},
|
|
140228
140249
|
{
|
|
140229
140250
|
id: "lmstudio",
|
|
140230
140251
|
displayName: "LM Studio (local)",
|
|
@@ -146165,6 +146186,7 @@ var init_config2 = __esm(() => {
|
|
|
146165
146186
|
allowedUsers: parsed.allowed_users ?? [],
|
|
146166
146187
|
transcribeVoice: parsed.transcribe_voice === true,
|
|
146167
146188
|
listenMode: parsed.listen_mode === true,
|
|
146189
|
+
mentionOnlyChannels: Array.isArray(parsed.mention_only_channels) ? parsed.mention_only_channels.filter((channelId) => typeof channelId === "string") : [],
|
|
146168
146190
|
allowBots: normalizeSlackAllowBotsMode(parsed.allow_bots)
|
|
146169
146191
|
};
|
|
146170
146192
|
}
|
|
@@ -150405,6 +150427,11 @@ function cloneAccount(account) {
|
|
|
150405
150427
|
if (isTelegramChannelAccount(account)) {
|
|
150406
150428
|
cloned.binding = { ...account.binding };
|
|
150407
150429
|
}
|
|
150430
|
+
if (isSlackChannelAccount(account)) {
|
|
150431
|
+
cloned.mentionOnlyChannels = [
|
|
150432
|
+
...account.mentionOnlyChannels ?? []
|
|
150433
|
+
];
|
|
150434
|
+
}
|
|
150408
150435
|
if (isDiscordChannelAccount(account) && account.allowedChannels) {
|
|
150409
150436
|
cloned.allowedChannels = Array.isArray(account.allowedChannels) ? [...account.allowedChannels] : { ...account.allowedChannels };
|
|
150410
150437
|
}
|
|
@@ -150474,6 +150501,8 @@ function normalizeLoadedAccount(account) {
|
|
|
150474
150501
|
delete next.progress_ui;
|
|
150475
150502
|
delete next.progressUi;
|
|
150476
150503
|
next.listenMode = next.listenMode === true;
|
|
150504
|
+
const mentionOnlyChannels = next.mentionOnlyChannels;
|
|
150505
|
+
next.mentionOnlyChannels = Array.isArray(mentionOnlyChannels) ? [...mentionOnlyChannels] : [];
|
|
150477
150506
|
next.allowBots = normalizeSlackAllowBotsMode(next.allowBots);
|
|
150478
150507
|
}
|
|
150479
150508
|
if (isDiscordChannelAccount(next)) {
|
|
@@ -150623,6 +150652,7 @@ function makeDefaultLegacyAccount(channelId) {
|
|
|
150623
150652
|
defaultPermissionMode: DEFAULT_SLACK_PERMISSION_MODE,
|
|
150624
150653
|
transcribeVoice: config3.transcribeVoice === true,
|
|
150625
150654
|
listenMode: config3.listenMode === true,
|
|
150655
|
+
mentionOnlyChannels: [...config3.mentionOnlyChannels ?? []],
|
|
150626
150656
|
allowBots: config3.allowBots ?? false,
|
|
150627
150657
|
createdAt: now,
|
|
150628
150658
|
updatedAt: now
|
|
@@ -150822,6 +150852,7 @@ var init_accounts = __esm(() => {
|
|
|
150822
150852
|
group_mode: "groupMode",
|
|
150823
150853
|
inbound_debounce_ms: "inboundDebounceMs",
|
|
150824
150854
|
listen_mode: "listenMode",
|
|
150855
|
+
mention_only_channels: "mentionOnlyChannels",
|
|
150825
150856
|
message_prefix: "messagePrefix",
|
|
150826
150857
|
media_max_bytes: "mediaMaxBytes",
|
|
150827
150858
|
attachment_filter: "attachmentFilter",
|
|
@@ -154533,6 +154564,9 @@ var init_inbound_debounce = __esm(() => {
|
|
|
154533
154564
|
});
|
|
154534
154565
|
|
|
154535
154566
|
// src/channels/slack/ingress-policy.ts
|
|
154567
|
+
function isSlackMentionOnlyChannel(channelId, mentionOnlyChannels) {
|
|
154568
|
+
return mentionOnlyChannels?.includes(channelId) === true;
|
|
154569
|
+
}
|
|
154536
154570
|
function hasRecordValue(value) {
|
|
154537
154571
|
return value !== null && typeof value === "object";
|
|
154538
154572
|
}
|
|
@@ -154763,6 +154797,9 @@ function createSlackIngressController(params) {
|
|
|
154763
154797
|
})) {
|
|
154764
154798
|
return;
|
|
154765
154799
|
}
|
|
154800
|
+
if (basePolicy.chatType === "channel" && !basePolicy.wasMentioned && isSlackMentionOnlyChannel(channelId, config3.mentionOnlyChannels)) {
|
|
154801
|
+
return;
|
|
154802
|
+
}
|
|
154766
154803
|
const attachments = await resolveSlackInboundAttachments({
|
|
154767
154804
|
accountId: config3.accountId,
|
|
154768
154805
|
token: config3.botToken,
|
|
@@ -154944,6 +154981,9 @@ function createSlackIngressController(params) {
|
|
|
154944
154981
|
return;
|
|
154945
154982
|
}
|
|
154946
154983
|
const chatType = resolveSlackChatType(chatId);
|
|
154984
|
+
if (chatType === "channel" && isSlackMentionOnlyChannel(chatId, config3.mentionOnlyChannels)) {
|
|
154985
|
+
return;
|
|
154986
|
+
}
|
|
154947
154987
|
const threadId = chatType === "channel" ? knownThreadIdsByMessageId.get(targetMessageId) ?? targetMessageId : knownThreadIdsByMessageId.get(targetMessageId) ?? null;
|
|
154948
154988
|
try {
|
|
154949
154989
|
await adapter.onMessage({
|
|
@@ -173673,6 +173713,10 @@ function getShellEnv() {
|
|
|
173673
173713
|
env3[pathKey] = existingPath ? `${pathPrefixes.join(shellPathDelimiter())}${shellPathDelimiter()}${existingPath}` : pathPrefixes.join(shellPathDelimiter());
|
|
173674
173714
|
}
|
|
173675
173715
|
env3.USER_CWD = getCurrentWorkingDirectory();
|
|
173716
|
+
const environmentDeviceId = getRuntimeContext()?.environmentDeviceId?.trim();
|
|
173717
|
+
if (environmentDeviceId) {
|
|
173718
|
+
env3.LETTA_RUNTIME_ENVIRONMENT_DEVICE_ID = environmentDeviceId;
|
|
173719
|
+
}
|
|
173676
173720
|
let agentId;
|
|
173677
173721
|
try {
|
|
173678
173722
|
const resolvedAgentId = getCurrentAgentId();
|
|
@@ -348867,9 +348911,21 @@ import { join as join34 } from "node:path";
|
|
|
348867
348911
|
async function getUnavailableListenerClient() {
|
|
348868
348912
|
throw new Error("letta.client is not available in listener mods");
|
|
348869
348913
|
}
|
|
348914
|
+
function resolveListenerAgentMemfsContext(agentId) {
|
|
348915
|
+
if (!agentId)
|
|
348916
|
+
return { enabled: false, memoryDir: null };
|
|
348917
|
+
try {
|
|
348918
|
+
return settingsManager.isMemfsEnabled(agentId) ? {
|
|
348919
|
+
enabled: true,
|
|
348920
|
+
memoryDir: getScopedMemoryFilesystemRoot(agentId)
|
|
348921
|
+
} : { enabled: false, memoryDir: null };
|
|
348922
|
+
} catch {
|
|
348923
|
+
return { enabled: false, memoryDir: null };
|
|
348924
|
+
}
|
|
348925
|
+
}
|
|
348870
348926
|
function createListenerModContext(options3 = {}) {
|
|
348871
348927
|
const cwd = options3.workingDirectory ?? getCurrentWorkingDirectory();
|
|
348872
|
-
|
|
348928
|
+
const context3 = buildModInvocationContext({
|
|
348873
348929
|
agent: options3.agent ?? null,
|
|
348874
348930
|
conversationId: options3.sessionId ?? null,
|
|
348875
348931
|
modelIdentifier: options3.modelIdentifier ?? null,
|
|
@@ -348877,6 +348933,13 @@ function createListenerModContext(options3 = {}) {
|
|
|
348877
348933
|
toolset: options3.toolset ?? null,
|
|
348878
348934
|
workingDirectory: cwd
|
|
348879
348935
|
});
|
|
348936
|
+
return {
|
|
348937
|
+
...context3,
|
|
348938
|
+
memfs: resolveListenerAgentMemfsContext(context3.agent.id)
|
|
348939
|
+
};
|
|
348940
|
+
}
|
|
348941
|
+
function createListenerAgentModContext(agentId) {
|
|
348942
|
+
return createListenerModContext({ agent: { id: agentId } });
|
|
348880
348943
|
}
|
|
348881
348944
|
function createListenerModAdapter(options3 = {}) {
|
|
348882
348945
|
return createModAdapter({
|
|
@@ -364865,6 +364928,7 @@ function composeSubagentChildEnv(options3) {
|
|
|
364865
364928
|
backendMode,
|
|
364866
364929
|
localBackendStorageDir,
|
|
364867
364930
|
parentAgentId,
|
|
364931
|
+
subagentType,
|
|
364868
364932
|
launchProfile,
|
|
364869
364933
|
inheritedPrimaryRoot,
|
|
364870
364934
|
memoryScope,
|
|
@@ -364878,6 +364942,7 @@ function composeSubagentChildEnv(options3) {
|
|
|
364878
364942
|
...inheritedApiKey && { LETTA_API_KEY: inheritedApiKey },
|
|
364879
364943
|
...inheritedBaseUrl && { LETTA_BASE_URL: inheritedBaseUrl },
|
|
364880
364944
|
LETTA_CODE_AGENT_ROLE: "subagent",
|
|
364945
|
+
...subagentType === "reflection" && { [LETTA_DISABLE_MODS_ENV]: "1" },
|
|
364881
364946
|
...parentAgentId && { LETTA_PARENT_AGENT_ID: parentAgentId },
|
|
364882
364947
|
...transcriptPath && { TRANSCRIPT_PATH: transcriptPath },
|
|
364883
364948
|
...inheritedChannelContext && {
|
|
@@ -365410,6 +365475,7 @@ async function executeSubagent(type3, config3, model, userPrompt, subagentId, is
|
|
|
365410
365475
|
backendMode,
|
|
365411
365476
|
localBackendStorageDir,
|
|
365412
365477
|
parentAgentId,
|
|
365478
|
+
subagentType: type3,
|
|
365413
365479
|
launchProfile: effectiveLaunchProfile,
|
|
365414
365480
|
inheritedPrimaryRoot,
|
|
365415
365481
|
memoryScope,
|
|
@@ -373761,6 +373827,7 @@ function parseInheritedChannelContextEnv() {
|
|
|
373761
373827
|
async function prepareToolExecutionContextForScope(params) {
|
|
373762
373828
|
const {
|
|
373763
373829
|
connectionId,
|
|
373830
|
+
environmentDeviceId,
|
|
373764
373831
|
agentId,
|
|
373765
373832
|
conversationId,
|
|
373766
373833
|
overrideModel,
|
|
@@ -373826,6 +373893,7 @@ async function prepareToolExecutionContextForScope(params) {
|
|
|
373826
373893
|
agent: agent2,
|
|
373827
373894
|
runtimeContext: {
|
|
373828
373895
|
connectionId,
|
|
373896
|
+
environmentDeviceId,
|
|
373829
373897
|
agentId,
|
|
373830
373898
|
agentName: agent2.name ?? null,
|
|
373831
373899
|
conversationId: scopedConversationId,
|
|
@@ -375025,13 +375093,13 @@ echo password=${token}
|
|
|
375025
375093
|
} else {
|
|
375026
375094
|
helper = `!f() { echo "username=letta"; echo "password=${token}"; }; f`;
|
|
375027
375095
|
}
|
|
375028
|
-
|
|
375029
|
-
"config",
|
|
375030
|
-
|
|
375031
|
-
|
|
375032
|
-
|
|
375096
|
+
const writeHelperWithReset = async (key) => {
|
|
375097
|
+
await gitConfig(dir, ["config", "--local", "--replace-all", key, ""]);
|
|
375098
|
+
await gitConfig(dir, ["config", "--local", "--add", key, helper]);
|
|
375099
|
+
};
|
|
375100
|
+
await writeHelperWithReset(`credential.${normalizedBaseUrl}.helper`);
|
|
375033
375101
|
if (rawBaseUrl !== normalizedBaseUrl) {
|
|
375034
|
-
await
|
|
375102
|
+
await writeHelperWithReset(`credential.${rawBaseUrl}.helper`);
|
|
375035
375103
|
}
|
|
375036
375104
|
debugLog("memfs-git", `Configured local credential helper for ${normalizedBaseUrl}${rawBaseUrl !== normalizedBaseUrl ? ` (and raw ${rawBaseUrl})` : ""}`);
|
|
375037
375105
|
}
|
|
@@ -379215,6 +379283,7 @@ function isEncryptedContentError(e2) {
|
|
|
379215
379283
|
function formatErrorDetails2(e2, agentId, conversationId, options3 = {}) {
|
|
379216
379284
|
let runId;
|
|
379217
379285
|
const surface = options3.surface ?? "terminal";
|
|
379286
|
+
const fallback = (raw) => options3.unclassifiedFallback === "generic" ? GENERIC_ERROR_MESSAGE : raw;
|
|
379218
379287
|
const encryptedContentMsg = checkEncryptedContentError(e2);
|
|
379219
379288
|
if (encryptedContentMsg)
|
|
379220
379289
|
return encryptedContentMsg;
|
|
@@ -379303,6 +379372,8 @@ Detail: ${detail}` : "";
|
|
|
379303
379372
|
const conversationBusyMessage = formatConversationBusyErrorForDisplay(baseError, runId, options3);
|
|
379304
379373
|
if (conversationBusyMessage)
|
|
379305
379374
|
return conversationBusyMessage;
|
|
379375
|
+
if (options3.unclassifiedFallback === "generic")
|
|
379376
|
+
return fallback(baseError);
|
|
379306
379377
|
return runId && agentId ? `${baseError}
|
|
379307
379378
|
${createAgentLink(runId, agentId, conversationId, surface)}` : baseError;
|
|
379308
379379
|
}
|
|
@@ -379316,32 +379387,34 @@ ${createAgentLink(runId, agentId, conversationId, surface)}` : baseError;
|
|
|
379316
379387
|
const conversationBusyMessage = formatConversationBusyErrorForDisplay(baseError, runId, options3);
|
|
379317
379388
|
if (conversationBusyMessage)
|
|
379318
379389
|
return conversationBusyMessage;
|
|
379390
|
+
if (options3.unclassifiedFallback === "generic")
|
|
379391
|
+
return fallback(baseError);
|
|
379319
379392
|
return runId && agentId ? `${baseError}
|
|
379320
379393
|
${createAgentLink(runId, agentId, conversationId, surface)}` : baseError;
|
|
379321
379394
|
}
|
|
379322
|
-
return e2.message;
|
|
379395
|
+
return fallback(e2.message);
|
|
379323
379396
|
}
|
|
379324
379397
|
if (e2 instanceof Error) {
|
|
379325
|
-
return e2.message;
|
|
379398
|
+
return fallback(e2.message);
|
|
379326
379399
|
}
|
|
379327
379400
|
if (typeof e2 === "object" && e2 !== null) {
|
|
379328
379401
|
const obj = e2;
|
|
379329
379402
|
if (typeof obj.message === "string") {
|
|
379330
|
-
return obj.message;
|
|
379403
|
+
return fallback(obj.message);
|
|
379331
379404
|
}
|
|
379332
379405
|
if (typeof obj.error === "string") {
|
|
379333
|
-
return obj.error;
|
|
379406
|
+
return fallback(obj.error);
|
|
379334
379407
|
}
|
|
379335
379408
|
if (typeof obj.detail === "string") {
|
|
379336
|
-
return obj.detail;
|
|
379409
|
+
return fallback(obj.detail);
|
|
379337
379410
|
}
|
|
379338
379411
|
try {
|
|
379339
|
-
return JSON.stringify(e2, null, 2);
|
|
379412
|
+
return fallback(JSON.stringify(e2, null, 2));
|
|
379340
379413
|
} catch {
|
|
379341
|
-
return "[Error: Unable to serialize error object]";
|
|
379414
|
+
return fallback("[Error: Unable to serialize error object]");
|
|
379342
379415
|
}
|
|
379343
379416
|
}
|
|
379344
|
-
return String(e2);
|
|
379417
|
+
return fallback(String(e2));
|
|
379345
379418
|
}
|
|
379346
379419
|
function getRetryStatusMessage(errorDetail2) {
|
|
379347
379420
|
if (!errorDetail2)
|
|
@@ -379373,7 +379446,7 @@ function createAgentLink(runId, agentId, conversationId, surface) {
|
|
|
379373
379446
|
const agentRef = surface === "terminal" ? buildAgentTerminalLink(agentId, { conversationId }) : agentId;
|
|
379374
379447
|
return `View agent: ${agentRef} (run: ${runId})`;
|
|
379375
379448
|
}
|
|
379376
|
-
var LETTA_USAGE_URL, LETTA_AGENTS_URL, CLOUDFLARE_EDGE_5XX_MARKER_PATTERN, CLOUDFLARE_EDGE_5XX_TITLE_PATTERN, CLOUDFLARE_EDGE_5XX_FORMATTED_PATTERN, CLOUDFLARE_JSON_5XX_PATTERN, CHATGPT_USAGE_LIMIT_HINT = "Switch models with /model, or connect your own provider keys with /connect.", ENCRYPTED_CONTENT_HINT, DEFAULT_RETRY_MESSAGE = "Unexpected downstream LLM API error, retrying...", ENDPOINT_TYPE_DISPLAY_NAMES;
|
|
379449
|
+
var LETTA_USAGE_URL, LETTA_AGENTS_URL, GENERIC_ERROR_MESSAGE = "The request failed. Please try again.", CLOUDFLARE_EDGE_5XX_MARKER_PATTERN, CLOUDFLARE_EDGE_5XX_TITLE_PATTERN, CLOUDFLARE_EDGE_5XX_FORMATTED_PATTERN, CLOUDFLARE_JSON_5XX_PATTERN, CHATGPT_USAGE_LIMIT_HINT = "Switch models with /model, or connect your own provider keys with /connect.", ENCRYPTED_CONTENT_HINT, DEFAULT_RETRY_MESSAGE = "Unexpected downstream LLM API error, retrying...", ENDPOINT_TYPE_DISPLAY_NAMES;
|
|
379377
379450
|
var init_error_formatter = __esm(() => {
|
|
379378
379451
|
init_error();
|
|
379379
379452
|
init_conversation_busy_error();
|
|
@@ -380797,7 +380870,10 @@ function createLocalEndpointPiProvider(options3) {
|
|
|
380797
380870
|
name: `${options3.name} API key`,
|
|
380798
380871
|
resolve: async ({ credential }) => {
|
|
380799
380872
|
const apiKey = credential?.key ?? options3.apiKey;
|
|
380800
|
-
return apiKey ? {
|
|
380873
|
+
return apiKey ? {
|
|
380874
|
+
auth: apiKey === "not-needed" ? { apiKey, headers: { Authorization: null } } : { apiKey },
|
|
380875
|
+
source: "local provider record"
|
|
380876
|
+
} : undefined;
|
|
380801
380877
|
}
|
|
380802
380878
|
}
|
|
380803
380879
|
},
|
|
@@ -381158,6 +381234,27 @@ var init_pi_ollama_provider = __esm(() => {
|
|
|
381158
381234
|
init_pi_local_endpoint_provider();
|
|
381159
381235
|
});
|
|
381160
381236
|
|
|
381237
|
+
// src/backend/dev/pi-openai-compatible-provider.ts
|
|
381238
|
+
function createOpenAICompatiblePiProvider(options3) {
|
|
381239
|
+
return createLocalEndpointPiProvider({
|
|
381240
|
+
id: OPENAI_COMPATIBLE_PI_PROVIDER_ID,
|
|
381241
|
+
name: "OpenAI-compatible API",
|
|
381242
|
+
baseURL: options3.baseURL,
|
|
381243
|
+
...options3.apiKey ? { apiKey: options3.apiKey } : {},
|
|
381244
|
+
...options3.fetchImpl ? { fetchImpl: options3.fetchImpl } : {},
|
|
381245
|
+
...options3.discoveryTimeoutMs ? { discoveryTimeoutMs: options3.discoveryTimeoutMs } : {},
|
|
381246
|
+
discover: openAICompatibleDiscover
|
|
381247
|
+
});
|
|
381248
|
+
}
|
|
381249
|
+
var openAICompatibleDiscover = async (context3) => {
|
|
381250
|
+
const list = await context3.fetchJson(`${context3.openAIBaseURL}/models`);
|
|
381251
|
+
return modelIdsFromOpenAICompatibleList(list).map((modelId) => context3.lastKnown.get(modelId) ?? context3.buildModel({ id: modelId }));
|
|
381252
|
+
};
|
|
381253
|
+
var init_pi_openai_compatible_provider = __esm(() => {
|
|
381254
|
+
init_pi_local_endpoint_provider();
|
|
381255
|
+
init_pi_provider_registry();
|
|
381256
|
+
});
|
|
381257
|
+
|
|
381161
381258
|
// src/backend/dev/pi-models-runtime.ts
|
|
381162
381259
|
function aliasedAuthContext() {
|
|
381163
381260
|
const base2 = defaultProviderAuthContext();
|
|
@@ -381185,7 +381282,7 @@ function resolveLocalEndpointConnection(providerId2, storageDir) {
|
|
|
381185
381282
|
break;
|
|
381186
381283
|
}
|
|
381187
381284
|
const baseURL = record5?.base_url ?? spec.baseUrlEnv?.() ?? spec.defaultBaseURL ?? "";
|
|
381188
|
-
const apiKey = localProviderApiKeyFromRecord(record5) ?? spec.apiKeyEnv?.() ?? spec.fallbackApiKey;
|
|
381285
|
+
const apiKey = localProviderApiKeyFromRecord(record5) ?? spec.apiKeyEnv?.() ?? (record5 !== null || spec.autoDetectLocalEndpoint === true ? spec.fallbackApiKey : undefined);
|
|
381189
381286
|
return {
|
|
381190
381287
|
baseURL,
|
|
381191
381288
|
apiKey,
|
|
@@ -381424,6 +381521,7 @@ var init_pi_models_runtime = __esm(() => {
|
|
|
381424
381521
|
init_pi_lmstudio_provider();
|
|
381425
381522
|
init_pi_mod_provider();
|
|
381426
381523
|
init_pi_ollama_provider();
|
|
381524
|
+
init_pi_openai_compatible_provider();
|
|
381427
381525
|
init_pi_provider_mod_registry();
|
|
381428
381526
|
init_pi_provider_registry();
|
|
381429
381527
|
init_registered_pi_provider_runtime();
|
|
@@ -381440,7 +381538,11 @@ var init_pi_models_runtime = __esm(() => {
|
|
|
381440
381538
|
})
|
|
381441
381539
|
],
|
|
381442
381540
|
[LLAMA_CPP_PI_PROVIDER_ID, (input) => createLlamaCppPiProvider(input)],
|
|
381443
|
-
[LMSTUDIO_PI_PROVIDER_ID, (input) => createLmStudioPiProvider(input)]
|
|
381541
|
+
[LMSTUDIO_PI_PROVIDER_ID, (input) => createLmStudioPiProvider(input)],
|
|
381542
|
+
[
|
|
381543
|
+
OPENAI_COMPATIBLE_PI_PROVIDER_ID,
|
|
381544
|
+
(input) => createOpenAICompatiblePiProvider(input)
|
|
381545
|
+
]
|
|
381444
381546
|
]);
|
|
381445
381547
|
});
|
|
381446
381548
|
|
|
@@ -381674,7 +381776,10 @@ async function resolvePiModelForAgent(modelHandle, modelSettings = {}, options3
|
|
|
381674
381776
|
}
|
|
381675
381777
|
const fallbackModelId = !registeredProvider && spec?.piProvider ? fallbackCatalogModelId(spec.piProvider, modelId) : undefined;
|
|
381676
381778
|
const { model: publishedModel, auth: authResult } = await modelsRuntime.resolveTurn(runtimeProviderId, modelId, fallbackModelId);
|
|
381677
|
-
connection = {
|
|
381779
|
+
connection = {
|
|
381780
|
+
...connection,
|
|
381781
|
+
apiKey: authResult?.auth.apiKey === LOCAL_PROVIDER_NO_API_KEY ? undefined : authResult?.auth.apiKey
|
|
381782
|
+
};
|
|
381678
381783
|
if (authResult?.auth.baseUrl)
|
|
381679
381784
|
baseURL = authResult.auth.baseUrl;
|
|
381680
381785
|
if (authResult?.auth.headers) {
|
|
@@ -426741,6 +426846,9 @@ function isNullableString4(value) {
|
|
|
426741
426846
|
function isBoolean3(value) {
|
|
426742
426847
|
return value === true || value === false;
|
|
426743
426848
|
}
|
|
426849
|
+
function isStringArray5(value) {
|
|
426850
|
+
return Array.isArray(value) && value.every(isString3);
|
|
426851
|
+
}
|
|
426744
426852
|
function isDefaultPermissionMode2(value) {
|
|
426745
426853
|
return value === "standard" || value === "acceptEdits" || value === "unrestricted" || value === "default" || value === "bypassPermissions" || value === "fullAccess";
|
|
426746
426854
|
}
|
|
@@ -426757,6 +426865,7 @@ var init_account_config4 = __esm(() => {
|
|
|
426757
426865
|
"transcribe_voice",
|
|
426758
426866
|
"show_completed_reaction",
|
|
426759
426867
|
"listen_mode",
|
|
426868
|
+
"mention_only_channels",
|
|
426760
426869
|
"allow_bots"
|
|
426761
426870
|
]);
|
|
426762
426871
|
slackAccountConfigAdapter = {
|
|
@@ -426766,7 +426875,7 @@ var init_account_config4 = __esm(() => {
|
|
|
426766
426875
|
return false;
|
|
426767
426876
|
}
|
|
426768
426877
|
}
|
|
426769
|
-
return (config3.bot_token === undefined || isString3(config3.bot_token)) && (config3.app_token === undefined || isString3(config3.app_token)) && (config3.mode === undefined || config3.mode === "socket") && (config3.agent_id === undefined || isNullableString4(config3.agent_id)) && (config3.default_permission_mode === undefined || isDefaultPermissionMode2(config3.default_permission_mode)) && (config3.transcribe_voice === undefined || isBoolean3(config3.transcribe_voice)) && (config3.show_completed_reaction === undefined || isBoolean3(config3.show_completed_reaction)) && (config3.listen_mode === undefined || isBoolean3(config3.listen_mode)) && isValidSlackAllowBotsConfigValue(config3.allow_bots);
|
|
426878
|
+
return (config3.bot_token === undefined || isString3(config3.bot_token)) && (config3.app_token === undefined || isString3(config3.app_token)) && (config3.mode === undefined || config3.mode === "socket") && (config3.agent_id === undefined || isNullableString4(config3.agent_id)) && (config3.default_permission_mode === undefined || isDefaultPermissionMode2(config3.default_permission_mode)) && (config3.transcribe_voice === undefined || isBoolean3(config3.transcribe_voice)) && (config3.show_completed_reaction === undefined || isBoolean3(config3.show_completed_reaction)) && (config3.listen_mode === undefined || isBoolean3(config3.listen_mode)) && (config3.mention_only_channels === undefined || isStringArray5(config3.mention_only_channels)) && isValidSlackAllowBotsConfigValue(config3.allow_bots);
|
|
426770
426879
|
},
|
|
426771
426880
|
toAccountPatch(config3) {
|
|
426772
426881
|
return {
|
|
@@ -426777,6 +426886,7 @@ var init_account_config4 = __esm(() => {
|
|
|
426777
426886
|
defaultPermissionMode: isDefaultPermissionMode2(config3.default_permission_mode) ? migratePermissionMode(config3.default_permission_mode) : undefined,
|
|
426778
426887
|
transcribeVoice: isBoolean3(config3.transcribe_voice) ? config3.transcribe_voice : undefined,
|
|
426779
426888
|
listenMode: isBoolean3(config3.listen_mode) ? config3.listen_mode : undefined,
|
|
426889
|
+
mentionOnlyChannels: isStringArray5(config3.mention_only_channels) ? [...config3.mention_only_channels] : undefined,
|
|
426780
426890
|
allowBots: config3.allow_bots !== undefined && isValidSlackAllowBotsConfigValue(config3.allow_bots) ? normalizeSlackAllowBotsMode(config3.allow_bots) : undefined
|
|
426781
426891
|
};
|
|
426782
426892
|
},
|
|
@@ -426789,6 +426899,7 @@ var init_account_config4 = __esm(() => {
|
|
|
426789
426899
|
default_permission_mode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
426790
426900
|
transcribe_voice: account.transcribeVoice === true,
|
|
426791
426901
|
listen_mode: account.listenMode === true,
|
|
426902
|
+
mention_only_channels: [...account.mentionOnlyChannels ?? []],
|
|
426792
426903
|
allow_bots: account.allowBots ?? false
|
|
426793
426904
|
};
|
|
426794
426905
|
},
|
|
@@ -426801,6 +426912,7 @@ var init_account_config4 = __esm(() => {
|
|
|
426801
426912
|
default_permission_mode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
426802
426913
|
transcribe_voice: account.transcribeVoice === true,
|
|
426803
426914
|
listen_mode: account.listenMode === true,
|
|
426915
|
+
mention_only_channels: [...account.mentionOnlyChannels ?? []],
|
|
426804
426916
|
allow_bots: account.allowBots ?? false
|
|
426805
426917
|
};
|
|
426806
426918
|
},
|
|
@@ -426890,7 +427002,7 @@ function isNullableString5(value) {
|
|
|
426890
427002
|
function isBoolean5(value) {
|
|
426891
427003
|
return typeof value === "boolean";
|
|
426892
427004
|
}
|
|
426893
|
-
function
|
|
427005
|
+
function isStringArray6(value) {
|
|
426894
427006
|
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
426895
427007
|
}
|
|
426896
427008
|
function isGroupMode3(value) {
|
|
@@ -426936,22 +427048,22 @@ var init_account_config6 = __esm(() => {
|
|
|
426936
427048
|
return false;
|
|
426937
427049
|
}
|
|
426938
427050
|
}
|
|
426939
|
-
return (config3.agent_id === undefined || isNullableString5(config3.agent_id)) && (config3.self_chat_mode === undefined || isBoolean5(config3.self_chat_mode)) && (config3.group_mode === undefined || isGroupMode3(config3.group_mode)) && (config3.allowed_groups === undefined ||
|
|
427051
|
+
return (config3.agent_id === undefined || isNullableString5(config3.agent_id)) && (config3.self_chat_mode === undefined || isBoolean5(config3.self_chat_mode)) && (config3.group_mode === undefined || isGroupMode3(config3.group_mode)) && (config3.allowed_groups === undefined || isStringArray6(config3.allowed_groups)) && (config3.mention_patterns === undefined || isStringArray6(config3.mention_patterns)) && (config3.transcribe_voice === undefined || isBoolean5(config3.transcribe_voice)) && (config3.download_media === undefined || isBoolean5(config3.download_media)) && (config3.media_max_bytes === undefined || isPositiveNumber2(config3.media_max_bytes)) && (config3.attachment_filter === undefined || isBoolean5(config3.attachment_filter)) && (config3.attachment_mime_types === undefined || isStringArray6(config3.attachment_mime_types)) && (config3.attachment_allowed_recipients === undefined || isStringArray6(config3.attachment_allowed_recipients)) && (config3.attachment_allowed_paths === undefined || isStringArray6(config3.attachment_allowed_paths)) && (config3.attachment_path_recursive === undefined || isBoolean5(config3.attachment_path_recursive)) && (config3.inbound_debounce_ms === undefined || isValidInboundDebounceMs(config3.inbound_debounce_ms)) && (config3.waiting_behavior === undefined || isWaitingBehavior(config3.waiting_behavior)) && (config3.message_prefix === undefined || isString5(config3.message_prefix));
|
|
426940
427052
|
},
|
|
426941
427053
|
toAccountPatch(config3) {
|
|
426942
427054
|
return {
|
|
426943
427055
|
agentId: isNullableString5(config3.agent_id) ? config3.agent_id : undefined,
|
|
426944
427056
|
selfChatMode: isBoolean5(config3.self_chat_mode) ? config3.self_chat_mode : undefined,
|
|
426945
427057
|
groupMode: isGroupMode3(config3.group_mode) ? config3.group_mode : undefined,
|
|
426946
|
-
allowedGroups:
|
|
426947
|
-
mentionPatterns:
|
|
427058
|
+
allowedGroups: isStringArray6(config3.allowed_groups) ? [...config3.allowed_groups] : undefined,
|
|
427059
|
+
mentionPatterns: isStringArray6(config3.mention_patterns) ? [...config3.mention_patterns] : undefined,
|
|
426948
427060
|
transcribeVoice: isBoolean5(config3.transcribe_voice) ? config3.transcribe_voice : undefined,
|
|
426949
427061
|
downloadMedia: isBoolean5(config3.download_media) ? config3.download_media : undefined,
|
|
426950
427062
|
mediaMaxBytes: isPositiveNumber2(config3.media_max_bytes) ? config3.media_max_bytes : undefined,
|
|
426951
427063
|
attachmentFilter: isBoolean5(config3.attachment_filter) ? config3.attachment_filter : undefined,
|
|
426952
|
-
attachmentMimeTypes:
|
|
426953
|
-
attachmentAllowedRecipients:
|
|
426954
|
-
attachmentAllowedPaths:
|
|
427064
|
+
attachmentMimeTypes: isStringArray6(config3.attachment_mime_types) ? [...config3.attachment_mime_types] : undefined,
|
|
427065
|
+
attachmentAllowedRecipients: isStringArray6(config3.attachment_allowed_recipients) ? [...config3.attachment_allowed_recipients] : undefined,
|
|
427066
|
+
attachmentAllowedPaths: isStringArray6(config3.attachment_allowed_paths) ? [...config3.attachment_allowed_paths] : undefined,
|
|
426955
427067
|
attachmentPathRecursive: isBoolean5(config3.attachment_path_recursive) ? config3.attachment_path_recursive : undefined,
|
|
426956
427068
|
inboundDebounceMs: isValidInboundDebounceMs(config3.inbound_debounce_ms) ? Math.trunc(Math.min(config3.inbound_debounce_ms, 1e4)) : undefined,
|
|
426957
427069
|
waitingBehavior: isWaitingBehavior(config3.waiting_behavior) ? config3.waiting_behavior : undefined,
|
|
@@ -427307,6 +427419,7 @@ function createAccountFromPatch(channelId, accountId, patch2) {
|
|
|
427307
427419
|
defaultPermissionMode: normalizedPatch.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
427308
427420
|
transcribeVoice: normalizedPatch.transcribeVoice === true,
|
|
427309
427421
|
listenMode: normalizedPatch.listenMode === true,
|
|
427422
|
+
mentionOnlyChannels: [...normalizedPatch.mentionOnlyChannels ?? []],
|
|
427310
427423
|
allowBots: normalizedPatch.allowBots ?? false,
|
|
427311
427424
|
dmPolicy: normalizedPatch.dmPolicy ?? "open",
|
|
427312
427425
|
allowedUsers: normalizedPatch.allowedUsers ?? [],
|
|
@@ -427423,6 +427536,9 @@ function mergeAccountPatch(existing, patch2) {
|
|
|
427423
427536
|
defaultPermissionMode: normalizedPatch.defaultPermissionMode ?? existing.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
427424
427537
|
transcribeVoice: normalizedPatch.transcribeVoice ?? existing.transcribeVoice ?? false,
|
|
427425
427538
|
listenMode: normalizedPatch.listenMode ?? existing.listenMode ?? false,
|
|
427539
|
+
mentionOnlyChannels: [
|
|
427540
|
+
...normalizedPatch.mentionOnlyChannels ?? existing.mentionOnlyChannels ?? []
|
|
427541
|
+
],
|
|
427426
427542
|
allowBots: normalizedPatch.allowBots ?? existing.allowBots ?? false,
|
|
427427
427543
|
dmPolicy: normalizedPatch.dmPolicy ?? existing.dmPolicy,
|
|
427428
427544
|
allowedUsers: normalizedPatch.allowedUsers ?? existing.allowedUsers,
|
|
@@ -427616,6 +427732,7 @@ function toAccountSnapshot(account) {
|
|
|
427616
427732
|
defaultPermissionMode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
427617
427733
|
transcribeVoice: account.transcribeVoice === true,
|
|
427618
427734
|
listenMode: account.listenMode === true,
|
|
427735
|
+
mentionOnlyChannels: [...account.mentionOnlyChannels ?? []],
|
|
427619
427736
|
allowBots: account.allowBots ?? false,
|
|
427620
427737
|
createdAt: account.createdAt,
|
|
427621
427738
|
updatedAt: account.updatedAt
|
|
@@ -427776,6 +427893,7 @@ function getChannelConfigSnapshot(channelId, accountId) {
|
|
|
427776
427893
|
defaultPermissionMode: account.defaultPermissionMode ?? DEFAULT_SLACK_PERMISSION_MODE,
|
|
427777
427894
|
transcribeVoice: account.transcribeVoice === true,
|
|
427778
427895
|
listenMode: account.listenMode === true,
|
|
427896
|
+
mentionOnlyChannels: [...account.mentionOnlyChannels ?? []],
|
|
427779
427897
|
allowBots: account.allowBots ?? false
|
|
427780
427898
|
};
|
|
427781
427899
|
}
|
|
@@ -428299,6 +428417,7 @@ async function setChannelConfigLive(channelId, patch2, accountId) {
|
|
|
428299
428417
|
threadPolicyByChannel: normalizedPatch.threadPolicyByChannel,
|
|
428300
428418
|
acknowledgeMessageReaction: normalizedPatch.acknowledgeMessageReaction,
|
|
428301
428419
|
listenMode: normalizedPatch.listenMode,
|
|
428420
|
+
mentionOnlyChannels: normalizedPatch.mentionOnlyChannels,
|
|
428302
428421
|
allowBots: normalizedPatch.allowBots,
|
|
428303
428422
|
removeStaleRoutes: normalizedPatch.removeStaleRoutes,
|
|
428304
428423
|
inboundDebounceMs: normalizedPatch.inboundDebounceMs,
|
|
@@ -428336,6 +428455,7 @@ async function setChannelConfigLive(channelId, patch2, accountId) {
|
|
|
428336
428455
|
threadPolicyByChannel: normalizedPatch.threadPolicyByChannel,
|
|
428337
428456
|
acknowledgeMessageReaction: normalizedPatch.acknowledgeMessageReaction,
|
|
428338
428457
|
listenMode: normalizedPatch.listenMode,
|
|
428458
|
+
mentionOnlyChannels: normalizedPatch.mentionOnlyChannels,
|
|
428339
428459
|
allowBots: normalizedPatch.allowBots,
|
|
428340
428460
|
removeStaleRoutes: normalizedPatch.removeStaleRoutes,
|
|
428341
428461
|
inboundDebounceMs: normalizedPatch.inboundDebounceMs,
|
|
@@ -429992,6 +430112,9 @@ function isConnectOAuthProvider(provider) {
|
|
|
429992
430112
|
function isConnectBedrockProvider(provider) {
|
|
429993
430113
|
return provider.byokProvider.providerType === "bedrock" || provider.byokProvider.providerType === "amazon-bedrock";
|
|
429994
430114
|
}
|
|
430115
|
+
function isConnectBaseURLRequired(provider) {
|
|
430116
|
+
return provider.byokProvider.fields?.some((field) => field.key === "baseUrl" && field.required !== false) === true;
|
|
430117
|
+
}
|
|
429995
430118
|
function isConnectApiKeyProvider(provider) {
|
|
429996
430119
|
return !isConnectOAuthProvider(provider) && !isConnectBedrockProvider(provider);
|
|
429997
430120
|
}
|
|
@@ -430049,6 +430172,7 @@ function formatUsage() {
|
|
|
430049
430172
|
" letta connect codex --method device-code",
|
|
430050
430173
|
" letta connect anthropic <api_key>",
|
|
430051
430174
|
" letta connect openai --api-key <api_key>",
|
|
430175
|
+
" letta connect openai-compatible --base-url http://localhost:8000/v1 [--api-key <api_key>]",
|
|
430052
430176
|
" letta connect ollama --base-url http://192.168.1.50:11434/v1",
|
|
430053
430177
|
" letta connect lmstudio --base-url http://127.0.0.1:1234/v1 --timeout 600s",
|
|
430054
430178
|
" letta connect llama-cpp --base-url http://localhost:8080/v1",
|
|
@@ -430262,6 +430386,10 @@ Provider '${providerName}' saved.`);
|
|
|
430262
430386
|
io.stderr(getErrorMessage2(error54));
|
|
430263
430387
|
return 1;
|
|
430264
430388
|
}
|
|
430389
|
+
if (isConnectBaseURLRequired(provider) && !connectionOptions.baseURL?.trim()) {
|
|
430390
|
+
io.stderr(`Missing base URL for ${provider.canonical}. Pass --base-url <url>.`);
|
|
430391
|
+
return 1;
|
|
430392
|
+
}
|
|
430265
430393
|
apiKey ||= defaultConnectApiKey(provider) ?? "";
|
|
430266
430394
|
if (!apiKey && isConnectZaiBaseProvider(provider)) {
|
|
430267
430395
|
io.stdout(`Do you have a Z.ai Coding plan?
|
|
@@ -438839,6 +438967,100 @@ var init_cron = __esm(async () => {
|
|
|
438839
438967
|
await init_scheduler();
|
|
438840
438968
|
});
|
|
438841
438969
|
|
|
438970
|
+
// src/backend/api/environments.ts
|
|
438971
|
+
var exports_environments2 = {};
|
|
438972
|
+
__export(exports_environments2, {
|
|
438973
|
+
sendEnvironmentMessage: () => sendEnvironmentMessage,
|
|
438974
|
+
resolveEnvironmentConnectionId: () => resolveEnvironmentConnectionId,
|
|
438975
|
+
resolveAgentSandboxConnectionId: () => resolveAgentSandboxConnectionId,
|
|
438976
|
+
listEnvironments: () => listEnvironments,
|
|
438977
|
+
isEnvironmentOnline: () => isEnvironmentOnline,
|
|
438978
|
+
getEnvironmentConnection: () => getEnvironmentConnection,
|
|
438979
|
+
describeEnvironment: () => describeEnvironment,
|
|
438980
|
+
createAgentSandbox: () => createAgentSandbox
|
|
438981
|
+
});
|
|
438982
|
+
async function listEnvironments(options3 = {}) {
|
|
438983
|
+
return apiRequest("GET", "/v1/environments", undefined, {
|
|
438984
|
+
query: {
|
|
438985
|
+
limit: options3.limit,
|
|
438986
|
+
after: options3.after,
|
|
438987
|
+
onlineOnly: options3.onlineOnly
|
|
438988
|
+
}
|
|
438989
|
+
});
|
|
438990
|
+
}
|
|
438991
|
+
async function sendEnvironmentMessage(connectionId, body3) {
|
|
438992
|
+
return apiRequest("POST", `/v1/environments/${encodeURIComponent(connectionId)}/messages`, body3);
|
|
438993
|
+
}
|
|
438994
|
+
async function getEnvironmentConnection(deviceId) {
|
|
438995
|
+
return apiRequest("GET", `/v1/environments/${encodeURIComponent(deviceId)}`);
|
|
438996
|
+
}
|
|
438997
|
+
async function createAgentSandbox(agentId) {
|
|
438998
|
+
return apiRequest("POST", `/v1/agents/${encodeURIComponent(agentId)}/sandboxes`, {});
|
|
438999
|
+
}
|
|
439000
|
+
function isEnvironmentOnline(environment2) {
|
|
439001
|
+
return typeof environment2.connectionId === "string" && environment2.connectionId.length > 0 && typeof environment2.lastHeartbeat === "number" && Date.now() - environment2.lastHeartbeat < 120000;
|
|
439002
|
+
}
|
|
439003
|
+
function describeEnvironment(environment2) {
|
|
439004
|
+
const status = isEnvironmentOnline(environment2) ? "online" : "offline";
|
|
439005
|
+
return `${environment2.connectionName} (${environment2.deviceId}, ${status})`;
|
|
439006
|
+
}
|
|
439007
|
+
async function resolveEnvironmentConnectionId(selector) {
|
|
439008
|
+
const trimmed = selector.trim();
|
|
439009
|
+
if (!trimmed) {
|
|
439010
|
+
throw new Error("Environment selector must not be empty");
|
|
439011
|
+
}
|
|
439012
|
+
const response = await listEnvironments({ limit: 100 });
|
|
439013
|
+
const matches2 = response.connections.filter((environment3) => {
|
|
439014
|
+
return environment3.connectionId === trimmed || environment3.id === trimmed || environment3.deviceId === trimmed || environment3.connectionName === trimmed;
|
|
439015
|
+
});
|
|
439016
|
+
if (matches2.length === 0) {
|
|
439017
|
+
throw new Error(`Environment "${trimmed}" not found. Run \`letta environments list\` to discover available environments.`);
|
|
439018
|
+
}
|
|
439019
|
+
const onlineMatches = matches2.filter(isEnvironmentOnline);
|
|
439020
|
+
if (onlineMatches.length === 0) {
|
|
439021
|
+
throw new Error(`Environment "${trimmed}" is offline. Matched: ${matches2.map(describeEnvironment).join(", ")}`);
|
|
439022
|
+
}
|
|
439023
|
+
if (onlineMatches.length > 1) {
|
|
439024
|
+
throw new Error(`Environment "${trimmed}" is ambiguous. Matched: ${onlineMatches.map(describeEnvironment).join(", ")}`);
|
|
439025
|
+
}
|
|
439026
|
+
const environment2 = onlineMatches[0];
|
|
439027
|
+
if (!environment2) {
|
|
439028
|
+
throw new Error(`Environment "${trimmed}" is offline`);
|
|
439029
|
+
}
|
|
439030
|
+
if (!environment2.connectionId) {
|
|
439031
|
+
throw new Error(`Environment "${trimmed}" has no active connection id`);
|
|
439032
|
+
}
|
|
439033
|
+
return { connectionId: environment2.connectionId, environment: environment2 };
|
|
439034
|
+
}
|
|
439035
|
+
async function resolveAgentSandboxConnectionId(agentId, options3 = {}) {
|
|
439036
|
+
const timeoutMs = options3.timeoutMs ?? 3 * 60000;
|
|
439037
|
+
const pollIntervalMs = options3.pollIntervalMs ?? 2000;
|
|
439038
|
+
const sandbox = await createAgentSandbox(agentId);
|
|
439039
|
+
const deviceId = sandbox.deviceId || `sandbox-${agentId}`;
|
|
439040
|
+
const deadline = Date.now() + timeoutMs;
|
|
439041
|
+
let lastEnvironment = null;
|
|
439042
|
+
let lastError = null;
|
|
439043
|
+
while (Date.now() < deadline) {
|
|
439044
|
+
try {
|
|
439045
|
+
const environment2 = await getEnvironmentConnection(deviceId);
|
|
439046
|
+
lastEnvironment = environment2;
|
|
439047
|
+
if (isEnvironmentOnline(environment2) && environment2.connectionId) {
|
|
439048
|
+
return { connectionId: environment2.connectionId, environment: environment2 };
|
|
439049
|
+
}
|
|
439050
|
+
} catch (error54) {
|
|
439051
|
+
lastError = error54;
|
|
439052
|
+
}
|
|
439053
|
+
await new Promise((resolve31) => setTimeout(resolve31, pollIntervalMs));
|
|
439054
|
+
}
|
|
439055
|
+
if (lastEnvironment) {
|
|
439056
|
+
throw new Error(`Timed out waiting for cloud sandbox ${sandbox.connectionName} to come online. Last status: ${describeEnvironment(lastEnvironment)}`);
|
|
439057
|
+
}
|
|
439058
|
+
throw new Error(`Timed out waiting for cloud sandbox ${sandbox.connectionName} to register${lastError instanceof Error ? `: ${lastError.message}` : ""}`);
|
|
439059
|
+
}
|
|
439060
|
+
var init_environments2 = __esm(() => {
|
|
439061
|
+
init_request();
|
|
439062
|
+
});
|
|
439063
|
+
|
|
438842
439064
|
// src/cli/subcommands/cron-runner.ts
|
|
438843
439065
|
function isLocalAgent(agentId) {
|
|
438844
439066
|
return agentId.startsWith("agent-local-");
|
|
@@ -438881,7 +439103,7 @@ function validateTargetDevice(deviceId, environment2) {
|
|
|
438881
439103
|
if (deviceId === SYNTHETIC_CLOUD_DEVICE_ID) {
|
|
438882
439104
|
return {
|
|
438883
439105
|
ok: false,
|
|
438884
|
-
error: `"Cloud" is
|
|
439106
|
+
error: `"Cloud" is not a computer. Pass --runner cloud to run in the agent's Cloud sandbox.`
|
|
438885
439107
|
};
|
|
438886
439108
|
}
|
|
438887
439109
|
if (deviceId === SYNTHETIC_LOCAL_PLACEHOLDER_ID) {
|
|
@@ -438898,6 +439120,32 @@ function validateTargetDevice(deviceId, environment2) {
|
|
|
438898
439120
|
}
|
|
438899
439121
|
return { ok: true };
|
|
438900
439122
|
}
|
|
439123
|
+
async function resolveInferredTargetDevice(deviceId, lookupEnvironment) {
|
|
439124
|
+
if (deviceId.startsWith("sandbox-")) {
|
|
439125
|
+
return { kind: "cloud-sandbox" };
|
|
439126
|
+
}
|
|
439127
|
+
const environment2 = await lookupEnvironment();
|
|
439128
|
+
const basicValidity = validateTargetDevice(deviceId, environment2);
|
|
439129
|
+
if (!basicValidity.ok) {
|
|
439130
|
+
return {
|
|
439131
|
+
kind: "local-fallback",
|
|
439132
|
+
reason: "this computer is not connected to your Letta account"
|
|
439133
|
+
};
|
|
439134
|
+
}
|
|
439135
|
+
if (!environment2) {
|
|
439136
|
+
return {
|
|
439137
|
+
kind: "local-fallback",
|
|
439138
|
+
reason: "this computer is not connected to your Letta account"
|
|
439139
|
+
};
|
|
439140
|
+
}
|
|
439141
|
+
if (!isEnvironmentOnline(environment2)) {
|
|
439142
|
+
return {
|
|
439143
|
+
kind: "local-fallback",
|
|
439144
|
+
reason: "this computer's connection to Letta is not currently online"
|
|
439145
|
+
};
|
|
439146
|
+
}
|
|
439147
|
+
return { kind: "device" };
|
|
439148
|
+
}
|
|
438901
439149
|
function buildCloudScheduleInput(params) {
|
|
438902
439150
|
const notes = [];
|
|
438903
439151
|
let schedule;
|
|
@@ -438928,6 +439176,9 @@ function buildCloudScheduleInput(params) {
|
|
|
438928
439176
|
};
|
|
438929
439177
|
}
|
|
438930
439178
|
var CLOUD_EXECUTION_TARGET = "cloud-sandbox", SYNTHETIC_CLOUD_DEVICE_ID = "__letta_cloud__", SYNTHETIC_LOCAL_PLACEHOLDER_ID = "local", CLOUD_CRON_UTC_NOTE = "Recurring Cloud schedules currently interpret cron expressions in UTC (timezone support is tracked in LET-9815).", CLOUD_DEVICE_FALLBACK_NOTE = "If the target computer is offline when the schedule fires, execution falls back to the agent's cloud sandbox.";
|
|
439179
|
+
var init_cron_runner = __esm(() => {
|
|
439180
|
+
init_environments2();
|
|
439181
|
+
});
|
|
438931
439182
|
|
|
438932
439183
|
// src/cli/subcommands/cron-task-ref.ts
|
|
438933
439184
|
async function ensureSettingsForCloud() {
|
|
@@ -438977,103 +439228,10 @@ function printAmbiguousTaskName(name, matches2) {
|
|
|
438977
439228
|
var init_cron_task_ref = __esm(async () => {
|
|
438978
439229
|
init_schedules2();
|
|
438979
439230
|
init_backend_mode();
|
|
439231
|
+
init_cron_runner();
|
|
438980
439232
|
await init_cron();
|
|
438981
439233
|
});
|
|
438982
439234
|
|
|
438983
|
-
// src/backend/api/environments.ts
|
|
438984
|
-
var exports_environments2 = {};
|
|
438985
|
-
__export(exports_environments2, {
|
|
438986
|
-
sendEnvironmentMessage: () => sendEnvironmentMessage,
|
|
438987
|
-
resolveEnvironmentConnectionId: () => resolveEnvironmentConnectionId,
|
|
438988
|
-
resolveAgentSandboxConnectionId: () => resolveAgentSandboxConnectionId,
|
|
438989
|
-
listEnvironments: () => listEnvironments,
|
|
438990
|
-
isEnvironmentOnline: () => isEnvironmentOnline,
|
|
438991
|
-
getEnvironmentConnection: () => getEnvironmentConnection,
|
|
438992
|
-
describeEnvironment: () => describeEnvironment,
|
|
438993
|
-
createAgentSandbox: () => createAgentSandbox
|
|
438994
|
-
});
|
|
438995
|
-
async function listEnvironments(options3 = {}) {
|
|
438996
|
-
return apiRequest("GET", "/v1/environments", undefined, {
|
|
438997
|
-
query: {
|
|
438998
|
-
limit: options3.limit,
|
|
438999
|
-
after: options3.after,
|
|
439000
|
-
onlineOnly: options3.onlineOnly
|
|
439001
|
-
}
|
|
439002
|
-
});
|
|
439003
|
-
}
|
|
439004
|
-
async function sendEnvironmentMessage(connectionId, body3) {
|
|
439005
|
-
return apiRequest("POST", `/v1/environments/${encodeURIComponent(connectionId)}/messages`, body3);
|
|
439006
|
-
}
|
|
439007
|
-
async function getEnvironmentConnection(deviceId) {
|
|
439008
|
-
return apiRequest("GET", `/v1/environments/${encodeURIComponent(deviceId)}`);
|
|
439009
|
-
}
|
|
439010
|
-
async function createAgentSandbox(agentId) {
|
|
439011
|
-
return apiRequest("POST", `/v1/agents/${encodeURIComponent(agentId)}/sandboxes`, {});
|
|
439012
|
-
}
|
|
439013
|
-
function isEnvironmentOnline(environment2) {
|
|
439014
|
-
return typeof environment2.connectionId === "string" && environment2.connectionId.length > 0 && typeof environment2.lastHeartbeat === "number" && Date.now() - environment2.lastHeartbeat < 120000;
|
|
439015
|
-
}
|
|
439016
|
-
function describeEnvironment(environment2) {
|
|
439017
|
-
const status = isEnvironmentOnline(environment2) ? "online" : "offline";
|
|
439018
|
-
return `${environment2.connectionName} (${environment2.deviceId}, ${status})`;
|
|
439019
|
-
}
|
|
439020
|
-
async function resolveEnvironmentConnectionId(selector) {
|
|
439021
|
-
const trimmed = selector.trim();
|
|
439022
|
-
if (!trimmed) {
|
|
439023
|
-
throw new Error("Environment selector must not be empty");
|
|
439024
|
-
}
|
|
439025
|
-
const response = await listEnvironments({ limit: 100 });
|
|
439026
|
-
const matches2 = response.connections.filter((environment3) => {
|
|
439027
|
-
return environment3.connectionId === trimmed || environment3.id === trimmed || environment3.deviceId === trimmed || environment3.connectionName === trimmed;
|
|
439028
|
-
});
|
|
439029
|
-
if (matches2.length === 0) {
|
|
439030
|
-
throw new Error(`Environment "${trimmed}" not found. Run \`letta environments list\` to discover available environments.`);
|
|
439031
|
-
}
|
|
439032
|
-
const onlineMatches = matches2.filter(isEnvironmentOnline);
|
|
439033
|
-
if (onlineMatches.length === 0) {
|
|
439034
|
-
throw new Error(`Environment "${trimmed}" is offline. Matched: ${matches2.map(describeEnvironment).join(", ")}`);
|
|
439035
|
-
}
|
|
439036
|
-
if (onlineMatches.length > 1) {
|
|
439037
|
-
throw new Error(`Environment "${trimmed}" is ambiguous. Matched: ${onlineMatches.map(describeEnvironment).join(", ")}`);
|
|
439038
|
-
}
|
|
439039
|
-
const environment2 = onlineMatches[0];
|
|
439040
|
-
if (!environment2) {
|
|
439041
|
-
throw new Error(`Environment "${trimmed}" is offline`);
|
|
439042
|
-
}
|
|
439043
|
-
if (!environment2.connectionId) {
|
|
439044
|
-
throw new Error(`Environment "${trimmed}" has no active connection id`);
|
|
439045
|
-
}
|
|
439046
|
-
return { connectionId: environment2.connectionId, environment: environment2 };
|
|
439047
|
-
}
|
|
439048
|
-
async function resolveAgentSandboxConnectionId(agentId, options3 = {}) {
|
|
439049
|
-
const timeoutMs = options3.timeoutMs ?? 3 * 60000;
|
|
439050
|
-
const pollIntervalMs = options3.pollIntervalMs ?? 2000;
|
|
439051
|
-
const sandbox = await createAgentSandbox(agentId);
|
|
439052
|
-
const deviceId = sandbox.deviceId || `sandbox-${agentId}`;
|
|
439053
|
-
const deadline = Date.now() + timeoutMs;
|
|
439054
|
-
let lastEnvironment = null;
|
|
439055
|
-
let lastError = null;
|
|
439056
|
-
while (Date.now() < deadline) {
|
|
439057
|
-
try {
|
|
439058
|
-
const environment2 = await getEnvironmentConnection(deviceId);
|
|
439059
|
-
lastEnvironment = environment2;
|
|
439060
|
-
if (isEnvironmentOnline(environment2) && environment2.connectionId) {
|
|
439061
|
-
return { connectionId: environment2.connectionId, environment: environment2 };
|
|
439062
|
-
}
|
|
439063
|
-
} catch (error54) {
|
|
439064
|
-
lastError = error54;
|
|
439065
|
-
}
|
|
439066
|
-
await new Promise((resolve31) => setTimeout(resolve31, pollIntervalMs));
|
|
439067
|
-
}
|
|
439068
|
-
if (lastEnvironment) {
|
|
439069
|
-
throw new Error(`Timed out waiting for cloud sandbox ${sandbox.connectionName} to come online. Last status: ${describeEnvironment(lastEnvironment)}`);
|
|
439070
|
-
}
|
|
439071
|
-
throw new Error(`Timed out waiting for cloud sandbox ${sandbox.connectionName} to register${lastError instanceof Error ? `: ${lastError.message}` : ""}`);
|
|
439072
|
-
}
|
|
439073
|
-
var init_environments2 = __esm(() => {
|
|
439074
|
-
init_request();
|
|
439075
|
-
});
|
|
439076
|
-
|
|
439077
439235
|
// src/cli/subcommands/cron.ts
|
|
439078
439236
|
import { parseArgs as parseArgs5 } from "node:util";
|
|
439079
439237
|
function printUsage4() {
|
|
@@ -439096,18 +439254,25 @@ Add options:
|
|
|
439096
439254
|
--cron <expr> Raw 5-field cron expression
|
|
439097
439255
|
--agent <id> Agent ID (defaults to LETTA_AGENT_ID)
|
|
439098
439256
|
--conversation <id> Conversation ID (defaults to LETTA_CONVERSATION_ID or "default")
|
|
439099
|
-
--runner <runner> Where the schedule lives and fires:
|
|
439100
|
-
|
|
439101
|
-
|
|
439102
|
-
|
|
439257
|
+
--runner <runner> Where the schedule lives and fires (normally omit:
|
|
439258
|
+
the default keeps the schedule running where it was
|
|
439259
|
+
created):
|
|
439260
|
+
cloud - durable Cloud schedule (default for cloud
|
|
439261
|
+
agents on Cloud-reachable runtimes:
|
|
439262
|
+
external listeners are targeted, managed
|
|
439263
|
+
sandboxes stay untargeted). Explicit
|
|
439264
|
+
--runner cloud always uses the Cloud sandbox
|
|
439103
439265
|
local - this device's scheduler (~/.letta/crons.json);
|
|
439104
439266
|
only fires while a session runs here (default
|
|
439105
|
-
for local-backend agents / self-hosted
|
|
439106
|
-
|
|
439107
|
-
|
|
439108
|
-
|
|
439109
|
-
|
|
439110
|
-
|
|
439267
|
+
for local-backend agents / self-hosted, and
|
|
439268
|
+
the fallback when Cloud scheduling cannot
|
|
439269
|
+
reach this computer)
|
|
439270
|
+
--computer <id> (cloud runner only) Override execution with a
|
|
439271
|
+
connected external environment (deviceId from
|
|
439272
|
+
\`letta environments list\`). Falls back to the Cloud
|
|
439273
|
+
sandbox if the computer is offline at fire time.
|
|
439274
|
+
Managed sandboxes and Desktop-local connections are
|
|
439275
|
+
not currently valid Cloud schedule targets.
|
|
439111
439276
|
|
|
439112
439277
|
List/filter options:
|
|
439113
439278
|
--agent <id> Filter by agent ID
|
|
@@ -439270,13 +439435,15 @@ async function handleAdd(values2) {
|
|
|
439270
439435
|
console.error("Error: no schedule specified.");
|
|
439271
439436
|
return 1;
|
|
439272
439437
|
}
|
|
439273
|
-
|
|
439438
|
+
let targetDeviceId = values2.computer?.trim() || undefined;
|
|
439274
439439
|
const resolved = await getRunnerForAgent(values2.runner, agentId);
|
|
439275
439440
|
if ("error" in resolved) {
|
|
439276
439441
|
console.error(`Error: ${resolved.error}`);
|
|
439277
439442
|
return 1;
|
|
439278
439443
|
}
|
|
439279
|
-
|
|
439444
|
+
let runner = resolved.runner;
|
|
439445
|
+
let localFallbackNote;
|
|
439446
|
+
if (targetDeviceId && runner !== "cloud") {
|
|
439280
439447
|
console.error("Error: --computer requires the cloud runner. Run `letta cron add` on the target computer itself (with --runner local) to schedule there locally.");
|
|
439281
439448
|
return 1;
|
|
439282
439449
|
}
|
|
@@ -439286,8 +439453,17 @@ async function handleAdd(values2) {
|
|
|
439286
439453
|
console.error(`Error: ${validity.error}`);
|
|
439287
439454
|
return 1;
|
|
439288
439455
|
}
|
|
439456
|
+
} else if (runner === "cloud" && values2.runner !== "cloud") {
|
|
439457
|
+
const inferredDeviceId = getRuntimeEnvironmentDeviceId();
|
|
439458
|
+
const resolution = await resolveInferredTargetDevice(inferredDeviceId, () => lookupEnvironmentForTarget(inferredDeviceId));
|
|
439459
|
+
if (resolution.kind === "device") {
|
|
439460
|
+
targetDeviceId = inferredDeviceId;
|
|
439461
|
+
} else if (resolution.kind === "local-fallback") {
|
|
439462
|
+
runner = "local";
|
|
439463
|
+
localFallbackNote = `This schedule is local to this computer (${resolution.reason}): it only fires while a Letta session is running here. For a schedule that fires regardless, pass --runner cloud (runs in the agent's cloud sandbox) or --computer <deviceId> (runs on a connected computer, from \`letta environments list\`).`;
|
|
439464
|
+
}
|
|
439289
439465
|
}
|
|
439290
|
-
if (
|
|
439466
|
+
if (runner === "cloud") {
|
|
439291
439467
|
return handleCloudAdd({
|
|
439292
439468
|
agentId,
|
|
439293
439469
|
conversationId,
|
|
@@ -439331,8 +439507,10 @@ async function handleAdd(values2) {
|
|
|
439331
439507
|
if (note) {
|
|
439332
439508
|
output.note = note;
|
|
439333
439509
|
}
|
|
439334
|
-
|
|
439335
|
-
|
|
439510
|
+
const fallbackWarning = localFallbackNote && recurring ? `${localFallbackNote} Recurring schedules on an unregistered computer stop firing whenever no session is running — strongly consider a durable alternative.` : localFallbackNote;
|
|
439511
|
+
const warnings = [fallbackWarning, result.warning].filter(Boolean);
|
|
439512
|
+
if (warnings.length > 0) {
|
|
439513
|
+
output.warning = warnings.join(" ");
|
|
439336
439514
|
}
|
|
439337
439515
|
console.log(JSON.stringify(output, null, 2));
|
|
439338
439516
|
console.error("Created local schedule: it only fires while a Letta session is running on this device.");
|
|
@@ -439694,9 +439872,11 @@ async function runCronSubcommand(argv) {
|
|
|
439694
439872
|
}
|
|
439695
439873
|
var CRON_OPTIONS;
|
|
439696
439874
|
var init_cron2 = __esm(async () => {
|
|
439875
|
+
init_client2();
|
|
439697
439876
|
init_request();
|
|
439698
439877
|
init_schedules2();
|
|
439699
439878
|
init_backend_mode();
|
|
439879
|
+
init_cron_runner();
|
|
439700
439880
|
await __promiseAll([
|
|
439701
439881
|
init_cron(),
|
|
439702
439882
|
init_cron_task_ref()
|
|
@@ -448335,13 +448515,13 @@ var init_channel_service_validation = __esm(() => {
|
|
|
448335
448515
|
function isExperimentId(value) {
|
|
448336
448516
|
return typeof value === "string" && EXPERIMENT_IDS.has(value);
|
|
448337
448517
|
}
|
|
448338
|
-
function
|
|
448518
|
+
function isStringArray7(value) {
|
|
448339
448519
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
448340
448520
|
}
|
|
448341
448521
|
function isClientToolsetConfig(value) {
|
|
448342
448522
|
if (!isObjectRecord2(value))
|
|
448343
448523
|
return false;
|
|
448344
|
-
return (value.base === undefined || typeof value.base === "string" && TOOLSET_PREFERENCES.has(value.base)) && (value.include === undefined ||
|
|
448524
|
+
return (value.base === undefined || typeof value.base === "string" && TOOLSET_PREFERENCES.has(value.base)) && (value.include === undefined || isStringArray7(value.include));
|
|
448345
448525
|
}
|
|
448346
448526
|
function isStringRecord2(value) {
|
|
448347
448527
|
return !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((item) => typeof item === "string");
|
|
@@ -448372,7 +448552,7 @@ function isInputCommand(value) {
|
|
|
448372
448552
|
}
|
|
448373
448553
|
const payload = candidate.payload;
|
|
448374
448554
|
if (payload.kind === "create_message") {
|
|
448375
|
-
return Array.isArray(payload.messages) && (payload.image_failure_mode === undefined || payload.image_failure_mode === "strict" || payload.image_failure_mode === "drop") && (payload.client_tool_allowlist === undefined ||
|
|
448555
|
+
return Array.isArray(payload.messages) && (payload.image_failure_mode === undefined || payload.image_failure_mode === "strict" || payload.image_failure_mode === "drop") && (payload.client_tool_allowlist === undefined || isStringArray7(payload.client_tool_allowlist)) && (payload.client_toolset === undefined || isClientToolsetConfig(payload.client_toolset)) && (payload.external_tool_scope_ids === undefined || isStringArray7(payload.external_tool_scope_ids)) && (payload.exclude_interactive_tools === undefined || typeof payload.exclude_interactive_tools === "boolean");
|
|
448376
448556
|
}
|
|
448377
448557
|
if (payload.kind === "approval_response") {
|
|
448378
448558
|
return isValidApprovalResponseBody(payload);
|
|
@@ -448397,9 +448577,9 @@ function legacyEnvironmentMessageToInputCommand(value) {
|
|
|
448397
448577
|
payload: {
|
|
448398
448578
|
kind: "create_message",
|
|
448399
448579
|
messages: candidate.messages,
|
|
448400
|
-
client_tool_allowlist:
|
|
448580
|
+
client_tool_allowlist: isStringArray7(candidate.clientToolAllowlist) ? candidate.clientToolAllowlist : undefined,
|
|
448401
448581
|
client_toolset: isClientToolsetConfig(candidate.clientToolset) ? candidate.clientToolset : undefined,
|
|
448402
|
-
external_tool_scope_ids:
|
|
448582
|
+
external_tool_scope_ids: isStringArray7(candidate.externalToolScopeIds) ? candidate.externalToolScopeIds : undefined
|
|
448403
448583
|
}
|
|
448404
448584
|
};
|
|
448405
448585
|
}
|
|
@@ -448431,7 +448611,7 @@ function getInvalidInputReason(value) {
|
|
|
448431
448611
|
reason: "Protocol violation: input.payload.image_failure_mode must be strict or drop"
|
|
448432
448612
|
};
|
|
448433
448613
|
}
|
|
448434
|
-
if (payload.client_tool_allowlist !== undefined && !
|
|
448614
|
+
if (payload.client_tool_allowlist !== undefined && !isStringArray7(payload.client_tool_allowlist)) {
|
|
448435
448615
|
return {
|
|
448436
448616
|
runtime: candidate.runtime,
|
|
448437
448617
|
reason: "Protocol violation: input.payload.client_tool_allowlist must be string[]"
|
|
@@ -448449,7 +448629,7 @@ function getInvalidInputReason(value) {
|
|
|
448449
448629
|
reason: "Protocol violation: input.payload.exclude_interactive_tools must be boolean"
|
|
448450
448630
|
};
|
|
448451
448631
|
}
|
|
448452
|
-
if (payload.external_tool_scope_ids !== undefined && !
|
|
448632
|
+
if (payload.external_tool_scope_ids !== undefined && !isStringArray7(payload.external_tool_scope_ids)) {
|
|
448453
448633
|
return {
|
|
448454
448634
|
runtime: candidate.runtime,
|
|
448455
448635
|
reason: "Protocol violation: input.payload.external_tool_scope_ids must be string[]"
|
|
@@ -448811,7 +448991,7 @@ function isCreateAgentCommand(value) {
|
|
|
448811
448991
|
if (!value || typeof value !== "object")
|
|
448812
448992
|
return false;
|
|
448813
448993
|
const c = value;
|
|
448814
|
-
return c.type === "create_agent" && typeof c.request_id === "string" && (c.personality === "memo" || c.personality === "blank" || c.personality === "tutorial" || c.personality === "linus" || c.personality === "kawaii") && (c.model === undefined || typeof c.model === "string") && (c.tags === undefined ||
|
|
448994
|
+
return c.type === "create_agent" && typeof c.request_id === "string" && (c.personality === "memo" || c.personality === "blank" || c.personality === "tutorial" || c.personality === "linus" || c.personality === "kawaii") && (c.model === undefined || typeof c.model === "string") && (c.tags === undefined || isStringArray7(c.tags)) && (c.pin_global === undefined || typeof c.pin_global === "boolean");
|
|
448815
448995
|
}
|
|
448816
448996
|
function isAgentListCommand(value) {
|
|
448817
448997
|
if (!value || typeof value !== "object")
|
|
@@ -451068,6 +451248,7 @@ async function applyModelUpdateForRuntime(params) {
|
|
|
451068
451248
|
conversationId,
|
|
451069
451249
|
overrideModel: model.handle,
|
|
451070
451250
|
overrideProviderType: providerTypeFromModelSettings3(modelSettings) ?? inferProviderTypeFromRegistryHandle(model.handle) ?? null,
|
|
451251
|
+
modContext: createListenerAgentModContext(agentId),
|
|
451071
451252
|
modAdapters,
|
|
451072
451253
|
modEvents: createListenerModEvents(modAdapters)
|
|
451073
451254
|
});
|
|
@@ -451140,6 +451321,7 @@ async function applyToolsetUpdateForRuntime(params) {
|
|
|
451140
451321
|
const preparedToolContext = await prepareToolExecutionContextForScope({
|
|
451141
451322
|
agentId,
|
|
451142
451323
|
conversationId,
|
|
451324
|
+
modContext: createListenerAgentModContext(agentId),
|
|
451143
451325
|
modAdapters,
|
|
451144
451326
|
modEvents: createListenerModEvents(modAdapters)
|
|
451145
451327
|
});
|
|
@@ -452655,13 +452837,24 @@ function getLoopErrorNoticeDecision(params) {
|
|
|
452655
452837
|
apiError
|
|
452656
452838
|
};
|
|
452657
452839
|
}
|
|
452658
|
-
const formattedMessage = formatErrorDetails2(apiError ? buildStructuredFormatInput(apiError) : params.error ?? params.message, params.agentId ?? undefined, params.conversationId ?? undefined
|
|
452840
|
+
const formattedMessage = formatErrorDetails2(apiError ? buildStructuredFormatInput(apiError) : params.error ?? params.message, params.agentId ?? undefined, params.conversationId ?? undefined, {
|
|
452841
|
+
surface: params.surface,
|
|
452842
|
+
unclassifiedFallback: params.unclassifiedFallback
|
|
452843
|
+
});
|
|
452659
452844
|
return {
|
|
452660
452845
|
visibility: "transcript",
|
|
452661
452846
|
message: formattedMessage,
|
|
452662
452847
|
apiError
|
|
452663
452848
|
};
|
|
452664
452849
|
}
|
|
452850
|
+
function getTranscriptLoopErrorMessage(params) {
|
|
452851
|
+
const decision = getLoopErrorNoticeDecision({
|
|
452852
|
+
...params,
|
|
452853
|
+
surface: "plain",
|
|
452854
|
+
unclassifiedFallback: "generic"
|
|
452855
|
+
});
|
|
452856
|
+
return decision.visibility === "transcript" ? decision.message : undefined;
|
|
452857
|
+
}
|
|
452665
452858
|
function emitLoopErrorNotice(socket, runtime, params) {
|
|
452666
452859
|
const decision = getLoopErrorNoticeDecision(params);
|
|
452667
452860
|
if (decision.visibility === "debug_only") {
|
|
@@ -455231,23 +455424,27 @@ function finalizeHandledRecoveryTurn(runtime, socket, turnLease, params) {
|
|
|
455231
455424
|
}
|
|
455232
455425
|
const terminalStopReason = params.drainResult.stopReason || "error";
|
|
455233
455426
|
const runId = runtime.activeRunId;
|
|
455427
|
+
const noticeParams = {
|
|
455428
|
+
message: `Recovery continuation ended unexpectedly: ${terminalStopReason}`,
|
|
455429
|
+
agentId: params.agentId,
|
|
455430
|
+
conversationId: params.conversationId
|
|
455431
|
+
};
|
|
455234
455432
|
const transition = finishListenerTurn(runtime, turnLease, {
|
|
455235
455433
|
stopReason: terminalStopReason,
|
|
455236
455434
|
socket,
|
|
455237
455435
|
agentId: params.agentId,
|
|
455238
455436
|
conversationId: params.conversationId,
|
|
455239
|
-
turnId: params.turnId
|
|
455437
|
+
turnId: params.turnId,
|
|
455438
|
+
error: getTranscriptLoopErrorMessage(noticeParams)
|
|
455240
455439
|
});
|
|
455241
455440
|
if (!transition.finished) {
|
|
455242
455441
|
return transition;
|
|
455243
455442
|
}
|
|
455244
455443
|
emitLoopErrorNotice(socket, runtime, {
|
|
455245
|
-
|
|
455444
|
+
...noticeParams,
|
|
455246
455445
|
stopReason: terminalStopReason,
|
|
455247
455446
|
isTerminal: true,
|
|
455248
|
-
runId: runId || undefined
|
|
455249
|
-
agentId: params.agentId ?? undefined,
|
|
455250
|
-
conversationId: params.conversationId
|
|
455447
|
+
runId: runId || undefined
|
|
455251
455448
|
});
|
|
455252
455449
|
return transition;
|
|
455253
455450
|
}
|
|
@@ -455508,6 +455705,7 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
455508
455705
|
conversationId: recovered.conversationId,
|
|
455509
455706
|
workingDirectory,
|
|
455510
455707
|
permissionModeState: getOrCreateConversationPermissionModeStateRef(runtime.listener, recovered.agentId, recovered.conversationId),
|
|
455708
|
+
modContext: createListenerAgentModContext(recovered.agentId),
|
|
455511
455709
|
modAdapters,
|
|
455512
455710
|
modEvents: createListenerModEvents(modAdapters)
|
|
455513
455711
|
});
|
|
@@ -455603,13 +455801,17 @@ async function resolveRecoveredApprovalResponse(runtime, socket, response, proce
|
|
|
455603
455801
|
recovered.pendingRequestIds = new Set(recovered.approvalsByRequestId.keys());
|
|
455604
455802
|
recovered.responsesByRequestId.clear();
|
|
455605
455803
|
}
|
|
455804
|
+
const stopReason = recoveryLease.signal.aborted ? "cancelled" : "error";
|
|
455606
455805
|
finishListenerTurn(runtime, recoveryLease, {
|
|
455607
|
-
stopReason
|
|
455806
|
+
stopReason,
|
|
455608
455807
|
socket,
|
|
455609
455808
|
agentId: recovered.agentId,
|
|
455610
455809
|
conversationId: recovered.conversationId,
|
|
455611
455810
|
turnId: `batch-recovered-${requestId}`,
|
|
455612
|
-
error:
|
|
455811
|
+
error: stopReason === "error" ? getTranscriptLoopErrorMessage({
|
|
455812
|
+
error: error54,
|
|
455813
|
+
message: error54 instanceof Error ? error54.message : String(error54)
|
|
455814
|
+
}) : undefined
|
|
455613
455815
|
});
|
|
455614
455816
|
throw error54;
|
|
455615
455817
|
}
|
|
@@ -455917,6 +456119,7 @@ async function resolveStaleApprovals(runtime, socket, turnLease, deps = {}) {
|
|
|
455917
456119
|
conversationId: recoveryConversationId,
|
|
455918
456120
|
workingDirectory: recoveryWorkingDirectory,
|
|
455919
456121
|
permissionModeState: getOrCreateConversationPermissionModeStateRef(runtime.listener, runtime.agentId, runtime.conversationId),
|
|
456122
|
+
modContext: createListenerAgentModContext(runtime.agentId),
|
|
455920
456123
|
modAdapters,
|
|
455921
456124
|
modEvents: createListenerModEvents(modAdapters)
|
|
455922
456125
|
});
|
|
@@ -459107,7 +459310,7 @@ async function emitListenerTurnStart(options3) {
|
|
|
459107
459310
|
sessionId: options3.conversationId,
|
|
459108
459311
|
workingDirectory: options3.workingDirectory,
|
|
459109
459312
|
permissionMode: options3.permissionMode ?? null,
|
|
459110
|
-
agent: options3.cachedAgent ??
|
|
459313
|
+
agent: options3.cachedAgent ?? { id: options3.agentId }
|
|
459111
459314
|
});
|
|
459112
459315
|
const event2 = {
|
|
459113
459316
|
agentId: options3.agentId,
|
|
@@ -459134,7 +459337,7 @@ async function emitListenerTurnEnd(options3) {
|
|
|
459134
459337
|
sessionId: options3.conversationId,
|
|
459135
459338
|
workingDirectory: options3.workingDirectory,
|
|
459136
459339
|
permissionMode: options3.permissionMode ?? null,
|
|
459137
|
-
agent: options3.cachedAgent ??
|
|
459340
|
+
agent: options3.cachedAgent ?? { id: options3.agentId }
|
|
459138
459341
|
});
|
|
459139
459342
|
const event2 = {
|
|
459140
459343
|
agentId: options3.agentId,
|
|
@@ -460227,8 +460430,10 @@ async function prepareListenerTurn(params) {
|
|
|
460227
460430
|
inboundUserTranscriptLines = buildInboundUserTranscriptLines(currentInput);
|
|
460228
460431
|
}
|
|
460229
460432
|
const modAdapters = await ensureListenerModAdaptersForAgent(runtime.listener, agentId);
|
|
460433
|
+
const environmentDeviceId = connectionId ? runtime.listener.connections.get(connectionId)?.options.deviceId : undefined;
|
|
460230
460434
|
const preparedToolContext = await prepareToolExecutionContextForScope({
|
|
460231
460435
|
connectionId,
|
|
460436
|
+
environmentDeviceId,
|
|
460232
460437
|
agentId,
|
|
460233
460438
|
conversationId,
|
|
460234
460439
|
clientToolset: msg.clientToolset,
|
|
@@ -460239,6 +460444,7 @@ async function prepareListenerTurn(params) {
|
|
|
460239
460444
|
permissionModeState,
|
|
460240
460445
|
skillSources: runtime.skillSources,
|
|
460241
460446
|
cachedAgent,
|
|
460447
|
+
modContext: createListenerAgentModContext(agentId),
|
|
460242
460448
|
modAdapters,
|
|
460243
460449
|
modEvents: createListenerModEvents(modAdapters)
|
|
460244
460450
|
});
|
|
@@ -460359,7 +460565,8 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
460359
460565
|
if (!agentId) {
|
|
460360
460566
|
finishTurn({
|
|
460361
460567
|
stopReason: "error",
|
|
460362
|
-
conversationId
|
|
460568
|
+
conversationId,
|
|
460569
|
+
error: getTranscriptLoopErrorMessage({ message: "Missing agent ID" })
|
|
460363
460570
|
});
|
|
460364
460571
|
return;
|
|
460365
460572
|
}
|
|
@@ -460732,24 +460939,29 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
460732
460939
|
}
|
|
460733
460940
|
const errorMessage2 = errorDetail2 || `Unexpected stop reason: ${stopReason}`;
|
|
460734
460941
|
const terminalRunId = runId || runtime.activeRunId || runErrorInfo2?.run_id;
|
|
460942
|
+
const noticeParams = {
|
|
460943
|
+
message: errorMessage2,
|
|
460944
|
+
agentId,
|
|
460945
|
+
conversationId,
|
|
460946
|
+
runErrorInfo: runErrorInfo2 ?? undefined,
|
|
460947
|
+
cancelRequested: turnAbortSignal.aborted,
|
|
460948
|
+
abortSignal: turnAbortSignal
|
|
460949
|
+
};
|
|
460950
|
+
const terminalError = getTranscriptLoopErrorMessage(noticeParams);
|
|
460735
460951
|
const transition = finishTurn({
|
|
460736
460952
|
stopReason: effectiveStopReason,
|
|
460737
460953
|
agentId,
|
|
460738
|
-
conversationId
|
|
460954
|
+
conversationId,
|
|
460955
|
+
error: terminalError
|
|
460739
460956
|
});
|
|
460740
460957
|
if (!transition.finished) {
|
|
460741
460958
|
break;
|
|
460742
460959
|
}
|
|
460743
460960
|
const formattedError = emitLoopErrorNotice(socket, runtime, {
|
|
460744
|
-
|
|
460961
|
+
...noticeParams,
|
|
460745
460962
|
stopReason: effectiveStopReason,
|
|
460746
460963
|
isTerminal: true,
|
|
460747
|
-
runId: terminalRunId
|
|
460748
|
-
agentId,
|
|
460749
|
-
conversationId,
|
|
460750
|
-
runErrorInfo: runErrorInfo2 ?? undefined,
|
|
460751
|
-
cancelRequested: turnAbortSignal.aborted,
|
|
460752
|
-
abortSignal: turnAbortSignal
|
|
460964
|
+
runId: terminalRunId
|
|
460753
460965
|
});
|
|
460754
460966
|
runtime.lastTerminalLoopErrorMessage = formattedError ?? errorMessage2;
|
|
460755
460967
|
runtime.lastTerminalLoopErrorRunId = terminalRunId ?? null;
|
|
@@ -460776,10 +460988,14 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
460776
460988
|
});
|
|
460777
460989
|
if (approvalResult.kind === "error") {
|
|
460778
460990
|
const terminalRunId = runId || runtime.activeRunId;
|
|
460991
|
+
const terminalError = getTranscriptLoopErrorMessage({
|
|
460992
|
+
message: approvalResult.message
|
|
460993
|
+
});
|
|
460779
460994
|
const transition = finishTurn({
|
|
460780
460995
|
stopReason: "error",
|
|
460781
460996
|
agentId,
|
|
460782
|
-
conversationId
|
|
460997
|
+
conversationId,
|
|
460998
|
+
error: terminalError
|
|
460783
460999
|
});
|
|
460784
461000
|
if (!transition.finished) {
|
|
460785
461001
|
return;
|
|
@@ -460877,24 +461093,29 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
460877
461093
|
}
|
|
460878
461094
|
const errorMessage2 = error54 instanceof Error ? error54.message : String(error54);
|
|
460879
461095
|
const terminalRunId = runtime.activeRunId;
|
|
461096
|
+
const noticeParams = {
|
|
461097
|
+
message: errorMessage2,
|
|
461098
|
+
agentId,
|
|
461099
|
+
conversationId,
|
|
461100
|
+
error: error54,
|
|
461101
|
+
cancelRequested: turnAbortSignal.aborted,
|
|
461102
|
+
abortSignal: turnAbortSignal
|
|
461103
|
+
};
|
|
461104
|
+
const terminalError = getTranscriptLoopErrorMessage(noticeParams);
|
|
460880
461105
|
const transition = finishTurn({
|
|
460881
461106
|
stopReason: "error",
|
|
460882
461107
|
agentId: agentId || null,
|
|
460883
|
-
conversationId
|
|
461108
|
+
conversationId,
|
|
461109
|
+
error: terminalError
|
|
460884
461110
|
});
|
|
460885
461111
|
if (!transition.finished) {
|
|
460886
461112
|
return;
|
|
460887
461113
|
}
|
|
460888
461114
|
const formattedError = emitLoopErrorNotice(socket, runtime, {
|
|
460889
|
-
|
|
461115
|
+
...noticeParams,
|
|
460890
461116
|
stopReason: "error",
|
|
460891
461117
|
isTerminal: true,
|
|
460892
|
-
runId: terminalRunId
|
|
460893
|
-
agentId: agentId || undefined,
|
|
460894
|
-
conversationId,
|
|
460895
|
-
error: error54,
|
|
460896
|
-
cancelRequested: turnAbortSignal.aborted,
|
|
460897
|
-
abortSignal: turnAbortSignal
|
|
461118
|
+
runId: terminalRunId
|
|
460898
461119
|
});
|
|
460899
461120
|
runtime.lastTerminalLoopErrorMessage = formattedError ?? errorMessage2;
|
|
460900
461121
|
runtime.lastTerminalLoopErrorRunId = terminalRunId ?? null;
|
|
@@ -460914,7 +461135,8 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
|
|
|
460914
461135
|
socket,
|
|
460915
461136
|
runId: runtime.activeRunId || msgRunIds[msgRunIds.length - 1],
|
|
460916
461137
|
agentId: agentId || null,
|
|
460917
|
-
conversationId
|
|
461138
|
+
conversationId,
|
|
461139
|
+
error: turnAbortSignal.aborted ? undefined : getTranscriptLoopErrorMessage({ message: "Unexpected turn failure" })
|
|
460918
461140
|
});
|
|
460919
461141
|
}
|
|
460920
461142
|
if (runtime.activeConnectionId === connectionId) {
|
|
@@ -466115,6 +466337,7 @@ async function startConnectedListenerRuntime(runtime, transport, opts, processQu
|
|
|
466115
466337
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
466116
466338
|
return;
|
|
466117
466339
|
}
|
|
466340
|
+
installExternalToolBridge(runtime);
|
|
466118
466341
|
const shouldStartHeartbeat = options3.startHeartbeat !== false;
|
|
466119
466342
|
const cronSchedulerDisabledByEnv = process.env.LETTA_DISABLE_CRON_SCHEDULER === "1";
|
|
466120
466343
|
const shouldStartCronScheduler = options3.startCronScheduler !== false && !cronSchedulerDisabledByEnv;
|
|
@@ -469394,6 +469617,9 @@ async function resolveListenerStartupMode(channelNames, channelsRequested = chan
|
|
|
469394
469617
|
if (channelsRequested) {
|
|
469395
469618
|
return { kind: "local-channels", serverUrl, backend: "self-hosted" };
|
|
469396
469619
|
}
|
|
469620
|
+
if (process.env.IGNORE_SELF_HOSTED_LISTENER_ERROR === "1") {
|
|
469621
|
+
return { kind: "remote", serverUrl };
|
|
469622
|
+
}
|
|
469397
469623
|
return { kind: "unsupported-self-hosted", serverUrl };
|
|
469398
469624
|
}
|
|
469399
469625
|
function getScopedChannelRestoreAgentScope() {
|
|
@@ -469542,7 +469768,7 @@ async function runListenSubcommand(argv) {
|
|
|
469542
469768
|
try {
|
|
469543
469769
|
const deviceId = settingsManager.getOrCreateDeviceId();
|
|
469544
469770
|
const startupMode = await resolveListenerStartupMode(channelNames, channelNames.length > 0 || restoreEnabledChannels);
|
|
469545
|
-
if (startupMode.kind === "unsupported-self-hosted"
|
|
469771
|
+
if (startupMode.kind === "unsupported-self-hosted") {
|
|
469546
469772
|
console.error(`Self-hosted listener registration is not available for ${startupMode.serverUrl}.`);
|
|
469547
469773
|
console.error("Start with --channels to run local channel adapters, or unset LETTA_BASE_URL to use Letta API remote environments.");
|
|
469548
469774
|
await flushListenerTelemetryEnd("listener_self_hosted_no_channels");
|
|
@@ -491886,7 +492112,7 @@ var init_mcp_client = __esm(() => {
|
|
|
491886
492112
|
init_streamableHttp();
|
|
491887
492113
|
DEFAULT_CLIENT_INFO = {
|
|
491888
492114
|
name: "letta-code",
|
|
491889
|
-
version: "0.30.
|
|
492115
|
+
version: "0.30.6"
|
|
491890
492116
|
};
|
|
491891
492117
|
});
|
|
491892
492118
|
|
|
@@ -523799,6 +524025,7 @@ function formatConnectUsage() {
|
|
|
523799
524025
|
" /connect codex",
|
|
523800
524026
|
" /connect anthropic <api_key>",
|
|
523801
524027
|
" /connect openai <api_key>",
|
|
524028
|
+
" /connect openai-compatible --base-url http://localhost:8000/v1 [--api-key <api_key>]",
|
|
523802
524029
|
" /connect lmstudio --base-url http://127.0.0.1:1234/v1 --timeout 600s",
|
|
523803
524030
|
" /connect bedrock iam --access-key <id> --secret-key <key> --region <region>",
|
|
523804
524031
|
" /connect bedrock profile --profile <name> --region <region>"
|
|
@@ -523876,7 +524103,7 @@ function formatApiKeyUsage(provider) {
|
|
|
523876
524103
|
`Usage: /connect ${provider.canonical} [api_key]`,
|
|
523877
524104
|
"",
|
|
523878
524105
|
`Connect to ${provider.byokProvider.displayName}. API key is optional for this local provider.`,
|
|
523879
|
-
"Optional: --base-url <url> --timeout <ms|duration|false>"
|
|
524106
|
+
isConnectBaseURLRequired(provider) ? "Required: --base-url <url>. Optional: --timeout <ms|duration|false>" : "Optional: --base-url <url> --timeout <ms|duration|false>"
|
|
523880
524107
|
].join(`
|
|
523881
524108
|
`);
|
|
523882
524109
|
}
|
|
@@ -524172,6 +524399,12 @@ Usage: /connect chatgpt [--name <provider-name>]`, false);
|
|
|
524172
524399
|
if (parsed.error) {
|
|
524173
524400
|
addCommandResult(ctx.buffersRef, ctx.refreshDerived, msg, `${parsed.error}
|
|
524174
524401
|
|
|
524402
|
+
${formatApiKeyUsage(provider)}`, false);
|
|
524403
|
+
return;
|
|
524404
|
+
}
|
|
524405
|
+
if (isConnectBaseURLRequired(provider) && !parsed.baseURL?.trim()) {
|
|
524406
|
+
addCommandResult(ctx.buffersRef, ctx.refreshDerived, msg, `Missing required field: --base-url <url>.
|
|
524407
|
+
|
|
524175
524408
|
${formatApiKeyUsage(provider)}`, false);
|
|
524176
524409
|
return;
|
|
524177
524410
|
}
|
|
@@ -555619,9 +555852,8 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
555619
555852
|
const command = positionals[2];
|
|
555620
555853
|
if (values2.help) {
|
|
555621
555854
|
printHelp();
|
|
555622
|
-
|
|
555623
|
-
|
|
555624
|
-
await new Promise((resolve40) => setTimeout(resolve40, helpDelayMs));
|
|
555855
|
+
if (process.env.LETTA_TEST_WAIT_FOR_STARTUP_AUTO_UPDATE === "1") {
|
|
555856
|
+
await autoUpdatePromise;
|
|
555625
555857
|
}
|
|
555626
555858
|
process.exit(0);
|
|
555627
555859
|
}
|
|
@@ -558987,4 +559219,4 @@ function registerBunOAuthFlows() {
|
|
|
558987
559219
|
registerBunOAuthFlows();
|
|
558988
559220
|
await init_src5().then(() => exports_src2);
|
|
558989
559221
|
|
|
558990
|
-
//# debugId=
|
|
559222
|
+
//# debugId=AD09C8202E7874BF64756E2164756E21
|