@letta-ai/letta-code 0.31.9 → 0.31.10
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/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/types/backend/api/client.d.ts +0 -5
- package/dist/types/backend/api/client.d.ts.map +1 -1
- package/dist/types/backend/api/server-url.d.ts +11 -0
- package/dist/types/backend/api/server-url.d.ts.map +1 -0
- package/dist/types/backend/backend.d.ts +7 -1
- package/dist/types/backend/backend.d.ts.map +1 -1
- package/dist/types/backend/dev/fake-headless-backend.d.ts +3 -11
- package/dist/types/backend/dev/fake-headless-backend.d.ts.map +1 -1
- package/dist/types/backend/dev/headless-backend.d.ts +1 -1
- package/dist/types/backend/dev/headless-backend.d.ts.map +1 -1
- package/dist/types/backend/local/local-backend.d.ts.map +1 -1
- package/dist/types/tools/impl/task.d.ts.map +1 -1
- package/dist/types/tools/memory-tool-assets.d.ts.map +1 -1
- package/dist/types/tools/task-tool-assets.d.ts +14 -0
- package/dist/types/tools/task-tool-assets.d.ts.map +1 -0
- package/letta.js +487 -407
- package/package.json +1 -1
- package/scripts/source-file-size-baseline.json +1 -2
package/letta.js
CHANGED
|
@@ -3757,29 +3757,6 @@ var init_oauth = __esm(() => {
|
|
|
3757
3757
|
};
|
|
3758
3758
|
});
|
|
3759
3759
|
|
|
3760
|
-
// src/auth/oauth-refresh.ts
|
|
3761
|
-
async function refreshAccessTokenSingleFlight(refreshToken2, deviceId, deviceName, refresh = refreshAccessToken2) {
|
|
3762
|
-
const refreshKey = `${refreshToken2}\x00${deviceId}`;
|
|
3763
|
-
const existing = inFlightRefreshes.get(refreshKey);
|
|
3764
|
-
if (existing) {
|
|
3765
|
-
return await existing;
|
|
3766
|
-
}
|
|
3767
|
-
const pending = refresh(refreshToken2, deviceId, deviceName);
|
|
3768
|
-
inFlightRefreshes.set(refreshKey, pending);
|
|
3769
|
-
try {
|
|
3770
|
-
return await pending;
|
|
3771
|
-
} finally {
|
|
3772
|
-
if (inFlightRefreshes.get(refreshKey) === pending) {
|
|
3773
|
-
inFlightRefreshes.delete(refreshKey);
|
|
3774
|
-
}
|
|
3775
|
-
}
|
|
3776
|
-
}
|
|
3777
|
-
var inFlightRefreshes;
|
|
3778
|
-
var init_oauth_refresh = __esm(() => {
|
|
3779
|
-
init_oauth();
|
|
3780
|
-
inFlightRefreshes = new Map;
|
|
3781
|
-
});
|
|
3782
|
-
|
|
3783
3760
|
// src/agent/agent-id.ts
|
|
3784
3761
|
function isLocalAgentId(agentId) {
|
|
3785
3762
|
return agentId.startsWith("agent-local-");
|
|
@@ -5418,98 +5395,12 @@ var init_settings_manager = __esm(() => {
|
|
|
5418
5395
|
settingsManager = globalThis.__lettaSettingsManager;
|
|
5419
5396
|
});
|
|
5420
5397
|
|
|
5421
|
-
// src/utils/timing.ts
|
|
5422
|
-
function isTimingsEnabled() {
|
|
5423
|
-
const val = process.env.LETTA_DEBUG_TIMINGS;
|
|
5424
|
-
return val === "1" || val === "true";
|
|
5425
|
-
}
|
|
5426
|
-
function formatDuration(ms) {
|
|
5427
|
-
if (ms < 1000)
|
|
5428
|
-
return `${Math.round(ms)}ms`;
|
|
5429
|
-
return `${(ms / 1000).toFixed(2)}s`;
|
|
5430
|
-
}
|
|
5431
|
-
function formatTimestamp(date) {
|
|
5432
|
-
return date.toISOString().slice(11, 23);
|
|
5433
|
-
}
|
|
5434
|
-
function logTiming(message) {
|
|
5435
|
-
if (isTimingsEnabled()) {
|
|
5436
|
-
console.error(`[timing] ${message}`);
|
|
5437
|
-
}
|
|
5438
|
-
}
|
|
5439
|
-
function markMilestone(name) {
|
|
5440
|
-
const now = performance.now();
|
|
5441
|
-
milestones.set(name, now);
|
|
5442
|
-
if (firstMilestoneTime === null) {
|
|
5443
|
-
firstMilestoneTime = now;
|
|
5444
|
-
}
|
|
5445
|
-
if (isTimingsEnabled()) {
|
|
5446
|
-
const relative = now - firstMilestoneTime;
|
|
5447
|
-
console.error(`[timing] MILESTONE ${name} at +${formatDuration(relative)} (${formatTimestamp(new Date)})`);
|
|
5448
|
-
}
|
|
5449
|
-
}
|
|
5450
|
-
function measureSinceMilestone(label, fromMilestone) {
|
|
5451
|
-
if (!isTimingsEnabled())
|
|
5452
|
-
return;
|
|
5453
|
-
const startTime = milestones.get(fromMilestone);
|
|
5454
|
-
if (startTime === undefined) {
|
|
5455
|
-
console.error(`[timing] WARNING: milestone "${fromMilestone}" not found for measurement "${label}"`);
|
|
5456
|
-
return;
|
|
5457
|
-
}
|
|
5458
|
-
const duration = performance.now() - startTime;
|
|
5459
|
-
console.error(`[timing] ${label}: ${formatDuration(duration)}`);
|
|
5460
|
-
}
|
|
5461
|
-
function reportAllMilestones() {
|
|
5462
|
-
if (!isTimingsEnabled() || milestones.size === 0)
|
|
5463
|
-
return;
|
|
5464
|
-
const first = firstMilestoneTime ?? 0;
|
|
5465
|
-
console.error(`[timing] ======== MILESTONE SUMMARY ========`);
|
|
5466
|
-
const sorted = [...milestones.entries()].sort((a, b) => a[1] - b[1]);
|
|
5467
|
-
let prevTime = first;
|
|
5468
|
-
for (const [name, time] of sorted) {
|
|
5469
|
-
const relativeToStart = time - first;
|
|
5470
|
-
const delta = time - prevTime;
|
|
5471
|
-
const deltaStr = prevTime === first ? "" : ` (+${formatDuration(delta)})`;
|
|
5472
|
-
console.error(`[timing] +${formatDuration(relativeToStart).padStart(8)} ${name}${deltaStr}`);
|
|
5473
|
-
prevTime = time;
|
|
5474
|
-
}
|
|
5475
|
-
console.error(`[timing] =====================================`);
|
|
5476
|
-
}
|
|
5477
|
-
function createTimingFetch(baseFetch) {
|
|
5478
|
-
return async (input, init) => {
|
|
5479
|
-
const start = performance.now();
|
|
5480
|
-
const startTime = formatTimestamp(new Date);
|
|
5481
|
-
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
5482
|
-
const method = init?.method || "GET";
|
|
5483
|
-
let path2;
|
|
5484
|
-
try {
|
|
5485
|
-
path2 = new URL(url).pathname;
|
|
5486
|
-
} catch {
|
|
5487
|
-
path2 = url;
|
|
5488
|
-
}
|
|
5489
|
-
logTiming(`${method} ${path2} started at ${startTime}`);
|
|
5490
|
-
try {
|
|
5491
|
-
const response = await baseFetch(input, init);
|
|
5492
|
-
const duration = performance.now() - start;
|
|
5493
|
-
logTiming(`${method} ${path2} -> ${formatDuration(duration)} (status: ${response.status})`);
|
|
5494
|
-
return response;
|
|
5495
|
-
} catch (error) {
|
|
5496
|
-
const duration = performance.now() - start;
|
|
5497
|
-
logTiming(`${method} ${path2} -> FAILED after ${formatDuration(duration)}`);
|
|
5498
|
-
throw error;
|
|
5499
|
-
}
|
|
5500
|
-
};
|
|
5501
|
-
}
|
|
5502
|
-
var milestones, firstMilestoneTime = null;
|
|
5503
|
-
var init_timing = __esm(() => {
|
|
5504
|
-
milestones = new Map;
|
|
5505
|
-
});
|
|
5506
|
-
|
|
5507
5398
|
// package.json
|
|
5508
5399
|
var package_default;
|
|
5509
5400
|
var init_package = __esm(() => {
|
|
5510
5401
|
package_default = {
|
|
5511
5402
|
name: "@letta-ai/letta-code",
|
|
5512
|
-
version: "0.31.
|
|
5403
|
+
version: "0.31.10",
|
|
5513
5404
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5514
5405
|
type: "module",
|
|
5515
5406
|
packageManager: "bun@1.3.10",
|
|
@@ -5753,266 +5644,6 @@ var init_package = __esm(() => {
|
|
|
5753
5644
|
};
|
|
5754
5645
|
});
|
|
5755
5646
|
|
|
5756
|
-
// src/backend/api/memfs-git-proxy.ts
|
|
5757
|
-
var exports_memfs_git_proxy = {};
|
|
5758
|
-
__export(exports_memfs_git_proxy, {
|
|
5759
|
-
getMemfsServerUrl: () => getMemfsServerUrl,
|
|
5760
|
-
getMemfsGitProxyRewriteConfig: () => getMemfsGitProxyRewriteConfig,
|
|
5761
|
-
LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV: () => LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV
|
|
5762
|
-
});
|
|
5763
|
-
function isLocalhostUrl(value) {
|
|
5764
|
-
if (!value)
|
|
5765
|
-
return false;
|
|
5766
|
-
try {
|
|
5767
|
-
const parsed = new URL(value);
|
|
5768
|
-
return ["localhost", "127.0.0.1", "::1", "[::1]"].includes(parsed.hostname);
|
|
5769
|
-
} catch {
|
|
5770
|
-
return false;
|
|
5771
|
-
}
|
|
5772
|
-
}
|
|
5773
|
-
function trimBaseUrl(value) {
|
|
5774
|
-
return value.trim().replace(/\/+$/, "");
|
|
5775
|
-
}
|
|
5776
|
-
function getMemfsServerUrl() {
|
|
5777
|
-
let settings = null;
|
|
5778
|
-
try {
|
|
5779
|
-
settings = settingsManager.getSettings();
|
|
5780
|
-
} catch {}
|
|
5781
|
-
const configuredMemfsUrl = process.env.LETTA_MEMFS_BASE_URL || settings?.env?.LETTA_MEMFS_BASE_URL;
|
|
5782
|
-
if (configuredMemfsUrl) {
|
|
5783
|
-
return configuredMemfsUrl;
|
|
5784
|
-
}
|
|
5785
|
-
return LETTA_CLOUD_API_URL;
|
|
5786
|
-
}
|
|
5787
|
-
function getMemfsGitProxyRewriteConfig(env = process.env) {
|
|
5788
|
-
const rawProxyBaseUrl = env[LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV]?.trim();
|
|
5789
|
-
if (!rawProxyBaseUrl || !isLocalhostUrl(rawProxyBaseUrl)) {
|
|
5790
|
-
return null;
|
|
5791
|
-
}
|
|
5792
|
-
const memfsBaseUrl = trimBaseUrl(getMemfsServerUrl());
|
|
5793
|
-
if (!memfsBaseUrl.includes("api.letta.com")) {
|
|
5794
|
-
return null;
|
|
5795
|
-
}
|
|
5796
|
-
const proxyBaseUrl = trimBaseUrl(rawProxyBaseUrl);
|
|
5797
|
-
const proxyPrefix = `${proxyBaseUrl}/v1/git/`;
|
|
5798
|
-
const memfsPrefix = `${memfsBaseUrl}/v1/git/`;
|
|
5799
|
-
return {
|
|
5800
|
-
proxyBaseUrl,
|
|
5801
|
-
memfsBaseUrl,
|
|
5802
|
-
proxyPrefix,
|
|
5803
|
-
memfsPrefix,
|
|
5804
|
-
configKey: `url.${proxyPrefix}.insteadOf`,
|
|
5805
|
-
configValue: memfsPrefix
|
|
5806
|
-
};
|
|
5807
|
-
}
|
|
5808
|
-
var LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV = "LETTA_MEMFS_GIT_PROXY_BASE_URL";
|
|
5809
|
-
var init_memfs_git_proxy = __esm(() => {
|
|
5810
|
-
init_oauth();
|
|
5811
|
-
init_settings_manager();
|
|
5812
|
-
});
|
|
5813
|
-
|
|
5814
|
-
// src/backend/api/client.ts
|
|
5815
|
-
var exports_client = {};
|
|
5816
|
-
__export(exports_client, {
|
|
5817
|
-
getServerUrl: () => getServerUrl,
|
|
5818
|
-
getRuntimeEnvironmentDeviceId: () => getRuntimeEnvironmentDeviceId,
|
|
5819
|
-
getMemfsServerUrl: () => getMemfsServerUrl,
|
|
5820
|
-
getMemfsGitProxyRewriteConfig: () => getMemfsGitProxyRewriteConfig,
|
|
5821
|
-
getClientDefaultHeaders: () => getClientDefaultHeaders,
|
|
5822
|
-
getClient: () => getClient,
|
|
5823
|
-
consumeLastSDKDiagnostic: () => consumeLastSDKDiagnostic,
|
|
5824
|
-
clearLastSDKDiagnostic: () => clearLastSDKDiagnostic,
|
|
5825
|
-
__testOverrideGetClient: () => __testOverrideGetClient,
|
|
5826
|
-
LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV: () => LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV
|
|
5827
|
-
});
|
|
5828
|
-
import { hostname } from "node:os";
|
|
5829
|
-
function __testOverrideGetClient(factory) {
|
|
5830
|
-
_testClientOverride = factory;
|
|
5831
|
-
}
|
|
5832
|
-
function safeDiagnosticString(value) {
|
|
5833
|
-
if (value === null || value === undefined) {
|
|
5834
|
-
return "";
|
|
5835
|
-
}
|
|
5836
|
-
if (typeof value === "string") {
|
|
5837
|
-
return value;
|
|
5838
|
-
}
|
|
5839
|
-
try {
|
|
5840
|
-
return JSON.stringify(value);
|
|
5841
|
-
} catch {
|
|
5842
|
-
return String(value);
|
|
5843
|
-
}
|
|
5844
|
-
}
|
|
5845
|
-
function truncateDiagnostic(value) {
|
|
5846
|
-
const text = safeDiagnosticString(value);
|
|
5847
|
-
if (text.length <= SDK_DIAGNOSTIC_MAX_LEN) {
|
|
5848
|
-
return text;
|
|
5849
|
-
}
|
|
5850
|
-
return `${text.slice(0, SDK_DIAGNOSTIC_MAX_LEN)}...[truncated, was ${text.length}b]`;
|
|
5851
|
-
}
|
|
5852
|
-
function captureSDKErrorDiagnostic(args) {
|
|
5853
|
-
const diagnosticLine = truncateDiagnostic(args.map((arg) => safeDiagnosticString(arg)).join(" "));
|
|
5854
|
-
const previous = lastSDKDiagnostic ?? { lines: [] };
|
|
5855
|
-
lastSDKDiagnostic = {
|
|
5856
|
-
lines: [...previous.lines, diagnosticLine].slice(-SDK_DIAGNOSTIC_MAX_LINES)
|
|
5857
|
-
};
|
|
5858
|
-
}
|
|
5859
|
-
function consumeLastSDKDiagnostic() {
|
|
5860
|
-
const diag = lastSDKDiagnostic;
|
|
5861
|
-
lastSDKDiagnostic = null;
|
|
5862
|
-
if (!diag || diag.lines.length === 0) {
|
|
5863
|
-
return null;
|
|
5864
|
-
}
|
|
5865
|
-
return `sdk_error=${diag.lines.join(" || ")}`;
|
|
5866
|
-
}
|
|
5867
|
-
function clearLastSDKDiagnostic() {
|
|
5868
|
-
lastSDKDiagnostic = null;
|
|
5869
|
-
}
|
|
5870
|
-
function getServerUrl() {
|
|
5871
|
-
const settings = settingsManager.getSettings();
|
|
5872
|
-
return process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
|
|
5873
|
-
}
|
|
5874
|
-
function getNodeRoutingHeader() {
|
|
5875
|
-
const raw = process.env.LETTA_NODE;
|
|
5876
|
-
if (raw === undefined || raw.trim() === "") {
|
|
5877
|
-
return {};
|
|
5878
|
-
}
|
|
5879
|
-
const enabled = NODE_HEADER_ENABLED_VALUES.has(raw.trim().toLowerCase());
|
|
5880
|
-
return { "x-letta-node": enabled ? "1" : "0" };
|
|
5881
|
-
}
|
|
5882
|
-
function getRuntimeEnvironmentDeviceId() {
|
|
5883
|
-
return process.env[RUNTIME_ENVIRONMENT_DEVICE_ID_ENV]?.trim() || settingsManager.getOrCreateDeviceId();
|
|
5884
|
-
}
|
|
5885
|
-
function getClientDefaultHeaders() {
|
|
5886
|
-
return {
|
|
5887
|
-
"X-Letta-Source": "letta-code",
|
|
5888
|
-
"User-Agent": `letta-code/${package_default.version}`,
|
|
5889
|
-
"X-Letta-Environment-Device-Id": getRuntimeEnvironmentDeviceId(),
|
|
5890
|
-
...getNodeRoutingHeader(),
|
|
5891
|
-
...process.env.LETTA_MEMFS_BACKEND === "hosted" ? { "x-letta-memfs-backend": "hosted" } : {}
|
|
5892
|
-
};
|
|
5893
|
-
}
|
|
5894
|
-
async function getClient() {
|
|
5895
|
-
if (_testClientOverride) {
|
|
5896
|
-
return await _testClientOverride();
|
|
5897
|
-
}
|
|
5898
|
-
const baseSettings = settingsManager.getSettings();
|
|
5899
|
-
const cachedTokens = settingsManager.getCachedSecureTokens();
|
|
5900
|
-
const cachedSettings = {
|
|
5901
|
-
...baseSettings,
|
|
5902
|
-
env: {
|
|
5903
|
-
...baseSettings.env,
|
|
5904
|
-
...cachedTokens.apiKey && { LETTA_API_KEY: cachedTokens.apiKey }
|
|
5905
|
-
},
|
|
5906
|
-
refreshToken: cachedTokens.refreshToken ?? baseSettings.refreshToken
|
|
5907
|
-
};
|
|
5908
|
-
const settings = process.env.LETTA_API_KEY || cachedSettings.env?.LETTA_API_KEY || cachedSettings.refreshToken ? cachedSettings : await settingsManager.getSettingsWithSecureTokens();
|
|
5909
|
-
let apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
|
|
5910
|
-
if (!process.env.LETTA_API_KEY) {
|
|
5911
|
-
if (apiKey) {
|
|
5912
|
-
_cachedApiKey = apiKey;
|
|
5913
|
-
} else if (_cachedApiKey) {
|
|
5914
|
-
apiKey = _cachedApiKey;
|
|
5915
|
-
}
|
|
5916
|
-
}
|
|
5917
|
-
if (!process.env.LETTA_API_KEY && settings.tokenExpiresAt && settings.refreshToken) {
|
|
5918
|
-
const now = Date.now();
|
|
5919
|
-
const expiresAt = settings.tokenExpiresAt;
|
|
5920
|
-
if (!apiKey || expiresAt - now < 5 * 60 * 1000) {
|
|
5921
|
-
try {
|
|
5922
|
-
const deviceId = settingsManager.getOrCreateDeviceId();
|
|
5923
|
-
const deviceName = hostname();
|
|
5924
|
-
const tokens = await refreshAccessTokenSingleFlight(settings.refreshToken, deviceId, deviceName);
|
|
5925
|
-
settingsManager.updateSettings({
|
|
5926
|
-
env: { LETTA_API_KEY: tokens.access_token },
|
|
5927
|
-
refreshToken: tokens.refresh_token || settings.refreshToken,
|
|
5928
|
-
tokenExpiresAt: now + tokens.expires_in * 1000
|
|
5929
|
-
});
|
|
5930
|
-
apiKey = tokens.access_token;
|
|
5931
|
-
_cachedApiKey = tokens.access_token;
|
|
5932
|
-
} catch (error) {
|
|
5933
|
-
trackBoundaryError({
|
|
5934
|
-
errorType: "auth_token_refresh_failed",
|
|
5935
|
-
error,
|
|
5936
|
-
context: "auth_client_token_refresh"
|
|
5937
|
-
});
|
|
5938
|
-
console.error("Failed to refresh access token:", error);
|
|
5939
|
-
console.error(`
|
|
5940
|
-
If you experience this issue multiple times, move ~/.letta to ~/.letta_backup, and re-run 'letta' to re-authenticate`);
|
|
5941
|
-
throw new Error(`Failed to refresh access token: ${error instanceof Error ? error.message : String(error)}`);
|
|
5942
|
-
}
|
|
5943
|
-
}
|
|
5944
|
-
}
|
|
5945
|
-
const baseURL = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
|
|
5946
|
-
if (!apiKey && baseURL === LETTA_CLOUD_API_URL) {
|
|
5947
|
-
console.error("Missing LETTA_API_KEY");
|
|
5948
|
-
console.error("Run 'letta' to configure authentication, or set LETTA_API_KEY to your API key");
|
|
5949
|
-
console.error(new Error("getClient() called without credentials").stack);
|
|
5950
|
-
throw new Error("Missing LETTA_API_KEY. Run 'letta' to configure authentication, or set LETTA_API_KEY to your API key.");
|
|
5951
|
-
}
|
|
5952
|
-
const client = new Letta({
|
|
5953
|
-
apiKey,
|
|
5954
|
-
baseURL,
|
|
5955
|
-
logger: sdkLogger,
|
|
5956
|
-
timeout: Number(process.env.LETTA_REQUEST_TIMEOUT_MS) || 10 * 60 * 1000,
|
|
5957
|
-
defaultHeaders: getClientDefaultHeaders(),
|
|
5958
|
-
...isTimingsEnabled() && { fetch: createTimingFetch(fetch) }
|
|
5959
|
-
});
|
|
5960
|
-
const MESSAGE_CACHE_MAX = 32;
|
|
5961
|
-
const messageCache = new Map;
|
|
5962
|
-
const origRetrieveMessage = client.messages.retrieve.bind(client.messages);
|
|
5963
|
-
client.messages.retrieve = (...args) => {
|
|
5964
|
-
const messageId = args[0];
|
|
5965
|
-
const cached = messageCache.get(messageId);
|
|
5966
|
-
if (cached) {
|
|
5967
|
-
messageCache.delete(messageId);
|
|
5968
|
-
messageCache.set(messageId, cached);
|
|
5969
|
-
return cached;
|
|
5970
|
-
}
|
|
5971
|
-
const promise = origRetrieveMessage(...args);
|
|
5972
|
-
messageCache.set(messageId, promise);
|
|
5973
|
-
if (messageCache.size > MESSAGE_CACHE_MAX) {
|
|
5974
|
-
const oldest = messageCache.keys().next().value;
|
|
5975
|
-
if (oldest !== undefined)
|
|
5976
|
-
messageCache.delete(oldest);
|
|
5977
|
-
}
|
|
5978
|
-
promise.catch(() => messageCache.delete(messageId));
|
|
5979
|
-
return promise;
|
|
5980
|
-
};
|
|
5981
|
-
return client;
|
|
5982
|
-
}
|
|
5983
|
-
var SDK_DIAGNOSTIC_MAX_LEN = 400, SDK_DIAGNOSTIC_MAX_LINES = 4, lastSDKDiagnostic = null, _cachedApiKey, _testClientOverride = null, sdkLogger, NODE_HEADER_ENABLED_VALUES, RUNTIME_ENVIRONMENT_DEVICE_ID_ENV = "LETTA_RUNTIME_ENVIRONMENT_DEVICE_ID";
|
|
5984
|
-
var init_client2 = __esm(() => {
|
|
5985
|
-
init_letta_client();
|
|
5986
|
-
init_oauth();
|
|
5987
|
-
init_oauth_refresh();
|
|
5988
|
-
init_settings_manager();
|
|
5989
|
-
init_error_reporting();
|
|
5990
|
-
init_debug();
|
|
5991
|
-
init_timing();
|
|
5992
|
-
init_package();
|
|
5993
|
-
init_memfs_git_proxy();
|
|
5994
|
-
sdkLogger = {
|
|
5995
|
-
error: (...args) => {
|
|
5996
|
-
try {
|
|
5997
|
-
captureSDKErrorDiagnostic(args);
|
|
5998
|
-
} catch {}
|
|
5999
|
-
if (isDebugEnabled()) {
|
|
6000
|
-
console.error(...args);
|
|
6001
|
-
}
|
|
6002
|
-
},
|
|
6003
|
-
warn: (...args) => {
|
|
6004
|
-
console.warn(...args);
|
|
6005
|
-
},
|
|
6006
|
-
info: (...args) => {
|
|
6007
|
-
console.info(...args);
|
|
6008
|
-
},
|
|
6009
|
-
debug: (...args) => {
|
|
6010
|
-
console.debug(...args);
|
|
6011
|
-
}
|
|
6012
|
-
};
|
|
6013
|
-
NODE_HEADER_ENABLED_VALUES = new Set(["1", "true", "yes"]);
|
|
6014
|
-
});
|
|
6015
|
-
|
|
6016
5647
|
// src/backend/api/http-headers.ts
|
|
6017
5648
|
function getLettaCodeHeaders(apiKey) {
|
|
6018
5649
|
return {
|
|
@@ -6140,8 +5771,8 @@ function parseUrl(value, options = {}) {
|
|
|
6140
5771
|
return null;
|
|
6141
5772
|
}
|
|
6142
5773
|
}
|
|
6143
|
-
function isLoopbackHostname(
|
|
6144
|
-
const normalized =
|
|
5774
|
+
function isLoopbackHostname(hostname) {
|
|
5775
|
+
const normalized = hostname.toLowerCase();
|
|
6145
5776
|
return normalized === "localhost" || normalized === "0.0.0.0" || normalized === "::1" || normalized === "[::1]" || normalized.startsWith("127.");
|
|
6146
5777
|
}
|
|
6147
5778
|
function isLoopbackUrl(value, options = {}) {
|
|
@@ -6198,6 +5829,38 @@ var init_metadata = __esm(() => {
|
|
|
6198
5829
|
init_request();
|
|
6199
5830
|
});
|
|
6200
5831
|
|
|
5832
|
+
// src/backend/api/server-url.ts
|
|
5833
|
+
var exports_server_url = {};
|
|
5834
|
+
__export(exports_server_url, {
|
|
5835
|
+
isCloudServerUrl: () => isCloudServerUrl,
|
|
5836
|
+
getServerUrl: () => getServerUrl
|
|
5837
|
+
});
|
|
5838
|
+
function getServerUrl() {
|
|
5839
|
+
const settings = settingsManager.getSettings();
|
|
5840
|
+
return process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
|
|
5841
|
+
}
|
|
5842
|
+
function isCloudServerUrl(serverUrl) {
|
|
5843
|
+
let resolved = serverUrl;
|
|
5844
|
+
if (resolved === undefined) {
|
|
5845
|
+
try {
|
|
5846
|
+
resolved = getServerUrl();
|
|
5847
|
+
} catch {
|
|
5848
|
+
resolved = process.env.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
|
|
5849
|
+
}
|
|
5850
|
+
}
|
|
5851
|
+
try {
|
|
5852
|
+
const parsed = new URL(resolved);
|
|
5853
|
+
const cloud = new URL(LETTA_CLOUD_API_URL);
|
|
5854
|
+
return parsed.hostname === cloud.hostname;
|
|
5855
|
+
} catch {
|
|
5856
|
+
return false;
|
|
5857
|
+
}
|
|
5858
|
+
}
|
|
5859
|
+
var init_server_url = __esm(() => {
|
|
5860
|
+
init_oauth();
|
|
5861
|
+
init_settings_manager();
|
|
5862
|
+
});
|
|
5863
|
+
|
|
6201
5864
|
// src/version.ts
|
|
6202
5865
|
var exports_version = {};
|
|
6203
5866
|
__export(exports_version, {
|
|
@@ -6725,9 +6388,9 @@ class TelemetryManager {
|
|
|
6725
6388
|
var telemetry;
|
|
6726
6389
|
var init_telemetry = __esm(() => {
|
|
6727
6390
|
init_oauth();
|
|
6728
|
-
init_client2();
|
|
6729
6391
|
init_health();
|
|
6730
6392
|
init_metadata();
|
|
6393
|
+
init_server_url();
|
|
6731
6394
|
init_paths();
|
|
6732
6395
|
init_settings_manager();
|
|
6733
6396
|
init_debug();
|
|
@@ -6776,6 +6439,370 @@ function buildCreatedAgentTags(options = {}) {
|
|
|
6776
6439
|
}
|
|
6777
6440
|
var LETTA_CODE_ORIGIN_TAG = "origin:letta-code", ONBOARDING_ORIGIN_TAG = "origin:onboarding", LETTA_CODE_SUBAGENT_TAG = "role:subagent", GIT_MEMORY_ENABLED_TAG = "git-memory-enabled";
|
|
6778
6441
|
|
|
6442
|
+
// src/auth/oauth-refresh.ts
|
|
6443
|
+
async function refreshAccessTokenSingleFlight(refreshToken2, deviceId, deviceName, refresh = refreshAccessToken2) {
|
|
6444
|
+
const refreshKey = `${refreshToken2}\x00${deviceId}`;
|
|
6445
|
+
const existing = inFlightRefreshes.get(refreshKey);
|
|
6446
|
+
if (existing) {
|
|
6447
|
+
return await existing;
|
|
6448
|
+
}
|
|
6449
|
+
const pending = refresh(refreshToken2, deviceId, deviceName);
|
|
6450
|
+
inFlightRefreshes.set(refreshKey, pending);
|
|
6451
|
+
try {
|
|
6452
|
+
return await pending;
|
|
6453
|
+
} finally {
|
|
6454
|
+
if (inFlightRefreshes.get(refreshKey) === pending) {
|
|
6455
|
+
inFlightRefreshes.delete(refreshKey);
|
|
6456
|
+
}
|
|
6457
|
+
}
|
|
6458
|
+
}
|
|
6459
|
+
var inFlightRefreshes;
|
|
6460
|
+
var init_oauth_refresh = __esm(() => {
|
|
6461
|
+
init_oauth();
|
|
6462
|
+
inFlightRefreshes = new Map;
|
|
6463
|
+
});
|
|
6464
|
+
|
|
6465
|
+
// src/utils/timing.ts
|
|
6466
|
+
function isTimingsEnabled() {
|
|
6467
|
+
const val = process.env.LETTA_DEBUG_TIMINGS;
|
|
6468
|
+
return val === "1" || val === "true";
|
|
6469
|
+
}
|
|
6470
|
+
function formatDuration(ms) {
|
|
6471
|
+
if (ms < 1000)
|
|
6472
|
+
return `${Math.round(ms)}ms`;
|
|
6473
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
6474
|
+
}
|
|
6475
|
+
function formatTimestamp(date) {
|
|
6476
|
+
return date.toISOString().slice(11, 23);
|
|
6477
|
+
}
|
|
6478
|
+
function logTiming(message) {
|
|
6479
|
+
if (isTimingsEnabled()) {
|
|
6480
|
+
console.error(`[timing] ${message}`);
|
|
6481
|
+
}
|
|
6482
|
+
}
|
|
6483
|
+
function markMilestone(name) {
|
|
6484
|
+
const now = performance.now();
|
|
6485
|
+
milestones.set(name, now);
|
|
6486
|
+
if (firstMilestoneTime === null) {
|
|
6487
|
+
firstMilestoneTime = now;
|
|
6488
|
+
}
|
|
6489
|
+
if (isTimingsEnabled()) {
|
|
6490
|
+
const relative = now - firstMilestoneTime;
|
|
6491
|
+
console.error(`[timing] MILESTONE ${name} at +${formatDuration(relative)} (${formatTimestamp(new Date)})`);
|
|
6492
|
+
}
|
|
6493
|
+
}
|
|
6494
|
+
function measureSinceMilestone(label, fromMilestone) {
|
|
6495
|
+
if (!isTimingsEnabled())
|
|
6496
|
+
return;
|
|
6497
|
+
const startTime = milestones.get(fromMilestone);
|
|
6498
|
+
if (startTime === undefined) {
|
|
6499
|
+
console.error(`[timing] WARNING: milestone "${fromMilestone}" not found for measurement "${label}"`);
|
|
6500
|
+
return;
|
|
6501
|
+
}
|
|
6502
|
+
const duration = performance.now() - startTime;
|
|
6503
|
+
console.error(`[timing] ${label}: ${formatDuration(duration)}`);
|
|
6504
|
+
}
|
|
6505
|
+
function reportAllMilestones() {
|
|
6506
|
+
if (!isTimingsEnabled() || milestones.size === 0)
|
|
6507
|
+
return;
|
|
6508
|
+
const first = firstMilestoneTime ?? 0;
|
|
6509
|
+
console.error(`[timing] ======== MILESTONE SUMMARY ========`);
|
|
6510
|
+
const sorted = [...milestones.entries()].sort((a, b) => a[1] - b[1]);
|
|
6511
|
+
let prevTime = first;
|
|
6512
|
+
for (const [name, time] of sorted) {
|
|
6513
|
+
const relativeToStart = time - first;
|
|
6514
|
+
const delta = time - prevTime;
|
|
6515
|
+
const deltaStr = prevTime === first ? "" : ` (+${formatDuration(delta)})`;
|
|
6516
|
+
console.error(`[timing] +${formatDuration(relativeToStart).padStart(8)} ${name}${deltaStr}`);
|
|
6517
|
+
prevTime = time;
|
|
6518
|
+
}
|
|
6519
|
+
console.error(`[timing] =====================================`);
|
|
6520
|
+
}
|
|
6521
|
+
function createTimingFetch(baseFetch) {
|
|
6522
|
+
return async (input, init) => {
|
|
6523
|
+
const start = performance.now();
|
|
6524
|
+
const startTime = formatTimestamp(new Date);
|
|
6525
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
6526
|
+
const method = init?.method || "GET";
|
|
6527
|
+
let path2;
|
|
6528
|
+
try {
|
|
6529
|
+
path2 = new URL(url).pathname;
|
|
6530
|
+
} catch {
|
|
6531
|
+
path2 = url;
|
|
6532
|
+
}
|
|
6533
|
+
logTiming(`${method} ${path2} started at ${startTime}`);
|
|
6534
|
+
try {
|
|
6535
|
+
const response = await baseFetch(input, init);
|
|
6536
|
+
const duration = performance.now() - start;
|
|
6537
|
+
logTiming(`${method} ${path2} -> ${formatDuration(duration)} (status: ${response.status})`);
|
|
6538
|
+
return response;
|
|
6539
|
+
} catch (error) {
|
|
6540
|
+
const duration = performance.now() - start;
|
|
6541
|
+
logTiming(`${method} ${path2} -> FAILED after ${formatDuration(duration)}`);
|
|
6542
|
+
throw error;
|
|
6543
|
+
}
|
|
6544
|
+
};
|
|
6545
|
+
}
|
|
6546
|
+
var milestones, firstMilestoneTime = null;
|
|
6547
|
+
var init_timing = __esm(() => {
|
|
6548
|
+
milestones = new Map;
|
|
6549
|
+
});
|
|
6550
|
+
|
|
6551
|
+
// src/backend/api/memfs-git-proxy.ts
|
|
6552
|
+
var exports_memfs_git_proxy = {};
|
|
6553
|
+
__export(exports_memfs_git_proxy, {
|
|
6554
|
+
getMemfsServerUrl: () => getMemfsServerUrl,
|
|
6555
|
+
getMemfsGitProxyRewriteConfig: () => getMemfsGitProxyRewriteConfig,
|
|
6556
|
+
LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV: () => LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV
|
|
6557
|
+
});
|
|
6558
|
+
function isLocalhostUrl(value) {
|
|
6559
|
+
if (!value)
|
|
6560
|
+
return false;
|
|
6561
|
+
try {
|
|
6562
|
+
const parsed = new URL(value);
|
|
6563
|
+
return ["localhost", "127.0.0.1", "::1", "[::1]"].includes(parsed.hostname);
|
|
6564
|
+
} catch {
|
|
6565
|
+
return false;
|
|
6566
|
+
}
|
|
6567
|
+
}
|
|
6568
|
+
function trimBaseUrl(value) {
|
|
6569
|
+
return value.trim().replace(/\/+$/, "");
|
|
6570
|
+
}
|
|
6571
|
+
function getMemfsServerUrl() {
|
|
6572
|
+
let settings = null;
|
|
6573
|
+
try {
|
|
6574
|
+
settings = settingsManager.getSettings();
|
|
6575
|
+
} catch {}
|
|
6576
|
+
const configuredMemfsUrl = process.env.LETTA_MEMFS_BASE_URL || settings?.env?.LETTA_MEMFS_BASE_URL;
|
|
6577
|
+
if (configuredMemfsUrl) {
|
|
6578
|
+
return configuredMemfsUrl;
|
|
6579
|
+
}
|
|
6580
|
+
return LETTA_CLOUD_API_URL;
|
|
6581
|
+
}
|
|
6582
|
+
function getMemfsGitProxyRewriteConfig(env = process.env) {
|
|
6583
|
+
const rawProxyBaseUrl = env[LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV]?.trim();
|
|
6584
|
+
if (!rawProxyBaseUrl || !isLocalhostUrl(rawProxyBaseUrl)) {
|
|
6585
|
+
return null;
|
|
6586
|
+
}
|
|
6587
|
+
const memfsBaseUrl = trimBaseUrl(getMemfsServerUrl());
|
|
6588
|
+
if (!memfsBaseUrl.includes("api.letta.com")) {
|
|
6589
|
+
return null;
|
|
6590
|
+
}
|
|
6591
|
+
const proxyBaseUrl = trimBaseUrl(rawProxyBaseUrl);
|
|
6592
|
+
const proxyPrefix = `${proxyBaseUrl}/v1/git/`;
|
|
6593
|
+
const memfsPrefix = `${memfsBaseUrl}/v1/git/`;
|
|
6594
|
+
return {
|
|
6595
|
+
proxyBaseUrl,
|
|
6596
|
+
memfsBaseUrl,
|
|
6597
|
+
proxyPrefix,
|
|
6598
|
+
memfsPrefix,
|
|
6599
|
+
configKey: `url.${proxyPrefix}.insteadOf`,
|
|
6600
|
+
configValue: memfsPrefix
|
|
6601
|
+
};
|
|
6602
|
+
}
|
|
6603
|
+
var LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV = "LETTA_MEMFS_GIT_PROXY_BASE_URL";
|
|
6604
|
+
var init_memfs_git_proxy = __esm(() => {
|
|
6605
|
+
init_oauth();
|
|
6606
|
+
init_settings_manager();
|
|
6607
|
+
});
|
|
6608
|
+
|
|
6609
|
+
// src/backend/api/client.ts
|
|
6610
|
+
var exports_client = {};
|
|
6611
|
+
__export(exports_client, {
|
|
6612
|
+
getRuntimeEnvironmentDeviceId: () => getRuntimeEnvironmentDeviceId,
|
|
6613
|
+
getMemfsServerUrl: () => getMemfsServerUrl,
|
|
6614
|
+
getMemfsGitProxyRewriteConfig: () => getMemfsGitProxyRewriteConfig,
|
|
6615
|
+
getClientDefaultHeaders: () => getClientDefaultHeaders,
|
|
6616
|
+
getClient: () => getClient,
|
|
6617
|
+
consumeLastSDKDiagnostic: () => consumeLastSDKDiagnostic,
|
|
6618
|
+
clearLastSDKDiagnostic: () => clearLastSDKDiagnostic,
|
|
6619
|
+
__testOverrideGetClient: () => __testOverrideGetClient,
|
|
6620
|
+
LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV: () => LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV
|
|
6621
|
+
});
|
|
6622
|
+
import { hostname } from "node:os";
|
|
6623
|
+
function __testOverrideGetClient(factory) {
|
|
6624
|
+
_testClientOverride = factory;
|
|
6625
|
+
}
|
|
6626
|
+
function safeDiagnosticString(value) {
|
|
6627
|
+
if (value === null || value === undefined) {
|
|
6628
|
+
return "";
|
|
6629
|
+
}
|
|
6630
|
+
if (typeof value === "string") {
|
|
6631
|
+
return value;
|
|
6632
|
+
}
|
|
6633
|
+
try {
|
|
6634
|
+
return JSON.stringify(value);
|
|
6635
|
+
} catch {
|
|
6636
|
+
return String(value);
|
|
6637
|
+
}
|
|
6638
|
+
}
|
|
6639
|
+
function truncateDiagnostic(value) {
|
|
6640
|
+
const text = safeDiagnosticString(value);
|
|
6641
|
+
if (text.length <= SDK_DIAGNOSTIC_MAX_LEN) {
|
|
6642
|
+
return text;
|
|
6643
|
+
}
|
|
6644
|
+
return `${text.slice(0, SDK_DIAGNOSTIC_MAX_LEN)}...[truncated, was ${text.length}b]`;
|
|
6645
|
+
}
|
|
6646
|
+
function captureSDKErrorDiagnostic(args) {
|
|
6647
|
+
const diagnosticLine = truncateDiagnostic(args.map((arg) => safeDiagnosticString(arg)).join(" "));
|
|
6648
|
+
const previous = lastSDKDiagnostic ?? { lines: [] };
|
|
6649
|
+
lastSDKDiagnostic = {
|
|
6650
|
+
lines: [...previous.lines, diagnosticLine].slice(-SDK_DIAGNOSTIC_MAX_LINES)
|
|
6651
|
+
};
|
|
6652
|
+
}
|
|
6653
|
+
function consumeLastSDKDiagnostic() {
|
|
6654
|
+
const diag = lastSDKDiagnostic;
|
|
6655
|
+
lastSDKDiagnostic = null;
|
|
6656
|
+
if (!diag || diag.lines.length === 0) {
|
|
6657
|
+
return null;
|
|
6658
|
+
}
|
|
6659
|
+
return `sdk_error=${diag.lines.join(" || ")}`;
|
|
6660
|
+
}
|
|
6661
|
+
function clearLastSDKDiagnostic() {
|
|
6662
|
+
lastSDKDiagnostic = null;
|
|
6663
|
+
}
|
|
6664
|
+
function getNodeRoutingHeader() {
|
|
6665
|
+
const raw = process.env.LETTA_NODE;
|
|
6666
|
+
if (raw === undefined || raw.trim() === "") {
|
|
6667
|
+
return {};
|
|
6668
|
+
}
|
|
6669
|
+
const enabled = NODE_HEADER_ENABLED_VALUES.has(raw.trim().toLowerCase());
|
|
6670
|
+
return { "x-letta-node": enabled ? "1" : "0" };
|
|
6671
|
+
}
|
|
6672
|
+
function getRuntimeEnvironmentDeviceId() {
|
|
6673
|
+
return process.env[RUNTIME_ENVIRONMENT_DEVICE_ID_ENV]?.trim() || settingsManager.getOrCreateDeviceId();
|
|
6674
|
+
}
|
|
6675
|
+
function getClientDefaultHeaders() {
|
|
6676
|
+
return {
|
|
6677
|
+
"X-Letta-Source": "letta-code",
|
|
6678
|
+
"User-Agent": `letta-code/${package_default.version}`,
|
|
6679
|
+
"X-Letta-Environment-Device-Id": getRuntimeEnvironmentDeviceId(),
|
|
6680
|
+
...getNodeRoutingHeader(),
|
|
6681
|
+
...process.env.LETTA_MEMFS_BACKEND === "hosted" ? { "x-letta-memfs-backend": "hosted" } : {}
|
|
6682
|
+
};
|
|
6683
|
+
}
|
|
6684
|
+
async function getClient() {
|
|
6685
|
+
if (_testClientOverride) {
|
|
6686
|
+
return await _testClientOverride();
|
|
6687
|
+
}
|
|
6688
|
+
const baseSettings = settingsManager.getSettings();
|
|
6689
|
+
const cachedTokens = settingsManager.getCachedSecureTokens();
|
|
6690
|
+
const cachedSettings = {
|
|
6691
|
+
...baseSettings,
|
|
6692
|
+
env: {
|
|
6693
|
+
...baseSettings.env,
|
|
6694
|
+
...cachedTokens.apiKey && { LETTA_API_KEY: cachedTokens.apiKey }
|
|
6695
|
+
},
|
|
6696
|
+
refreshToken: cachedTokens.refreshToken ?? baseSettings.refreshToken
|
|
6697
|
+
};
|
|
6698
|
+
const settings = process.env.LETTA_API_KEY || cachedSettings.env?.LETTA_API_KEY || cachedSettings.refreshToken ? cachedSettings : await settingsManager.getSettingsWithSecureTokens();
|
|
6699
|
+
let apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
|
|
6700
|
+
if (!process.env.LETTA_API_KEY) {
|
|
6701
|
+
if (apiKey) {
|
|
6702
|
+
_cachedApiKey = apiKey;
|
|
6703
|
+
} else if (_cachedApiKey) {
|
|
6704
|
+
apiKey = _cachedApiKey;
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
if (!process.env.LETTA_API_KEY && settings.tokenExpiresAt && settings.refreshToken) {
|
|
6708
|
+
const now = Date.now();
|
|
6709
|
+
const expiresAt = settings.tokenExpiresAt;
|
|
6710
|
+
if (!apiKey || expiresAt - now < 5 * 60 * 1000) {
|
|
6711
|
+
try {
|
|
6712
|
+
const deviceId = settingsManager.getOrCreateDeviceId();
|
|
6713
|
+
const deviceName = hostname();
|
|
6714
|
+
const tokens = await refreshAccessTokenSingleFlight(settings.refreshToken, deviceId, deviceName);
|
|
6715
|
+
settingsManager.updateSettings({
|
|
6716
|
+
env: { LETTA_API_KEY: tokens.access_token },
|
|
6717
|
+
refreshToken: tokens.refresh_token || settings.refreshToken,
|
|
6718
|
+
tokenExpiresAt: now + tokens.expires_in * 1000
|
|
6719
|
+
});
|
|
6720
|
+
apiKey = tokens.access_token;
|
|
6721
|
+
_cachedApiKey = tokens.access_token;
|
|
6722
|
+
} catch (error) {
|
|
6723
|
+
trackBoundaryError({
|
|
6724
|
+
errorType: "auth_token_refresh_failed",
|
|
6725
|
+
error,
|
|
6726
|
+
context: "auth_client_token_refresh"
|
|
6727
|
+
});
|
|
6728
|
+
console.error("Failed to refresh access token:", error);
|
|
6729
|
+
console.error(`
|
|
6730
|
+
If you experience this issue multiple times, move ~/.letta to ~/.letta_backup, and re-run 'letta' to re-authenticate`);
|
|
6731
|
+
throw new Error(`Failed to refresh access token: ${error instanceof Error ? error.message : String(error)}`);
|
|
6732
|
+
}
|
|
6733
|
+
}
|
|
6734
|
+
}
|
|
6735
|
+
const baseURL = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
|
|
6736
|
+
if (!apiKey && baseURL === LETTA_CLOUD_API_URL) {
|
|
6737
|
+
console.error("Missing LETTA_API_KEY");
|
|
6738
|
+
console.error("Run 'letta' to configure authentication, or set LETTA_API_KEY to your API key");
|
|
6739
|
+
console.error(new Error("getClient() called without credentials").stack);
|
|
6740
|
+
throw new Error("Missing LETTA_API_KEY. Run 'letta' to configure authentication, or set LETTA_API_KEY to your API key.");
|
|
6741
|
+
}
|
|
6742
|
+
const client = new Letta({
|
|
6743
|
+
apiKey,
|
|
6744
|
+
baseURL,
|
|
6745
|
+
logger: sdkLogger,
|
|
6746
|
+
timeout: Number(process.env.LETTA_REQUEST_TIMEOUT_MS) || 10 * 60 * 1000,
|
|
6747
|
+
defaultHeaders: getClientDefaultHeaders(),
|
|
6748
|
+
...isTimingsEnabled() && { fetch: createTimingFetch(fetch) }
|
|
6749
|
+
});
|
|
6750
|
+
const MESSAGE_CACHE_MAX = 32;
|
|
6751
|
+
const messageCache = new Map;
|
|
6752
|
+
const origRetrieveMessage = client.messages.retrieve.bind(client.messages);
|
|
6753
|
+
client.messages.retrieve = (...args) => {
|
|
6754
|
+
const messageId = args[0];
|
|
6755
|
+
const cached = messageCache.get(messageId);
|
|
6756
|
+
if (cached) {
|
|
6757
|
+
messageCache.delete(messageId);
|
|
6758
|
+
messageCache.set(messageId, cached);
|
|
6759
|
+
return cached;
|
|
6760
|
+
}
|
|
6761
|
+
const promise = origRetrieveMessage(...args);
|
|
6762
|
+
messageCache.set(messageId, promise);
|
|
6763
|
+
if (messageCache.size > MESSAGE_CACHE_MAX) {
|
|
6764
|
+
const oldest = messageCache.keys().next().value;
|
|
6765
|
+
if (oldest !== undefined)
|
|
6766
|
+
messageCache.delete(oldest);
|
|
6767
|
+
}
|
|
6768
|
+
promise.catch(() => messageCache.delete(messageId));
|
|
6769
|
+
return promise;
|
|
6770
|
+
};
|
|
6771
|
+
return client;
|
|
6772
|
+
}
|
|
6773
|
+
var SDK_DIAGNOSTIC_MAX_LEN = 400, SDK_DIAGNOSTIC_MAX_LINES = 4, lastSDKDiagnostic = null, _cachedApiKey, _testClientOverride = null, sdkLogger, NODE_HEADER_ENABLED_VALUES, RUNTIME_ENVIRONMENT_DEVICE_ID_ENV = "LETTA_RUNTIME_ENVIRONMENT_DEVICE_ID";
|
|
6774
|
+
var init_client2 = __esm(() => {
|
|
6775
|
+
init_letta_client();
|
|
6776
|
+
init_oauth();
|
|
6777
|
+
init_oauth_refresh();
|
|
6778
|
+
init_settings_manager();
|
|
6779
|
+
init_error_reporting();
|
|
6780
|
+
init_debug();
|
|
6781
|
+
init_timing();
|
|
6782
|
+
init_package();
|
|
6783
|
+
init_memfs_git_proxy();
|
|
6784
|
+
sdkLogger = {
|
|
6785
|
+
error: (...args) => {
|
|
6786
|
+
try {
|
|
6787
|
+
captureSDKErrorDiagnostic(args);
|
|
6788
|
+
} catch {}
|
|
6789
|
+
if (isDebugEnabled()) {
|
|
6790
|
+
console.error(...args);
|
|
6791
|
+
}
|
|
6792
|
+
},
|
|
6793
|
+
warn: (...args) => {
|
|
6794
|
+
console.warn(...args);
|
|
6795
|
+
},
|
|
6796
|
+
info: (...args) => {
|
|
6797
|
+
console.info(...args);
|
|
6798
|
+
},
|
|
6799
|
+
debug: (...args) => {
|
|
6800
|
+
console.debug(...args);
|
|
6801
|
+
}
|
|
6802
|
+
};
|
|
6803
|
+
NODE_HEADER_ENABLED_VALUES = new Set(["1", "true", "yes"]);
|
|
6804
|
+
});
|
|
6805
|
+
|
|
6779
6806
|
// src/utils/text-files.ts
|
|
6780
6807
|
import { readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
6781
6808
|
function getUtf16Bom(bytes) {
|
|
@@ -88170,6 +88197,30 @@ var init_tool_return_clamp = __esm(() => {
|
|
|
88170
88197
|
init_truncation();
|
|
88171
88198
|
});
|
|
88172
88199
|
|
|
88200
|
+
// src/tools/task-tool-assets.ts
|
|
88201
|
+
function stripComputerFromTaskSchema(schema5) {
|
|
88202
|
+
const properties4 = schema5.properties;
|
|
88203
|
+
if (!properties4 || !Object.hasOwn(properties4, "computer")) {
|
|
88204
|
+
return schema5;
|
|
88205
|
+
}
|
|
88206
|
+
const { computer: _computer, ...rest3 } = properties4;
|
|
88207
|
+
return { ...schema5, properties: rest3 };
|
|
88208
|
+
}
|
|
88209
|
+
function stripComputerFromTaskDescription(description) {
|
|
88210
|
+
const start = description.indexOf(COMPUTER_SECTION_HEADING);
|
|
88211
|
+
if (start === -1) {
|
|
88212
|
+
return description;
|
|
88213
|
+
}
|
|
88214
|
+
const afterHeading = start + COMPUTER_SECTION_HEADING.length;
|
|
88215
|
+
const next = description.indexOf(`
|
|
88216
|
+
## `, afterHeading);
|
|
88217
|
+
const removed = next === -1 ? description.slice(0, start) : description.slice(0, start) + description.slice(next + 1);
|
|
88218
|
+
return removed.replace(/\n{3,}/g, `
|
|
88219
|
+
|
|
88220
|
+
`).trimEnd();
|
|
88221
|
+
}
|
|
88222
|
+
var COMPUTER_SECTION_HEADING = "## Running on Another Computer";
|
|
88223
|
+
|
|
88173
88224
|
// src/tools/define-tool.ts
|
|
88174
88225
|
function defineTool(input) {
|
|
88175
88226
|
return {
|
|
@@ -93661,7 +93712,7 @@ var LETTA_BIN_ARGS_ENV = "LETTA_CODE_BIN_ARGS_JSON", SHELL_SHIM_DIR_NAME = "lett
|
|
|
93661
93712
|
var init_shell_env = __esm(() => {
|
|
93662
93713
|
init_context();
|
|
93663
93714
|
init_memory_filesystem2();
|
|
93664
|
-
|
|
93715
|
+
init_server_url();
|
|
93665
93716
|
init_paths();
|
|
93666
93717
|
init_runtime_context();
|
|
93667
93718
|
init_settings_manager();
|
|
@@ -115525,6 +115576,17 @@ async function task(args) {
|
|
|
115525
115576
|
if (!config) {
|
|
115526
115577
|
return `Error: Invalid subagent type "${subagent_type}"`;
|
|
115527
115578
|
}
|
|
115579
|
+
if (typeof args.computer === "string" && args.computer.trim()) {
|
|
115580
|
+
let environmentRouting = false;
|
|
115581
|
+
try {
|
|
115582
|
+
environmentRouting = getBackend().capabilities.environmentRouting;
|
|
115583
|
+
} catch {
|
|
115584
|
+
environmentRouting = false;
|
|
115585
|
+
}
|
|
115586
|
+
if (!environmentRouting) {
|
|
115587
|
+
return "Error: The computer option requires a Letta Cloud backend. This backend has no connected computers; omit the computer field to run the subagent on the current machine.";
|
|
115588
|
+
}
|
|
115589
|
+
}
|
|
115528
115590
|
let effectiveAgentId = args.agent_id;
|
|
115529
115591
|
let effectiveConversationId = args.conversation_id;
|
|
115530
115592
|
if (config.fork) {
|
|
@@ -118106,6 +118168,21 @@ ${WINDOWS_UNIFIED_EXEC_GUIDANCE}`;
|
|
|
118106
118168
|
|
|
118107
118169
|
// src/tools/memory-tool-assets.ts
|
|
118108
118170
|
async function resolveBackendSpecificToolAssets(name, description, inputSchema) {
|
|
118171
|
+
if (name === "Task") {
|
|
118172
|
+
let environmentRouting = false;
|
|
118173
|
+
try {
|
|
118174
|
+
environmentRouting = getBackend().capabilities.environmentRouting;
|
|
118175
|
+
} catch {
|
|
118176
|
+
environmentRouting = false;
|
|
118177
|
+
}
|
|
118178
|
+
if (!environmentRouting) {
|
|
118179
|
+
return {
|
|
118180
|
+
description: stripComputerFromTaskDescription(description),
|
|
118181
|
+
inputSchema: stripComputerFromTaskSchema(inputSchema)
|
|
118182
|
+
};
|
|
118183
|
+
}
|
|
118184
|
+
return { description, inputSchema };
|
|
118185
|
+
}
|
|
118109
118186
|
let isLocalMemfs = false;
|
|
118110
118187
|
try {
|
|
118111
118188
|
isLocalMemfs = getBackend().capabilities.localMemfs;
|
|
@@ -125779,7 +125856,7 @@ async function applyMemfsFlags(agentId, memfsFlag, options) {
|
|
|
125779
125856
|
};
|
|
125780
125857
|
}
|
|
125781
125858
|
async function isLettaCloud() {
|
|
125782
|
-
const { getServerUrl: getServerUrl2 } = await Promise.resolve().then(() => (
|
|
125859
|
+
const { getServerUrl: getServerUrl2 } = await Promise.resolve().then(() => (init_server_url(), exports_server_url));
|
|
125783
125860
|
const serverUrl = getServerUrl2();
|
|
125784
125861
|
return serverUrl.includes("api.letta.com") || process.env.LETTA_MEMFS_LOCAL === "1" || process.env.LETTA_API_KEY === "local-desktop";
|
|
125785
125862
|
}
|
|
@@ -130984,6 +131061,7 @@ var init_local_provider_errors = __esm(() => {
|
|
|
130984
131061
|
var exports_fake_headless_backend = {};
|
|
130985
131062
|
__export(exports_fake_headless_backend, {
|
|
130986
131063
|
HeadlessBackend: () => HeadlessBackend,
|
|
131064
|
+
HEADLESS_BACKEND_CAPABILITIES: () => HEADLESS_BACKEND_CAPABILITIES,
|
|
130987
131065
|
FakeHeadlessBackend: () => HeadlessBackend
|
|
130988
131066
|
});
|
|
130989
131067
|
function createPage(items3) {
|
|
@@ -131077,16 +131155,7 @@ function isTerminalRun(run) {
|
|
|
131077
131155
|
}
|
|
131078
131156
|
|
|
131079
131157
|
class HeadlessBackend {
|
|
131080
|
-
capabilities =
|
|
131081
|
-
remoteMemfs: false,
|
|
131082
|
-
serverSideToolManagement: false,
|
|
131083
|
-
serverSecrets: false,
|
|
131084
|
-
agentFileImportExport: false,
|
|
131085
|
-
promptRecompile: false,
|
|
131086
|
-
byokProviderRefresh: false,
|
|
131087
|
-
localModelCatalog: true,
|
|
131088
|
-
localMemfs: false
|
|
131089
|
-
};
|
|
131158
|
+
capabilities = HEADLESS_BACKEND_CAPABILITIES;
|
|
131090
131159
|
store;
|
|
131091
131160
|
executor;
|
|
131092
131161
|
runs = new Map;
|
|
@@ -131462,13 +131531,24 @@ class HeadlessBackend {
|
|
|
131462
131531
|
};
|
|
131463
131532
|
}
|
|
131464
131533
|
}
|
|
131465
|
-
var FAKE_HEADLESS_MODEL = "dev/fake-headless";
|
|
131534
|
+
var FAKE_HEADLESS_MODEL = "dev/fake-headless", HEADLESS_BACKEND_CAPABILITIES;
|
|
131466
131535
|
var init_fake_headless_backend = __esm(() => {
|
|
131467
131536
|
init_model_handles();
|
|
131468
131537
|
init_local_store();
|
|
131469
131538
|
init_local_stream_chunks();
|
|
131470
131539
|
init_constants2();
|
|
131471
131540
|
init_local_provider_errors();
|
|
131541
|
+
HEADLESS_BACKEND_CAPABILITIES = {
|
|
131542
|
+
remoteMemfs: false,
|
|
131543
|
+
serverSideToolManagement: false,
|
|
131544
|
+
serverSecrets: false,
|
|
131545
|
+
agentFileImportExport: false,
|
|
131546
|
+
promptRecompile: false,
|
|
131547
|
+
byokProviderRefresh: false,
|
|
131548
|
+
localModelCatalog: true,
|
|
131549
|
+
localMemfs: false,
|
|
131550
|
+
environmentRouting: false
|
|
131551
|
+
};
|
|
131472
131552
|
});
|
|
131473
131553
|
|
|
131474
131554
|
// src/backend/dev/headless-backend.ts
|
|
@@ -135121,13 +135201,8 @@ var init_local_backend = __esm(() => {
|
|
|
135121
135201
|
init_system_prompt_compilation();
|
|
135122
135202
|
LocalBackend = class LocalBackend extends HeadlessBackend {
|
|
135123
135203
|
capabilities = {
|
|
135124
|
-
|
|
135125
|
-
serverSideToolManagement: false,
|
|
135126
|
-
serverSecrets: false,
|
|
135127
|
-
agentFileImportExport: false,
|
|
135204
|
+
...HEADLESS_BACKEND_CAPABILITIES,
|
|
135128
135205
|
promptRecompile: true,
|
|
135129
|
-
byokProviderRefresh: false,
|
|
135130
|
-
localModelCatalog: true,
|
|
135131
135206
|
localMemfs: true
|
|
135132
135207
|
};
|
|
135133
135208
|
memoryDir;
|
|
@@ -135554,16 +135629,19 @@ function toApiConversationMessageListBody(body) {
|
|
|
135554
135629
|
}
|
|
135555
135630
|
|
|
135556
135631
|
class APIBackend {
|
|
135557
|
-
capabilities
|
|
135558
|
-
|
|
135559
|
-
|
|
135560
|
-
|
|
135561
|
-
|
|
135562
|
-
|
|
135563
|
-
|
|
135564
|
-
|
|
135565
|
-
|
|
135566
|
-
|
|
135632
|
+
get capabilities() {
|
|
135633
|
+
return {
|
|
135634
|
+
remoteMemfs: true,
|
|
135635
|
+
serverSideToolManagement: true,
|
|
135636
|
+
serverSecrets: true,
|
|
135637
|
+
agentFileImportExport: true,
|
|
135638
|
+
promptRecompile: true,
|
|
135639
|
+
byokProviderRefresh: true,
|
|
135640
|
+
localModelCatalog: false,
|
|
135641
|
+
localMemfs: false,
|
|
135642
|
+
environmentRouting: isCloudServerUrl()
|
|
135643
|
+
};
|
|
135644
|
+
}
|
|
135567
135645
|
getApiClientOverride;
|
|
135568
135646
|
forkConversationOverride;
|
|
135569
135647
|
constructor(deps = {}) {
|
|
@@ -135785,6 +135863,7 @@ function __testSetBackend(nextBackend) {
|
|
|
135785
135863
|
}
|
|
135786
135864
|
var DEFAULT_CONVERSATION_MESSAGE_ORDER = "desc", backend = null;
|
|
135787
135865
|
var init_backend = __esm(() => {
|
|
135866
|
+
init_server_url();
|
|
135788
135867
|
init_backend_mode();
|
|
135789
135868
|
init_local_backend();
|
|
135790
135869
|
init_paths();
|
|
@@ -432086,7 +432165,7 @@ var init_mcp_client = __esm(() => {
|
|
|
432086
432165
|
init_streamableHttp();
|
|
432087
432166
|
DEFAULT_CLIENT_INFO = {
|
|
432088
432167
|
name: "letta-code",
|
|
432089
|
-
version: "0.31.
|
|
432168
|
+
version: "0.31.10"
|
|
432090
432169
|
};
|
|
432091
432170
|
});
|
|
432092
432171
|
|
|
@@ -445283,8 +445362,8 @@ async function startDockerVersionCheck() {
|
|
|
445283
445362
|
}
|
|
445284
445363
|
var MINIMUM_DOCKER_VERSION = "0.16.6";
|
|
445285
445364
|
var init_startup_docker_check = __esm(() => {
|
|
445286
|
-
init_client2();
|
|
445287
445365
|
init_health();
|
|
445366
|
+
init_server_url();
|
|
445288
445367
|
});
|
|
445289
445368
|
|
|
445290
445369
|
// src/agent/bootstrap-tools.ts
|
|
@@ -446917,7 +446996,7 @@ async function ensureDefaultAgents(backend3, options) {
|
|
|
446917
446996
|
}
|
|
446918
446997
|
var MEMO_TAG = "default:memo", TUTOR_TAG = "default:tutorial", MEMO_PERSONA, MEMO_HUMAN, MEMO_DESCRIPTION = "The default Letta Code agent with persistent memory", DEFAULT_AGENT_CONFIGS;
|
|
446919
446998
|
var init_defaults = __esm(() => {
|
|
446920
|
-
|
|
446999
|
+
init_server_url();
|
|
446921
447000
|
init_settings_manager();
|
|
446922
447001
|
init_create5();
|
|
446923
447002
|
init_memory();
|
|
@@ -468917,6 +468996,7 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
468917
468996
|
init_agents7();
|
|
468918
468997
|
init_client2();
|
|
468919
468998
|
init_request();
|
|
468999
|
+
init_server_url();
|
|
468920
469000
|
init_context_usage();
|
|
468921
469001
|
init_local_memory_context();
|
|
468922
469002
|
init_memory_viewer_template();
|
|
@@ -497893,7 +497973,7 @@ var init_use_conversation_switching = __esm(async () => {
|
|
|
497893
497973
|
init_create5();
|
|
497894
497974
|
init_defaults();
|
|
497895
497975
|
init_backend2();
|
|
497896
|
-
|
|
497976
|
+
init_server_url();
|
|
497897
497977
|
init_app_urls();
|
|
497898
497978
|
init_backfill();
|
|
497899
497979
|
init_error_formatter();
|
|
@@ -512915,4 +512995,4 @@ function registerBunOAuthFlows() {
|
|
|
512915
512995
|
registerBunOAuthFlows();
|
|
512916
512996
|
await init_src5().then(() => exports_src2);
|
|
512917
512997
|
|
|
512918
|
-
//# debugId=
|
|
512998
|
+
//# debugId=39DF2EA197BB152964756E2164756E21
|