@letta-ai/letta-code 0.24.5 → 0.24.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/letta.js +609 -237
- package/package.json +1 -1
- package/skills/configuring-your-harness/SKILL.md +242 -0
- package/skills/configuring-your-harness/references/hooks.md +261 -0
- package/skills/modifying-letta-code/SKILL.md +0 -270
- /package/skills/{modifying-letta-code → configuring-your-harness}/scripts/add_hook.py +0 -0
- /package/skills/{modifying-letta-code → configuring-your-harness}/scripts/add_permission.py +0 -0
- /package/skills/{modifying-letta-code → configuring-your-harness}/scripts/show_config.py +0 -0
package/letta.js
CHANGED
|
@@ -3269,7 +3269,7 @@ var package_default;
|
|
|
3269
3269
|
var init_package = __esm(() => {
|
|
3270
3270
|
package_default = {
|
|
3271
3271
|
name: "@letta-ai/letta-code",
|
|
3272
|
-
version: "0.24.
|
|
3272
|
+
version: "0.24.7",
|
|
3273
3273
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3274
3274
|
type: "module",
|
|
3275
3275
|
bin: {
|
|
@@ -4721,13 +4721,14 @@ var init_timing = __esm(() => {
|
|
|
4721
4721
|
// src/agent/client.ts
|
|
4722
4722
|
var exports_client = {};
|
|
4723
4723
|
__export(exports_client, {
|
|
4724
|
-
isDesktopLocalProxyUrl: () => isDesktopLocalProxyUrl,
|
|
4725
4724
|
getServerUrl: () => getServerUrl,
|
|
4726
4725
|
getMemfsServerUrl: () => getMemfsServerUrl,
|
|
4726
|
+
getMemfsGitProxyRewriteConfig: () => getMemfsGitProxyRewriteConfig,
|
|
4727
4727
|
getClient: () => getClient,
|
|
4728
4728
|
consumeLastSDKDiagnostic: () => consumeLastSDKDiagnostic,
|
|
4729
4729
|
clearLastSDKDiagnostic: () => clearLastSDKDiagnostic,
|
|
4730
|
-
__testOverrideGetClient: () => __testOverrideGetClient
|
|
4730
|
+
__testOverrideGetClient: () => __testOverrideGetClient,
|
|
4731
|
+
LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV: () => LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV
|
|
4731
4732
|
});
|
|
4732
4733
|
import { hostname } from "node:os";
|
|
4733
4734
|
function __testOverrideGetClient(factory) {
|
|
@@ -4785,8 +4786,29 @@ function isLocalhostUrl(value) {
|
|
|
4785
4786
|
return false;
|
|
4786
4787
|
}
|
|
4787
4788
|
}
|
|
4788
|
-
function
|
|
4789
|
-
return
|
|
4789
|
+
function trimBaseUrl(value) {
|
|
4790
|
+
return value.trim().replace(/\/+$/, "");
|
|
4791
|
+
}
|
|
4792
|
+
function getMemfsGitProxyRewriteConfig(env = process.env) {
|
|
4793
|
+
const rawProxyBaseUrl = env[LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV]?.trim();
|
|
4794
|
+
if (!rawProxyBaseUrl || !isLocalhostUrl(rawProxyBaseUrl)) {
|
|
4795
|
+
return null;
|
|
4796
|
+
}
|
|
4797
|
+
const memfsBaseUrl = trimBaseUrl(getMemfsServerUrl());
|
|
4798
|
+
if (!memfsBaseUrl.includes("api.letta.com")) {
|
|
4799
|
+
return null;
|
|
4800
|
+
}
|
|
4801
|
+
const proxyBaseUrl = trimBaseUrl(rawProxyBaseUrl);
|
|
4802
|
+
const proxyPrefix = `${proxyBaseUrl}/v1/git/`;
|
|
4803
|
+
const memfsPrefix = `${memfsBaseUrl}/v1/git/`;
|
|
4804
|
+
return {
|
|
4805
|
+
proxyBaseUrl,
|
|
4806
|
+
memfsBaseUrl,
|
|
4807
|
+
proxyPrefix,
|
|
4808
|
+
memfsPrefix,
|
|
4809
|
+
configKey: `url.${proxyPrefix}.insteadOf`,
|
|
4810
|
+
configValue: memfsPrefix
|
|
4811
|
+
};
|
|
4790
4812
|
}
|
|
4791
4813
|
function getMemfsServerUrl() {
|
|
4792
4814
|
let settings = null;
|
|
@@ -4797,10 +4819,6 @@ function getMemfsServerUrl() {
|
|
|
4797
4819
|
if (configuredMemfsUrl) {
|
|
4798
4820
|
return configuredMemfsUrl;
|
|
4799
4821
|
}
|
|
4800
|
-
const apiUrl = process.env.LETTA_BASE_URL || settings?.env?.LETTA_BASE_URL;
|
|
4801
|
-
if (apiUrl && isDesktopLocalProxyUrl(apiUrl)) {
|
|
4802
|
-
return apiUrl;
|
|
4803
|
-
}
|
|
4804
4822
|
return LETTA_CLOUD_API_URL;
|
|
4805
4823
|
}
|
|
4806
4824
|
async function getClient() {
|
|
@@ -4876,7 +4894,7 @@ If you experience this issue multiple times, move ~/.letta to ~/.letta_backup, a
|
|
|
4876
4894
|
...isTimingsEnabled() && { fetch: createTimingFetch(fetch) }
|
|
4877
4895
|
});
|
|
4878
4896
|
}
|
|
4879
|
-
var SDK_DIAGNOSTIC_MAX_LEN = 400, SDK_DIAGNOSTIC_MAX_LINES = 4, lastSDKDiagnostic = null, _cachedApiKey, _testClientOverride = null, sdkLogger;
|
|
4897
|
+
var SDK_DIAGNOSTIC_MAX_LEN = 400, SDK_DIAGNOSTIC_MAX_LINES = 4, lastSDKDiagnostic = null, _cachedApiKey, _testClientOverride = null, sdkLogger, LETTA_MEMFS_GIT_PROXY_BASE_URL_ENV = "LETTA_MEMFS_GIT_PROXY_BASE_URL";
|
|
4880
4898
|
var init_client2 = __esm(() => {
|
|
4881
4899
|
init_letta_client();
|
|
4882
4900
|
init_package();
|
|
@@ -38537,6 +38555,7 @@ var init_create = __esm(() => {
|
|
|
38537
38555
|
var exports_memoryGit = {};
|
|
38538
38556
|
__export(exports_memoryGit, {
|
|
38539
38557
|
unsetMemoryRepositoryUrl: () => unsetMemoryRepositoryUrl,
|
|
38558
|
+
shouldConfigurePersistentMemfsCredentialHelper: () => shouldConfigurePersistentMemfsCredentialHelper,
|
|
38540
38559
|
setMemoryRepositoryUrl: () => setMemoryRepositoryUrl,
|
|
38541
38560
|
removeGitMemoryTag: () => removeGitMemoryTag,
|
|
38542
38561
|
readMemoryRepositoryPushLog: () => readMemoryRepositoryPushLog,
|
|
@@ -38548,6 +38567,7 @@ __export(exports_memoryGit, {
|
|
|
38548
38567
|
isRetryableGitTransientError: () => isRetryableGitTransientError,
|
|
38549
38568
|
isMissingCwdGitError: () => isMissingCwdGitError,
|
|
38550
38569
|
isMemfsRemoteUrlForAgent: () => isMemfsRemoteUrlForAgent,
|
|
38570
|
+
isMemfsGitNetworkCommand: () => isMemfsGitNetworkCommand,
|
|
38551
38571
|
isGitRepo: () => isGitRepo,
|
|
38552
38572
|
getMemoryRepositoryUrl: () => getMemoryRepositoryUrl,
|
|
38553
38573
|
getMemoryRepoDir: () => getMemoryRepoDir,
|
|
@@ -38559,6 +38579,7 @@ __export(exports_memoryGit, {
|
|
|
38559
38579
|
commitAndSyncMemoryWrite: () => commitAndSyncMemoryWrite,
|
|
38560
38580
|
cloneMemoryRepo: () => cloneMemoryRepo,
|
|
38561
38581
|
buildNonInteractiveGitEnv: () => buildNonInteractiveGitEnv,
|
|
38582
|
+
buildMemfsGitProxyArgs: () => buildMemfsGitProxyArgs,
|
|
38562
38583
|
buildGitAuthArgs: () => buildGitAuthArgs,
|
|
38563
38584
|
assertMemoryRepoReadyForWrite: () => assertMemoryRepoReadyForWrite,
|
|
38564
38585
|
addGitMemoryTag: () => addGitMemoryTag,
|
|
@@ -38679,6 +38700,22 @@ function buildGitAuthArgs(token) {
|
|
|
38679
38700
|
`http.extraHeader=Authorization: Basic ${Buffer.from(`letta:${token}`).toString("base64")}`
|
|
38680
38701
|
];
|
|
38681
38702
|
}
|
|
38703
|
+
function isMemfsGitNetworkCommand(args) {
|
|
38704
|
+
return ["clone", "fetch", "pull", "push"].includes(args[0] ?? "");
|
|
38705
|
+
}
|
|
38706
|
+
function buildMemfsGitProxyArgs(args, env3 = process.env) {
|
|
38707
|
+
if (!isMemfsGitNetworkCommand(args)) {
|
|
38708
|
+
return [];
|
|
38709
|
+
}
|
|
38710
|
+
const rewrite = getMemfsGitProxyRewriteConfig(env3);
|
|
38711
|
+
if (!rewrite) {
|
|
38712
|
+
return [];
|
|
38713
|
+
}
|
|
38714
|
+
return ["-c", `${rewrite.configKey}=${rewrite.configValue}`];
|
|
38715
|
+
}
|
|
38716
|
+
function shouldConfigurePersistentMemfsCredentialHelper(env3 = process.env) {
|
|
38717
|
+
return getMemfsGitProxyRewriteConfig(env3) === null;
|
|
38718
|
+
}
|
|
38682
38719
|
function buildNonInteractiveGitEnv(env3 = process.env) {
|
|
38683
38720
|
return {
|
|
38684
38721
|
...env3,
|
|
@@ -38690,7 +38727,7 @@ function buildNonInteractiveGitEnv(env3 = process.env) {
|
|
|
38690
38727
|
}
|
|
38691
38728
|
async function runGit(cwd2, args, token) {
|
|
38692
38729
|
const authArgs = token ? buildGitAuthArgs(token) : [];
|
|
38693
|
-
const allArgs = [...authArgs, ...args];
|
|
38730
|
+
const allArgs = [...buildMemfsGitProxyArgs(args), ...authArgs, ...args];
|
|
38694
38731
|
let loggableArgs = args;
|
|
38695
38732
|
if (args[0] === "config" && typeof args[1] === "string" && args[1].includes("credential") && args[1].includes(".helper")) {
|
|
38696
38733
|
loggableArgs = [args[0], args[1], "<redacted>"];
|
|
@@ -38754,6 +38791,11 @@ async function runGitWithRetry(cwd2, args, token, options) {
|
|
|
38754
38791
|
async function configureLocalCredentialHelper(dir, token) {
|
|
38755
38792
|
const rawBaseUrl = getMemfsServerUrl();
|
|
38756
38793
|
const normalizedBaseUrl = normalizeCredentialBaseUrl(rawBaseUrl);
|
|
38794
|
+
if (!shouldConfigurePersistentMemfsCredentialHelper()) {
|
|
38795
|
+
await clearLocalCredentialHelper(dir, rawBaseUrl, normalizedBaseUrl);
|
|
38796
|
+
debugLog("memfs-git", `Skipped persistent credential helper for ${normalizedBaseUrl}; using transient MemFS git proxy transport`);
|
|
38797
|
+
return;
|
|
38798
|
+
}
|
|
38757
38799
|
let helper;
|
|
38758
38800
|
if (platform2() === "win32") {
|
|
38759
38801
|
const helperScriptPath = join7(dir, ".git", "letta-credential-helper.cmd");
|
|
@@ -38777,6 +38819,17 @@ echo password=${token}
|
|
|
38777
38819
|
}
|
|
38778
38820
|
debugLog("memfs-git", `Configured local credential helper for ${normalizedBaseUrl}${rawBaseUrl !== normalizedBaseUrl ? ` (and raw ${rawBaseUrl})` : ""}`);
|
|
38779
38821
|
}
|
|
38822
|
+
async function clearLocalCredentialHelper(dir, rawBaseUrl, normalizedBaseUrl) {
|
|
38823
|
+
const keys = new Set([
|
|
38824
|
+
`credential.${normalizedBaseUrl}.helper`,
|
|
38825
|
+
`credential.${rawBaseUrl}.helper`
|
|
38826
|
+
]);
|
|
38827
|
+
for (const key of keys) {
|
|
38828
|
+
try {
|
|
38829
|
+
await runGit(dir, ["config", "--local", "--unset-all", key]);
|
|
38830
|
+
} catch {}
|
|
38831
|
+
}
|
|
38832
|
+
}
|
|
38780
38833
|
function installPreCommitHook(dir) {
|
|
38781
38834
|
const hooksDir = join7(dir, ".git", "hooks");
|
|
38782
38835
|
const hookPath = join7(hooksDir, "pre-commit");
|
|
@@ -39027,6 +39080,32 @@ async function fetchMemoryRemote(memoryDir, token) {
|
|
|
39027
39080
|
operation: "fetch origin"
|
|
39028
39081
|
});
|
|
39029
39082
|
}
|
|
39083
|
+
async function getMemoryAheadBehind(memoryDir) {
|
|
39084
|
+
try {
|
|
39085
|
+
const { stdout } = await runGit(memoryDir, [
|
|
39086
|
+
"rev-list",
|
|
39087
|
+
"--left-right",
|
|
39088
|
+
"--count",
|
|
39089
|
+
"HEAD...@{u}"
|
|
39090
|
+
]);
|
|
39091
|
+
const [aheadRaw, behindRaw] = stdout.trim().split(/\s+/);
|
|
39092
|
+
return {
|
|
39093
|
+
ahead: Number.parseInt(aheadRaw ?? "0", 10) || 0,
|
|
39094
|
+
behind: Number.parseInt(behindRaw ?? "0", 10) || 0
|
|
39095
|
+
};
|
|
39096
|
+
} catch {
|
|
39097
|
+
return null;
|
|
39098
|
+
}
|
|
39099
|
+
}
|
|
39100
|
+
async function pushCleanPendingMemoryCommitsForWrite(memoryDir, agentId, token) {
|
|
39101
|
+
await prepareMemoryRepoForGitOps(memoryDir, agentId, token);
|
|
39102
|
+
const divergence = await getMemoryAheadBehind(memoryDir);
|
|
39103
|
+
if (divergence && divergence.ahead > 0) {
|
|
39104
|
+
await runGitWithRetry(memoryDir, ["push"], token, {
|
|
39105
|
+
operation: "push pending memory commits"
|
|
39106
|
+
});
|
|
39107
|
+
}
|
|
39108
|
+
}
|
|
39030
39109
|
async function resetMemoryToUpstream(memoryDir, token) {
|
|
39031
39110
|
await runGit(memoryDir, ["reset", "--hard", "@{u}"], token);
|
|
39032
39111
|
}
|
|
@@ -39092,19 +39171,18 @@ async function recoverMemoryPushConflict(params, token, initialSha) {
|
|
|
39092
39171
|
rescueRef
|
|
39093
39172
|
};
|
|
39094
39173
|
}
|
|
39095
|
-
async function assertMemoryRepoReadyForWrite(memoryDir) {
|
|
39174
|
+
async function assertMemoryRepoReadyForWrite(memoryDir, agentId) {
|
|
39096
39175
|
const status = await runGit(memoryDir, ["status", "--porcelain"]);
|
|
39097
39176
|
if (status.stdout.trim().length > 0) {
|
|
39098
39177
|
throw new Error("Memory repo has uncommitted changes. Commit, discard, or sync them before using memory tools.");
|
|
39099
39178
|
}
|
|
39179
|
+
if (agentId) {
|
|
39180
|
+
const token = await getAuthToken();
|
|
39181
|
+
await pushCleanPendingMemoryCommitsForWrite(memoryDir, agentId, token);
|
|
39182
|
+
}
|
|
39100
39183
|
try {
|
|
39101
|
-
const
|
|
39102
|
-
|
|
39103
|
-
"--count",
|
|
39104
|
-
"@{u}..HEAD"
|
|
39105
|
-
]);
|
|
39106
|
-
const aheadCount = parseInt(stdout.trim(), 10);
|
|
39107
|
-
if (aheadCount > 0) {
|
|
39184
|
+
const divergence = await getMemoryAheadBehind(memoryDir);
|
|
39185
|
+
if (divergence && divergence.ahead > 0) {
|
|
39108
39186
|
throw new Error("Memory repo has local commits that are not pushed to remote. Sync the repo before using memory tools.");
|
|
39109
39187
|
}
|
|
39110
39188
|
} catch (error) {
|
|
@@ -49253,9 +49331,9 @@ function getServerHostLabel(serverUrl) {
|
|
|
49253
49331
|
}
|
|
49254
49332
|
}
|
|
49255
49333
|
async function isLettaMemfsServer() {
|
|
49256
|
-
const { getMemfsServerUrl: getMemfsServerUrl2
|
|
49334
|
+
const { getMemfsServerUrl: getMemfsServerUrl2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
49257
49335
|
const memfsServerUrl = getMemfsServerUrl2();
|
|
49258
|
-
return memfsServerUrl.includes("api.letta.com") ||
|
|
49336
|
+
return memfsServerUrl.includes("api.letta.com") || process.env.LETTA_MEMFS_LOCAL === "1" || process.env.LETTA_API_KEY === "local-desktop";
|
|
49259
49337
|
}
|
|
49260
49338
|
async function getMemfsSyncUnavailableMessage() {
|
|
49261
49339
|
const { getMemfsServerUrl: getMemfsServerUrl2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
@@ -54655,6 +54733,24 @@ exec ${commandWithArgs} "$@"
|
|
|
54655
54733
|
});
|
|
54656
54734
|
return shimDir;
|
|
54657
54735
|
}
|
|
54736
|
+
function appendGitConfigEnv(env3, key, value) {
|
|
54737
|
+
const rawCount = env3.GIT_CONFIG_COUNT;
|
|
54738
|
+
const count = rawCount && /^\d+$/.test(rawCount) ? Number(rawCount) : 0;
|
|
54739
|
+
env3[`GIT_CONFIG_KEY_${count}`] = key;
|
|
54740
|
+
env3[`GIT_CONFIG_VALUE_${count}`] = value;
|
|
54741
|
+
env3.GIT_CONFIG_COUNT = String(count + 1);
|
|
54742
|
+
}
|
|
54743
|
+
function applyMemfsGitProxyEnv(env3) {
|
|
54744
|
+
const rewrite = getMemfsGitProxyRewriteConfig(env3);
|
|
54745
|
+
if (!rewrite) {
|
|
54746
|
+
return;
|
|
54747
|
+
}
|
|
54748
|
+
appendGitConfigEnv(env3, rewrite.configKey, rewrite.configValue);
|
|
54749
|
+
env3.GIT_TERMINAL_PROMPT = "0";
|
|
54750
|
+
env3.GCM_INTERACTIVE = "never";
|
|
54751
|
+
env3.GIT_ASKPASS = "";
|
|
54752
|
+
env3.SSH_ASKPASS = "";
|
|
54753
|
+
}
|
|
54658
54754
|
function getShellEnv() {
|
|
54659
54755
|
const env3 = { ...process.env };
|
|
54660
54756
|
const pathKey = Object.keys(env3).find((k) => k.toUpperCase() === "PATH") || "PATH";
|
|
@@ -54742,6 +54838,7 @@ function getShellEnv() {
|
|
|
54742
54838
|
if (!env3.TERM) {
|
|
54743
54839
|
env3.TERM = "xterm-256color";
|
|
54744
54840
|
}
|
|
54841
|
+
applyMemfsGitProxyEnv(env3);
|
|
54745
54842
|
return env3;
|
|
54746
54843
|
}
|
|
54747
54844
|
var LETTA_BIN_ARGS_ENV = "LETTA_CODE_BIN_ARGS_JSON";
|
|
@@ -56563,14 +56660,14 @@ async function memory(args) {
|
|
|
56563
56660
|
}
|
|
56564
56661
|
const memoryDir = resolveMemoryDir();
|
|
56565
56662
|
ensureMemoryRepo(memoryDir);
|
|
56566
|
-
await
|
|
56663
|
+
const { agentId, agentName } = await getAgentIdentity();
|
|
56664
|
+
await assertMemoryRepoReadyForWrite(memoryDir, agentId);
|
|
56567
56665
|
const affectedPaths = await applyMemoryCommand(memoryDir, args);
|
|
56568
56666
|
if (affectedPaths.length === 0) {
|
|
56569
56667
|
return {
|
|
56570
56668
|
message: `Memory ${args.command} completed with no changed paths.`
|
|
56571
56669
|
};
|
|
56572
56670
|
}
|
|
56573
|
-
const { agentId, agentName } = await getAgentIdentity();
|
|
56574
56671
|
const commitResult = await commitAndSyncMemoryWrite({
|
|
56575
56672
|
memoryDir,
|
|
56576
56673
|
pathspecs: affectedPaths,
|
|
@@ -56948,12 +57045,12 @@ async function memory_apply_patch(args) {
|
|
|
56948
57045
|
}
|
|
56949
57046
|
const memoryDir = resolveMemoryDir2();
|
|
56950
57047
|
ensureMemoryRepo2(memoryDir);
|
|
56951
|
-
await
|
|
57048
|
+
const { agentId, agentName } = await getAgentIdentity2();
|
|
57049
|
+
await assertMemoryRepoReadyForWrite(memoryDir, agentId);
|
|
56952
57050
|
const pathspecs = await applyMemoryPatch(memoryDir, input);
|
|
56953
57051
|
if (pathspecs.length === 0) {
|
|
56954
57052
|
return { message: "memory_apply_patch completed with no changed paths." };
|
|
56955
57053
|
}
|
|
56956
|
-
const { agentId, agentName } = await getAgentIdentity2();
|
|
56957
57054
|
const commitResult = await commitAndSyncMemoryWrite({
|
|
56958
57055
|
memoryDir,
|
|
56959
57056
|
pathspecs,
|
|
@@ -72351,6 +72448,15 @@ Results include:
|
|
|
72351
72448
|
`;
|
|
72352
72449
|
var init_recall_subagent = () => {};
|
|
72353
72450
|
|
|
72451
|
+
// src/agent/subagents/contextBudget.ts
|
|
72452
|
+
function estimateStartupContextTokens(text) {
|
|
72453
|
+
return Math.ceil(text.length / STARTUP_CONTEXT_ESTIMATED_CHARS_PER_TOKEN);
|
|
72454
|
+
}
|
|
72455
|
+
var STARTUP_CONTEXT_ESTIMATED_CHARS_PER_TOKEN = 4, REFLECTION_STARTUP_CONTEXT_TOKEN_LIMIT = 16000, REFLECTION_STARTUP_CONTEXT_CHAR_LIMIT, REFLECTION_PARENT_MEMORY_SNAPSHOT_CHAR_LIMIT = 40000;
|
|
72456
|
+
var init_contextBudget = __esm(() => {
|
|
72457
|
+
REFLECTION_STARTUP_CONTEXT_CHAR_LIMIT = REFLECTION_STARTUP_CONTEXT_TOKEN_LIMIT * STARTUP_CONTEXT_ESTIMATED_CHARS_PER_TOKEN;
|
|
72458
|
+
});
|
|
72459
|
+
|
|
72354
72460
|
// src/agent/subagents/manager.ts
|
|
72355
72461
|
import { spawn as spawn5 } from "node:child_process";
|
|
72356
72462
|
function getModelHandleFromAgent(agent) {
|
|
@@ -72668,6 +72774,68 @@ function composeSubagentChildEnv(options) {
|
|
|
72668
72774
|
}
|
|
72669
72775
|
return childEnv;
|
|
72670
72776
|
}
|
|
72777
|
+
function getReflectionStartupNotice() {
|
|
72778
|
+
return `[Reflection startup context truncated: system prompt + initial message are capped at ~${REFLECTION_STARTUP_CONTEXT_TOKEN_LIMIT.toLocaleString()} estimated tokens. Some parent memory preview content was omitted; read files directly from MEMORY_DIR if needed.]`;
|
|
72779
|
+
}
|
|
72780
|
+
function buildMinimalParentMemorySection(maxChars) {
|
|
72781
|
+
const notice = getReflectionStartupNotice();
|
|
72782
|
+
const section = `<parent_memory>
|
|
72783
|
+
${notice}
|
|
72784
|
+
</parent_memory>`;
|
|
72785
|
+
if (section.length <= maxChars) {
|
|
72786
|
+
return section;
|
|
72787
|
+
}
|
|
72788
|
+
return section.slice(0, Math.max(0, maxChars));
|
|
72789
|
+
}
|
|
72790
|
+
function shrinkParentMemorySection(section, maxChars) {
|
|
72791
|
+
const notice = getReflectionStartupNotice();
|
|
72792
|
+
const treeMatch = section.match(/<memory_filesystem>[\s\S]*?<\/memory_filesystem>/);
|
|
72793
|
+
const prefix = `<parent_memory>
|
|
72794
|
+
`;
|
|
72795
|
+
const suffix = `
|
|
72796
|
+
</parent_memory>`;
|
|
72797
|
+
const tree = treeMatch?.[0];
|
|
72798
|
+
if (tree) {
|
|
72799
|
+
const candidate = `${prefix}${tree}
|
|
72800
|
+
${notice}${suffix}`;
|
|
72801
|
+
if (candidate.length <= maxChars) {
|
|
72802
|
+
return candidate;
|
|
72803
|
+
}
|
|
72804
|
+
}
|
|
72805
|
+
return buildMinimalParentMemorySection(maxChars);
|
|
72806
|
+
}
|
|
72807
|
+
function hardTruncateReflectionPrompt(prompt, maxChars) {
|
|
72808
|
+
const notice = `
|
|
72809
|
+
${getReflectionStartupNotice()}`;
|
|
72810
|
+
if (maxChars <= notice.length) {
|
|
72811
|
+
return notice.slice(0, Math.max(0, maxChars));
|
|
72812
|
+
}
|
|
72813
|
+
return `${prompt.slice(0, maxChars - notice.length).trimEnd()}${notice}`;
|
|
72814
|
+
}
|
|
72815
|
+
function capReflectionStartupPrompt(type, systemPrompt, userPrompt) {
|
|
72816
|
+
if (type !== "reflection") {
|
|
72817
|
+
return userPrompt;
|
|
72818
|
+
}
|
|
72819
|
+
const estimatedTokens = estimateStartupContextTokens(`${systemPrompt}
|
|
72820
|
+
${userPrompt}`);
|
|
72821
|
+
if (estimatedTokens <= REFLECTION_STARTUP_CONTEXT_TOKEN_LIMIT) {
|
|
72822
|
+
return userPrompt;
|
|
72823
|
+
}
|
|
72824
|
+
const allowedPromptChars = Math.max(0, REFLECTION_STARTUP_CONTEXT_CHAR_LIMIT - systemPrompt.length - 1);
|
|
72825
|
+
const parentMemoryMatch = userPrompt.match(/<parent_memory>[\s\S]*?<\/parent_memory>/);
|
|
72826
|
+
if (parentMemoryMatch?.index !== undefined) {
|
|
72827
|
+
const start = parentMemoryMatch.index;
|
|
72828
|
+
const end = start + parentMemoryMatch[0].length;
|
|
72829
|
+
const outsideChars = userPrompt.length - parentMemoryMatch[0].length;
|
|
72830
|
+
const parentMemoryBudget = Math.max(0, allowedPromptChars - outsideChars);
|
|
72831
|
+
const replacement = shrinkParentMemorySection(parentMemoryMatch[0], parentMemoryBudget);
|
|
72832
|
+
const candidate = `${userPrompt.slice(0, start)}${replacement}${userPrompt.slice(end)}`;
|
|
72833
|
+
if (candidate.length <= allowedPromptChars) {
|
|
72834
|
+
return candidate;
|
|
72835
|
+
}
|
|
72836
|
+
}
|
|
72837
|
+
return hardTruncateReflectionPrompt(userPrompt, allowedPromptChars);
|
|
72838
|
+
}
|
|
72671
72839
|
function buildSubagentArgs(type, config, model, userPrompt, existingAgentId, existingConversationId, maxTurns) {
|
|
72672
72840
|
const args = [];
|
|
72673
72841
|
const isDeployingExisting = Boolean(existingAgentId || existingConversationId);
|
|
@@ -72685,7 +72853,8 @@ function buildSubagentArgs(type, config, model, userPrompt, existingAgentId, exi
|
|
|
72685
72853
|
args.push("--model", model);
|
|
72686
72854
|
}
|
|
72687
72855
|
}
|
|
72688
|
-
|
|
72856
|
+
const boundedUserPrompt = capReflectionStartupPrompt(type, config.systemPrompt, userPrompt);
|
|
72857
|
+
args.push("-p", boundedUserPrompt);
|
|
72689
72858
|
args.push("--output-format", "stream-json");
|
|
72690
72859
|
const subagentMode = config.permissionMode;
|
|
72691
72860
|
const parentMode = permissionMode.getMode();
|
|
@@ -72976,6 +73145,7 @@ var init_manager2 = __esm(() => {
|
|
|
72976
73145
|
init_model2();
|
|
72977
73146
|
init_recall_subagent();
|
|
72978
73147
|
init_subagents();
|
|
73148
|
+
init_contextBudget();
|
|
72979
73149
|
BYOK_PROVIDER_TO_BASE = {
|
|
72980
73150
|
"lc-anthropic": "anthropic",
|
|
72981
73151
|
"lc-openai": "openai",
|
|
@@ -77253,11 +77423,14 @@ var init_checker = __esm(() => {
|
|
|
77253
77423
|
var exports_loader = {};
|
|
77254
77424
|
__export(exports_loader, {
|
|
77255
77425
|
savePermissionRule: () => savePermissionRule,
|
|
77426
|
+
resetPermissionLoaderCacheForTests: () => resetPermissionLoaderCacheForTests,
|
|
77256
77427
|
loadPermissions: () => loadPermissions,
|
|
77257
77428
|
getUserSettingsPaths: () => getUserSettingsPaths
|
|
77258
77429
|
});
|
|
77430
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
77431
|
+
import { readFileSync as readFileSync18, statSync as statSync6, watch } from "node:fs";
|
|
77259
77432
|
import { homedir as homedir17 } from "node:os";
|
|
77260
|
-
import { join as join26 } from "node:path";
|
|
77433
|
+
import { dirname as dirname13, join as join26, resolve as resolve25 } from "node:path";
|
|
77261
77434
|
function getUserSettingsPaths(options = {}) {
|
|
77262
77435
|
const homeDir = options.homeDir || homedir17();
|
|
77263
77436
|
const xdgConfigHome = options.xdgConfigHome || process.env.XDG_CONFIG_HOME || join26(homeDir, ".config");
|
|
@@ -77266,20 +77439,127 @@ function getUserSettingsPaths(options = {}) {
|
|
|
77266
77439
|
legacy: join26(xdgConfigHome, "letta", "settings.json")
|
|
77267
77440
|
};
|
|
77268
77441
|
}
|
|
77442
|
+
function getPermissionSourcePaths(workingDirectory) {
|
|
77443
|
+
const { canonical: userSettingsPath, legacy: legacyUserSettingsPath } = getUserSettingsPaths();
|
|
77444
|
+
return [
|
|
77445
|
+
legacyUserSettingsPath,
|
|
77446
|
+
userSettingsPath,
|
|
77447
|
+
join26(workingDirectory, ".letta", "settings.json"),
|
|
77448
|
+
join26(workingDirectory, ".letta", "settings.local.json")
|
|
77449
|
+
];
|
|
77450
|
+
}
|
|
77451
|
+
function getFileSignature(path20) {
|
|
77452
|
+
try {
|
|
77453
|
+
const stat5 = statSync6(path20);
|
|
77454
|
+
if (!stat5.isFile()) {
|
|
77455
|
+
return { exists: false };
|
|
77456
|
+
}
|
|
77457
|
+
return {
|
|
77458
|
+
exists: true,
|
|
77459
|
+
mtimeMs: stat5.mtimeMs,
|
|
77460
|
+
size: stat5.size,
|
|
77461
|
+
hash: createHash3("sha256").update(readFileSync18(path20)).digest("hex")
|
|
77462
|
+
};
|
|
77463
|
+
} catch {
|
|
77464
|
+
return { exists: false };
|
|
77465
|
+
}
|
|
77466
|
+
}
|
|
77467
|
+
function getFileSignatures(paths) {
|
|
77468
|
+
const signatures = new Map;
|
|
77469
|
+
for (const path20 of paths) {
|
|
77470
|
+
signatures.set(path20, getFileSignature(path20));
|
|
77471
|
+
}
|
|
77472
|
+
return signatures;
|
|
77473
|
+
}
|
|
77474
|
+
function signaturesEqual(a, b) {
|
|
77475
|
+
if (!a || !b)
|
|
77476
|
+
return false;
|
|
77477
|
+
if (!a.exists || !b.exists)
|
|
77478
|
+
return a.exists === b.exists;
|
|
77479
|
+
return a.mtimeMs === b.mtimeMs && a.size === b.size && a.hash === b.hash;
|
|
77480
|
+
}
|
|
77481
|
+
function cachedEntryMatchesSources(entry, sources, signatures) {
|
|
77482
|
+
if (entry.sources.length !== sources.length) {
|
|
77483
|
+
return false;
|
|
77484
|
+
}
|
|
77485
|
+
for (let i = 0;i < sources.length; i += 1) {
|
|
77486
|
+
if (entry.sources[i] !== sources[i]) {
|
|
77487
|
+
return false;
|
|
77488
|
+
}
|
|
77489
|
+
}
|
|
77490
|
+
for (const source of sources) {
|
|
77491
|
+
if (!signaturesEqual(entry.signatures.get(source), signatures.get(source))) {
|
|
77492
|
+
return false;
|
|
77493
|
+
}
|
|
77494
|
+
}
|
|
77495
|
+
return true;
|
|
77496
|
+
}
|
|
77497
|
+
function clonePermissions(permissions) {
|
|
77498
|
+
return {
|
|
77499
|
+
allow: [...permissions.allow || []],
|
|
77500
|
+
deny: [...permissions.deny || []],
|
|
77501
|
+
ask: [...permissions.ask || []],
|
|
77502
|
+
additionalDirectories: [...permissions.additionalDirectories || []]
|
|
77503
|
+
};
|
|
77504
|
+
}
|
|
77505
|
+
function invalidatePermissionSource(sourcePath) {
|
|
77506
|
+
for (const [cacheKey, entry] of permissionCache) {
|
|
77507
|
+
if (entry.sources.includes(sourcePath)) {
|
|
77508
|
+
permissionCache.delete(cacheKey);
|
|
77509
|
+
}
|
|
77510
|
+
}
|
|
77511
|
+
}
|
|
77512
|
+
function invalidatePermissionSourcesInDirectory(directoryPath) {
|
|
77513
|
+
for (const [cacheKey, entry] of permissionCache) {
|
|
77514
|
+
if (entry.sources.some((source) => dirname13(source) === directoryPath)) {
|
|
77515
|
+
permissionCache.delete(cacheKey);
|
|
77516
|
+
}
|
|
77517
|
+
}
|
|
77518
|
+
}
|
|
77519
|
+
function watchPath(path20, onChange) {
|
|
77520
|
+
if (watchers.has(path20) || !exists(path20)) {
|
|
77521
|
+
return;
|
|
77522
|
+
}
|
|
77523
|
+
try {
|
|
77524
|
+
const watcher = watch(path20, { persistent: false }, onChange);
|
|
77525
|
+
watcher.on("error", () => {
|
|
77526
|
+
watcher.close();
|
|
77527
|
+
watchers.delete(path20);
|
|
77528
|
+
onChange();
|
|
77529
|
+
});
|
|
77530
|
+
watchers.set(path20, watcher);
|
|
77531
|
+
} catch {}
|
|
77532
|
+
}
|
|
77533
|
+
function ensurePermissionWatchers(sources) {
|
|
77534
|
+
for (const source of sources) {
|
|
77535
|
+
watchPath(source, () => invalidatePermissionSource(source));
|
|
77536
|
+
const directoryPath = dirname13(source);
|
|
77537
|
+
watchPath(directoryPath, () => invalidatePermissionSourcesInDirectory(directoryPath));
|
|
77538
|
+
}
|
|
77539
|
+
}
|
|
77540
|
+
function resetPermissionLoaderCacheForTests() {
|
|
77541
|
+
permissionCache.clear();
|
|
77542
|
+
for (const watcher of watchers.values()) {
|
|
77543
|
+
watcher.close();
|
|
77544
|
+
}
|
|
77545
|
+
watchers.clear();
|
|
77546
|
+
}
|
|
77269
77547
|
async function loadPermissions(workingDirectory = process.cwd()) {
|
|
77548
|
+
const normalizedWorkingDirectory = resolve25(workingDirectory);
|
|
77549
|
+
const sources = getPermissionSourcePaths(normalizedWorkingDirectory);
|
|
77550
|
+
const signatures = getFileSignatures(sources);
|
|
77551
|
+
const cacheKey = normalizedWorkingDirectory;
|
|
77552
|
+
const cached = permissionCache.get(cacheKey);
|
|
77553
|
+
if (cached && cachedEntryMatchesSources(cached, sources, signatures)) {
|
|
77554
|
+
ensurePermissionWatchers(sources);
|
|
77555
|
+
return clonePermissions(cached.permissions);
|
|
77556
|
+
}
|
|
77270
77557
|
const merged = {
|
|
77271
77558
|
allow: [],
|
|
77272
77559
|
deny: [],
|
|
77273
77560
|
ask: [],
|
|
77274
77561
|
additionalDirectories: []
|
|
77275
77562
|
};
|
|
77276
|
-
const { canonical: userSettingsPath, legacy: legacyUserSettingsPath } = getUserSettingsPaths();
|
|
77277
|
-
const sources = [
|
|
77278
|
-
legacyUserSettingsPath,
|
|
77279
|
-
userSettingsPath,
|
|
77280
|
-
join26(workingDirectory, ".letta", "settings.json"),
|
|
77281
|
-
join26(workingDirectory, ".letta", "settings.local.json")
|
|
77282
|
-
];
|
|
77283
77563
|
for (const settingsPath of sources) {
|
|
77284
77564
|
try {
|
|
77285
77565
|
if (exists(settingsPath)) {
|
|
@@ -77291,7 +77571,13 @@ async function loadPermissions(workingDirectory = process.cwd()) {
|
|
|
77291
77571
|
}
|
|
77292
77572
|
} catch (_error) {}
|
|
77293
77573
|
}
|
|
77294
|
-
|
|
77574
|
+
permissionCache.set(cacheKey, {
|
|
77575
|
+
permissions: clonePermissions(merged),
|
|
77576
|
+
sources,
|
|
77577
|
+
signatures
|
|
77578
|
+
});
|
|
77579
|
+
ensurePermissionWatchers(sources);
|
|
77580
|
+
return clonePermissions(merged);
|
|
77295
77581
|
}
|
|
77296
77582
|
function mergePermissions(target, source) {
|
|
77297
77583
|
if (source.allow) {
|
|
@@ -77320,16 +77606,17 @@ function mergeRuleList(existing, incoming) {
|
|
|
77320
77606
|
return merged;
|
|
77321
77607
|
}
|
|
77322
77608
|
async function savePermissionRule(rule, ruleType, scope, workingDirectory = process.cwd()) {
|
|
77609
|
+
const normalizedWorkingDirectory = resolve25(workingDirectory);
|
|
77323
77610
|
let settingsPath;
|
|
77324
77611
|
switch (scope) {
|
|
77325
77612
|
case "user":
|
|
77326
77613
|
settingsPath = getUserSettingsPaths().canonical;
|
|
77327
77614
|
break;
|
|
77328
77615
|
case "project":
|
|
77329
|
-
settingsPath = join26(
|
|
77616
|
+
settingsPath = join26(normalizedWorkingDirectory, ".letta", "settings.json");
|
|
77330
77617
|
break;
|
|
77331
77618
|
case "local":
|
|
77332
|
-
settingsPath = join26(
|
|
77619
|
+
settingsPath = join26(normalizedWorkingDirectory, ".letta", "settings.local.json");
|
|
77333
77620
|
break;
|
|
77334
77621
|
}
|
|
77335
77622
|
let settings = {};
|
|
@@ -77350,8 +77637,9 @@ async function savePermissionRule(rule, ruleType, scope, workingDirectory = proc
|
|
|
77350
77637
|
settings.permissions[ruleType].push(normalizedRule);
|
|
77351
77638
|
}
|
|
77352
77639
|
await writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
77640
|
+
invalidatePermissionSource(settingsPath);
|
|
77353
77641
|
if (scope === "local") {
|
|
77354
|
-
await ensureLocalSettingsIgnored(
|
|
77642
|
+
await ensureLocalSettingsIgnored(normalizedWorkingDirectory);
|
|
77355
77643
|
}
|
|
77356
77644
|
}
|
|
77357
77645
|
async function ensureLocalSettingsIgnored(workingDirectory) {
|
|
@@ -77371,9 +77659,12 @@ async function ensureLocalSettingsIgnored(workingDirectory) {
|
|
|
77371
77659
|
}
|
|
77372
77660
|
} catch (_error) {}
|
|
77373
77661
|
}
|
|
77662
|
+
var permissionCache, watchers;
|
|
77374
77663
|
var init_loader2 = __esm(() => {
|
|
77375
77664
|
init_fs();
|
|
77376
77665
|
init_rule_normalization();
|
|
77666
|
+
permissionCache = new Map;
|
|
77667
|
+
watchers = new Map;
|
|
77377
77668
|
});
|
|
77378
77669
|
|
|
77379
77670
|
// src/permissions/analyzer.ts
|
|
@@ -77382,7 +77673,7 @@ __export(exports_analyzer, {
|
|
|
77382
77673
|
analyzeApprovalContext: () => analyzeApprovalContext
|
|
77383
77674
|
});
|
|
77384
77675
|
import { homedir as homedir18 } from "node:os";
|
|
77385
|
-
import { dirname as
|
|
77676
|
+
import { dirname as dirname14, relative as relative8, resolve as resolve26, win32 as win323 } from "node:path";
|
|
77386
77677
|
function normalizeOsPath(path20) {
|
|
77387
77678
|
return path20.replace(/\\/g, "/");
|
|
77388
77679
|
}
|
|
@@ -77391,7 +77682,7 @@ function isWindowsPath(path20) {
|
|
|
77391
77682
|
}
|
|
77392
77683
|
function resolvePathForContext(basePath, targetPath) {
|
|
77393
77684
|
const windows = isWindowsPath(basePath) || isWindowsPath(targetPath);
|
|
77394
|
-
return windows ? win323.resolve(basePath, targetPath) :
|
|
77685
|
+
return windows ? win323.resolve(basePath, targetPath) : resolve26(basePath, targetPath);
|
|
77395
77686
|
}
|
|
77396
77687
|
function relativePathForContext(basePath, targetPath) {
|
|
77397
77688
|
const windows = isWindowsPath(basePath) || isWindowsPath(targetPath);
|
|
@@ -77408,7 +77699,7 @@ function isPathWithinDirectory(path20, directory) {
|
|
|
77408
77699
|
return !relativePath.startsWith("../") && relativePath !== ".." && !relativePath.startsWith("/") && !/^[a-zA-Z]:\//.test(relativePath);
|
|
77409
77700
|
}
|
|
77410
77701
|
function dirnameForContext(path20) {
|
|
77411
|
-
return isWindowsPath(path20) ? win323.dirname(path20) :
|
|
77702
|
+
return isWindowsPath(path20) ? win323.dirname(path20) : dirname14(path20);
|
|
77412
77703
|
}
|
|
77413
77704
|
function formatAbsoluteRulePath(path20) {
|
|
77414
77705
|
const normalized = normalizeOsPath(path20).replace(/\/+$/, "");
|
|
@@ -77469,7 +77760,7 @@ function analyzeReadApproval(filePath, workingDir) {
|
|
|
77469
77760
|
};
|
|
77470
77761
|
}
|
|
77471
77762
|
const relativePath = normalizeOsPath(relativePathForContext(workingDir, absolutePath));
|
|
77472
|
-
const relativeDir =
|
|
77763
|
+
const relativeDir = dirname14(relativePath);
|
|
77473
77764
|
const pattern = relativeDir === "." || relativeDir === "" ? "**" : `${relativeDir}/**`;
|
|
77474
77765
|
return {
|
|
77475
77766
|
recommendedRule: `Read(${pattern})`,
|
|
@@ -78095,8 +78386,8 @@ function acquireSwitchLock() {
|
|
|
78095
78386
|
const lock = getSwitchLock();
|
|
78096
78387
|
lock.refCount++;
|
|
78097
78388
|
if (lock.refCount === 1) {
|
|
78098
|
-
lock.promise = new Promise((
|
|
78099
|
-
lock.resolve =
|
|
78389
|
+
lock.promise = new Promise((resolve28) => {
|
|
78390
|
+
lock.resolve = resolve28;
|
|
78100
78391
|
});
|
|
78101
78392
|
}
|
|
78102
78393
|
}
|
|
@@ -80151,7 +80442,7 @@ async function generatePKCE() {
|
|
|
80151
80442
|
return { codeVerifier, codeChallenge };
|
|
80152
80443
|
}
|
|
80153
80444
|
function startLocalOAuthServer(expectedState, port = OPENAI_OAUTH_CONFIG.defaultPort) {
|
|
80154
|
-
return new Promise((
|
|
80445
|
+
return new Promise((resolve28, reject) => {
|
|
80155
80446
|
const server = http.createServer((req, res) => {
|
|
80156
80447
|
const url = new URL(req.url || "", `http://localhost:${port}`);
|
|
80157
80448
|
if (url.pathname === OPENAI_OAUTH_CONFIG.callbackPath) {
|
|
@@ -80197,7 +80488,7 @@ function startLocalOAuthServer(expectedState, port = OPENAI_OAUTH_CONFIG.default
|
|
|
80197
80488
|
message: "You can close this window and return to Letta Code.",
|
|
80198
80489
|
autoClose: true
|
|
80199
80490
|
}));
|
|
80200
|
-
|
|
80491
|
+
resolve28({ result: { code, state }, server });
|
|
80201
80492
|
} else {
|
|
80202
80493
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
80203
80494
|
res.end("Not found");
|
|
@@ -80712,14 +81003,14 @@ var execFile11, __dirname2, localXdgOpenPath, platform4, arch, pTryEach = async
|
|
|
80712
81003
|
}
|
|
80713
81004
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
80714
81005
|
if (options.wait) {
|
|
80715
|
-
return new Promise((
|
|
81006
|
+
return new Promise((resolve28, reject) => {
|
|
80716
81007
|
subprocess.once("error", reject);
|
|
80717
81008
|
subprocess.once("close", (exitCode) => {
|
|
80718
81009
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
80719
81010
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
80720
81011
|
return;
|
|
80721
81012
|
}
|
|
80722
|
-
|
|
81013
|
+
resolve28(subprocess);
|
|
80723
81014
|
});
|
|
80724
81015
|
});
|
|
80725
81016
|
}
|
|
@@ -81105,10 +81396,10 @@ import { randomBytes } from "node:crypto";
|
|
|
81105
81396
|
import {
|
|
81106
81397
|
existsSync as existsSync24,
|
|
81107
81398
|
mkdirSync as mkdirSync18,
|
|
81108
|
-
readFileSync as
|
|
81399
|
+
readFileSync as readFileSync19,
|
|
81109
81400
|
renameSync as renameSync2,
|
|
81110
81401
|
rmSync as rmSync2,
|
|
81111
|
-
statSync as
|
|
81402
|
+
statSync as statSync7,
|
|
81112
81403
|
writeFileSync as writeFileSync15
|
|
81113
81404
|
} from "node:fs";
|
|
81114
81405
|
import { join as join27 } from "node:path";
|
|
@@ -81131,7 +81422,7 @@ function readCronFile() {
|
|
|
81131
81422
|
if (!existsSync24(path21))
|
|
81132
81423
|
return emptyFile();
|
|
81133
81424
|
try {
|
|
81134
|
-
const raw =
|
|
81425
|
+
const raw = readFileSync19(path21, "utf-8");
|
|
81135
81426
|
const data = JSON.parse(raw);
|
|
81136
81427
|
if (data.version !== 1)
|
|
81137
81428
|
return emptyFile();
|
|
@@ -81152,7 +81443,7 @@ function writeCronFile(data) {
|
|
|
81152
81443
|
}
|
|
81153
81444
|
function readLinuxProcessIdentity(pid) {
|
|
81154
81445
|
try {
|
|
81155
|
-
const stat5 =
|
|
81446
|
+
const stat5 = readFileSync19(`/proc/${pid}/stat`, "utf8");
|
|
81156
81447
|
const endCommand = stat5.lastIndexOf(")");
|
|
81157
81448
|
if (endCommand === -1) {
|
|
81158
81449
|
return null;
|
|
@@ -81164,7 +81455,7 @@ function readLinuxProcessIdentity(pid) {
|
|
|
81164
81455
|
}
|
|
81165
81456
|
let bootId = null;
|
|
81166
81457
|
try {
|
|
81167
|
-
bootId =
|
|
81458
|
+
bootId = readFileSync19("/proc/sys/kernel/random/boot_id", "utf8").trim() || null;
|
|
81168
81459
|
} catch {}
|
|
81169
81460
|
return { startTicks, bootId };
|
|
81170
81461
|
} catch {
|
|
@@ -81205,7 +81496,7 @@ function isProcessAlive(pid, owner) {
|
|
|
81205
81496
|
}
|
|
81206
81497
|
function readLockOwner(lockDir) {
|
|
81207
81498
|
try {
|
|
81208
|
-
const raw =
|
|
81499
|
+
const raw = readFileSync19(join27(lockDir, LOCK_TOKEN_FILE), "utf-8");
|
|
81209
81500
|
return JSON.parse(raw);
|
|
81210
81501
|
} catch {
|
|
81211
81502
|
return null;
|
|
@@ -81218,7 +81509,7 @@ function isLockStale(lockDir) {
|
|
|
81218
81509
|
const owner = readLockOwner(lockDir);
|
|
81219
81510
|
if (!owner) {
|
|
81220
81511
|
try {
|
|
81221
|
-
const stat5 =
|
|
81512
|
+
const stat5 = statSync7(lockDir);
|
|
81222
81513
|
return Date.now() - stat5.mtimeMs > LOCK_STALE_AGE_MS;
|
|
81223
81514
|
} catch {
|
|
81224
81515
|
return true;
|
|
@@ -81462,7 +81753,7 @@ function getActiveTasks() {
|
|
|
81462
81753
|
function getCronFileMtime() {
|
|
81463
81754
|
const path21 = getCronFilePath();
|
|
81464
81755
|
try {
|
|
81465
|
-
return
|
|
81756
|
+
return statSync7(path21).mtimeMs;
|
|
81466
81757
|
} catch {
|
|
81467
81758
|
return 0;
|
|
81468
81759
|
}
|
|
@@ -81705,7 +81996,7 @@ async function registerWithCloudRetry(opts, callbacks) {
|
|
|
81705
81996
|
if (error instanceof Error) {
|
|
81706
81997
|
callbacks?.onRetry?.(attempt, delay, error);
|
|
81707
81998
|
}
|
|
81708
|
-
await new Promise((
|
|
81999
|
+
await new Promise((resolve28) => setTimeout(resolve28, delay));
|
|
81709
82000
|
}
|
|
81710
82001
|
}
|
|
81711
82002
|
}
|
|
@@ -83610,7 +83901,7 @@ var init_memoryReminder = __esm(() => {
|
|
|
83610
83901
|
});
|
|
83611
83902
|
|
|
83612
83903
|
// src/utils/systemPromptSize.ts
|
|
83613
|
-
import { existsSync as existsSync26, readdirSync as readdirSync8, readFileSync as
|
|
83904
|
+
import { existsSync as existsSync26, readdirSync as readdirSync8, readFileSync as readFileSync20 } from "node:fs";
|
|
83614
83905
|
import { join as join29 } from "node:path";
|
|
83615
83906
|
function estimateSystemTokens(text) {
|
|
83616
83907
|
return Math.ceil(Buffer.byteLength(text, "utf8") / SYSTEM_PROMPT_BYTES_PER_TOKEN);
|
|
@@ -83647,7 +83938,7 @@ function estimateSystemPromptSize(memoryDir) {
|
|
|
83647
83938
|
const files = walkMarkdownFiles(systemDir).sort();
|
|
83648
83939
|
const rows = [];
|
|
83649
83940
|
for (const filePath of files) {
|
|
83650
|
-
const text =
|
|
83941
|
+
const text = readFileSync20(filePath, "utf8");
|
|
83651
83942
|
const rel = normalizePath2(filePath.slice(memoryDir.length + 1));
|
|
83652
83943
|
rows.push({ path: rel, tokens: estimateSystemTokens(text) });
|
|
83653
83944
|
}
|
|
@@ -87043,10 +87334,36 @@ function buildParentMemoryTree(files) {
|
|
|
87043
87334
|
return lines.join(`
|
|
87044
87335
|
`);
|
|
87045
87336
|
}
|
|
87046
|
-
|
|
87337
|
+
function joinedLength(lines) {
|
|
87338
|
+
return lines.join(`
|
|
87339
|
+
`).length;
|
|
87340
|
+
}
|
|
87341
|
+
function canAppendWithinBudget(lines, additions, maxChars) {
|
|
87342
|
+
return joinedLength([...lines, ...additions, "</parent_memory>"]) <= maxChars;
|
|
87343
|
+
}
|
|
87344
|
+
function truncateMemoryContentToFit(lines, prefix, content, suffix, maxChars) {
|
|
87345
|
+
const fixedLength = joinedLength([
|
|
87346
|
+
...lines,
|
|
87347
|
+
...prefix,
|
|
87348
|
+
"",
|
|
87349
|
+
...suffix,
|
|
87350
|
+
"</parent_memory>"
|
|
87351
|
+
]);
|
|
87352
|
+
const budget = maxChars - fixedLength;
|
|
87353
|
+
if (budget <= 0) {
|
|
87354
|
+
return null;
|
|
87355
|
+
}
|
|
87356
|
+
return content.slice(0, budget).trimEnd();
|
|
87357
|
+
}
|
|
87358
|
+
function buildMemoryPreviewNotice(relativePath, absolutePath, kind) {
|
|
87359
|
+
const action = kind === "truncated" ? "truncated" : "omitted";
|
|
87360
|
+
return `[Memory preview ${action}: startup context is capped at ~16k estimated tokens. Full file available at ${absolutePath}; read it directly if needed. Relative path: ${relativePath}]`;
|
|
87361
|
+
}
|
|
87362
|
+
async function buildParentMemorySnapshot(memoryDir, options = {}) {
|
|
87047
87363
|
const files = await collectParentMemoryFiles(memoryDir);
|
|
87048
87364
|
const tree = buildParentMemoryTree(files);
|
|
87049
87365
|
const systemFiles = files.filter((file) => isSystemMemoryFile(file.relativePath));
|
|
87366
|
+
const maxChars = Math.max(1000, options.maxChars ?? REFLECTION_PARENT_MEMORY_SNAPSHOT_CHAR_LIMIT);
|
|
87050
87367
|
const lines = [
|
|
87051
87368
|
"<parent_memory>",
|
|
87052
87369
|
"<memory_filesystem>",
|
|
@@ -87056,13 +87373,47 @@ async function buildParentMemorySnapshot(memoryDir) {
|
|
|
87056
87373
|
if (files.length === 0) {
|
|
87057
87374
|
lines.push("(no memory markdown files found)");
|
|
87058
87375
|
} else {
|
|
87376
|
+
let omittedSystemFiles = 0;
|
|
87059
87377
|
for (const file of systemFiles) {
|
|
87060
87378
|
const normalizedPath = file.relativePath.replace(/\\/g, "/");
|
|
87061
87379
|
const absolutePath = `${memoryDir.replace(/\\/g, "/")}/${normalizedPath}`;
|
|
87062
|
-
|
|
87063
|
-
|
|
87064
|
-
|
|
87065
|
-
lines
|
|
87380
|
+
const prefix = ["<memory>", `<path>${absolutePath}</path>`];
|
|
87381
|
+
const suffix = ["</memory>"];
|
|
87382
|
+
const fullEntry = [...prefix, file.content, ...suffix];
|
|
87383
|
+
if (canAppendWithinBudget(lines, fullEntry, maxChars)) {
|
|
87384
|
+
lines.push(...fullEntry);
|
|
87385
|
+
continue;
|
|
87386
|
+
}
|
|
87387
|
+
const truncatedNotice = buildMemoryPreviewNotice(normalizedPath, absolutePath, "truncated");
|
|
87388
|
+
const truncatedContent = truncateMemoryContentToFit(lines, prefix, file.content, [truncatedNotice, ...suffix], maxChars);
|
|
87389
|
+
if (truncatedContent) {
|
|
87390
|
+
const truncatedEntry = [
|
|
87391
|
+
...prefix,
|
|
87392
|
+
truncatedContent,
|
|
87393
|
+
truncatedNotice,
|
|
87394
|
+
...suffix
|
|
87395
|
+
];
|
|
87396
|
+
if (canAppendWithinBudget(lines, truncatedEntry, maxChars)) {
|
|
87397
|
+
lines.push(...truncatedEntry);
|
|
87398
|
+
continue;
|
|
87399
|
+
}
|
|
87400
|
+
}
|
|
87401
|
+
const omittedEntry = [
|
|
87402
|
+
...prefix,
|
|
87403
|
+
buildMemoryPreviewNotice(normalizedPath, absolutePath, "omitted"),
|
|
87404
|
+
...suffix
|
|
87405
|
+
];
|
|
87406
|
+
if (canAppendWithinBudget(lines, omittedEntry, maxChars)) {
|
|
87407
|
+
lines.push(...omittedEntry);
|
|
87408
|
+
} else {
|
|
87409
|
+
omittedSystemFiles += 1;
|
|
87410
|
+
}
|
|
87411
|
+
}
|
|
87412
|
+
if (omittedSystemFiles > 0) {
|
|
87413
|
+
const notice = `[Memory preview omitted ${omittedSystemFiles.toLocaleString()} additional system file(s) because the reflection startup context budget was exhausted. Read files directly from ${memoryDir} if needed.]`;
|
|
87414
|
+
if (canAppendWithinBudget(lines, [notice], maxChars)) {
|
|
87415
|
+
lines.push(notice);
|
|
87416
|
+
}
|
|
87066
87417
|
}
|
|
87067
87418
|
}
|
|
87068
87419
|
lines.push("</parent_memory>");
|
|
@@ -87310,12 +87661,13 @@ async function finalizeAutoReflectionPayload(agentId, conversationId, _payloadPa
|
|
|
87310
87661
|
var TRANSCRIPT_ROOT_ENV = "LETTA_TRANSCRIPT_ROOT", DEFAULT_TRANSCRIPT_DIR = "transcripts", TOOL_ARGS_TRUNCATE_LIMIT = 300;
|
|
87311
87662
|
var init_reflectionTranscript = __esm(() => {
|
|
87312
87663
|
init_memoryFilesystem();
|
|
87664
|
+
init_contextBudget();
|
|
87313
87665
|
init_directoryLimits();
|
|
87314
87666
|
});
|
|
87315
87667
|
|
|
87316
87668
|
// src/utils/tuiPerf.ts
|
|
87317
87669
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync20 } from "node:fs";
|
|
87318
|
-
import { dirname as
|
|
87670
|
+
import { dirname as dirname15 } from "node:path";
|
|
87319
87671
|
function ensureExitHook() {
|
|
87320
87672
|
if (tuiPerfExitHookRegistered) {
|
|
87321
87673
|
return;
|
|
@@ -87404,7 +87756,7 @@ function flushTuiPerfTelemetry() {
|
|
|
87404
87756
|
};
|
|
87405
87757
|
}
|
|
87406
87758
|
try {
|
|
87407
|
-
const dir =
|
|
87759
|
+
const dir = dirname15(filePath);
|
|
87408
87760
|
if (tuiPerfFileDirEnsured !== dir) {
|
|
87409
87761
|
mkdirSync20(dir, { recursive: true });
|
|
87410
87762
|
tuiPerfFileDirEnsured = dir;
|
|
@@ -87746,11 +88098,11 @@ async function discoverFallbackRunIdWithTimeout(client, ctx) {
|
|
|
87746
88098
|
return withTimeout(discoverFallbackRunIdForResume(client, ctx), FALLBACK_RUN_DISCOVERY_TIMEOUT_MS, `Fallback run discovery timed out after ${FALLBACK_RUN_DISCOVERY_TIMEOUT_MS}ms`);
|
|
87747
88099
|
}
|
|
87748
88100
|
function withTimeout(promise, timeoutMs, timeoutMessage) {
|
|
87749
|
-
return new Promise((
|
|
88101
|
+
return new Promise((resolve28, reject) => {
|
|
87750
88102
|
const timer = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs);
|
|
87751
88103
|
promise.then((value) => {
|
|
87752
88104
|
clearTimeout(timer);
|
|
87753
|
-
|
|
88105
|
+
resolve28(value);
|
|
87754
88106
|
}, (error) => {
|
|
87755
88107
|
clearTimeout(timer);
|
|
87756
88108
|
reject(error);
|
|
@@ -88645,7 +88997,7 @@ var init_constants2 = __esm(() => {
|
|
|
88645
88997
|
});
|
|
88646
88998
|
|
|
88647
88999
|
// src/websocket/listener/remote-settings.ts
|
|
88648
|
-
import { existsSync as existsSync29, readFileSync as
|
|
89000
|
+
import { existsSync as existsSync29, readFileSync as readFileSync21 } from "node:fs";
|
|
88649
89001
|
import { mkdir as mkdir8, writeFile as writeFile10 } from "node:fs/promises";
|
|
88650
89002
|
import { homedir as homedir22 } from "node:os";
|
|
88651
89003
|
import path21 from "node:path";
|
|
@@ -88660,7 +89012,7 @@ function loadRemoteSettings() {
|
|
|
88660
89012
|
try {
|
|
88661
89013
|
const settingsPath = getRemoteSettingsPath();
|
|
88662
89014
|
if (existsSync29(settingsPath)) {
|
|
88663
|
-
const raw =
|
|
89015
|
+
const raw = readFileSync21(settingsPath, "utf-8");
|
|
88664
89016
|
const parsed = JSON.parse(raw);
|
|
88665
89017
|
loaded = parsed;
|
|
88666
89018
|
}
|
|
@@ -88697,7 +89049,7 @@ function loadLegacyCwdCache() {
|
|
|
88697
89049
|
const legacyPath = path21.join(homedir22(), ".letta", "cwd-cache.json");
|
|
88698
89050
|
if (!existsSync29(legacyPath))
|
|
88699
89051
|
return {};
|
|
88700
|
-
const raw =
|
|
89052
|
+
const raw = readFileSync21(legacyPath, "utf-8");
|
|
88701
89053
|
const parsed = JSON.parse(raw);
|
|
88702
89054
|
const result = {};
|
|
88703
89055
|
for (const [key, value] of Object.entries(parsed)) {
|
|
@@ -88899,7 +89251,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
|
|
|
88899
89251
|
if (isInterrupted()) {
|
|
88900
89252
|
return Promise.reject(new Error("Cancelled by user"));
|
|
88901
89253
|
}
|
|
88902
|
-
return new Promise((
|
|
89254
|
+
return new Promise((resolve28, reject) => {
|
|
88903
89255
|
let settled = false;
|
|
88904
89256
|
const cleanupAbortListener = () => {
|
|
88905
89257
|
abortSignal?.removeEventListener("abort", handleAbort);
|
|
@@ -88910,7 +89262,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
|
|
|
88910
89262
|
}
|
|
88911
89263
|
settled = true;
|
|
88912
89264
|
cleanupAbortListener();
|
|
88913
|
-
|
|
89265
|
+
resolve28(response);
|
|
88914
89266
|
};
|
|
88915
89267
|
const wrappedReject = (error) => {
|
|
88916
89268
|
if (settled) {
|
|
@@ -90535,7 +90887,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
90535
90887
|
conversationId
|
|
90536
90888
|
});
|
|
90537
90889
|
}
|
|
90538
|
-
await new Promise((
|
|
90890
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
90539
90891
|
if (abortSignal?.aborted) {
|
|
90540
90892
|
throw new Error("Cancelled by user");
|
|
90541
90893
|
}
|
|
@@ -90590,7 +90942,7 @@ async function sendMessageStreamWithRetry(conversationId, messages, opts, socket
|
|
|
90590
90942
|
agentId: runtime.agentId ?? undefined,
|
|
90591
90943
|
conversationId
|
|
90592
90944
|
});
|
|
90593
|
-
await new Promise((
|
|
90945
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
90594
90946
|
if (abortSignal?.aborted) {
|
|
90595
90947
|
throw new Error("Cancelled by user");
|
|
90596
90948
|
}
|
|
@@ -90677,7 +91029,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
90677
91029
|
conversationId
|
|
90678
91030
|
});
|
|
90679
91031
|
}
|
|
90680
|
-
await new Promise((
|
|
91032
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
90681
91033
|
if (abortSignal?.aborted) {
|
|
90682
91034
|
throw new Error("Cancelled by user");
|
|
90683
91035
|
}
|
|
@@ -90731,7 +91083,7 @@ async function sendApprovalContinuationWithRetry(conversationId, messages, opts,
|
|
|
90731
91083
|
agentId: runtime.agentId ?? undefined,
|
|
90732
91084
|
conversationId
|
|
90733
91085
|
});
|
|
90734
|
-
await new Promise((
|
|
91086
|
+
await new Promise((resolve28) => setTimeout(resolve28, retryDelayMs));
|
|
90735
91087
|
if (abortSignal?.aborted) {
|
|
90736
91088
|
throw new Error("Cancelled by user");
|
|
90737
91089
|
}
|
|
@@ -93732,7 +94084,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
93732
94084
|
agentId,
|
|
93733
94085
|
conversationId
|
|
93734
94086
|
});
|
|
93735
|
-
await new Promise((
|
|
94087
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
93736
94088
|
if (turnAbortSignal.aborted) {
|
|
93737
94089
|
throw new Error("Cancelled by user");
|
|
93738
94090
|
}
|
|
@@ -93777,7 +94129,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
93777
94129
|
agentId,
|
|
93778
94130
|
conversationId
|
|
93779
94131
|
});
|
|
93780
|
-
await new Promise((
|
|
94132
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
93781
94133
|
if (turnAbortSignal.aborted) {
|
|
93782
94134
|
throw new Error("Cancelled by user");
|
|
93783
94135
|
}
|
|
@@ -94282,7 +94634,7 @@ var init_commands = __esm(async () => {
|
|
|
94282
94634
|
|
|
94283
94635
|
// src/websocket/listener/protocol-outbound.ts
|
|
94284
94636
|
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync22 } from "node:fs";
|
|
94285
|
-
import { dirname as
|
|
94637
|
+
import { dirname as dirname16 } from "node:path";
|
|
94286
94638
|
import { performance as performance2 } from "node:perf_hooks";
|
|
94287
94639
|
import WebSocket3 from "ws";
|
|
94288
94640
|
function getProtocolPerfKey(message) {
|
|
@@ -94331,7 +94683,7 @@ function writeProtocolPerfFile(record, fallbackLine) {
|
|
|
94331
94683
|
return;
|
|
94332
94684
|
}
|
|
94333
94685
|
try {
|
|
94334
|
-
const dir =
|
|
94686
|
+
const dir = dirname16(filePath);
|
|
94335
94687
|
if (protocolPerfFileDirEnsured !== dir) {
|
|
94336
94688
|
mkdirSync22(dir, { recursive: true });
|
|
94337
94689
|
protocolPerfFileDirEnsured = dir;
|
|
@@ -95697,7 +96049,7 @@ async function runGrepInFiles(args) {
|
|
|
95697
96049
|
});
|
|
95698
96050
|
}
|
|
95699
96051
|
function runRipgrep(rgArgs) {
|
|
95700
|
-
return new Promise((
|
|
96052
|
+
return new Promise((resolve28, reject) => {
|
|
95701
96053
|
const child = execFile12(rgPath3, rgArgs, {
|
|
95702
96054
|
maxBuffer: 50 * 1024 * 1024
|
|
95703
96055
|
}, (error, stdout, _stderr) => {
|
|
@@ -95705,7 +96057,7 @@ function runRipgrep(rgArgs) {
|
|
|
95705
96057
|
reject(error);
|
|
95706
96058
|
return;
|
|
95707
96059
|
}
|
|
95708
|
-
|
|
96060
|
+
resolve28(stdout);
|
|
95709
96061
|
});
|
|
95710
96062
|
const timer = setTimeout(() => {
|
|
95711
96063
|
child.kill("SIGTERM");
|
|
@@ -96353,7 +96705,7 @@ var init_protocol_inbound = __esm(async () => {
|
|
|
96353
96705
|
});
|
|
96354
96706
|
|
|
96355
96707
|
// src/websocket/listener/worktree-watcher.ts
|
|
96356
|
-
import { readdir as readdir6, stat as stat5, watch } from "node:fs/promises";
|
|
96708
|
+
import { readdir as readdir6, stat as stat5, watch as watch2 } from "node:fs/promises";
|
|
96357
96709
|
import path24 from "node:path";
|
|
96358
96710
|
function startWorktreeWatcher(params) {
|
|
96359
96711
|
const { runtime, agentId, conversationId } = params;
|
|
@@ -96409,7 +96761,7 @@ async function runWatchLoop(params) {
|
|
|
96409
96761
|
}
|
|
96410
96762
|
const existingEntries = new Set(await safeReaddir(worktreesDir));
|
|
96411
96763
|
let debounceTimer = null;
|
|
96412
|
-
const watcher =
|
|
96764
|
+
const watcher = watch2(worktreesDir, { signal: abort.signal });
|
|
96413
96765
|
for await (const event of watcher) {
|
|
96414
96766
|
if (event.eventType !== "rename" || !event.filename)
|
|
96415
96767
|
continue;
|
|
@@ -96460,7 +96812,7 @@ async function handleNewWorktree(params) {
|
|
|
96460
96812
|
}
|
|
96461
96813
|
}
|
|
96462
96814
|
async function waitForDirectoryCreation(parentDir, targetName, signal) {
|
|
96463
|
-
const watcher =
|
|
96815
|
+
const watcher = watch2(parentDir, { signal });
|
|
96464
96816
|
for await (const event of watcher) {
|
|
96465
96817
|
if (event.eventType === "rename" && event.filename === targetName && await directoryExists(path24.join(parentDir, targetName))) {
|
|
96466
96818
|
return;
|
|
@@ -96497,7 +96849,7 @@ __export(exports_memoryScanner, {
|
|
|
96497
96849
|
readFileContent: () => readFileContent,
|
|
96498
96850
|
getFileNodes: () => getFileNodes
|
|
96499
96851
|
});
|
|
96500
|
-
import { readdirSync as readdirSync10, readFileSync as
|
|
96852
|
+
import { readdirSync as readdirSync10, readFileSync as readFileSync22, statSync as statSync8 } from "node:fs";
|
|
96501
96853
|
import { join as join33, relative as relative13 } from "node:path";
|
|
96502
96854
|
function scanMemoryFilesystem(memoryRoot) {
|
|
96503
96855
|
const nodes = [];
|
|
@@ -96515,10 +96867,10 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
96515
96867
|
let aIsDir = false;
|
|
96516
96868
|
let bIsDir = false;
|
|
96517
96869
|
try {
|
|
96518
|
-
aIsDir =
|
|
96870
|
+
aIsDir = statSync8(aPath).isDirectory();
|
|
96519
96871
|
} catch {}
|
|
96520
96872
|
try {
|
|
96521
|
-
bIsDir =
|
|
96873
|
+
bIsDir = statSync8(bPath).isDirectory();
|
|
96522
96874
|
} catch {}
|
|
96523
96875
|
if (aIsDir !== bIsDir)
|
|
96524
96876
|
return aIsDir ? -1 : 1;
|
|
@@ -96534,7 +96886,7 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
96534
96886
|
const fullPath = join33(dir, name);
|
|
96535
96887
|
let isDir = false;
|
|
96536
96888
|
try {
|
|
96537
|
-
isDir =
|
|
96889
|
+
isDir = statSync8(fullPath).isDirectory();
|
|
96538
96890
|
} catch {
|
|
96539
96891
|
return;
|
|
96540
96892
|
}
|
|
@@ -96562,7 +96914,7 @@ function getFileNodes(nodes) {
|
|
|
96562
96914
|
}
|
|
96563
96915
|
function readFileContent(fullPath) {
|
|
96564
96916
|
try {
|
|
96565
|
-
return
|
|
96917
|
+
return readFileSync22(fullPath, "utf-8");
|
|
96566
96918
|
} catch {
|
|
96567
96919
|
return "(unable to read file)";
|
|
96568
96920
|
}
|
|
@@ -98826,8 +99178,8 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
98826
99178
|
const delay = Math.min(INITIAL_RETRY_DELAY_MS * 2 ** (attempt - 1), MAX_RETRY_DELAY_MS);
|
|
98827
99179
|
const maxAttempts = Math.ceil(Math.log2(MAX_RETRY_DURATION_MS / INITIAL_RETRY_DELAY_MS));
|
|
98828
99180
|
opts.onRetrying?.(attempt, maxAttempts, delay, opts.connectionId);
|
|
98829
|
-
await new Promise((
|
|
98830
|
-
runtime.reconnectTimeout = setTimeout(
|
|
99181
|
+
await new Promise((resolve28) => {
|
|
99182
|
+
runtime.reconnectTimeout = setTimeout(resolve28, delay);
|
|
98831
99183
|
});
|
|
98832
99184
|
runtime.reconnectTimeout = null;
|
|
98833
99185
|
if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
|
|
@@ -99374,11 +99726,11 @@ async function connectWithRetry(runtime, opts, attempt = 0, startTime = Date.now
|
|
|
99374
99726
|
return;
|
|
99375
99727
|
}
|
|
99376
99728
|
try {
|
|
99377
|
-
const { watch:
|
|
99729
|
+
const { watch: watch3 } = await import("node:fs");
|
|
99378
99730
|
const { stat: stat7 } = await import("node:fs/promises");
|
|
99379
99731
|
if (cancelledWatches.delete(parsed.path))
|
|
99380
99732
|
return;
|
|
99381
|
-
const watcher =
|
|
99733
|
+
const watcher = watch3(parsed.path, { persistent: false }, (eventType) => {
|
|
99382
99734
|
if (eventType !== "change" && eventType !== "rename")
|
|
99383
99735
|
return;
|
|
99384
99736
|
const existing2 = watchDebounceTimers.get(parsed.path);
|
|
@@ -100305,7 +100657,7 @@ import {
|
|
|
100305
100657
|
existsSync as existsSync31,
|
|
100306
100658
|
mkdirSync as mkdirSync24,
|
|
100307
100659
|
readdirSync as readdirSync11,
|
|
100308
|
-
readFileSync as
|
|
100660
|
+
readFileSync as readFileSync23,
|
|
100309
100661
|
unlinkSync as unlinkSync8
|
|
100310
100662
|
} from "node:fs";
|
|
100311
100663
|
import { homedir as homedir26 } from "node:os";
|
|
@@ -100359,7 +100711,7 @@ class DebugLogFile2 {
|
|
|
100359
100711
|
try {
|
|
100360
100712
|
if (!existsSync31(this.logPath))
|
|
100361
100713
|
return;
|
|
100362
|
-
const content =
|
|
100714
|
+
const content = readFileSync23(this.logPath, "utf8");
|
|
100363
100715
|
const lines = content.trimEnd().split(`
|
|
100364
100716
|
`);
|
|
100365
100717
|
return lines.slice(-maxLines).join(`
|
|
@@ -100443,10 +100795,10 @@ __export(exports_skills2, {
|
|
|
100443
100795
|
});
|
|
100444
100796
|
import { existsSync as existsSync32 } from "node:fs";
|
|
100445
100797
|
import { readdir as readdir8, readFile as readFile13, realpath as realpath4, stat as stat7 } from "node:fs/promises";
|
|
100446
|
-
import { dirname as
|
|
100798
|
+
import { dirname as dirname17, join as join38 } from "node:path";
|
|
100447
100799
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
100448
100800
|
function getBundledSkillsPath2() {
|
|
100449
|
-
const thisDir =
|
|
100801
|
+
const thisDir = dirname17(fileURLToPath9(import.meta.url));
|
|
100450
100802
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
100451
100803
|
return join38(thisDir, "../skills/builtin");
|
|
100452
100804
|
}
|
|
@@ -100642,12 +100994,12 @@ import {
|
|
|
100642
100994
|
writeFileSync as fsWriteFileSync2,
|
|
100643
100995
|
mkdirSync as mkdirSync25
|
|
100644
100996
|
} from "node:fs";
|
|
100645
|
-
import { dirname as
|
|
100997
|
+
import { dirname as dirname18 } from "node:path";
|
|
100646
100998
|
async function readFile14(path26) {
|
|
100647
100999
|
return fsReadFileSync2(path26, { encoding: "utf-8" });
|
|
100648
101000
|
}
|
|
100649
101001
|
async function writeFile12(path26, content) {
|
|
100650
|
-
const dir =
|
|
101002
|
+
const dir = dirname18(path26);
|
|
100651
101003
|
if (!existsSync33(dir)) {
|
|
100652
101004
|
mkdirSync25(dir, { recursive: true });
|
|
100653
101005
|
}
|
|
@@ -100692,7 +101044,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
100692
101044
|
}
|
|
100693
101045
|
const wasRaw = process.stdin.isRaw;
|
|
100694
101046
|
const wasFlowing = process.stdin.readableFlowing;
|
|
100695
|
-
return new Promise((
|
|
101047
|
+
return new Promise((resolve30) => {
|
|
100696
101048
|
let response = "";
|
|
100697
101049
|
let resolved = false;
|
|
100698
101050
|
const cleanup = () => {
|
|
@@ -100709,7 +101061,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
100709
101061
|
};
|
|
100710
101062
|
const timeout = setTimeout(() => {
|
|
100711
101063
|
cleanup();
|
|
100712
|
-
|
|
101064
|
+
resolve30(null);
|
|
100713
101065
|
}, timeoutMs);
|
|
100714
101066
|
const onData = (data) => {
|
|
100715
101067
|
response += data.toString();
|
|
@@ -100719,7 +101071,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
100719
101071
|
if (match3) {
|
|
100720
101072
|
clearTimeout(timeout);
|
|
100721
101073
|
cleanup();
|
|
100722
|
-
|
|
101074
|
+
resolve30({
|
|
100723
101075
|
r: parseHexComponent(match3[1] ?? "0"),
|
|
100724
101076
|
g: parseHexComponent(match3[2] ?? "0"),
|
|
100725
101077
|
b: parseHexComponent(match3[3] ?? "0")
|
|
@@ -100734,7 +101086,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
100734
101086
|
} catch {
|
|
100735
101087
|
clearTimeout(timeout);
|
|
100736
101088
|
cleanup();
|
|
100737
|
-
|
|
101089
|
+
resolve30(null);
|
|
100738
101090
|
}
|
|
100739
101091
|
});
|
|
100740
101092
|
}
|
|
@@ -101967,10 +102319,10 @@ __export(exports_setup, {
|
|
|
101967
102319
|
runSetup: () => runSetup
|
|
101968
102320
|
});
|
|
101969
102321
|
async function runSetup() {
|
|
101970
|
-
return new Promise((
|
|
102322
|
+
return new Promise((resolve31) => {
|
|
101971
102323
|
const { waitUntilExit } = render_default(import_react32.default.createElement(SetupUI, {
|
|
101972
102324
|
onComplete: () => {
|
|
101973
|
-
|
|
102325
|
+
resolve31();
|
|
101974
102326
|
}
|
|
101975
102327
|
}));
|
|
101976
102328
|
waitUntilExit().catch((error) => {
|
|
@@ -102458,9 +102810,28 @@ function validateRegistryHandleOrThrow2(handle) {
|
|
|
102458
102810
|
}
|
|
102459
102811
|
|
|
102460
102812
|
// src/streamJsonWriter.ts
|
|
102813
|
+
function stampWireMessage(msg) {
|
|
102814
|
+
return msg.timestamp === undefined ? { ...msg, timestamp: new Date().toISOString() } : msg;
|
|
102815
|
+
}
|
|
102461
102816
|
function writeWireMessage(msg) {
|
|
102462
|
-
|
|
102463
|
-
|
|
102817
|
+
console.log(JSON.stringify(stampWireMessage(msg)));
|
|
102818
|
+
}
|
|
102819
|
+
async function writeWireMessageAsync(msg) {
|
|
102820
|
+
const line = `${JSON.stringify(stampWireMessage(msg))}
|
|
102821
|
+
`;
|
|
102822
|
+
await new Promise((resolve31, reject) => {
|
|
102823
|
+
if (process.stdout.destroyed || process.stdout.writableEnded) {
|
|
102824
|
+
resolve31();
|
|
102825
|
+
return;
|
|
102826
|
+
}
|
|
102827
|
+
process.stdout.write(line, (error) => {
|
|
102828
|
+
if (error) {
|
|
102829
|
+
reject(error);
|
|
102830
|
+
return;
|
|
102831
|
+
}
|
|
102832
|
+
resolve31();
|
|
102833
|
+
});
|
|
102834
|
+
});
|
|
102464
102835
|
}
|
|
102465
102836
|
|
|
102466
102837
|
// src/agent/github-utils.ts
|
|
@@ -102504,10 +102875,10 @@ __export(exports_import, {
|
|
|
102504
102875
|
});
|
|
102505
102876
|
import { createReadStream } from "node:fs";
|
|
102506
102877
|
import { chmod, mkdir as mkdir10, readFile as readFile15, writeFile as writeFile13 } from "node:fs/promises";
|
|
102507
|
-
import { dirname as
|
|
102878
|
+
import { dirname as dirname19, resolve as resolve31 } from "node:path";
|
|
102508
102879
|
async function importAgentFromFile(options) {
|
|
102509
102880
|
const client = await getClient();
|
|
102510
|
-
const resolvedPath =
|
|
102881
|
+
const resolvedPath = resolve31(options.filePath);
|
|
102511
102882
|
const file = createReadStream(resolvedPath);
|
|
102512
102883
|
const importResponse = await client.agents.importFile({
|
|
102513
102884
|
file,
|
|
@@ -102542,7 +102913,7 @@ async function extractSkillsFromAf(afPath, destDir) {
|
|
|
102542
102913
|
return [];
|
|
102543
102914
|
}
|
|
102544
102915
|
for (const skill2 of afData.skills) {
|
|
102545
|
-
const skillDir =
|
|
102916
|
+
const skillDir = resolve31(destDir, skill2.name);
|
|
102546
102917
|
await mkdir10(skillDir, { recursive: true });
|
|
102547
102918
|
if (skill2.files) {
|
|
102548
102919
|
await writeSkillFiles(skillDir, skill2.files);
|
|
@@ -102562,8 +102933,8 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
102562
102933
|
}
|
|
102563
102934
|
}
|
|
102564
102935
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
102565
|
-
const fullPath =
|
|
102566
|
-
await mkdir10(
|
|
102936
|
+
const fullPath = resolve31(skillDir, filePath);
|
|
102937
|
+
await mkdir10(dirname19(fullPath), { recursive: true });
|
|
102567
102938
|
await writeFile13(fullPath, content, "utf-8");
|
|
102568
102939
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
102569
102940
|
if (isScript) {
|
|
@@ -102904,12 +103275,12 @@ async function sendScopedApprovalMessages(params) {
|
|
|
102904
103275
|
});
|
|
102905
103276
|
}
|
|
102906
103277
|
async function flushAndExit(code) {
|
|
102907
|
-
const flushWritable = (stream2) => new Promise((
|
|
103278
|
+
const flushWritable = (stream2) => new Promise((resolve32) => {
|
|
102908
103279
|
if (stream2.destroyed || stream2.writableEnded) {
|
|
102909
|
-
|
|
103280
|
+
resolve32();
|
|
102910
103281
|
return;
|
|
102911
103282
|
}
|
|
102912
|
-
stream2.write("", () =>
|
|
103283
|
+
stream2.write("", () => resolve32());
|
|
102913
103284
|
});
|
|
102914
103285
|
await Promise.allSettled([
|
|
102915
103286
|
flushWritable(process.stdout),
|
|
@@ -102918,12 +103289,12 @@ async function flushAndExit(code) {
|
|
|
102918
103289
|
process.exit(code);
|
|
102919
103290
|
}
|
|
102920
103291
|
async function writeFinalHeadlessStdout(text) {
|
|
102921
|
-
await new Promise((
|
|
103292
|
+
await new Promise((resolve32) => {
|
|
102922
103293
|
if (process.stdout.destroyed || process.stdout.writableEnded) {
|
|
102923
|
-
|
|
103294
|
+
resolve32();
|
|
102924
103295
|
return;
|
|
102925
103296
|
}
|
|
102926
|
-
process.stdout.write(text, () =>
|
|
103297
|
+
process.stdout.write(text, () => resolve32());
|
|
102927
103298
|
});
|
|
102928
103299
|
}
|
|
102929
103300
|
async function handleHeadlessCommand(parsedArgs, model, skillsDirectoryOverride, skillSourcesOverride, systemInfoReminderEnabledOverride) {
|
|
@@ -103756,7 +104127,7 @@ ${loadedContents.join(`
|
|
|
103756
104127
|
session_id: sessionId,
|
|
103757
104128
|
uuid: `error-max-turns-${randomUUID15()}`
|
|
103758
104129
|
};
|
|
103759
|
-
|
|
104130
|
+
await writeWireMessageAsync(errorMsg);
|
|
103760
104131
|
} else {
|
|
103761
104132
|
console.error(`Maximum turns limit reached (${buffers.usage.stepCount}/${maxTurns} steps)`);
|
|
103762
104133
|
}
|
|
@@ -103855,7 +104226,7 @@ ${loadedContents.join(`
|
|
|
103855
104226
|
} else {
|
|
103856
104227
|
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
103857
104228
|
}
|
|
103858
|
-
await new Promise((
|
|
104229
|
+
await new Promise((resolve32) => setTimeout(resolve32, retryDelayMs));
|
|
103859
104230
|
continue;
|
|
103860
104231
|
}
|
|
103861
104232
|
}
|
|
@@ -103904,7 +104275,7 @@ ${loadedContents.join(`
|
|
|
103904
104275
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
103905
104276
|
console.error(`Transient API error before streaming (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
103906
104277
|
}
|
|
103907
|
-
await new Promise((
|
|
104278
|
+
await new Promise((resolve32) => setTimeout(resolve32, delayMs));
|
|
103908
104279
|
conversationBusyRetries = 0;
|
|
103909
104280
|
continue;
|
|
103910
104281
|
}
|
|
@@ -104140,7 +104511,7 @@ ${loadedContents.join(`
|
|
|
104140
104511
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
104141
104512
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
104142
104513
|
}
|
|
104143
|
-
await new Promise((
|
|
104514
|
+
await new Promise((resolve32) => setTimeout(resolve32, delayMs));
|
|
104144
104515
|
refreshCurrentInputOtids();
|
|
104145
104516
|
continue;
|
|
104146
104517
|
}
|
|
@@ -104173,7 +104544,7 @@ ${loadedContents.join(`
|
|
|
104173
104544
|
session_id: sessionId,
|
|
104174
104545
|
uuid: `error-${lastRunId || randomUUID15()}`
|
|
104175
104546
|
};
|
|
104176
|
-
|
|
104547
|
+
await writeWireMessageAsync(errorMsg);
|
|
104177
104548
|
} else {
|
|
104178
104549
|
console.error("Failed to fetch pending approvals for resync");
|
|
104179
104550
|
}
|
|
@@ -104230,7 +104601,7 @@ ${loadedContents.join(`
|
|
|
104230
104601
|
} else {
|
|
104231
104602
|
console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
|
|
104232
104603
|
}
|
|
104233
|
-
await new Promise((
|
|
104604
|
+
await new Promise((resolve32) => setTimeout(resolve32, delayMs));
|
|
104234
104605
|
refreshCurrentInputOtids();
|
|
104235
104606
|
continue;
|
|
104236
104607
|
}
|
|
@@ -104258,7 +104629,7 @@ ${loadedContents.join(`
|
|
|
104258
104629
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
104259
104630
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
104260
104631
|
}
|
|
104261
|
-
await new Promise((
|
|
104632
|
+
await new Promise((resolve32) => setTimeout(resolve32, delayMs));
|
|
104262
104633
|
refreshCurrentInputOtids();
|
|
104263
104634
|
continue;
|
|
104264
104635
|
}
|
|
@@ -104288,7 +104659,7 @@ ${loadedContents.join(`
|
|
|
104288
104659
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
104289
104660
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
104290
104661
|
}
|
|
104291
|
-
await new Promise((
|
|
104662
|
+
await new Promise((resolve32) => setTimeout(resolve32, delayMs));
|
|
104292
104663
|
refreshCurrentInputOtids();
|
|
104293
104664
|
continue;
|
|
104294
104665
|
}
|
|
@@ -104326,7 +104697,7 @@ ${loadedContents.join(`
|
|
|
104326
104697
|
session_id: sessionId,
|
|
104327
104698
|
uuid: `error-${lastRunId || randomUUID15()}`
|
|
104328
104699
|
};
|
|
104329
|
-
|
|
104700
|
+
await writeWireMessageAsync(errorMsg);
|
|
104330
104701
|
} else {
|
|
104331
104702
|
console.error(`Error: ${errorMessage}`);
|
|
104332
104703
|
}
|
|
@@ -104345,7 +104716,7 @@ ${loadedContents.join(`
|
|
|
104345
104716
|
session_id: sessionId,
|
|
104346
104717
|
uuid: `error-${lastKnownRunId || randomUUID15()}`
|
|
104347
104718
|
};
|
|
104348
|
-
|
|
104719
|
+
await writeWireMessageAsync(errorMsg);
|
|
104349
104720
|
} else {
|
|
104350
104721
|
console.error(`Error: ${errorDetails}`);
|
|
104351
104722
|
}
|
|
@@ -104408,7 +104779,7 @@ ${loadedContents.join(`
|
|
|
104408
104779
|
usage,
|
|
104409
104780
|
uuid: resultUuid
|
|
104410
104781
|
};
|
|
104411
|
-
|
|
104782
|
+
await writeWireMessageAsync(resultEvent);
|
|
104412
104783
|
} else {
|
|
104413
104784
|
if (!resultText || resultText === "No assistant response found") {
|
|
104414
104785
|
console.error("No assistant response found");
|
|
@@ -104607,9 +104978,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
104607
104978
|
const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
|
|
104608
104979
|
maybeNotifyBlocked(syntheticUserLine);
|
|
104609
104980
|
if (lineResolver) {
|
|
104610
|
-
const
|
|
104981
|
+
const resolve32 = lineResolver;
|
|
104611
104982
|
lineResolver = null;
|
|
104612
|
-
|
|
104983
|
+
resolve32(syntheticUserLine);
|
|
104613
104984
|
return;
|
|
104614
104985
|
}
|
|
104615
104986
|
lineQueue.push(syntheticUserLine);
|
|
@@ -104617,9 +104988,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
104617
104988
|
rl.on("line", (line) => {
|
|
104618
104989
|
maybeNotifyBlocked(line);
|
|
104619
104990
|
if (lineResolver) {
|
|
104620
|
-
const
|
|
104991
|
+
const resolve32 = lineResolver;
|
|
104621
104992
|
lineResolver = null;
|
|
104622
|
-
|
|
104993
|
+
resolve32(line);
|
|
104623
104994
|
} else {
|
|
104624
104995
|
lineQueue.push(line);
|
|
104625
104996
|
}
|
|
@@ -104628,17 +104999,17 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
104628
104999
|
setMessageQueueAdder(null);
|
|
104629
105000
|
msgQueueRuntime.clear("shutdown");
|
|
104630
105001
|
if (lineResolver) {
|
|
104631
|
-
const
|
|
105002
|
+
const resolve32 = lineResolver;
|
|
104632
105003
|
lineResolver = null;
|
|
104633
|
-
|
|
105004
|
+
resolve32(null);
|
|
104634
105005
|
}
|
|
104635
105006
|
});
|
|
104636
105007
|
async function getNextLine() {
|
|
104637
105008
|
if (lineQueue.length > 0) {
|
|
104638
105009
|
return lineQueue.shift() ?? null;
|
|
104639
105010
|
}
|
|
104640
|
-
return new Promise((
|
|
104641
|
-
lineResolver =
|
|
105011
|
+
return new Promise((resolve32) => {
|
|
105012
|
+
lineResolver = resolve32;
|
|
104642
105013
|
});
|
|
104643
105014
|
}
|
|
104644
105015
|
async function requestPermission(toolCallId, toolName, toolInput) {
|
|
@@ -105099,7 +105470,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
105099
105470
|
uuid: `retry-bidir-${randomUUID15()}`
|
|
105100
105471
|
};
|
|
105101
105472
|
writeWireMessage(retryMsg);
|
|
105102
|
-
await new Promise((
|
|
105473
|
+
await new Promise((resolve32) => setTimeout(resolve32, delayMs));
|
|
105103
105474
|
continue;
|
|
105104
105475
|
}
|
|
105105
105476
|
throw preStreamError;
|
|
@@ -105399,10 +105770,10 @@ async function detectAndEnableKittyProtocol() {
|
|
|
105399
105770
|
detectionComplete = true;
|
|
105400
105771
|
return;
|
|
105401
105772
|
}
|
|
105402
|
-
return new Promise((
|
|
105773
|
+
return new Promise((resolve32) => {
|
|
105403
105774
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
105404
105775
|
detectionComplete = true;
|
|
105405
|
-
|
|
105776
|
+
resolve32();
|
|
105406
105777
|
return;
|
|
105407
105778
|
}
|
|
105408
105779
|
const originalRawMode = process.stdin.isRaw;
|
|
@@ -105435,7 +105806,7 @@ async function detectAndEnableKittyProtocol() {
|
|
|
105435
105806
|
console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
|
|
105436
105807
|
}
|
|
105437
105808
|
detectionComplete = true;
|
|
105438
|
-
|
|
105809
|
+
resolve32();
|
|
105439
105810
|
};
|
|
105440
105811
|
const handleData = (data) => {
|
|
105441
105812
|
if (timeoutId === undefined) {
|
|
@@ -127540,9 +127911,9 @@ var init_pasteRegistry = __esm(() => {
|
|
|
127540
127911
|
|
|
127541
127912
|
// src/cli/helpers/clipboard.ts
|
|
127542
127913
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
127543
|
-
import { existsSync as existsSync38, readFileSync as
|
|
127914
|
+
import { existsSync as existsSync38, readFileSync as readFileSync25, statSync as statSync11, unlinkSync as unlinkSync10 } from "node:fs";
|
|
127544
127915
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
127545
|
-
import { basename as basename13, extname as extname8, isAbsolute as isAbsolute20, join as join45, resolve as
|
|
127916
|
+
import { basename as basename13, extname as extname8, isAbsolute as isAbsolute20, join as join45, resolve as resolve32 } from "node:path";
|
|
127546
127917
|
function countLines2(text) {
|
|
127547
127918
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
127548
127919
|
}
|
|
@@ -127592,21 +127963,21 @@ function translatePasteForImages(paste) {
|
|
|
127592
127963
|
} catch {}
|
|
127593
127964
|
}
|
|
127594
127965
|
if (!isAbsolute20(filePath))
|
|
127595
|
-
filePath =
|
|
127966
|
+
filePath = resolve32(process.cwd(), filePath);
|
|
127596
127967
|
const ext3 = extname8(filePath || "").toLowerCase();
|
|
127597
127968
|
if (IMAGE_EXTS.has(ext3)) {
|
|
127598
127969
|
let buf = null;
|
|
127599
127970
|
try {
|
|
127600
|
-
const stat8 =
|
|
127971
|
+
const stat8 = statSync11(filePath);
|
|
127601
127972
|
if (stat8.isFile())
|
|
127602
|
-
buf =
|
|
127973
|
+
buf = readFileSync25(filePath);
|
|
127603
127974
|
} catch {}
|
|
127604
127975
|
let clipboardMediaType = null;
|
|
127605
127976
|
if (!buf && process.platform === "darwin" && /TemporaryItems\/.*screencaptureui/i.test(filePath)) {
|
|
127606
127977
|
const clipResult = getClipboardImageToTempFile();
|
|
127607
127978
|
if (clipResult) {
|
|
127608
127979
|
try {
|
|
127609
|
-
buf =
|
|
127980
|
+
buf = readFileSync25(clipResult.tempPath);
|
|
127610
127981
|
clipboardMediaType = UTI_TO_MEDIA_TYPE[clipResult.uti] || null;
|
|
127611
127982
|
try {
|
|
127612
127983
|
unlinkSync10(clipResult.tempPath);
|
|
@@ -127675,7 +128046,7 @@ async function tryImportClipboardImageMac() {
|
|
|
127675
128046
|
return null;
|
|
127676
128047
|
const { tempPath, uti } = clipboardResult;
|
|
127677
128048
|
try {
|
|
127678
|
-
const buffer =
|
|
128049
|
+
const buffer = readFileSync25(tempPath);
|
|
127679
128050
|
try {
|
|
127680
128051
|
unlinkSync10(tempPath);
|
|
127681
128052
|
} catch {}
|
|
@@ -128290,8 +128661,8 @@ async function pushToMemoryRepositoryWithTimeout(agentId) {
|
|
|
128290
128661
|
try {
|
|
128291
128662
|
return await Promise.race([
|
|
128292
128663
|
pushToMemoryRepository(agentId),
|
|
128293
|
-
new Promise((
|
|
128294
|
-
timeout = setTimeout(() =>
|
|
128664
|
+
new Promise((resolve33) => {
|
|
128665
|
+
timeout = setTimeout(() => resolve33("timeout"), INITIAL_PUSH_TIMEOUT_MS);
|
|
128295
128666
|
})
|
|
128296
128667
|
]);
|
|
128297
128668
|
} finally {
|
|
@@ -128542,11 +128913,11 @@ import {
|
|
|
128542
128913
|
copyFileSync,
|
|
128543
128914
|
existsSync as existsSync39,
|
|
128544
128915
|
mkdirSync as mkdirSync30,
|
|
128545
|
-
readFileSync as
|
|
128916
|
+
readFileSync as readFileSync26,
|
|
128546
128917
|
writeFileSync as writeFileSync21
|
|
128547
128918
|
} from "node:fs";
|
|
128548
128919
|
import { homedir as homedir32, platform as platform6 } from "node:os";
|
|
128549
|
-
import { dirname as
|
|
128920
|
+
import { dirname as dirname20, join as join46 } from "node:path";
|
|
128550
128921
|
function detectTerminalType() {
|
|
128551
128922
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
128552
128923
|
return "cursor";
|
|
@@ -128612,7 +128983,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
128612
128983
|
if (!existsSync39(keybindingsPath))
|
|
128613
128984
|
return false;
|
|
128614
128985
|
try {
|
|
128615
|
-
const content =
|
|
128986
|
+
const content = readFileSync26(keybindingsPath, { encoding: "utf-8" });
|
|
128616
128987
|
const keybindings = parseKeybindings(content);
|
|
128617
128988
|
if (!keybindings)
|
|
128618
128989
|
return false;
|
|
@@ -128637,7 +129008,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
128637
129008
|
if (keybindingExists(keybindingsPath)) {
|
|
128638
129009
|
return { success: true, alreadyExists: true };
|
|
128639
129010
|
}
|
|
128640
|
-
const parentDir =
|
|
129011
|
+
const parentDir = dirname20(keybindingsPath);
|
|
128641
129012
|
if (!existsSync39(parentDir)) {
|
|
128642
129013
|
mkdirSync30(parentDir, { recursive: true });
|
|
128643
129014
|
}
|
|
@@ -128645,7 +129016,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
128645
129016
|
let backupPath = null;
|
|
128646
129017
|
if (existsSync39(keybindingsPath)) {
|
|
128647
129018
|
backupPath = createBackup(keybindingsPath);
|
|
128648
|
-
const content =
|
|
129019
|
+
const content = readFileSync26(keybindingsPath, { encoding: "utf-8" });
|
|
128649
129020
|
const parsed = parseKeybindings(content);
|
|
128650
129021
|
if (parsed === null) {
|
|
128651
129022
|
return {
|
|
@@ -128676,7 +129047,7 @@ function removeKeybinding(keybindingsPath) {
|
|
|
128676
129047
|
if (!existsSync39(keybindingsPath)) {
|
|
128677
129048
|
return { success: true };
|
|
128678
129049
|
}
|
|
128679
|
-
const content =
|
|
129050
|
+
const content = readFileSync26(keybindingsPath, { encoding: "utf-8" });
|
|
128680
129051
|
const keybindings = parseKeybindings(content);
|
|
128681
129052
|
if (!keybindings) {
|
|
128682
129053
|
return {
|
|
@@ -128753,7 +129124,7 @@ function wezTermDeleteFixExists(configPath) {
|
|
|
128753
129124
|
if (!existsSync39(configPath))
|
|
128754
129125
|
return false;
|
|
128755
129126
|
try {
|
|
128756
|
-
const content =
|
|
129127
|
+
const content = readFileSync26(configPath, { encoding: "utf-8" });
|
|
128757
129128
|
return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
|
|
128758
129129
|
} catch {
|
|
128759
129130
|
return false;
|
|
@@ -128770,7 +129141,7 @@ function installWezTermDeleteFix() {
|
|
|
128770
129141
|
if (existsSync39(configPath)) {
|
|
128771
129142
|
backupPath = `${configPath}.letta-backup`;
|
|
128772
129143
|
copyFileSync(configPath, backupPath);
|
|
128773
|
-
content =
|
|
129144
|
+
content = readFileSync26(configPath, { encoding: "utf-8" });
|
|
128774
129145
|
}
|
|
128775
129146
|
if (content.includes("return {") && !content.includes("local config")) {
|
|
128776
129147
|
content = content.replace(/return\s*\{/, "local config = {");
|
|
@@ -128796,7 +129167,7 @@ return config`);
|
|
|
128796
129167
|
${WEZTERM_DELETE_FIX}
|
|
128797
129168
|
`;
|
|
128798
129169
|
}
|
|
128799
|
-
const parentDir =
|
|
129170
|
+
const parentDir = dirname20(configPath);
|
|
128800
129171
|
if (!existsSync39(parentDir)) {
|
|
128801
129172
|
mkdirSync30(parentDir, { recursive: true });
|
|
128802
129173
|
}
|
|
@@ -129396,7 +129767,7 @@ __export(exports_custom, {
|
|
|
129396
129767
|
});
|
|
129397
129768
|
import { existsSync as existsSync40 } from "node:fs";
|
|
129398
129769
|
import { readdir as readdir10, readFile as readFile16 } from "node:fs/promises";
|
|
129399
|
-
import { basename as basename14, dirname as
|
|
129770
|
+
import { basename as basename14, dirname as dirname21, join as join47 } from "node:path";
|
|
129400
129771
|
async function getCustomCommands() {
|
|
129401
129772
|
if (cachedCommands !== null) {
|
|
129402
129773
|
return cachedCommands;
|
|
@@ -129457,7 +129828,7 @@ async function parseCommandFile(filePath, rootPath, source2) {
|
|
|
129457
129828
|
const content = await readFile16(filePath, "utf-8");
|
|
129458
129829
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
129459
129830
|
const id = basename14(filePath, ".md");
|
|
129460
|
-
const relativePath =
|
|
129831
|
+
const relativePath = dirname21(filePath).slice(rootPath.length);
|
|
129461
129832
|
const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
|
|
129462
129833
|
let description = getStringField(frontmatter, "description");
|
|
129463
129834
|
if (!description) {
|
|
@@ -129806,11 +130177,11 @@ var init_HelpDialog = __esm(async () => {
|
|
|
129806
130177
|
|
|
129807
130178
|
// src/hooks/writer.ts
|
|
129808
130179
|
import { homedir as homedir33 } from "node:os";
|
|
129809
|
-
import { resolve as
|
|
130180
|
+
import { resolve as resolve33 } from "node:path";
|
|
129810
130181
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
129811
130182
|
const home = process.env.HOME || homedir33();
|
|
129812
|
-
const globalSettingsPath =
|
|
129813
|
-
const projectSettingsPath =
|
|
130183
|
+
const globalSettingsPath = resolve33(home, ".letta", "settings.json");
|
|
130184
|
+
const projectSettingsPath = resolve33(workingDirectory, ".letta", "settings.json");
|
|
129814
130185
|
return globalSettingsPath === projectSettingsPath;
|
|
129815
130186
|
}
|
|
129816
130187
|
function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
|
|
@@ -132449,8 +132820,8 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
132449
132820
|
});
|
|
132450
132821
|
|
|
132451
132822
|
// src/cli/helpers/fileSearch.ts
|
|
132452
|
-
import { readdirSync as readdirSync13, statSync as
|
|
132453
|
-
import { join as join48, relative as relative17, resolve as
|
|
132823
|
+
import { readdirSync as readdirSync13, statSync as statSync12 } from "node:fs";
|
|
132824
|
+
import { join as join48, relative as relative17, resolve as resolve34 } from "node:path";
|
|
132454
132825
|
function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
|
|
132455
132826
|
if (results.length >= maxResults || depth >= maxDepth) {
|
|
132456
132827
|
return results;
|
|
@@ -132464,7 +132835,7 @@ function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [],
|
|
|
132464
132835
|
if (shouldHardExcludeEntry(entry, getIndexRoot())) {
|
|
132465
132836
|
continue;
|
|
132466
132837
|
}
|
|
132467
|
-
const stats =
|
|
132838
|
+
const stats = statSync12(fullPath);
|
|
132468
132839
|
const matches = pattern.length === 0 || relativePath.toLowerCase().includes(lowerPattern);
|
|
132469
132840
|
if (matches) {
|
|
132470
132841
|
results.push({
|
|
@@ -132493,9 +132864,9 @@ async function searchFiles(query, deep = false) {
|
|
|
132493
132864
|
const dirPart = query.slice(0, lastSlashIndex);
|
|
132494
132865
|
const pattern = query.slice(lastSlashIndex + 1);
|
|
132495
132866
|
try {
|
|
132496
|
-
const resolvedDir =
|
|
132867
|
+
const resolvedDir = resolve34(getIndexRoot(), dirPart);
|
|
132497
132868
|
try {
|
|
132498
|
-
|
|
132869
|
+
statSync12(resolvedDir);
|
|
132499
132870
|
searchDir = resolvedDir;
|
|
132500
132871
|
searchPattern = pattern;
|
|
132501
132872
|
} catch {}
|
|
@@ -132538,7 +132909,7 @@ async function searchFiles(query, deep = false) {
|
|
|
132538
132909
|
for (const entry of matchingEntries.slice(0, 50)) {
|
|
132539
132910
|
try {
|
|
132540
132911
|
const fullPath = join48(searchDir, entry);
|
|
132541
|
-
const stats =
|
|
132912
|
+
const stats = statSync12(fullPath);
|
|
132542
132913
|
const relativePath = relative17(getIndexRoot(), fullPath);
|
|
132543
132914
|
results.push({
|
|
132544
132915
|
path: relativePath,
|
|
@@ -134619,12 +134990,12 @@ import {
|
|
|
134619
134990
|
existsSync as existsSync41,
|
|
134620
134991
|
mkdirSync as mkdirSync31,
|
|
134621
134992
|
mkdtempSync,
|
|
134622
|
-
readFileSync as
|
|
134993
|
+
readFileSync as readFileSync27,
|
|
134623
134994
|
rmSync as rmSync4,
|
|
134624
134995
|
writeFileSync as writeFileSync22
|
|
134625
134996
|
} from "node:fs";
|
|
134626
134997
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
134627
|
-
import { dirname as
|
|
134998
|
+
import { dirname as dirname22, join as join49 } from "node:path";
|
|
134628
134999
|
function runCommand(command, args, cwd2, input) {
|
|
134629
135000
|
try {
|
|
134630
135001
|
return execFileSync4(command, args, {
|
|
@@ -134871,13 +135242,13 @@ function runGit3(args, cwd2) {
|
|
|
134871
135242
|
}
|
|
134872
135243
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
134873
135244
|
const absolutePath = join49(repoDir, workflowPath);
|
|
134874
|
-
if (!existsSync41(
|
|
134875
|
-
mkdirSync31(
|
|
135245
|
+
if (!existsSync41(dirname22(absolutePath))) {
|
|
135246
|
+
mkdirSync31(dirname22(absolutePath), { recursive: true });
|
|
134876
135247
|
}
|
|
134877
135248
|
const next = `${content.trimEnd()}
|
|
134878
135249
|
`;
|
|
134879
135250
|
if (existsSync41(absolutePath)) {
|
|
134880
|
-
const previous =
|
|
135251
|
+
const previous = readFileSync27(absolutePath, "utf8");
|
|
134881
135252
|
if (previous === next) {
|
|
134882
135253
|
return false;
|
|
134883
135254
|
}
|
|
@@ -147638,7 +148009,7 @@ async function executeStatusLineCommand(command, payload, options) {
|
|
|
147638
148009
|
};
|
|
147639
148010
|
}
|
|
147640
148011
|
function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory, startTime) {
|
|
147641
|
-
return new Promise((
|
|
148012
|
+
return new Promise((resolve35, reject) => {
|
|
147642
148013
|
const [executable, ...args] = launcher;
|
|
147643
148014
|
if (!executable) {
|
|
147644
148015
|
reject(new Error("Empty launcher"));
|
|
@@ -147651,7 +148022,7 @@ function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory,
|
|
|
147651
148022
|
const safeResolve = (result) => {
|
|
147652
148023
|
if (!resolved) {
|
|
147653
148024
|
resolved = true;
|
|
147654
|
-
|
|
148025
|
+
resolve35(result);
|
|
147655
148026
|
}
|
|
147656
148027
|
};
|
|
147657
148028
|
let child;
|
|
@@ -148098,7 +148469,7 @@ __export(exports_shellAliases, {
|
|
|
148098
148469
|
expandAliases: () => expandAliases,
|
|
148099
148470
|
clearAliasCache: () => clearAliasCache
|
|
148100
148471
|
});
|
|
148101
|
-
import { existsSync as existsSync44, readFileSync as
|
|
148472
|
+
import { existsSync as existsSync44, readFileSync as readFileSync28 } from "node:fs";
|
|
148102
148473
|
import { homedir as homedir36 } from "node:os";
|
|
148103
148474
|
import { join as join52 } from "node:path";
|
|
148104
148475
|
function parseAliasesFromFile(filePath) {
|
|
@@ -148107,7 +148478,7 @@ function parseAliasesFromFile(filePath) {
|
|
|
148107
148478
|
return aliases;
|
|
148108
148479
|
}
|
|
148109
148480
|
try {
|
|
148110
|
-
const content =
|
|
148481
|
+
const content = readFileSync28(filePath, "utf-8");
|
|
148111
148482
|
const lines = content.split(`
|
|
148112
148483
|
`);
|
|
148113
148484
|
let inFunction = false;
|
|
@@ -148826,14 +149197,14 @@ __export(exports_export, {
|
|
|
148826
149197
|
packageSkills: () => packageSkills
|
|
148827
149198
|
});
|
|
148828
149199
|
import { readdir as readdir11, readFile as readFile18 } from "node:fs/promises";
|
|
148829
|
-
import { relative as relative18, resolve as
|
|
149200
|
+
import { relative as relative18, resolve as resolve35 } from "node:path";
|
|
148830
149201
|
async function packageSkills(agentId, skillsDir) {
|
|
148831
149202
|
const skills = [];
|
|
148832
149203
|
const skillNames = new Set;
|
|
148833
149204
|
const dirsToCheck = skillsDir ? [skillsDir] : [
|
|
148834
149205
|
agentId && getAgentSkillsDir(agentId),
|
|
148835
|
-
|
|
148836
|
-
|
|
149206
|
+
resolve35(process.cwd(), ".skills"),
|
|
149207
|
+
resolve35(process.env.HOME || "~", ".letta", "skills")
|
|
148837
149208
|
].filter((dir) => Boolean(dir));
|
|
148838
149209
|
for (const baseDir of dirsToCheck) {
|
|
148839
149210
|
try {
|
|
@@ -148843,8 +149214,8 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
148843
149214
|
continue;
|
|
148844
149215
|
if (skillNames.has(entry.name))
|
|
148845
149216
|
continue;
|
|
148846
|
-
const skillDir =
|
|
148847
|
-
const skillMdPath =
|
|
149217
|
+
const skillDir = resolve35(baseDir, entry.name);
|
|
149218
|
+
const skillMdPath = resolve35(skillDir, "SKILL.md");
|
|
148848
149219
|
try {
|
|
148849
149220
|
await readFile18(skillMdPath, "utf-8");
|
|
148850
149221
|
} catch {
|
|
@@ -148874,7 +149245,7 @@ async function readSkillFiles(skillDir) {
|
|
|
148874
149245
|
async function walk(dir) {
|
|
148875
149246
|
const entries = await readdir11(dir, { withFileTypes: true });
|
|
148876
149247
|
for (const entry of entries) {
|
|
148877
|
-
const fullPath =
|
|
149248
|
+
const fullPath = resolve35(dir, entry.name);
|
|
148878
149249
|
if (entry.isDirectory()) {
|
|
148879
149250
|
await walk(fullPath);
|
|
148880
149251
|
} else {
|
|
@@ -149018,7 +149389,7 @@ __export(exports_App, {
|
|
|
149018
149389
|
default: () => App2
|
|
149019
149390
|
});
|
|
149020
149391
|
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
149021
|
-
import { existsSync as existsSync45, readFileSync as
|
|
149392
|
+
import { existsSync as existsSync45, readFileSync as readFileSync29, renameSync as renameSync3, writeFileSync as writeFileSync24 } from "node:fs";
|
|
149022
149393
|
import { homedir as homedir37, tmpdir as tmpdir7 } from "node:os";
|
|
149023
149394
|
import { join as join53, relative as relative19 } from "node:path";
|
|
149024
149395
|
function deriveReasoningEffort(modelSettings, llmConfig) {
|
|
@@ -149245,7 +149616,7 @@ function _readPlanFile(fallbackPlanFilePath) {
|
|
|
149245
149616
|
return `Plan file not found at ${planFilePath}`;
|
|
149246
149617
|
}
|
|
149247
149618
|
try {
|
|
149248
|
-
return
|
|
149619
|
+
return readFileSync29(planFilePath, "utf-8");
|
|
149249
149620
|
} catch {
|
|
149250
149621
|
return `Failed to read plan file at ${planFilePath}`;
|
|
149251
149622
|
}
|
|
@@ -150596,10 +150967,10 @@ function App2({
|
|
|
150596
150967
|
if (!planFilePath)
|
|
150597
150968
|
return;
|
|
150598
150969
|
try {
|
|
150599
|
-
const { readFileSync:
|
|
150970
|
+
const { readFileSync: readFileSync30, existsSync: existsSync46 } = __require("node:fs");
|
|
150600
150971
|
if (!existsSync46(planFilePath))
|
|
150601
150972
|
return;
|
|
150602
|
-
const planContent =
|
|
150973
|
+
const planContent = readFileSync30(planFilePath, "utf-8");
|
|
150603
150974
|
const previewItem = {
|
|
150604
150975
|
kind: "approval_preview",
|
|
150605
150976
|
id: `approval-preview-${toolCallId}`,
|
|
@@ -151009,12 +151380,12 @@ Memory may be stale. Try running: git -C ~/.letta/agents/${agentId}/memory pull`
|
|
|
151009
151380
|
let watcher = null;
|
|
151010
151381
|
(async () => {
|
|
151011
151382
|
try {
|
|
151012
|
-
const { watch:
|
|
151383
|
+
const { watch: watch3 } = await import("node:fs");
|
|
151013
151384
|
const { existsSync: existsSync46 } = await import("node:fs");
|
|
151014
151385
|
const memRoot = getMemoryFilesystemRoot(agentId);
|
|
151015
151386
|
if (!existsSync46(memRoot))
|
|
151016
151387
|
return;
|
|
151017
|
-
watcher =
|
|
151388
|
+
watcher = watch3(memRoot, { recursive: true }, () => {});
|
|
151018
151389
|
memfsWatcherRef.current = watcher;
|
|
151019
151390
|
debugLog("memfs", `Watching memory directory: ${memRoot}`);
|
|
151020
151391
|
watcher.on("error", (err) => {
|
|
@@ -151341,7 +151712,7 @@ ${newState.originalPrompt}`,
|
|
|
151341
151712
|
cancelled = true;
|
|
151342
151713
|
break;
|
|
151343
151714
|
}
|
|
151344
|
-
await new Promise((
|
|
151715
|
+
await new Promise((resolve36) => setTimeout(resolve36, 100));
|
|
151345
151716
|
}
|
|
151346
151717
|
buffersRef.current.byId.delete(statusId);
|
|
151347
151718
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
@@ -151405,7 +151776,7 @@ ${newState.originalPrompt}`,
|
|
|
151405
151776
|
cancelled = true;
|
|
151406
151777
|
break;
|
|
151407
151778
|
}
|
|
151408
|
-
await new Promise((
|
|
151779
|
+
await new Promise((resolve36) => setTimeout(resolve36, 100));
|
|
151409
151780
|
}
|
|
151410
151781
|
if (retryStatusId) {
|
|
151411
151782
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -152155,7 +152526,7 @@ ${feedback}
|
|
|
152155
152526
|
});
|
|
152156
152527
|
buffersRef.current.order.push(statusId);
|
|
152157
152528
|
refreshDerived();
|
|
152158
|
-
await new Promise((
|
|
152529
|
+
await new Promise((resolve36) => setTimeout(resolve36, delayMs));
|
|
152159
152530
|
buffersRef.current.byId.delete(statusId);
|
|
152160
152531
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
152161
152532
|
refreshDerived();
|
|
@@ -152215,7 +152586,7 @@ ${feedback}
|
|
|
152215
152586
|
cancelled = true;
|
|
152216
152587
|
break;
|
|
152217
152588
|
}
|
|
152218
|
-
await new Promise((
|
|
152589
|
+
await new Promise((resolve36) => setTimeout(resolve36, 100));
|
|
152219
152590
|
}
|
|
152220
152591
|
if (retryStatusId) {
|
|
152221
152592
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -153377,7 +153748,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
|
|
|
153377
153748
|
];
|
|
153378
153749
|
const personaPath = personaCandidates.find((candidate) => existsSync45(candidate));
|
|
153379
153750
|
if (personaPath) {
|
|
153380
|
-
const personaContent =
|
|
153751
|
+
const personaContent = readFileSync29(personaPath, "utf-8");
|
|
153381
153752
|
setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
|
|
153382
153753
|
} else {
|
|
153383
153754
|
setCurrentPersonalityId(null);
|
|
@@ -158272,11 +158643,11 @@ import {
|
|
|
158272
158643
|
copyFileSync as copyFileSync2,
|
|
158273
158644
|
existsSync as existsSync46,
|
|
158274
158645
|
mkdirSync as mkdirSync33,
|
|
158275
|
-
readFileSync as
|
|
158646
|
+
readFileSync as readFileSync30,
|
|
158276
158647
|
writeFileSync as writeFileSync25
|
|
158277
158648
|
} from "node:fs";
|
|
158278
158649
|
import { homedir as homedir38, platform as platform7 } from "node:os";
|
|
158279
|
-
import { dirname as
|
|
158650
|
+
import { dirname as dirname23, join as join54 } from "node:path";
|
|
158280
158651
|
function detectTerminalType2() {
|
|
158281
158652
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
158282
158653
|
return "cursor";
|
|
@@ -158342,7 +158713,7 @@ function keybindingExists2(keybindingsPath) {
|
|
|
158342
158713
|
if (!existsSync46(keybindingsPath))
|
|
158343
158714
|
return false;
|
|
158344
158715
|
try {
|
|
158345
|
-
const content =
|
|
158716
|
+
const content = readFileSync30(keybindingsPath, { encoding: "utf-8" });
|
|
158346
158717
|
const keybindings = parseKeybindings2(content);
|
|
158347
158718
|
if (!keybindings)
|
|
158348
158719
|
return false;
|
|
@@ -158367,7 +158738,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
158367
158738
|
if (keybindingExists2(keybindingsPath)) {
|
|
158368
158739
|
return { success: true, alreadyExists: true };
|
|
158369
158740
|
}
|
|
158370
|
-
const parentDir =
|
|
158741
|
+
const parentDir = dirname23(keybindingsPath);
|
|
158371
158742
|
if (!existsSync46(parentDir)) {
|
|
158372
158743
|
mkdirSync33(parentDir, { recursive: true });
|
|
158373
158744
|
}
|
|
@@ -158375,7 +158746,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
158375
158746
|
let backupPath = null;
|
|
158376
158747
|
if (existsSync46(keybindingsPath)) {
|
|
158377
158748
|
backupPath = createBackup2(keybindingsPath);
|
|
158378
|
-
const content =
|
|
158749
|
+
const content = readFileSync30(keybindingsPath, { encoding: "utf-8" });
|
|
158379
158750
|
const parsed = parseKeybindings2(content);
|
|
158380
158751
|
if (parsed === null) {
|
|
158381
158752
|
return {
|
|
@@ -158406,7 +158777,7 @@ function removeKeybinding2(keybindingsPath) {
|
|
|
158406
158777
|
if (!existsSync46(keybindingsPath)) {
|
|
158407
158778
|
return { success: true };
|
|
158408
158779
|
}
|
|
158409
|
-
const content =
|
|
158780
|
+
const content = readFileSync30(keybindingsPath, { encoding: "utf-8" });
|
|
158410
158781
|
const keybindings = parseKeybindings2(content);
|
|
158411
158782
|
if (!keybindings) {
|
|
158412
158783
|
return {
|
|
@@ -158483,7 +158854,7 @@ function wezTermDeleteFixExists2(configPath) {
|
|
|
158483
158854
|
if (!existsSync46(configPath))
|
|
158484
158855
|
return false;
|
|
158485
158856
|
try {
|
|
158486
|
-
const content =
|
|
158857
|
+
const content = readFileSync30(configPath, { encoding: "utf-8" });
|
|
158487
158858
|
return content.includes("Letta Code: Fix Delete key") || content.includes("key = 'Delete'") && content.includes("SendString") && content.includes("\\x1b[3~");
|
|
158488
158859
|
} catch {
|
|
158489
158860
|
return false;
|
|
@@ -158500,7 +158871,7 @@ function installWezTermDeleteFix2() {
|
|
|
158500
158871
|
if (existsSync46(configPath)) {
|
|
158501
158872
|
backupPath = `${configPath}.letta-backup`;
|
|
158502
158873
|
copyFileSync2(configPath, backupPath);
|
|
158503
|
-
content =
|
|
158874
|
+
content = readFileSync30(configPath, { encoding: "utf-8" });
|
|
158504
158875
|
}
|
|
158505
158876
|
if (content.includes("return {") && !content.includes("local config")) {
|
|
158506
158877
|
content = content.replace(/return\s*\{/, "local config = {");
|
|
@@ -158526,7 +158897,7 @@ return config`);
|
|
|
158526
158897
|
${WEZTERM_DELETE_FIX2}
|
|
158527
158898
|
`;
|
|
158528
158899
|
}
|
|
158529
|
-
const parentDir =
|
|
158900
|
+
const parentDir = dirname23(configPath);
|
|
158530
158901
|
if (!existsSync46(parentDir)) {
|
|
158531
158902
|
mkdirSync33(parentDir, { recursive: true });
|
|
158532
158903
|
}
|
|
@@ -159096,10 +159467,10 @@ __export(exports_import2, {
|
|
|
159096
159467
|
});
|
|
159097
159468
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
159098
159469
|
import { chmod as chmod2, mkdir as mkdir11, readFile as readFile19, writeFile as writeFile14 } from "node:fs/promises";
|
|
159099
|
-
import { dirname as
|
|
159470
|
+
import { dirname as dirname24, resolve as resolve36 } from "node:path";
|
|
159100
159471
|
async function importAgentFromFile2(options) {
|
|
159101
159472
|
const client = await getClient();
|
|
159102
|
-
const resolvedPath =
|
|
159473
|
+
const resolvedPath = resolve36(options.filePath);
|
|
159103
159474
|
const file = createReadStream2(resolvedPath);
|
|
159104
159475
|
const importResponse = await client.agents.importFile({
|
|
159105
159476
|
file,
|
|
@@ -159134,7 +159505,7 @@ async function extractSkillsFromAf2(afPath, destDir) {
|
|
|
159134
159505
|
return [];
|
|
159135
159506
|
}
|
|
159136
159507
|
for (const skill2 of afData.skills) {
|
|
159137
|
-
const skillDir =
|
|
159508
|
+
const skillDir = resolve36(destDir, skill2.name);
|
|
159138
159509
|
await mkdir11(skillDir, { recursive: true });
|
|
159139
159510
|
if (skill2.files) {
|
|
159140
159511
|
await writeSkillFiles2(skillDir, skill2.files);
|
|
@@ -159154,8 +159525,8 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
159154
159525
|
}
|
|
159155
159526
|
}
|
|
159156
159527
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
159157
|
-
const fullPath =
|
|
159158
|
-
await mkdir11(
|
|
159528
|
+
const fullPath = resolve36(skillDir, filePath);
|
|
159529
|
+
await mkdir11(dirname24(fullPath), { recursive: true });
|
|
159159
159530
|
await writeFile14(fullPath, content, "utf-8");
|
|
159160
159531
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
159161
159532
|
if (isScript) {
|
|
@@ -159268,7 +159639,7 @@ __export(exports_memoryFilesystem2, {
|
|
|
159268
159639
|
});
|
|
159269
159640
|
import { existsSync as existsSync47, mkdirSync as mkdirSync34 } from "node:fs";
|
|
159270
159641
|
import { homedir as homedir40 } from "node:os";
|
|
159271
|
-
import { join as join56, resolve as
|
|
159642
|
+
import { join as join56, resolve as resolve37 } from "node:path";
|
|
159272
159643
|
function getMemoryFilesystemRoot2(agentId, homeDir = homedir40()) {
|
|
159273
159644
|
return join56(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
159274
159645
|
}
|
|
@@ -159290,7 +159661,7 @@ function resolveScopedMemoryDir2(options = {}) {
|
|
|
159290
159661
|
} catch {}
|
|
159291
159662
|
const directMemoryDir = (env4.LETTA_MEMORY_DIR || env4.MEMORY_DIR || "").trim();
|
|
159292
159663
|
if (directMemoryDir) {
|
|
159293
|
-
return
|
|
159664
|
+
return resolve37(directMemoryDir);
|
|
159294
159665
|
}
|
|
159295
159666
|
const envAgentId = (env4.LETTA_AGENT_ID || env4.AGENT_ID || "").trim();
|
|
159296
159667
|
if (envAgentId) {
|
|
@@ -159519,9 +159890,9 @@ function getServerHostLabel2(serverUrl) {
|
|
|
159519
159890
|
}
|
|
159520
159891
|
}
|
|
159521
159892
|
async function isLettaMemfsServer2() {
|
|
159522
|
-
const { getMemfsServerUrl: getMemfsServerUrl2
|
|
159893
|
+
const { getMemfsServerUrl: getMemfsServerUrl2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
159523
159894
|
const memfsServerUrl = getMemfsServerUrl2();
|
|
159524
|
-
return memfsServerUrl.includes("api.letta.com") ||
|
|
159895
|
+
return memfsServerUrl.includes("api.letta.com") || process.env.LETTA_MEMFS_LOCAL === "1" || process.env.LETTA_API_KEY === "local-desktop";
|
|
159525
159896
|
}
|
|
159526
159897
|
async function getMemfsSyncUnavailableMessage2() {
|
|
159527
159898
|
const { getMemfsServerUrl: getMemfsServerUrl2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
@@ -164440,11 +164811,11 @@ async function runListenSubcommand(argv) {
|
|
|
164440
164811
|
connectionName = hostname3();
|
|
164441
164812
|
settingsManager.setListenerEnvName(connectionName);
|
|
164442
164813
|
} else {
|
|
164443
|
-
connectionName = await new Promise((
|
|
164814
|
+
connectionName = await new Promise((resolve28) => {
|
|
164444
164815
|
const { unmount } = render_default(/* @__PURE__ */ jsx_dev_runtime9.jsxDEV(PromptEnvName, {
|
|
164445
164816
|
onSubmit: (name) => {
|
|
164446
164817
|
unmount();
|
|
164447
|
-
|
|
164818
|
+
resolve28(name);
|
|
164448
164819
|
}
|
|
164449
164820
|
}, undefined, false, undefined, this));
|
|
164450
164821
|
});
|
|
@@ -164646,7 +165017,7 @@ async function runListenSubcommand(argv) {
|
|
|
164646
165017
|
|
|
164647
165018
|
// src/cli/subcommands/memory.ts
|
|
164648
165019
|
init_memoryGit();
|
|
164649
|
-
import { cpSync, existsSync as existsSync30, mkdirSync as mkdirSync23, rmSync as rmSync3, statSync as
|
|
165020
|
+
import { cpSync, existsSync as existsSync30, mkdirSync as mkdirSync23, rmSync as rmSync3, statSync as statSync9 } from "node:fs";
|
|
164650
165021
|
import { readdir as readdir7 } from "node:fs/promises";
|
|
164651
165022
|
import { homedir as homedir23 } from "node:os";
|
|
164652
165023
|
import { join as join34 } from "node:path";
|
|
@@ -164814,7 +165185,7 @@ async function listBackups(agentId) {
|
|
|
164814
165185
|
const path26 = join34(agentRoot, entry.name);
|
|
164815
165186
|
let createdAt = null;
|
|
164816
165187
|
try {
|
|
164817
|
-
const stat7 =
|
|
165188
|
+
const stat7 = statSync9(path26);
|
|
164818
165189
|
createdAt = stat7.mtime.toISOString();
|
|
164819
165190
|
} catch {
|
|
164820
165191
|
createdAt = null;
|
|
@@ -164932,7 +165303,7 @@ async function runMemorySubcommand(argv) {
|
|
|
164932
165303
|
console.error(`Backup not found: ${backupPath}`);
|
|
164933
165304
|
return 1;
|
|
164934
165305
|
}
|
|
164935
|
-
const stat7 =
|
|
165306
|
+
const stat7 = statSync9(backupPath);
|
|
164936
165307
|
if (!stat7.isDirectory()) {
|
|
164937
165308
|
console.error(`Backup path is not a directory: ${backupPath}`);
|
|
164938
165309
|
return 1;
|
|
@@ -164955,7 +165326,7 @@ async function runMemorySubcommand(argv) {
|
|
|
164955
165326
|
return 1;
|
|
164956
165327
|
}
|
|
164957
165328
|
if (existsSync30(out)) {
|
|
164958
|
-
const stat7 =
|
|
165329
|
+
const stat7 = statSync9(out);
|
|
164959
165330
|
if (stat7.isDirectory()) {
|
|
164960
165331
|
const contents = await readdir7(out);
|
|
164961
165332
|
if (contents.length > 0) {
|
|
@@ -164986,7 +165357,7 @@ async function runMemorySubcommand(argv) {
|
|
|
164986
165357
|
init_client2();
|
|
164987
165358
|
init_settings_manager();
|
|
164988
165359
|
import { writeFile as writeFile11 } from "node:fs/promises";
|
|
164989
|
-
import { resolve as
|
|
165360
|
+
import { resolve as resolve28 } from "node:path";
|
|
164990
165361
|
import { parseArgs as parseArgs9 } from "node:util";
|
|
164991
165362
|
function printUsage6() {
|
|
164992
165363
|
console.log(`
|
|
@@ -165291,7 +165662,7 @@ async function runMessagesSubcommand(argv) {
|
|
|
165291
165662
|
|
|
165292
165663
|
`).trim();
|
|
165293
165664
|
if (outputPathRaw && typeof outputPathRaw === "string") {
|
|
165294
|
-
const outputPath =
|
|
165665
|
+
const outputPath = resolve28(process.cwd(), outputPathRaw);
|
|
165295
165666
|
await writeFile11(outputPath, `${transcript}
|
|
165296
165667
|
`, "utf-8");
|
|
165297
165668
|
console.log(JSON.stringify({
|
|
@@ -165740,7 +166111,7 @@ init_fs();
|
|
|
165740
166111
|
init_secrets();
|
|
165741
166112
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
165742
166113
|
import { homedir as homedir25 } from "node:os";
|
|
165743
|
-
import { join as join36, resolve as
|
|
166114
|
+
import { join as join36, resolve as resolve29 } from "node:path";
|
|
165744
166115
|
var DEFAULT_SETTINGS3 = {
|
|
165745
166116
|
lastAgent: null,
|
|
165746
166117
|
tokenStreaming: false,
|
|
@@ -166219,7 +166590,7 @@ class SettingsManager2 {
|
|
|
166219
166590
|
return join36(workingDirectory, ".letta", "settings.json");
|
|
166220
166591
|
}
|
|
166221
166592
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
166222
|
-
return
|
|
166593
|
+
return resolve29(this.getProjectSettingsPath(workingDirectory)) === resolve29(this.getSettingsPath());
|
|
166223
166594
|
}
|
|
166224
166595
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
166225
166596
|
return join36(workingDirectory, ".letta", "settings.local.json");
|
|
@@ -167251,8 +167622,8 @@ function acquireSwitchLock2() {
|
|
|
167251
167622
|
const lock = getSwitchLock2();
|
|
167252
167623
|
lock.refCount++;
|
|
167253
167624
|
if (lock.refCount === 1) {
|
|
167254
|
-
lock.promise = new Promise((
|
|
167255
|
-
lock.resolve =
|
|
167625
|
+
lock.promise = new Promise((resolve30) => {
|
|
167626
|
+
lock.resolve = resolve30;
|
|
167256
167627
|
});
|
|
167257
167628
|
}
|
|
167258
167629
|
}
|
|
@@ -167737,7 +168108,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
167737
168108
|
printHelp();
|
|
167738
168109
|
const helpDelayMs = Number.parseInt(process.env.LETTA_TEST_HELP_EXIT_DELAY_MS ?? "", 10);
|
|
167739
168110
|
if (Number.isFinite(helpDelayMs) && helpDelayMs > 0) {
|
|
167740
|
-
await new Promise((
|
|
168111
|
+
await new Promise((resolve38) => setTimeout(resolve38, helpDelayMs));
|
|
167741
168112
|
}
|
|
167742
168113
|
process.exit(0);
|
|
167743
168114
|
}
|
|
@@ -167959,9 +168330,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
167959
168330
|
process.exit(1);
|
|
167960
168331
|
}
|
|
167961
168332
|
} else {
|
|
167962
|
-
const { resolve:
|
|
168333
|
+
const { resolve: resolve38 } = await import("path");
|
|
167963
168334
|
const { existsSync: existsSync48 } = await import("fs");
|
|
167964
|
-
const resolvedPath =
|
|
168335
|
+
const resolvedPath = resolve38(fromAfFile);
|
|
167965
168336
|
if (!existsSync48(resolvedPath)) {
|
|
167966
168337
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
167967
168338
|
process.exit(1);
|
|
@@ -167981,6 +168352,12 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
167981
168352
|
}
|
|
167982
168353
|
const apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
|
|
167983
168354
|
const baseURL = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL2;
|
|
168355
|
+
if (isHeadless && baseURL === LETTA_CLOUD_API_URL2 && !process.env.LETTA_API_KEY) {
|
|
168356
|
+
console.error("Missing LETTA_API_KEY");
|
|
168357
|
+
console.error("Headless mode requires an API key set via the LETTA_API_KEY environment variable.");
|
|
168358
|
+
console.error("Get an API key at https://app.letta.com/api-keys");
|
|
168359
|
+
process.exit(1);
|
|
168360
|
+
}
|
|
167984
168361
|
if (!isHeadless && baseURL === LETTA_CLOUD_API_URL2 && !settings.refreshToken && !apiKey) {
|
|
167985
168362
|
const { runSetup: runSetup2 } = await init_setup4().then(() => exports_setup);
|
|
167986
168363
|
await runSetup2();
|
|
@@ -167996,11 +168373,6 @@ Error: ${message}`);
|
|
|
167996
168373
|
});
|
|
167997
168374
|
}
|
|
167998
168375
|
if (!apiKey && baseURL === LETTA_CLOUD_API_URL2) {
|
|
167999
|
-
if (isHeadless) {
|
|
168000
|
-
console.error("Missing LETTA_API_KEY");
|
|
168001
|
-
console.error("Run 'letta' in interactive mode to authenticate or export the missing environment variable");
|
|
168002
|
-
process.exit(1);
|
|
168003
|
-
}
|
|
168004
168376
|
console.log(`No credentials found. Let's get you set up!
|
|
168005
168377
|
`);
|
|
168006
168378
|
const { runSetup: runSetup2 } = await init_setup4().then(() => exports_setup);
|
|
@@ -168849,4 +169221,4 @@ Error during initialization: ${message}`);
|
|
|
168849
169221
|
}
|
|
168850
169222
|
main();
|
|
168851
169223
|
|
|
168852
|
-
//# debugId=
|
|
169224
|
+
//# debugId=25A0545792FBAA5C64756E2164756E21
|