@letta-ai/letta-code 0.28.3 → 0.28.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-presets.js +3 -1
- package/dist/agent-presets.js.map +3 -3
- package/dist/types/agent/model-catalog.d.ts +27 -0
- package/dist/types/agent/model-catalog.d.ts.map +1 -1
- package/dist/types/agent-presets.d.ts +1 -0
- package/dist/types/agent-presets.d.ts.map +1 -1
- package/letta.js +890 -740
- package/package.json +1 -1
- package/scripts/source-file-size-baseline.json +2 -2
package/letta.js
CHANGED
|
@@ -4815,7 +4815,7 @@ var package_default;
|
|
|
4815
4815
|
var init_package = __esm(() => {
|
|
4816
4816
|
package_default = {
|
|
4817
4817
|
name: "@letta-ai/letta-code",
|
|
4818
|
-
version: "0.28.
|
|
4818
|
+
version: "0.28.4",
|
|
4819
4819
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
4820
4820
|
type: "module",
|
|
4821
4821
|
packageManager: "bun@1.3.0",
|
|
@@ -154418,6 +154418,23 @@ function resolveProviderFromModelHandle(model) {
|
|
|
154418
154418
|
return;
|
|
154419
154419
|
return PI_PROVIDER_SPECS.find((provider) => provider.handlePrefixes.some((prefix) => model.startsWith(prefix)))?.id;
|
|
154420
154420
|
}
|
|
154421
|
+
function resolvePiModelIdentity(model) {
|
|
154422
|
+
const provider = resolveProviderFromModelHandle(model);
|
|
154423
|
+
if (!model || !provider)
|
|
154424
|
+
return;
|
|
154425
|
+
const modelId = stripProviderHandlePrefix(model, provider);
|
|
154426
|
+
return modelId ? `${provider}/${modelId}` : undefined;
|
|
154427
|
+
}
|
|
154428
|
+
function isResolvablePiModelHandle(model) {
|
|
154429
|
+
const provider = resolveProviderFromModelHandle(model);
|
|
154430
|
+
if (!model || !provider)
|
|
154431
|
+
return false;
|
|
154432
|
+
const spec = getPiProviderSpec(provider);
|
|
154433
|
+
if (!spec.piProvider)
|
|
154434
|
+
return spec.createCustomModel === true;
|
|
154435
|
+
const modelId = stripProviderHandlePrefix(model, provider);
|
|
154436
|
+
return getModels(spec.piProvider).some((entry) => entry.id === modelId);
|
|
154437
|
+
}
|
|
154421
154438
|
function resolveProviderFromProviderType(providerType) {
|
|
154422
154439
|
if (typeof providerType !== "string")
|
|
154423
154440
|
return;
|
|
@@ -154569,6 +154586,11 @@ var init_pi_provider_registry = __esm(() => {
|
|
|
154569
154586
|
baseUrlEnv: () => process.env.GOOGLE_GENERATIVE_AI_BASE_URL,
|
|
154570
154587
|
envConfigured: () => hasEnvValue(process.env.GOOGLE_GENERATIVE_AI_API_KEY) || getEnvApiKey("google") !== undefined
|
|
154571
154588
|
},
|
|
154589
|
+
"google-vertex": {
|
|
154590
|
+
providerTypes: ["google-vertex", "google_vertex"],
|
|
154591
|
+
handlePrefixes: ["google-vertex/", "google_vertex/"],
|
|
154592
|
+
localProviderNames: ["google-vertex", "google_vertex"]
|
|
154593
|
+
},
|
|
154572
154594
|
"amazon-bedrock": {
|
|
154573
154595
|
providerTypes: ["amazon-bedrock", "bedrock"],
|
|
154574
154596
|
handlePrefixes: ["amazon-bedrock/", "bedrock/"],
|
|
@@ -155407,6 +155429,7 @@ __export(exports_available_models, {
|
|
|
155407
155429
|
getModelContextWindow: () => getModelContextWindow,
|
|
155408
155430
|
getCachedModelProviderTypes: () => getCachedModelProviderTypes,
|
|
155409
155431
|
getCachedModelHandles: () => getCachedModelHandles,
|
|
155432
|
+
getCachedAvailableModels: () => getCachedAvailableModels,
|
|
155410
155433
|
getAvailableModelsCacheInfo: () => getAvailableModelsCacheInfo,
|
|
155411
155434
|
getAvailableModelHandles: () => getAvailableModelHandles,
|
|
155412
155435
|
clearAvailableModelsCache: () => clearAvailableModelsCache
|
|
@@ -155441,11 +155464,15 @@ function getCachedModelProviderTypes() {
|
|
|
155441
155464
|
}
|
|
155442
155465
|
return new Map(cache.providerTypes);
|
|
155443
155466
|
}
|
|
155467
|
+
function getCachedAvailableModels() {
|
|
155468
|
+
return cache?.models.map((model) => ({ ...model })) ?? null;
|
|
155469
|
+
}
|
|
155444
155470
|
async function fetchFromNetwork() {
|
|
155445
155471
|
const modelsList2 = await getBackend().listModels();
|
|
155446
155472
|
const handles = new Set(modelsList2.map((m2) => m2.handle).filter((h2) => !!h2));
|
|
155447
155473
|
const contextWindows = new Map;
|
|
155448
155474
|
const providerTypes = new Map;
|
|
155475
|
+
const modelsByHandle = new Map;
|
|
155449
155476
|
for (const model of modelsList2) {
|
|
155450
155477
|
if (model.handle && model.max_context_window) {
|
|
155451
155478
|
contextWindows.set(model.handle, model.max_context_window);
|
|
@@ -155454,8 +155481,27 @@ async function fetchFromNetwork() {
|
|
|
155454
155481
|
if (model.handle && providerType) {
|
|
155455
155482
|
providerTypes.set(model.handle, providerType);
|
|
155456
155483
|
}
|
|
155484
|
+
if (model.handle) {
|
|
155485
|
+
const label = typeof model.display_name === "string" && model.display_name || typeof model.name === "string" && model.name || typeof model.model === "string" && model.model || model.handle;
|
|
155486
|
+
const availableModel = {
|
|
155487
|
+
handle: model.handle,
|
|
155488
|
+
label,
|
|
155489
|
+
...typeof model.max_context_window === "number" ? { maxContextWindow: model.max_context_window } : {},
|
|
155490
|
+
...typeof model.max_tokens === "number" ? { maxOutputTokens: model.max_tokens } : {},
|
|
155491
|
+
...providerType ? { providerType } : {}
|
|
155492
|
+
};
|
|
155493
|
+
if (!modelsByHandle.has(model.handle)) {
|
|
155494
|
+
modelsByHandle.set(model.handle, availableModel);
|
|
155495
|
+
}
|
|
155496
|
+
}
|
|
155457
155497
|
}
|
|
155458
|
-
return {
|
|
155498
|
+
return {
|
|
155499
|
+
handles,
|
|
155500
|
+
contextWindows,
|
|
155501
|
+
providerTypes,
|
|
155502
|
+
models: [...modelsByHandle.values()],
|
|
155503
|
+
fetchedAt: Date.now()
|
|
155504
|
+
};
|
|
155459
155505
|
}
|
|
155460
155506
|
async function getAvailableModelHandles(options3) {
|
|
155461
155507
|
const forceRefresh = options3?.forceRefresh === true;
|
|
@@ -155464,6 +155510,7 @@ async function getAvailableModelHandles(options3) {
|
|
|
155464
155510
|
return {
|
|
155465
155511
|
handles: cache.handles,
|
|
155466
155512
|
providerTypes: cache.providerTypes,
|
|
155513
|
+
models: cache.models,
|
|
155467
155514
|
source: "cache",
|
|
155468
155515
|
fetchedAt: cache.fetchedAt
|
|
155469
155516
|
};
|
|
@@ -155473,6 +155520,7 @@ async function getAvailableModelHandles(options3) {
|
|
|
155473
155520
|
return {
|
|
155474
155521
|
handles: entry2.handles,
|
|
155475
155522
|
providerTypes: entry2.providerTypes,
|
|
155523
|
+
models: entry2.models,
|
|
155476
155524
|
source: "network",
|
|
155477
155525
|
fetchedAt: entry2.fetchedAt
|
|
155478
155526
|
};
|
|
@@ -155497,6 +155545,7 @@ async function getAvailableModelHandles(options3) {
|
|
|
155497
155545
|
return {
|
|
155498
155546
|
handles: entry.handles,
|
|
155499
155547
|
providerTypes: entry.providerTypes,
|
|
155548
|
+
models: entry.models,
|
|
155500
155549
|
source: "network",
|
|
155501
155550
|
fetchedAt: entry.fetchedAt
|
|
155502
155551
|
};
|
|
@@ -392147,6 +392196,200 @@ var init_memory_filesystem2 = __esm(() => {
|
|
|
392147
392196
|
MEMORY_TREE_MAX_CHILDREN_PER_DIR = DIRECTORY_LIMIT_DEFAULTS.memfsTreeMaxChildrenPerDir;
|
|
392148
392197
|
});
|
|
392149
392198
|
|
|
392199
|
+
// src/agent/memory-git-hooks.ts
|
|
392200
|
+
import { chmodSync as chmodSync4, existsSync as existsSync31, mkdirSync as mkdirSync22, writeFileSync as writeFileSync16 } from "node:fs";
|
|
392201
|
+
import { join as join38 } from "node:path";
|
|
392202
|
+
function installPreCommitHook(dir) {
|
|
392203
|
+
const hooksDir = join38(dir, ".git", "hooks");
|
|
392204
|
+
const hookPath = join38(hooksDir, "pre-commit");
|
|
392205
|
+
if (!existsSync31(hooksDir)) {
|
|
392206
|
+
mkdirSync22(hooksDir, { recursive: true });
|
|
392207
|
+
}
|
|
392208
|
+
writeFileSync16(hookPath, PRE_COMMIT_HOOK_SCRIPT, "utf-8");
|
|
392209
|
+
chmodSync4(hookPath, 493);
|
|
392210
|
+
debugLog("memfs-git", "Installed pre-commit hook");
|
|
392211
|
+
}
|
|
392212
|
+
function installPostCommitHook(dir) {
|
|
392213
|
+
const hooksDir = join38(dir, ".git", "hooks");
|
|
392214
|
+
const hookPath = join38(hooksDir, "post-commit");
|
|
392215
|
+
if (!existsSync31(hooksDir)) {
|
|
392216
|
+
mkdirSync22(hooksDir, { recursive: true });
|
|
392217
|
+
}
|
|
392218
|
+
writeFileSync16(hookPath, POST_COMMIT_HOOK_SCRIPT, "utf-8");
|
|
392219
|
+
chmodSync4(hookPath, 493);
|
|
392220
|
+
debugLog("memfs-git", "Installed post-commit memory-repository hook");
|
|
392221
|
+
}
|
|
392222
|
+
var PRE_COMMIT_HOOK_SCRIPT = `#!/usr/bin/env bash
|
|
392223
|
+
# Validate frontmatter in staged memory .md files
|
|
392224
|
+
# Installed by Letta Code CLI
|
|
392225
|
+
|
|
392226
|
+
AGENT_EDITABLE_KEYS="description"
|
|
392227
|
+
PROTECTED_KEYS="read_only"
|
|
392228
|
+
ALL_KNOWN_KEYS="description read_only limit"
|
|
392229
|
+
errors=""
|
|
392230
|
+
|
|
392231
|
+
# Skills must always be directories: skills/<name>/SKILL.md
|
|
392232
|
+
# Reject legacy flat skill files (both current and legacy repo layouts).
|
|
392233
|
+
for file in $(git diff --cached --name-only --diff-filter=ACMR | grep -E '^(memory/)?skills/[^/]+\\.md$' || true); do
|
|
392234
|
+
errors="$errors\\n $file: invalid skill path (skills must be folders). Use skills/<name>/SKILL.md"
|
|
392235
|
+
done
|
|
392236
|
+
|
|
392237
|
+
# Helper: extract a frontmatter value from content
|
|
392238
|
+
get_fm_value() {
|
|
392239
|
+
local content="$1" key="$2"
|
|
392240
|
+
local closing_line
|
|
392241
|
+
closing_line=$(echo "$content" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
|
|
392242
|
+
[ -z "$closing_line" ] && return
|
|
392243
|
+
echo "$content" | tail -n +2 | head -n $((closing_line - 1)) | grep "^$key:" | cut -d: -f2- | sed 's/^ *//;s/ *$//'
|
|
392244
|
+
}
|
|
392245
|
+
|
|
392246
|
+
# Match .md files under system/ or reference/ (with optional memory/ prefix).
|
|
392247
|
+
# Skip skill SKILL.md files — they use a different frontmatter format.
|
|
392248
|
+
for file in $(git diff --cached --name-only --diff-filter=ACM | grep -E '^(memory/)?(system|reference)/.*\\.md$'); do
|
|
392249
|
+
staged=$(git show ":$file")
|
|
392250
|
+
|
|
392251
|
+
# Frontmatter is required
|
|
392252
|
+
first_line=$(echo "$staged" | head -1)
|
|
392253
|
+
if [ "$first_line" != "---" ]; then
|
|
392254
|
+
errors="$errors\\n $file: missing frontmatter (must start with ---)"
|
|
392255
|
+
continue
|
|
392256
|
+
fi
|
|
392257
|
+
|
|
392258
|
+
# Check frontmatter is properly closed
|
|
392259
|
+
closing_line=$(echo "$staged" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
|
|
392260
|
+
if [ -z "$closing_line" ]; then
|
|
392261
|
+
errors="$errors\\n $file: frontmatter opened but never closed (missing closing ---)"
|
|
392262
|
+
continue
|
|
392263
|
+
fi
|
|
392264
|
+
|
|
392265
|
+
# Check read_only protection against HEAD version
|
|
392266
|
+
head_content=$(git show "HEAD:$file" 2>/dev/null || true)
|
|
392267
|
+
if [ -n "$head_content" ]; then
|
|
392268
|
+
head_ro=$(get_fm_value "$head_content" "read_only")
|
|
392269
|
+
if [ "$head_ro" = "true" ]; then
|
|
392270
|
+
errors="$errors\\n $file: file is read_only and cannot be modified"
|
|
392271
|
+
continue
|
|
392272
|
+
fi
|
|
392273
|
+
fi
|
|
392274
|
+
|
|
392275
|
+
# Extract frontmatter lines
|
|
392276
|
+
frontmatter=$(echo "$staged" | tail -n +2 | head -n $((closing_line - 1)))
|
|
392277
|
+
|
|
392278
|
+
# Track required fields
|
|
392279
|
+
has_description=false
|
|
392280
|
+
|
|
392281
|
+
# Validate each line
|
|
392282
|
+
while IFS= read -r line; do
|
|
392283
|
+
[ -z "$line" ] && continue
|
|
392284
|
+
# Skip YAML multiline continuation lines (indented lines that continue a previous value)
|
|
392285
|
+
case "$line" in
|
|
392286
|
+
" "*|$' '*) continue ;;
|
|
392287
|
+
esac
|
|
392288
|
+
|
|
392289
|
+
key=$(echo "$line" | cut -d: -f1 | tr -d ' ')
|
|
392290
|
+
value=$(echo "$line" | cut -d: -f2- | sed 's/^ *//;s/ *$//')
|
|
392291
|
+
|
|
392292
|
+
# Check key is known
|
|
392293
|
+
known=false
|
|
392294
|
+
for k in $ALL_KNOWN_KEYS; do
|
|
392295
|
+
if [ "$key" = "$k" ]; then
|
|
392296
|
+
known=true
|
|
392297
|
+
break
|
|
392298
|
+
fi
|
|
392299
|
+
done
|
|
392300
|
+
if [ "$known" = "false" ]; then
|
|
392301
|
+
errors="$errors\\n $file: unknown frontmatter key '$key' (allowed: $ALL_KNOWN_KEYS)"
|
|
392302
|
+
continue
|
|
392303
|
+
fi
|
|
392304
|
+
|
|
392305
|
+
# Check if agent is trying to modify a protected key
|
|
392306
|
+
for k in $PROTECTED_KEYS; do
|
|
392307
|
+
if [ "$key" = "$k" ]; then
|
|
392308
|
+
# Compare against HEAD — if value changed (or key was added), reject
|
|
392309
|
+
if [ -n "$head_content" ]; then
|
|
392310
|
+
head_val=$(get_fm_value "$head_content" "$key")
|
|
392311
|
+
if [ "$value" != "$head_val" ]; then
|
|
392312
|
+
errors="$errors\\n $file: '$key' is a protected field and cannot be changed by the agent"
|
|
392313
|
+
fi
|
|
392314
|
+
else
|
|
392315
|
+
# New file with read_only — agent shouldn't set this
|
|
392316
|
+
errors="$errors\\n $file: '$key' is a protected field and cannot be set by the agent"
|
|
392317
|
+
fi
|
|
392318
|
+
fi
|
|
392319
|
+
done
|
|
392320
|
+
|
|
392321
|
+
# Validate value types
|
|
392322
|
+
case "$key" in
|
|
392323
|
+
limit)
|
|
392324
|
+
# Legacy field accepted for backward compatibility.
|
|
392325
|
+
;;
|
|
392326
|
+
description)
|
|
392327
|
+
has_description=true
|
|
392328
|
+
if [ -z "$value" ]; then
|
|
392329
|
+
errors="$errors\\n $file: 'description' must not be empty"
|
|
392330
|
+
fi
|
|
392331
|
+
;;
|
|
392332
|
+
esac
|
|
392333
|
+
done <<< "$frontmatter"
|
|
392334
|
+
|
|
392335
|
+
# Check required fields
|
|
392336
|
+
if [ "$has_description" = "false" ]; then
|
|
392337
|
+
errors="$errors\\n $file: missing required field 'description'"
|
|
392338
|
+
fi
|
|
392339
|
+
|
|
392340
|
+
# Check if protected keys were removed (existed in HEAD but not in staged)
|
|
392341
|
+
if [ -n "$head_content" ]; then
|
|
392342
|
+
for k in $PROTECTED_KEYS; do
|
|
392343
|
+
head_val=$(get_fm_value "$head_content" "$k")
|
|
392344
|
+
if [ -n "$head_val" ]; then
|
|
392345
|
+
staged_val=$(get_fm_value "$staged" "$k")
|
|
392346
|
+
if [ -z "$staged_val" ]; then
|
|
392347
|
+
errors="$errors\\n $file: '$k' is a protected field and cannot be removed by the agent"
|
|
392348
|
+
fi
|
|
392349
|
+
fi
|
|
392350
|
+
done
|
|
392351
|
+
fi
|
|
392352
|
+
done
|
|
392353
|
+
|
|
392354
|
+
if [ -n "$errors" ]; then
|
|
392355
|
+
echo "Frontmatter validation failed:"
|
|
392356
|
+
echo -e "$errors"
|
|
392357
|
+
exit 1
|
|
392358
|
+
fi
|
|
392359
|
+
`, POST_COMMIT_HOOK_SCRIPT = `#!/usr/bin/env bash
|
|
392360
|
+
# Letta Code: push memfs commits to the configured memory-repository remote.
|
|
392361
|
+
# Installed by Letta Code CLI. Do not edit by hand — regenerated on startup.
|
|
392362
|
+
url=$(git config --local --get letta.memoryRepository.url 2>/dev/null)
|
|
392363
|
+
[ -z "$url" ] && exit 0
|
|
392364
|
+
branch=$(git symbolic-ref --quiet --short HEAD 2>/dev/null) || exit 0
|
|
392365
|
+
[ -z "$branch" ] && exit 0
|
|
392366
|
+
# Reflection and other harness worktrees commit on temporary branches; only the
|
|
392367
|
+
# main MemFS checkout should push to the optional memory repository remote.
|
|
392368
|
+
[ "$branch" != "main" ] && exit 0
|
|
392369
|
+
log="$(git rev-parse --git-dir)/memory-repository-push.log"
|
|
392370
|
+
(
|
|
392371
|
+
{
|
|
392372
|
+
printf '\\n--- %s %s on %s ---\\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$(git rev-parse --short HEAD)" "$branch"
|
|
392373
|
+
git push --quiet "$url" "$branch":"$branch" 2>&1
|
|
392374
|
+
echo "exit=$?"
|
|
392375
|
+
} >> "$log" 2>&1
|
|
392376
|
+
) &
|
|
392377
|
+
disown 2>/dev/null || true
|
|
392378
|
+
exit 0
|
|
392379
|
+
`;
|
|
392380
|
+
var init_memory_git_hooks = __esm(() => {
|
|
392381
|
+
init_debug();
|
|
392382
|
+
});
|
|
392383
|
+
|
|
392384
|
+
// src/agent/memory-git-signing.ts
|
|
392385
|
+
var GIT_DISABLE_COMMIT_SIGNING_ARGS;
|
|
392386
|
+
var init_memory_git_signing = __esm(() => {
|
|
392387
|
+
GIT_DISABLE_COMMIT_SIGNING_ARGS = [
|
|
392388
|
+
"-c",
|
|
392389
|
+
"commit.gpgsign=false"
|
|
392390
|
+
];
|
|
392391
|
+
});
|
|
392392
|
+
|
|
392150
392393
|
// src/agent/memory-git.ts
|
|
392151
392394
|
var exports_memory_git = {};
|
|
392152
392395
|
__export(exports_memory_git, {
|
|
@@ -392185,28 +392428,25 @@ __export(exports_memory_git, {
|
|
|
392185
392428
|
buildMemfsGitProxyArgs: () => buildMemfsGitProxyArgs,
|
|
392186
392429
|
buildGitAuthArgs: () => buildGitAuthArgs,
|
|
392187
392430
|
assertMemoryRepoCleanForWrite: () => assertMemoryRepoCleanForWrite,
|
|
392188
|
-
addGitMemoryTag: () => addGitMemoryTag
|
|
392189
|
-
PRE_COMMIT_HOOK_SCRIPT: () => PRE_COMMIT_HOOK_SCRIPT,
|
|
392190
|
-
POST_COMMIT_HOOK_SCRIPT: () => POST_COMMIT_HOOK_SCRIPT
|
|
392431
|
+
addGitMemoryTag: () => addGitMemoryTag
|
|
392191
392432
|
});
|
|
392192
392433
|
import { execFile as execFileCb } from "node:child_process";
|
|
392193
392434
|
import {
|
|
392194
|
-
|
|
392195
|
-
|
|
392196
|
-
mkdirSync as mkdirSync22,
|
|
392435
|
+
existsSync as existsSync32,
|
|
392436
|
+
mkdirSync as mkdirSync23,
|
|
392197
392437
|
readFileSync as readFileSync23,
|
|
392198
392438
|
renameSync as renameSync2,
|
|
392199
392439
|
rmSync as rmSync5,
|
|
392200
|
-
writeFileSync as
|
|
392440
|
+
writeFileSync as writeFileSync17
|
|
392201
392441
|
} from "node:fs";
|
|
392202
392442
|
import { homedir as homedir25, platform as platform3 } from "node:os";
|
|
392203
|
-
import { dirname as dirname20, isAbsolute as isAbsolute20, join as
|
|
392443
|
+
import { dirname as dirname20, isAbsolute as isAbsolute20, join as join39 } from "node:path";
|
|
392204
392444
|
import { promisify as promisify5 } from "node:util";
|
|
392205
392445
|
function getAgentRootDir(agentId) {
|
|
392206
|
-
return
|
|
392446
|
+
return join39(homedir25(), ".letta", "agents", agentId);
|
|
392207
392447
|
}
|
|
392208
392448
|
function getMemoryRepoDir(agentId) {
|
|
392209
|
-
return
|
|
392449
|
+
return join39(getAgentRootDir(agentId), "memory");
|
|
392210
392450
|
}
|
|
392211
392451
|
function getMemoryRepositoryRepoDir(agentId) {
|
|
392212
392452
|
return getScopedMemoryFilesystemRoot(agentId);
|
|
@@ -392280,7 +392520,7 @@ function getRepositoryRemoteUrl(agentId, repositoryName, baseUrl) {
|
|
|
392280
392520
|
return `${resolvedBaseUrl}/v1/git/${agentId}/repositories/${encodeURIComponent(repositoryName)}.git`;
|
|
392281
392521
|
}
|
|
392282
392522
|
function getRepositoryMountDir(agentId, repositoryName) {
|
|
392283
|
-
return
|
|
392523
|
+
return join39(dirname20(getMemoryRepoDir(agentId)), repositoryName);
|
|
392284
392524
|
}
|
|
392285
392525
|
function validateAgentRepositoryName(name) {
|
|
392286
392526
|
const trimmed = name.trim();
|
|
@@ -392333,8 +392573,8 @@ async function prepareAttachedRepositoryForGitOps(args) {
|
|
|
392333
392573
|
await ensureLocalMemfsGitConfig(args.directory, args.agentId);
|
|
392334
392574
|
}
|
|
392335
392575
|
async function cloneRepositoryMount(args) {
|
|
392336
|
-
if (!
|
|
392337
|
-
|
|
392576
|
+
if (!existsSync32(args.directory)) {
|
|
392577
|
+
mkdirSync23(args.directory, { recursive: true });
|
|
392338
392578
|
try {
|
|
392339
392579
|
await runGitWithRetry(args.directory, ["clone", args.remoteUrl, "."], args.token, {
|
|
392340
392580
|
operation: `clone repository ${args.repositoryName}`,
|
|
@@ -392344,7 +392584,7 @@ async function cloneRepositoryMount(args) {
|
|
|
392344
392584
|
rmSync5(args.directory, { recursive: true, force: true });
|
|
392345
392585
|
throw err;
|
|
392346
392586
|
}
|
|
392347
|
-
} else if (!
|
|
392587
|
+
} else if (!existsSync32(join39(args.directory, ".git"))) {
|
|
392348
392588
|
throw new Error(`repository mount path already exists and is not a git repository: ${args.directory}`);
|
|
392349
392589
|
} else {
|
|
392350
392590
|
await prepareAttachedRepositoryForGitOps(args);
|
|
@@ -392465,7 +392705,12 @@ function buildNonInteractiveGitEnv(env3 = process.env) {
|
|
|
392465
392705
|
}
|
|
392466
392706
|
async function runGit3(cwd, args, token, options3) {
|
|
392467
392707
|
const authArgs = token ? buildGitAuthArgs(token) : [];
|
|
392468
|
-
const allArgs = [
|
|
392708
|
+
const allArgs = [
|
|
392709
|
+
...GIT_DISABLE_COMMIT_SIGNING_ARGS,
|
|
392710
|
+
...buildMemfsGitProxyArgs(args),
|
|
392711
|
+
...authArgs,
|
|
392712
|
+
...args
|
|
392713
|
+
];
|
|
392469
392714
|
let loggableArgs = args;
|
|
392470
392715
|
if (args[0] === "config" && typeof args[1] === "string" && args[1].includes("credential") && args[1].includes(".helper")) {
|
|
392471
392716
|
loggableArgs = [args[0], args[1], "<redacted>"];
|
|
@@ -392510,15 +392755,15 @@ async function runGitWithRetry(cwd, args, token, options3) {
|
|
|
392510
392755
|
const operation = options3?.operation ?? args[0] ?? "git op";
|
|
392511
392756
|
for (let attempt = 1;attempt <= attempts; attempt += 1) {
|
|
392512
392757
|
try {
|
|
392513
|
-
if (!
|
|
392514
|
-
|
|
392758
|
+
if (!existsSync32(cwd)) {
|
|
392759
|
+
mkdirSync23(cwd, { recursive: true });
|
|
392515
392760
|
}
|
|
392516
392761
|
return await runGit3(cwd, args, token, {
|
|
392517
392762
|
timeoutMs: options3?.timeoutMs
|
|
392518
392763
|
});
|
|
392519
392764
|
} catch (error54) {
|
|
392520
392765
|
if (isMissingCwdGitError(error54)) {
|
|
392521
|
-
|
|
392766
|
+
mkdirSync23(cwd, { recursive: true });
|
|
392522
392767
|
if (attempt < attempts) {
|
|
392523
392768
|
continue;
|
|
392524
392769
|
}
|
|
@@ -392544,12 +392789,12 @@ async function configureLocalCredentialHelper(dir, token) {
|
|
|
392544
392789
|
}
|
|
392545
392790
|
let helper;
|
|
392546
392791
|
if (platform3() === "win32") {
|
|
392547
|
-
const helperScriptPath =
|
|
392792
|
+
const helperScriptPath = join39(dir, ".git", "letta-credential-helper.cmd");
|
|
392548
392793
|
const batchScript = `@echo off
|
|
392549
392794
|
echo username=letta
|
|
392550
392795
|
echo password=${token}
|
|
392551
392796
|
`;
|
|
392552
|
-
|
|
392797
|
+
writeFileSync17(helperScriptPath, batchScript, "utf-8");
|
|
392553
392798
|
helper = formatGitCredentialHelperPath(helperScriptPath);
|
|
392554
392799
|
debugLog("memfs-git", `Wrote Windows credential helper script`);
|
|
392555
392800
|
} else {
|
|
@@ -392576,26 +392821,6 @@ async function clearLocalCredentialHelper(dir, rawBaseUrl, normalizedBaseUrl) {
|
|
|
392576
392821
|
} catch {}
|
|
392577
392822
|
}
|
|
392578
392823
|
}
|
|
392579
|
-
function installPreCommitHook(dir) {
|
|
392580
|
-
const hooksDir = join38(dir, ".git", "hooks");
|
|
392581
|
-
const hookPath = join38(hooksDir, "pre-commit");
|
|
392582
|
-
if (!existsSync31(hooksDir)) {
|
|
392583
|
-
mkdirSync22(hooksDir, { recursive: true });
|
|
392584
|
-
}
|
|
392585
|
-
writeFileSync16(hookPath, PRE_COMMIT_HOOK_SCRIPT, "utf-8");
|
|
392586
|
-
chmodSync4(hookPath, 493);
|
|
392587
|
-
debugLog("memfs-git", "Installed pre-commit hook");
|
|
392588
|
-
}
|
|
392589
|
-
function installPostCommitHook(dir) {
|
|
392590
|
-
const hooksDir = join38(dir, ".git", "hooks");
|
|
392591
|
-
const hookPath = join38(hooksDir, "post-commit");
|
|
392592
|
-
if (!existsSync31(hooksDir)) {
|
|
392593
|
-
mkdirSync22(hooksDir, { recursive: true });
|
|
392594
|
-
}
|
|
392595
|
-
writeFileSync16(hookPath, POST_COMMIT_HOOK_SCRIPT, "utf-8");
|
|
392596
|
-
chmodSync4(hookPath, 493);
|
|
392597
|
-
debugLog("memfs-git", "Installed post-commit memory-repository hook");
|
|
392598
|
-
}
|
|
392599
392824
|
async function getLocalGitConfig(dir, key) {
|
|
392600
392825
|
try {
|
|
392601
392826
|
const { stdout } = await runGit3(dir, ["config", "--local", "--get", key]);
|
|
@@ -392639,7 +392864,7 @@ async function fetchAgentDisplayName(agentId) {
|
|
|
392639
392864
|
}
|
|
392640
392865
|
}
|
|
392641
392866
|
async function ensureLocalMemfsGitConfig(dir, agentId) {
|
|
392642
|
-
if (!
|
|
392867
|
+
if (!existsSync32(join39(dir, ".git"))) {
|
|
392643
392868
|
return;
|
|
392644
392869
|
}
|
|
392645
392870
|
try {
|
|
@@ -392656,20 +392881,24 @@ async function ensureLocalMemfsGitConfig(dir, agentId) {
|
|
|
392656
392881
|
const displayName = await fetchAgentDisplayName(agentId) ?? "Letta Agent";
|
|
392657
392882
|
await setLocalGitConfig(dir, "user.name", displayName);
|
|
392658
392883
|
}
|
|
392884
|
+
const currentGpgSign = await getLocalGitConfig(dir, "commit.gpgsign");
|
|
392885
|
+
if (currentGpgSign === null) {
|
|
392886
|
+
await setLocalGitConfig(dir, "commit.gpgsign", "false");
|
|
392887
|
+
}
|
|
392659
392888
|
} catch (err) {
|
|
392660
392889
|
debugWarn("memfs-git", `Failed to ensure local memfs git config: ${err instanceof Error ? err.message : String(err)}`);
|
|
392661
392890
|
}
|
|
392662
392891
|
}
|
|
392663
392892
|
async function getMemoryRepositoryUrl(agentId) {
|
|
392664
392893
|
const dir = getMemoryRepositoryRepoDir(agentId);
|
|
392665
|
-
if (!
|
|
392894
|
+
if (!existsSync32(join39(dir, ".git"))) {
|
|
392666
392895
|
return null;
|
|
392667
392896
|
}
|
|
392668
392897
|
return await getLocalGitConfig(dir, MEMORY_REPOSITORY_CONFIG_KEY);
|
|
392669
392898
|
}
|
|
392670
392899
|
async function setMemoryRepositoryUrl(agentId, url2) {
|
|
392671
392900
|
const dir = getMemoryRepositoryRepoDir(agentId);
|
|
392672
|
-
if (!
|
|
392901
|
+
if (!existsSync32(join39(dir, ".git"))) {
|
|
392673
392902
|
throw new Error(`Memory repo not initialized for ${agentId} — cannot configure memory-repository endpoint.`);
|
|
392674
392903
|
}
|
|
392675
392904
|
await setLocalGitConfig(dir, MEMORY_REPOSITORY_CONFIG_KEY, url2.trim());
|
|
@@ -392677,7 +392906,7 @@ async function setMemoryRepositoryUrl(agentId, url2) {
|
|
|
392677
392906
|
}
|
|
392678
392907
|
async function unsetMemoryRepositoryUrl(agentId) {
|
|
392679
392908
|
const dir = getMemoryRepositoryRepoDir(agentId);
|
|
392680
|
-
if (!
|
|
392909
|
+
if (!existsSync32(join39(dir, ".git"))) {
|
|
392681
392910
|
return;
|
|
392682
392911
|
}
|
|
392683
392912
|
await unsetLocalGitConfig(dir, MEMORY_REPOSITORY_CONFIG_KEY);
|
|
@@ -392741,8 +392970,8 @@ async function pushToMemoryRepository(agentId) {
|
|
|
392741
392970
|
}
|
|
392742
392971
|
}
|
|
392743
392972
|
function readMemoryRepositoryPushLog(agentId, tailLines = 20) {
|
|
392744
|
-
const logPath =
|
|
392745
|
-
if (!
|
|
392973
|
+
const logPath = join39(getMemoryRepositoryRepoDir(agentId), ".git", MEMORY_REPOSITORY_PUSH_LOG);
|
|
392974
|
+
if (!existsSync32(logPath)) {
|
|
392746
392975
|
return "";
|
|
392747
392976
|
}
|
|
392748
392977
|
try {
|
|
@@ -392828,6 +393057,9 @@ async function prepareLocalOnlyMemoryRepoForGitOps(memoryDir, author) {
|
|
|
392828
393057
|
await setLocalGitConfig(memoryDir, "letta.agentId", author.agentId);
|
|
392829
393058
|
await setLocalGitConfig(memoryDir, "user.email", author.authorEmail);
|
|
392830
393059
|
await setLocalGitConfig(memoryDir, "user.name", author.authorName.trim() || "Letta Agent");
|
|
393060
|
+
if (await getLocalGitConfig(memoryDir, "commit.gpgsign") === null) {
|
|
393061
|
+
await setLocalGitConfig(memoryDir, "commit.gpgsign", "false");
|
|
393062
|
+
}
|
|
392831
393063
|
}
|
|
392832
393064
|
async function stageMemoryPaths(memoryDir, pathspecs) {
|
|
392833
393065
|
if (pathspecs.length === 0) {
|
|
@@ -392909,8 +393141,8 @@ function parsePorcelainPath(line) {
|
|
|
392909
393141
|
return path31.replace(/^"|"$/g, "");
|
|
392910
393142
|
}
|
|
392911
393143
|
function describeMarkdownEncodingIssue(memoryDir, relativePath) {
|
|
392912
|
-
const filePath =
|
|
392913
|
-
if (!
|
|
393144
|
+
const filePath = join39(memoryDir, relativePath);
|
|
393145
|
+
if (!existsSync32(filePath)) {
|
|
392914
393146
|
return null;
|
|
392915
393147
|
}
|
|
392916
393148
|
const bytes = readFileSync23(filePath);
|
|
@@ -392944,7 +393176,7 @@ async function commitMemoryWrite(params) {
|
|
|
392944
393176
|
};
|
|
392945
393177
|
}
|
|
392946
393178
|
function isGitRepo(agentId) {
|
|
392947
|
-
return
|
|
393179
|
+
return existsSync32(join39(getScopedMemoryFilesystemRoot(agentId), ".git"));
|
|
392948
393180
|
}
|
|
392949
393181
|
async function hasMemoryHead(memoryDir) {
|
|
392950
393182
|
try {
|
|
@@ -392968,8 +393200,8 @@ async function getMemoryHeadRevision(memoryDir) {
|
|
|
392968
393200
|
}
|
|
392969
393201
|
}
|
|
392970
393202
|
async function initializeLocalMemoryRepo(params) {
|
|
392971
|
-
|
|
392972
|
-
if (!
|
|
393203
|
+
mkdirSync23(params.memoryDir, { recursive: true });
|
|
393204
|
+
if (!existsSync32(join39(params.memoryDir, ".git"))) {
|
|
392973
393205
|
await runGit3(params.memoryDir, ["init"]);
|
|
392974
393206
|
await runGit3(params.memoryDir, ["symbolic-ref", "HEAD", "refs/heads/main"]);
|
|
392975
393207
|
}
|
|
@@ -392989,9 +393221,9 @@ async function initializeLocalMemoryRepo(params) {
|
|
|
392989
393221
|
if (!relativePath || relativePath.startsWith("/") || segments.length === 0 || segments.some((segment) => segment === "." || segment === "..")) {
|
|
392990
393222
|
continue;
|
|
392991
393223
|
}
|
|
392992
|
-
const fullPath =
|
|
392993
|
-
|
|
392994
|
-
|
|
393224
|
+
const fullPath = join39(params.memoryDir, relativePath);
|
|
393225
|
+
mkdirSync23(dirname20(fullPath), { recursive: true });
|
|
393226
|
+
writeFileSync17(fullPath, file3.content, "utf8");
|
|
392995
393227
|
pathspecs.push(relativePath);
|
|
392996
393228
|
}
|
|
392997
393229
|
if (pathspecs.length > 0) {
|
|
@@ -393081,24 +393313,24 @@ async function cloneMemoryRepo(agentId) {
|
|
|
393081
393313
|
const url2 = getMemoryRemoteUrl(agentId);
|
|
393082
393314
|
const dir = getMemoryRepoDir(agentId);
|
|
393083
393315
|
debugLog("memfs-git", `Cloning ${url2} → ${dir}`);
|
|
393084
|
-
if (!
|
|
393085
|
-
|
|
393316
|
+
if (!existsSync32(dir)) {
|
|
393317
|
+
mkdirSync23(dir, { recursive: true });
|
|
393086
393318
|
await runGitWithRetry(dir, ["clone", url2, "."], token, {
|
|
393087
393319
|
operation: "clone memory repo",
|
|
393088
393320
|
timeoutMs: GIT_CLONE_TIMEOUT_MS
|
|
393089
393321
|
});
|
|
393090
|
-
} else if (!
|
|
393322
|
+
} else if (!existsSync32(join39(dir, ".git"))) {
|
|
393091
393323
|
const tmpDir = `${dir}-git-clone-tmp`;
|
|
393092
393324
|
try {
|
|
393093
|
-
if (
|
|
393325
|
+
if (existsSync32(tmpDir)) {
|
|
393094
393326
|
rmSync5(tmpDir, { recursive: true, force: true });
|
|
393095
393327
|
}
|
|
393096
|
-
|
|
393328
|
+
mkdirSync23(tmpDir, { recursive: true });
|
|
393097
393329
|
await runGitWithRetry(tmpDir, ["clone", url2, "."], token, {
|
|
393098
393330
|
operation: "clone memory repo (tmp migration)",
|
|
393099
393331
|
timeoutMs: GIT_CLONE_TIMEOUT_MS
|
|
393100
393332
|
});
|
|
393101
|
-
renameSync2(
|
|
393333
|
+
renameSync2(join39(tmpDir, ".git"), join39(dir, ".git"));
|
|
393102
393334
|
try {
|
|
393103
393335
|
await runGit3(dir, ["rev-parse", "--verify", "HEAD"], token);
|
|
393104
393336
|
await runGit3(dir, ["checkout", "--", "."], token);
|
|
@@ -393108,7 +393340,7 @@ async function cloneMemoryRepo(agentId) {
|
|
|
393108
393340
|
}
|
|
393109
393341
|
debugLog("memfs-git", "Migrated existing memory directory to git repo");
|
|
393110
393342
|
} finally {
|
|
393111
|
-
if (
|
|
393343
|
+
if (existsSync32(tmpDir)) {
|
|
393112
393344
|
rmSync5(tmpDir, { recursive: true, force: true });
|
|
393113
393345
|
}
|
|
393114
393346
|
}
|
|
@@ -393227,15 +393459,15 @@ function isUnmergedStatusCode(code2) {
|
|
|
393227
393459
|
async function getMemoryGitDir(memoryDir) {
|
|
393228
393460
|
const { stdout } = await runGit3(memoryDir, ["rev-parse", "--git-dir"]);
|
|
393229
393461
|
const gitDir = stdout.trim() || ".git";
|
|
393230
|
-
return isAbsolute20(gitDir) ? gitDir :
|
|
393462
|
+
return isAbsolute20(gitDir) ? gitDir : join39(memoryDir, gitDir);
|
|
393231
393463
|
}
|
|
393232
393464
|
async function getMemoryConflictSummary(memoryDir, statusOut) {
|
|
393233
393465
|
let operation = null;
|
|
393234
393466
|
try {
|
|
393235
393467
|
const gitDir = await getMemoryGitDir(memoryDir);
|
|
393236
|
-
if (
|
|
393468
|
+
if (existsSync32(join39(gitDir, "MERGE_HEAD"))) {
|
|
393237
393469
|
operation = "merge in progress";
|
|
393238
|
-
} else if (
|
|
393470
|
+
} else if (existsSync32(join39(gitDir, "rebase-merge")) || existsSync32(join39(gitDir, "rebase-apply"))) {
|
|
393239
393471
|
operation = "rebase in progress";
|
|
393240
393472
|
}
|
|
393241
393473
|
} catch {
|
|
@@ -393278,7 +393510,7 @@ async function syncPendingMemoryCommitsAfterTurn(agentId, options3 = {}) {
|
|
|
393278
393510
|
const backend = getBackend2();
|
|
393279
393511
|
const localOnly = backend.capabilities.localMemfs && !backend.capabilities.remoteMemfs;
|
|
393280
393512
|
const memoryDir = options3.memoryDir ?? getScopedMemoryFilesystemRoot(agentId);
|
|
393281
|
-
if (!
|
|
393513
|
+
if (!existsSync32(join39(memoryDir, ".git"))) {
|
|
393282
393514
|
return {
|
|
393283
393515
|
status: "skipped",
|
|
393284
393516
|
summary: "Memory repo is not initialized.",
|
|
@@ -393404,164 +393636,7 @@ async function addGitMemoryTag(agentId, prefetchedAgent) {
|
|
|
393404
393636
|
debugWarn("memfs-git", `Failed to add git-memory tag: ${err instanceof Error ? err.message : String(err)}`);
|
|
393405
393637
|
}
|
|
393406
393638
|
}
|
|
393407
|
-
var execFile5, RETRYABLE_GIT_HTTP_ERROR_RE, RETRYABLE_GIT_NETWORK_ERROR_RE, MISSING_CWD_GIT_ERROR_RE, NON_FAST_FORWARD_PUSH_ERROR_RE, UNRELATED_HISTORY_PULL_ERROR_RE, NO_UPSTREAM_PULL_ERROR_RE, AGENT_DISPLAY_NAME_TIMEOUT_MS = 3000, HOSTED_BACKEND_HEADER2 = "x-letta-memfs-backend", HOSTED_BACKEND_VALUE2 = "hosted", GIT_DEFAULT_TIMEOUT_MS = 60000, GIT_CLONE_TIMEOUT_MS = 180000,
|
|
393408
|
-
# Validate frontmatter in staged memory .md files
|
|
393409
|
-
# Installed by Letta Code CLI
|
|
393410
|
-
|
|
393411
|
-
AGENT_EDITABLE_KEYS="description"
|
|
393412
|
-
PROTECTED_KEYS="read_only"
|
|
393413
|
-
ALL_KNOWN_KEYS="description read_only limit"
|
|
393414
|
-
errors=""
|
|
393415
|
-
|
|
393416
|
-
# Skills must always be directories: skills/<name>/SKILL.md
|
|
393417
|
-
# Reject legacy flat skill files (both current and legacy repo layouts).
|
|
393418
|
-
for file in $(git diff --cached --name-only --diff-filter=ACMR | grep -E '^(memory/)?skills/[^/]+\\.md$' || true); do
|
|
393419
|
-
errors="$errors\\n $file: invalid skill path (skills must be folders). Use skills/<name>/SKILL.md"
|
|
393420
|
-
done
|
|
393421
|
-
|
|
393422
|
-
# Helper: extract a frontmatter value from content
|
|
393423
|
-
get_fm_value() {
|
|
393424
|
-
local content="$1" key="$2"
|
|
393425
|
-
local closing_line
|
|
393426
|
-
closing_line=$(echo "$content" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
|
|
393427
|
-
[ -z "$closing_line" ] && return
|
|
393428
|
-
echo "$content" | tail -n +2 | head -n $((closing_line - 1)) | grep "^$key:" | cut -d: -f2- | sed 's/^ *//;s/ *$//'
|
|
393429
|
-
}
|
|
393430
|
-
|
|
393431
|
-
# Match .md files under system/ or reference/ (with optional memory/ prefix).
|
|
393432
|
-
# Skip skill SKILL.md files — they use a different frontmatter format.
|
|
393433
|
-
for file in $(git diff --cached --name-only --diff-filter=ACM | grep -E '^(memory/)?(system|reference)/.*\\.md$'); do
|
|
393434
|
-
staged=$(git show ":$file")
|
|
393435
|
-
|
|
393436
|
-
# Frontmatter is required
|
|
393437
|
-
first_line=$(echo "$staged" | head -1)
|
|
393438
|
-
if [ "$first_line" != "---" ]; then
|
|
393439
|
-
errors="$errors\\n $file: missing frontmatter (must start with ---)"
|
|
393440
|
-
continue
|
|
393441
|
-
fi
|
|
393442
|
-
|
|
393443
|
-
# Check frontmatter is properly closed
|
|
393444
|
-
closing_line=$(echo "$staged" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
|
|
393445
|
-
if [ -z "$closing_line" ]; then
|
|
393446
|
-
errors="$errors\\n $file: frontmatter opened but never closed (missing closing ---)"
|
|
393447
|
-
continue
|
|
393448
|
-
fi
|
|
393449
|
-
|
|
393450
|
-
# Check read_only protection against HEAD version
|
|
393451
|
-
head_content=$(git show "HEAD:$file" 2>/dev/null || true)
|
|
393452
|
-
if [ -n "$head_content" ]; then
|
|
393453
|
-
head_ro=$(get_fm_value "$head_content" "read_only")
|
|
393454
|
-
if [ "$head_ro" = "true" ]; then
|
|
393455
|
-
errors="$errors\\n $file: file is read_only and cannot be modified"
|
|
393456
|
-
continue
|
|
393457
|
-
fi
|
|
393458
|
-
fi
|
|
393459
|
-
|
|
393460
|
-
# Extract frontmatter lines
|
|
393461
|
-
frontmatter=$(echo "$staged" | tail -n +2 | head -n $((closing_line - 1)))
|
|
393462
|
-
|
|
393463
|
-
# Track required fields
|
|
393464
|
-
has_description=false
|
|
393465
|
-
|
|
393466
|
-
# Validate each line
|
|
393467
|
-
while IFS= read -r line; do
|
|
393468
|
-
[ -z "$line" ] && continue
|
|
393469
|
-
# Skip YAML multiline continuation lines (indented lines that continue a previous value)
|
|
393470
|
-
case "$line" in
|
|
393471
|
-
" "*|$' '*) continue ;;
|
|
393472
|
-
esac
|
|
393473
|
-
|
|
393474
|
-
key=$(echo "$line" | cut -d: -f1 | tr -d ' ')
|
|
393475
|
-
value=$(echo "$line" | cut -d: -f2- | sed 's/^ *//;s/ *$//')
|
|
393476
|
-
|
|
393477
|
-
# Check key is known
|
|
393478
|
-
known=false
|
|
393479
|
-
for k in $ALL_KNOWN_KEYS; do
|
|
393480
|
-
if [ "$key" = "$k" ]; then
|
|
393481
|
-
known=true
|
|
393482
|
-
break
|
|
393483
|
-
fi
|
|
393484
|
-
done
|
|
393485
|
-
if [ "$known" = "false" ]; then
|
|
393486
|
-
errors="$errors\\n $file: unknown frontmatter key '$key' (allowed: $ALL_KNOWN_KEYS)"
|
|
393487
|
-
continue
|
|
393488
|
-
fi
|
|
393489
|
-
|
|
393490
|
-
# Check if agent is trying to modify a protected key
|
|
393491
|
-
for k in $PROTECTED_KEYS; do
|
|
393492
|
-
if [ "$key" = "$k" ]; then
|
|
393493
|
-
# Compare against HEAD — if value changed (or key was added), reject
|
|
393494
|
-
if [ -n "$head_content" ]; then
|
|
393495
|
-
head_val=$(get_fm_value "$head_content" "$key")
|
|
393496
|
-
if [ "$value" != "$head_val" ]; then
|
|
393497
|
-
errors="$errors\\n $file: '$key' is a protected field and cannot be changed by the agent"
|
|
393498
|
-
fi
|
|
393499
|
-
else
|
|
393500
|
-
# New file with read_only — agent shouldn't set this
|
|
393501
|
-
errors="$errors\\n $file: '$key' is a protected field and cannot be set by the agent"
|
|
393502
|
-
fi
|
|
393503
|
-
fi
|
|
393504
|
-
done
|
|
393505
|
-
|
|
393506
|
-
# Validate value types
|
|
393507
|
-
case "$key" in
|
|
393508
|
-
limit)
|
|
393509
|
-
# Legacy field accepted for backward compatibility.
|
|
393510
|
-
;;
|
|
393511
|
-
description)
|
|
393512
|
-
has_description=true
|
|
393513
|
-
if [ -z "$value" ]; then
|
|
393514
|
-
errors="$errors\\n $file: 'description' must not be empty"
|
|
393515
|
-
fi
|
|
393516
|
-
;;
|
|
393517
|
-
esac
|
|
393518
|
-
done <<< "$frontmatter"
|
|
393519
|
-
|
|
393520
|
-
# Check required fields
|
|
393521
|
-
if [ "$has_description" = "false" ]; then
|
|
393522
|
-
errors="$errors\\n $file: missing required field 'description'"
|
|
393523
|
-
fi
|
|
393524
|
-
|
|
393525
|
-
# Check if protected keys were removed (existed in HEAD but not in staged)
|
|
393526
|
-
if [ -n "$head_content" ]; then
|
|
393527
|
-
for k in $PROTECTED_KEYS; do
|
|
393528
|
-
head_val=$(get_fm_value "$head_content" "$k")
|
|
393529
|
-
if [ -n "$head_val" ]; then
|
|
393530
|
-
staged_val=$(get_fm_value "$staged" "$k")
|
|
393531
|
-
if [ -z "$staged_val" ]; then
|
|
393532
|
-
errors="$errors\\n $file: '$k' is a protected field and cannot be removed by the agent"
|
|
393533
|
-
fi
|
|
393534
|
-
fi
|
|
393535
|
-
done
|
|
393536
|
-
fi
|
|
393537
|
-
done
|
|
393538
|
-
|
|
393539
|
-
if [ -n "$errors" ]; then
|
|
393540
|
-
echo "Frontmatter validation failed:"
|
|
393541
|
-
echo -e "$errors"
|
|
393542
|
-
exit 1
|
|
393543
|
-
fi
|
|
393544
|
-
`, POST_COMMIT_HOOK_SCRIPT = `#!/usr/bin/env bash
|
|
393545
|
-
# Letta Code: push memfs commits to the configured memory-repository remote.
|
|
393546
|
-
# Installed by Letta Code CLI. Do not edit by hand — regenerated on startup.
|
|
393547
|
-
url=$(git config --local --get letta.memoryRepository.url 2>/dev/null)
|
|
393548
|
-
[ -z "$url" ] && exit 0
|
|
393549
|
-
branch=$(git symbolic-ref --quiet --short HEAD 2>/dev/null) || exit 0
|
|
393550
|
-
[ -z "$branch" ] && exit 0
|
|
393551
|
-
# Reflection and other harness worktrees commit on temporary branches; only the
|
|
393552
|
-
# main MemFS checkout should push to the optional memory repository remote.
|
|
393553
|
-
[ "$branch" != "main" ] && exit 0
|
|
393554
|
-
log="$(git rev-parse --git-dir)/memory-repository-push.log"
|
|
393555
|
-
(
|
|
393556
|
-
{
|
|
393557
|
-
printf '\\n--- %s %s on %s ---\\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$(git rev-parse --short HEAD)" "$branch"
|
|
393558
|
-
git push --quiet "$url" "$branch":"$branch" 2>&1
|
|
393559
|
-
echo "exit=$?"
|
|
393560
|
-
} >> "$log" 2>&1
|
|
393561
|
-
) &
|
|
393562
|
-
disown 2>/dev/null || true
|
|
393563
|
-
exit 0
|
|
393564
|
-
`, MEMORY_REPOSITORY_CONFIG_KEY = "letta.memoryRepository.url", MEMORY_REPOSITORY_PUSH_LOG = "memory-repository-push.log";
|
|
393639
|
+
var execFile5, RETRYABLE_GIT_HTTP_ERROR_RE, RETRYABLE_GIT_NETWORK_ERROR_RE, MISSING_CWD_GIT_ERROR_RE, NON_FAST_FORWARD_PUSH_ERROR_RE, UNRELATED_HISTORY_PULL_ERROR_RE, NO_UPSTREAM_PULL_ERROR_RE, AGENT_DISPLAY_NAME_TIMEOUT_MS = 3000, HOSTED_BACKEND_HEADER2 = "x-letta-memfs-backend", HOSTED_BACKEND_VALUE2 = "hosted", GIT_DEFAULT_TIMEOUT_MS = 60000, GIT_CLONE_TIMEOUT_MS = 180000, MEMORY_REPOSITORY_CONFIG_KEY = "letta.memoryRepository.url", MEMORY_REPOSITORY_PUSH_LOG = "memory-repository-push.log";
|
|
393565
393640
|
var init_memory_git = __esm(() => {
|
|
393566
393641
|
init_client2();
|
|
393567
393642
|
init_memfs_git_proxy();
|
|
@@ -393569,6 +393644,8 @@ var init_memory_git = __esm(() => {
|
|
|
393569
393644
|
init_debug();
|
|
393570
393645
|
init_text_files();
|
|
393571
393646
|
init_memory_filesystem2();
|
|
393647
|
+
init_memory_git_hooks();
|
|
393648
|
+
init_memory_git_signing();
|
|
393572
393649
|
execFile5 = promisify5(execFileCb);
|
|
393573
393650
|
RETRYABLE_GIT_HTTP_ERROR_RE = /(?:\bHTTP\s+(?:520|521|522|523|524)\b|The requested URL returned error:\s*(?:520|521|522|523|524))/i;
|
|
393574
393651
|
RETRYABLE_GIT_NETWORK_ERROR_RE = /(remote end hung up unexpectedly|connection reset by peer|operation timed out|timed out|SIGTERM|ETIMEDOUT)/i;
|
|
@@ -393932,6 +394009,9 @@ function providerTypeFromModelSettings2(modelSettings) {
|
|
|
393932
394009
|
return typeof providerType === "string" && providerType.length > 0 ? providerType : null;
|
|
393933
394010
|
}
|
|
393934
394011
|
function normalizeLocalModelHandle(model, modelSettings, legacyLlmConfig) {
|
|
394012
|
+
if (isResolvablePiModelHandle(model) || resolveRegisteredPiProviderFromModelHandle(model)) {
|
|
394013
|
+
return model;
|
|
394014
|
+
}
|
|
393935
394015
|
const providerType = providerTypeFromModelSettings2(modelSettings);
|
|
393936
394016
|
const legacyEndpointType = legacyLlmConfig?.model_endpoint_type;
|
|
393937
394017
|
return resolveModelHandleFromLlmConfig({
|
|
@@ -393972,6 +394052,8 @@ function localLlmConfigModelPatch(model, modelSettings) {
|
|
|
393972
394052
|
}
|
|
393973
394053
|
var init_local_model_normalization = __esm(() => {
|
|
393974
394054
|
init_model_handles();
|
|
394055
|
+
init_pi_provider_mod_registry();
|
|
394056
|
+
init_pi_provider_registry();
|
|
393975
394057
|
});
|
|
393976
394058
|
|
|
393977
394059
|
// src/backend/local/local-stream-chunks.ts
|
|
@@ -394010,17 +394092,17 @@ import { randomUUID as randomUUID18 } from "node:crypto";
|
|
|
394010
394092
|
import {
|
|
394011
394093
|
appendFileSync as appendFileSync4,
|
|
394012
394094
|
closeSync,
|
|
394013
|
-
existsSync as
|
|
394014
|
-
mkdirSync as
|
|
394095
|
+
existsSync as existsSync33,
|
|
394096
|
+
mkdirSync as mkdirSync24,
|
|
394015
394097
|
openSync,
|
|
394016
394098
|
readdirSync as readdirSync11,
|
|
394017
394099
|
readFileSync as readFileSync24,
|
|
394018
394100
|
readSync,
|
|
394019
394101
|
rmSync as rmSync6,
|
|
394020
394102
|
statSync as statSync9,
|
|
394021
|
-
writeFileSync as
|
|
394103
|
+
writeFileSync as writeFileSync18
|
|
394022
394104
|
} from "node:fs";
|
|
394023
|
-
import { join as
|
|
394105
|
+
import { join as join40 } from "node:path";
|
|
394024
394106
|
function isStringArray2(value) {
|
|
394025
394107
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
394026
394108
|
}
|
|
@@ -394311,18 +394393,18 @@ function jsonl(items3) {
|
|
|
394311
394393
|
`;
|
|
394312
394394
|
}
|
|
394313
394395
|
function readJsonFile2(path31) {
|
|
394314
|
-
if (!
|
|
394396
|
+
if (!existsSync33(path31))
|
|
394315
394397
|
return;
|
|
394316
394398
|
return JSON.parse(readFileSync24(path31, "utf8"));
|
|
394317
394399
|
}
|
|
394318
394400
|
function readJsonlFile(path31) {
|
|
394319
|
-
if (!
|
|
394401
|
+
if (!existsSync33(path31))
|
|
394320
394402
|
return [];
|
|
394321
394403
|
return readFileSync24(path31, "utf8").split(`
|
|
394322
394404
|
`).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
394323
394405
|
}
|
|
394324
394406
|
function readJsonlFileSuffix(path31, maxBytes) {
|
|
394325
|
-
if (!
|
|
394407
|
+
if (!existsSync33(path31))
|
|
394326
394408
|
return { items: [], reachedStart: true };
|
|
394327
394409
|
const size = statSync9(path31).size;
|
|
394328
394410
|
if (size === 0)
|
|
@@ -394354,13 +394436,13 @@ function localTranscriptMigrationCommand(storageDir) {
|
|
|
394354
394436
|
return `letta local-backend migrate-transcripts --storage-dir ${quotedStorageDir}`;
|
|
394355
394437
|
}
|
|
394356
394438
|
function transcriptManifestPath(conversationDir) {
|
|
394357
|
-
return
|
|
394439
|
+
return join40(conversationDir, "manifest.json");
|
|
394358
394440
|
}
|
|
394359
394441
|
function transcriptMessagesPath(conversationDir) {
|
|
394360
|
-
return
|
|
394442
|
+
return join40(conversationDir, "messages.jsonl");
|
|
394361
394443
|
}
|
|
394362
394444
|
function hasNonEmptyJsonl(path31) {
|
|
394363
|
-
if (!
|
|
394445
|
+
if (!existsSync33(path31))
|
|
394364
394446
|
return false;
|
|
394365
394447
|
const stats = statSync9(path31);
|
|
394366
394448
|
if (stats.size === 0)
|
|
@@ -394496,7 +394578,7 @@ function validateLocalTranscriptManifest(conversationDir, storageDir) {
|
|
|
394496
394578
|
return manifest;
|
|
394497
394579
|
}
|
|
394498
394580
|
function writeLocalTranscriptManifest(conversationDir, manifest = createLocalTranscriptManifest()) {
|
|
394499
|
-
|
|
394581
|
+
writeFileSync18(transcriptManifestPath(conversationDir), `${JSON.stringify(manifest, null, 2)}
|
|
394500
394582
|
`);
|
|
394501
394583
|
}
|
|
394502
394584
|
function numericSuffix(value, prefix) {
|
|
@@ -394513,7 +394595,7 @@ function fileIsoTimestamp(value) {
|
|
|
394513
394595
|
}
|
|
394514
394596
|
function transcriptTimingForConversationDir(conversationDir, manifest) {
|
|
394515
394597
|
const messagesPath = transcriptMessagesPath(conversationDir);
|
|
394516
|
-
const stats =
|
|
394598
|
+
const stats = existsSync33(messagesPath) ? statSync9(messagesPath) : undefined;
|
|
394517
394599
|
const manifestCreatedAt = parseIsoTimestamp(manifest?.created_at) !== null ? manifest?.created_at : undefined;
|
|
394518
394600
|
const fileCreatedAt = fileIsoTimestamp(stats?.birthtimeMs);
|
|
394519
394601
|
const fileUpdatedAt = fileIsoTimestamp(stats?.mtimeMs);
|
|
@@ -394677,7 +394759,7 @@ class LocalStore {
|
|
|
394677
394759
|
this.persistedMessageByMessageIdByConversationKey.delete(key);
|
|
394678
394760
|
this.lastSessionEntryIdByConversationKey.delete(key);
|
|
394679
394761
|
if (this.storageDir) {
|
|
394680
|
-
rmSync6(
|
|
394762
|
+
rmSync6(join40(this.storageDir, "conversations", encodePathSegment(key)), {
|
|
394681
394763
|
recursive: true,
|
|
394682
394764
|
force: true
|
|
394683
394765
|
});
|
|
@@ -394685,7 +394767,7 @@ class LocalStore {
|
|
|
394685
394767
|
}
|
|
394686
394768
|
}
|
|
394687
394769
|
if (this.storageDir) {
|
|
394688
|
-
rmSync6(
|
|
394770
|
+
rmSync6(join40(this.storageDir, "agents", `${encodePathSegment(agentId)}.json`), { force: true });
|
|
394689
394771
|
}
|
|
394690
394772
|
}
|
|
394691
394773
|
retrieveAgentRecord(agentId) {
|
|
@@ -395008,7 +395090,7 @@ class LocalStore {
|
|
|
395008
395090
|
continue;
|
|
395009
395091
|
this.compiledSystemPromptByConversationKey.delete(key);
|
|
395010
395092
|
if (this.storageDir) {
|
|
395011
|
-
rmSync6(
|
|
395093
|
+
rmSync6(join40(this.storageDir, "conversations", encodePathSegment(key), "system-prompt.json"), { force: true });
|
|
395012
395094
|
}
|
|
395013
395095
|
}
|
|
395014
395096
|
}
|
|
@@ -395778,11 +395860,11 @@ class LocalStore {
|
|
|
395778
395860
|
});
|
|
395779
395861
|
}
|
|
395780
395862
|
conversationsDir() {
|
|
395781
|
-
return this.storageDir ?
|
|
395863
|
+
return this.storageDir ? join40(this.storageDir, "conversations") : undefined;
|
|
395782
395864
|
}
|
|
395783
395865
|
conversationDirForKey(key) {
|
|
395784
395866
|
const conversationsDir = this.conversationsDir();
|
|
395785
|
-
return conversationsDir ?
|
|
395867
|
+
return conversationsDir ? join40(conversationsDir, encodePathSegment(key)) : undefined;
|
|
395786
395868
|
}
|
|
395787
395869
|
updateConversationSequences(conversation) {
|
|
395788
395870
|
this.conversationSeq = Math.max(this.conversationSeq, numericSuffix(conversation.id, this.conversationIdPrefix));
|
|
@@ -395801,7 +395883,7 @@ class LocalStore {
|
|
|
395801
395883
|
const conversation = requiresFullTimestampRepair ? normalizedInput : repairSyntheticConversationTimestamps(normalizedInput, [], timing);
|
|
395802
395884
|
let compiledSystemPrompt;
|
|
395803
395885
|
try {
|
|
395804
|
-
compiledSystemPrompt = readJsonFile2(
|
|
395886
|
+
compiledSystemPrompt = readJsonFile2(join40(conversationDir, "system-prompt.json"));
|
|
395805
395887
|
} catch {
|
|
395806
395888
|
compiledSystemPrompt = undefined;
|
|
395807
395889
|
}
|
|
@@ -395820,7 +395902,7 @@ class LocalStore {
|
|
|
395820
395902
|
}
|
|
395821
395903
|
loadConversationRecordFromDir(conversationDir) {
|
|
395822
395904
|
try {
|
|
395823
|
-
const conversation = readJsonFile2(
|
|
395905
|
+
const conversation = readJsonFile2(join40(conversationDir, "conversation.json"));
|
|
395824
395906
|
if (!conversation?.id || !conversation.agent_id)
|
|
395825
395907
|
return;
|
|
395826
395908
|
return this.cacheConversationRecord(conversationDir, conversation);
|
|
@@ -395830,7 +395912,7 @@ class LocalStore {
|
|
|
395830
395912
|
}
|
|
395831
395913
|
conversationRecordMtimeMs(conversationDir) {
|
|
395832
395914
|
try {
|
|
395833
|
-
return statSync9(
|
|
395915
|
+
return statSync9(join40(conversationDir, "conversation.json")).mtimeMs;
|
|
395834
395916
|
} catch {
|
|
395835
395917
|
return;
|
|
395836
395918
|
}
|
|
@@ -395856,7 +395938,7 @@ class LocalStore {
|
|
|
395856
395938
|
return existing;
|
|
395857
395939
|
}
|
|
395858
395940
|
try {
|
|
395859
|
-
const conversation = readJsonFile2(
|
|
395941
|
+
const conversation = readJsonFile2(join40(conversationDir, "conversation.json"));
|
|
395860
395942
|
if (!conversation?.id || !conversation.agent_id)
|
|
395861
395943
|
return existing;
|
|
395862
395944
|
const loadedKey = this.conversationKey(conversation.id, conversation.agent_id);
|
|
@@ -395875,7 +395957,7 @@ class LocalStore {
|
|
|
395875
395957
|
return;
|
|
395876
395958
|
this.conversationRecordsScanned = true;
|
|
395877
395959
|
const conversationsDir = this.conversationsDir();
|
|
395878
|
-
if (!conversationsDir || !
|
|
395960
|
+
if (!conversationsDir || !existsSync33(conversationsDir))
|
|
395879
395961
|
return;
|
|
395880
395962
|
let entries;
|
|
395881
395963
|
try {
|
|
@@ -395884,7 +395966,7 @@ class LocalStore {
|
|
|
395884
395966
|
return;
|
|
395885
395967
|
}
|
|
395886
395968
|
for (const entry of entries) {
|
|
395887
|
-
const conversationDir =
|
|
395969
|
+
const conversationDir = join40(conversationsDir, entry);
|
|
395888
395970
|
try {
|
|
395889
395971
|
if (!statSync9(conversationDir).isDirectory())
|
|
395890
395972
|
continue;
|
|
@@ -395900,14 +395982,14 @@ class LocalStore {
|
|
|
395900
395982
|
}
|
|
395901
395983
|
}
|
|
395902
395984
|
loadFromStorage() {
|
|
395903
|
-
if (!this.storageDir || !
|
|
395985
|
+
if (!this.storageDir || !existsSync33(this.storageDir))
|
|
395904
395986
|
return;
|
|
395905
|
-
const agentsDir =
|
|
395906
|
-
if (
|
|
395987
|
+
const agentsDir = join40(this.storageDir, "agents");
|
|
395988
|
+
if (existsSync33(agentsDir)) {
|
|
395907
395989
|
for (const file3 of readdirSync11(agentsDir)) {
|
|
395908
395990
|
if (!file3.endsWith(".json"))
|
|
395909
395991
|
continue;
|
|
395910
|
-
const raw = readJsonFile2(
|
|
395992
|
+
const raw = readJsonFile2(join40(agentsDir, file3));
|
|
395911
395993
|
const agent2 = normalizeAgentRecord(raw, this.defaultAgentModel);
|
|
395912
395994
|
if (agent2?.id) {
|
|
395913
395995
|
this.agents.set(agent2.id, agent2);
|
|
@@ -395924,9 +396006,9 @@ class LocalStore {
|
|
|
395924
396006
|
const agent2 = this.agents.get(agentId);
|
|
395925
396007
|
if (!agent2)
|
|
395926
396008
|
return;
|
|
395927
|
-
const agentsDir =
|
|
395928
|
-
|
|
395929
|
-
|
|
396009
|
+
const agentsDir = join40(this.storageDir, "agents");
|
|
396010
|
+
mkdirSync24(agentsDir, { recursive: true });
|
|
396011
|
+
writeFileSync18(join40(agentsDir, `${encodePathSegment(agentId)}.json`), `${JSON.stringify(agent2, null, 2)}
|
|
395930
396012
|
`);
|
|
395931
396013
|
}
|
|
395932
396014
|
projectAgent(record5) {
|
|
@@ -395943,15 +396025,15 @@ class LocalStore {
|
|
|
395943
396025
|
const conversation = this.conversations.get(key);
|
|
395944
396026
|
if (!conversation)
|
|
395945
396027
|
return;
|
|
395946
|
-
const conversationDir =
|
|
395947
|
-
|
|
395948
|
-
|
|
396028
|
+
const conversationDir = join40(this.storageDir, "conversations", encodePathSegment(key));
|
|
396029
|
+
mkdirSync24(conversationDir, { recursive: true });
|
|
396030
|
+
writeFileSync18(join40(conversationDir, "conversation.json"), `${JSON.stringify(conversation, null, 2)}
|
|
395949
396031
|
`);
|
|
395950
396032
|
this.recordConversationRecordMtime(key, conversationDir);
|
|
395951
396033
|
const messagesPath = transcriptMessagesPath(conversationDir);
|
|
395952
396034
|
let metadata = this.transcriptMetadataRecord(key, conversationDir);
|
|
395953
396035
|
const manifestPath = transcriptManifestPath(conversationDir);
|
|
395954
|
-
if (!
|
|
396036
|
+
if (!existsSync33(manifestPath) && !hasNonEmptyJsonl(messagesPath)) {
|
|
395955
396037
|
const manifest = createLocalTranscriptManifest();
|
|
395956
396038
|
writeLocalTranscriptManifest(conversationDir, manifest);
|
|
395957
396039
|
metadata = this.setTranscriptMetadata(key, {
|
|
@@ -395970,7 +396052,7 @@ class LocalStore {
|
|
|
395970
396052
|
persistConversationTranscript(key, conversation, conversationDir, messagesPath, messageFormat, options3) {
|
|
395971
396053
|
if (options3.transcript === "skip")
|
|
395972
396054
|
return;
|
|
395973
|
-
if (options3.transcript === undefined && this.loadRepairedConversationKeys.has(key) &&
|
|
396055
|
+
if (options3.transcript === undefined && this.loadRepairedConversationKeys.has(key) && existsSync33(messagesPath)) {
|
|
395974
396056
|
return;
|
|
395975
396057
|
}
|
|
395976
396058
|
const messages = this.localMessagesByConversationKey.get(key) ?? [];
|
|
@@ -396005,7 +396087,7 @@ class LocalStore {
|
|
|
396005
396087
|
this.appendConversationSessionCompactionEntry(key, conversation, messagesPath, options3.compaction);
|
|
396006
396088
|
return;
|
|
396007
396089
|
}
|
|
396008
|
-
if (options3.transcript === "rewrite" || this.loadedConversationKeys.has(key) || !
|
|
396090
|
+
if (options3.transcript === "rewrite" || this.loadedConversationKeys.has(key) || !existsSync33(messagesPath)) {
|
|
396009
396091
|
if (messages.length === 0)
|
|
396010
396092
|
return;
|
|
396011
396093
|
this.rewriteConversationSessionTranscript(key, conversation, messagesPath, messages);
|
|
@@ -396016,7 +396098,7 @@ class LocalStore {
|
|
|
396016
396098
|
if (messages.length === 0)
|
|
396017
396099
|
return;
|
|
396018
396100
|
const entries = localTranscriptSessionEntries(conversation, messages);
|
|
396019
|
-
|
|
396101
|
+
writeFileSync18(messagesPath, jsonl(entries));
|
|
396020
396102
|
this.resetPersistedSessionStateFromEntries(key, entries);
|
|
396021
396103
|
}
|
|
396022
396104
|
appendConversationSessionMessageEntry(key, conversation, messagesPath, message) {
|
|
@@ -396066,9 +396148,9 @@ class LocalStore {
|
|
|
396066
396148
|
this.lastSessionEntryIdByConversationKey.set(key, entry.id);
|
|
396067
396149
|
}
|
|
396068
396150
|
ensureConversationTranscriptHeader(conversation, messagesPath) {
|
|
396069
|
-
if (
|
|
396151
|
+
if (existsSync33(messagesPath) && statSync9(messagesPath).size > 0)
|
|
396070
396152
|
return;
|
|
396071
|
-
|
|
396153
|
+
writeFileSync18(messagesPath, `${JSON.stringify(createLocalTranscriptSessionHeader(conversation))}
|
|
396072
396154
|
`);
|
|
396073
396155
|
}
|
|
396074
396156
|
resetPersistedSessionState(key, messageFormat, transcript) {
|
|
@@ -396125,9 +396207,9 @@ class LocalStore {
|
|
|
396125
396207
|
const prompt = this.compiledSystemPromptByConversationKey.get(key);
|
|
396126
396208
|
if (!prompt)
|
|
396127
396209
|
return;
|
|
396128
|
-
const conversationDir =
|
|
396129
|
-
|
|
396130
|
-
|
|
396210
|
+
const conversationDir = join40(this.storageDir, "conversations", encodePathSegment(key));
|
|
396211
|
+
mkdirSync24(conversationDir, { recursive: true });
|
|
396212
|
+
writeFileSync18(join40(conversationDir, "system-prompt.json"), `${JSON.stringify(prompt, null, 2)}
|
|
396131
396213
|
`);
|
|
396132
396214
|
}
|
|
396133
396215
|
ensureConversation(conversationId, agentId) {
|
|
@@ -396156,7 +396238,7 @@ class LocalStore {
|
|
|
396156
396238
|
if (this.conversations.has(key))
|
|
396157
396239
|
continue;
|
|
396158
396240
|
const conversationDir = this.conversationDirForKey(key);
|
|
396159
|
-
if (conversationDir &&
|
|
396241
|
+
if (conversationDir && existsSync33(conversationDir))
|
|
396160
396242
|
continue;
|
|
396161
396243
|
return conversationId;
|
|
396162
396244
|
}
|
|
@@ -398846,11 +398928,21 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
398846
398928
|
return;
|
|
398847
398929
|
const modelSettings = localModelSettingsForHandle(handle);
|
|
398848
398930
|
const maxContextWindow = options4.maxContextWindow ?? (typeof modelSettings?.context_window_limit === "number" ? modelSettings.context_window_limit : undefined);
|
|
398931
|
+
const maxOutputTokens = options4.maxOutputTokens ?? (typeof modelSettings?.max_tokens === "number" ? modelSettings.max_tokens : undefined);
|
|
398932
|
+
const modelId = typeof provider === "string" && isPiProvider(provider) ? stripProviderHandlePrefix(handle, provider) ?? model : model;
|
|
398933
|
+
const providerSpec = isPiProvider(provider) ? getPiProviderSpec(provider) : undefined;
|
|
398934
|
+
const catalogModel = providerSpec?.piProvider ? getModels(providerSpec.piProvider).find((entry) => entry.id === modelId) : undefined;
|
|
398935
|
+
const providerType = options4.modelEndpointType ?? localProviderTypeForModelConfig(provider);
|
|
398936
|
+
const name = options4.name ?? catalogModel?.name ?? modelId;
|
|
398849
398937
|
models3.push({
|
|
398938
|
+
display_name: name,
|
|
398850
398939
|
handle,
|
|
398851
398940
|
...maxContextWindow ? { max_context_window: maxContextWindow } : {},
|
|
398941
|
+
...maxOutputTokens ? { max_tokens: maxOutputTokens } : {},
|
|
398852
398942
|
model: handle,
|
|
398853
|
-
model_endpoint_type:
|
|
398943
|
+
model_endpoint_type: providerType,
|
|
398944
|
+
name,
|
|
398945
|
+
provider_type: providerType
|
|
398854
398946
|
});
|
|
398855
398947
|
};
|
|
398856
398948
|
for (const provider of registeredProviders2) {
|
|
@@ -398864,7 +398956,9 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
398864
398956
|
addModel(provider.providerName, model.id, {
|
|
398865
398957
|
handle: `${provider.providerName}/${model.id}`,
|
|
398866
398958
|
maxContextWindow: model.contextWindow,
|
|
398867
|
-
|
|
398959
|
+
maxOutputTokens: model.maxTokens,
|
|
398960
|
+
modelEndpointType: provider.providerName,
|
|
398961
|
+
name: model.name
|
|
398868
398962
|
});
|
|
398869
398963
|
}
|
|
398870
398964
|
} catch {
|
|
@@ -398872,7 +398966,9 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
398872
398966
|
addModel(provider.providerName, model.id, {
|
|
398873
398967
|
handle: `${provider.providerName}/${model.id}`,
|
|
398874
398968
|
maxContextWindow: model.contextWindow,
|
|
398875
|
-
|
|
398969
|
+
maxOutputTokens: model.maxTokens,
|
|
398970
|
+
modelEndpointType: provider.providerName,
|
|
398971
|
+
name: model.name
|
|
398876
398972
|
});
|
|
398877
398973
|
}
|
|
398878
398974
|
}
|
|
@@ -400397,7 +400493,7 @@ Keep your summary under ${SLIDING_WORD_LIMIT} words. Only output the summary.`;
|
|
|
400397
400493
|
// src/backend/local/system-prompt-compilation.ts
|
|
400398
400494
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
400399
400495
|
import { createHash as createHash4 } from "node:crypto";
|
|
400400
|
-
import { existsSync as
|
|
400496
|
+
import { existsSync as existsSync34 } from "node:fs";
|
|
400401
400497
|
import { basename as basename16, dirname as dirname21, relative as relative6 } from "node:path";
|
|
400402
400498
|
function hashString(value) {
|
|
400403
400499
|
return createHash4("sha256").update(value).digest("hex");
|
|
@@ -400419,7 +400515,7 @@ function gitOutput(memoryDir, args) {
|
|
|
400419
400515
|
});
|
|
400420
400516
|
}
|
|
400421
400517
|
function getCommittedMemfsRevision(memoryDir) {
|
|
400422
|
-
if (!
|
|
400518
|
+
if (!existsSync34(memoryDir))
|
|
400423
400519
|
return;
|
|
400424
400520
|
try {
|
|
400425
400521
|
const revision = gitOutput(memoryDir, [
|
|
@@ -438685,9 +438781,9 @@ var init_paste_registry = __esm(() => {
|
|
|
438685
438781
|
|
|
438686
438782
|
// src/cli/helpers/clipboard.ts
|
|
438687
438783
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
438688
|
-
import { existsSync as
|
|
438784
|
+
import { existsSync as existsSync36, readFileSync as readFileSync26, statSync as statSync10, unlinkSync as unlinkSync5 } from "node:fs";
|
|
438689
438785
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
438690
|
-
import { basename as basename18, extname as extname10, isAbsolute as isAbsolute21, join as
|
|
438786
|
+
import { basename as basename18, extname as extname10, isAbsolute as isAbsolute21, join as join41, resolve as resolve29 } from "node:path";
|
|
438691
438787
|
function countLines(text2) {
|
|
438692
438788
|
return (text2.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
438693
438789
|
}
|
|
@@ -438777,7 +438873,7 @@ function translatePasteForImages(paste) {
|
|
|
438777
438873
|
function getClipboardImageToTempFile() {
|
|
438778
438874
|
if (process.platform !== "darwin")
|
|
438779
438875
|
return null;
|
|
438780
|
-
const tempPath =
|
|
438876
|
+
const tempPath = join41(tmpdir7(), `letta-clipboard-${Date.now()}.bin`);
|
|
438781
438877
|
try {
|
|
438782
438878
|
const jxa = `
|
|
438783
438879
|
ObjC.import('AppKit');
|
|
@@ -438800,11 +438896,11 @@ function getClipboardImageToTempFile() {
|
|
|
438800
438896
|
encoding: "utf8",
|
|
438801
438897
|
stdio: ["ignore", "pipe", "ignore"]
|
|
438802
438898
|
}).trim();
|
|
438803
|
-
if (!uti || !
|
|
438899
|
+
if (!uti || !existsSync36(tempPath))
|
|
438804
438900
|
return null;
|
|
438805
438901
|
return { tempPath, uti };
|
|
438806
438902
|
} catch {
|
|
438807
|
-
if (
|
|
438903
|
+
if (existsSync36(tempPath)) {
|
|
438808
438904
|
try {
|
|
438809
438905
|
unlinkSync5(tempPath);
|
|
438810
438906
|
} catch {}
|
|
@@ -438837,7 +438933,7 @@ async function tryImportClipboardImageMac() {
|
|
|
438837
438933
|
height: resized.height
|
|
438838
438934
|
};
|
|
438839
438935
|
} catch (err) {
|
|
438840
|
-
if (
|
|
438936
|
+
if (existsSync36(tempPath)) {
|
|
438841
438937
|
try {
|
|
438842
438938
|
unlinkSync5(tempPath);
|
|
438843
438939
|
} catch {}
|
|
@@ -439320,18 +439416,18 @@ var init_local = __esm(() => {
|
|
|
439320
439416
|
});
|
|
439321
439417
|
|
|
439322
439418
|
// src/cli/helpers/local-agent-listing.ts
|
|
439323
|
-
import { existsSync as
|
|
439324
|
-
import { join as
|
|
439419
|
+
import { existsSync as existsSync38, readdirSync as readdirSync13, readFileSync as readFileSync27, statSync as statSync12 } from "node:fs";
|
|
439420
|
+
import { join as join43 } from "node:path";
|
|
439325
439421
|
function listLocalAgentsFromDisk() {
|
|
439326
439422
|
const storageDir = getLocalBackendStorageDir();
|
|
439327
|
-
const agentsDir =
|
|
439328
|
-
if (!
|
|
439423
|
+
const agentsDir = join43(storageDir, "agents");
|
|
439424
|
+
if (!existsSync38(agentsDir))
|
|
439329
439425
|
return [];
|
|
439330
439426
|
const files = readdirSync13(agentsDir).filter((f4) => f4.endsWith(".json"));
|
|
439331
439427
|
const agents = [];
|
|
439332
439428
|
for (const file3 of files) {
|
|
439333
439429
|
try {
|
|
439334
|
-
const filePath =
|
|
439430
|
+
const filePath = join43(agentsDir, file3);
|
|
439335
439431
|
const raw2 = readFileSync27(filePath, "utf8");
|
|
439336
439432
|
const record5 = JSON.parse(raw2);
|
|
439337
439433
|
if (isHiddenLocalAgentRecord(record5))
|
|
@@ -440049,23 +440145,23 @@ __export(exports_personality, {
|
|
|
440049
440145
|
applyPersonalityToMemory: () => applyPersonalityToMemory
|
|
440050
440146
|
});
|
|
440051
440147
|
import { execFile as execFileCb3 } from "node:child_process";
|
|
440052
|
-
import { existsSync as
|
|
440053
|
-
import { dirname as dirname22, join as
|
|
440148
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync26, readFileSync as readFileSync28, writeFileSync as writeFileSync19 } from "node:fs";
|
|
440149
|
+
import { dirname as dirname22, join as join44 } from "node:path";
|
|
440054
440150
|
import { promisify as promisify7 } from "node:util";
|
|
440055
440151
|
function ensureTrailingNewline2(content) {
|
|
440056
440152
|
return `${content.trimEnd()}
|
|
440057
440153
|
`;
|
|
440058
440154
|
}
|
|
440059
440155
|
function getMemoryFileRelativePathForRepo(repoDir, primaryRelativePath, legacyRelativePath) {
|
|
440060
|
-
const primaryPath =
|
|
440061
|
-
if (
|
|
440156
|
+
const primaryPath = join44(repoDir, primaryRelativePath);
|
|
440157
|
+
if (existsSync39(primaryPath)) {
|
|
440062
440158
|
return primaryRelativePath;
|
|
440063
440159
|
}
|
|
440064
|
-
const legacyPath =
|
|
440065
|
-
if (
|
|
440160
|
+
const legacyPath = join44(repoDir, legacyRelativePath);
|
|
440161
|
+
if (existsSync39(legacyPath)) {
|
|
440066
440162
|
return legacyRelativePath;
|
|
440067
440163
|
}
|
|
440068
|
-
if (
|
|
440164
|
+
if (existsSync39(join44(repoDir, "memory"))) {
|
|
440069
440165
|
return legacyRelativePath;
|
|
440070
440166
|
}
|
|
440071
440167
|
return primaryRelativePath;
|
|
@@ -440175,15 +440271,15 @@ async function getMemoryCommitAuthor(agentId) {
|
|
|
440175
440271
|
function applyPersonalityFiles(filesToUpdate) {
|
|
440176
440272
|
const changedPaths = [];
|
|
440177
440273
|
for (const file3 of filesToUpdate) {
|
|
440178
|
-
const existingContent =
|
|
440274
|
+
const existingContent = existsSync39(file3.absolutePath) ? readFileSync28(file3.absolutePath, "utf-8") : null;
|
|
440179
440275
|
const nextContent = existingContent ? replaceBodyPreservingFrontmatter(existingContent, file3.content, {
|
|
440180
440276
|
description: file3.description
|
|
440181
440277
|
}) : buildDefaultMemoryFile(file3.templatePromptAssetName, file3.content, file3.description);
|
|
440182
440278
|
if (existingContent !== null && normalizeComparableContent(existingContent) === normalizeComparableContent(nextContent)) {
|
|
440183
440279
|
continue;
|
|
440184
440280
|
}
|
|
440185
|
-
|
|
440186
|
-
|
|
440281
|
+
mkdirSync26(dirname22(file3.absolutePath), { recursive: true });
|
|
440282
|
+
writeFileSync19(file3.absolutePath, nextContent, "utf-8");
|
|
440187
440283
|
changedPaths.push(file3.relativePath);
|
|
440188
440284
|
}
|
|
440189
440285
|
return changedPaths;
|
|
@@ -440205,8 +440301,8 @@ async function applyPersonalityToMemory(params) {
|
|
|
440205
440301
|
}
|
|
440206
440302
|
const personaRelativePath = getPersonaRelativePathForRepo(repoDir);
|
|
440207
440303
|
const humanRelativePath = getHumanRelativePathForRepo(repoDir);
|
|
440208
|
-
const personaPath =
|
|
440209
|
-
const humanPath =
|
|
440304
|
+
const personaPath = join44(repoDir, personaRelativePath);
|
|
440305
|
+
const humanPath = join44(repoDir, humanRelativePath);
|
|
440210
440306
|
const filesToUpdate = [
|
|
440211
440307
|
{
|
|
440212
440308
|
relativePath: personaRelativePath,
|
|
@@ -440645,13 +440741,14 @@ var init_progress_builder = __esm(async () => {
|
|
|
440645
440741
|
// src/agent/memory-worktree.ts
|
|
440646
440742
|
import { execFile as execFileCb4 } from "node:child_process";
|
|
440647
440743
|
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
440648
|
-
import { existsSync as
|
|
440744
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
440649
440745
|
import { mkdir as mkdir11, realpath as realpath4 } from "node:fs/promises";
|
|
440650
|
-
import { dirname as dirname23, isAbsolute as isAbsolute23, join as
|
|
440746
|
+
import { dirname as dirname23, isAbsolute as isAbsolute23, join as join45, relative as relative7, resolve as resolve30 } from "node:path";
|
|
440651
440747
|
import { promisify as promisify8 } from "node:util";
|
|
440652
440748
|
async function runGit4(cwd2, args) {
|
|
440653
440749
|
try {
|
|
440654
|
-
const
|
|
440750
|
+
const allArgs = [...GIT_DISABLE_COMMIT_SIGNING_ARGS, ...args];
|
|
440751
|
+
const { stdout, stderr } = await execFile8("git", allArgs, {
|
|
440655
440752
|
cwd: cwd2,
|
|
440656
440753
|
env: {
|
|
440657
440754
|
...process.env,
|
|
@@ -440706,8 +440803,8 @@ async function buildReflectionMergeMessage(parentMemoryDir, branchName) {
|
|
|
440706
440803
|
async function createReflectionMemoryWorktree(options3) {
|
|
440707
440804
|
const parentMemoryDir = resolve30(options3.parentMemoryDir);
|
|
440708
440805
|
const id2 = buildReflectionWorktreeId(options3.now);
|
|
440709
|
-
const worktreeBaseDir =
|
|
440710
|
-
const worktreeDir =
|
|
440806
|
+
const worktreeBaseDir = join45(dirname23(parentMemoryDir), "memory-worktrees");
|
|
440807
|
+
const worktreeDir = join45(worktreeBaseDir, `reflection-${id2}`);
|
|
440711
440808
|
const branchName = `letta/reflection/${id2}`;
|
|
440712
440809
|
await mkdir11(worktreeBaseDir, { recursive: true });
|
|
440713
440810
|
const { stdout: baseHeadOut } = await runGit4(parentMemoryDir, [
|
|
@@ -440824,7 +440921,7 @@ function parseWorktreeListPorcelain(output) {
|
|
|
440824
440921
|
}
|
|
440825
440922
|
async function listPendingReflectionMemoryWorktrees(parentMemoryDir) {
|
|
440826
440923
|
const resolvedParent = await realpath4(resolve30(parentMemoryDir));
|
|
440827
|
-
const worktreeBaseDir =
|
|
440924
|
+
const worktreeBaseDir = join45(dirname23(resolvedParent), "memory-worktrees");
|
|
440828
440925
|
const worktreeList = await tryRunGit(resolvedParent, [
|
|
440829
440926
|
"worktree",
|
|
440830
440927
|
"list",
|
|
@@ -440915,7 +441012,7 @@ async function integratePendingReflectionMemoryWorktrees(parentMemoryDir) {
|
|
|
440915
441012
|
return unresolved;
|
|
440916
441013
|
}
|
|
440917
441014
|
async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName, options3 = {}) {
|
|
440918
|
-
const removedWorktree =
|
|
441015
|
+
const removedWorktree = existsSync40(worktreeDir);
|
|
440919
441016
|
if (removedWorktree) {
|
|
440920
441017
|
await runGit4(parentMemoryDir, [
|
|
440921
441018
|
"worktree",
|
|
@@ -441026,6 +441123,7 @@ async function finalizeReflectionMemoryWorktree(worktree, options3) {
|
|
|
441026
441123
|
}
|
|
441027
441124
|
var execFile8, GIT_TIMEOUT_MS = 30000, HARNESS_GIT_ENV;
|
|
441028
441125
|
var init_memory_worktree = __esm(() => {
|
|
441126
|
+
init_memory_git_signing();
|
|
441029
441127
|
init_debug();
|
|
441030
441128
|
execFile8 = promisify8(execFileCb4);
|
|
441031
441129
|
HARNESS_GIT_ENV = {
|
|
@@ -441292,7 +441390,7 @@ import {
|
|
|
441292
441390
|
stat as stat11,
|
|
441293
441391
|
writeFile as writeFile13
|
|
441294
441392
|
} from "node:fs/promises";
|
|
441295
|
-
import { join as
|
|
441393
|
+
import { join as join46 } from "node:path";
|
|
441296
441394
|
function buildReflectionSubagentPrompt(input) {
|
|
441297
441395
|
const lines = [];
|
|
441298
441396
|
lines.push('Review the conversation transcript payload and update memory files. The payload path is available as the `$TRANSCRIPT_PATH` env var — read it via Bash (e.g. `wc -c "$TRANSCRIPT_PATH"`). Note: `$TRANSCRIPT_PATH` only expands in shell commands; Edit `file_path` is literal and does NOT expand env vars.', "", 'The payload may be either a JSON message array for one conversation or a `multi_transcript_reflection_payload` manifest. If it is a manifest, read each `payload_path` listed in `transcripts` and synthesize across all conversations. Entries with `mode: "replay"` were already reflected before and are included intentionally for re-review/deduplication; do not ignore them just because they are replay slices.', "When reviewing multiple transcripts, prefer durable patterns and latest evidence across sessions. Resolve contradictions by updating stale memory at the source, deduplicate repeated facts, and avoid storing one-off task state.", "", "The primary agent's memory filesystem is available through the `$MEMORY_DIR` environment variable.", "Run git add or git commit commands only from $MEMORY_DIR; the harness handles integration after your commit. If these fail, stop reflecting and report the failure. All other git commands are out of your purview.", 'When using Edit, first resolve the absolute file path from `$MEMORY_DIR` with Bash (for example: `printf "%s/system/persona.md\\n" "$MEMORY_DIR"`) and use the printed path. Do not hardcode memory paths from the prompt.', "In-context memory (in the parent agent's system prompt) is stored in the `system/` folder and are rendered in <memory> tags below. Modification to files in `system/` will edit the parent agent's system prompt.", "Additional memory files (such as skills and external memory) may also be read and modified.", "");
|
|
@@ -441338,7 +441436,7 @@ async function collectParentMemoryFiles(memoryDir) {
|
|
|
441338
441436
|
return a2.name.localeCompare(b3.name);
|
|
441339
441437
|
});
|
|
441340
441438
|
for (const entry of sortedEntries) {
|
|
441341
|
-
const entryPath =
|
|
441439
|
+
const entryPath = join46(currentDir, entry.name);
|
|
441342
441440
|
const relativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
|
|
441343
441441
|
if (entry.isDirectory()) {
|
|
441344
441442
|
await walk(entryPath, relativePath);
|
|
@@ -441784,17 +441882,17 @@ async function writeState(paths, state) {
|
|
|
441784
441882
|
}
|
|
441785
441883
|
function buildPayloadPath(rootDir, kind) {
|
|
441786
441884
|
const nonce = Math.random().toString(36).slice(2, 8);
|
|
441787
|
-
return
|
|
441885
|
+
return join46(rootDir, `payload-${kind}-${nonce}.json`);
|
|
441788
441886
|
}
|
|
441789
441887
|
function getAgentTranscriptRoot(agentId) {
|
|
441790
|
-
return
|
|
441888
|
+
return join46(getTranscriptRoot(), sanitizePathSegment2(agentId));
|
|
441791
441889
|
}
|
|
441792
441890
|
function getReflectionTranscriptPaths(agentId, conversationId) {
|
|
441793
|
-
const rootDir =
|
|
441891
|
+
const rootDir = join46(getTranscriptRoot(), sanitizePathSegment2(agentId), sanitizePathSegment2(conversationId));
|
|
441794
441892
|
return {
|
|
441795
441893
|
rootDir,
|
|
441796
|
-
transcriptPath:
|
|
441797
|
-
statePath:
|
|
441894
|
+
transcriptPath: join46(rootDir, "transcript.jsonl"),
|
|
441895
|
+
statePath: join46(rootDir, "state.json")
|
|
441798
441896
|
};
|
|
441799
441897
|
}
|
|
441800
441898
|
async function appendTranscriptDeltaJsonl(agentId, conversationId, lines) {
|
|
@@ -441963,7 +442061,7 @@ async function getTranscriptLastUpdatedAt(paths) {
|
|
|
441963
442061
|
}
|
|
441964
442062
|
}
|
|
441965
442063
|
async function ensureAgentPayloadRoot(agentId) {
|
|
441966
|
-
const root2 =
|
|
442064
|
+
const root2 = join46(getAgentTranscriptRoot(agentId), "multi-reflection-payloads");
|
|
441967
442065
|
await mkdir12(root2, { recursive: true });
|
|
441968
442066
|
return root2;
|
|
441969
442067
|
}
|
|
@@ -443910,25 +444008,25 @@ var init_parse_interval = __esm(() => {
|
|
|
443910
444008
|
// src/cron/cron-file.ts
|
|
443911
444009
|
import { randomBytes } from "node:crypto";
|
|
443912
444010
|
import {
|
|
443913
|
-
existsSync as
|
|
443914
|
-
mkdirSync as
|
|
444011
|
+
existsSync as existsSync41,
|
|
444012
|
+
mkdirSync as mkdirSync27,
|
|
443915
444013
|
readFileSync as readFileSync29,
|
|
443916
444014
|
renameSync as renameSync4,
|
|
443917
444015
|
rmSync as rmSync8,
|
|
443918
444016
|
statSync as statSync13,
|
|
443919
|
-
writeFileSync as
|
|
444017
|
+
writeFileSync as writeFileSync20
|
|
443920
444018
|
} from "node:fs";
|
|
443921
|
-
import { join as
|
|
444019
|
+
import { join as join47 } from "node:path";
|
|
443922
444020
|
function getLettaDir() {
|
|
443923
444021
|
if (process.env.LETTA_HOME)
|
|
443924
444022
|
return process.env.LETTA_HOME;
|
|
443925
|
-
return
|
|
444023
|
+
return join47(process.env.HOME ?? process.env.USERPROFILE ?? "~", ".letta");
|
|
443926
444024
|
}
|
|
443927
444025
|
function getCronFilePath() {
|
|
443928
|
-
return
|
|
444026
|
+
return join47(getLettaDir(), CRON_FILE_NAME);
|
|
443929
444027
|
}
|
|
443930
444028
|
function getLockDirPath() {
|
|
443931
|
-
return
|
|
444029
|
+
return join47(getLettaDir(), LOCK_DIR_NAME);
|
|
443932
444030
|
}
|
|
443933
444031
|
function emptyFile() {
|
|
443934
444032
|
return {
|
|
@@ -443958,7 +444056,7 @@ function normalizeCronFileData(data) {
|
|
|
443958
444056
|
}
|
|
443959
444057
|
function readCronFile() {
|
|
443960
444058
|
const path31 = getCronFilePath();
|
|
443961
|
-
if (!
|
|
444059
|
+
if (!existsSync41(path31))
|
|
443962
444060
|
return emptyFile();
|
|
443963
444061
|
try {
|
|
443964
444062
|
const raw2 = readFileSync29(path31, "utf-8");
|
|
@@ -443973,11 +444071,11 @@ function readCronFile() {
|
|
|
443973
444071
|
function writeCronFile(data) {
|
|
443974
444072
|
const path31 = getCronFilePath();
|
|
443975
444073
|
const dir = getLettaDir();
|
|
443976
|
-
if (!
|
|
443977
|
-
|
|
444074
|
+
if (!existsSync41(dir)) {
|
|
444075
|
+
mkdirSync27(dir, { recursive: true });
|
|
443978
444076
|
}
|
|
443979
444077
|
const tmp = `${path31}.tmp`;
|
|
443980
|
-
|
|
444078
|
+
writeFileSync20(tmp, JSON.stringify(data, null, 2), { flush: true });
|
|
443981
444079
|
renameSync4(tmp, path31);
|
|
443982
444080
|
}
|
|
443983
444081
|
function readLinuxProcessIdentity(pid) {
|
|
@@ -444035,14 +444133,14 @@ function isProcessAlive(pid, owner) {
|
|
|
444035
444133
|
}
|
|
444036
444134
|
function readLockOwner(lockDir) {
|
|
444037
444135
|
try {
|
|
444038
|
-
const raw2 = readFileSync29(
|
|
444136
|
+
const raw2 = readFileSync29(join47(lockDir, LOCK_TOKEN_FILE), "utf-8");
|
|
444039
444137
|
return JSON.parse(raw2);
|
|
444040
444138
|
} catch {
|
|
444041
444139
|
return null;
|
|
444042
444140
|
}
|
|
444043
444141
|
}
|
|
444044
444142
|
function writeLockOwner(lockDir, owner) {
|
|
444045
|
-
|
|
444143
|
+
writeFileSync20(join47(lockDir, LOCK_TOKEN_FILE), JSON.stringify(owner));
|
|
444046
444144
|
}
|
|
444047
444145
|
function isLockStale(lockDir) {
|
|
444048
444146
|
const owner = readLockOwner(lockDir);
|
|
@@ -444069,7 +444167,7 @@ function acquireLock() {
|
|
|
444069
444167
|
const token2 = randomBytes(4).toString("hex");
|
|
444070
444168
|
while (Date.now() < deadline) {
|
|
444071
444169
|
try {
|
|
444072
|
-
|
|
444170
|
+
mkdirSync27(lockDir, { recursive: false });
|
|
444073
444171
|
const owner = {
|
|
444074
444172
|
pid: process.pid,
|
|
444075
444173
|
token: token2,
|
|
@@ -444314,11 +444412,11 @@ var init_cron_file = __esm(() => {
|
|
|
444314
444412
|
import {
|
|
444315
444413
|
appendFileSync as appendFileSync5,
|
|
444316
444414
|
chmodSync as chmodSync6,
|
|
444317
|
-
existsSync as
|
|
444318
|
-
mkdirSync as
|
|
444415
|
+
existsSync as existsSync42,
|
|
444416
|
+
mkdirSync as mkdirSync28,
|
|
444319
444417
|
readFileSync as readFileSync30,
|
|
444320
444418
|
statSync as statSync14,
|
|
444321
|
-
writeFileSync as
|
|
444419
|
+
writeFileSync as writeFileSync21
|
|
444322
444420
|
} from "node:fs";
|
|
444323
444421
|
import path31 from "node:path";
|
|
444324
444422
|
function assertSafeCronRunLogJobId(jobId) {
|
|
@@ -444368,7 +444466,7 @@ function pruneIfNeeded(filePath, opts) {
|
|
|
444368
444466
|
const lines = raw2.split(`
|
|
444369
444467
|
`).map((line) => line.trim()).filter(Boolean);
|
|
444370
444468
|
const kept = lines.slice(Math.max(0, lines.length - opts.keepLines));
|
|
444371
|
-
|
|
444469
|
+
writeFileSync21(filePath, `${kept.join(`
|
|
444372
444470
|
`)}
|
|
444373
444471
|
`, { mode: 384 });
|
|
444374
444472
|
setSecureFileMode(filePath);
|
|
@@ -444376,8 +444474,8 @@ function pruneIfNeeded(filePath, opts) {
|
|
|
444376
444474
|
function appendCronRunLog(filePath, entry, opts) {
|
|
444377
444475
|
const resolved = path31.resolve(filePath);
|
|
444378
444476
|
const runDir = path31.dirname(resolved);
|
|
444379
|
-
if (!
|
|
444380
|
-
|
|
444477
|
+
if (!existsSync42(runDir)) {
|
|
444478
|
+
mkdirSync28(runDir, { recursive: true, mode: 448 });
|
|
444381
444479
|
}
|
|
444382
444480
|
setSecureDirMode(runDir);
|
|
444383
444481
|
appendFileSync5(resolved, `${JSON.stringify(entry)}
|
|
@@ -445693,9 +445791,9 @@ __export(exports_custom, {
|
|
|
445693
445791
|
GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
|
|
445694
445792
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
445695
445793
|
});
|
|
445696
|
-
import { existsSync as
|
|
445794
|
+
import { existsSync as existsSync43 } from "node:fs";
|
|
445697
445795
|
import { readdir as readdir9, readFile as readFile16 } from "node:fs/promises";
|
|
445698
|
-
import { basename as basename20, dirname as dirname24, join as
|
|
445796
|
+
import { basename as basename20, dirname as dirname24, join as join48 } from "node:path";
|
|
445699
445797
|
async function getCustomCommands() {
|
|
445700
445798
|
if (cachedCommands !== null) {
|
|
445701
445799
|
return cachedCommands;
|
|
@@ -445706,7 +445804,7 @@ async function getCustomCommands() {
|
|
|
445706
445804
|
function refreshCustomCommands() {
|
|
445707
445805
|
cachedCommands = null;
|
|
445708
445806
|
}
|
|
445709
|
-
async function discoverCustomCommands(projectPath =
|
|
445807
|
+
async function discoverCustomCommands(projectPath = join48(process.cwd(), COMMANDS_DIR)) {
|
|
445710
445808
|
const commandsById = new Map;
|
|
445711
445809
|
const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
|
|
445712
445810
|
for (const cmd of userCommands) {
|
|
@@ -445727,7 +445825,7 @@ async function discoverCustomCommands(projectPath = join47(process.cwd(), COMMAN
|
|
|
445727
445825
|
return result;
|
|
445728
445826
|
}
|
|
445729
445827
|
async function discoverFromDirectory(dirPath, source2) {
|
|
445730
|
-
if (!
|
|
445828
|
+
if (!existsSync43(dirPath)) {
|
|
445731
445829
|
return [];
|
|
445732
445830
|
}
|
|
445733
445831
|
const commands = [];
|
|
@@ -445738,7 +445836,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source2) {
|
|
|
445738
445836
|
try {
|
|
445739
445837
|
const entries = await readdir9(currentPath, { withFileTypes: true });
|
|
445740
445838
|
for (const entry of entries) {
|
|
445741
|
-
const fullPath =
|
|
445839
|
+
const fullPath = join48(currentPath, entry.name);
|
|
445742
445840
|
if (entry.isDirectory()) {
|
|
445743
445841
|
await findCommandFiles(fullPath, rootPath, commands, source2);
|
|
445744
445842
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -445823,7 +445921,7 @@ async function findCustomCommand(commandName) {
|
|
|
445823
445921
|
}
|
|
445824
445922
|
var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
|
|
445825
445923
|
var init_custom = __esm(() => {
|
|
445826
|
-
GLOBAL_COMMANDS_DIR =
|
|
445924
|
+
GLOBAL_COMMANDS_DIR = join48(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
|
|
445827
445925
|
});
|
|
445828
445926
|
|
|
445829
445927
|
// src/cli/helpers/init-command.ts
|
|
@@ -445913,7 +446011,7 @@ var init_init_command = __esm(() => {
|
|
|
445913
446011
|
|
|
445914
446012
|
// src/cli/helpers/skill-name-frontmatter-repair.ts
|
|
445915
446013
|
import { readdir as readdir10, readFile as readFile17, stat as stat12, writeFile as writeFile14 } from "node:fs/promises";
|
|
445916
|
-
import { basename as basename21, dirname as dirname25, join as
|
|
446014
|
+
import { basename as basename21, dirname as dirname25, join as join49, relative as relative8 } from "node:path";
|
|
445917
446015
|
async function pathExists(path32) {
|
|
445918
446016
|
try {
|
|
445919
446017
|
await stat12(path32);
|
|
@@ -445929,7 +446027,7 @@ async function findSkillMarkdownFiles(root2) {
|
|
|
445929
446027
|
if (entry.name === ".git" || entry.name === "node_modules") {
|
|
445930
446028
|
continue;
|
|
445931
446029
|
}
|
|
445932
|
-
const fullPath =
|
|
446030
|
+
const fullPath = join49(root2, entry.name);
|
|
445933
446031
|
if (entry.isSymbolicLink()) {
|
|
445934
446032
|
continue;
|
|
445935
446033
|
}
|
|
@@ -446001,7 +446099,7 @@ async function repairMissingSkillNameFrontmatter(memoryDir) {
|
|
|
446001
446099
|
if (!memoryDir) {
|
|
446002
446100
|
return result;
|
|
446003
446101
|
}
|
|
446004
|
-
const skillsDir =
|
|
446102
|
+
const skillsDir = join49(memoryDir, "skills");
|
|
446005
446103
|
if (!await pathExists(skillsDir)) {
|
|
446006
446104
|
return result;
|
|
446007
446105
|
}
|
|
@@ -449003,7 +449101,7 @@ var init_accumulator = __esm(async () => {
|
|
|
449003
449101
|
});
|
|
449004
449102
|
|
|
449005
449103
|
// src/utils/tui-perf.ts
|
|
449006
|
-
import { appendFileSync as appendFileSync6, mkdirSync as
|
|
449104
|
+
import { appendFileSync as appendFileSync6, mkdirSync as mkdirSync29 } from "node:fs";
|
|
449007
449105
|
import { dirname as dirname26 } from "node:path";
|
|
449008
449106
|
function ensureExitHook() {
|
|
449009
449107
|
if (tuiPerfExitHookRegistered) {
|
|
@@ -449095,7 +449193,7 @@ function flushTuiPerfTelemetry() {
|
|
|
449095
449193
|
try {
|
|
449096
449194
|
const dir = dirname26(filePath);
|
|
449097
449195
|
if (tuiPerfFileDirEnsured !== dir) {
|
|
449098
|
-
|
|
449196
|
+
mkdirSync29(dir, { recursive: true });
|
|
449099
449197
|
tuiPerfFileDirEnsured = dir;
|
|
449100
449198
|
}
|
|
449101
449199
|
appendFileSync6(filePath, `${JSON.stringify({
|
|
@@ -449126,14 +449224,14 @@ var init_tui_perf = __esm(() => {
|
|
|
449126
449224
|
|
|
449127
449225
|
// src/cli/helpers/chunk-log.ts
|
|
449128
449226
|
import {
|
|
449129
|
-
existsSync as
|
|
449130
|
-
mkdirSync as
|
|
449227
|
+
existsSync as existsSync44,
|
|
449228
|
+
mkdirSync as mkdirSync30,
|
|
449131
449229
|
readdirSync as readdirSync14,
|
|
449132
449230
|
unlinkSync as unlinkSync6,
|
|
449133
|
-
writeFileSync as
|
|
449231
|
+
writeFileSync as writeFileSync22
|
|
449134
449232
|
} from "node:fs";
|
|
449135
449233
|
import { homedir as homedir29 } from "node:os";
|
|
449136
|
-
import { join as
|
|
449234
|
+
import { join as join50 } from "node:path";
|
|
449137
449235
|
function truncateStr(value, maxLen) {
|
|
449138
449236
|
if (value === null || value === undefined)
|
|
449139
449237
|
return "";
|
|
@@ -449197,8 +449295,8 @@ class ChunkLog {
|
|
|
449197
449295
|
agentDir = null;
|
|
449198
449296
|
dirCreated = false;
|
|
449199
449297
|
init(agentId, sessionId) {
|
|
449200
|
-
this.agentDir =
|
|
449201
|
-
this.logPath =
|
|
449298
|
+
this.agentDir = join50(LOG_BASE_DIR, agentId);
|
|
449299
|
+
this.logPath = join50(this.agentDir, `${sessionId}.jsonl`);
|
|
449202
449300
|
this.buffer = [];
|
|
449203
449301
|
this.dirty = false;
|
|
449204
449302
|
this.dirCreated = false;
|
|
@@ -449227,8 +449325,8 @@ class ChunkLog {
|
|
|
449227
449325
|
if (this.dirCreated || !this.agentDir)
|
|
449228
449326
|
return;
|
|
449229
449327
|
try {
|
|
449230
|
-
if (!
|
|
449231
|
-
|
|
449328
|
+
if (!existsSync44(this.agentDir)) {
|
|
449329
|
+
mkdirSync30(this.agentDir, { recursive: true });
|
|
449232
449330
|
}
|
|
449233
449331
|
this.dirCreated = true;
|
|
449234
449332
|
} catch (e2) {
|
|
@@ -449242,7 +449340,7 @@ class ChunkLog {
|
|
|
449242
449340
|
try {
|
|
449243
449341
|
const content = this.buffer.map((entry) => JSON.stringify(entry)).join(`
|
|
449244
449342
|
`);
|
|
449245
|
-
|
|
449343
|
+
writeFileSync22(this.logPath, `${content}
|
|
449246
449344
|
`, "utf8");
|
|
449247
449345
|
} catch (e2) {
|
|
449248
449346
|
debugWarn("chunkLog", `Failed to write ${this.logPath}: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -449252,14 +449350,14 @@ class ChunkLog {
|
|
|
449252
449350
|
if (!this.agentDir)
|
|
449253
449351
|
return;
|
|
449254
449352
|
try {
|
|
449255
|
-
if (!
|
|
449353
|
+
if (!existsSync44(this.agentDir))
|
|
449256
449354
|
return;
|
|
449257
449355
|
const files = readdirSync14(this.agentDir).filter((f4) => f4.endsWith(".jsonl")).sort();
|
|
449258
449356
|
if (files.length >= MAX_SESSION_FILES2) {
|
|
449259
449357
|
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES2 + 1);
|
|
449260
449358
|
for (const file3 of toDelete) {
|
|
449261
449359
|
try {
|
|
449262
|
-
unlinkSync6(
|
|
449360
|
+
unlinkSync6(join50(this.agentDir, file3));
|
|
449263
449361
|
} catch (e2) {
|
|
449264
449362
|
debugWarn("chunkLog", `Failed to delete old session log ${file3}: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
449265
449363
|
}
|
|
@@ -449273,7 +449371,7 @@ class ChunkLog {
|
|
|
449273
449371
|
var MAX_ENTRIES = 100, CONTENT_TRUNCATE_LEN = 200, MAX_SESSION_FILES2 = 5, LOG_BASE_DIR, chunkLog;
|
|
449274
449372
|
var init_chunk_log = __esm(() => {
|
|
449275
449373
|
init_debug();
|
|
449276
|
-
LOG_BASE_DIR =
|
|
449374
|
+
LOG_BASE_DIR = join50(homedir29(), ".letta", "logs", "chunk-logs");
|
|
449277
449375
|
chunkLog = new ChunkLog;
|
|
449278
449376
|
});
|
|
449279
449377
|
|
|
@@ -458716,7 +458814,7 @@ var init_commands2 = __esm(async () => {
|
|
|
458716
458814
|
});
|
|
458717
458815
|
|
|
458718
458816
|
// src/channels/custom/scaffolding.ts
|
|
458719
|
-
import { existsSync as
|
|
458817
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync31, rmSync as rmSync9, writeFileSync as writeFileSync23 } from "node:fs";
|
|
458720
458818
|
function removeUserPlugin(channelId) {
|
|
458721
458819
|
if (FIRST_PARTY_SET.has(channelId)) {
|
|
458722
458820
|
return;
|
|
@@ -458725,7 +458823,7 @@ function removeUserPlugin(channelId) {
|
|
|
458725
458823
|
return;
|
|
458726
458824
|
}
|
|
458727
458825
|
const channelDir = getChannelDir(channelId);
|
|
458728
|
-
if (!
|
|
458826
|
+
if (!existsSync45(channelDir)) {
|
|
458729
458827
|
return;
|
|
458730
458828
|
}
|
|
458731
458829
|
try {
|
|
@@ -459527,6 +459625,55 @@ var init_toolset_labels = __esm(() => {
|
|
|
459527
459625
|
};
|
|
459528
459626
|
});
|
|
459529
459627
|
|
|
459628
|
+
// src/websocket/listener/commands/model-catalog.ts
|
|
459629
|
+
function buildPresetEntry(model) {
|
|
459630
|
+
return {
|
|
459631
|
+
id: model.id,
|
|
459632
|
+
handle: model.handle,
|
|
459633
|
+
label: model.label,
|
|
459634
|
+
description: model.description,
|
|
459635
|
+
...typeof model.isDefault === "boolean" ? { isDefault: model.isDefault } : {},
|
|
459636
|
+
...typeof model.isFeatured === "boolean" ? { isFeatured: model.isFeatured } : {},
|
|
459637
|
+
...typeof model.free === "boolean" ? { free: model.free } : {},
|
|
459638
|
+
...model.updateArgs && typeof model.updateArgs === "object" ? { updateArgs: model.updateArgs } : {}
|
|
459639
|
+
};
|
|
459640
|
+
}
|
|
459641
|
+
function buildNativeEntry(model) {
|
|
459642
|
+
return {
|
|
459643
|
+
id: model.handle,
|
|
459644
|
+
handle: model.handle,
|
|
459645
|
+
label: model.label,
|
|
459646
|
+
description: ""
|
|
459647
|
+
};
|
|
459648
|
+
}
|
|
459649
|
+
function modelIdentity(handle2) {
|
|
459650
|
+
return resolvePiModelIdentity(handle2) ?? handle2;
|
|
459651
|
+
}
|
|
459652
|
+
function findAvailableModelForPreset(presetHandle, availableModels) {
|
|
459653
|
+
return availableModels.find((model) => model.handle === presetHandle) ?? availableModels.find((model) => modelIdentity(model.handle) === modelIdentity(presetHandle));
|
|
459654
|
+
}
|
|
459655
|
+
function buildListModelsEntries(availableModels = []) {
|
|
459656
|
+
const presetEntries = models2.map((model) => {
|
|
459657
|
+
const entry = buildPresetEntry(model);
|
|
459658
|
+
const availableModel = findAvailableModelForPreset(entry.handle, availableModels);
|
|
459659
|
+
return availableModel ? { ...entry, handle: availableModel.handle } : entry;
|
|
459660
|
+
});
|
|
459661
|
+
const presetHandles = new Set(presetEntries.map((entry) => entry.handle));
|
|
459662
|
+
const nativeHandles = new Set;
|
|
459663
|
+
const nativeEntries = availableModels.flatMap((model) => {
|
|
459664
|
+
if (nativeHandles.has(model.handle) || presetHandles.has(model.handle)) {
|
|
459665
|
+
return [];
|
|
459666
|
+
}
|
|
459667
|
+
nativeHandles.add(model.handle);
|
|
459668
|
+
return [buildNativeEntry(model)];
|
|
459669
|
+
});
|
|
459670
|
+
return [...presetEntries, ...nativeEntries];
|
|
459671
|
+
}
|
|
459672
|
+
var init_model_catalog2 = __esm(() => {
|
|
459673
|
+
init_model();
|
|
459674
|
+
init_pi_provider_registry();
|
|
459675
|
+
});
|
|
459676
|
+
|
|
459530
459677
|
// src/websocket/listener/commands/model-toolset.ts
|
|
459531
459678
|
function inferProviderTypeFromRegistryHandle(modelHandle) {
|
|
459532
459679
|
const provider = modelHandle.split("/")[0];
|
|
@@ -459589,22 +459736,34 @@ async function getCurrentModelStatusForRuntime(params) {
|
|
|
459589
459736
|
};
|
|
459590
459737
|
}
|
|
459591
459738
|
function resolveModelForUpdate(payload) {
|
|
459739
|
+
const availableModels = getCachedAvailableModels() ?? [];
|
|
459592
459740
|
if (typeof payload.model_id === "string" && payload.model_id.length > 0) {
|
|
459593
459741
|
const byId = getModelInfo(payload.model_id);
|
|
459594
459742
|
if (byId) {
|
|
459595
459743
|
const explicitHandle = typeof payload.model_handle === "string" && payload.model_handle.length > 0 ? payload.model_handle : null;
|
|
459596
459744
|
const updateArgs = byId.updateArgs && typeof byId.updateArgs === "object" ? { ...byId.updateArgs } : undefined;
|
|
459597
459745
|
const providerType = inferProviderTypeFromRegistryHandle(byId.handle);
|
|
459598
|
-
|
|
459599
|
-
|
|
459746
|
+
const availableModel = findAvailableModelForPreset(byId.handle, availableModels);
|
|
459747
|
+
if ((explicitHandle || availableModel) && updateArgs && (availableModel?.providerType || providerType) && typeof updateArgs.provider_type !== "string") {
|
|
459748
|
+
updateArgs.provider_type = availableModel?.providerType ?? providerType;
|
|
459600
459749
|
}
|
|
459601
459750
|
return {
|
|
459602
459751
|
id: byId.id,
|
|
459603
|
-
handle: explicitHandle ?? byId.handle,
|
|
459752
|
+
handle: explicitHandle ?? availableModel?.handle ?? byId.handle,
|
|
459604
459753
|
label: byId.label,
|
|
459605
459754
|
updateArgs
|
|
459606
459755
|
};
|
|
459607
459756
|
}
|
|
459757
|
+
const nativeModel = availableModels.find((model) => model.handle === payload.model_id);
|
|
459758
|
+
if (nativeModel || payload.model_id.includes("/")) {
|
|
459759
|
+
const explicitHandle = typeof payload.model_handle === "string" && payload.model_handle.length > 0 ? payload.model_handle : null;
|
|
459760
|
+
return {
|
|
459761
|
+
id: payload.model_id,
|
|
459762
|
+
handle: explicitHandle ?? payload.model_id,
|
|
459763
|
+
label: nativeModel?.label ?? payload.model_id,
|
|
459764
|
+
updateArgs: undefined
|
|
459765
|
+
};
|
|
459766
|
+
}
|
|
459608
459767
|
}
|
|
459609
459768
|
if (typeof payload.model_handle === "string" && payload.model_handle.length > 0) {
|
|
459610
459769
|
const exactByHandle = models2.find((m4) => m4.handle === payload.model_handle);
|
|
@@ -459616,10 +459775,11 @@ function resolveModelForUpdate(payload) {
|
|
|
459616
459775
|
updateArgs: exactByHandle.updateArgs && typeof exactByHandle.updateArgs === "object" ? { ...exactByHandle.updateArgs } : undefined
|
|
459617
459776
|
};
|
|
459618
459777
|
}
|
|
459778
|
+
const nativeModel = availableModels.find((model) => model.handle === payload.model_handle);
|
|
459619
459779
|
return {
|
|
459620
459780
|
id: payload.model_handle,
|
|
459621
459781
|
handle: payload.model_handle,
|
|
459622
|
-
label: payload.model_handle,
|
|
459782
|
+
label: nativeModel?.label ?? payload.model_handle,
|
|
459623
459783
|
updateArgs: undefined
|
|
459624
459784
|
};
|
|
459625
459785
|
}
|
|
@@ -459830,25 +459990,13 @@ async function applyToolsetUpdateForRuntime(params) {
|
|
|
459830
459990
|
current_toolset_preference: toolsetPreference
|
|
459831
459991
|
};
|
|
459832
459992
|
}
|
|
459833
|
-
function buildListModelsEntries() {
|
|
459834
|
-
return models2.map((model) => ({
|
|
459835
|
-
id: model.id,
|
|
459836
|
-
handle: model.handle,
|
|
459837
|
-
label: model.label,
|
|
459838
|
-
description: model.description,
|
|
459839
|
-
...typeof model.isDefault === "boolean" ? { isDefault: model.isDefault } : {},
|
|
459840
|
-
...typeof model.isFeatured === "boolean" ? { isFeatured: model.isFeatured } : {},
|
|
459841
|
-
...typeof model.free === "boolean" ? { free: model.free } : {},
|
|
459842
|
-
...model.updateArgs && typeof model.updateArgs === "object" ? { updateArgs: model.updateArgs } : {}
|
|
459843
|
-
}));
|
|
459844
|
-
}
|
|
459845
459993
|
async function buildListModelsResponse(requestId, options3 = {}) {
|
|
459846
|
-
const entries = buildListModelsEntries();
|
|
459847
459994
|
const [handlesResult, providersResult] = await Promise.allSettled([
|
|
459848
459995
|
getAvailableModelHandles(options3.forceRefresh === true ? { forceRefresh: true } : undefined),
|
|
459849
459996
|
listProviders2()
|
|
459850
459997
|
]);
|
|
459851
459998
|
const availableHandles = handlesResult.status === "fulfilled" ? [...handlesResult.value.handles] : null;
|
|
459999
|
+
const entries = buildListModelsEntries(handlesResult.status === "fulfilled" ? handlesResult.value.models : []);
|
|
459852
460000
|
const providers = providersResult.status === "fulfilled" ? providersResult.value : [];
|
|
459853
460001
|
const byokProviderAliases = buildByokProviderAliases(providers);
|
|
459854
460002
|
return {
|
|
@@ -459966,6 +460114,7 @@ var init_model_toolset = __esm(async () => {
|
|
|
459966
460114
|
init_byok_providers();
|
|
459967
460115
|
init_settings_manager();
|
|
459968
460116
|
init_toolset_labels();
|
|
460117
|
+
init_model_catalog2();
|
|
459969
460118
|
await __promiseAll([
|
|
459970
460119
|
init_toolset(),
|
|
459971
460120
|
init_mod_adapter2(),
|
|
@@ -462942,7 +463091,7 @@ __export(exports_memory_scanner, {
|
|
|
462942
463091
|
getFileNodes: () => getFileNodes
|
|
462943
463092
|
});
|
|
462944
463093
|
import { readdirSync as readdirSync15, readFileSync as readFileSync31, statSync as statSync15 } from "node:fs";
|
|
462945
|
-
import { join as
|
|
463094
|
+
import { join as join51, relative as relative12 } from "node:path";
|
|
462946
463095
|
function scanMemoryFilesystem(memoryRoot) {
|
|
462947
463096
|
const nodes = [];
|
|
462948
463097
|
const scanDir = (dir, depth, parentIsLast) => {
|
|
@@ -462954,8 +463103,8 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
462954
463103
|
}
|
|
462955
463104
|
const filtered = entries.filter((name) => !name.startsWith("."));
|
|
462956
463105
|
const sorted = filtered.sort((a2, b3) => {
|
|
462957
|
-
const aPath =
|
|
462958
|
-
const bPath =
|
|
463106
|
+
const aPath = join51(dir, a2);
|
|
463107
|
+
const bPath = join51(dir, b3);
|
|
462959
463108
|
let aIsDir = false;
|
|
462960
463109
|
let bIsDir = false;
|
|
462961
463110
|
try {
|
|
@@ -462975,7 +463124,7 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
462975
463124
|
return a2.localeCompare(b3);
|
|
462976
463125
|
});
|
|
462977
463126
|
sorted.forEach((name, index) => {
|
|
462978
|
-
const fullPath =
|
|
463127
|
+
const fullPath = join51(dir, name);
|
|
462979
463128
|
let isDir = false;
|
|
462980
463129
|
try {
|
|
462981
463130
|
isDir = statSync15(fullPath).isDirectory();
|
|
@@ -463077,10 +463226,10 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
463077
463226
|
const isMemfsEnabledOnServer2 = overrides.isMemfsEnabledOnServer ?? actualIsMemfsEnabledOnServer;
|
|
463078
463227
|
const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memory_scanner(), exports_memory_scanner));
|
|
463079
463228
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
|
|
463080
|
-
const { existsSync:
|
|
463081
|
-
const { join:
|
|
463229
|
+
const { existsSync: existsSync46, statSync: statSync16 } = await import("node:fs");
|
|
463230
|
+
const { join: join52, posix: posix4 } = await import("node:path");
|
|
463082
463231
|
const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
|
|
463083
|
-
let memfsInitialized =
|
|
463232
|
+
let memfsInitialized = existsSync46(join52(memoryRoot, ".git"));
|
|
463084
463233
|
const memfsEnabled = memfsInitialized ? true : await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463085
463234
|
if (!memfsEnabled) {
|
|
463086
463235
|
safeSocketSend(socket, {
|
|
@@ -463098,7 +463247,7 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
463098
463247
|
await ensureLocalMemfsCheckout2(parsed.agent_id, {
|
|
463099
463248
|
pullOnExistingRepo: true
|
|
463100
463249
|
});
|
|
463101
|
-
memfsInitialized =
|
|
463250
|
+
memfsInitialized = existsSync46(join52(memoryRoot, ".git"));
|
|
463102
463251
|
if (!memfsInitialized) {
|
|
463103
463252
|
throw new Error("MemFS is enabled, but the local memory checkout could not be initialized.");
|
|
463104
463253
|
}
|
|
@@ -463398,27 +463547,27 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
463398
463547
|
isMemfsEnabledOnServer: isMemfsEnabledOnServer2
|
|
463399
463548
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
463400
463549
|
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
463401
|
-
const { existsSync:
|
|
463402
|
-
const { isAbsolute: isAbsolute24, join:
|
|
463550
|
+
const { existsSync: existsSync46 } = await import("node:fs");
|
|
463551
|
+
const { isAbsolute: isAbsolute24, join: join52, normalize: normalize5, relative: relative13, sep: sep6 } = await import("node:path");
|
|
463403
463552
|
if (isAbsolute24(parsed.path) || parsed.path.length === 0) {
|
|
463404
463553
|
sendFailure("path must be a non-empty relative path");
|
|
463405
463554
|
return;
|
|
463406
463555
|
}
|
|
463407
463556
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
463408
|
-
const absolutePath = normalize5(
|
|
463557
|
+
const absolutePath = normalize5(join52(memoryRoot, parsed.path));
|
|
463409
463558
|
const rel = relative13(memoryRoot, absolutePath);
|
|
463410
463559
|
if (rel.startsWith("..") || rel === "" || isAbsolute24(rel) || rel.split(sep6).includes("..")) {
|
|
463411
463560
|
sendFailure("path must resolve inside the memory root");
|
|
463412
463561
|
return;
|
|
463413
463562
|
}
|
|
463414
|
-
if (!
|
|
463563
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463415
463564
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463416
463565
|
if (!enabled) {
|
|
463417
463566
|
sendFailure("memfs is not enabled for this agent");
|
|
463418
463567
|
return;
|
|
463419
463568
|
}
|
|
463420
463569
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
463421
|
-
if (!
|
|
463570
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463422
463571
|
sendFailure("failed to initialize local memory checkout");
|
|
463423
463572
|
return;
|
|
463424
463573
|
}
|
|
@@ -463464,27 +463613,27 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
463464
463613
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
463465
463614
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
463466
463615
|
const { writeFile: writeFile15, mkdir: mkdir13 } = await import("node:fs/promises");
|
|
463467
|
-
const { existsSync:
|
|
463468
|
-
const { dirname: dirname27, isAbsolute: isAbsolute24, join:
|
|
463616
|
+
const { existsSync: existsSync46 } = await import("node:fs");
|
|
463617
|
+
const { dirname: dirname27, isAbsolute: isAbsolute24, join: join52, normalize: normalize5, relative: relative13, sep: sep6 } = await import("node:path");
|
|
463469
463618
|
if (isAbsolute24(parsed.path) || parsed.path.length === 0) {
|
|
463470
463619
|
sendFailure("write_memory_file: path must be a non-empty relative path");
|
|
463471
463620
|
return;
|
|
463472
463621
|
}
|
|
463473
463622
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
463474
|
-
const absolutePath = normalize5(
|
|
463623
|
+
const absolutePath = normalize5(join52(memoryRoot, parsed.path));
|
|
463475
463624
|
const rel = relative13(memoryRoot, absolutePath);
|
|
463476
463625
|
if (rel.startsWith("..") || rel === "" || isAbsolute24(rel) || rel.split(sep6).includes("..")) {
|
|
463477
463626
|
sendFailure("write_memory_file: path must resolve inside the memory root");
|
|
463478
463627
|
return;
|
|
463479
463628
|
}
|
|
463480
|
-
if (!
|
|
463629
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463481
463630
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463482
463631
|
if (!enabled) {
|
|
463483
463632
|
sendFailure("write_memory_file: memfs is not enabled for this agent");
|
|
463484
463633
|
return;
|
|
463485
463634
|
}
|
|
463486
463635
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
463487
|
-
if (!
|
|
463636
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463488
463637
|
sendFailure("write_memory_file: failed to initialize local memory checkout");
|
|
463489
463638
|
return;
|
|
463490
463639
|
}
|
|
@@ -463562,34 +463711,34 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
463562
463711
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
463563
463712
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
463564
463713
|
const { unlink: unlink5 } = await import("node:fs/promises");
|
|
463565
|
-
const { existsSync:
|
|
463566
|
-
const { isAbsolute: isAbsolute24, join:
|
|
463714
|
+
const { existsSync: existsSync46 } = await import("node:fs");
|
|
463715
|
+
const { isAbsolute: isAbsolute24, join: join52, normalize: normalize5, relative: relative13, sep: sep6 } = await import("node:path");
|
|
463567
463716
|
if (isAbsolute24(parsed.path) || parsed.path.length === 0) {
|
|
463568
463717
|
sendFailure("delete_memory_file: path must be a non-empty relative path");
|
|
463569
463718
|
return;
|
|
463570
463719
|
}
|
|
463571
463720
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
463572
|
-
const absolutePath = normalize5(
|
|
463721
|
+
const absolutePath = normalize5(join52(memoryRoot, parsed.path));
|
|
463573
463722
|
const rel = relative13(memoryRoot, absolutePath);
|
|
463574
463723
|
if (rel.startsWith("..") || rel === "" || isAbsolute24(rel) || rel.split(sep6).includes("..")) {
|
|
463575
463724
|
sendFailure("delete_memory_file: path must resolve inside the memory root");
|
|
463576
463725
|
return;
|
|
463577
463726
|
}
|
|
463578
|
-
if (!
|
|
463727
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463579
463728
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463580
463729
|
if (!enabled) {
|
|
463581
463730
|
sendFailure("delete_memory_file: memfs is not enabled for this agent");
|
|
463582
463731
|
return;
|
|
463583
463732
|
}
|
|
463584
463733
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
463585
|
-
if (!
|
|
463734
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463586
463735
|
sendFailure("delete_memory_file: failed to initialize local memory checkout");
|
|
463587
463736
|
return;
|
|
463588
463737
|
}
|
|
463589
463738
|
}
|
|
463590
463739
|
const pathspec = rel.split(sep6).join("/");
|
|
463591
463740
|
const removeIfPresent = async () => {
|
|
463592
|
-
if (!
|
|
463741
|
+
if (!existsSync46(absolutePath))
|
|
463593
463742
|
return false;
|
|
463594
463743
|
await unlink5(absolutePath);
|
|
463595
463744
|
return true;
|
|
@@ -463995,19 +464144,19 @@ function emitSkillsUpdated(socket, safeSocketSend) {
|
|
|
463995
464144
|
}
|
|
463996
464145
|
async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
463997
464146
|
const {
|
|
463998
|
-
existsSync:
|
|
464147
|
+
existsSync: existsSync46,
|
|
463999
464148
|
lstatSync: lstatSync3,
|
|
464000
|
-
mkdirSync:
|
|
464149
|
+
mkdirSync: mkdirSync32,
|
|
464001
464150
|
rmdirSync,
|
|
464002
464151
|
symlinkSync: symlinkSync2,
|
|
464003
464152
|
unlinkSync: unlinkSync7
|
|
464004
464153
|
} = await import("node:fs");
|
|
464005
|
-
const { basename: basename25, join:
|
|
464006
|
-
const lettaHome = process.env.LETTA_HOME ||
|
|
464007
|
-
const globalSkillsDir =
|
|
464154
|
+
const { basename: basename25, join: join52 } = await import("node:path");
|
|
464155
|
+
const lettaHome = process.env.LETTA_HOME || join52(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
|
|
464156
|
+
const globalSkillsDir = join52(lettaHome, "skills");
|
|
464008
464157
|
if (parsed.type === "skill_enable") {
|
|
464009
464158
|
try {
|
|
464010
|
-
if (!
|
|
464159
|
+
if (!existsSync46(parsed.skill_path)) {
|
|
464011
464160
|
safeSocketSend(socket, {
|
|
464012
464161
|
type: "skill_enable_response",
|
|
464013
464162
|
request_id: parsed.request_id,
|
|
@@ -464016,8 +464165,8 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
464016
464165
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
464017
464166
|
return true;
|
|
464018
464167
|
}
|
|
464019
|
-
const skillMdPath =
|
|
464020
|
-
if (!
|
|
464168
|
+
const skillMdPath = join52(parsed.skill_path, "SKILL.md");
|
|
464169
|
+
if (!existsSync46(skillMdPath)) {
|
|
464021
464170
|
safeSocketSend(socket, {
|
|
464022
464171
|
type: "skill_enable_response",
|
|
464023
464172
|
request_id: parsed.request_id,
|
|
@@ -464027,9 +464176,9 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
464027
464176
|
return true;
|
|
464028
464177
|
}
|
|
464029
464178
|
const linkName = basename25(parsed.skill_path);
|
|
464030
|
-
const linkPath =
|
|
464031
|
-
|
|
464032
|
-
if (
|
|
464179
|
+
const linkPath = join52(globalSkillsDir, linkName);
|
|
464180
|
+
mkdirSync32(globalSkillsDir, { recursive: true });
|
|
464181
|
+
if (existsSync46(linkPath)) {
|
|
464033
464182
|
const stat14 = lstatSync3(linkPath);
|
|
464034
464183
|
if (stat14.isSymbolicLink()) {
|
|
464035
464184
|
if (process.platform === "win32") {
|
|
@@ -464070,8 +464219,8 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
464070
464219
|
}
|
|
464071
464220
|
if (parsed.type === "skill_disable") {
|
|
464072
464221
|
try {
|
|
464073
|
-
const linkPath =
|
|
464074
|
-
if (!
|
|
464222
|
+
const linkPath = join52(globalSkillsDir, parsed.name);
|
|
464223
|
+
if (!existsSync46(linkPath)) {
|
|
464075
464224
|
safeSocketSend(socket, {
|
|
464076
464225
|
type: "skill_disable_response",
|
|
464077
464226
|
request_id: parsed.request_id,
|
|
@@ -469062,6 +469211,7 @@ function createLegacyTestRuntime() {
|
|
|
469062
469211
|
}
|
|
469063
469212
|
var __listenClientTestUtils;
|
|
469064
469213
|
var init_client7 = __esm(async () => {
|
|
469214
|
+
init_model_catalog2();
|
|
469065
469215
|
init_cwd();
|
|
469066
469216
|
init_runtime6();
|
|
469067
469217
|
await __promiseAll([
|
|
@@ -469210,10 +469360,10 @@ var init_listen_client = __esm(async () => {
|
|
|
469210
469360
|
});
|
|
469211
469361
|
|
|
469212
469362
|
// src/backend/local/transcript-search.ts
|
|
469213
|
-
import { existsSync as
|
|
469214
|
-
import { join as
|
|
469363
|
+
import { existsSync as existsSync49, readdirSync as readdirSync18, readFileSync as readFileSync33, statSync as statSync17 } from "node:fs";
|
|
469364
|
+
import { join as join57 } from "node:path";
|
|
469215
469365
|
function readJsonFile3(path37) {
|
|
469216
|
-
if (!
|
|
469366
|
+
if (!existsSync49(path37))
|
|
469217
469367
|
return;
|
|
469218
469368
|
try {
|
|
469219
469369
|
return JSON.parse(readFileSync33(path37, "utf8"));
|
|
@@ -469222,7 +469372,7 @@ function readJsonFile3(path37) {
|
|
|
469222
469372
|
}
|
|
469223
469373
|
}
|
|
469224
469374
|
function readJsonlFile2(path37) {
|
|
469225
|
-
if (!
|
|
469375
|
+
if (!existsSync49(path37))
|
|
469226
469376
|
return [];
|
|
469227
469377
|
try {
|
|
469228
469378
|
return readFileSync33(path37, "utf8").split(`
|
|
@@ -469432,11 +469582,11 @@ function collectConversationMessages(input) {
|
|
|
469432
469582
|
return [];
|
|
469433
469583
|
if (input.conversationId && conversation.id !== input.conversationId)
|
|
469434
469584
|
return [];
|
|
469435
|
-
const messagesPath =
|
|
469585
|
+
const messagesPath = join57(conversationDir, "messages.jsonl");
|
|
469436
469586
|
const rows = readJsonlFile2(messagesPath);
|
|
469437
469587
|
if (rows.length === 0)
|
|
469438
469588
|
return [];
|
|
469439
|
-
const manifest2 = readJsonFile3(
|
|
469589
|
+
const manifest2 = readJsonFile3(join57(conversationDir, "manifest.json"));
|
|
469440
469590
|
const format5 = transcriptFormat(manifest2, rows);
|
|
469441
469591
|
if (!format5)
|
|
469442
469592
|
return [];
|
|
@@ -469457,11 +469607,11 @@ function collectConversationMessages(input) {
|
|
|
469457
469607
|
});
|
|
469458
469608
|
}
|
|
469459
469609
|
function conversationDirectories(storageDir) {
|
|
469460
|
-
const conversationsDir =
|
|
469461
|
-
if (!
|
|
469610
|
+
const conversationsDir = join57(storageDir, "conversations");
|
|
469611
|
+
if (!existsSync49(conversationsDir))
|
|
469462
469612
|
return [];
|
|
469463
469613
|
try {
|
|
469464
|
-
return readdirSync18(conversationsDir).map((entry) =>
|
|
469614
|
+
return readdirSync18(conversationsDir).map((entry) => join57(conversationsDir, entry)).filter((entryPath) => statSync17(entryPath).isDirectory());
|
|
469465
469615
|
} catch {
|
|
469466
469616
|
return [];
|
|
469467
469617
|
}
|
|
@@ -469485,7 +469635,7 @@ function searchLocalTranscriptMessages(storageDir, body3) {
|
|
|
469485
469635
|
const endDate = typeof body3.end_date === "string" ? body3.end_date : undefined;
|
|
469486
469636
|
const includeHidden = body3.include_hidden === true;
|
|
469487
469637
|
const records = conversationDirectories(storageDir).flatMap((conversationDir) => {
|
|
469488
|
-
const conversation = conversationSearchRecord(readJsonFile3(
|
|
469638
|
+
const conversation = conversationSearchRecord(readJsonFile3(join57(conversationDir, "conversation.json")));
|
|
469489
469639
|
if (!conversation)
|
|
469490
469640
|
return [];
|
|
469491
469641
|
if (conversation.hidden && !includeHidden)
|
|
@@ -471357,14 +471507,14 @@ __export(exports_debug2, {
|
|
|
471357
471507
|
});
|
|
471358
471508
|
import {
|
|
471359
471509
|
appendFileSync as appendFileSync8,
|
|
471360
|
-
existsSync as
|
|
471361
|
-
mkdirSync as
|
|
471510
|
+
existsSync as existsSync53,
|
|
471511
|
+
mkdirSync as mkdirSync37,
|
|
471362
471512
|
readdirSync as readdirSync20,
|
|
471363
471513
|
readFileSync as readFileSync37,
|
|
471364
471514
|
unlinkSync as unlinkSync8
|
|
471365
471515
|
} from "node:fs";
|
|
471366
471516
|
import { homedir as homedir33 } from "node:os";
|
|
471367
|
-
import { join as
|
|
471517
|
+
import { join as join61 } from "node:path";
|
|
471368
471518
|
import { format as format5 } from "node:util";
|
|
471369
471519
|
function isDebugEnabled2() {
|
|
471370
471520
|
const lettaDebug = process.env.LETTA_DEBUG;
|
|
@@ -471395,8 +471545,8 @@ class DebugLogFile2 {
|
|
|
471395
471545
|
const telem = process.env.LETTA_CODE_TELEM;
|
|
471396
471546
|
if (telem === "0" || telem === "false")
|
|
471397
471547
|
return;
|
|
471398
|
-
this.agentDir =
|
|
471399
|
-
this.logPath =
|
|
471548
|
+
this.agentDir = join61(DEBUG_LOG_DIR2, agentId);
|
|
471549
|
+
this.logPath = join61(this.agentDir, `${sessionId}.log`);
|
|
471400
471550
|
this.dirCreated = false;
|
|
471401
471551
|
this.pruneOldSessions();
|
|
471402
471552
|
}
|
|
@@ -471412,7 +471562,7 @@ class DebugLogFile2 {
|
|
|
471412
471562
|
if (!this.logPath)
|
|
471413
471563
|
return;
|
|
471414
471564
|
try {
|
|
471415
|
-
if (!
|
|
471565
|
+
if (!existsSync53(this.logPath))
|
|
471416
471566
|
return;
|
|
471417
471567
|
const content = readFileSync37(this.logPath, "utf8");
|
|
471418
471568
|
const lines = content.trimEnd().split(`
|
|
@@ -471427,8 +471577,8 @@ class DebugLogFile2 {
|
|
|
471427
471577
|
if (this.dirCreated || !this.agentDir)
|
|
471428
471578
|
return;
|
|
471429
471579
|
try {
|
|
471430
|
-
if (!
|
|
471431
|
-
|
|
471580
|
+
if (!existsSync53(this.agentDir)) {
|
|
471581
|
+
mkdirSync37(this.agentDir, { recursive: true });
|
|
471432
471582
|
}
|
|
471433
471583
|
this.dirCreated = true;
|
|
471434
471584
|
} catch {}
|
|
@@ -471437,14 +471587,14 @@ class DebugLogFile2 {
|
|
|
471437
471587
|
if (!this.agentDir)
|
|
471438
471588
|
return;
|
|
471439
471589
|
try {
|
|
471440
|
-
if (!
|
|
471590
|
+
if (!existsSync53(this.agentDir))
|
|
471441
471591
|
return;
|
|
471442
471592
|
const files = readdirSync20(this.agentDir).filter((f4) => f4.endsWith(".log")).sort();
|
|
471443
471593
|
if (files.length >= MAX_SESSION_FILES3) {
|
|
471444
471594
|
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES3 + 1);
|
|
471445
471595
|
for (const file3 of toDelete) {
|
|
471446
471596
|
try {
|
|
471447
|
-
unlinkSync8(
|
|
471597
|
+
unlinkSync8(join61(this.agentDir, file3));
|
|
471448
471598
|
} catch {}
|
|
471449
471599
|
}
|
|
471450
471600
|
}
|
|
@@ -471469,7 +471619,7 @@ function debugWarn2(prefix, message, ...args) {
|
|
|
471469
471619
|
}
|
|
471470
471620
|
var DEBUG_LOG_DIR2, MAX_SESSION_FILES3 = 5, DEFAULT_TAIL_LINES2 = 50, debugLogFile2;
|
|
471471
471621
|
var init_debug2 = __esm(() => {
|
|
471472
|
-
DEBUG_LOG_DIR2 =
|
|
471622
|
+
DEBUG_LOG_DIR2 = join61(homedir33(), ".letta", "logs", "debug");
|
|
471473
471623
|
debugLogFile2 = new DebugLogFile2;
|
|
471474
471624
|
});
|
|
471475
471625
|
|
|
@@ -471503,16 +471653,16 @@ __export(exports_skills3, {
|
|
|
471503
471653
|
PROJECT_SKILLS_DIR: () => PROJECT_SKILLS_DIR2,
|
|
471504
471654
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
471505
471655
|
});
|
|
471506
|
-
import { existsSync as
|
|
471656
|
+
import { existsSync as existsSync54 } from "node:fs";
|
|
471507
471657
|
import { readdir as readdir15, readFile as readFile22, realpath as realpath6, stat as stat15 } from "node:fs/promises";
|
|
471508
|
-
import { dirname as dirname31, join as
|
|
471658
|
+
import { dirname as dirname31, join as join62 } from "node:path";
|
|
471509
471659
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
471510
471660
|
function getBundledSkillsPath2() {
|
|
471511
471661
|
const thisDir = dirname31(fileURLToPath8(import.meta.url));
|
|
471512
471662
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
471513
|
-
return
|
|
471663
|
+
return join62(thisDir, "../skills/builtin");
|
|
471514
471664
|
}
|
|
471515
|
-
return
|
|
471665
|
+
return join62(thisDir, "skills");
|
|
471516
471666
|
}
|
|
471517
471667
|
function compareSkills2(a2, b3) {
|
|
471518
471668
|
return a2.id.localeCompare(b3.id) || a2.source.localeCompare(b3.source) || a2.path.localeCompare(b3.path);
|
|
@@ -471559,7 +471709,7 @@ function isSkillAvailableForAgent2(skill2, agentId) {
|
|
|
471559
471709
|
return true;
|
|
471560
471710
|
}
|
|
471561
471711
|
function getAgentSkillsDir2(agentId) {
|
|
471562
|
-
return
|
|
471712
|
+
return join62(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
471563
471713
|
}
|
|
471564
471714
|
async function getBundledSkills2() {
|
|
471565
471715
|
const bundledPath = getBundledSkillsPath2();
|
|
@@ -471568,7 +471718,7 @@ async function getBundledSkills2() {
|
|
|
471568
471718
|
}
|
|
471569
471719
|
async function discoverSkillsFromDir2(skillsPath, source2) {
|
|
471570
471720
|
const errors7 = [];
|
|
471571
|
-
if (!
|
|
471721
|
+
if (!existsSync54(skillsPath)) {
|
|
471572
471722
|
return { skills: [], errors: [] };
|
|
471573
471723
|
}
|
|
471574
471724
|
const skills = [];
|
|
@@ -471582,7 +471732,7 @@ async function discoverSkillsFromDir2(skillsPath, source2) {
|
|
|
471582
471732
|
}
|
|
471583
471733
|
return { skills, errors: errors7 };
|
|
471584
471734
|
}
|
|
471585
|
-
async function discoverSkills2(projectSkillsPath =
|
|
471735
|
+
async function discoverSkills2(projectSkillsPath = join62(process.cwd(), SKILLS_DIR2), agentId, options3) {
|
|
471586
471736
|
const allErrors = [];
|
|
471587
471737
|
const skillsById = new Map;
|
|
471588
471738
|
const sourceSet = new Set(options3?.sources ?? ALL_SKILL_SOURCES);
|
|
@@ -471637,7 +471787,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors7, source2,
|
|
|
471637
471787
|
try {
|
|
471638
471788
|
const entries = await readdir15(currentPath, { withFileTypes: true });
|
|
471639
471789
|
for (const entry of entries) {
|
|
471640
|
-
const fullPath =
|
|
471790
|
+
const fullPath = join62(currentPath, entry.name);
|
|
471641
471791
|
try {
|
|
471642
471792
|
let isDirectory = entry.isDirectory();
|
|
471643
471793
|
let isFile = entry.isFile();
|
|
@@ -471728,8 +471878,8 @@ var LOCAL_AGENT_EXCLUDED_BUNDLED_SKILLS2, PROJECT_SKILLS_DIR2, SKILLS_DIR2 = ".s
|
|
|
471728
471878
|
var init_skills4 = __esm(() => {
|
|
471729
471879
|
init_skill_sources();
|
|
471730
471880
|
LOCAL_AGENT_EXCLUDED_BUNDLED_SKILLS2 = new Set(["image-generation"]);
|
|
471731
|
-
PROJECT_SKILLS_DIR2 =
|
|
471732
|
-
GLOBAL_SKILLS_DIR2 =
|
|
471881
|
+
PROJECT_SKILLS_DIR2 = join62(".agents", "skills");
|
|
471882
|
+
GLOBAL_SKILLS_DIR2 = join62(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
|
|
471733
471883
|
});
|
|
471734
471884
|
|
|
471735
471885
|
// src/utils/fs.ts
|
|
@@ -471743,10 +471893,10 @@ __export(exports_fs, {
|
|
|
471743
471893
|
exists: () => exists2
|
|
471744
471894
|
});
|
|
471745
471895
|
import {
|
|
471746
|
-
existsSync as
|
|
471896
|
+
existsSync as existsSync55,
|
|
471747
471897
|
readFileSync as fsReadFileSync2,
|
|
471748
471898
|
writeFileSync as fsWriteFileSync2,
|
|
471749
|
-
mkdirSync as
|
|
471899
|
+
mkdirSync as mkdirSync38
|
|
471750
471900
|
} from "node:fs";
|
|
471751
471901
|
import { dirname as dirname32 } from "node:path";
|
|
471752
471902
|
async function readFile23(path39) {
|
|
@@ -471754,16 +471904,16 @@ async function readFile23(path39) {
|
|
|
471754
471904
|
}
|
|
471755
471905
|
async function writeFile17(path39, content) {
|
|
471756
471906
|
const dir = dirname32(path39);
|
|
471757
|
-
if (!
|
|
471758
|
-
|
|
471907
|
+
if (!existsSync55(dir)) {
|
|
471908
|
+
mkdirSync38(dir, { recursive: true });
|
|
471759
471909
|
}
|
|
471760
471910
|
fsWriteFileSync2(path39, content, { encoding: "utf-8", flush: true });
|
|
471761
471911
|
}
|
|
471762
471912
|
function exists2(path39) {
|
|
471763
|
-
return
|
|
471913
|
+
return existsSync55(path39);
|
|
471764
471914
|
}
|
|
471765
471915
|
async function mkdir15(path39, options3) {
|
|
471766
|
-
|
|
471916
|
+
mkdirSync38(path39, options3);
|
|
471767
471917
|
}
|
|
471768
471918
|
async function readJsonFile4(path39) {
|
|
471769
471919
|
const text2 = await readFile23(path39);
|
|
@@ -471973,7 +472123,7 @@ import {
|
|
|
471973
472123
|
} from "node:child_process";
|
|
471974
472124
|
import { accessSync as accessSync2, constants as constants4, realpathSync as realpathSync6 } from "node:fs";
|
|
471975
472125
|
import { readdir as readdir16, rm as rm6 } from "node:fs/promises";
|
|
471976
|
-
import { dirname as dirname33, join as
|
|
472126
|
+
import { dirname as dirname33, join as join63 } from "node:path";
|
|
471977
472127
|
import { promisify as promisify15 } from "node:util";
|
|
471978
472128
|
function debugLog4(...args) {
|
|
471979
472129
|
if (DEBUG2) {
|
|
@@ -472048,7 +472198,7 @@ function getResolvedEntrypoint2() {
|
|
|
472048
472198
|
}
|
|
472049
472199
|
}
|
|
472050
472200
|
function findInstalledPackagePath2(resolvedPath) {
|
|
472051
|
-
const marker = `${
|
|
472201
|
+
const marker = `${join63("node_modules", "@letta-ai", "letta-code")}`;
|
|
472052
472202
|
const index = resolvedPath.lastIndexOf(marker);
|
|
472053
472203
|
if (index === -1) {
|
|
472054
472204
|
return null;
|
|
@@ -472197,12 +472347,12 @@ async function getNpmGlobalPath2() {
|
|
|
472197
472347
|
}
|
|
472198
472348
|
}
|
|
472199
472349
|
async function cleanupOrphanedDirs2(globalPath) {
|
|
472200
|
-
const lettaAiDir =
|
|
472350
|
+
const lettaAiDir = join63(globalPath, "lib/node_modules/@letta-ai");
|
|
472201
472351
|
try {
|
|
472202
472352
|
const entries = await readdir16(lettaAiDir);
|
|
472203
472353
|
for (const entry of entries) {
|
|
472204
472354
|
if (entry.startsWith(".letta-code-")) {
|
|
472205
|
-
const orphanPath =
|
|
472355
|
+
const orphanPath = join63(lettaAiDir, entry);
|
|
472206
472356
|
debugLog4("Cleaning orphaned temp directory:", orphanPath);
|
|
472207
472357
|
await rm6(orphanPath, { recursive: true, force: true });
|
|
472208
472358
|
}
|
|
@@ -472732,18 +472882,18 @@ var exports_bootstrap_tools = {};
|
|
|
472732
472882
|
__export(exports_bootstrap_tools, {
|
|
472733
472883
|
bootstrapBaseToolsIfNeeded: () => bootstrapBaseToolsIfNeeded
|
|
472734
472884
|
});
|
|
472735
|
-
import { existsSync as
|
|
472885
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync40, writeFileSync as writeFileSync29 } from "node:fs";
|
|
472736
472886
|
import { homedir as homedir35 } from "node:os";
|
|
472737
|
-
import { join as
|
|
472887
|
+
import { join as join65 } from "node:path";
|
|
472738
472888
|
async function bootstrapBaseToolsIfNeeded() {
|
|
472739
|
-
if (
|
|
472889
|
+
if (existsSync57(MARKER_PATH))
|
|
472740
472890
|
return;
|
|
472741
472891
|
debugLog("bootstrap", "No marker found, bootstrapping base tools...");
|
|
472742
472892
|
try {
|
|
472743
472893
|
const success2 = await addBaseToolsToServer();
|
|
472744
472894
|
if (success2) {
|
|
472745
|
-
|
|
472746
|
-
|
|
472895
|
+
mkdirSync40(join65(homedir35(), ".letta"), { recursive: true });
|
|
472896
|
+
writeFileSync29(MARKER_PATH, new Date().toISOString(), "utf-8");
|
|
472747
472897
|
}
|
|
472748
472898
|
} catch (err) {
|
|
472749
472899
|
debugWarn("bootstrap", `Failed to bootstrap base tools: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -472753,7 +472903,7 @@ var MARKER_PATH;
|
|
|
472753
472903
|
var init_bootstrap_tools = __esm(() => {
|
|
472754
472904
|
init_debug();
|
|
472755
472905
|
init_create6();
|
|
472756
|
-
MARKER_PATH =
|
|
472906
|
+
MARKER_PATH = join65(homedir35(), ".letta", ".bootstrapped");
|
|
472757
472907
|
});
|
|
472758
472908
|
|
|
472759
472909
|
// src/tools/filter.ts
|
|
@@ -473205,7 +473355,7 @@ function validateRegistryHandleOrThrow2(handle2) {
|
|
|
473205
473355
|
}
|
|
473206
473356
|
|
|
473207
473357
|
// src/headless-mod-adapter.ts
|
|
473208
|
-
import { join as
|
|
473358
|
+
import { join as join66 } from "node:path";
|
|
473209
473359
|
function isHeadlessMemfsEnabled(agentId) {
|
|
473210
473360
|
try {
|
|
473211
473361
|
return settingsManager.isMemfsEnabled(agentId);
|
|
@@ -473276,7 +473426,7 @@ function createHeadlessModContext(options3) {
|
|
|
473276
473426
|
};
|
|
473277
473427
|
}
|
|
473278
473428
|
function createHeadlessModAdapter(options3) {
|
|
473279
|
-
const agentModsDirectory = isHeadlessMemfsEnabled(options3.agent.id) ?
|
|
473429
|
+
const agentModsDirectory = isHeadlessMemfsEnabled(options3.agent.id) ? join66(getScopedMemoryFilesystemRoot(options3.agent.id), "mods") : undefined;
|
|
473280
473430
|
return createModAdapter({
|
|
473281
473431
|
...agentModsDirectory ? { agentModsDirectory } : {},
|
|
473282
473432
|
...options3.cacheDirectory ? { cacheDirectory: options3.cacheDirectory } : {},
|
|
@@ -473407,8 +473557,8 @@ var init_headless_tool_events = __esm(async () => {
|
|
|
473407
473557
|
});
|
|
473408
473558
|
|
|
473409
473559
|
// src/skills/builtin/creating-skills/scripts/validate-skill.ts
|
|
473410
|
-
import { existsSync as
|
|
473411
|
-
import { basename as basename27, join as
|
|
473560
|
+
import { existsSync as existsSync58, readFileSync as readFileSync38 } from "node:fs";
|
|
473561
|
+
import { basename as basename27, join as join67, resolve as resolve35 } from "node:path";
|
|
473412
473562
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
473413
473563
|
function parseQuotedScalar(value) {
|
|
473414
473564
|
if (value.startsWith('"')) {
|
|
@@ -473505,8 +473655,8 @@ function parseFrontmatter2(source2) {
|
|
|
473505
473655
|
return parseFrontmatterFallback(source2);
|
|
473506
473656
|
}
|
|
473507
473657
|
function validateSkill(skillPath) {
|
|
473508
|
-
const skillMdPath =
|
|
473509
|
-
if (!
|
|
473658
|
+
const skillMdPath = join67(skillPath, "SKILL.md");
|
|
473659
|
+
if (!existsSync58(skillMdPath)) {
|
|
473510
473660
|
return { valid: false, message: "SKILL.md not found" };
|
|
473511
473661
|
}
|
|
473512
473662
|
const content = readFileSync38(skillMdPath, "utf-8");
|
|
@@ -473854,7 +474004,7 @@ function parseRegistryHandle(handle2) {
|
|
|
473854
474004
|
}
|
|
473855
474005
|
async function importAgentFromRegistry(options3) {
|
|
473856
474006
|
const { tmpdir: tmpdir10 } = await import("node:os");
|
|
473857
|
-
const { join:
|
|
474007
|
+
const { join: join68 } = await import("node:path");
|
|
473858
474008
|
const { writeFile: writeFile19, unlink: unlink5 } = await import("node:fs/promises");
|
|
473859
474009
|
const { author, name } = parseRegistryHandle(options3.handle);
|
|
473860
474010
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -473866,7 +474016,7 @@ async function importAgentFromRegistry(options3) {
|
|
|
473866
474016
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
473867
474017
|
}
|
|
473868
474018
|
const afContent = await response.text();
|
|
473869
|
-
const tempPath =
|
|
474019
|
+
const tempPath = join68(tmpdir10(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
473870
474020
|
await writeFile19(tempPath, afContent, "utf-8");
|
|
473871
474021
|
try {
|
|
473872
474022
|
const result = await importAgentFromFile({
|
|
@@ -478681,10 +478831,10 @@ var init_queued_message_parts = __esm(() => {
|
|
|
478681
478831
|
|
|
478682
478832
|
// src/cli/helpers/reflection-arena-hf-upload.ts
|
|
478683
478833
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
478684
|
-
import { existsSync as
|
|
478834
|
+
import { existsSync as existsSync60 } from "node:fs";
|
|
478685
478835
|
import { appendFile as appendFile2, chmod as chmod2, mkdir as mkdir17, writeFile as writeFile19 } from "node:fs/promises";
|
|
478686
478836
|
import { homedir as homedir38 } from "node:os";
|
|
478687
|
-
import { join as
|
|
478837
|
+
import { join as join69 } from "node:path";
|
|
478688
478838
|
import { promisify as promisify16 } from "node:util";
|
|
478689
478839
|
function buildGitEnv(token2, askpassPath) {
|
|
478690
478840
|
return {
|
|
@@ -478720,7 +478870,7 @@ async function runGit6(cwd2, args, env5) {
|
|
|
478720
478870
|
}
|
|
478721
478871
|
}
|
|
478722
478872
|
async function writeGitAskpass(repoRoot) {
|
|
478723
|
-
const askpassPath =
|
|
478873
|
+
const askpassPath = join69(repoRoot, "hf-askpass.sh");
|
|
478724
478874
|
await writeFile19(askpassPath, [
|
|
478725
478875
|
"#!/bin/sh",
|
|
478726
478876
|
'case "$1" in',
|
|
@@ -478735,7 +478885,7 @@ async function writeGitAskpass(repoRoot) {
|
|
|
478735
478885
|
}
|
|
478736
478886
|
async function prepareHfRepo(env5) {
|
|
478737
478887
|
await mkdir17(HF_CACHE_ROOT, { recursive: true });
|
|
478738
|
-
if (!
|
|
478888
|
+
if (!existsSync60(join69(HF_REPO_DIR, ".git"))) {
|
|
478739
478889
|
await runGit6(HF_CACHE_ROOT, ["clone", "--depth", "1", HF_REPO_URL, HF_REPO_DIR], env5);
|
|
478740
478890
|
return HF_REPO_DIR;
|
|
478741
478891
|
}
|
|
@@ -478770,8 +478920,8 @@ async function maybeUploadReflectionArenaChoiceToHf(row) {
|
|
|
478770
478920
|
const env5 = buildGitEnv(token2, askpassPath);
|
|
478771
478921
|
try {
|
|
478772
478922
|
const repoDir = await prepareHfRepo(env5);
|
|
478773
|
-
await mkdir17(
|
|
478774
|
-
await appendFile2(
|
|
478923
|
+
await mkdir17(join69(repoDir, "data"), { recursive: true });
|
|
478924
|
+
await appendFile2(join69(repoDir, HF_DATASET_PATH), `${JSON.stringify(row)}
|
|
478775
478925
|
`, {
|
|
478776
478926
|
encoding: "utf-8"
|
|
478777
478927
|
});
|
|
@@ -478799,8 +478949,8 @@ var init_reflection_arena_hf_upload = __esm(() => {
|
|
|
478799
478949
|
init_version();
|
|
478800
478950
|
execFile18 = promisify16(execFileCb5);
|
|
478801
478951
|
HF_REPO_URL = `https://huggingface.co/datasets/${HF_REPO_ID}`;
|
|
478802
|
-
HF_CACHE_ROOT =
|
|
478803
|
-
HF_REPO_DIR =
|
|
478952
|
+
HF_CACHE_ROOT = join69(homedir38(), ".letta", "reflection-arena", "hf-upload");
|
|
478953
|
+
HF_REPO_DIR = join69(HF_CACHE_ROOT, "repo");
|
|
478804
478954
|
});
|
|
478805
478955
|
|
|
478806
478956
|
// src/cli/helpers/reflection-arena.ts
|
|
@@ -478808,7 +478958,7 @@ import { execFile as execFileCb6 } from "node:child_process";
|
|
|
478808
478958
|
import { randomInt, randomUUID as randomUUID30 } from "node:crypto";
|
|
478809
478959
|
import { appendFile as appendFile3, mkdir as mkdir18, readFile as readFile25, writeFile as writeFile20 } from "node:fs/promises";
|
|
478810
478960
|
import { homedir as homedir39 } from "node:os";
|
|
478811
|
-
import { join as
|
|
478961
|
+
import { join as join70 } from "node:path";
|
|
478812
478962
|
import { promisify as promisify17 } from "node:util";
|
|
478813
478963
|
function sampleReflectionArenaComparisonModel(excludedModels = []) {
|
|
478814
478964
|
const excluded = new Set(excludedModels);
|
|
@@ -478838,16 +478988,16 @@ async function getGitHead(cwd2) {
|
|
|
478838
478988
|
}
|
|
478839
478989
|
}
|
|
478840
478990
|
function getReflectionArenaRoot() {
|
|
478841
|
-
return
|
|
478991
|
+
return join70(homedir39(), ".letta", "reflection-arena");
|
|
478842
478992
|
}
|
|
478843
478993
|
function getReflectionArenaRunsDir() {
|
|
478844
|
-
return
|
|
478994
|
+
return join70(getReflectionArenaRoot(), "runs");
|
|
478845
478995
|
}
|
|
478846
478996
|
function getReflectionArenaChoiceLogPath() {
|
|
478847
|
-
return
|
|
478997
|
+
return join70(getReflectionArenaRoot(), "choices.jsonl");
|
|
478848
478998
|
}
|
|
478849
478999
|
function getReflectionArenaRunPath(runId) {
|
|
478850
|
-
return
|
|
479000
|
+
return join70(getReflectionArenaRunsDir(), `${runId}.json`);
|
|
478851
479001
|
}
|
|
478852
479002
|
async function saveReflectionArenaRun(run) {
|
|
478853
479003
|
await mkdir18(getReflectionArenaRunsDir(), { recursive: true });
|
|
@@ -479944,13 +480094,13 @@ __export(exports_terminal_keybinding_installer, {
|
|
|
479944
480094
|
});
|
|
479945
480095
|
import {
|
|
479946
480096
|
copyFileSync as copyFileSync5,
|
|
479947
|
-
existsSync as
|
|
479948
|
-
mkdirSync as
|
|
480097
|
+
existsSync as existsSync61,
|
|
480098
|
+
mkdirSync as mkdirSync42,
|
|
479949
480099
|
readFileSync as readFileSync40,
|
|
479950
|
-
writeFileSync as
|
|
480100
|
+
writeFileSync as writeFileSync31
|
|
479951
480101
|
} from "node:fs";
|
|
479952
480102
|
import { homedir as homedir40, platform as platform9 } from "node:os";
|
|
479953
|
-
import { dirname as dirname35, join as
|
|
480103
|
+
import { dirname as dirname35, join as join71 } from "node:path";
|
|
479954
480104
|
function detectTerminalType() {
|
|
479955
480105
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
479956
480106
|
return "cursor";
|
|
@@ -479982,16 +480132,16 @@ function getKeybindingsPath(terminal) {
|
|
|
479982
480132
|
}[terminal];
|
|
479983
480133
|
const os9 = platform9();
|
|
479984
480134
|
if (os9 === "darwin") {
|
|
479985
|
-
return
|
|
480135
|
+
return join71(homedir40(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
479986
480136
|
}
|
|
479987
480137
|
if (os9 === "win32") {
|
|
479988
480138
|
const appData = process.env.APPDATA;
|
|
479989
480139
|
if (!appData)
|
|
479990
480140
|
return null;
|
|
479991
|
-
return
|
|
480141
|
+
return join71(appData, appName, "User", "keybindings.json");
|
|
479992
480142
|
}
|
|
479993
480143
|
if (os9 === "linux") {
|
|
479994
|
-
return
|
|
480144
|
+
return join71(homedir40(), ".config", appName, "User", "keybindings.json");
|
|
479995
480145
|
}
|
|
479996
480146
|
return null;
|
|
479997
480147
|
}
|
|
@@ -480013,7 +480163,7 @@ function parseKeybindings(content) {
|
|
|
480013
480163
|
}
|
|
480014
480164
|
}
|
|
480015
480165
|
function keybindingExists(keybindingsPath) {
|
|
480016
|
-
if (!
|
|
480166
|
+
if (!existsSync61(keybindingsPath))
|
|
480017
480167
|
return false;
|
|
480018
480168
|
try {
|
|
480019
480169
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -480026,7 +480176,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
480026
480176
|
}
|
|
480027
480177
|
}
|
|
480028
480178
|
function createBackup(keybindingsPath) {
|
|
480029
|
-
if (!
|
|
480179
|
+
if (!existsSync61(keybindingsPath))
|
|
480030
480180
|
return null;
|
|
480031
480181
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
480032
480182
|
try {
|
|
@@ -480042,12 +480192,12 @@ function installKeybinding(keybindingsPath) {
|
|
|
480042
480192
|
return { success: true, alreadyExists: true };
|
|
480043
480193
|
}
|
|
480044
480194
|
const parentDir = dirname35(keybindingsPath);
|
|
480045
|
-
if (!
|
|
480046
|
-
|
|
480195
|
+
if (!existsSync61(parentDir)) {
|
|
480196
|
+
mkdirSync42(parentDir, { recursive: true });
|
|
480047
480197
|
}
|
|
480048
480198
|
let keybindings = [];
|
|
480049
480199
|
let backupPath = null;
|
|
480050
|
-
if (
|
|
480200
|
+
if (existsSync61(keybindingsPath)) {
|
|
480051
480201
|
backupPath = createBackup(keybindingsPath);
|
|
480052
480202
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
480053
480203
|
const parsed = parseKeybindings(content);
|
|
@@ -480062,7 +480212,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
480062
480212
|
keybindings.push(SHIFT_ENTER_KEYBINDING);
|
|
480063
480213
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
480064
480214
|
`;
|
|
480065
|
-
|
|
480215
|
+
writeFileSync31(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
480066
480216
|
return {
|
|
480067
480217
|
success: true,
|
|
480068
480218
|
backupPath: backupPath ?? undefined
|
|
@@ -480077,7 +480227,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
480077
480227
|
}
|
|
480078
480228
|
function removeKeybinding(keybindingsPath) {
|
|
480079
480229
|
try {
|
|
480080
|
-
if (!
|
|
480230
|
+
if (!existsSync61(keybindingsPath)) {
|
|
480081
480231
|
return { success: true };
|
|
480082
480232
|
}
|
|
480083
480233
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -480091,7 +480241,7 @@ function removeKeybinding(keybindingsPath) {
|
|
|
480091
480241
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
480092
480242
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
480093
480243
|
`;
|
|
480094
|
-
|
|
480244
|
+
writeFileSync31(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
480095
480245
|
return { success: true };
|
|
480096
480246
|
} catch (error54) {
|
|
480097
480247
|
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
@@ -480144,14 +480294,14 @@ function getWezTermConfigPath() {
|
|
|
480144
480294
|
}
|
|
480145
480295
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
480146
480296
|
if (xdgConfig) {
|
|
480147
|
-
const xdgPath =
|
|
480148
|
-
if (
|
|
480297
|
+
const xdgPath = join71(xdgConfig, "wezterm", "wezterm.lua");
|
|
480298
|
+
if (existsSync61(xdgPath))
|
|
480149
480299
|
return xdgPath;
|
|
480150
480300
|
}
|
|
480151
|
-
const configPath =
|
|
480152
|
-
if (
|
|
480301
|
+
const configPath = join71(homedir40(), ".config", "wezterm", "wezterm.lua");
|
|
480302
|
+
if (existsSync61(configPath))
|
|
480153
480303
|
return configPath;
|
|
480154
|
-
return
|
|
480304
|
+
return join71(homedir40(), ".wezterm.lua");
|
|
480155
480305
|
}
|
|
480156
480306
|
function stripLuaCommentsFromLine(line, blockCommentEnd) {
|
|
480157
480307
|
let code2 = "";
|
|
@@ -480254,7 +480404,7 @@ ${WEZTERM_DELETE_FIX}
|
|
|
480254
480404
|
`;
|
|
480255
480405
|
}
|
|
480256
480406
|
function wezTermDeleteFixExists(configPath) {
|
|
480257
|
-
if (!
|
|
480407
|
+
if (!existsSync61(configPath))
|
|
480258
480408
|
return false;
|
|
480259
480409
|
try {
|
|
480260
480410
|
const content = readFileSync40(configPath, { encoding: "utf-8" });
|
|
@@ -480271,17 +480421,17 @@ function installWezTermDeleteFix() {
|
|
|
480271
480421
|
}
|
|
480272
480422
|
let content = "";
|
|
480273
480423
|
let backupPath = null;
|
|
480274
|
-
if (
|
|
480424
|
+
if (existsSync61(configPath)) {
|
|
480275
480425
|
backupPath = `${configPath}.letta-backup`;
|
|
480276
480426
|
copyFileSync5(configPath, backupPath);
|
|
480277
480427
|
content = readFileSync40(configPath, { encoding: "utf-8" });
|
|
480278
480428
|
}
|
|
480279
480429
|
content = injectWezTermDeleteFix(content);
|
|
480280
480430
|
const parentDir = dirname35(configPath);
|
|
480281
|
-
if (!
|
|
480282
|
-
|
|
480431
|
+
if (!existsSync61(parentDir)) {
|
|
480432
|
+
mkdirSync42(parentDir, { recursive: true });
|
|
480283
480433
|
}
|
|
480284
|
-
|
|
480434
|
+
writeFileSync31(configPath, content, { encoding: "utf-8" });
|
|
480285
480435
|
return {
|
|
480286
480436
|
success: true,
|
|
480287
480437
|
backupPath: backupPath ?? undefined
|
|
@@ -480330,9 +480480,9 @@ __export(exports_settings2, {
|
|
|
480330
480480
|
getSetting: () => getSetting
|
|
480331
480481
|
});
|
|
480332
480482
|
import { homedir as homedir41 } from "node:os";
|
|
480333
|
-
import { join as
|
|
480483
|
+
import { join as join72 } from "node:path";
|
|
480334
480484
|
function getSettingsPath() {
|
|
480335
|
-
return
|
|
480485
|
+
return join72(homedir41(), ".letta", "settings.json");
|
|
480336
480486
|
}
|
|
480337
480487
|
async function loadSettings() {
|
|
480338
480488
|
const settingsPath = getSettingsPath();
|
|
@@ -480369,7 +480519,7 @@ async function getSetting(key2) {
|
|
|
480369
480519
|
return settings3[key2];
|
|
480370
480520
|
}
|
|
480371
480521
|
function getProjectSettingsPath() {
|
|
480372
|
-
return
|
|
480522
|
+
return join72(process.cwd(), ".letta", "settings.local.json");
|
|
480373
480523
|
}
|
|
480374
480524
|
async function loadProjectSettings() {
|
|
480375
480525
|
const settingsPath = getProjectSettingsPath();
|
|
@@ -480387,7 +480537,7 @@ async function loadProjectSettings() {
|
|
|
480387
480537
|
}
|
|
480388
480538
|
async function saveProjectSettings(settings3) {
|
|
480389
480539
|
const settingsPath = getProjectSettingsPath();
|
|
480390
|
-
const dirPath =
|
|
480540
|
+
const dirPath = join72(process.cwd(), ".letta");
|
|
480391
480541
|
try {
|
|
480392
480542
|
if (!exists(dirPath)) {
|
|
480393
480543
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -482274,9 +482424,9 @@ function getHeaderText(fileEdit) {
|
|
|
482274
482424
|
const relPath = relative16(cwd2, fileEdit.filePath);
|
|
482275
482425
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
482276
482426
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
482277
|
-
const { existsSync:
|
|
482427
|
+
const { existsSync: existsSync62 } = __require("node:fs");
|
|
482278
482428
|
try {
|
|
482279
|
-
if (
|
|
482429
|
+
if (existsSync62(fileEdit.filePath)) {
|
|
482280
482430
|
return `Overwrite ${displayPath}?`;
|
|
482281
482431
|
}
|
|
482282
482432
|
} catch {}
|
|
@@ -489784,15 +489934,15 @@ import { spawn as spawn12, spawnSync as spawnSync4 } from "node:child_process";
|
|
|
489784
489934
|
import {
|
|
489785
489935
|
chmodSync as chmodSync7,
|
|
489786
489936
|
createWriteStream as createWriteStream4,
|
|
489787
|
-
existsSync as
|
|
489788
|
-
mkdirSync as
|
|
489937
|
+
existsSync as existsSync62,
|
|
489938
|
+
mkdirSync as mkdirSync43,
|
|
489789
489939
|
readdirSync as readdirSync22,
|
|
489790
489940
|
renameSync as renameSync6,
|
|
489791
489941
|
rmSync as rmSync14,
|
|
489792
489942
|
statSync as statSync20
|
|
489793
489943
|
} from "node:fs";
|
|
489794
489944
|
import { arch as arch4, homedir as homedir43, platform as platform10 } from "node:os";
|
|
489795
|
-
import { basename as basename29, join as
|
|
489945
|
+
import { basename as basename29, join as join73 } from "node:path";
|
|
489796
489946
|
function toDisplayPath(value) {
|
|
489797
489947
|
return value.replace(/\\/g, "/");
|
|
489798
489948
|
}
|
|
@@ -490034,7 +490184,7 @@ class FileAutocompleteProvider {
|
|
|
490034
490184
|
}
|
|
490035
490185
|
expandHomePath(path42) {
|
|
490036
490186
|
if (path42.startsWith("~/")) {
|
|
490037
|
-
const expandedPath =
|
|
490187
|
+
const expandedPath = join73(homedir43(), path42.slice(2));
|
|
490038
490188
|
return path42.endsWith("/") && !expandedPath.endsWith("/") ? `${expandedPath}/` : expandedPath;
|
|
490039
490189
|
} else if (path42 === "~") {
|
|
490040
490190
|
return homedir43();
|
|
@@ -490055,7 +490205,7 @@ class FileAutocompleteProvider {
|
|
|
490055
490205
|
} else if (displayBase.startsWith("/")) {
|
|
490056
490206
|
baseDir = displayBase;
|
|
490057
490207
|
} else {
|
|
490058
|
-
baseDir =
|
|
490208
|
+
baseDir = join73(this.basePath, displayBase);
|
|
490059
490209
|
}
|
|
490060
490210
|
try {
|
|
490061
490211
|
if (!statSync20(baseDir).isDirectory()) {
|
|
@@ -490134,9 +490284,9 @@ class FileAutocompleteProvider {
|
|
|
490134
490284
|
var PATH_DELIMITERS2, FD_TOOLS_DIR2, FD_BINARY_NAME2, FD_LOCAL_PATH2;
|
|
490135
490285
|
var init_file_autocomplete = __esm(() => {
|
|
490136
490286
|
PATH_DELIMITERS2 = new Set([" ", "\t", '"', "'", "="]);
|
|
490137
|
-
FD_TOOLS_DIR2 =
|
|
490287
|
+
FD_TOOLS_DIR2 = join73(homedir43(), ".letta", "bin");
|
|
490138
490288
|
FD_BINARY_NAME2 = platform10() === "win32" ? "fd.exe" : "fd";
|
|
490139
|
-
FD_LOCAL_PATH2 =
|
|
490289
|
+
FD_LOCAL_PATH2 = join73(FD_TOOLS_DIR2, FD_BINARY_NAME2);
|
|
490140
490290
|
});
|
|
490141
490291
|
|
|
490142
490292
|
// src/cli/hooks/use-autocomplete-navigation.ts
|
|
@@ -492955,15 +493105,15 @@ var init_agents7 = __esm(() => {
|
|
|
492955
493105
|
// src/cli/commands/install-github-app.ts
|
|
492956
493106
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
492957
493107
|
import {
|
|
492958
|
-
existsSync as
|
|
492959
|
-
mkdirSync as
|
|
493108
|
+
existsSync as existsSync63,
|
|
493109
|
+
mkdirSync as mkdirSync44,
|
|
492960
493110
|
mkdtempSync as mkdtempSync5,
|
|
492961
493111
|
readFileSync as readFileSync41,
|
|
492962
493112
|
rmSync as rmSync15,
|
|
492963
|
-
writeFileSync as
|
|
493113
|
+
writeFileSync as writeFileSync32
|
|
492964
493114
|
} from "node:fs";
|
|
492965
493115
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
492966
|
-
import { dirname as dirname36, join as
|
|
493116
|
+
import { dirname as dirname36, join as join74 } from "node:path";
|
|
492967
493117
|
function runCommand(command, args, cwd2, input) {
|
|
492968
493118
|
try {
|
|
492969
493119
|
return execFileSync8(command, args, {
|
|
@@ -493184,8 +493334,8 @@ async function createLettaAgent(apiKey, name) {
|
|
|
493184
493334
|
return createMinimalAgent(apiKey, name);
|
|
493185
493335
|
}
|
|
493186
493336
|
function cloneRepoToTemp(repo) {
|
|
493187
|
-
const tempDir = mkdtempSync5(
|
|
493188
|
-
const repoDir =
|
|
493337
|
+
const tempDir = mkdtempSync5(join74(tmpdir10(), "letta-install-github-app-"));
|
|
493338
|
+
const repoDir = join74(tempDir, "repo");
|
|
493189
493339
|
runCommand("gh", ["repo", "clone", repo, repoDir, "--", "--depth=1"]);
|
|
493190
493340
|
return { tempDir, repoDir };
|
|
493191
493341
|
}
|
|
@@ -493196,19 +493346,19 @@ function runGit7(args, cwd2) {
|
|
|
493196
493346
|
return runCommand("git", args, cwd2);
|
|
493197
493347
|
}
|
|
493198
493348
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
493199
|
-
const absolutePath =
|
|
493200
|
-
if (!
|
|
493201
|
-
|
|
493349
|
+
const absolutePath = join74(repoDir, workflowPath);
|
|
493350
|
+
if (!existsSync63(dirname36(absolutePath))) {
|
|
493351
|
+
mkdirSync44(dirname36(absolutePath), { recursive: true });
|
|
493202
493352
|
}
|
|
493203
493353
|
const next = `${content.trimEnd()}
|
|
493204
493354
|
`;
|
|
493205
|
-
if (
|
|
493355
|
+
if (existsSync63(absolutePath)) {
|
|
493206
493356
|
const previous = readFileSync41(absolutePath, "utf8");
|
|
493207
493357
|
if (previous === next) {
|
|
493208
493358
|
return false;
|
|
493209
493359
|
}
|
|
493210
493360
|
}
|
|
493211
|
-
|
|
493361
|
+
writeFileSync32(absolutePath, next, "utf8");
|
|
493212
493362
|
return true;
|
|
493213
493363
|
}
|
|
493214
493364
|
function getDefaultBaseBranch(repoDir) {
|
|
@@ -497625,9 +497775,9 @@ __export(exports_generate_memory_viewer, {
|
|
|
497625
497775
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
497626
497776
|
});
|
|
497627
497777
|
import { execFile as execFileCb7 } from "node:child_process";
|
|
497628
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
497778
|
+
import { chmodSync as chmodSync8, existsSync as existsSync64, mkdirSync as mkdirSync45, writeFileSync as writeFileSync33 } from "node:fs";
|
|
497629
497779
|
import { homedir as homedir44 } from "node:os";
|
|
497630
|
-
import { join as
|
|
497780
|
+
import { join as join75 } from "node:path";
|
|
497631
497781
|
import { promisify as promisify18 } from "node:util";
|
|
497632
497782
|
function messagesFromOverview(overview) {
|
|
497633
497783
|
return overview.messages?.map((message) => ({
|
|
@@ -497936,7 +498086,7 @@ ${m4.body}` : m4.subject;
|
|
|
497936
498086
|
async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
497937
498087
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
497938
498088
|
const repoDir = memoryRoot;
|
|
497939
|
-
if (!
|
|
498089
|
+
if (!existsSync64(join75(repoDir, ".git"))) {
|
|
497940
498090
|
throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
|
|
497941
498091
|
}
|
|
497942
498092
|
const data = await collectMemoryData(agentId, repoDir, memoryRoot, options3?.conversationId);
|
|
@@ -497946,14 +498096,14 @@ async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
|
497946
498096
|
data.context = applyContextUsageSnapshot(data.context, options3?.contextUsage);
|
|
497947
498097
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
497948
498098
|
const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
497949
|
-
if (!
|
|
497950
|
-
|
|
498099
|
+
if (!existsSync64(VIEWERS_DIR)) {
|
|
498100
|
+
mkdirSync45(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
497951
498101
|
}
|
|
497952
498102
|
try {
|
|
497953
498103
|
chmodSync8(VIEWERS_DIR, 448);
|
|
497954
498104
|
} catch {}
|
|
497955
|
-
const filePath =
|
|
497956
|
-
|
|
498105
|
+
const filePath = join75(VIEWERS_DIR, `memory-${encodeURIComponent(agentId)}.html`);
|
|
498106
|
+
writeFileSync33(filePath, html5);
|
|
497957
498107
|
chmodSync8(filePath, 384);
|
|
497958
498108
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
497959
498109
|
if (!skipOpen) {
|
|
@@ -497977,13 +498127,13 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
497977
498127
|
init_local_memory_context();
|
|
497978
498128
|
init_memory_viewer_template();
|
|
497979
498129
|
execFile20 = promisify18(execFileCb7);
|
|
497980
|
-
VIEWERS_DIR =
|
|
498130
|
+
VIEWERS_DIR = join75(homedir44(), ".letta", "viewers");
|
|
497981
498131
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
497982
498132
|
});
|
|
497983
498133
|
|
|
497984
498134
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
497985
|
-
import { existsSync as
|
|
497986
|
-
import { join as
|
|
498135
|
+
import { existsSync as existsSync65 } from "node:fs";
|
|
498136
|
+
import { join as join76 } from "node:path";
|
|
497987
498137
|
function renderTreePrefix(node) {
|
|
497988
498138
|
let prefix = "";
|
|
497989
498139
|
for (let i4 = 0;i4 < node.depth; i4++) {
|
|
@@ -498011,8 +498161,8 @@ function MemfsTreeViewer({
|
|
|
498011
498161
|
const [status, setStatus] = import_react90.useState(null);
|
|
498012
498162
|
const statusTimerRef = import_react90.useRef(null);
|
|
498013
498163
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
498014
|
-
const memoryExists =
|
|
498015
|
-
const hasGitRepo = import_react90.useMemo(() =>
|
|
498164
|
+
const memoryExists = existsSync65(memoryRoot);
|
|
498165
|
+
const hasGitRepo = import_react90.useMemo(() => existsSync65(join76(memoryRoot, ".git")), [memoryRoot]);
|
|
498016
498166
|
function showStatus(msg, durationMs) {
|
|
498017
498167
|
if (statusTimerRef.current)
|
|
498018
498168
|
clearTimeout(statusTimerRef.current);
|
|
@@ -500478,10 +500628,10 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
500478
500628
|
// src/utils/aws-credentials.ts
|
|
500479
500629
|
import { readFile as readFile26 } from "node:fs/promises";
|
|
500480
500630
|
import { homedir as homedir45 } from "node:os";
|
|
500481
|
-
import { join as
|
|
500631
|
+
import { join as join77 } from "node:path";
|
|
500482
500632
|
async function parseAwsCredentials() {
|
|
500483
|
-
const credentialsPath =
|
|
500484
|
-
const configPath =
|
|
500633
|
+
const credentialsPath = join77(homedir45(), ".aws", "credentials");
|
|
500634
|
+
const configPath = join77(homedir45(), ".aws", "config");
|
|
500485
500635
|
const profiles = new Map;
|
|
500486
500636
|
try {
|
|
500487
500637
|
const content = await readFile26(credentialsPath, "utf-8");
|
|
@@ -502057,8 +502207,8 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
502057
502207
|
try {
|
|
502058
502208
|
const { discoverSkills: discoverSkills3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
|
|
502059
502209
|
const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
502060
|
-
const { join:
|
|
502061
|
-
const skillsDir = getSkillsDirectory2() ||
|
|
502210
|
+
const { join: join78 } = await import("node:path");
|
|
502211
|
+
const skillsDir = getSkillsDirectory2() || join78(process.cwd(), SKILLS_DIR3);
|
|
502062
502212
|
const result = await discoverSkills3(skillsDir, agentId, {
|
|
502063
502213
|
sources: getSkillSources2()
|
|
502064
502214
|
});
|
|
@@ -505984,9 +506134,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
505984
506134
|
const relPath = relative16(cwd2, filePath);
|
|
505985
506135
|
const displayPath2 = relPath.startsWith("..") ? filePath : relPath;
|
|
505986
506136
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
505987
|
-
const { existsSync:
|
|
506137
|
+
const { existsSync: existsSync66 } = __require("node:fs");
|
|
505988
506138
|
try {
|
|
505989
|
-
if (
|
|
506139
|
+
if (existsSync66(filePath)) {
|
|
505990
506140
|
return `Overwrite ${displayPath2}?`;
|
|
505991
506141
|
}
|
|
505992
506142
|
} catch {}
|
|
@@ -521326,9 +521476,9 @@ __export(exports_generate_diff_viewer, {
|
|
|
521326
521476
|
generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
|
|
521327
521477
|
});
|
|
521328
521478
|
import { execFile as execFileCb8 } from "node:child_process";
|
|
521329
|
-
import { chmodSync as chmodSync9, existsSync as
|
|
521479
|
+
import { chmodSync as chmodSync9, existsSync as existsSync66, mkdirSync as mkdirSync46, writeFileSync as writeFileSync34 } from "node:fs";
|
|
521330
521480
|
import { homedir as homedir46 } from "node:os";
|
|
521331
|
-
import { isAbsolute as isAbsolute26, join as
|
|
521481
|
+
import { isAbsolute as isAbsolute26, join as join78, resolve as resolve39 } from "node:path";
|
|
521332
521482
|
import { promisify as promisify19 } from "node:util";
|
|
521333
521483
|
async function runGit8(cwd2, args) {
|
|
521334
521484
|
try {
|
|
@@ -521547,14 +521697,14 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
521547
521697
|
};
|
|
521548
521698
|
const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
|
|
521549
521699
|
const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
521550
|
-
if (!
|
|
521551
|
-
|
|
521700
|
+
if (!existsSync66(VIEWERS_DIR2)) {
|
|
521701
|
+
mkdirSync46(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
521552
521702
|
}
|
|
521553
521703
|
try {
|
|
521554
521704
|
chmodSync9(VIEWERS_DIR2, 448);
|
|
521555
521705
|
} catch {}
|
|
521556
|
-
const filePath =
|
|
521557
|
-
|
|
521706
|
+
const filePath = join78(VIEWERS_DIR2, `diff-${encodeURIComponent(worktreePath)}.html`);
|
|
521707
|
+
writeFileSync34(filePath, html5);
|
|
521558
521708
|
chmodSync9(filePath, 384);
|
|
521559
521709
|
const skipOpen = shouldSkipOpen();
|
|
521560
521710
|
if (!skipOpen) {
|
|
@@ -521624,7 +521774,7 @@ var init_generate_diff_viewer = __esm(() => {
|
|
|
521624
521774
|
init_ssr();
|
|
521625
521775
|
init_diff_viewer_template();
|
|
521626
521776
|
execFile21 = promisify19(execFileCb8);
|
|
521627
|
-
VIEWERS_DIR2 =
|
|
521777
|
+
VIEWERS_DIR2 = join78(homedir46(), ".letta", "viewers");
|
|
521628
521778
|
GIT_MAX_BUFFER = 50 * 1024 * 1024;
|
|
521629
521779
|
});
|
|
521630
521780
|
|
|
@@ -523589,12 +523739,12 @@ __export(exports_shell_aliases, {
|
|
|
523589
523739
|
expandAliases: () => expandAliases,
|
|
523590
523740
|
clearAliasCache: () => clearAliasCache
|
|
523591
523741
|
});
|
|
523592
|
-
import { existsSync as
|
|
523742
|
+
import { existsSync as existsSync67, readFileSync as readFileSync42 } from "node:fs";
|
|
523593
523743
|
import { homedir as homedir47 } from "node:os";
|
|
523594
|
-
import { join as
|
|
523744
|
+
import { join as join79 } from "node:path";
|
|
523595
523745
|
function parseAliasesFromFile(filePath) {
|
|
523596
523746
|
const aliases = new Map;
|
|
523597
|
-
if (!
|
|
523747
|
+
if (!existsSync67(filePath)) {
|
|
523598
523748
|
return aliases;
|
|
523599
523749
|
}
|
|
523600
523750
|
try {
|
|
@@ -523663,7 +523813,7 @@ function loadAliases(forceReload = false) {
|
|
|
523663
523813
|
const home = homedir47();
|
|
523664
523814
|
const allAliases = new Map;
|
|
523665
523815
|
for (const file3 of ALIAS_FILES) {
|
|
523666
|
-
const filePath =
|
|
523816
|
+
const filePath = join79(home, file3);
|
|
523667
523817
|
const fileAliases = parseAliasesFromFile(filePath);
|
|
523668
523818
|
for (const [name, value] of fileAliases) {
|
|
523669
523819
|
allAliases.set(name, value);
|
|
@@ -531935,9 +532085,9 @@ var init_conversation_switch_alert = __esm(() => {
|
|
|
531935
532085
|
|
|
531936
532086
|
// src/cli/app/use-submit-handler.ts
|
|
531937
532087
|
import { randomUUID as randomUUID35 } from "node:crypto";
|
|
531938
|
-
import { existsSync as
|
|
532088
|
+
import { existsSync as existsSync68, readFileSync as readFileSync43, renameSync as renameSync7, writeFileSync as writeFileSync35 } from "node:fs";
|
|
531939
532089
|
import { tmpdir as tmpdir11 } from "node:os";
|
|
531940
|
-
import { join as
|
|
532090
|
+
import { join as join80 } from "node:path";
|
|
531941
532091
|
async function findCustomCommandByName(commandName) {
|
|
531942
532092
|
const { findCustomCommand: findCustomCommand2 } = await Promise.resolve().then(() => (init_custom(), exports_custom));
|
|
531943
532093
|
return findCustomCommand2(commandName);
|
|
@@ -532633,10 +532783,10 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
532633
532783
|
try {
|
|
532634
532784
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
532635
532785
|
const personaCandidates = [
|
|
532636
|
-
|
|
532637
|
-
|
|
532786
|
+
join80(memoryRoot, "system", "persona.md"),
|
|
532787
|
+
join80(memoryRoot, "memory", "system", "persona.md")
|
|
532638
532788
|
];
|
|
532639
|
-
const personaPath = personaCandidates.find((candidate) =>
|
|
532789
|
+
const personaPath = personaCandidates.find((candidate) => existsSync68(candidate));
|
|
532640
532790
|
if (personaPath) {
|
|
532641
532791
|
const personaContent = readFileSync43(personaPath, "utf-8");
|
|
532642
532792
|
setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
|
|
@@ -533410,7 +533560,7 @@ Tip: Use /clear instead to clear the current message buffer.`;
|
|
|
533410
533560
|
fileContent.skills = skills;
|
|
533411
533561
|
}
|
|
533412
533562
|
const fileName = exportParams.conversation_id ? `${exportParams.conversation_id}.af` : `${agentId}.af`;
|
|
533413
|
-
|
|
533563
|
+
writeFileSync35(fileName, JSON.stringify(fileContent, null, 2));
|
|
533414
533564
|
let summary = `AgentFile exported to ${fileName}`;
|
|
533415
533565
|
if (skills.length > 0) {
|
|
533416
533566
|
summary += `
|
|
@@ -533517,11 +533667,11 @@ Path: ${memoryDir}`, true);
|
|
|
533517
533667
|
setCommandRunning(true);
|
|
533518
533668
|
try {
|
|
533519
533669
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
533520
|
-
if (!
|
|
533670
|
+
if (!existsSync68(memoryDir)) {
|
|
533521
533671
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
533522
533672
|
return { submitted: true };
|
|
533523
533673
|
}
|
|
533524
|
-
const backupDir =
|
|
533674
|
+
const backupDir = join80(tmpdir11(), `letta-memfs-reset-${agentId}-${Date.now()}`);
|
|
533525
533675
|
renameSync7(memoryDir, backupDir);
|
|
533526
533676
|
if (getBackend().capabilities.localMemfs) {
|
|
533527
533677
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
@@ -534485,7 +534635,7 @@ var init_use_submit_handler = __esm(async () => {
|
|
|
534485
534635
|
});
|
|
534486
534636
|
|
|
534487
534637
|
// src/cli/app/AppCoordinator.tsx
|
|
534488
|
-
import { join as
|
|
534638
|
+
import { join as join81 } from "node:path";
|
|
534489
534639
|
function buildStartupCommandHints(options3) {
|
|
534490
534640
|
const {
|
|
534491
534641
|
isResumingConversation,
|
|
@@ -535791,7 +535941,7 @@ function App2({
|
|
|
535791
535941
|
agentId: a2.agentId ?? null
|
|
535792
535942
|
}))
|
|
535793
535943
|
});
|
|
535794
|
-
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ?
|
|
535944
|
+
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ? join81(modContext.memfs.memoryDir, "mods") : null;
|
|
535795
535945
|
const modAdapter = useLocalModAdapter(modContext, {
|
|
535796
535946
|
agentModsDirectory,
|
|
535797
535947
|
disabled: modsDisabled
|
|
@@ -536564,9 +536714,9 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
536564
536714
|
(async () => {
|
|
536565
536715
|
try {
|
|
536566
536716
|
const { watch: watch3 } = await import("node:fs");
|
|
536567
|
-
const { existsSync:
|
|
536717
|
+
const { existsSync: existsSync69 } = await import("node:fs");
|
|
536568
536718
|
const memRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
536569
|
-
if (!
|
|
536719
|
+
if (!existsSync69(memRoot))
|
|
536570
536720
|
return;
|
|
536571
536721
|
watcher2 = watch3(memRoot, { recursive: true }, () => {});
|
|
536572
536722
|
memfsWatcherRef.current = watcher2;
|
|
@@ -537891,13 +538041,13 @@ __export(exports_terminal_keybinding_installer2, {
|
|
|
537891
538041
|
});
|
|
537892
538042
|
import {
|
|
537893
538043
|
copyFileSync as copyFileSync6,
|
|
537894
|
-
existsSync as
|
|
537895
|
-
mkdirSync as
|
|
538044
|
+
existsSync as existsSync69,
|
|
538045
|
+
mkdirSync as mkdirSync47,
|
|
537896
538046
|
readFileSync as readFileSync44,
|
|
537897
|
-
writeFileSync as
|
|
538047
|
+
writeFileSync as writeFileSync36
|
|
537898
538048
|
} from "node:fs";
|
|
537899
538049
|
import { homedir as homedir49, platform as platform11 } from "node:os";
|
|
537900
|
-
import { dirname as dirname37, join as
|
|
538050
|
+
import { dirname as dirname37, join as join82 } from "node:path";
|
|
537901
538051
|
function detectTerminalType2() {
|
|
537902
538052
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
537903
538053
|
return "cursor";
|
|
@@ -537929,16 +538079,16 @@ function getKeybindingsPath2(terminal) {
|
|
|
537929
538079
|
}[terminal];
|
|
537930
538080
|
const os10 = platform11();
|
|
537931
538081
|
if (os10 === "darwin") {
|
|
537932
|
-
return
|
|
538082
|
+
return join82(homedir49(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
537933
538083
|
}
|
|
537934
538084
|
if (os10 === "win32") {
|
|
537935
538085
|
const appData = process.env.APPDATA;
|
|
537936
538086
|
if (!appData)
|
|
537937
538087
|
return null;
|
|
537938
|
-
return
|
|
538088
|
+
return join82(appData, appName, "User", "keybindings.json");
|
|
537939
538089
|
}
|
|
537940
538090
|
if (os10 === "linux") {
|
|
537941
|
-
return
|
|
538091
|
+
return join82(homedir49(), ".config", appName, "User", "keybindings.json");
|
|
537942
538092
|
}
|
|
537943
538093
|
return null;
|
|
537944
538094
|
}
|
|
@@ -537960,7 +538110,7 @@ function parseKeybindings2(content) {
|
|
|
537960
538110
|
}
|
|
537961
538111
|
}
|
|
537962
538112
|
function keybindingExists2(keybindingsPath) {
|
|
537963
|
-
if (!
|
|
538113
|
+
if (!existsSync69(keybindingsPath))
|
|
537964
538114
|
return false;
|
|
537965
538115
|
try {
|
|
537966
538116
|
const content = readFileSync44(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -537973,7 +538123,7 @@ function keybindingExists2(keybindingsPath) {
|
|
|
537973
538123
|
}
|
|
537974
538124
|
}
|
|
537975
538125
|
function createBackup2(keybindingsPath) {
|
|
537976
|
-
if (!
|
|
538126
|
+
if (!existsSync69(keybindingsPath))
|
|
537977
538127
|
return null;
|
|
537978
538128
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
537979
538129
|
try {
|
|
@@ -537989,12 +538139,12 @@ function installKeybinding2(keybindingsPath) {
|
|
|
537989
538139
|
return { success: true, alreadyExists: true };
|
|
537990
538140
|
}
|
|
537991
538141
|
const parentDir = dirname37(keybindingsPath);
|
|
537992
|
-
if (!
|
|
537993
|
-
|
|
538142
|
+
if (!existsSync69(parentDir)) {
|
|
538143
|
+
mkdirSync47(parentDir, { recursive: true });
|
|
537994
538144
|
}
|
|
537995
538145
|
let keybindings = [];
|
|
537996
538146
|
let backupPath = null;
|
|
537997
|
-
if (
|
|
538147
|
+
if (existsSync69(keybindingsPath)) {
|
|
537998
538148
|
backupPath = createBackup2(keybindingsPath);
|
|
537999
538149
|
const content = readFileSync44(keybindingsPath, { encoding: "utf-8" });
|
|
538000
538150
|
const parsed = parseKeybindings2(content);
|
|
@@ -538009,7 +538159,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
538009
538159
|
keybindings.push(SHIFT_ENTER_KEYBINDING2);
|
|
538010
538160
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
538011
538161
|
`;
|
|
538012
|
-
|
|
538162
|
+
writeFileSync36(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
538013
538163
|
return {
|
|
538014
538164
|
success: true,
|
|
538015
538165
|
backupPath: backupPath ?? undefined
|
|
@@ -538024,7 +538174,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
538024
538174
|
}
|
|
538025
538175
|
function removeKeybinding2(keybindingsPath) {
|
|
538026
538176
|
try {
|
|
538027
|
-
if (!
|
|
538177
|
+
if (!existsSync69(keybindingsPath)) {
|
|
538028
538178
|
return { success: true };
|
|
538029
538179
|
}
|
|
538030
538180
|
const content = readFileSync44(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -538038,7 +538188,7 @@ function removeKeybinding2(keybindingsPath) {
|
|
|
538038
538188
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
538039
538189
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
538040
538190
|
`;
|
|
538041
|
-
|
|
538191
|
+
writeFileSync36(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
538042
538192
|
return { success: true };
|
|
538043
538193
|
} catch (error54) {
|
|
538044
538194
|
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
@@ -538091,14 +538241,14 @@ function getWezTermConfigPath2() {
|
|
|
538091
538241
|
}
|
|
538092
538242
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
538093
538243
|
if (xdgConfig) {
|
|
538094
|
-
const xdgPath =
|
|
538095
|
-
if (
|
|
538244
|
+
const xdgPath = join82(xdgConfig, "wezterm", "wezterm.lua");
|
|
538245
|
+
if (existsSync69(xdgPath))
|
|
538096
538246
|
return xdgPath;
|
|
538097
538247
|
}
|
|
538098
|
-
const configPath =
|
|
538099
|
-
if (
|
|
538248
|
+
const configPath = join82(homedir49(), ".config", "wezterm", "wezterm.lua");
|
|
538249
|
+
if (existsSync69(configPath))
|
|
538100
538250
|
return configPath;
|
|
538101
|
-
return
|
|
538251
|
+
return join82(homedir49(), ".wezterm.lua");
|
|
538102
538252
|
}
|
|
538103
538253
|
function stripLuaCommentsFromLine2(line, blockCommentEnd) {
|
|
538104
538254
|
let code2 = "";
|
|
@@ -538201,7 +538351,7 @@ ${WEZTERM_DELETE_FIX2}
|
|
|
538201
538351
|
`;
|
|
538202
538352
|
}
|
|
538203
538353
|
function wezTermDeleteFixExists2(configPath) {
|
|
538204
|
-
if (!
|
|
538354
|
+
if (!existsSync69(configPath))
|
|
538205
538355
|
return false;
|
|
538206
538356
|
try {
|
|
538207
538357
|
const content = readFileSync44(configPath, { encoding: "utf-8" });
|
|
@@ -538218,17 +538368,17 @@ function installWezTermDeleteFix2() {
|
|
|
538218
538368
|
}
|
|
538219
538369
|
let content = "";
|
|
538220
538370
|
let backupPath = null;
|
|
538221
|
-
if (
|
|
538371
|
+
if (existsSync69(configPath)) {
|
|
538222
538372
|
backupPath = `${configPath}.letta-backup`;
|
|
538223
538373
|
copyFileSync6(configPath, backupPath);
|
|
538224
538374
|
content = readFileSync44(configPath, { encoding: "utf-8" });
|
|
538225
538375
|
}
|
|
538226
538376
|
content = injectWezTermDeleteFix2(content);
|
|
538227
538377
|
const parentDir = dirname37(configPath);
|
|
538228
|
-
if (!
|
|
538229
|
-
|
|
538378
|
+
if (!existsSync69(parentDir)) {
|
|
538379
|
+
mkdirSync47(parentDir, { recursive: true });
|
|
538230
538380
|
}
|
|
538231
|
-
|
|
538381
|
+
writeFileSync36(configPath, content, { encoding: "utf-8" });
|
|
538232
538382
|
return {
|
|
538233
538383
|
success: true,
|
|
538234
538384
|
backupPath: backupPath ?? undefined
|
|
@@ -538277,9 +538427,9 @@ __export(exports_settings3, {
|
|
|
538277
538427
|
getSetting: () => getSetting2
|
|
538278
538428
|
});
|
|
538279
538429
|
import { homedir as homedir50 } from "node:os";
|
|
538280
|
-
import { join as
|
|
538430
|
+
import { join as join83 } from "node:path";
|
|
538281
538431
|
function getSettingsPath2() {
|
|
538282
|
-
return
|
|
538432
|
+
return join83(homedir50(), ".letta", "settings.json");
|
|
538283
538433
|
}
|
|
538284
538434
|
async function loadSettings2() {
|
|
538285
538435
|
const settingsPath = getSettingsPath2();
|
|
@@ -538316,7 +538466,7 @@ async function getSetting2(key2) {
|
|
|
538316
538466
|
return settings3[key2];
|
|
538317
538467
|
}
|
|
538318
538468
|
function getProjectSettingsPath2() {
|
|
538319
|
-
return
|
|
538469
|
+
return join83(process.cwd(), ".letta", "settings.local.json");
|
|
538320
538470
|
}
|
|
538321
538471
|
async function loadProjectSettings2() {
|
|
538322
538472
|
const settingsPath = getProjectSettingsPath2();
|
|
@@ -538334,7 +538484,7 @@ async function loadProjectSettings2() {
|
|
|
538334
538484
|
}
|
|
538335
538485
|
async function saveProjectSettings2(settings3) {
|
|
538336
538486
|
const settingsPath = getProjectSettingsPath2();
|
|
538337
|
-
const dirPath =
|
|
538487
|
+
const dirPath = join83(process.cwd(), ".letta");
|
|
538338
538488
|
try {
|
|
538339
538489
|
if (!exists(dirPath)) {
|
|
538340
538490
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -539007,7 +539157,7 @@ function parseRegistryHandle2(handle2) {
|
|
|
539007
539157
|
}
|
|
539008
539158
|
async function importAgentFromRegistry2(options3) {
|
|
539009
539159
|
const { tmpdir: tmpdir12 } = await import("node:os");
|
|
539010
|
-
const { join:
|
|
539160
|
+
const { join: join84 } = await import("node:path");
|
|
539011
539161
|
const { writeFile: writeFile23, unlink: unlink5 } = await import("node:fs/promises");
|
|
539012
539162
|
const { author, name } = parseRegistryHandle2(options3.handle);
|
|
539013
539163
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -539019,7 +539169,7 @@ async function importAgentFromRegistry2(options3) {
|
|
|
539019
539169
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
539020
539170
|
}
|
|
539021
539171
|
const afContent = await response.text();
|
|
539022
|
-
const tempPath =
|
|
539172
|
+
const tempPath = join84(tmpdir12(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
539023
539173
|
await writeFile23(tempPath, afContent, "utf-8");
|
|
539024
539174
|
try {
|
|
539025
539175
|
const result = await importAgentFromFile2({
|
|
@@ -539073,14 +539223,14 @@ __export(exports_memory_filesystem2, {
|
|
|
539073
539223
|
MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
|
|
539074
539224
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
539075
539225
|
});
|
|
539076
|
-
import { existsSync as
|
|
539226
|
+
import { existsSync as existsSync70, mkdirSync as mkdirSync48 } from "node:fs";
|
|
539077
539227
|
import { homedir as homedir51 } from "node:os";
|
|
539078
|
-
import { join as
|
|
539228
|
+
import { join as join84, resolve as resolve42 } from "node:path";
|
|
539079
539229
|
function getMemoryFilesystemRoot2(agentId, homeDir = homedir51()) {
|
|
539080
|
-
return
|
|
539230
|
+
return join84(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
539081
539231
|
}
|
|
539082
539232
|
function getMemorySystemDir2(agentId, homeDir = homedir51()) {
|
|
539083
|
-
return
|
|
539233
|
+
return join84(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
|
|
539084
539234
|
}
|
|
539085
539235
|
function getScopedMemoryFilesystemRoot2(agentId, options3 = {}) {
|
|
539086
539236
|
const env6 = options3.env ?? process.env;
|
|
@@ -539116,11 +539266,11 @@ function resolveScopedMemoryDir2(options3 = {}) {
|
|
|
539116
539266
|
function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir51()) {
|
|
539117
539267
|
const root2 = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
539118
539268
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
539119
|
-
if (!
|
|
539120
|
-
|
|
539269
|
+
if (!existsSync70(root2)) {
|
|
539270
|
+
mkdirSync48(root2, { recursive: true });
|
|
539121
539271
|
}
|
|
539122
|
-
if (!
|
|
539123
|
-
|
|
539272
|
+
if (!existsSync70(systemDir)) {
|
|
539273
|
+
mkdirSync48(systemDir, { recursive: true });
|
|
539124
539274
|
}
|
|
539125
539275
|
}
|
|
539126
539276
|
function stampMemfsTagOnCreateBody2(body3, gitMemoryEnabledTag) {
|
|
@@ -539425,8 +539575,8 @@ __export(exports_secrets_store2, {
|
|
|
539425
539575
|
__testOverrideSecretsBackend: () => __testOverrideSecretsBackend2,
|
|
539426
539576
|
__testOverrideLocalSecretStorage: () => __testOverrideLocalSecretStorage2
|
|
539427
539577
|
});
|
|
539428
|
-
import { existsSync as
|
|
539429
|
-
import { dirname as dirname39, join as
|
|
539578
|
+
import { existsSync as existsSync71, mkdirSync as mkdirSync49, readFileSync as readFileSync45, writeFileSync as writeFileSync37 } from "node:fs";
|
|
539579
|
+
import { dirname as dirname39, join as join85 } from "node:path";
|
|
539430
539580
|
function __testOverrideSecretsBackend2(backend4) {
|
|
539431
539581
|
testBackendOverride2 = backend4;
|
|
539432
539582
|
}
|
|
@@ -539437,11 +539587,11 @@ function getSecretsBackend2() {
|
|
|
539437
539587
|
return testBackendOverride2 ?? getBackend();
|
|
539438
539588
|
}
|
|
539439
539589
|
function getFileBackedLocalSecretsPath2() {
|
|
539440
|
-
return
|
|
539590
|
+
return join85(getLocalBackendStorageDir(), FILE_BACKED_LOCAL_SECRETS_PATH2);
|
|
539441
539591
|
}
|
|
539442
539592
|
function readFileBackedLocalSecrets2() {
|
|
539443
539593
|
const filePath = getFileBackedLocalSecretsPath2();
|
|
539444
|
-
if (!
|
|
539594
|
+
if (!existsSync71(filePath))
|
|
539445
539595
|
return {};
|
|
539446
539596
|
try {
|
|
539447
539597
|
const parsed = JSON.parse(readFileSync45(filePath, "utf8"));
|
|
@@ -539454,8 +539604,8 @@ function readFileBackedLocalSecrets2() {
|
|
|
539454
539604
|
}
|
|
539455
539605
|
function writeFileBackedLocalSecrets2(secrets2) {
|
|
539456
539606
|
const filePath = getFileBackedLocalSecretsPath2();
|
|
539457
|
-
|
|
539458
|
-
|
|
539607
|
+
mkdirSync49(dirname39(filePath), { mode: 448, recursive: true });
|
|
539608
|
+
writeFileSync37(filePath, `${JSON.stringify({ secrets: secrets2 }, null, 2)}
|
|
539459
539609
|
`, {
|
|
539460
539610
|
encoding: "utf8",
|
|
539461
539611
|
flush: true,
|
|
@@ -539750,7 +539900,7 @@ var init_secrets_store2 = __esm(() => {
|
|
|
539750
539900
|
init_backend2();
|
|
539751
539901
|
init_paths();
|
|
539752
539902
|
init_secrets();
|
|
539753
|
-
FILE_BACKED_LOCAL_SECRETS_PATH2 =
|
|
539903
|
+
FILE_BACKED_LOCAL_SECRETS_PATH2 = join85("secrets", "local-agent-secrets.json");
|
|
539754
539904
|
SECRETS_CACHE_KEY2 = Symbol.for("@letta/secretsCache");
|
|
539755
539905
|
LOCAL_SECRET_NAME_PATTERN2 = /^[A-Z_][A-Z0-9_]*$/;
|
|
539756
539906
|
});
|
|
@@ -542949,21 +543099,21 @@ import { spawn as spawn9, spawnSync as spawnSync3 } from "node:child_process";
|
|
|
542949
543099
|
import {
|
|
542950
543100
|
chmodSync as chmodSync5,
|
|
542951
543101
|
createWriteStream as createWriteStream3,
|
|
542952
|
-
existsSync as
|
|
542953
|
-
mkdirSync as
|
|
543102
|
+
existsSync as existsSync37,
|
|
543103
|
+
mkdirSync as mkdirSync25,
|
|
542954
543104
|
readdirSync as readdirSync12,
|
|
542955
543105
|
renameSync as renameSync3,
|
|
542956
543106
|
rmSync as rmSync7,
|
|
542957
543107
|
statSync as statSync11
|
|
542958
543108
|
} from "node:fs";
|
|
542959
543109
|
import { arch as arch2, homedir as homedir27, platform as platform5 } from "node:os";
|
|
542960
|
-
import { basename as basename19, join as
|
|
543110
|
+
import { basename as basename19, join as join42 } from "node:path";
|
|
542961
543111
|
import { Readable as Readable3 } from "node:stream";
|
|
542962
543112
|
import { pipeline as pipeline6 } from "node:stream/promises";
|
|
542963
543113
|
var PATH_DELIMITERS = new Set([" ", "\t", '"', "'", "="]);
|
|
542964
|
-
var FD_TOOLS_DIR =
|
|
543114
|
+
var FD_TOOLS_DIR = join42(homedir27(), ".letta", "bin");
|
|
542965
543115
|
var FD_BINARY_NAME = platform5() === "win32" ? "fd.exe" : "fd";
|
|
542966
|
-
var FD_LOCAL_PATH =
|
|
543116
|
+
var FD_LOCAL_PATH = join42(FD_TOOLS_DIR, FD_BINARY_NAME);
|
|
542967
543117
|
var FD_DOWNLOAD_REPO = "sharkdp/fd";
|
|
542968
543118
|
var FD_DOWNLOAD_TIMEOUT_MS = 120000;
|
|
542969
543119
|
var FD_NETWORK_TIMEOUT_MS = 1e4;
|
|
@@ -543050,8 +543200,8 @@ function extractTarGzArchive2(archivePath, extractDir) {
|
|
|
543050
543200
|
function getWindowsTarCommand2() {
|
|
543051
543201
|
const systemRoot = process.env.SystemRoot ?? process.env.WINDIR;
|
|
543052
543202
|
if (systemRoot) {
|
|
543053
|
-
const systemTar =
|
|
543054
|
-
if (
|
|
543203
|
+
const systemTar = join42(systemRoot, "System32", "tar.exe");
|
|
543204
|
+
if (existsSync37(systemTar)) {
|
|
543055
543205
|
return systemTar;
|
|
543056
543206
|
}
|
|
543057
543207
|
}
|
|
@@ -543113,7 +543263,7 @@ function findBinaryRecursively2(rootDir, binaryName2) {
|
|
|
543113
543263
|
if (!currentDir)
|
|
543114
543264
|
continue;
|
|
543115
543265
|
for (const entry of readdirSync12(currentDir, { withFileTypes: true })) {
|
|
543116
|
-
const fullPath =
|
|
543266
|
+
const fullPath = join42(currentDir, entry.name);
|
|
543117
543267
|
if (entry.isFile() && entry.name === binaryName2) {
|
|
543118
543268
|
return fullPath;
|
|
543119
543269
|
}
|
|
@@ -543133,10 +543283,10 @@ async function downloadFd() {
|
|
|
543133
543283
|
if (!assetName) {
|
|
543134
543284
|
throw new Error(`Unsupported platform: ${platform5()}/${arch2()}`);
|
|
543135
543285
|
}
|
|
543136
|
-
|
|
543137
|
-
const archivePath =
|
|
543138
|
-
const extractDir =
|
|
543139
|
-
|
|
543286
|
+
mkdirSync25(FD_TOOLS_DIR, { recursive: true });
|
|
543287
|
+
const archivePath = join42(FD_TOOLS_DIR, assetName);
|
|
543288
|
+
const extractDir = join42(FD_TOOLS_DIR, `extract_tmp_fd_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`);
|
|
543289
|
+
mkdirSync25(extractDir, { recursive: true });
|
|
543140
543290
|
try {
|
|
543141
543291
|
await downloadFile3(`https://github.com/${FD_DOWNLOAD_REPO}/releases/download/v${version2}/${assetName}`, archivePath);
|
|
543142
543292
|
if (assetName.endsWith(".tar.gz")) {
|
|
@@ -543164,7 +543314,7 @@ function resolveFdPath() {
|
|
|
543164
543314
|
if (cachedFdPath !== undefined) {
|
|
543165
543315
|
return cachedFdPath;
|
|
543166
543316
|
}
|
|
543167
|
-
if (
|
|
543317
|
+
if (existsSync37(FD_LOCAL_PATH)) {
|
|
543168
543318
|
cachedFdPath = FD_LOCAL_PATH;
|
|
543169
543319
|
return cachedFdPath;
|
|
543170
543320
|
}
|
|
@@ -546204,7 +546354,7 @@ import { createHash as createHash6 } from "node:crypto";
|
|
|
546204
546354
|
|
|
546205
546355
|
// src/cli/subcommands/dream-sources/openhands.ts
|
|
546206
546356
|
import { readdir as readdir12, readFile as readFile19, stat as stat14 } from "node:fs/promises";
|
|
546207
|
-
import { join as
|
|
546357
|
+
import { join as join52 } from "node:path";
|
|
546208
546358
|
var RESULT_TEXT_TRUNCATE_LIMIT = 4000;
|
|
546209
546359
|
function joinTextContent(content) {
|
|
546210
546360
|
if (!Array.isArray(content))
|
|
@@ -546319,7 +546469,7 @@ function eventSequence(fileName) {
|
|
|
546319
546469
|
async function readOpenHandsEventDir(dir) {
|
|
546320
546470
|
let eventsDir = dir;
|
|
546321
546471
|
try {
|
|
546322
|
-
const nested =
|
|
546472
|
+
const nested = join52(dir, "events");
|
|
546323
546473
|
if ((await stat14(nested)).isDirectory()) {
|
|
546324
546474
|
eventsDir = nested;
|
|
546325
546475
|
}
|
|
@@ -546330,7 +546480,7 @@ async function readOpenHandsEventDir(dir) {
|
|
|
546330
546480
|
}
|
|
546331
546481
|
const events = [];
|
|
546332
546482
|
for (const name of fileNames) {
|
|
546333
|
-
const raw2 = await readFile19(
|
|
546483
|
+
const raw2 = await readFile19(join52(eventsDir, name), "utf-8");
|
|
546334
546484
|
const event2 = safeJsonParseOr(raw2, null);
|
|
546335
546485
|
if (event2 && typeof event2 === "object") {
|
|
546336
546486
|
events.push(event2);
|
|
@@ -546408,7 +546558,7 @@ init_memory_filesystem2();
|
|
|
546408
546558
|
init_memory_git();
|
|
546409
546559
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
546410
546560
|
import { mkdir as mkdir13, readFile as readFile21, rm as rm5, writeFile as writeFile15 } from "node:fs/promises";
|
|
546411
|
-
import { basename as basename25, dirname as dirname27, join as
|
|
546561
|
+
import { basename as basename25, dirname as dirname27, join as join53 } from "node:path";
|
|
546412
546562
|
function resolveDreamTarget(spec) {
|
|
546413
546563
|
const fileName = basename25(spec);
|
|
546414
546564
|
if (!fileName) {
|
|
@@ -546509,7 +546659,7 @@ async function syncTargetIntoMemory(agentId, target2, content) {
|
|
|
546509
546659
|
if (committed !== null && stripFrontmatter(committed) === stripFrontmatter(content)) {
|
|
546510
546660
|
return { synced: false };
|
|
546511
546661
|
}
|
|
546512
|
-
const absPath =
|
|
546662
|
+
const absPath = join53(memoryDir, relPath);
|
|
546513
546663
|
await mkdir13(dirname27(absPath), { recursive: true });
|
|
546514
546664
|
await writeFile15(absPath, addManagedFrontmatter(content, target2.kind), "utf-8");
|
|
546515
546665
|
try {
|
|
@@ -547072,14 +547222,14 @@ init_telemetry();
|
|
|
547072
547222
|
// src/websocket/listen-log.ts
|
|
547073
547223
|
import {
|
|
547074
547224
|
appendFileSync as appendFileSync7,
|
|
547075
|
-
existsSync as
|
|
547076
|
-
mkdirSync as
|
|
547225
|
+
existsSync as existsSync46,
|
|
547226
|
+
mkdirSync as mkdirSync32,
|
|
547077
547227
|
readdirSync as readdirSync16,
|
|
547078
547228
|
unlinkSync as unlinkSync7
|
|
547079
547229
|
} from "node:fs";
|
|
547080
547230
|
import { homedir as homedir31 } from "node:os";
|
|
547081
|
-
import { join as
|
|
547082
|
-
var REMOTE_LOG_DIR =
|
|
547231
|
+
import { join as join54 } from "node:path";
|
|
547232
|
+
var REMOTE_LOG_DIR = join54(homedir31(), ".letta", "logs", "remote");
|
|
547083
547233
|
var MAX_LOG_FILES = 10;
|
|
547084
547234
|
function formatTimestamp2() {
|
|
547085
547235
|
const now = new Date;
|
|
@@ -547091,14 +547241,14 @@ function formatTimestamp2() {
|
|
|
547091
547241
|
}
|
|
547092
547242
|
function pruneOldLogs() {
|
|
547093
547243
|
try {
|
|
547094
|
-
if (!
|
|
547244
|
+
if (!existsSync46(REMOTE_LOG_DIR))
|
|
547095
547245
|
return;
|
|
547096
547246
|
const files = readdirSync16(REMOTE_LOG_DIR).filter((f4) => f4.endsWith(".log")).sort();
|
|
547097
547247
|
if (files.length >= MAX_LOG_FILES) {
|
|
547098
547248
|
const toDelete = files.slice(0, files.length - MAX_LOG_FILES + 1);
|
|
547099
547249
|
for (const file3 of toDelete) {
|
|
547100
547250
|
try {
|
|
547101
|
-
unlinkSync7(
|
|
547251
|
+
unlinkSync7(join54(REMOTE_LOG_DIR, file3));
|
|
547102
547252
|
} catch {}
|
|
547103
547253
|
}
|
|
547104
547254
|
}
|
|
@@ -547111,7 +547261,7 @@ class RemoteSessionLog {
|
|
|
547111
547261
|
constructor() {
|
|
547112
547262
|
const now = new Date;
|
|
547113
547263
|
const stamp = now.toISOString().replace(/[:.]/g, "-");
|
|
547114
|
-
this.path =
|
|
547264
|
+
this.path = join54(REMOTE_LOG_DIR, `${stamp}.log`);
|
|
547115
547265
|
}
|
|
547116
547266
|
init() {
|
|
547117
547267
|
this.ensureDir();
|
|
@@ -547138,8 +547288,8 @@ class RemoteSessionLog {
|
|
|
547138
547288
|
if (this.dirCreated)
|
|
547139
547289
|
return;
|
|
547140
547290
|
try {
|
|
547141
|
-
if (!
|
|
547142
|
-
|
|
547291
|
+
if (!existsSync46(REMOTE_LOG_DIR)) {
|
|
547292
|
+
mkdirSync32(REMOTE_LOG_DIR, { recursive: true });
|
|
547143
547293
|
}
|
|
547144
547294
|
this.dirCreated = true;
|
|
547145
547295
|
} catch {}
|
|
@@ -547734,15 +547884,15 @@ init_local_store();
|
|
|
547734
547884
|
import { randomUUID as randomUUID24 } from "node:crypto";
|
|
547735
547885
|
import {
|
|
547736
547886
|
copyFileSync as copyFileSync2,
|
|
547737
|
-
existsSync as
|
|
547738
|
-
mkdirSync as
|
|
547887
|
+
existsSync as existsSync47,
|
|
547888
|
+
mkdirSync as mkdirSync33,
|
|
547739
547889
|
readdirSync as readdirSync17,
|
|
547740
547890
|
readFileSync as readFileSync32,
|
|
547741
|
-
writeFileSync as
|
|
547891
|
+
writeFileSync as writeFileSync24
|
|
547742
547892
|
} from "node:fs";
|
|
547743
|
-
import { join as
|
|
547893
|
+
import { join as join55 } from "node:path";
|
|
547744
547894
|
function readJsonl(path37) {
|
|
547745
|
-
if (!
|
|
547895
|
+
if (!existsSync47(path37))
|
|
547746
547896
|
return [];
|
|
547747
547897
|
return readFileSync32(path37, "utf8").split(`
|
|
547748
547898
|
`).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
@@ -547754,7 +547904,7 @@ function isPiLocalMessage(value) {
|
|
|
547754
547904
|
return isRecord(value) && typeof value.id === "string" && (value.role === "user" || value.role === "assistant" || value.role === "toolResult") && Object.hasOwn(value, "content");
|
|
547755
547905
|
}
|
|
547756
547906
|
function writeJsonl(path37, items3) {
|
|
547757
|
-
|
|
547907
|
+
writeFileSync24(path37, `${items3.map((item) => JSON.stringify(item)).join(`
|
|
547758
547908
|
`)}
|
|
547759
547909
|
`);
|
|
547760
547910
|
}
|
|
@@ -548023,20 +548173,20 @@ function convertMessages4(messages, mode, nextId2) {
|
|
|
548023
548173
|
}
|
|
548024
548174
|
function migrateLocalBackendTranscripts(input) {
|
|
548025
548175
|
const storageDir = input.storageDir;
|
|
548026
|
-
const conversationsDir =
|
|
548176
|
+
const conversationsDir = join55(storageDir, "conversations");
|
|
548027
548177
|
const result = {
|
|
548028
548178
|
storageDir,
|
|
548029
548179
|
converted: [],
|
|
548030
548180
|
skipped: [],
|
|
548031
548181
|
dryRun: input.dryRun === true
|
|
548032
548182
|
};
|
|
548033
|
-
if (!
|
|
548183
|
+
if (!existsSync47(conversationsDir))
|
|
548034
548184
|
return result;
|
|
548035
548185
|
for (const name of readdirSync17(conversationsDir)) {
|
|
548036
|
-
const conversationDir =
|
|
548037
|
-
const messagesPath =
|
|
548038
|
-
const manifestPath =
|
|
548039
|
-
const hasManifest =
|
|
548186
|
+
const conversationDir = join55(conversationsDir, name);
|
|
548187
|
+
const messagesPath = join55(conversationDir, "messages.jsonl");
|
|
548188
|
+
const manifestPath = join55(conversationDir, "manifest.json");
|
|
548189
|
+
const hasManifest = existsSync47(manifestPath);
|
|
548040
548190
|
const existingManifest = hasManifest ? (() => {
|
|
548041
548191
|
try {
|
|
548042
548192
|
return JSON.parse(readFileSync32(manifestPath, "utf8"));
|
|
@@ -548054,8 +548204,8 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
548054
548204
|
if (legacyMessages.length === 0) {
|
|
548055
548205
|
result.skipped.push({ conversationDir, reason: "empty" });
|
|
548056
548206
|
if (!input.dryRun) {
|
|
548057
|
-
|
|
548058
|
-
|
|
548207
|
+
mkdirSync33(conversationDir, { recursive: true });
|
|
548208
|
+
writeFileSync24(manifestPath, `${JSON.stringify(manifest({}), null, 2)}
|
|
548059
548209
|
`);
|
|
548060
548210
|
}
|
|
548061
548211
|
continue;
|
|
@@ -548078,9 +548228,9 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
548078
548228
|
const backupPath = `${messagesPath}.pre-pi-backup-${timestampSuffix()}`;
|
|
548079
548229
|
if (!input.dryRun) {
|
|
548080
548230
|
copyFileSync2(messagesPath, backupPath);
|
|
548081
|
-
const conversationPath =
|
|
548231
|
+
const conversationPath = join55(conversationDir, "conversation.json");
|
|
548082
548232
|
let conversation;
|
|
548083
|
-
if (
|
|
548233
|
+
if (existsSync47(conversationPath)) {
|
|
548084
548234
|
try {
|
|
548085
548235
|
conversation = JSON.parse(readFileSync32(conversationPath, "utf8"));
|
|
548086
548236
|
} catch {
|
|
@@ -548108,12 +548258,12 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
548108
548258
|
}
|
|
548109
548259
|
}
|
|
548110
548260
|
conversation.in_context_message_ids = remapped;
|
|
548111
|
-
|
|
548261
|
+
writeFileSync24(conversationPath, `${JSON.stringify(conversation, null, 2)}
|
|
548112
548262
|
`);
|
|
548113
548263
|
}
|
|
548114
548264
|
} catch {}
|
|
548115
548265
|
}
|
|
548116
|
-
|
|
548266
|
+
writeFileSync24(manifestPath, `${JSON.stringify(manifest({
|
|
548117
548267
|
backupPath,
|
|
548118
548268
|
migratedFrom: repairVersioned ? hasLegacyUiRows ? "versioned-pi-transcript-with-legacy-ui-message-rows" : "versioned-pi-ai-message-jsonl" : undefined
|
|
548119
548269
|
}), null, 2)}
|
|
@@ -548190,9 +548340,9 @@ async function runLocalBackendSubcommand(argv) {
|
|
|
548190
548340
|
init_memory_filesystem2();
|
|
548191
548341
|
init_memory_git();
|
|
548192
548342
|
init_paths();
|
|
548193
|
-
import { cpSync, existsSync as
|
|
548343
|
+
import { cpSync, existsSync as existsSync48, mkdirSync as mkdirSync34, rmSync as rmSync10, statSync as statSync16 } from "node:fs";
|
|
548194
548344
|
import { readdir as readdir13 } from "node:fs/promises";
|
|
548195
|
-
import { dirname as dirname28, join as
|
|
548345
|
+
import { dirname as dirname28, join as join56 } from "node:path";
|
|
548196
548346
|
import { parseArgs as parseArgs11 } from "node:util";
|
|
548197
548347
|
|
|
548198
548348
|
// src/cli/subcommands/memory-tokens.ts
|
|
@@ -548344,7 +548494,7 @@ function formatBackupTimestamp(date6 = new Date) {
|
|
|
548344
548494
|
}
|
|
548345
548495
|
async function listBackups(agentId) {
|
|
548346
548496
|
const agentRoot = getAgentRoot(agentId);
|
|
548347
|
-
if (!
|
|
548497
|
+
if (!existsSync48(agentRoot)) {
|
|
548348
548498
|
return [];
|
|
548349
548499
|
}
|
|
548350
548500
|
const entries = await readdir13(agentRoot, { withFileTypes: true });
|
|
@@ -548354,7 +548504,7 @@ async function listBackups(agentId) {
|
|
|
548354
548504
|
continue;
|
|
548355
548505
|
if (!entry.name.startsWith("memory-backup-"))
|
|
548356
548506
|
continue;
|
|
548357
|
-
const path37 =
|
|
548507
|
+
const path37 = join56(agentRoot, entry.name);
|
|
548358
548508
|
let createdAt = null;
|
|
548359
548509
|
try {
|
|
548360
548510
|
const stat15 = statSync16(path37);
|
|
@@ -548371,7 +548521,7 @@ function resolveBackupPath(agentId, from) {
|
|
|
548371
548521
|
if (from.startsWith("/") || /^[A-Za-z]:[/\\]/.test(from)) {
|
|
548372
548522
|
return from;
|
|
548373
548523
|
}
|
|
548374
|
-
return
|
|
548524
|
+
return join56(getAgentRoot(agentId), from);
|
|
548375
548525
|
}
|
|
548376
548526
|
async function runMemorySubcommand(argv) {
|
|
548377
548527
|
let parsed;
|
|
@@ -548447,14 +548597,14 @@ async function runMemorySubcommand(argv) {
|
|
|
548447
548597
|
}
|
|
548448
548598
|
if (action3 === "backup") {
|
|
548449
548599
|
const root2 = getMemoryRoot(agentId);
|
|
548450
|
-
if (!
|
|
548600
|
+
if (!existsSync48(root2)) {
|
|
548451
548601
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
548452
548602
|
return 1;
|
|
548453
548603
|
}
|
|
548454
548604
|
const agentRoot = getAgentRoot(agentId);
|
|
548455
548605
|
const backupName = `memory-backup-${formatBackupTimestamp()}`;
|
|
548456
|
-
const backupPath =
|
|
548457
|
-
if (
|
|
548606
|
+
const backupPath = join56(agentRoot, backupName);
|
|
548607
|
+
if (existsSync48(backupPath)) {
|
|
548458
548608
|
console.error(`Backup already exists at ${backupPath}`);
|
|
548459
548609
|
return 1;
|
|
548460
548610
|
}
|
|
@@ -548478,7 +548628,7 @@ async function runMemorySubcommand(argv) {
|
|
|
548478
548628
|
return 1;
|
|
548479
548629
|
}
|
|
548480
548630
|
const backupPath = resolveBackupPath(agentId, from);
|
|
548481
|
-
if (!
|
|
548631
|
+
if (!existsSync48(backupPath)) {
|
|
548482
548632
|
console.error(`Backup not found: ${backupPath}`);
|
|
548483
548633
|
return 1;
|
|
548484
548634
|
}
|
|
@@ -548500,11 +548650,11 @@ async function runMemorySubcommand(argv) {
|
|
|
548500
548650
|
return 1;
|
|
548501
548651
|
}
|
|
548502
548652
|
const root2 = getMemoryRoot(agentId);
|
|
548503
|
-
if (!
|
|
548653
|
+
if (!existsSync48(root2)) {
|
|
548504
548654
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
548505
548655
|
return 1;
|
|
548506
548656
|
}
|
|
548507
|
-
if (
|
|
548657
|
+
if (existsSync48(out)) {
|
|
548508
548658
|
const stat15 = statSync16(out);
|
|
548509
548659
|
if (stat15.isDirectory()) {
|
|
548510
548660
|
const contents = await readdir13(out);
|
|
@@ -548517,7 +548667,7 @@ async function runMemorySubcommand(argv) {
|
|
|
548517
548667
|
return 1;
|
|
548518
548668
|
}
|
|
548519
548669
|
} else {
|
|
548520
|
-
|
|
548670
|
+
mkdirSync34(out, { recursive: true });
|
|
548521
548671
|
}
|
|
548522
548672
|
cpSync(root2, out, { recursive: true });
|
|
548523
548673
|
console.log(JSON.stringify({ exportedFrom: root2, exportedTo: out, agentId }, null, 2));
|
|
@@ -548911,7 +549061,7 @@ async function runMessagesSubcommand(argv, deps = {}) {
|
|
|
548911
549061
|
// src/cli/subcommands/mods.ts
|
|
548912
549062
|
init_memory_filesystem2();
|
|
548913
549063
|
await init_mod_engine();
|
|
548914
|
-
import { dirname as dirname29, join as
|
|
549064
|
+
import { dirname as dirname29, join as join58 } from "node:path";
|
|
548915
549065
|
import { parseArgs as parseArgs13 } from "node:util";
|
|
548916
549066
|
|
|
548917
549067
|
// src/mods/package-installer.ts
|
|
@@ -548923,15 +549073,15 @@ import {
|
|
|
548923
549073
|
} from "node:child_process";
|
|
548924
549074
|
import {
|
|
548925
549075
|
copyFileSync as copyFileSync3,
|
|
548926
|
-
existsSync as
|
|
549076
|
+
existsSync as existsSync50,
|
|
548927
549077
|
lstatSync as lstatSync3,
|
|
548928
|
-
mkdirSync as
|
|
549078
|
+
mkdirSync as mkdirSync35,
|
|
548929
549079
|
mkdtempSync as mkdtempSync3,
|
|
548930
549080
|
readdirSync as readdirSync19,
|
|
548931
549081
|
readFileSync as readFileSync34,
|
|
548932
549082
|
renameSync as renameSync5,
|
|
548933
549083
|
rmSync as rmSync11,
|
|
548934
|
-
writeFileSync as
|
|
549084
|
+
writeFileSync as writeFileSync25
|
|
548935
549085
|
} from "node:fs";
|
|
548936
549086
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
548937
549087
|
import path37 from "node:path";
|
|
@@ -549071,7 +549221,7 @@ function validatePackageSource(packageDirectory) {
|
|
|
549071
549221
|
};
|
|
549072
549222
|
}
|
|
549073
549223
|
function copyPackageDirectory(sourceRoot, targetRoot) {
|
|
549074
|
-
|
|
549224
|
+
mkdirSync35(targetRoot, { recursive: true });
|
|
549075
549225
|
for (const entry of readdirSync19(sourceRoot, { withFileTypes: true })) {
|
|
549076
549226
|
if (SKIPPED_PACKAGE_COPY_NAMES.has(entry.name))
|
|
549077
549227
|
continue;
|
|
@@ -549086,7 +549236,7 @@ function copyPackageDirectory(sourceRoot, targetRoot) {
|
|
|
549086
549236
|
continue;
|
|
549087
549237
|
}
|
|
549088
549238
|
if (stats.isFile()) {
|
|
549089
|
-
|
|
549239
|
+
mkdirSync35(path37.dirname(targetPath), { recursive: true });
|
|
549090
549240
|
copyFileSync3(sourcePath, targetPath);
|
|
549091
549241
|
continue;
|
|
549092
549242
|
}
|
|
@@ -549126,7 +549276,7 @@ function copyDependencyDirectoryFiltered(params) {
|
|
|
549126
549276
|
continue;
|
|
549127
549277
|
}
|
|
549128
549278
|
if (stats.isFile()) {
|
|
549129
|
-
|
|
549279
|
+
mkdirSync35(path37.dirname(targetPath), { recursive: true });
|
|
549130
549280
|
copyFileSync3(sourcePath, targetPath);
|
|
549131
549281
|
copied = true;
|
|
549132
549282
|
continue;
|
|
@@ -549136,7 +549286,7 @@ function copyDependencyDirectoryFiltered(params) {
|
|
|
549136
549286
|
return copied;
|
|
549137
549287
|
}
|
|
549138
549288
|
function copyDependencyNodeModules(params) {
|
|
549139
|
-
if (!
|
|
549289
|
+
if (!existsSync50(params.sourceNodeModulesDirectory))
|
|
549140
549290
|
return;
|
|
549141
549291
|
copyDependencyDirectoryFiltered({
|
|
549142
549292
|
installedPackageName: params.installedPackageName,
|
|
@@ -549146,7 +549296,7 @@ function copyDependencyNodeModules(params) {
|
|
|
549146
549296
|
}
|
|
549147
549297
|
function copyPackageInternalNodeModules(params) {
|
|
549148
549298
|
const sourceNodeModulesDirectory = path37.join(params.packageDirectory, "node_modules");
|
|
549149
|
-
if (!
|
|
549299
|
+
if (!existsSync50(sourceNodeModulesDirectory))
|
|
549150
549300
|
return;
|
|
549151
549301
|
copyDependencyDirectoryFiltered({
|
|
549152
549302
|
sourceRoot: sourceNodeModulesDirectory,
|
|
@@ -549158,8 +549308,8 @@ function restoreRegistry(registryPath, previousContents) {
|
|
|
549158
549308
|
rmSync11(registryPath, { force: true });
|
|
549159
549309
|
return;
|
|
549160
549310
|
}
|
|
549161
|
-
|
|
549162
|
-
|
|
549311
|
+
mkdirSync35(path37.dirname(registryPath), { recursive: true });
|
|
549312
|
+
writeFileSync25(registryPath, previousContents);
|
|
549163
549313
|
}
|
|
549164
549314
|
function removeIfExists(targetPath) {
|
|
549165
549315
|
if (!targetPath)
|
|
@@ -549168,12 +549318,12 @@ function removeIfExists(targetPath) {
|
|
|
549168
549318
|
}
|
|
549169
549319
|
function restoreDestination(params) {
|
|
549170
549320
|
rmSync11(params.destinationRoot, { force: true, recursive: true });
|
|
549171
|
-
if (params.backupRoot &&
|
|
549321
|
+
if (params.backupRoot && existsSync50(params.backupRoot)) {
|
|
549172
549322
|
renameSync5(params.backupRoot, params.destinationRoot);
|
|
549173
549323
|
}
|
|
549174
549324
|
}
|
|
549175
549325
|
function restoreDestinationIfNeeded(params) {
|
|
549176
|
-
if (!params.backupRoot || !
|
|
549326
|
+
if (!params.backupRoot || !existsSync50(params.backupRoot)) {
|
|
549177
549327
|
rmSync11(params.destinationRoot, { force: true, recursive: true });
|
|
549178
549328
|
return;
|
|
549179
549329
|
}
|
|
@@ -549182,7 +549332,7 @@ function restoreDestinationIfNeeded(params) {
|
|
|
549182
549332
|
function makeSiblingTempDirectory(destinationRoot, label) {
|
|
549183
549333
|
const parent = path37.dirname(destinationRoot);
|
|
549184
549334
|
const baseName = path37.basename(destinationRoot).replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
549185
|
-
|
|
549335
|
+
mkdirSync35(parent, { recursive: true });
|
|
549186
549336
|
return mkdtempSync3(path37.join(parent, `.${baseName}.${label}-`));
|
|
549187
549337
|
}
|
|
549188
549338
|
function installPreparedManagedModPackage(params) {
|
|
@@ -549214,7 +549364,7 @@ function installPreparedManagedModPackage(params) {
|
|
|
549214
549364
|
targetPackageRoot: stagingRoot
|
|
549215
549365
|
});
|
|
549216
549366
|
}
|
|
549217
|
-
if (
|
|
549367
|
+
if (existsSync50(destinationRoot)) {
|
|
549218
549368
|
backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
|
|
549219
549369
|
rmSync11(backupRoot, { force: true, recursive: true });
|
|
549220
549370
|
renameSync5(destinationRoot, backupRoot);
|
|
@@ -549280,7 +549430,7 @@ function getNpmInstallArgs(installSpec) {
|
|
|
549280
549430
|
];
|
|
549281
549431
|
}
|
|
549282
549432
|
function writeNpmInstallManifest(tempRoot) {
|
|
549283
|
-
|
|
549433
|
+
writeFileSync25(path37.join(tempRoot, "package.json"), `${JSON.stringify({
|
|
549284
549434
|
private: true,
|
|
549285
549435
|
name: "letta-managed-mod-install"
|
|
549286
549436
|
}, null, 2)}
|
|
@@ -549497,7 +549647,7 @@ function hasRuntimeDependencies(packageJson) {
|
|
|
549497
549647
|
}
|
|
549498
549648
|
function readPackageJsonIfExists(packageDirectory) {
|
|
549499
549649
|
const packageJsonPath = path37.join(packageDirectory, "package.json");
|
|
549500
|
-
if (!
|
|
549650
|
+
if (!existsSync50(packageJsonPath))
|
|
549501
549651
|
return null;
|
|
549502
549652
|
return readPackageJson(packageJsonPath);
|
|
549503
549653
|
}
|
|
@@ -549511,7 +549661,7 @@ function isRegularModFile(filePath) {
|
|
|
549511
549661
|
}
|
|
549512
549662
|
function inferCompatibilityModEntries(packageDirectory) {
|
|
549513
549663
|
const modsDirectory = path37.join(packageDirectory, "mods");
|
|
549514
|
-
if (
|
|
549664
|
+
if (existsSync50(modsDirectory)) {
|
|
549515
549665
|
const stats = lstatSync3(modsDirectory);
|
|
549516
549666
|
if (stats.isSymbolicLink()) {
|
|
549517
549667
|
throw new Error(`Package mods directory must not be a symlink: mods`);
|
|
@@ -549552,7 +549702,7 @@ function getPackageVersionForGitPackage(params) {
|
|
|
549552
549702
|
}
|
|
549553
549703
|
function writeCompatibilityPackageManifest(params) {
|
|
549554
549704
|
const packageJsonPath = path37.join(params.packageDirectory, "package.json");
|
|
549555
|
-
|
|
549705
|
+
writeFileSync25(packageJsonPath, `${JSON.stringify({
|
|
549556
549706
|
...params.packageJson ?? {},
|
|
549557
549707
|
name: params.packageName,
|
|
549558
549708
|
version: params.version,
|
|
@@ -549783,11 +549933,11 @@ init_package_manifest();
|
|
|
549783
549933
|
init_package_registry();
|
|
549784
549934
|
import {
|
|
549785
549935
|
copyFileSync as copyFileSync4,
|
|
549786
|
-
existsSync as
|
|
549936
|
+
existsSync as existsSync51,
|
|
549787
549937
|
lstatSync as lstatSync4,
|
|
549788
|
-
mkdirSync as
|
|
549938
|
+
mkdirSync as mkdirSync36,
|
|
549789
549939
|
rmSync as rmSync12,
|
|
549790
|
-
writeFileSync as
|
|
549940
|
+
writeFileSync as writeFileSync26
|
|
549791
549941
|
} from "node:fs";
|
|
549792
549942
|
import path38 from "node:path";
|
|
549793
549943
|
var DEFAULT_PACKAGE_VERSION = "0.1.0";
|
|
@@ -549879,7 +550029,7 @@ function scaffoldLocalModPackage(options3) {
|
|
|
549879
550029
|
const sourceFile = readSourceFile(options3.sourceFile);
|
|
549880
550030
|
const packageName = assertValidPackageName(options3.packageName);
|
|
549881
550031
|
const outputDirectory = path38.resolve(options3.outputDirectory ?? defaultOutputDirectory(sourceFile, packageName));
|
|
549882
|
-
if (
|
|
550032
|
+
if (existsSync51(outputDirectory)) {
|
|
549883
550033
|
throw new Error(`Output directory already exists: ${outputDirectory}`);
|
|
549884
550034
|
}
|
|
549885
550035
|
const modFileName = path38.basename(sourceFile);
|
|
@@ -549891,12 +550041,12 @@ function scaffoldLocalModPackage(options3) {
|
|
|
549891
550041
|
const modGuidePath = path38.join(outputDirectory, "MOD.md");
|
|
549892
550042
|
const installCommand = `letta install ${outputDirectory}`;
|
|
549893
550043
|
try {
|
|
549894
|
-
|
|
550044
|
+
mkdirSync36(targetModsDirectory, { recursive: true });
|
|
549895
550045
|
copyFileSync4(sourceFile, targetModPath);
|
|
549896
|
-
|
|
550046
|
+
writeFileSync26(packageJsonPath, `${JSON.stringify(createPackageJson(packageName, manifestEntry), null, 2)}
|
|
549897
550047
|
`);
|
|
549898
|
-
|
|
549899
|
-
|
|
550048
|
+
writeFileSync26(readmePath, createReadme(packageName));
|
|
550049
|
+
writeFileSync26(modGuidePath, createModGuide(packageName, manifestEntry));
|
|
549900
550050
|
} catch (error54) {
|
|
549901
550051
|
rmSync12(outputDirectory, { force: true, recursive: true });
|
|
549902
550052
|
throw error54;
|
|
@@ -549964,7 +550114,7 @@ function getExplicitAgentId(values2) {
|
|
|
549964
550114
|
return typeof explicitAgent === "string" && explicitAgent.trim() ? explicitAgent.trim() : null;
|
|
549965
550115
|
}
|
|
549966
550116
|
function getAgentModsDirectory(agentId) {
|
|
549967
|
-
return
|
|
550117
|
+
return join58(getScopedMemoryFilesystemRoot(agentId), "mods");
|
|
549968
550118
|
}
|
|
549969
550119
|
function directFilesForSource(source2) {
|
|
549970
550120
|
return source2.files.filter((file3) => dirname29(file3) === source2.root);
|
|
@@ -550293,16 +550443,16 @@ async function runSetupSubcommand(argv) {
|
|
|
550293
550443
|
// src/cli/subcommands/skills.ts
|
|
550294
550444
|
import {
|
|
550295
550445
|
cpSync as cpSync2,
|
|
550296
|
-
existsSync as
|
|
550446
|
+
existsSync as existsSync52,
|
|
550297
550447
|
mkdtempSync as mkdtempSync4,
|
|
550298
550448
|
readFileSync as readFileSync35,
|
|
550299
550449
|
rmSync as rmSync13,
|
|
550300
550450
|
statSync as statSync18,
|
|
550301
|
-
writeFileSync as
|
|
550451
|
+
writeFileSync as writeFileSync27
|
|
550302
550452
|
} from "node:fs";
|
|
550303
550453
|
import { mkdir as mkdir14, readdir as readdir14 } from "node:fs/promises";
|
|
550304
550454
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
550305
|
-
import { basename as basename26, dirname as dirname30, join as
|
|
550455
|
+
import { basename as basename26, dirname as dirname30, join as join59, normalize as normalize5, resolve as resolve32, sep as sep6 } from "node:path";
|
|
550306
550456
|
import { parseArgs as parseArgs14, TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
|
|
550307
550457
|
init_paths2();
|
|
550308
550458
|
var HERMES_REPO_URL = "https://github.com/NousResearch/hermes-agent.git";
|
|
@@ -550607,14 +550757,14 @@ async function resolveBranchAndSubdir(location) {
|
|
|
550607
550757
|
}
|
|
550608
550758
|
async function cloneSkillSource(location) {
|
|
550609
550759
|
const resolvedLocation = await resolveBranchAndSubdir(location);
|
|
550610
|
-
const tmpDir = mkdtempSync4(
|
|
550760
|
+
const tmpDir = mkdtempSync4(join59(tmpdir9(), "letta-skill-install-"));
|
|
550611
550761
|
const args = ["clone", "--depth", "1"];
|
|
550612
550762
|
if (resolvedLocation.branch) {
|
|
550613
550763
|
args.push("--branch", resolvedLocation.branch);
|
|
550614
550764
|
}
|
|
550615
550765
|
args.push(resolvedLocation.repoUrl, tmpDir);
|
|
550616
550766
|
await execFile16("git", args, { timeout: 120000 });
|
|
550617
|
-
const sourceDir = resolvedLocation.subdir ?
|
|
550767
|
+
const sourceDir = resolvedLocation.subdir ? join59(tmpDir, resolvedLocation.subdir) : tmpDir;
|
|
550618
550768
|
return { tmpDir, sourceDir };
|
|
550619
550769
|
}
|
|
550620
550770
|
function assertDirectSkillFileSize(receivedBytes, maxBytes) {
|
|
@@ -550669,11 +550819,11 @@ async function downloadDirectSkillFileSource(location, options3 = {}) {
|
|
|
550669
550819
|
throw new Error(`Direct skill file download failed for ${location.url}: ${response.status}`);
|
|
550670
550820
|
}
|
|
550671
550821
|
const skillText = await readResponseTextWithLimit(response, MAX_DIRECT_SKILL_FILE_BYTES);
|
|
550672
|
-
const tmpDir = mkdtempSync4(
|
|
550822
|
+
const tmpDir = mkdtempSync4(join59(tmpdir9(), "letta-direct-skill-"));
|
|
550673
550823
|
try {
|
|
550674
|
-
const sourceDir =
|
|
550824
|
+
const sourceDir = join59(tmpDir, "skill");
|
|
550675
550825
|
await mkdir14(sourceDir, { recursive: true });
|
|
550676
|
-
|
|
550826
|
+
writeFileSync27(join59(sourceDir, "SKILL.md"), skillText, "utf8");
|
|
550677
550827
|
return { tmpDir, sourceDir };
|
|
550678
550828
|
} catch (error54) {
|
|
550679
550829
|
rmSync13(tmpDir, { recursive: true, force: true });
|
|
@@ -550714,9 +550864,9 @@ function assertSafeZipMember(name) {
|
|
|
550714
550864
|
}
|
|
550715
550865
|
async function downloadClawHubSkillSource(location) {
|
|
550716
550866
|
const version2 = await resolveClawHubVersion(location);
|
|
550717
|
-
const tmpDir = mkdtempSync4(
|
|
550718
|
-
const zipPath =
|
|
550719
|
-
const sourceDir =
|
|
550867
|
+
const tmpDir = mkdtempSync4(join59(tmpdir9(), "letta-clawhub-skill-"));
|
|
550868
|
+
const zipPath = join59(tmpDir, "skill.zip");
|
|
550869
|
+
const sourceDir = join59(tmpDir, "skill");
|
|
550720
550870
|
await mkdir14(sourceDir, { recursive: true });
|
|
550721
550871
|
const url2 = new URL(`${CLAWHUB_API_BASE_URL}/download`);
|
|
550722
550872
|
url2.searchParams.set("slug", location.slug);
|
|
@@ -550725,7 +550875,7 @@ async function downloadClawHubSkillSource(location) {
|
|
|
550725
550875
|
if (!response.ok) {
|
|
550726
550876
|
throw new Error(`ClawHub download failed for ${location.slug}@${version2}: ${response.status}`);
|
|
550727
550877
|
}
|
|
550728
|
-
|
|
550878
|
+
writeFileSync27(zipPath, Buffer.from(await response.arrayBuffer()));
|
|
550729
550879
|
const { stdout } = await execFile16("unzip", ["-Z1", zipPath], {
|
|
550730
550880
|
timeout: 30000
|
|
550731
550881
|
});
|
|
@@ -550755,7 +550905,7 @@ function sanitizeSkillName(name) {
|
|
|
550755
550905
|
return trimmed;
|
|
550756
550906
|
}
|
|
550757
550907
|
function getSkillName(sourceDir) {
|
|
550758
|
-
const skillMd = readFileSync35(
|
|
550908
|
+
const skillMd = readFileSync35(join59(sourceDir, "SKILL.md"), "utf8");
|
|
550759
550909
|
const { frontmatter } = parseFrontmatter(skillMd);
|
|
550760
550910
|
const frontmatterName = frontmatter.name;
|
|
550761
550911
|
const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename26(sourceDir);
|
|
@@ -550764,18 +550914,18 @@ function getSkillName(sourceDir) {
|
|
|
550764
550914
|
async function installSkillDirectory(params) {
|
|
550765
550915
|
const sourceDir = resolve32(params.sourceDir);
|
|
550766
550916
|
const memoryDir = resolve32(params.memoryDir);
|
|
550767
|
-
const skillMdPath =
|
|
550768
|
-
if (!
|
|
550917
|
+
const skillMdPath = join59(sourceDir, "SKILL.md");
|
|
550918
|
+
if (!existsSync52(skillMdPath)) {
|
|
550769
550919
|
throw new Error("No SKILL.md found in the skill directory.");
|
|
550770
550920
|
}
|
|
550771
550921
|
if (!statSync18(sourceDir).isDirectory()) {
|
|
550772
550922
|
throw new Error(`Skill source is not a directory: ${sourceDir}`);
|
|
550773
550923
|
}
|
|
550774
550924
|
const name = getSkillName(sourceDir);
|
|
550775
|
-
const skillsDir =
|
|
550776
|
-
const targetPath =
|
|
550925
|
+
const skillsDir = join59(memoryDir, "skills");
|
|
550926
|
+
const targetPath = join59(skillsDir, name);
|
|
550777
550927
|
assertInside(skillsDir, targetPath);
|
|
550778
|
-
if (
|
|
550928
|
+
if (existsSync52(targetPath)) {
|
|
550779
550929
|
if (!params.force) {
|
|
550780
550930
|
throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
|
|
550781
550931
|
}
|
|
@@ -550790,17 +550940,17 @@ async function installSkillDirectory(params) {
|
|
|
550790
550940
|
}
|
|
550791
550941
|
async function listSkillDirectories(params) {
|
|
550792
550942
|
const memoryDir = resolve32(params.memoryDir);
|
|
550793
|
-
const skillsDir =
|
|
550794
|
-
if (!
|
|
550943
|
+
const skillsDir = join59(memoryDir, "skills");
|
|
550944
|
+
if (!existsSync52(skillsDir))
|
|
550795
550945
|
return [];
|
|
550796
550946
|
const entries = await readdir14(skillsDir, { withFileTypes: true });
|
|
550797
550947
|
const skills = [];
|
|
550798
550948
|
for (const entry of entries) {
|
|
550799
550949
|
if (!entry.isDirectory())
|
|
550800
550950
|
continue;
|
|
550801
|
-
const skillDir =
|
|
550802
|
-
const skillMdPath =
|
|
550803
|
-
if (!
|
|
550951
|
+
const skillDir = join59(skillsDir, entry.name);
|
|
550952
|
+
const skillMdPath = join59(skillDir, "SKILL.md");
|
|
550953
|
+
if (!existsSync52(skillMdPath))
|
|
550804
550954
|
continue;
|
|
550805
550955
|
let name = entry.name;
|
|
550806
550956
|
let description;
|
|
@@ -550820,11 +550970,11 @@ async function listSkillDirectories(params) {
|
|
|
550820
550970
|
}
|
|
550821
550971
|
async function deleteSkillDirectory(params) {
|
|
550822
550972
|
const memoryDir = resolve32(params.memoryDir);
|
|
550823
|
-
const skillsDir =
|
|
550973
|
+
const skillsDir = join59(memoryDir, "skills");
|
|
550824
550974
|
const name = sanitizeSkillName(params.name);
|
|
550825
|
-
const targetPath =
|
|
550975
|
+
const targetPath = join59(skillsDir, name);
|
|
550826
550976
|
assertInside(skillsDir, targetPath);
|
|
550827
|
-
if (!
|
|
550977
|
+
if (!existsSync52(targetPath)) {
|
|
550828
550978
|
throw new Error(`Skill "${name}" is not installed at ${targetPath}.`);
|
|
550829
550979
|
}
|
|
550830
550980
|
if (!statSync18(targetPath).isDirectory()) {
|
|
@@ -550873,7 +551023,7 @@ async function installSkill(specifier, agentId, force) {
|
|
|
550873
551023
|
tmpDir = downloaded.tmpDir;
|
|
550874
551024
|
const sourceDir = resolve32(downloaded.sourceDir);
|
|
550875
551025
|
assertInside(tmpDir, sourceDir);
|
|
550876
|
-
if (!
|
|
551026
|
+
if (!existsSync52(sourceDir)) {
|
|
550877
551027
|
const missingPath = source2.type === "git" ? source2.location.subdir ?? "." : source2.type === "direct-file" ? source2.location.url : source2.location.slug;
|
|
550878
551028
|
throw new Error(`Skill path not found: ${missingPath}`);
|
|
550879
551029
|
}
|
|
@@ -551327,7 +551477,7 @@ init_secrets();
|
|
|
551327
551477
|
import { randomUUID as randomUUID25 } from "node:crypto";
|
|
551328
551478
|
import { readFileSync as readFileSync36 } from "node:fs";
|
|
551329
551479
|
import { homedir as homedir32 } from "node:os";
|
|
551330
|
-
import { join as
|
|
551480
|
+
import { join as join60, resolve as resolve33 } from "node:path";
|
|
551331
551481
|
var OBSOLETE_SETTINGS_KEYS2 = [
|
|
551332
551482
|
"reflectionBehavior",
|
|
551333
551483
|
"enableSleeptime",
|
|
@@ -551770,7 +551920,7 @@ class SettingsManager2 {
|
|
|
551770
551920
|
return;
|
|
551771
551921
|
const settingsPath = this.getSettingsPath();
|
|
551772
551922
|
const home = process.env.HOME || homedir32();
|
|
551773
|
-
const dirPath =
|
|
551923
|
+
const dirPath = join60(home, ".letta");
|
|
551774
551924
|
try {
|
|
551775
551925
|
if (!exists(dirPath)) {
|
|
551776
551926
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -551811,7 +551961,7 @@ class SettingsManager2 {
|
|
|
551811
551961
|
if (!settings3)
|
|
551812
551962
|
return;
|
|
551813
551963
|
const settingsPath = this.getProjectSettingsPath(workingDirectory);
|
|
551814
|
-
const dirPath =
|
|
551964
|
+
const dirPath = join60(workingDirectory, ".letta");
|
|
551815
551965
|
try {
|
|
551816
551966
|
let existingSettings = {};
|
|
551817
551967
|
if (exists(settingsPath)) {
|
|
@@ -551833,16 +551983,16 @@ class SettingsManager2 {
|
|
|
551833
551983
|
}
|
|
551834
551984
|
getSettingsPath() {
|
|
551835
551985
|
const home = process.env.HOME || homedir32();
|
|
551836
|
-
return
|
|
551986
|
+
return join60(home, ".letta", "settings.json");
|
|
551837
551987
|
}
|
|
551838
551988
|
getProjectSettingsPath(workingDirectory) {
|
|
551839
|
-
return
|
|
551989
|
+
return join60(workingDirectory, ".letta", "settings.json");
|
|
551840
551990
|
}
|
|
551841
551991
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
551842
551992
|
return resolve33(this.getProjectSettingsPath(workingDirectory)) === resolve33(this.getSettingsPath());
|
|
551843
551993
|
}
|
|
551844
551994
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
551845
|
-
return
|
|
551995
|
+
return join60(workingDirectory, ".letta", "settings.local.json");
|
|
551846
551996
|
}
|
|
551847
551997
|
async loadLocalProjectSettings(workingDirectory = process.cwd()) {
|
|
551848
551998
|
const cached3 = this.localProjectSettings.get(workingDirectory);
|
|
@@ -551903,7 +552053,7 @@ class SettingsManager2 {
|
|
|
551903
552053
|
if (!settings3)
|
|
551904
552054
|
return;
|
|
551905
552055
|
const settingsPath = this.getLocalProjectSettingsPath(workingDirectory);
|
|
551906
|
-
const dirPath =
|
|
552056
|
+
const dirPath = join60(workingDirectory, ".letta");
|
|
551907
552057
|
try {
|
|
551908
552058
|
if (!exists(dirPath)) {
|
|
551909
552059
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -552257,7 +552407,7 @@ class SettingsManager2 {
|
|
|
552257
552407
|
});
|
|
552258
552408
|
}
|
|
552259
552409
|
hasLocalLettaDir(workingDirectory = process.cwd()) {
|
|
552260
|
-
const dirPath =
|
|
552410
|
+
const dirPath = join60(workingDirectory, ".letta");
|
|
552261
552411
|
return exists(dirPath);
|
|
552262
552412
|
}
|
|
552263
552413
|
storeOAuthState(state, codeVerifier, redirectUri, provider) {
|
|
@@ -553032,12 +553182,12 @@ EXAMPLES
|
|
|
553032
553182
|
console.log(usage);
|
|
553033
553183
|
}
|
|
553034
553184
|
async function printInfo() {
|
|
553035
|
-
const { join:
|
|
553185
|
+
const { join: join86 } = await import("path");
|
|
553036
553186
|
const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version2));
|
|
553037
553187
|
const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills4(), exports_skills3));
|
|
553038
553188
|
const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
|
|
553039
553189
|
const cwd2 = process.cwd();
|
|
553040
|
-
const skillsDir =
|
|
553190
|
+
const skillsDir = join86(cwd2, SKILLS_DIR3);
|
|
553041
553191
|
const skillsExist = exists3(skillsDir);
|
|
553042
553192
|
await settingsManager2.loadLocalProjectSettings(cwd2);
|
|
553043
553193
|
const pinned = settingsManager2.getPinnedAgents();
|
|
@@ -553611,9 +553761,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
553611
553761
|
}
|
|
553612
553762
|
} else {
|
|
553613
553763
|
const { resolve: resolve43 } = await import("path");
|
|
553614
|
-
const { existsSync:
|
|
553764
|
+
const { existsSync: existsSync72 } = await import("fs");
|
|
553615
553765
|
const resolvedPath = resolve43(fromAfFile);
|
|
553616
|
-
if (!
|
|
553766
|
+
if (!existsSync72(resolvedPath)) {
|
|
553617
553767
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
553618
553768
|
process.exit(1);
|
|
553619
553769
|
}
|
|
@@ -554643,4 +554793,4 @@ Error during initialization: ${message}`);
|
|
|
554643
554793
|
}
|
|
554644
554794
|
main2();
|
|
554645
554795
|
|
|
554646
|
-
//# debugId=
|
|
554796
|
+
//# debugId=EA7311931B35FB9664756E2164756E21
|