@letta-ai/letta-code 0.28.2 → 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 +894 -743
- 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;
|
|
@@ -393725,7 +393802,8 @@ function projectLocalMessageToStoredMessages(message, fallbackAgentId, fallbackC
|
|
|
393725
393802
|
conversation_id: conversationId,
|
|
393726
393803
|
message_type: "user_message",
|
|
393727
393804
|
role: "user",
|
|
393728
|
-
content: userContentToStoredContent(message.content)
|
|
393805
|
+
content: userContentToStoredContent(message.content),
|
|
393806
|
+
...message.otid ? { otid: message.otid } : {}
|
|
393729
393807
|
}
|
|
393730
393808
|
];
|
|
393731
393809
|
}
|
|
@@ -393931,6 +394009,9 @@ function providerTypeFromModelSettings2(modelSettings) {
|
|
|
393931
394009
|
return typeof providerType === "string" && providerType.length > 0 ? providerType : null;
|
|
393932
394010
|
}
|
|
393933
394011
|
function normalizeLocalModelHandle(model, modelSettings, legacyLlmConfig) {
|
|
394012
|
+
if (isResolvablePiModelHandle(model) || resolveRegisteredPiProviderFromModelHandle(model)) {
|
|
394013
|
+
return model;
|
|
394014
|
+
}
|
|
393934
394015
|
const providerType = providerTypeFromModelSettings2(modelSettings);
|
|
393935
394016
|
const legacyEndpointType = legacyLlmConfig?.model_endpoint_type;
|
|
393936
394017
|
return resolveModelHandleFromLlmConfig({
|
|
@@ -393971,6 +394052,8 @@ function localLlmConfigModelPatch(model, modelSettings) {
|
|
|
393971
394052
|
}
|
|
393972
394053
|
var init_local_model_normalization = __esm(() => {
|
|
393973
394054
|
init_model_handles();
|
|
394055
|
+
init_pi_provider_mod_registry();
|
|
394056
|
+
init_pi_provider_registry();
|
|
393974
394057
|
});
|
|
393975
394058
|
|
|
393976
394059
|
// src/backend/local/local-stream-chunks.ts
|
|
@@ -394009,17 +394092,17 @@ import { randomUUID as randomUUID18 } from "node:crypto";
|
|
|
394009
394092
|
import {
|
|
394010
394093
|
appendFileSync as appendFileSync4,
|
|
394011
394094
|
closeSync,
|
|
394012
|
-
existsSync as
|
|
394013
|
-
mkdirSync as
|
|
394095
|
+
existsSync as existsSync33,
|
|
394096
|
+
mkdirSync as mkdirSync24,
|
|
394014
394097
|
openSync,
|
|
394015
394098
|
readdirSync as readdirSync11,
|
|
394016
394099
|
readFileSync as readFileSync24,
|
|
394017
394100
|
readSync,
|
|
394018
394101
|
rmSync as rmSync6,
|
|
394019
394102
|
statSync as statSync9,
|
|
394020
|
-
writeFileSync as
|
|
394103
|
+
writeFileSync as writeFileSync18
|
|
394021
394104
|
} from "node:fs";
|
|
394022
|
-
import { join as
|
|
394105
|
+
import { join as join40 } from "node:path";
|
|
394023
394106
|
function isStringArray2(value) {
|
|
394024
394107
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
394025
394108
|
}
|
|
@@ -394310,18 +394393,18 @@ function jsonl(items3) {
|
|
|
394310
394393
|
`;
|
|
394311
394394
|
}
|
|
394312
394395
|
function readJsonFile2(path31) {
|
|
394313
|
-
if (!
|
|
394396
|
+
if (!existsSync33(path31))
|
|
394314
394397
|
return;
|
|
394315
394398
|
return JSON.parse(readFileSync24(path31, "utf8"));
|
|
394316
394399
|
}
|
|
394317
394400
|
function readJsonlFile(path31) {
|
|
394318
|
-
if (!
|
|
394401
|
+
if (!existsSync33(path31))
|
|
394319
394402
|
return [];
|
|
394320
394403
|
return readFileSync24(path31, "utf8").split(`
|
|
394321
394404
|
`).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
394322
394405
|
}
|
|
394323
394406
|
function readJsonlFileSuffix(path31, maxBytes) {
|
|
394324
|
-
if (!
|
|
394407
|
+
if (!existsSync33(path31))
|
|
394325
394408
|
return { items: [], reachedStart: true };
|
|
394326
394409
|
const size = statSync9(path31).size;
|
|
394327
394410
|
if (size === 0)
|
|
@@ -394353,13 +394436,13 @@ function localTranscriptMigrationCommand(storageDir) {
|
|
|
394353
394436
|
return `letta local-backend migrate-transcripts --storage-dir ${quotedStorageDir}`;
|
|
394354
394437
|
}
|
|
394355
394438
|
function transcriptManifestPath(conversationDir) {
|
|
394356
|
-
return
|
|
394439
|
+
return join40(conversationDir, "manifest.json");
|
|
394357
394440
|
}
|
|
394358
394441
|
function transcriptMessagesPath(conversationDir) {
|
|
394359
|
-
return
|
|
394442
|
+
return join40(conversationDir, "messages.jsonl");
|
|
394360
394443
|
}
|
|
394361
394444
|
function hasNonEmptyJsonl(path31) {
|
|
394362
|
-
if (!
|
|
394445
|
+
if (!existsSync33(path31))
|
|
394363
394446
|
return false;
|
|
394364
394447
|
const stats = statSync9(path31);
|
|
394365
394448
|
if (stats.size === 0)
|
|
@@ -394495,7 +394578,7 @@ function validateLocalTranscriptManifest(conversationDir, storageDir) {
|
|
|
394495
394578
|
return manifest;
|
|
394496
394579
|
}
|
|
394497
394580
|
function writeLocalTranscriptManifest(conversationDir, manifest = createLocalTranscriptManifest()) {
|
|
394498
|
-
|
|
394581
|
+
writeFileSync18(transcriptManifestPath(conversationDir), `${JSON.stringify(manifest, null, 2)}
|
|
394499
394582
|
`);
|
|
394500
394583
|
}
|
|
394501
394584
|
function numericSuffix(value, prefix) {
|
|
@@ -394512,7 +394595,7 @@ function fileIsoTimestamp(value) {
|
|
|
394512
394595
|
}
|
|
394513
394596
|
function transcriptTimingForConversationDir(conversationDir, manifest) {
|
|
394514
394597
|
const messagesPath = transcriptMessagesPath(conversationDir);
|
|
394515
|
-
const stats =
|
|
394598
|
+
const stats = existsSync33(messagesPath) ? statSync9(messagesPath) : undefined;
|
|
394516
394599
|
const manifestCreatedAt = parseIsoTimestamp(manifest?.created_at) !== null ? manifest?.created_at : undefined;
|
|
394517
394600
|
const fileCreatedAt = fileIsoTimestamp(stats?.birthtimeMs);
|
|
394518
394601
|
const fileUpdatedAt = fileIsoTimestamp(stats?.mtimeMs);
|
|
@@ -394676,7 +394759,7 @@ class LocalStore {
|
|
|
394676
394759
|
this.persistedMessageByMessageIdByConversationKey.delete(key);
|
|
394677
394760
|
this.lastSessionEntryIdByConversationKey.delete(key);
|
|
394678
394761
|
if (this.storageDir) {
|
|
394679
|
-
rmSync6(
|
|
394762
|
+
rmSync6(join40(this.storageDir, "conversations", encodePathSegment(key)), {
|
|
394680
394763
|
recursive: true,
|
|
394681
394764
|
force: true
|
|
394682
394765
|
});
|
|
@@ -394684,7 +394767,7 @@ class LocalStore {
|
|
|
394684
394767
|
}
|
|
394685
394768
|
}
|
|
394686
394769
|
if (this.storageDir) {
|
|
394687
|
-
rmSync6(
|
|
394770
|
+
rmSync6(join40(this.storageDir, "agents", `${encodePathSegment(agentId)}.json`), { force: true });
|
|
394688
394771
|
}
|
|
394689
394772
|
}
|
|
394690
394773
|
retrieveAgentRecord(agentId) {
|
|
@@ -395007,7 +395090,7 @@ class LocalStore {
|
|
|
395007
395090
|
continue;
|
|
395008
395091
|
this.compiledSystemPromptByConversationKey.delete(key);
|
|
395009
395092
|
if (this.storageDir) {
|
|
395010
|
-
rmSync6(
|
|
395093
|
+
rmSync6(join40(this.storageDir, "conversations", encodePathSegment(key), "system-prompt.json"), { force: true });
|
|
395011
395094
|
}
|
|
395012
395095
|
}
|
|
395013
395096
|
}
|
|
@@ -395109,11 +395192,11 @@ class LocalStore {
|
|
|
395109
395192
|
}
|
|
395110
395193
|
appendUserLocalMessage(conversationId, agentId, message) {
|
|
395111
395194
|
const conversation = this.ensureConversation(conversationId, agentId);
|
|
395112
|
-
const id2 = this.nextLocalMessageId();
|
|
395113
395195
|
const date6 = this.currentLocalMessageDate();
|
|
395114
395196
|
const localMessage = {
|
|
395115
|
-
id:
|
|
395197
|
+
id: this.nextLocalMessageId(),
|
|
395116
395198
|
role: "user",
|
|
395199
|
+
otid: optionalString(message.otid ?? message.client_message_id),
|
|
395117
395200
|
metadata: {
|
|
395118
395201
|
created_at: date6,
|
|
395119
395202
|
updated_at: date6,
|
|
@@ -395777,11 +395860,11 @@ class LocalStore {
|
|
|
395777
395860
|
});
|
|
395778
395861
|
}
|
|
395779
395862
|
conversationsDir() {
|
|
395780
|
-
return this.storageDir ?
|
|
395863
|
+
return this.storageDir ? join40(this.storageDir, "conversations") : undefined;
|
|
395781
395864
|
}
|
|
395782
395865
|
conversationDirForKey(key) {
|
|
395783
395866
|
const conversationsDir = this.conversationsDir();
|
|
395784
|
-
return conversationsDir ?
|
|
395867
|
+
return conversationsDir ? join40(conversationsDir, encodePathSegment(key)) : undefined;
|
|
395785
395868
|
}
|
|
395786
395869
|
updateConversationSequences(conversation) {
|
|
395787
395870
|
this.conversationSeq = Math.max(this.conversationSeq, numericSuffix(conversation.id, this.conversationIdPrefix));
|
|
@@ -395800,7 +395883,7 @@ class LocalStore {
|
|
|
395800
395883
|
const conversation = requiresFullTimestampRepair ? normalizedInput : repairSyntheticConversationTimestamps(normalizedInput, [], timing);
|
|
395801
395884
|
let compiledSystemPrompt;
|
|
395802
395885
|
try {
|
|
395803
|
-
compiledSystemPrompt = readJsonFile2(
|
|
395886
|
+
compiledSystemPrompt = readJsonFile2(join40(conversationDir, "system-prompt.json"));
|
|
395804
395887
|
} catch {
|
|
395805
395888
|
compiledSystemPrompt = undefined;
|
|
395806
395889
|
}
|
|
@@ -395819,7 +395902,7 @@ class LocalStore {
|
|
|
395819
395902
|
}
|
|
395820
395903
|
loadConversationRecordFromDir(conversationDir) {
|
|
395821
395904
|
try {
|
|
395822
|
-
const conversation = readJsonFile2(
|
|
395905
|
+
const conversation = readJsonFile2(join40(conversationDir, "conversation.json"));
|
|
395823
395906
|
if (!conversation?.id || !conversation.agent_id)
|
|
395824
395907
|
return;
|
|
395825
395908
|
return this.cacheConversationRecord(conversationDir, conversation);
|
|
@@ -395829,7 +395912,7 @@ class LocalStore {
|
|
|
395829
395912
|
}
|
|
395830
395913
|
conversationRecordMtimeMs(conversationDir) {
|
|
395831
395914
|
try {
|
|
395832
|
-
return statSync9(
|
|
395915
|
+
return statSync9(join40(conversationDir, "conversation.json")).mtimeMs;
|
|
395833
395916
|
} catch {
|
|
395834
395917
|
return;
|
|
395835
395918
|
}
|
|
@@ -395855,7 +395938,7 @@ class LocalStore {
|
|
|
395855
395938
|
return existing;
|
|
395856
395939
|
}
|
|
395857
395940
|
try {
|
|
395858
|
-
const conversation = readJsonFile2(
|
|
395941
|
+
const conversation = readJsonFile2(join40(conversationDir, "conversation.json"));
|
|
395859
395942
|
if (!conversation?.id || !conversation.agent_id)
|
|
395860
395943
|
return existing;
|
|
395861
395944
|
const loadedKey = this.conversationKey(conversation.id, conversation.agent_id);
|
|
@@ -395874,7 +395957,7 @@ class LocalStore {
|
|
|
395874
395957
|
return;
|
|
395875
395958
|
this.conversationRecordsScanned = true;
|
|
395876
395959
|
const conversationsDir = this.conversationsDir();
|
|
395877
|
-
if (!conversationsDir || !
|
|
395960
|
+
if (!conversationsDir || !existsSync33(conversationsDir))
|
|
395878
395961
|
return;
|
|
395879
395962
|
let entries;
|
|
395880
395963
|
try {
|
|
@@ -395883,7 +395966,7 @@ class LocalStore {
|
|
|
395883
395966
|
return;
|
|
395884
395967
|
}
|
|
395885
395968
|
for (const entry of entries) {
|
|
395886
|
-
const conversationDir =
|
|
395969
|
+
const conversationDir = join40(conversationsDir, entry);
|
|
395887
395970
|
try {
|
|
395888
395971
|
if (!statSync9(conversationDir).isDirectory())
|
|
395889
395972
|
continue;
|
|
@@ -395899,14 +395982,14 @@ class LocalStore {
|
|
|
395899
395982
|
}
|
|
395900
395983
|
}
|
|
395901
395984
|
loadFromStorage() {
|
|
395902
|
-
if (!this.storageDir || !
|
|
395985
|
+
if (!this.storageDir || !existsSync33(this.storageDir))
|
|
395903
395986
|
return;
|
|
395904
|
-
const agentsDir =
|
|
395905
|
-
if (
|
|
395987
|
+
const agentsDir = join40(this.storageDir, "agents");
|
|
395988
|
+
if (existsSync33(agentsDir)) {
|
|
395906
395989
|
for (const file3 of readdirSync11(agentsDir)) {
|
|
395907
395990
|
if (!file3.endsWith(".json"))
|
|
395908
395991
|
continue;
|
|
395909
|
-
const raw = readJsonFile2(
|
|
395992
|
+
const raw = readJsonFile2(join40(agentsDir, file3));
|
|
395910
395993
|
const agent2 = normalizeAgentRecord(raw, this.defaultAgentModel);
|
|
395911
395994
|
if (agent2?.id) {
|
|
395912
395995
|
this.agents.set(agent2.id, agent2);
|
|
@@ -395923,9 +396006,9 @@ class LocalStore {
|
|
|
395923
396006
|
const agent2 = this.agents.get(agentId);
|
|
395924
396007
|
if (!agent2)
|
|
395925
396008
|
return;
|
|
395926
|
-
const agentsDir =
|
|
395927
|
-
|
|
395928
|
-
|
|
396009
|
+
const agentsDir = join40(this.storageDir, "agents");
|
|
396010
|
+
mkdirSync24(agentsDir, { recursive: true });
|
|
396011
|
+
writeFileSync18(join40(agentsDir, `${encodePathSegment(agentId)}.json`), `${JSON.stringify(agent2, null, 2)}
|
|
395929
396012
|
`);
|
|
395930
396013
|
}
|
|
395931
396014
|
projectAgent(record5) {
|
|
@@ -395942,15 +396025,15 @@ class LocalStore {
|
|
|
395942
396025
|
const conversation = this.conversations.get(key);
|
|
395943
396026
|
if (!conversation)
|
|
395944
396027
|
return;
|
|
395945
|
-
const conversationDir =
|
|
395946
|
-
|
|
395947
|
-
|
|
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)}
|
|
395948
396031
|
`);
|
|
395949
396032
|
this.recordConversationRecordMtime(key, conversationDir);
|
|
395950
396033
|
const messagesPath = transcriptMessagesPath(conversationDir);
|
|
395951
396034
|
let metadata = this.transcriptMetadataRecord(key, conversationDir);
|
|
395952
396035
|
const manifestPath = transcriptManifestPath(conversationDir);
|
|
395953
|
-
if (!
|
|
396036
|
+
if (!existsSync33(manifestPath) && !hasNonEmptyJsonl(messagesPath)) {
|
|
395954
396037
|
const manifest = createLocalTranscriptManifest();
|
|
395955
396038
|
writeLocalTranscriptManifest(conversationDir, manifest);
|
|
395956
396039
|
metadata = this.setTranscriptMetadata(key, {
|
|
@@ -395969,7 +396052,7 @@ class LocalStore {
|
|
|
395969
396052
|
persistConversationTranscript(key, conversation, conversationDir, messagesPath, messageFormat, options3) {
|
|
395970
396053
|
if (options3.transcript === "skip")
|
|
395971
396054
|
return;
|
|
395972
|
-
if (options3.transcript === undefined && this.loadRepairedConversationKeys.has(key) &&
|
|
396055
|
+
if (options3.transcript === undefined && this.loadRepairedConversationKeys.has(key) && existsSync33(messagesPath)) {
|
|
395973
396056
|
return;
|
|
395974
396057
|
}
|
|
395975
396058
|
const messages = this.localMessagesByConversationKey.get(key) ?? [];
|
|
@@ -396004,7 +396087,7 @@ class LocalStore {
|
|
|
396004
396087
|
this.appendConversationSessionCompactionEntry(key, conversation, messagesPath, options3.compaction);
|
|
396005
396088
|
return;
|
|
396006
396089
|
}
|
|
396007
|
-
if (options3.transcript === "rewrite" || this.loadedConversationKeys.has(key) || !
|
|
396090
|
+
if (options3.transcript === "rewrite" || this.loadedConversationKeys.has(key) || !existsSync33(messagesPath)) {
|
|
396008
396091
|
if (messages.length === 0)
|
|
396009
396092
|
return;
|
|
396010
396093
|
this.rewriteConversationSessionTranscript(key, conversation, messagesPath, messages);
|
|
@@ -396015,7 +396098,7 @@ class LocalStore {
|
|
|
396015
396098
|
if (messages.length === 0)
|
|
396016
396099
|
return;
|
|
396017
396100
|
const entries = localTranscriptSessionEntries(conversation, messages);
|
|
396018
|
-
|
|
396101
|
+
writeFileSync18(messagesPath, jsonl(entries));
|
|
396019
396102
|
this.resetPersistedSessionStateFromEntries(key, entries);
|
|
396020
396103
|
}
|
|
396021
396104
|
appendConversationSessionMessageEntry(key, conversation, messagesPath, message) {
|
|
@@ -396065,9 +396148,9 @@ class LocalStore {
|
|
|
396065
396148
|
this.lastSessionEntryIdByConversationKey.set(key, entry.id);
|
|
396066
396149
|
}
|
|
396067
396150
|
ensureConversationTranscriptHeader(conversation, messagesPath) {
|
|
396068
|
-
if (
|
|
396151
|
+
if (existsSync33(messagesPath) && statSync9(messagesPath).size > 0)
|
|
396069
396152
|
return;
|
|
396070
|
-
|
|
396153
|
+
writeFileSync18(messagesPath, `${JSON.stringify(createLocalTranscriptSessionHeader(conversation))}
|
|
396071
396154
|
`);
|
|
396072
396155
|
}
|
|
396073
396156
|
resetPersistedSessionState(key, messageFormat, transcript) {
|
|
@@ -396124,9 +396207,9 @@ class LocalStore {
|
|
|
396124
396207
|
const prompt = this.compiledSystemPromptByConversationKey.get(key);
|
|
396125
396208
|
if (!prompt)
|
|
396126
396209
|
return;
|
|
396127
|
-
const conversationDir =
|
|
396128
|
-
|
|
396129
|
-
|
|
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)}
|
|
396130
396213
|
`);
|
|
396131
396214
|
}
|
|
396132
396215
|
ensureConversation(conversationId, agentId) {
|
|
@@ -396155,7 +396238,7 @@ class LocalStore {
|
|
|
396155
396238
|
if (this.conversations.has(key))
|
|
396156
396239
|
continue;
|
|
396157
396240
|
const conversationDir = this.conversationDirForKey(key);
|
|
396158
|
-
if (conversationDir &&
|
|
396241
|
+
if (conversationDir && existsSync33(conversationDir))
|
|
396159
396242
|
continue;
|
|
396160
396243
|
return conversationId;
|
|
396161
396244
|
}
|
|
@@ -398845,11 +398928,21 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
398845
398928
|
return;
|
|
398846
398929
|
const modelSettings = localModelSettingsForHandle(handle);
|
|
398847
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;
|
|
398848
398937
|
models3.push({
|
|
398938
|
+
display_name: name,
|
|
398849
398939
|
handle,
|
|
398850
398940
|
...maxContextWindow ? { max_context_window: maxContextWindow } : {},
|
|
398941
|
+
...maxOutputTokens ? { max_tokens: maxOutputTokens } : {},
|
|
398851
398942
|
model: handle,
|
|
398852
|
-
model_endpoint_type:
|
|
398943
|
+
model_endpoint_type: providerType,
|
|
398944
|
+
name,
|
|
398945
|
+
provider_type: providerType
|
|
398853
398946
|
});
|
|
398854
398947
|
};
|
|
398855
398948
|
for (const provider of registeredProviders2) {
|
|
@@ -398863,7 +398956,9 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
398863
398956
|
addModel(provider.providerName, model.id, {
|
|
398864
398957
|
handle: `${provider.providerName}/${model.id}`,
|
|
398865
398958
|
maxContextWindow: model.contextWindow,
|
|
398866
|
-
|
|
398959
|
+
maxOutputTokens: model.maxTokens,
|
|
398960
|
+
modelEndpointType: provider.providerName,
|
|
398961
|
+
name: model.name
|
|
398867
398962
|
});
|
|
398868
398963
|
}
|
|
398869
398964
|
} catch {
|
|
@@ -398871,7 +398966,9 @@ async function listLocalModels(storageDir, options3 = {}) {
|
|
|
398871
398966
|
addModel(provider.providerName, model.id, {
|
|
398872
398967
|
handle: `${provider.providerName}/${model.id}`,
|
|
398873
398968
|
maxContextWindow: model.contextWindow,
|
|
398874
|
-
|
|
398969
|
+
maxOutputTokens: model.maxTokens,
|
|
398970
|
+
modelEndpointType: provider.providerName,
|
|
398971
|
+
name: model.name
|
|
398875
398972
|
});
|
|
398876
398973
|
}
|
|
398877
398974
|
}
|
|
@@ -400396,7 +400493,7 @@ Keep your summary under ${SLIDING_WORD_LIMIT} words. Only output the summary.`;
|
|
|
400396
400493
|
// src/backend/local/system-prompt-compilation.ts
|
|
400397
400494
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
400398
400495
|
import { createHash as createHash4 } from "node:crypto";
|
|
400399
|
-
import { existsSync as
|
|
400496
|
+
import { existsSync as existsSync34 } from "node:fs";
|
|
400400
400497
|
import { basename as basename16, dirname as dirname21, relative as relative6 } from "node:path";
|
|
400401
400498
|
function hashString(value) {
|
|
400402
400499
|
return createHash4("sha256").update(value).digest("hex");
|
|
@@ -400418,7 +400515,7 @@ function gitOutput(memoryDir, args) {
|
|
|
400418
400515
|
});
|
|
400419
400516
|
}
|
|
400420
400517
|
function getCommittedMemfsRevision(memoryDir) {
|
|
400421
|
-
if (!
|
|
400518
|
+
if (!existsSync34(memoryDir))
|
|
400422
400519
|
return;
|
|
400423
400520
|
try {
|
|
400424
400521
|
const revision = gitOutput(memoryDir, [
|
|
@@ -438684,9 +438781,9 @@ var init_paste_registry = __esm(() => {
|
|
|
438684
438781
|
|
|
438685
438782
|
// src/cli/helpers/clipboard.ts
|
|
438686
438783
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
438687
|
-
import { existsSync as
|
|
438784
|
+
import { existsSync as existsSync36, readFileSync as readFileSync26, statSync as statSync10, unlinkSync as unlinkSync5 } from "node:fs";
|
|
438688
438785
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
438689
|
-
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";
|
|
438690
438787
|
function countLines(text2) {
|
|
438691
438788
|
return (text2.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
438692
438789
|
}
|
|
@@ -438776,7 +438873,7 @@ function translatePasteForImages(paste) {
|
|
|
438776
438873
|
function getClipboardImageToTempFile() {
|
|
438777
438874
|
if (process.platform !== "darwin")
|
|
438778
438875
|
return null;
|
|
438779
|
-
const tempPath =
|
|
438876
|
+
const tempPath = join41(tmpdir7(), `letta-clipboard-${Date.now()}.bin`);
|
|
438780
438877
|
try {
|
|
438781
438878
|
const jxa = `
|
|
438782
438879
|
ObjC.import('AppKit');
|
|
@@ -438799,11 +438896,11 @@ function getClipboardImageToTempFile() {
|
|
|
438799
438896
|
encoding: "utf8",
|
|
438800
438897
|
stdio: ["ignore", "pipe", "ignore"]
|
|
438801
438898
|
}).trim();
|
|
438802
|
-
if (!uti || !
|
|
438899
|
+
if (!uti || !existsSync36(tempPath))
|
|
438803
438900
|
return null;
|
|
438804
438901
|
return { tempPath, uti };
|
|
438805
438902
|
} catch {
|
|
438806
|
-
if (
|
|
438903
|
+
if (existsSync36(tempPath)) {
|
|
438807
438904
|
try {
|
|
438808
438905
|
unlinkSync5(tempPath);
|
|
438809
438906
|
} catch {}
|
|
@@ -438836,7 +438933,7 @@ async function tryImportClipboardImageMac() {
|
|
|
438836
438933
|
height: resized.height
|
|
438837
438934
|
};
|
|
438838
438935
|
} catch (err) {
|
|
438839
|
-
if (
|
|
438936
|
+
if (existsSync36(tempPath)) {
|
|
438840
438937
|
try {
|
|
438841
438938
|
unlinkSync5(tempPath);
|
|
438842
438939
|
} catch {}
|
|
@@ -439319,18 +439416,18 @@ var init_local = __esm(() => {
|
|
|
439319
439416
|
});
|
|
439320
439417
|
|
|
439321
439418
|
// src/cli/helpers/local-agent-listing.ts
|
|
439322
|
-
import { existsSync as
|
|
439323
|
-
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";
|
|
439324
439421
|
function listLocalAgentsFromDisk() {
|
|
439325
439422
|
const storageDir = getLocalBackendStorageDir();
|
|
439326
|
-
const agentsDir =
|
|
439327
|
-
if (!
|
|
439423
|
+
const agentsDir = join43(storageDir, "agents");
|
|
439424
|
+
if (!existsSync38(agentsDir))
|
|
439328
439425
|
return [];
|
|
439329
439426
|
const files = readdirSync13(agentsDir).filter((f4) => f4.endsWith(".json"));
|
|
439330
439427
|
const agents = [];
|
|
439331
439428
|
for (const file3 of files) {
|
|
439332
439429
|
try {
|
|
439333
|
-
const filePath =
|
|
439430
|
+
const filePath = join43(agentsDir, file3);
|
|
439334
439431
|
const raw2 = readFileSync27(filePath, "utf8");
|
|
439335
439432
|
const record5 = JSON.parse(raw2);
|
|
439336
439433
|
if (isHiddenLocalAgentRecord(record5))
|
|
@@ -440048,23 +440145,23 @@ __export(exports_personality, {
|
|
|
440048
440145
|
applyPersonalityToMemory: () => applyPersonalityToMemory
|
|
440049
440146
|
});
|
|
440050
440147
|
import { execFile as execFileCb3 } from "node:child_process";
|
|
440051
|
-
import { existsSync as
|
|
440052
|
-
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";
|
|
440053
440150
|
import { promisify as promisify7 } from "node:util";
|
|
440054
440151
|
function ensureTrailingNewline2(content) {
|
|
440055
440152
|
return `${content.trimEnd()}
|
|
440056
440153
|
`;
|
|
440057
440154
|
}
|
|
440058
440155
|
function getMemoryFileRelativePathForRepo(repoDir, primaryRelativePath, legacyRelativePath) {
|
|
440059
|
-
const primaryPath =
|
|
440060
|
-
if (
|
|
440156
|
+
const primaryPath = join44(repoDir, primaryRelativePath);
|
|
440157
|
+
if (existsSync39(primaryPath)) {
|
|
440061
440158
|
return primaryRelativePath;
|
|
440062
440159
|
}
|
|
440063
|
-
const legacyPath =
|
|
440064
|
-
if (
|
|
440160
|
+
const legacyPath = join44(repoDir, legacyRelativePath);
|
|
440161
|
+
if (existsSync39(legacyPath)) {
|
|
440065
440162
|
return legacyRelativePath;
|
|
440066
440163
|
}
|
|
440067
|
-
if (
|
|
440164
|
+
if (existsSync39(join44(repoDir, "memory"))) {
|
|
440068
440165
|
return legacyRelativePath;
|
|
440069
440166
|
}
|
|
440070
440167
|
return primaryRelativePath;
|
|
@@ -440174,15 +440271,15 @@ async function getMemoryCommitAuthor(agentId) {
|
|
|
440174
440271
|
function applyPersonalityFiles(filesToUpdate) {
|
|
440175
440272
|
const changedPaths = [];
|
|
440176
440273
|
for (const file3 of filesToUpdate) {
|
|
440177
|
-
const existingContent =
|
|
440274
|
+
const existingContent = existsSync39(file3.absolutePath) ? readFileSync28(file3.absolutePath, "utf-8") : null;
|
|
440178
440275
|
const nextContent = existingContent ? replaceBodyPreservingFrontmatter(existingContent, file3.content, {
|
|
440179
440276
|
description: file3.description
|
|
440180
440277
|
}) : buildDefaultMemoryFile(file3.templatePromptAssetName, file3.content, file3.description);
|
|
440181
440278
|
if (existingContent !== null && normalizeComparableContent(existingContent) === normalizeComparableContent(nextContent)) {
|
|
440182
440279
|
continue;
|
|
440183
440280
|
}
|
|
440184
|
-
|
|
440185
|
-
|
|
440281
|
+
mkdirSync26(dirname22(file3.absolutePath), { recursive: true });
|
|
440282
|
+
writeFileSync19(file3.absolutePath, nextContent, "utf-8");
|
|
440186
440283
|
changedPaths.push(file3.relativePath);
|
|
440187
440284
|
}
|
|
440188
440285
|
return changedPaths;
|
|
@@ -440204,8 +440301,8 @@ async function applyPersonalityToMemory(params) {
|
|
|
440204
440301
|
}
|
|
440205
440302
|
const personaRelativePath = getPersonaRelativePathForRepo(repoDir);
|
|
440206
440303
|
const humanRelativePath = getHumanRelativePathForRepo(repoDir);
|
|
440207
|
-
const personaPath =
|
|
440208
|
-
const humanPath =
|
|
440304
|
+
const personaPath = join44(repoDir, personaRelativePath);
|
|
440305
|
+
const humanPath = join44(repoDir, humanRelativePath);
|
|
440209
440306
|
const filesToUpdate = [
|
|
440210
440307
|
{
|
|
440211
440308
|
relativePath: personaRelativePath,
|
|
@@ -440644,13 +440741,14 @@ var init_progress_builder = __esm(async () => {
|
|
|
440644
440741
|
// src/agent/memory-worktree.ts
|
|
440645
440742
|
import { execFile as execFileCb4 } from "node:child_process";
|
|
440646
440743
|
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
440647
|
-
import { existsSync as
|
|
440744
|
+
import { existsSync as existsSync40 } from "node:fs";
|
|
440648
440745
|
import { mkdir as mkdir11, realpath as realpath4 } from "node:fs/promises";
|
|
440649
|
-
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";
|
|
440650
440747
|
import { promisify as promisify8 } from "node:util";
|
|
440651
440748
|
async function runGit4(cwd2, args) {
|
|
440652
440749
|
try {
|
|
440653
|
-
const
|
|
440750
|
+
const allArgs = [...GIT_DISABLE_COMMIT_SIGNING_ARGS, ...args];
|
|
440751
|
+
const { stdout, stderr } = await execFile8("git", allArgs, {
|
|
440654
440752
|
cwd: cwd2,
|
|
440655
440753
|
env: {
|
|
440656
440754
|
...process.env,
|
|
@@ -440705,8 +440803,8 @@ async function buildReflectionMergeMessage(parentMemoryDir, branchName) {
|
|
|
440705
440803
|
async function createReflectionMemoryWorktree(options3) {
|
|
440706
440804
|
const parentMemoryDir = resolve30(options3.parentMemoryDir);
|
|
440707
440805
|
const id2 = buildReflectionWorktreeId(options3.now);
|
|
440708
|
-
const worktreeBaseDir =
|
|
440709
|
-
const worktreeDir =
|
|
440806
|
+
const worktreeBaseDir = join45(dirname23(parentMemoryDir), "memory-worktrees");
|
|
440807
|
+
const worktreeDir = join45(worktreeBaseDir, `reflection-${id2}`);
|
|
440710
440808
|
const branchName = `letta/reflection/${id2}`;
|
|
440711
440809
|
await mkdir11(worktreeBaseDir, { recursive: true });
|
|
440712
440810
|
const { stdout: baseHeadOut } = await runGit4(parentMemoryDir, [
|
|
@@ -440823,7 +440921,7 @@ function parseWorktreeListPorcelain(output) {
|
|
|
440823
440921
|
}
|
|
440824
440922
|
async function listPendingReflectionMemoryWorktrees(parentMemoryDir) {
|
|
440825
440923
|
const resolvedParent = await realpath4(resolve30(parentMemoryDir));
|
|
440826
|
-
const worktreeBaseDir =
|
|
440924
|
+
const worktreeBaseDir = join45(dirname23(resolvedParent), "memory-worktrees");
|
|
440827
440925
|
const worktreeList = await tryRunGit(resolvedParent, [
|
|
440828
440926
|
"worktree",
|
|
440829
440927
|
"list",
|
|
@@ -440914,7 +441012,7 @@ async function integratePendingReflectionMemoryWorktrees(parentMemoryDir) {
|
|
|
440914
441012
|
return unresolved;
|
|
440915
441013
|
}
|
|
440916
441014
|
async function cleanupWorktreeAndBranch(parentMemoryDir, worktreeDir, branchName, options3 = {}) {
|
|
440917
|
-
const removedWorktree =
|
|
441015
|
+
const removedWorktree = existsSync40(worktreeDir);
|
|
440918
441016
|
if (removedWorktree) {
|
|
440919
441017
|
await runGit4(parentMemoryDir, [
|
|
440920
441018
|
"worktree",
|
|
@@ -441025,6 +441123,7 @@ async function finalizeReflectionMemoryWorktree(worktree, options3) {
|
|
|
441025
441123
|
}
|
|
441026
441124
|
var execFile8, GIT_TIMEOUT_MS = 30000, HARNESS_GIT_ENV;
|
|
441027
441125
|
var init_memory_worktree = __esm(() => {
|
|
441126
|
+
init_memory_git_signing();
|
|
441028
441127
|
init_debug();
|
|
441029
441128
|
execFile8 = promisify8(execFileCb4);
|
|
441030
441129
|
HARNESS_GIT_ENV = {
|
|
@@ -441291,7 +441390,7 @@ import {
|
|
|
441291
441390
|
stat as stat11,
|
|
441292
441391
|
writeFile as writeFile13
|
|
441293
441392
|
} from "node:fs/promises";
|
|
441294
|
-
import { join as
|
|
441393
|
+
import { join as join46 } from "node:path";
|
|
441295
441394
|
function buildReflectionSubagentPrompt(input) {
|
|
441296
441395
|
const lines = [];
|
|
441297
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.", "");
|
|
@@ -441337,7 +441436,7 @@ async function collectParentMemoryFiles(memoryDir) {
|
|
|
441337
441436
|
return a2.name.localeCompare(b3.name);
|
|
441338
441437
|
});
|
|
441339
441438
|
for (const entry of sortedEntries) {
|
|
441340
|
-
const entryPath =
|
|
441439
|
+
const entryPath = join46(currentDir, entry.name);
|
|
441341
441440
|
const relativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
|
|
441342
441441
|
if (entry.isDirectory()) {
|
|
441343
441442
|
await walk(entryPath, relativePath);
|
|
@@ -441783,17 +441882,17 @@ async function writeState(paths, state) {
|
|
|
441783
441882
|
}
|
|
441784
441883
|
function buildPayloadPath(rootDir, kind) {
|
|
441785
441884
|
const nonce = Math.random().toString(36).slice(2, 8);
|
|
441786
|
-
return
|
|
441885
|
+
return join46(rootDir, `payload-${kind}-${nonce}.json`);
|
|
441787
441886
|
}
|
|
441788
441887
|
function getAgentTranscriptRoot(agentId) {
|
|
441789
|
-
return
|
|
441888
|
+
return join46(getTranscriptRoot(), sanitizePathSegment2(agentId));
|
|
441790
441889
|
}
|
|
441791
441890
|
function getReflectionTranscriptPaths(agentId, conversationId) {
|
|
441792
|
-
const rootDir =
|
|
441891
|
+
const rootDir = join46(getTranscriptRoot(), sanitizePathSegment2(agentId), sanitizePathSegment2(conversationId));
|
|
441793
441892
|
return {
|
|
441794
441893
|
rootDir,
|
|
441795
|
-
transcriptPath:
|
|
441796
|
-
statePath:
|
|
441894
|
+
transcriptPath: join46(rootDir, "transcript.jsonl"),
|
|
441895
|
+
statePath: join46(rootDir, "state.json")
|
|
441797
441896
|
};
|
|
441798
441897
|
}
|
|
441799
441898
|
async function appendTranscriptDeltaJsonl(agentId, conversationId, lines) {
|
|
@@ -441962,7 +442061,7 @@ async function getTranscriptLastUpdatedAt(paths) {
|
|
|
441962
442061
|
}
|
|
441963
442062
|
}
|
|
441964
442063
|
async function ensureAgentPayloadRoot(agentId) {
|
|
441965
|
-
const root2 =
|
|
442064
|
+
const root2 = join46(getAgentTranscriptRoot(agentId), "multi-reflection-payloads");
|
|
441966
442065
|
await mkdir12(root2, { recursive: true });
|
|
441967
442066
|
return root2;
|
|
441968
442067
|
}
|
|
@@ -443909,25 +444008,25 @@ var init_parse_interval = __esm(() => {
|
|
|
443909
444008
|
// src/cron/cron-file.ts
|
|
443910
444009
|
import { randomBytes } from "node:crypto";
|
|
443911
444010
|
import {
|
|
443912
|
-
existsSync as
|
|
443913
|
-
mkdirSync as
|
|
444011
|
+
existsSync as existsSync41,
|
|
444012
|
+
mkdirSync as mkdirSync27,
|
|
443914
444013
|
readFileSync as readFileSync29,
|
|
443915
444014
|
renameSync as renameSync4,
|
|
443916
444015
|
rmSync as rmSync8,
|
|
443917
444016
|
statSync as statSync13,
|
|
443918
|
-
writeFileSync as
|
|
444017
|
+
writeFileSync as writeFileSync20
|
|
443919
444018
|
} from "node:fs";
|
|
443920
|
-
import { join as
|
|
444019
|
+
import { join as join47 } from "node:path";
|
|
443921
444020
|
function getLettaDir() {
|
|
443922
444021
|
if (process.env.LETTA_HOME)
|
|
443923
444022
|
return process.env.LETTA_HOME;
|
|
443924
|
-
return
|
|
444023
|
+
return join47(process.env.HOME ?? process.env.USERPROFILE ?? "~", ".letta");
|
|
443925
444024
|
}
|
|
443926
444025
|
function getCronFilePath() {
|
|
443927
|
-
return
|
|
444026
|
+
return join47(getLettaDir(), CRON_FILE_NAME);
|
|
443928
444027
|
}
|
|
443929
444028
|
function getLockDirPath() {
|
|
443930
|
-
return
|
|
444029
|
+
return join47(getLettaDir(), LOCK_DIR_NAME);
|
|
443931
444030
|
}
|
|
443932
444031
|
function emptyFile() {
|
|
443933
444032
|
return {
|
|
@@ -443957,7 +444056,7 @@ function normalizeCronFileData(data) {
|
|
|
443957
444056
|
}
|
|
443958
444057
|
function readCronFile() {
|
|
443959
444058
|
const path31 = getCronFilePath();
|
|
443960
|
-
if (!
|
|
444059
|
+
if (!existsSync41(path31))
|
|
443961
444060
|
return emptyFile();
|
|
443962
444061
|
try {
|
|
443963
444062
|
const raw2 = readFileSync29(path31, "utf-8");
|
|
@@ -443972,11 +444071,11 @@ function readCronFile() {
|
|
|
443972
444071
|
function writeCronFile(data) {
|
|
443973
444072
|
const path31 = getCronFilePath();
|
|
443974
444073
|
const dir = getLettaDir();
|
|
443975
|
-
if (!
|
|
443976
|
-
|
|
444074
|
+
if (!existsSync41(dir)) {
|
|
444075
|
+
mkdirSync27(dir, { recursive: true });
|
|
443977
444076
|
}
|
|
443978
444077
|
const tmp = `${path31}.tmp`;
|
|
443979
|
-
|
|
444078
|
+
writeFileSync20(tmp, JSON.stringify(data, null, 2), { flush: true });
|
|
443980
444079
|
renameSync4(tmp, path31);
|
|
443981
444080
|
}
|
|
443982
444081
|
function readLinuxProcessIdentity(pid) {
|
|
@@ -444034,14 +444133,14 @@ function isProcessAlive(pid, owner) {
|
|
|
444034
444133
|
}
|
|
444035
444134
|
function readLockOwner(lockDir) {
|
|
444036
444135
|
try {
|
|
444037
|
-
const raw2 = readFileSync29(
|
|
444136
|
+
const raw2 = readFileSync29(join47(lockDir, LOCK_TOKEN_FILE), "utf-8");
|
|
444038
444137
|
return JSON.parse(raw2);
|
|
444039
444138
|
} catch {
|
|
444040
444139
|
return null;
|
|
444041
444140
|
}
|
|
444042
444141
|
}
|
|
444043
444142
|
function writeLockOwner(lockDir, owner) {
|
|
444044
|
-
|
|
444143
|
+
writeFileSync20(join47(lockDir, LOCK_TOKEN_FILE), JSON.stringify(owner));
|
|
444045
444144
|
}
|
|
444046
444145
|
function isLockStale(lockDir) {
|
|
444047
444146
|
const owner = readLockOwner(lockDir);
|
|
@@ -444068,7 +444167,7 @@ function acquireLock() {
|
|
|
444068
444167
|
const token2 = randomBytes(4).toString("hex");
|
|
444069
444168
|
while (Date.now() < deadline) {
|
|
444070
444169
|
try {
|
|
444071
|
-
|
|
444170
|
+
mkdirSync27(lockDir, { recursive: false });
|
|
444072
444171
|
const owner = {
|
|
444073
444172
|
pid: process.pid,
|
|
444074
444173
|
token: token2,
|
|
@@ -444313,11 +444412,11 @@ var init_cron_file = __esm(() => {
|
|
|
444313
444412
|
import {
|
|
444314
444413
|
appendFileSync as appendFileSync5,
|
|
444315
444414
|
chmodSync as chmodSync6,
|
|
444316
|
-
existsSync as
|
|
444317
|
-
mkdirSync as
|
|
444415
|
+
existsSync as existsSync42,
|
|
444416
|
+
mkdirSync as mkdirSync28,
|
|
444318
444417
|
readFileSync as readFileSync30,
|
|
444319
444418
|
statSync as statSync14,
|
|
444320
|
-
writeFileSync as
|
|
444419
|
+
writeFileSync as writeFileSync21
|
|
444321
444420
|
} from "node:fs";
|
|
444322
444421
|
import path31 from "node:path";
|
|
444323
444422
|
function assertSafeCronRunLogJobId(jobId) {
|
|
@@ -444367,7 +444466,7 @@ function pruneIfNeeded(filePath, opts) {
|
|
|
444367
444466
|
const lines = raw2.split(`
|
|
444368
444467
|
`).map((line) => line.trim()).filter(Boolean);
|
|
444369
444468
|
const kept = lines.slice(Math.max(0, lines.length - opts.keepLines));
|
|
444370
|
-
|
|
444469
|
+
writeFileSync21(filePath, `${kept.join(`
|
|
444371
444470
|
`)}
|
|
444372
444471
|
`, { mode: 384 });
|
|
444373
444472
|
setSecureFileMode(filePath);
|
|
@@ -444375,8 +444474,8 @@ function pruneIfNeeded(filePath, opts) {
|
|
|
444375
444474
|
function appendCronRunLog(filePath, entry, opts) {
|
|
444376
444475
|
const resolved = path31.resolve(filePath);
|
|
444377
444476
|
const runDir = path31.dirname(resolved);
|
|
444378
|
-
if (!
|
|
444379
|
-
|
|
444477
|
+
if (!existsSync42(runDir)) {
|
|
444478
|
+
mkdirSync28(runDir, { recursive: true, mode: 448 });
|
|
444380
444479
|
}
|
|
444381
444480
|
setSecureDirMode(runDir);
|
|
444382
444481
|
appendFileSync5(resolved, `${JSON.stringify(entry)}
|
|
@@ -445692,9 +445791,9 @@ __export(exports_custom, {
|
|
|
445692
445791
|
GLOBAL_COMMANDS_DIR: () => GLOBAL_COMMANDS_DIR,
|
|
445693
445792
|
COMMANDS_DIR: () => COMMANDS_DIR
|
|
445694
445793
|
});
|
|
445695
|
-
import { existsSync as
|
|
445794
|
+
import { existsSync as existsSync43 } from "node:fs";
|
|
445696
445795
|
import { readdir as readdir9, readFile as readFile16 } from "node:fs/promises";
|
|
445697
|
-
import { basename as basename20, dirname as dirname24, join as
|
|
445796
|
+
import { basename as basename20, dirname as dirname24, join as join48 } from "node:path";
|
|
445698
445797
|
async function getCustomCommands() {
|
|
445699
445798
|
if (cachedCommands !== null) {
|
|
445700
445799
|
return cachedCommands;
|
|
@@ -445705,7 +445804,7 @@ async function getCustomCommands() {
|
|
|
445705
445804
|
function refreshCustomCommands() {
|
|
445706
445805
|
cachedCommands = null;
|
|
445707
445806
|
}
|
|
445708
|
-
async function discoverCustomCommands(projectPath =
|
|
445807
|
+
async function discoverCustomCommands(projectPath = join48(process.cwd(), COMMANDS_DIR)) {
|
|
445709
445808
|
const commandsById = new Map;
|
|
445710
445809
|
const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
|
|
445711
445810
|
for (const cmd of userCommands) {
|
|
@@ -445726,7 +445825,7 @@ async function discoverCustomCommands(projectPath = join47(process.cwd(), COMMAN
|
|
|
445726
445825
|
return result;
|
|
445727
445826
|
}
|
|
445728
445827
|
async function discoverFromDirectory(dirPath, source2) {
|
|
445729
|
-
if (!
|
|
445828
|
+
if (!existsSync43(dirPath)) {
|
|
445730
445829
|
return [];
|
|
445731
445830
|
}
|
|
445732
445831
|
const commands = [];
|
|
@@ -445737,7 +445836,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source2) {
|
|
|
445737
445836
|
try {
|
|
445738
445837
|
const entries = await readdir9(currentPath, { withFileTypes: true });
|
|
445739
445838
|
for (const entry of entries) {
|
|
445740
|
-
const fullPath =
|
|
445839
|
+
const fullPath = join48(currentPath, entry.name);
|
|
445741
445840
|
if (entry.isDirectory()) {
|
|
445742
445841
|
await findCommandFiles(fullPath, rootPath, commands, source2);
|
|
445743
445842
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -445822,7 +445921,7 @@ async function findCustomCommand(commandName) {
|
|
|
445822
445921
|
}
|
|
445823
445922
|
var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
|
|
445824
445923
|
var init_custom = __esm(() => {
|
|
445825
|
-
GLOBAL_COMMANDS_DIR =
|
|
445924
|
+
GLOBAL_COMMANDS_DIR = join48(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
|
|
445826
445925
|
});
|
|
445827
445926
|
|
|
445828
445927
|
// src/cli/helpers/init-command.ts
|
|
@@ -445912,7 +446011,7 @@ var init_init_command = __esm(() => {
|
|
|
445912
446011
|
|
|
445913
446012
|
// src/cli/helpers/skill-name-frontmatter-repair.ts
|
|
445914
446013
|
import { readdir as readdir10, readFile as readFile17, stat as stat12, writeFile as writeFile14 } from "node:fs/promises";
|
|
445915
|
-
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";
|
|
445916
446015
|
async function pathExists(path32) {
|
|
445917
446016
|
try {
|
|
445918
446017
|
await stat12(path32);
|
|
@@ -445928,7 +446027,7 @@ async function findSkillMarkdownFiles(root2) {
|
|
|
445928
446027
|
if (entry.name === ".git" || entry.name === "node_modules") {
|
|
445929
446028
|
continue;
|
|
445930
446029
|
}
|
|
445931
|
-
const fullPath =
|
|
446030
|
+
const fullPath = join49(root2, entry.name);
|
|
445932
446031
|
if (entry.isSymbolicLink()) {
|
|
445933
446032
|
continue;
|
|
445934
446033
|
}
|
|
@@ -446000,7 +446099,7 @@ async function repairMissingSkillNameFrontmatter(memoryDir) {
|
|
|
446000
446099
|
if (!memoryDir) {
|
|
446001
446100
|
return result;
|
|
446002
446101
|
}
|
|
446003
|
-
const skillsDir =
|
|
446102
|
+
const skillsDir = join49(memoryDir, "skills");
|
|
446004
446103
|
if (!await pathExists(skillsDir)) {
|
|
446005
446104
|
return result;
|
|
446006
446105
|
}
|
|
@@ -449002,7 +449101,7 @@ var init_accumulator = __esm(async () => {
|
|
|
449002
449101
|
});
|
|
449003
449102
|
|
|
449004
449103
|
// src/utils/tui-perf.ts
|
|
449005
|
-
import { appendFileSync as appendFileSync6, mkdirSync as
|
|
449104
|
+
import { appendFileSync as appendFileSync6, mkdirSync as mkdirSync29 } from "node:fs";
|
|
449006
449105
|
import { dirname as dirname26 } from "node:path";
|
|
449007
449106
|
function ensureExitHook() {
|
|
449008
449107
|
if (tuiPerfExitHookRegistered) {
|
|
@@ -449094,7 +449193,7 @@ function flushTuiPerfTelemetry() {
|
|
|
449094
449193
|
try {
|
|
449095
449194
|
const dir = dirname26(filePath);
|
|
449096
449195
|
if (tuiPerfFileDirEnsured !== dir) {
|
|
449097
|
-
|
|
449196
|
+
mkdirSync29(dir, { recursive: true });
|
|
449098
449197
|
tuiPerfFileDirEnsured = dir;
|
|
449099
449198
|
}
|
|
449100
449199
|
appendFileSync6(filePath, `${JSON.stringify({
|
|
@@ -449125,14 +449224,14 @@ var init_tui_perf = __esm(() => {
|
|
|
449125
449224
|
|
|
449126
449225
|
// src/cli/helpers/chunk-log.ts
|
|
449127
449226
|
import {
|
|
449128
|
-
existsSync as
|
|
449129
|
-
mkdirSync as
|
|
449227
|
+
existsSync as existsSync44,
|
|
449228
|
+
mkdirSync as mkdirSync30,
|
|
449130
449229
|
readdirSync as readdirSync14,
|
|
449131
449230
|
unlinkSync as unlinkSync6,
|
|
449132
|
-
writeFileSync as
|
|
449231
|
+
writeFileSync as writeFileSync22
|
|
449133
449232
|
} from "node:fs";
|
|
449134
449233
|
import { homedir as homedir29 } from "node:os";
|
|
449135
|
-
import { join as
|
|
449234
|
+
import { join as join50 } from "node:path";
|
|
449136
449235
|
function truncateStr(value, maxLen) {
|
|
449137
449236
|
if (value === null || value === undefined)
|
|
449138
449237
|
return "";
|
|
@@ -449196,8 +449295,8 @@ class ChunkLog {
|
|
|
449196
449295
|
agentDir = null;
|
|
449197
449296
|
dirCreated = false;
|
|
449198
449297
|
init(agentId, sessionId) {
|
|
449199
|
-
this.agentDir =
|
|
449200
|
-
this.logPath =
|
|
449298
|
+
this.agentDir = join50(LOG_BASE_DIR, agentId);
|
|
449299
|
+
this.logPath = join50(this.agentDir, `${sessionId}.jsonl`);
|
|
449201
449300
|
this.buffer = [];
|
|
449202
449301
|
this.dirty = false;
|
|
449203
449302
|
this.dirCreated = false;
|
|
@@ -449226,8 +449325,8 @@ class ChunkLog {
|
|
|
449226
449325
|
if (this.dirCreated || !this.agentDir)
|
|
449227
449326
|
return;
|
|
449228
449327
|
try {
|
|
449229
|
-
if (!
|
|
449230
|
-
|
|
449328
|
+
if (!existsSync44(this.agentDir)) {
|
|
449329
|
+
mkdirSync30(this.agentDir, { recursive: true });
|
|
449231
449330
|
}
|
|
449232
449331
|
this.dirCreated = true;
|
|
449233
449332
|
} catch (e2) {
|
|
@@ -449241,7 +449340,7 @@ class ChunkLog {
|
|
|
449241
449340
|
try {
|
|
449242
449341
|
const content = this.buffer.map((entry) => JSON.stringify(entry)).join(`
|
|
449243
449342
|
`);
|
|
449244
|
-
|
|
449343
|
+
writeFileSync22(this.logPath, `${content}
|
|
449245
449344
|
`, "utf8");
|
|
449246
449345
|
} catch (e2) {
|
|
449247
449346
|
debugWarn("chunkLog", `Failed to write ${this.logPath}: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -449251,14 +449350,14 @@ class ChunkLog {
|
|
|
449251
449350
|
if (!this.agentDir)
|
|
449252
449351
|
return;
|
|
449253
449352
|
try {
|
|
449254
|
-
if (!
|
|
449353
|
+
if (!existsSync44(this.agentDir))
|
|
449255
449354
|
return;
|
|
449256
449355
|
const files = readdirSync14(this.agentDir).filter((f4) => f4.endsWith(".jsonl")).sort();
|
|
449257
449356
|
if (files.length >= MAX_SESSION_FILES2) {
|
|
449258
449357
|
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES2 + 1);
|
|
449259
449358
|
for (const file3 of toDelete) {
|
|
449260
449359
|
try {
|
|
449261
|
-
unlinkSync6(
|
|
449360
|
+
unlinkSync6(join50(this.agentDir, file3));
|
|
449262
449361
|
} catch (e2) {
|
|
449263
449362
|
debugWarn("chunkLog", `Failed to delete old session log ${file3}: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
449264
449363
|
}
|
|
@@ -449272,7 +449371,7 @@ class ChunkLog {
|
|
|
449272
449371
|
var MAX_ENTRIES = 100, CONTENT_TRUNCATE_LEN = 200, MAX_SESSION_FILES2 = 5, LOG_BASE_DIR, chunkLog;
|
|
449273
449372
|
var init_chunk_log = __esm(() => {
|
|
449274
449373
|
init_debug();
|
|
449275
|
-
LOG_BASE_DIR =
|
|
449374
|
+
LOG_BASE_DIR = join50(homedir29(), ".letta", "logs", "chunk-logs");
|
|
449276
449375
|
chunkLog = new ChunkLog;
|
|
449277
449376
|
});
|
|
449278
449377
|
|
|
@@ -458715,7 +458814,7 @@ var init_commands2 = __esm(async () => {
|
|
|
458715
458814
|
});
|
|
458716
458815
|
|
|
458717
458816
|
// src/channels/custom/scaffolding.ts
|
|
458718
|
-
import { existsSync as
|
|
458817
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync31, rmSync as rmSync9, writeFileSync as writeFileSync23 } from "node:fs";
|
|
458719
458818
|
function removeUserPlugin(channelId) {
|
|
458720
458819
|
if (FIRST_PARTY_SET.has(channelId)) {
|
|
458721
458820
|
return;
|
|
@@ -458724,7 +458823,7 @@ function removeUserPlugin(channelId) {
|
|
|
458724
458823
|
return;
|
|
458725
458824
|
}
|
|
458726
458825
|
const channelDir = getChannelDir(channelId);
|
|
458727
|
-
if (!
|
|
458826
|
+
if (!existsSync45(channelDir)) {
|
|
458728
458827
|
return;
|
|
458729
458828
|
}
|
|
458730
458829
|
try {
|
|
@@ -459526,6 +459625,55 @@ var init_toolset_labels = __esm(() => {
|
|
|
459526
459625
|
};
|
|
459527
459626
|
});
|
|
459528
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
|
+
|
|
459529
459677
|
// src/websocket/listener/commands/model-toolset.ts
|
|
459530
459678
|
function inferProviderTypeFromRegistryHandle(modelHandle) {
|
|
459531
459679
|
const provider = modelHandle.split("/")[0];
|
|
@@ -459588,22 +459736,34 @@ async function getCurrentModelStatusForRuntime(params) {
|
|
|
459588
459736
|
};
|
|
459589
459737
|
}
|
|
459590
459738
|
function resolveModelForUpdate(payload) {
|
|
459739
|
+
const availableModels = getCachedAvailableModels() ?? [];
|
|
459591
459740
|
if (typeof payload.model_id === "string" && payload.model_id.length > 0) {
|
|
459592
459741
|
const byId = getModelInfo(payload.model_id);
|
|
459593
459742
|
if (byId) {
|
|
459594
459743
|
const explicitHandle = typeof payload.model_handle === "string" && payload.model_handle.length > 0 ? payload.model_handle : null;
|
|
459595
459744
|
const updateArgs = byId.updateArgs && typeof byId.updateArgs === "object" ? { ...byId.updateArgs } : undefined;
|
|
459596
459745
|
const providerType = inferProviderTypeFromRegistryHandle(byId.handle);
|
|
459597
|
-
|
|
459598
|
-
|
|
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;
|
|
459599
459749
|
}
|
|
459600
459750
|
return {
|
|
459601
459751
|
id: byId.id,
|
|
459602
|
-
handle: explicitHandle ?? byId.handle,
|
|
459752
|
+
handle: explicitHandle ?? availableModel?.handle ?? byId.handle,
|
|
459603
459753
|
label: byId.label,
|
|
459604
459754
|
updateArgs
|
|
459605
459755
|
};
|
|
459606
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
|
+
}
|
|
459607
459767
|
}
|
|
459608
459768
|
if (typeof payload.model_handle === "string" && payload.model_handle.length > 0) {
|
|
459609
459769
|
const exactByHandle = models2.find((m4) => m4.handle === payload.model_handle);
|
|
@@ -459615,10 +459775,11 @@ function resolveModelForUpdate(payload) {
|
|
|
459615
459775
|
updateArgs: exactByHandle.updateArgs && typeof exactByHandle.updateArgs === "object" ? { ...exactByHandle.updateArgs } : undefined
|
|
459616
459776
|
};
|
|
459617
459777
|
}
|
|
459778
|
+
const nativeModel = availableModels.find((model) => model.handle === payload.model_handle);
|
|
459618
459779
|
return {
|
|
459619
459780
|
id: payload.model_handle,
|
|
459620
459781
|
handle: payload.model_handle,
|
|
459621
|
-
label: payload.model_handle,
|
|
459782
|
+
label: nativeModel?.label ?? payload.model_handle,
|
|
459622
459783
|
updateArgs: undefined
|
|
459623
459784
|
};
|
|
459624
459785
|
}
|
|
@@ -459829,25 +459990,13 @@ async function applyToolsetUpdateForRuntime(params) {
|
|
|
459829
459990
|
current_toolset_preference: toolsetPreference
|
|
459830
459991
|
};
|
|
459831
459992
|
}
|
|
459832
|
-
function buildListModelsEntries() {
|
|
459833
|
-
return models2.map((model) => ({
|
|
459834
|
-
id: model.id,
|
|
459835
|
-
handle: model.handle,
|
|
459836
|
-
label: model.label,
|
|
459837
|
-
description: model.description,
|
|
459838
|
-
...typeof model.isDefault === "boolean" ? { isDefault: model.isDefault } : {},
|
|
459839
|
-
...typeof model.isFeatured === "boolean" ? { isFeatured: model.isFeatured } : {},
|
|
459840
|
-
...typeof model.free === "boolean" ? { free: model.free } : {},
|
|
459841
|
-
...model.updateArgs && typeof model.updateArgs === "object" ? { updateArgs: model.updateArgs } : {}
|
|
459842
|
-
}));
|
|
459843
|
-
}
|
|
459844
459993
|
async function buildListModelsResponse(requestId, options3 = {}) {
|
|
459845
|
-
const entries = buildListModelsEntries();
|
|
459846
459994
|
const [handlesResult, providersResult] = await Promise.allSettled([
|
|
459847
459995
|
getAvailableModelHandles(options3.forceRefresh === true ? { forceRefresh: true } : undefined),
|
|
459848
459996
|
listProviders2()
|
|
459849
459997
|
]);
|
|
459850
459998
|
const availableHandles = handlesResult.status === "fulfilled" ? [...handlesResult.value.handles] : null;
|
|
459999
|
+
const entries = buildListModelsEntries(handlesResult.status === "fulfilled" ? handlesResult.value.models : []);
|
|
459851
460000
|
const providers = providersResult.status === "fulfilled" ? providersResult.value : [];
|
|
459852
460001
|
const byokProviderAliases = buildByokProviderAliases(providers);
|
|
459853
460002
|
return {
|
|
@@ -459965,6 +460114,7 @@ var init_model_toolset = __esm(async () => {
|
|
|
459965
460114
|
init_byok_providers();
|
|
459966
460115
|
init_settings_manager();
|
|
459967
460116
|
init_toolset_labels();
|
|
460117
|
+
init_model_catalog2();
|
|
459968
460118
|
await __promiseAll([
|
|
459969
460119
|
init_toolset(),
|
|
459970
460120
|
init_mod_adapter2(),
|
|
@@ -462941,7 +463091,7 @@ __export(exports_memory_scanner, {
|
|
|
462941
463091
|
getFileNodes: () => getFileNodes
|
|
462942
463092
|
});
|
|
462943
463093
|
import { readdirSync as readdirSync15, readFileSync as readFileSync31, statSync as statSync15 } from "node:fs";
|
|
462944
|
-
import { join as
|
|
463094
|
+
import { join as join51, relative as relative12 } from "node:path";
|
|
462945
463095
|
function scanMemoryFilesystem(memoryRoot) {
|
|
462946
463096
|
const nodes = [];
|
|
462947
463097
|
const scanDir = (dir, depth, parentIsLast) => {
|
|
@@ -462953,8 +463103,8 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
462953
463103
|
}
|
|
462954
463104
|
const filtered = entries.filter((name) => !name.startsWith("."));
|
|
462955
463105
|
const sorted = filtered.sort((a2, b3) => {
|
|
462956
|
-
const aPath =
|
|
462957
|
-
const bPath =
|
|
463106
|
+
const aPath = join51(dir, a2);
|
|
463107
|
+
const bPath = join51(dir, b3);
|
|
462958
463108
|
let aIsDir = false;
|
|
462959
463109
|
let bIsDir = false;
|
|
462960
463110
|
try {
|
|
@@ -462974,7 +463124,7 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
462974
463124
|
return a2.localeCompare(b3);
|
|
462975
463125
|
});
|
|
462976
463126
|
sorted.forEach((name, index) => {
|
|
462977
|
-
const fullPath =
|
|
463127
|
+
const fullPath = join51(dir, name);
|
|
462978
463128
|
let isDir = false;
|
|
462979
463129
|
try {
|
|
462980
463130
|
isDir = statSync15(fullPath).isDirectory();
|
|
@@ -463076,10 +463226,10 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
463076
463226
|
const isMemfsEnabledOnServer2 = overrides.isMemfsEnabledOnServer ?? actualIsMemfsEnabledOnServer;
|
|
463077
463227
|
const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memory_scanner(), exports_memory_scanner));
|
|
463078
463228
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
|
|
463079
|
-
const { existsSync:
|
|
463080
|
-
const { join:
|
|
463229
|
+
const { existsSync: existsSync46, statSync: statSync16 } = await import("node:fs");
|
|
463230
|
+
const { join: join52, posix: posix4 } = await import("node:path");
|
|
463081
463231
|
const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
|
|
463082
|
-
let memfsInitialized =
|
|
463232
|
+
let memfsInitialized = existsSync46(join52(memoryRoot, ".git"));
|
|
463083
463233
|
const memfsEnabled = memfsInitialized ? true : await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463084
463234
|
if (!memfsEnabled) {
|
|
463085
463235
|
safeSocketSend(socket, {
|
|
@@ -463097,7 +463247,7 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
463097
463247
|
await ensureLocalMemfsCheckout2(parsed.agent_id, {
|
|
463098
463248
|
pullOnExistingRepo: true
|
|
463099
463249
|
});
|
|
463100
|
-
memfsInitialized =
|
|
463250
|
+
memfsInitialized = existsSync46(join52(memoryRoot, ".git"));
|
|
463101
463251
|
if (!memfsInitialized) {
|
|
463102
463252
|
throw new Error("MemFS is enabled, but the local memory checkout could not be initialized.");
|
|
463103
463253
|
}
|
|
@@ -463397,27 +463547,27 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
463397
463547
|
isMemfsEnabledOnServer: isMemfsEnabledOnServer2
|
|
463398
463548
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
463399
463549
|
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
463400
|
-
const { existsSync:
|
|
463401
|
-
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");
|
|
463402
463552
|
if (isAbsolute24(parsed.path) || parsed.path.length === 0) {
|
|
463403
463553
|
sendFailure("path must be a non-empty relative path");
|
|
463404
463554
|
return;
|
|
463405
463555
|
}
|
|
463406
463556
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
463407
|
-
const absolutePath = normalize5(
|
|
463557
|
+
const absolutePath = normalize5(join52(memoryRoot, parsed.path));
|
|
463408
463558
|
const rel = relative13(memoryRoot, absolutePath);
|
|
463409
463559
|
if (rel.startsWith("..") || rel === "" || isAbsolute24(rel) || rel.split(sep6).includes("..")) {
|
|
463410
463560
|
sendFailure("path must resolve inside the memory root");
|
|
463411
463561
|
return;
|
|
463412
463562
|
}
|
|
463413
|
-
if (!
|
|
463563
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463414
463564
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463415
463565
|
if (!enabled) {
|
|
463416
463566
|
sendFailure("memfs is not enabled for this agent");
|
|
463417
463567
|
return;
|
|
463418
463568
|
}
|
|
463419
463569
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
463420
|
-
if (!
|
|
463570
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463421
463571
|
sendFailure("failed to initialize local memory checkout");
|
|
463422
463572
|
return;
|
|
463423
463573
|
}
|
|
@@ -463463,27 +463613,27 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
463463
463613
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
463464
463614
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
463465
463615
|
const { writeFile: writeFile15, mkdir: mkdir13 } = await import("node:fs/promises");
|
|
463466
|
-
const { existsSync:
|
|
463467
|
-
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");
|
|
463468
463618
|
if (isAbsolute24(parsed.path) || parsed.path.length === 0) {
|
|
463469
463619
|
sendFailure("write_memory_file: path must be a non-empty relative path");
|
|
463470
463620
|
return;
|
|
463471
463621
|
}
|
|
463472
463622
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
463473
|
-
const absolutePath = normalize5(
|
|
463623
|
+
const absolutePath = normalize5(join52(memoryRoot, parsed.path));
|
|
463474
463624
|
const rel = relative13(memoryRoot, absolutePath);
|
|
463475
463625
|
if (rel.startsWith("..") || rel === "" || isAbsolute24(rel) || rel.split(sep6).includes("..")) {
|
|
463476
463626
|
sendFailure("write_memory_file: path must resolve inside the memory root");
|
|
463477
463627
|
return;
|
|
463478
463628
|
}
|
|
463479
|
-
if (!
|
|
463629
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463480
463630
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463481
463631
|
if (!enabled) {
|
|
463482
463632
|
sendFailure("write_memory_file: memfs is not enabled for this agent");
|
|
463483
463633
|
return;
|
|
463484
463634
|
}
|
|
463485
463635
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
463486
|
-
if (!
|
|
463636
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463487
463637
|
sendFailure("write_memory_file: failed to initialize local memory checkout");
|
|
463488
463638
|
return;
|
|
463489
463639
|
}
|
|
@@ -463561,34 +463711,34 @@ function handleMemoryProtocolCommand(parsed, context4) {
|
|
|
463561
463711
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
463562
463712
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
463563
463713
|
const { unlink: unlink5 } = await import("node:fs/promises");
|
|
463564
|
-
const { existsSync:
|
|
463565
|
-
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");
|
|
463566
463716
|
if (isAbsolute24(parsed.path) || parsed.path.length === 0) {
|
|
463567
463717
|
sendFailure("delete_memory_file: path must be a non-empty relative path");
|
|
463568
463718
|
return;
|
|
463569
463719
|
}
|
|
463570
463720
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
463571
|
-
const absolutePath = normalize5(
|
|
463721
|
+
const absolutePath = normalize5(join52(memoryRoot, parsed.path));
|
|
463572
463722
|
const rel = relative13(memoryRoot, absolutePath);
|
|
463573
463723
|
if (rel.startsWith("..") || rel === "" || isAbsolute24(rel) || rel.split(sep6).includes("..")) {
|
|
463574
463724
|
sendFailure("delete_memory_file: path must resolve inside the memory root");
|
|
463575
463725
|
return;
|
|
463576
463726
|
}
|
|
463577
|
-
if (!
|
|
463727
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463578
463728
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
463579
463729
|
if (!enabled) {
|
|
463580
463730
|
sendFailure("delete_memory_file: memfs is not enabled for this agent");
|
|
463581
463731
|
return;
|
|
463582
463732
|
}
|
|
463583
463733
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
463584
|
-
if (!
|
|
463734
|
+
if (!existsSync46(join52(memoryRoot, ".git"))) {
|
|
463585
463735
|
sendFailure("delete_memory_file: failed to initialize local memory checkout");
|
|
463586
463736
|
return;
|
|
463587
463737
|
}
|
|
463588
463738
|
}
|
|
463589
463739
|
const pathspec = rel.split(sep6).join("/");
|
|
463590
463740
|
const removeIfPresent = async () => {
|
|
463591
|
-
if (!
|
|
463741
|
+
if (!existsSync46(absolutePath))
|
|
463592
463742
|
return false;
|
|
463593
463743
|
await unlink5(absolutePath);
|
|
463594
463744
|
return true;
|
|
@@ -463994,19 +464144,19 @@ function emitSkillsUpdated(socket, safeSocketSend) {
|
|
|
463994
464144
|
}
|
|
463995
464145
|
async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
463996
464146
|
const {
|
|
463997
|
-
existsSync:
|
|
464147
|
+
existsSync: existsSync46,
|
|
463998
464148
|
lstatSync: lstatSync3,
|
|
463999
|
-
mkdirSync:
|
|
464149
|
+
mkdirSync: mkdirSync32,
|
|
464000
464150
|
rmdirSync,
|
|
464001
464151
|
symlinkSync: symlinkSync2,
|
|
464002
464152
|
unlinkSync: unlinkSync7
|
|
464003
464153
|
} = await import("node:fs");
|
|
464004
|
-
const { basename: basename25, join:
|
|
464005
|
-
const lettaHome = process.env.LETTA_HOME ||
|
|
464006
|
-
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");
|
|
464007
464157
|
if (parsed.type === "skill_enable") {
|
|
464008
464158
|
try {
|
|
464009
|
-
if (!
|
|
464159
|
+
if (!existsSync46(parsed.skill_path)) {
|
|
464010
464160
|
safeSocketSend(socket, {
|
|
464011
464161
|
type: "skill_enable_response",
|
|
464012
464162
|
request_id: parsed.request_id,
|
|
@@ -464015,8 +464165,8 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
464015
464165
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
464016
464166
|
return true;
|
|
464017
464167
|
}
|
|
464018
|
-
const skillMdPath =
|
|
464019
|
-
if (!
|
|
464168
|
+
const skillMdPath = join52(parsed.skill_path, "SKILL.md");
|
|
464169
|
+
if (!existsSync46(skillMdPath)) {
|
|
464020
464170
|
safeSocketSend(socket, {
|
|
464021
464171
|
type: "skill_enable_response",
|
|
464022
464172
|
request_id: parsed.request_id,
|
|
@@ -464026,9 +464176,9 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
464026
464176
|
return true;
|
|
464027
464177
|
}
|
|
464028
464178
|
const linkName = basename25(parsed.skill_path);
|
|
464029
|
-
const linkPath =
|
|
464030
|
-
|
|
464031
|
-
if (
|
|
464179
|
+
const linkPath = join52(globalSkillsDir, linkName);
|
|
464180
|
+
mkdirSync32(globalSkillsDir, { recursive: true });
|
|
464181
|
+
if (existsSync46(linkPath)) {
|
|
464032
464182
|
const stat14 = lstatSync3(linkPath);
|
|
464033
464183
|
if (stat14.isSymbolicLink()) {
|
|
464034
464184
|
if (process.platform === "win32") {
|
|
@@ -464069,8 +464219,8 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
464069
464219
|
}
|
|
464070
464220
|
if (parsed.type === "skill_disable") {
|
|
464071
464221
|
try {
|
|
464072
|
-
const linkPath =
|
|
464073
|
-
if (!
|
|
464222
|
+
const linkPath = join52(globalSkillsDir, parsed.name);
|
|
464223
|
+
if (!existsSync46(linkPath)) {
|
|
464074
464224
|
safeSocketSend(socket, {
|
|
464075
464225
|
type: "skill_disable_response",
|
|
464076
464226
|
request_id: parsed.request_id,
|
|
@@ -469061,6 +469211,7 @@ function createLegacyTestRuntime() {
|
|
|
469061
469211
|
}
|
|
469062
469212
|
var __listenClientTestUtils;
|
|
469063
469213
|
var init_client7 = __esm(async () => {
|
|
469214
|
+
init_model_catalog2();
|
|
469064
469215
|
init_cwd();
|
|
469065
469216
|
init_runtime6();
|
|
469066
469217
|
await __promiseAll([
|
|
@@ -469209,10 +469360,10 @@ var init_listen_client = __esm(async () => {
|
|
|
469209
469360
|
});
|
|
469210
469361
|
|
|
469211
469362
|
// src/backend/local/transcript-search.ts
|
|
469212
|
-
import { existsSync as
|
|
469213
|
-
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";
|
|
469214
469365
|
function readJsonFile3(path37) {
|
|
469215
|
-
if (!
|
|
469366
|
+
if (!existsSync49(path37))
|
|
469216
469367
|
return;
|
|
469217
469368
|
try {
|
|
469218
469369
|
return JSON.parse(readFileSync33(path37, "utf8"));
|
|
@@ -469221,7 +469372,7 @@ function readJsonFile3(path37) {
|
|
|
469221
469372
|
}
|
|
469222
469373
|
}
|
|
469223
469374
|
function readJsonlFile2(path37) {
|
|
469224
|
-
if (!
|
|
469375
|
+
if (!existsSync49(path37))
|
|
469225
469376
|
return [];
|
|
469226
469377
|
try {
|
|
469227
469378
|
return readFileSync33(path37, "utf8").split(`
|
|
@@ -469431,11 +469582,11 @@ function collectConversationMessages(input) {
|
|
|
469431
469582
|
return [];
|
|
469432
469583
|
if (input.conversationId && conversation.id !== input.conversationId)
|
|
469433
469584
|
return [];
|
|
469434
|
-
const messagesPath =
|
|
469585
|
+
const messagesPath = join57(conversationDir, "messages.jsonl");
|
|
469435
469586
|
const rows = readJsonlFile2(messagesPath);
|
|
469436
469587
|
if (rows.length === 0)
|
|
469437
469588
|
return [];
|
|
469438
|
-
const manifest2 = readJsonFile3(
|
|
469589
|
+
const manifest2 = readJsonFile3(join57(conversationDir, "manifest.json"));
|
|
469439
469590
|
const format5 = transcriptFormat(manifest2, rows);
|
|
469440
469591
|
if (!format5)
|
|
469441
469592
|
return [];
|
|
@@ -469456,11 +469607,11 @@ function collectConversationMessages(input) {
|
|
|
469456
469607
|
});
|
|
469457
469608
|
}
|
|
469458
469609
|
function conversationDirectories(storageDir) {
|
|
469459
|
-
const conversationsDir =
|
|
469460
|
-
if (!
|
|
469610
|
+
const conversationsDir = join57(storageDir, "conversations");
|
|
469611
|
+
if (!existsSync49(conversationsDir))
|
|
469461
469612
|
return [];
|
|
469462
469613
|
try {
|
|
469463
|
-
return readdirSync18(conversationsDir).map((entry) =>
|
|
469614
|
+
return readdirSync18(conversationsDir).map((entry) => join57(conversationsDir, entry)).filter((entryPath) => statSync17(entryPath).isDirectory());
|
|
469464
469615
|
} catch {
|
|
469465
469616
|
return [];
|
|
469466
469617
|
}
|
|
@@ -469484,7 +469635,7 @@ function searchLocalTranscriptMessages(storageDir, body3) {
|
|
|
469484
469635
|
const endDate = typeof body3.end_date === "string" ? body3.end_date : undefined;
|
|
469485
469636
|
const includeHidden = body3.include_hidden === true;
|
|
469486
469637
|
const records = conversationDirectories(storageDir).flatMap((conversationDir) => {
|
|
469487
|
-
const conversation = conversationSearchRecord(readJsonFile3(
|
|
469638
|
+
const conversation = conversationSearchRecord(readJsonFile3(join57(conversationDir, "conversation.json")));
|
|
469488
469639
|
if (!conversation)
|
|
469489
469640
|
return [];
|
|
469490
469641
|
if (conversation.hidden && !includeHidden)
|
|
@@ -471356,14 +471507,14 @@ __export(exports_debug2, {
|
|
|
471356
471507
|
});
|
|
471357
471508
|
import {
|
|
471358
471509
|
appendFileSync as appendFileSync8,
|
|
471359
|
-
existsSync as
|
|
471360
|
-
mkdirSync as
|
|
471510
|
+
existsSync as existsSync53,
|
|
471511
|
+
mkdirSync as mkdirSync37,
|
|
471361
471512
|
readdirSync as readdirSync20,
|
|
471362
471513
|
readFileSync as readFileSync37,
|
|
471363
471514
|
unlinkSync as unlinkSync8
|
|
471364
471515
|
} from "node:fs";
|
|
471365
471516
|
import { homedir as homedir33 } from "node:os";
|
|
471366
|
-
import { join as
|
|
471517
|
+
import { join as join61 } from "node:path";
|
|
471367
471518
|
import { format as format5 } from "node:util";
|
|
471368
471519
|
function isDebugEnabled2() {
|
|
471369
471520
|
const lettaDebug = process.env.LETTA_DEBUG;
|
|
@@ -471394,8 +471545,8 @@ class DebugLogFile2 {
|
|
|
471394
471545
|
const telem = process.env.LETTA_CODE_TELEM;
|
|
471395
471546
|
if (telem === "0" || telem === "false")
|
|
471396
471547
|
return;
|
|
471397
|
-
this.agentDir =
|
|
471398
|
-
this.logPath =
|
|
471548
|
+
this.agentDir = join61(DEBUG_LOG_DIR2, agentId);
|
|
471549
|
+
this.logPath = join61(this.agentDir, `${sessionId}.log`);
|
|
471399
471550
|
this.dirCreated = false;
|
|
471400
471551
|
this.pruneOldSessions();
|
|
471401
471552
|
}
|
|
@@ -471411,7 +471562,7 @@ class DebugLogFile2 {
|
|
|
471411
471562
|
if (!this.logPath)
|
|
471412
471563
|
return;
|
|
471413
471564
|
try {
|
|
471414
|
-
if (!
|
|
471565
|
+
if (!existsSync53(this.logPath))
|
|
471415
471566
|
return;
|
|
471416
471567
|
const content = readFileSync37(this.logPath, "utf8");
|
|
471417
471568
|
const lines = content.trimEnd().split(`
|
|
@@ -471426,8 +471577,8 @@ class DebugLogFile2 {
|
|
|
471426
471577
|
if (this.dirCreated || !this.agentDir)
|
|
471427
471578
|
return;
|
|
471428
471579
|
try {
|
|
471429
|
-
if (!
|
|
471430
|
-
|
|
471580
|
+
if (!existsSync53(this.agentDir)) {
|
|
471581
|
+
mkdirSync37(this.agentDir, { recursive: true });
|
|
471431
471582
|
}
|
|
471432
471583
|
this.dirCreated = true;
|
|
471433
471584
|
} catch {}
|
|
@@ -471436,14 +471587,14 @@ class DebugLogFile2 {
|
|
|
471436
471587
|
if (!this.agentDir)
|
|
471437
471588
|
return;
|
|
471438
471589
|
try {
|
|
471439
|
-
if (!
|
|
471590
|
+
if (!existsSync53(this.agentDir))
|
|
471440
471591
|
return;
|
|
471441
471592
|
const files = readdirSync20(this.agentDir).filter((f4) => f4.endsWith(".log")).sort();
|
|
471442
471593
|
if (files.length >= MAX_SESSION_FILES3) {
|
|
471443
471594
|
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES3 + 1);
|
|
471444
471595
|
for (const file3 of toDelete) {
|
|
471445
471596
|
try {
|
|
471446
|
-
unlinkSync8(
|
|
471597
|
+
unlinkSync8(join61(this.agentDir, file3));
|
|
471447
471598
|
} catch {}
|
|
471448
471599
|
}
|
|
471449
471600
|
}
|
|
@@ -471468,7 +471619,7 @@ function debugWarn2(prefix, message, ...args) {
|
|
|
471468
471619
|
}
|
|
471469
471620
|
var DEBUG_LOG_DIR2, MAX_SESSION_FILES3 = 5, DEFAULT_TAIL_LINES2 = 50, debugLogFile2;
|
|
471470
471621
|
var init_debug2 = __esm(() => {
|
|
471471
|
-
DEBUG_LOG_DIR2 =
|
|
471622
|
+
DEBUG_LOG_DIR2 = join61(homedir33(), ".letta", "logs", "debug");
|
|
471472
471623
|
debugLogFile2 = new DebugLogFile2;
|
|
471473
471624
|
});
|
|
471474
471625
|
|
|
@@ -471502,16 +471653,16 @@ __export(exports_skills3, {
|
|
|
471502
471653
|
PROJECT_SKILLS_DIR: () => PROJECT_SKILLS_DIR2,
|
|
471503
471654
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
471504
471655
|
});
|
|
471505
|
-
import { existsSync as
|
|
471656
|
+
import { existsSync as existsSync54 } from "node:fs";
|
|
471506
471657
|
import { readdir as readdir15, readFile as readFile22, realpath as realpath6, stat as stat15 } from "node:fs/promises";
|
|
471507
|
-
import { dirname as dirname31, join as
|
|
471658
|
+
import { dirname as dirname31, join as join62 } from "node:path";
|
|
471508
471659
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
471509
471660
|
function getBundledSkillsPath2() {
|
|
471510
471661
|
const thisDir = dirname31(fileURLToPath8(import.meta.url));
|
|
471511
471662
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
471512
|
-
return
|
|
471663
|
+
return join62(thisDir, "../skills/builtin");
|
|
471513
471664
|
}
|
|
471514
|
-
return
|
|
471665
|
+
return join62(thisDir, "skills");
|
|
471515
471666
|
}
|
|
471516
471667
|
function compareSkills2(a2, b3) {
|
|
471517
471668
|
return a2.id.localeCompare(b3.id) || a2.source.localeCompare(b3.source) || a2.path.localeCompare(b3.path);
|
|
@@ -471558,7 +471709,7 @@ function isSkillAvailableForAgent2(skill2, agentId) {
|
|
|
471558
471709
|
return true;
|
|
471559
471710
|
}
|
|
471560
471711
|
function getAgentSkillsDir2(agentId) {
|
|
471561
|
-
return
|
|
471712
|
+
return join62(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
471562
471713
|
}
|
|
471563
471714
|
async function getBundledSkills2() {
|
|
471564
471715
|
const bundledPath = getBundledSkillsPath2();
|
|
@@ -471567,7 +471718,7 @@ async function getBundledSkills2() {
|
|
|
471567
471718
|
}
|
|
471568
471719
|
async function discoverSkillsFromDir2(skillsPath, source2) {
|
|
471569
471720
|
const errors7 = [];
|
|
471570
|
-
if (!
|
|
471721
|
+
if (!existsSync54(skillsPath)) {
|
|
471571
471722
|
return { skills: [], errors: [] };
|
|
471572
471723
|
}
|
|
471573
471724
|
const skills = [];
|
|
@@ -471581,7 +471732,7 @@ async function discoverSkillsFromDir2(skillsPath, source2) {
|
|
|
471581
471732
|
}
|
|
471582
471733
|
return { skills, errors: errors7 };
|
|
471583
471734
|
}
|
|
471584
|
-
async function discoverSkills2(projectSkillsPath =
|
|
471735
|
+
async function discoverSkills2(projectSkillsPath = join62(process.cwd(), SKILLS_DIR2), agentId, options3) {
|
|
471585
471736
|
const allErrors = [];
|
|
471586
471737
|
const skillsById = new Map;
|
|
471587
471738
|
const sourceSet = new Set(options3?.sources ?? ALL_SKILL_SOURCES);
|
|
@@ -471636,7 +471787,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors7, source2,
|
|
|
471636
471787
|
try {
|
|
471637
471788
|
const entries = await readdir15(currentPath, { withFileTypes: true });
|
|
471638
471789
|
for (const entry of entries) {
|
|
471639
|
-
const fullPath =
|
|
471790
|
+
const fullPath = join62(currentPath, entry.name);
|
|
471640
471791
|
try {
|
|
471641
471792
|
let isDirectory = entry.isDirectory();
|
|
471642
471793
|
let isFile = entry.isFile();
|
|
@@ -471727,8 +471878,8 @@ var LOCAL_AGENT_EXCLUDED_BUNDLED_SKILLS2, PROJECT_SKILLS_DIR2, SKILLS_DIR2 = ".s
|
|
|
471727
471878
|
var init_skills4 = __esm(() => {
|
|
471728
471879
|
init_skill_sources();
|
|
471729
471880
|
LOCAL_AGENT_EXCLUDED_BUNDLED_SKILLS2 = new Set(["image-generation"]);
|
|
471730
|
-
PROJECT_SKILLS_DIR2 =
|
|
471731
|
-
GLOBAL_SKILLS_DIR2 =
|
|
471881
|
+
PROJECT_SKILLS_DIR2 = join62(".agents", "skills");
|
|
471882
|
+
GLOBAL_SKILLS_DIR2 = join62(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
|
|
471732
471883
|
});
|
|
471733
471884
|
|
|
471734
471885
|
// src/utils/fs.ts
|
|
@@ -471742,10 +471893,10 @@ __export(exports_fs, {
|
|
|
471742
471893
|
exists: () => exists2
|
|
471743
471894
|
});
|
|
471744
471895
|
import {
|
|
471745
|
-
existsSync as
|
|
471896
|
+
existsSync as existsSync55,
|
|
471746
471897
|
readFileSync as fsReadFileSync2,
|
|
471747
471898
|
writeFileSync as fsWriteFileSync2,
|
|
471748
|
-
mkdirSync as
|
|
471899
|
+
mkdirSync as mkdirSync38
|
|
471749
471900
|
} from "node:fs";
|
|
471750
471901
|
import { dirname as dirname32 } from "node:path";
|
|
471751
471902
|
async function readFile23(path39) {
|
|
@@ -471753,16 +471904,16 @@ async function readFile23(path39) {
|
|
|
471753
471904
|
}
|
|
471754
471905
|
async function writeFile17(path39, content) {
|
|
471755
471906
|
const dir = dirname32(path39);
|
|
471756
|
-
if (!
|
|
471757
|
-
|
|
471907
|
+
if (!existsSync55(dir)) {
|
|
471908
|
+
mkdirSync38(dir, { recursive: true });
|
|
471758
471909
|
}
|
|
471759
471910
|
fsWriteFileSync2(path39, content, { encoding: "utf-8", flush: true });
|
|
471760
471911
|
}
|
|
471761
471912
|
function exists2(path39) {
|
|
471762
|
-
return
|
|
471913
|
+
return existsSync55(path39);
|
|
471763
471914
|
}
|
|
471764
471915
|
async function mkdir15(path39, options3) {
|
|
471765
|
-
|
|
471916
|
+
mkdirSync38(path39, options3);
|
|
471766
471917
|
}
|
|
471767
471918
|
async function readJsonFile4(path39) {
|
|
471768
471919
|
const text2 = await readFile23(path39);
|
|
@@ -471972,7 +472123,7 @@ import {
|
|
|
471972
472123
|
} from "node:child_process";
|
|
471973
472124
|
import { accessSync as accessSync2, constants as constants4, realpathSync as realpathSync6 } from "node:fs";
|
|
471974
472125
|
import { readdir as readdir16, rm as rm6 } from "node:fs/promises";
|
|
471975
|
-
import { dirname as dirname33, join as
|
|
472126
|
+
import { dirname as dirname33, join as join63 } from "node:path";
|
|
471976
472127
|
import { promisify as promisify15 } from "node:util";
|
|
471977
472128
|
function debugLog4(...args) {
|
|
471978
472129
|
if (DEBUG2) {
|
|
@@ -472047,7 +472198,7 @@ function getResolvedEntrypoint2() {
|
|
|
472047
472198
|
}
|
|
472048
472199
|
}
|
|
472049
472200
|
function findInstalledPackagePath2(resolvedPath) {
|
|
472050
|
-
const marker = `${
|
|
472201
|
+
const marker = `${join63("node_modules", "@letta-ai", "letta-code")}`;
|
|
472051
472202
|
const index = resolvedPath.lastIndexOf(marker);
|
|
472052
472203
|
if (index === -1) {
|
|
472053
472204
|
return null;
|
|
@@ -472196,12 +472347,12 @@ async function getNpmGlobalPath2() {
|
|
|
472196
472347
|
}
|
|
472197
472348
|
}
|
|
472198
472349
|
async function cleanupOrphanedDirs2(globalPath) {
|
|
472199
|
-
const lettaAiDir =
|
|
472350
|
+
const lettaAiDir = join63(globalPath, "lib/node_modules/@letta-ai");
|
|
472200
472351
|
try {
|
|
472201
472352
|
const entries = await readdir16(lettaAiDir);
|
|
472202
472353
|
for (const entry of entries) {
|
|
472203
472354
|
if (entry.startsWith(".letta-code-")) {
|
|
472204
|
-
const orphanPath =
|
|
472355
|
+
const orphanPath = join63(lettaAiDir, entry);
|
|
472205
472356
|
debugLog4("Cleaning orphaned temp directory:", orphanPath);
|
|
472206
472357
|
await rm6(orphanPath, { recursive: true, force: true });
|
|
472207
472358
|
}
|
|
@@ -472731,18 +472882,18 @@ var exports_bootstrap_tools = {};
|
|
|
472731
472882
|
__export(exports_bootstrap_tools, {
|
|
472732
472883
|
bootstrapBaseToolsIfNeeded: () => bootstrapBaseToolsIfNeeded
|
|
472733
472884
|
});
|
|
472734
|
-
import { existsSync as
|
|
472885
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync40, writeFileSync as writeFileSync29 } from "node:fs";
|
|
472735
472886
|
import { homedir as homedir35 } from "node:os";
|
|
472736
|
-
import { join as
|
|
472887
|
+
import { join as join65 } from "node:path";
|
|
472737
472888
|
async function bootstrapBaseToolsIfNeeded() {
|
|
472738
|
-
if (
|
|
472889
|
+
if (existsSync57(MARKER_PATH))
|
|
472739
472890
|
return;
|
|
472740
472891
|
debugLog("bootstrap", "No marker found, bootstrapping base tools...");
|
|
472741
472892
|
try {
|
|
472742
472893
|
const success2 = await addBaseToolsToServer();
|
|
472743
472894
|
if (success2) {
|
|
472744
|
-
|
|
472745
|
-
|
|
472895
|
+
mkdirSync40(join65(homedir35(), ".letta"), { recursive: true });
|
|
472896
|
+
writeFileSync29(MARKER_PATH, new Date().toISOString(), "utf-8");
|
|
472746
472897
|
}
|
|
472747
472898
|
} catch (err) {
|
|
472748
472899
|
debugWarn("bootstrap", `Failed to bootstrap base tools: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -472752,7 +472903,7 @@ var MARKER_PATH;
|
|
|
472752
472903
|
var init_bootstrap_tools = __esm(() => {
|
|
472753
472904
|
init_debug();
|
|
472754
472905
|
init_create6();
|
|
472755
|
-
MARKER_PATH =
|
|
472906
|
+
MARKER_PATH = join65(homedir35(), ".letta", ".bootstrapped");
|
|
472756
472907
|
});
|
|
472757
472908
|
|
|
472758
472909
|
// src/tools/filter.ts
|
|
@@ -473204,7 +473355,7 @@ function validateRegistryHandleOrThrow2(handle2) {
|
|
|
473204
473355
|
}
|
|
473205
473356
|
|
|
473206
473357
|
// src/headless-mod-adapter.ts
|
|
473207
|
-
import { join as
|
|
473358
|
+
import { join as join66 } from "node:path";
|
|
473208
473359
|
function isHeadlessMemfsEnabled(agentId) {
|
|
473209
473360
|
try {
|
|
473210
473361
|
return settingsManager.isMemfsEnabled(agentId);
|
|
@@ -473275,7 +473426,7 @@ function createHeadlessModContext(options3) {
|
|
|
473275
473426
|
};
|
|
473276
473427
|
}
|
|
473277
473428
|
function createHeadlessModAdapter(options3) {
|
|
473278
|
-
const agentModsDirectory = isHeadlessMemfsEnabled(options3.agent.id) ?
|
|
473429
|
+
const agentModsDirectory = isHeadlessMemfsEnabled(options3.agent.id) ? join66(getScopedMemoryFilesystemRoot(options3.agent.id), "mods") : undefined;
|
|
473279
473430
|
return createModAdapter({
|
|
473280
473431
|
...agentModsDirectory ? { agentModsDirectory } : {},
|
|
473281
473432
|
...options3.cacheDirectory ? { cacheDirectory: options3.cacheDirectory } : {},
|
|
@@ -473406,8 +473557,8 @@ var init_headless_tool_events = __esm(async () => {
|
|
|
473406
473557
|
});
|
|
473407
473558
|
|
|
473408
473559
|
// src/skills/builtin/creating-skills/scripts/validate-skill.ts
|
|
473409
|
-
import { existsSync as
|
|
473410
|
-
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";
|
|
473411
473562
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
473412
473563
|
function parseQuotedScalar(value) {
|
|
473413
473564
|
if (value.startsWith('"')) {
|
|
@@ -473504,8 +473655,8 @@ function parseFrontmatter2(source2) {
|
|
|
473504
473655
|
return parseFrontmatterFallback(source2);
|
|
473505
473656
|
}
|
|
473506
473657
|
function validateSkill(skillPath) {
|
|
473507
|
-
const skillMdPath =
|
|
473508
|
-
if (!
|
|
473658
|
+
const skillMdPath = join67(skillPath, "SKILL.md");
|
|
473659
|
+
if (!existsSync58(skillMdPath)) {
|
|
473509
473660
|
return { valid: false, message: "SKILL.md not found" };
|
|
473510
473661
|
}
|
|
473511
473662
|
const content = readFileSync38(skillMdPath, "utf-8");
|
|
@@ -473853,7 +474004,7 @@ function parseRegistryHandle(handle2) {
|
|
|
473853
474004
|
}
|
|
473854
474005
|
async function importAgentFromRegistry(options3) {
|
|
473855
474006
|
const { tmpdir: tmpdir10 } = await import("node:os");
|
|
473856
|
-
const { join:
|
|
474007
|
+
const { join: join68 } = await import("node:path");
|
|
473857
474008
|
const { writeFile: writeFile19, unlink: unlink5 } = await import("node:fs/promises");
|
|
473858
474009
|
const { author, name } = parseRegistryHandle(options3.handle);
|
|
473859
474010
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -473865,7 +474016,7 @@ async function importAgentFromRegistry(options3) {
|
|
|
473865
474016
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
473866
474017
|
}
|
|
473867
474018
|
const afContent = await response.text();
|
|
473868
|
-
const tempPath =
|
|
474019
|
+
const tempPath = join68(tmpdir10(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
473869
474020
|
await writeFile19(tempPath, afContent, "utf-8");
|
|
473870
474021
|
try {
|
|
473871
474022
|
const result = await importAgentFromFile({
|
|
@@ -478680,10 +478831,10 @@ var init_queued_message_parts = __esm(() => {
|
|
|
478680
478831
|
|
|
478681
478832
|
// src/cli/helpers/reflection-arena-hf-upload.ts
|
|
478682
478833
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
478683
|
-
import { existsSync as
|
|
478834
|
+
import { existsSync as existsSync60 } from "node:fs";
|
|
478684
478835
|
import { appendFile as appendFile2, chmod as chmod2, mkdir as mkdir17, writeFile as writeFile19 } from "node:fs/promises";
|
|
478685
478836
|
import { homedir as homedir38 } from "node:os";
|
|
478686
|
-
import { join as
|
|
478837
|
+
import { join as join69 } from "node:path";
|
|
478687
478838
|
import { promisify as promisify16 } from "node:util";
|
|
478688
478839
|
function buildGitEnv(token2, askpassPath) {
|
|
478689
478840
|
return {
|
|
@@ -478719,7 +478870,7 @@ async function runGit6(cwd2, args, env5) {
|
|
|
478719
478870
|
}
|
|
478720
478871
|
}
|
|
478721
478872
|
async function writeGitAskpass(repoRoot) {
|
|
478722
|
-
const askpassPath =
|
|
478873
|
+
const askpassPath = join69(repoRoot, "hf-askpass.sh");
|
|
478723
478874
|
await writeFile19(askpassPath, [
|
|
478724
478875
|
"#!/bin/sh",
|
|
478725
478876
|
'case "$1" in',
|
|
@@ -478734,7 +478885,7 @@ async function writeGitAskpass(repoRoot) {
|
|
|
478734
478885
|
}
|
|
478735
478886
|
async function prepareHfRepo(env5) {
|
|
478736
478887
|
await mkdir17(HF_CACHE_ROOT, { recursive: true });
|
|
478737
|
-
if (!
|
|
478888
|
+
if (!existsSync60(join69(HF_REPO_DIR, ".git"))) {
|
|
478738
478889
|
await runGit6(HF_CACHE_ROOT, ["clone", "--depth", "1", HF_REPO_URL, HF_REPO_DIR], env5);
|
|
478739
478890
|
return HF_REPO_DIR;
|
|
478740
478891
|
}
|
|
@@ -478769,8 +478920,8 @@ async function maybeUploadReflectionArenaChoiceToHf(row) {
|
|
|
478769
478920
|
const env5 = buildGitEnv(token2, askpassPath);
|
|
478770
478921
|
try {
|
|
478771
478922
|
const repoDir = await prepareHfRepo(env5);
|
|
478772
|
-
await mkdir17(
|
|
478773
|
-
await appendFile2(
|
|
478923
|
+
await mkdir17(join69(repoDir, "data"), { recursive: true });
|
|
478924
|
+
await appendFile2(join69(repoDir, HF_DATASET_PATH), `${JSON.stringify(row)}
|
|
478774
478925
|
`, {
|
|
478775
478926
|
encoding: "utf-8"
|
|
478776
478927
|
});
|
|
@@ -478798,8 +478949,8 @@ var init_reflection_arena_hf_upload = __esm(() => {
|
|
|
478798
478949
|
init_version();
|
|
478799
478950
|
execFile18 = promisify16(execFileCb5);
|
|
478800
478951
|
HF_REPO_URL = `https://huggingface.co/datasets/${HF_REPO_ID}`;
|
|
478801
|
-
HF_CACHE_ROOT =
|
|
478802
|
-
HF_REPO_DIR =
|
|
478952
|
+
HF_CACHE_ROOT = join69(homedir38(), ".letta", "reflection-arena", "hf-upload");
|
|
478953
|
+
HF_REPO_DIR = join69(HF_CACHE_ROOT, "repo");
|
|
478803
478954
|
});
|
|
478804
478955
|
|
|
478805
478956
|
// src/cli/helpers/reflection-arena.ts
|
|
@@ -478807,7 +478958,7 @@ import { execFile as execFileCb6 } from "node:child_process";
|
|
|
478807
478958
|
import { randomInt, randomUUID as randomUUID30 } from "node:crypto";
|
|
478808
478959
|
import { appendFile as appendFile3, mkdir as mkdir18, readFile as readFile25, writeFile as writeFile20 } from "node:fs/promises";
|
|
478809
478960
|
import { homedir as homedir39 } from "node:os";
|
|
478810
|
-
import { join as
|
|
478961
|
+
import { join as join70 } from "node:path";
|
|
478811
478962
|
import { promisify as promisify17 } from "node:util";
|
|
478812
478963
|
function sampleReflectionArenaComparisonModel(excludedModels = []) {
|
|
478813
478964
|
const excluded = new Set(excludedModels);
|
|
@@ -478837,16 +478988,16 @@ async function getGitHead(cwd2) {
|
|
|
478837
478988
|
}
|
|
478838
478989
|
}
|
|
478839
478990
|
function getReflectionArenaRoot() {
|
|
478840
|
-
return
|
|
478991
|
+
return join70(homedir39(), ".letta", "reflection-arena");
|
|
478841
478992
|
}
|
|
478842
478993
|
function getReflectionArenaRunsDir() {
|
|
478843
|
-
return
|
|
478994
|
+
return join70(getReflectionArenaRoot(), "runs");
|
|
478844
478995
|
}
|
|
478845
478996
|
function getReflectionArenaChoiceLogPath() {
|
|
478846
|
-
return
|
|
478997
|
+
return join70(getReflectionArenaRoot(), "choices.jsonl");
|
|
478847
478998
|
}
|
|
478848
478999
|
function getReflectionArenaRunPath(runId) {
|
|
478849
|
-
return
|
|
479000
|
+
return join70(getReflectionArenaRunsDir(), `${runId}.json`);
|
|
478850
479001
|
}
|
|
478851
479002
|
async function saveReflectionArenaRun(run) {
|
|
478852
479003
|
await mkdir18(getReflectionArenaRunsDir(), { recursive: true });
|
|
@@ -479943,13 +480094,13 @@ __export(exports_terminal_keybinding_installer, {
|
|
|
479943
480094
|
});
|
|
479944
480095
|
import {
|
|
479945
480096
|
copyFileSync as copyFileSync5,
|
|
479946
|
-
existsSync as
|
|
479947
|
-
mkdirSync as
|
|
480097
|
+
existsSync as existsSync61,
|
|
480098
|
+
mkdirSync as mkdirSync42,
|
|
479948
480099
|
readFileSync as readFileSync40,
|
|
479949
|
-
writeFileSync as
|
|
480100
|
+
writeFileSync as writeFileSync31
|
|
479950
480101
|
} from "node:fs";
|
|
479951
480102
|
import { homedir as homedir40, platform as platform9 } from "node:os";
|
|
479952
|
-
import { dirname as dirname35, join as
|
|
480103
|
+
import { dirname as dirname35, join as join71 } from "node:path";
|
|
479953
480104
|
function detectTerminalType() {
|
|
479954
480105
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
479955
480106
|
return "cursor";
|
|
@@ -479981,16 +480132,16 @@ function getKeybindingsPath(terminal) {
|
|
|
479981
480132
|
}[terminal];
|
|
479982
480133
|
const os9 = platform9();
|
|
479983
480134
|
if (os9 === "darwin") {
|
|
479984
|
-
return
|
|
480135
|
+
return join71(homedir40(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
479985
480136
|
}
|
|
479986
480137
|
if (os9 === "win32") {
|
|
479987
480138
|
const appData = process.env.APPDATA;
|
|
479988
480139
|
if (!appData)
|
|
479989
480140
|
return null;
|
|
479990
|
-
return
|
|
480141
|
+
return join71(appData, appName, "User", "keybindings.json");
|
|
479991
480142
|
}
|
|
479992
480143
|
if (os9 === "linux") {
|
|
479993
|
-
return
|
|
480144
|
+
return join71(homedir40(), ".config", appName, "User", "keybindings.json");
|
|
479994
480145
|
}
|
|
479995
480146
|
return null;
|
|
479996
480147
|
}
|
|
@@ -480012,7 +480163,7 @@ function parseKeybindings(content) {
|
|
|
480012
480163
|
}
|
|
480013
480164
|
}
|
|
480014
480165
|
function keybindingExists(keybindingsPath) {
|
|
480015
|
-
if (!
|
|
480166
|
+
if (!existsSync61(keybindingsPath))
|
|
480016
480167
|
return false;
|
|
480017
480168
|
try {
|
|
480018
480169
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -480025,7 +480176,7 @@ function keybindingExists(keybindingsPath) {
|
|
|
480025
480176
|
}
|
|
480026
480177
|
}
|
|
480027
480178
|
function createBackup(keybindingsPath) {
|
|
480028
|
-
if (!
|
|
480179
|
+
if (!existsSync61(keybindingsPath))
|
|
480029
480180
|
return null;
|
|
480030
480181
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
480031
480182
|
try {
|
|
@@ -480041,12 +480192,12 @@ function installKeybinding(keybindingsPath) {
|
|
|
480041
480192
|
return { success: true, alreadyExists: true };
|
|
480042
480193
|
}
|
|
480043
480194
|
const parentDir = dirname35(keybindingsPath);
|
|
480044
|
-
if (!
|
|
480045
|
-
|
|
480195
|
+
if (!existsSync61(parentDir)) {
|
|
480196
|
+
mkdirSync42(parentDir, { recursive: true });
|
|
480046
480197
|
}
|
|
480047
480198
|
let keybindings = [];
|
|
480048
480199
|
let backupPath = null;
|
|
480049
|
-
if (
|
|
480200
|
+
if (existsSync61(keybindingsPath)) {
|
|
480050
480201
|
backupPath = createBackup(keybindingsPath);
|
|
480051
480202
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
480052
480203
|
const parsed = parseKeybindings(content);
|
|
@@ -480061,7 +480212,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
480061
480212
|
keybindings.push(SHIFT_ENTER_KEYBINDING);
|
|
480062
480213
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
480063
480214
|
`;
|
|
480064
|
-
|
|
480215
|
+
writeFileSync31(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
480065
480216
|
return {
|
|
480066
480217
|
success: true,
|
|
480067
480218
|
backupPath: backupPath ?? undefined
|
|
@@ -480076,7 +480227,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
480076
480227
|
}
|
|
480077
480228
|
function removeKeybinding(keybindingsPath) {
|
|
480078
480229
|
try {
|
|
480079
|
-
if (!
|
|
480230
|
+
if (!existsSync61(keybindingsPath)) {
|
|
480080
480231
|
return { success: true };
|
|
480081
480232
|
}
|
|
480082
480233
|
const content = readFileSync40(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -480090,7 +480241,7 @@ function removeKeybinding(keybindingsPath) {
|
|
|
480090
480241
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
480091
480242
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
480092
480243
|
`;
|
|
480093
|
-
|
|
480244
|
+
writeFileSync31(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
480094
480245
|
return { success: true };
|
|
480095
480246
|
} catch (error54) {
|
|
480096
480247
|
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
@@ -480143,14 +480294,14 @@ function getWezTermConfigPath() {
|
|
|
480143
480294
|
}
|
|
480144
480295
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
480145
480296
|
if (xdgConfig) {
|
|
480146
|
-
const xdgPath =
|
|
480147
|
-
if (
|
|
480297
|
+
const xdgPath = join71(xdgConfig, "wezterm", "wezterm.lua");
|
|
480298
|
+
if (existsSync61(xdgPath))
|
|
480148
480299
|
return xdgPath;
|
|
480149
480300
|
}
|
|
480150
|
-
const configPath =
|
|
480151
|
-
if (
|
|
480301
|
+
const configPath = join71(homedir40(), ".config", "wezterm", "wezterm.lua");
|
|
480302
|
+
if (existsSync61(configPath))
|
|
480152
480303
|
return configPath;
|
|
480153
|
-
return
|
|
480304
|
+
return join71(homedir40(), ".wezterm.lua");
|
|
480154
480305
|
}
|
|
480155
480306
|
function stripLuaCommentsFromLine(line, blockCommentEnd) {
|
|
480156
480307
|
let code2 = "";
|
|
@@ -480253,7 +480404,7 @@ ${WEZTERM_DELETE_FIX}
|
|
|
480253
480404
|
`;
|
|
480254
480405
|
}
|
|
480255
480406
|
function wezTermDeleteFixExists(configPath) {
|
|
480256
|
-
if (!
|
|
480407
|
+
if (!existsSync61(configPath))
|
|
480257
480408
|
return false;
|
|
480258
480409
|
try {
|
|
480259
480410
|
const content = readFileSync40(configPath, { encoding: "utf-8" });
|
|
@@ -480270,17 +480421,17 @@ function installWezTermDeleteFix() {
|
|
|
480270
480421
|
}
|
|
480271
480422
|
let content = "";
|
|
480272
480423
|
let backupPath = null;
|
|
480273
|
-
if (
|
|
480424
|
+
if (existsSync61(configPath)) {
|
|
480274
480425
|
backupPath = `${configPath}.letta-backup`;
|
|
480275
480426
|
copyFileSync5(configPath, backupPath);
|
|
480276
480427
|
content = readFileSync40(configPath, { encoding: "utf-8" });
|
|
480277
480428
|
}
|
|
480278
480429
|
content = injectWezTermDeleteFix(content);
|
|
480279
480430
|
const parentDir = dirname35(configPath);
|
|
480280
|
-
if (!
|
|
480281
|
-
|
|
480431
|
+
if (!existsSync61(parentDir)) {
|
|
480432
|
+
mkdirSync42(parentDir, { recursive: true });
|
|
480282
480433
|
}
|
|
480283
|
-
|
|
480434
|
+
writeFileSync31(configPath, content, { encoding: "utf-8" });
|
|
480284
480435
|
return {
|
|
480285
480436
|
success: true,
|
|
480286
480437
|
backupPath: backupPath ?? undefined
|
|
@@ -480329,9 +480480,9 @@ __export(exports_settings2, {
|
|
|
480329
480480
|
getSetting: () => getSetting
|
|
480330
480481
|
});
|
|
480331
480482
|
import { homedir as homedir41 } from "node:os";
|
|
480332
|
-
import { join as
|
|
480483
|
+
import { join as join72 } from "node:path";
|
|
480333
480484
|
function getSettingsPath() {
|
|
480334
|
-
return
|
|
480485
|
+
return join72(homedir41(), ".letta", "settings.json");
|
|
480335
480486
|
}
|
|
480336
480487
|
async function loadSettings() {
|
|
480337
480488
|
const settingsPath = getSettingsPath();
|
|
@@ -480368,7 +480519,7 @@ async function getSetting(key2) {
|
|
|
480368
480519
|
return settings3[key2];
|
|
480369
480520
|
}
|
|
480370
480521
|
function getProjectSettingsPath() {
|
|
480371
|
-
return
|
|
480522
|
+
return join72(process.cwd(), ".letta", "settings.local.json");
|
|
480372
480523
|
}
|
|
480373
480524
|
async function loadProjectSettings() {
|
|
480374
480525
|
const settingsPath = getProjectSettingsPath();
|
|
@@ -480386,7 +480537,7 @@ async function loadProjectSettings() {
|
|
|
480386
480537
|
}
|
|
480387
480538
|
async function saveProjectSettings(settings3) {
|
|
480388
480539
|
const settingsPath = getProjectSettingsPath();
|
|
480389
|
-
const dirPath =
|
|
480540
|
+
const dirPath = join72(process.cwd(), ".letta");
|
|
480390
480541
|
try {
|
|
480391
480542
|
if (!exists(dirPath)) {
|
|
480392
480543
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -482273,9 +482424,9 @@ function getHeaderText(fileEdit) {
|
|
|
482273
482424
|
const relPath = relative16(cwd2, fileEdit.filePath);
|
|
482274
482425
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
482275
482426
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
482276
|
-
const { existsSync:
|
|
482427
|
+
const { existsSync: existsSync62 } = __require("node:fs");
|
|
482277
482428
|
try {
|
|
482278
|
-
if (
|
|
482429
|
+
if (existsSync62(fileEdit.filePath)) {
|
|
482279
482430
|
return `Overwrite ${displayPath}?`;
|
|
482280
482431
|
}
|
|
482281
482432
|
} catch {}
|
|
@@ -489783,15 +489934,15 @@ import { spawn as spawn12, spawnSync as spawnSync4 } from "node:child_process";
|
|
|
489783
489934
|
import {
|
|
489784
489935
|
chmodSync as chmodSync7,
|
|
489785
489936
|
createWriteStream as createWriteStream4,
|
|
489786
|
-
existsSync as
|
|
489787
|
-
mkdirSync as
|
|
489937
|
+
existsSync as existsSync62,
|
|
489938
|
+
mkdirSync as mkdirSync43,
|
|
489788
489939
|
readdirSync as readdirSync22,
|
|
489789
489940
|
renameSync as renameSync6,
|
|
489790
489941
|
rmSync as rmSync14,
|
|
489791
489942
|
statSync as statSync20
|
|
489792
489943
|
} from "node:fs";
|
|
489793
489944
|
import { arch as arch4, homedir as homedir43, platform as platform10 } from "node:os";
|
|
489794
|
-
import { basename as basename29, join as
|
|
489945
|
+
import { basename as basename29, join as join73 } from "node:path";
|
|
489795
489946
|
function toDisplayPath(value) {
|
|
489796
489947
|
return value.replace(/\\/g, "/");
|
|
489797
489948
|
}
|
|
@@ -490033,7 +490184,7 @@ class FileAutocompleteProvider {
|
|
|
490033
490184
|
}
|
|
490034
490185
|
expandHomePath(path42) {
|
|
490035
490186
|
if (path42.startsWith("~/")) {
|
|
490036
|
-
const expandedPath =
|
|
490187
|
+
const expandedPath = join73(homedir43(), path42.slice(2));
|
|
490037
490188
|
return path42.endsWith("/") && !expandedPath.endsWith("/") ? `${expandedPath}/` : expandedPath;
|
|
490038
490189
|
} else if (path42 === "~") {
|
|
490039
490190
|
return homedir43();
|
|
@@ -490054,7 +490205,7 @@ class FileAutocompleteProvider {
|
|
|
490054
490205
|
} else if (displayBase.startsWith("/")) {
|
|
490055
490206
|
baseDir = displayBase;
|
|
490056
490207
|
} else {
|
|
490057
|
-
baseDir =
|
|
490208
|
+
baseDir = join73(this.basePath, displayBase);
|
|
490058
490209
|
}
|
|
490059
490210
|
try {
|
|
490060
490211
|
if (!statSync20(baseDir).isDirectory()) {
|
|
@@ -490133,9 +490284,9 @@ class FileAutocompleteProvider {
|
|
|
490133
490284
|
var PATH_DELIMITERS2, FD_TOOLS_DIR2, FD_BINARY_NAME2, FD_LOCAL_PATH2;
|
|
490134
490285
|
var init_file_autocomplete = __esm(() => {
|
|
490135
490286
|
PATH_DELIMITERS2 = new Set([" ", "\t", '"', "'", "="]);
|
|
490136
|
-
FD_TOOLS_DIR2 =
|
|
490287
|
+
FD_TOOLS_DIR2 = join73(homedir43(), ".letta", "bin");
|
|
490137
490288
|
FD_BINARY_NAME2 = platform10() === "win32" ? "fd.exe" : "fd";
|
|
490138
|
-
FD_LOCAL_PATH2 =
|
|
490289
|
+
FD_LOCAL_PATH2 = join73(FD_TOOLS_DIR2, FD_BINARY_NAME2);
|
|
490139
490290
|
});
|
|
490140
490291
|
|
|
490141
490292
|
// src/cli/hooks/use-autocomplete-navigation.ts
|
|
@@ -492954,15 +493105,15 @@ var init_agents7 = __esm(() => {
|
|
|
492954
493105
|
// src/cli/commands/install-github-app.ts
|
|
492955
493106
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
492956
493107
|
import {
|
|
492957
|
-
existsSync as
|
|
492958
|
-
mkdirSync as
|
|
493108
|
+
existsSync as existsSync63,
|
|
493109
|
+
mkdirSync as mkdirSync44,
|
|
492959
493110
|
mkdtempSync as mkdtempSync5,
|
|
492960
493111
|
readFileSync as readFileSync41,
|
|
492961
493112
|
rmSync as rmSync15,
|
|
492962
|
-
writeFileSync as
|
|
493113
|
+
writeFileSync as writeFileSync32
|
|
492963
493114
|
} from "node:fs";
|
|
492964
493115
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
492965
|
-
import { dirname as dirname36, join as
|
|
493116
|
+
import { dirname as dirname36, join as join74 } from "node:path";
|
|
492966
493117
|
function runCommand(command, args, cwd2, input) {
|
|
492967
493118
|
try {
|
|
492968
493119
|
return execFileSync8(command, args, {
|
|
@@ -493183,8 +493334,8 @@ async function createLettaAgent(apiKey, name) {
|
|
|
493183
493334
|
return createMinimalAgent(apiKey, name);
|
|
493184
493335
|
}
|
|
493185
493336
|
function cloneRepoToTemp(repo) {
|
|
493186
|
-
const tempDir = mkdtempSync5(
|
|
493187
|
-
const repoDir =
|
|
493337
|
+
const tempDir = mkdtempSync5(join74(tmpdir10(), "letta-install-github-app-"));
|
|
493338
|
+
const repoDir = join74(tempDir, "repo");
|
|
493188
493339
|
runCommand("gh", ["repo", "clone", repo, repoDir, "--", "--depth=1"]);
|
|
493189
493340
|
return { tempDir, repoDir };
|
|
493190
493341
|
}
|
|
@@ -493195,19 +493346,19 @@ function runGit7(args, cwd2) {
|
|
|
493195
493346
|
return runCommand("git", args, cwd2);
|
|
493196
493347
|
}
|
|
493197
493348
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
493198
|
-
const absolutePath =
|
|
493199
|
-
if (!
|
|
493200
|
-
|
|
493349
|
+
const absolutePath = join74(repoDir, workflowPath);
|
|
493350
|
+
if (!existsSync63(dirname36(absolutePath))) {
|
|
493351
|
+
mkdirSync44(dirname36(absolutePath), { recursive: true });
|
|
493201
493352
|
}
|
|
493202
493353
|
const next = `${content.trimEnd()}
|
|
493203
493354
|
`;
|
|
493204
|
-
if (
|
|
493355
|
+
if (existsSync63(absolutePath)) {
|
|
493205
493356
|
const previous = readFileSync41(absolutePath, "utf8");
|
|
493206
493357
|
if (previous === next) {
|
|
493207
493358
|
return false;
|
|
493208
493359
|
}
|
|
493209
493360
|
}
|
|
493210
|
-
|
|
493361
|
+
writeFileSync32(absolutePath, next, "utf8");
|
|
493211
493362
|
return true;
|
|
493212
493363
|
}
|
|
493213
493364
|
function getDefaultBaseBranch(repoDir) {
|
|
@@ -497624,9 +497775,9 @@ __export(exports_generate_memory_viewer, {
|
|
|
497624
497775
|
generateAndOpenMemoryViewer: () => generateAndOpenMemoryViewer
|
|
497625
497776
|
});
|
|
497626
497777
|
import { execFile as execFileCb7 } from "node:child_process";
|
|
497627
|
-
import { chmodSync as chmodSync8, existsSync as
|
|
497778
|
+
import { chmodSync as chmodSync8, existsSync as existsSync64, mkdirSync as mkdirSync45, writeFileSync as writeFileSync33 } from "node:fs";
|
|
497628
497779
|
import { homedir as homedir44 } from "node:os";
|
|
497629
|
-
import { join as
|
|
497780
|
+
import { join as join75 } from "node:path";
|
|
497630
497781
|
import { promisify as promisify18 } from "node:util";
|
|
497631
497782
|
function messagesFromOverview(overview) {
|
|
497632
497783
|
return overview.messages?.map((message) => ({
|
|
@@ -497935,7 +498086,7 @@ ${m4.body}` : m4.subject;
|
|
|
497935
498086
|
async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
497936
498087
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
497937
498088
|
const repoDir = memoryRoot;
|
|
497938
|
-
if (!
|
|
498089
|
+
if (!existsSync64(join75(repoDir, ".git"))) {
|
|
497939
498090
|
throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
|
|
497940
498091
|
}
|
|
497941
498092
|
const data = await collectMemoryData(agentId, repoDir, memoryRoot, options3?.conversationId);
|
|
@@ -497945,14 +498096,14 @@ async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
|
497945
498096
|
data.context = applyContextUsageSnapshot(data.context, options3?.contextUsage);
|
|
497946
498097
|
const jsonPayload = JSON.stringify(data).replace(/</g, "\\u003c");
|
|
497947
498098
|
const html5 = memory_viewer_template_default.replace("<!--LETTA_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
497948
|
-
if (!
|
|
497949
|
-
|
|
498099
|
+
if (!existsSync64(VIEWERS_DIR)) {
|
|
498100
|
+
mkdirSync45(VIEWERS_DIR, { recursive: true, mode: 448 });
|
|
497950
498101
|
}
|
|
497951
498102
|
try {
|
|
497952
498103
|
chmodSync8(VIEWERS_DIR, 448);
|
|
497953
498104
|
} catch {}
|
|
497954
|
-
const filePath =
|
|
497955
|
-
|
|
498105
|
+
const filePath = join75(VIEWERS_DIR, `memory-${encodeURIComponent(agentId)}.html`);
|
|
498106
|
+
writeFileSync33(filePath, html5);
|
|
497956
498107
|
chmodSync8(filePath, 384);
|
|
497957
498108
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
497958
498109
|
if (!skipOpen) {
|
|
@@ -497976,13 +498127,13 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
497976
498127
|
init_local_memory_context();
|
|
497977
498128
|
init_memory_viewer_template();
|
|
497978
498129
|
execFile20 = promisify18(execFileCb7);
|
|
497979
|
-
VIEWERS_DIR =
|
|
498130
|
+
VIEWERS_DIR = join75(homedir44(), ".letta", "viewers");
|
|
497980
498131
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
497981
498132
|
});
|
|
497982
498133
|
|
|
497983
498134
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
497984
|
-
import { existsSync as
|
|
497985
|
-
import { join as
|
|
498135
|
+
import { existsSync as existsSync65 } from "node:fs";
|
|
498136
|
+
import { join as join76 } from "node:path";
|
|
497986
498137
|
function renderTreePrefix(node) {
|
|
497987
498138
|
let prefix = "";
|
|
497988
498139
|
for (let i4 = 0;i4 < node.depth; i4++) {
|
|
@@ -498010,8 +498161,8 @@ function MemfsTreeViewer({
|
|
|
498010
498161
|
const [status, setStatus] = import_react90.useState(null);
|
|
498011
498162
|
const statusTimerRef = import_react90.useRef(null);
|
|
498012
498163
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
498013
|
-
const memoryExists =
|
|
498014
|
-
const hasGitRepo = import_react90.useMemo(() =>
|
|
498164
|
+
const memoryExists = existsSync65(memoryRoot);
|
|
498165
|
+
const hasGitRepo = import_react90.useMemo(() => existsSync65(join76(memoryRoot, ".git")), [memoryRoot]);
|
|
498015
498166
|
function showStatus(msg, durationMs) {
|
|
498016
498167
|
if (statusTimerRef.current)
|
|
498017
498168
|
clearTimeout(statusTimerRef.current);
|
|
@@ -500477,10 +500628,10 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
500477
500628
|
// src/utils/aws-credentials.ts
|
|
500478
500629
|
import { readFile as readFile26 } from "node:fs/promises";
|
|
500479
500630
|
import { homedir as homedir45 } from "node:os";
|
|
500480
|
-
import { join as
|
|
500631
|
+
import { join as join77 } from "node:path";
|
|
500481
500632
|
async function parseAwsCredentials() {
|
|
500482
|
-
const credentialsPath =
|
|
500483
|
-
const configPath =
|
|
500633
|
+
const credentialsPath = join77(homedir45(), ".aws", "credentials");
|
|
500634
|
+
const configPath = join77(homedir45(), ".aws", "config");
|
|
500484
500635
|
const profiles = new Map;
|
|
500485
500636
|
try {
|
|
500486
500637
|
const content = await readFile26(credentialsPath, "utf-8");
|
|
@@ -502056,8 +502207,8 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
502056
502207
|
try {
|
|
502057
502208
|
const { discoverSkills: discoverSkills3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
|
|
502058
502209
|
const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
502059
|
-
const { join:
|
|
502060
|
-
const skillsDir = getSkillsDirectory2() ||
|
|
502210
|
+
const { join: join78 } = await import("node:path");
|
|
502211
|
+
const skillsDir = getSkillsDirectory2() || join78(process.cwd(), SKILLS_DIR3);
|
|
502061
502212
|
const result = await discoverSkills3(skillsDir, agentId, {
|
|
502062
502213
|
sources: getSkillSources2()
|
|
502063
502214
|
});
|
|
@@ -505983,9 +506134,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
505983
506134
|
const relPath = relative16(cwd2, filePath);
|
|
505984
506135
|
const displayPath2 = relPath.startsWith("..") ? filePath : relPath;
|
|
505985
506136
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
505986
|
-
const { existsSync:
|
|
506137
|
+
const { existsSync: existsSync66 } = __require("node:fs");
|
|
505987
506138
|
try {
|
|
505988
|
-
if (
|
|
506139
|
+
if (existsSync66(filePath)) {
|
|
505989
506140
|
return `Overwrite ${displayPath2}?`;
|
|
505990
506141
|
}
|
|
505991
506142
|
} catch {}
|
|
@@ -521325,9 +521476,9 @@ __export(exports_generate_diff_viewer, {
|
|
|
521325
521476
|
generateAndOpenDiffViewer: () => generateAndOpenDiffViewer
|
|
521326
521477
|
});
|
|
521327
521478
|
import { execFile as execFileCb8 } from "node:child_process";
|
|
521328
|
-
import { chmodSync as chmodSync9, existsSync as
|
|
521479
|
+
import { chmodSync as chmodSync9, existsSync as existsSync66, mkdirSync as mkdirSync46, writeFileSync as writeFileSync34 } from "node:fs";
|
|
521329
521480
|
import { homedir as homedir46 } from "node:os";
|
|
521330
|
-
import { isAbsolute as isAbsolute26, join as
|
|
521481
|
+
import { isAbsolute as isAbsolute26, join as join78, resolve as resolve39 } from "node:path";
|
|
521331
521482
|
import { promisify as promisify19 } from "node:util";
|
|
521332
521483
|
async function runGit8(cwd2, args) {
|
|
521333
521484
|
try {
|
|
@@ -521546,14 +521697,14 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
521546
521697
|
};
|
|
521547
521698
|
const jsonPayload = JSON.stringify(payload).replace(/</g, "\\u003c");
|
|
521548
521699
|
const html5 = diff_viewer_template_default.replace("<!--LETTA_DIFF_DATA_PLACEHOLDER-->", () => jsonPayload);
|
|
521549
|
-
if (!
|
|
521550
|
-
|
|
521700
|
+
if (!existsSync66(VIEWERS_DIR2)) {
|
|
521701
|
+
mkdirSync46(VIEWERS_DIR2, { recursive: true, mode: 448 });
|
|
521551
521702
|
}
|
|
521552
521703
|
try {
|
|
521553
521704
|
chmodSync9(VIEWERS_DIR2, 448);
|
|
521554
521705
|
} catch {}
|
|
521555
|
-
const filePath =
|
|
521556
|
-
|
|
521706
|
+
const filePath = join78(VIEWERS_DIR2, `diff-${encodeURIComponent(worktreePath)}.html`);
|
|
521707
|
+
writeFileSync34(filePath, html5);
|
|
521557
521708
|
chmodSync9(filePath, 384);
|
|
521558
521709
|
const skipOpen = shouldSkipOpen();
|
|
521559
521710
|
if (!skipOpen) {
|
|
@@ -521623,7 +521774,7 @@ var init_generate_diff_viewer = __esm(() => {
|
|
|
521623
521774
|
init_ssr();
|
|
521624
521775
|
init_diff_viewer_template();
|
|
521625
521776
|
execFile21 = promisify19(execFileCb8);
|
|
521626
|
-
VIEWERS_DIR2 =
|
|
521777
|
+
VIEWERS_DIR2 = join78(homedir46(), ".letta", "viewers");
|
|
521627
521778
|
GIT_MAX_BUFFER = 50 * 1024 * 1024;
|
|
521628
521779
|
});
|
|
521629
521780
|
|
|
@@ -523588,12 +523739,12 @@ __export(exports_shell_aliases, {
|
|
|
523588
523739
|
expandAliases: () => expandAliases,
|
|
523589
523740
|
clearAliasCache: () => clearAliasCache
|
|
523590
523741
|
});
|
|
523591
|
-
import { existsSync as
|
|
523742
|
+
import { existsSync as existsSync67, readFileSync as readFileSync42 } from "node:fs";
|
|
523592
523743
|
import { homedir as homedir47 } from "node:os";
|
|
523593
|
-
import { join as
|
|
523744
|
+
import { join as join79 } from "node:path";
|
|
523594
523745
|
function parseAliasesFromFile(filePath) {
|
|
523595
523746
|
const aliases = new Map;
|
|
523596
|
-
if (!
|
|
523747
|
+
if (!existsSync67(filePath)) {
|
|
523597
523748
|
return aliases;
|
|
523598
523749
|
}
|
|
523599
523750
|
try {
|
|
@@ -523662,7 +523813,7 @@ function loadAliases(forceReload = false) {
|
|
|
523662
523813
|
const home = homedir47();
|
|
523663
523814
|
const allAliases = new Map;
|
|
523664
523815
|
for (const file3 of ALIAS_FILES) {
|
|
523665
|
-
const filePath =
|
|
523816
|
+
const filePath = join79(home, file3);
|
|
523666
523817
|
const fileAliases = parseAliasesFromFile(filePath);
|
|
523667
523818
|
for (const [name, value] of fileAliases) {
|
|
523668
523819
|
allAliases.set(name, value);
|
|
@@ -531934,9 +532085,9 @@ var init_conversation_switch_alert = __esm(() => {
|
|
|
531934
532085
|
|
|
531935
532086
|
// src/cli/app/use-submit-handler.ts
|
|
531936
532087
|
import { randomUUID as randomUUID35 } from "node:crypto";
|
|
531937
|
-
import { existsSync as
|
|
532088
|
+
import { existsSync as existsSync68, readFileSync as readFileSync43, renameSync as renameSync7, writeFileSync as writeFileSync35 } from "node:fs";
|
|
531938
532089
|
import { tmpdir as tmpdir11 } from "node:os";
|
|
531939
|
-
import { join as
|
|
532090
|
+
import { join as join80 } from "node:path";
|
|
531940
532091
|
async function findCustomCommandByName(commandName) {
|
|
531941
532092
|
const { findCustomCommand: findCustomCommand2 } = await Promise.resolve().then(() => (init_custom(), exports_custom));
|
|
531942
532093
|
return findCustomCommand2(commandName);
|
|
@@ -532632,10 +532783,10 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
532632
532783
|
try {
|
|
532633
532784
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
532634
532785
|
const personaCandidates = [
|
|
532635
|
-
|
|
532636
|
-
|
|
532786
|
+
join80(memoryRoot, "system", "persona.md"),
|
|
532787
|
+
join80(memoryRoot, "memory", "system", "persona.md")
|
|
532637
532788
|
];
|
|
532638
|
-
const personaPath = personaCandidates.find((candidate) =>
|
|
532789
|
+
const personaPath = personaCandidates.find((candidate) => existsSync68(candidate));
|
|
532639
532790
|
if (personaPath) {
|
|
532640
532791
|
const personaContent = readFileSync43(personaPath, "utf-8");
|
|
532641
532792
|
setCurrentPersonalityId(detectPersonalityFromPersonaFile(personaContent));
|
|
@@ -533409,7 +533560,7 @@ Tip: Use /clear instead to clear the current message buffer.`;
|
|
|
533409
533560
|
fileContent.skills = skills;
|
|
533410
533561
|
}
|
|
533411
533562
|
const fileName = exportParams.conversation_id ? `${exportParams.conversation_id}.af` : `${agentId}.af`;
|
|
533412
|
-
|
|
533563
|
+
writeFileSync35(fileName, JSON.stringify(fileContent, null, 2));
|
|
533413
533564
|
let summary = `AgentFile exported to ${fileName}`;
|
|
533414
533565
|
if (skills.length > 0) {
|
|
533415
533566
|
summary += `
|
|
@@ -533516,11 +533667,11 @@ Path: ${memoryDir}`, true);
|
|
|
533516
533667
|
setCommandRunning(true);
|
|
533517
533668
|
try {
|
|
533518
533669
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
533519
|
-
if (!
|
|
533670
|
+
if (!existsSync68(memoryDir)) {
|
|
533520
533671
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
533521
533672
|
return { submitted: true };
|
|
533522
533673
|
}
|
|
533523
|
-
const backupDir =
|
|
533674
|
+
const backupDir = join80(tmpdir11(), `letta-memfs-reset-${agentId}-${Date.now()}`);
|
|
533524
533675
|
renameSync7(memoryDir, backupDir);
|
|
533525
533676
|
if (getBackend().capabilities.localMemfs) {
|
|
533526
533677
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
@@ -534484,7 +534635,7 @@ var init_use_submit_handler = __esm(async () => {
|
|
|
534484
534635
|
});
|
|
534485
534636
|
|
|
534486
534637
|
// src/cli/app/AppCoordinator.tsx
|
|
534487
|
-
import { join as
|
|
534638
|
+
import { join as join81 } from "node:path";
|
|
534488
534639
|
function buildStartupCommandHints(options3) {
|
|
534489
534640
|
const {
|
|
534490
534641
|
isResumingConversation,
|
|
@@ -535790,7 +535941,7 @@ function App2({
|
|
|
535790
535941
|
agentId: a2.agentId ?? null
|
|
535791
535942
|
}))
|
|
535792
535943
|
});
|
|
535793
|
-
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ?
|
|
535944
|
+
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ? join81(modContext.memfs.memoryDir, "mods") : null;
|
|
535794
535945
|
const modAdapter = useLocalModAdapter(modContext, {
|
|
535795
535946
|
agentModsDirectory,
|
|
535796
535947
|
disabled: modsDisabled
|
|
@@ -536563,9 +536714,9 @@ Memory may be stale. Try running: git -C ${getScopedMemoryFilesystemRoot(agentId
|
|
|
536563
536714
|
(async () => {
|
|
536564
536715
|
try {
|
|
536565
536716
|
const { watch: watch3 } = await import("node:fs");
|
|
536566
|
-
const { existsSync:
|
|
536717
|
+
const { existsSync: existsSync69 } = await import("node:fs");
|
|
536567
536718
|
const memRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
536568
|
-
if (!
|
|
536719
|
+
if (!existsSync69(memRoot))
|
|
536569
536720
|
return;
|
|
536570
536721
|
watcher2 = watch3(memRoot, { recursive: true }, () => {});
|
|
536571
536722
|
memfsWatcherRef.current = watcher2;
|
|
@@ -537890,13 +538041,13 @@ __export(exports_terminal_keybinding_installer2, {
|
|
|
537890
538041
|
});
|
|
537891
538042
|
import {
|
|
537892
538043
|
copyFileSync as copyFileSync6,
|
|
537893
|
-
existsSync as
|
|
537894
|
-
mkdirSync as
|
|
538044
|
+
existsSync as existsSync69,
|
|
538045
|
+
mkdirSync as mkdirSync47,
|
|
537895
538046
|
readFileSync as readFileSync44,
|
|
537896
|
-
writeFileSync as
|
|
538047
|
+
writeFileSync as writeFileSync36
|
|
537897
538048
|
} from "node:fs";
|
|
537898
538049
|
import { homedir as homedir49, platform as platform11 } from "node:os";
|
|
537899
|
-
import { dirname as dirname37, join as
|
|
538050
|
+
import { dirname as dirname37, join as join82 } from "node:path";
|
|
537900
538051
|
function detectTerminalType2() {
|
|
537901
538052
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
537902
538053
|
return "cursor";
|
|
@@ -537928,16 +538079,16 @@ function getKeybindingsPath2(terminal) {
|
|
|
537928
538079
|
}[terminal];
|
|
537929
538080
|
const os10 = platform11();
|
|
537930
538081
|
if (os10 === "darwin") {
|
|
537931
|
-
return
|
|
538082
|
+
return join82(homedir49(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
537932
538083
|
}
|
|
537933
538084
|
if (os10 === "win32") {
|
|
537934
538085
|
const appData = process.env.APPDATA;
|
|
537935
538086
|
if (!appData)
|
|
537936
538087
|
return null;
|
|
537937
|
-
return
|
|
538088
|
+
return join82(appData, appName, "User", "keybindings.json");
|
|
537938
538089
|
}
|
|
537939
538090
|
if (os10 === "linux") {
|
|
537940
|
-
return
|
|
538091
|
+
return join82(homedir49(), ".config", appName, "User", "keybindings.json");
|
|
537941
538092
|
}
|
|
537942
538093
|
return null;
|
|
537943
538094
|
}
|
|
@@ -537959,7 +538110,7 @@ function parseKeybindings2(content) {
|
|
|
537959
538110
|
}
|
|
537960
538111
|
}
|
|
537961
538112
|
function keybindingExists2(keybindingsPath) {
|
|
537962
|
-
if (!
|
|
538113
|
+
if (!existsSync69(keybindingsPath))
|
|
537963
538114
|
return false;
|
|
537964
538115
|
try {
|
|
537965
538116
|
const content = readFileSync44(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -537972,7 +538123,7 @@ function keybindingExists2(keybindingsPath) {
|
|
|
537972
538123
|
}
|
|
537973
538124
|
}
|
|
537974
538125
|
function createBackup2(keybindingsPath) {
|
|
537975
|
-
if (!
|
|
538126
|
+
if (!existsSync69(keybindingsPath))
|
|
537976
538127
|
return null;
|
|
537977
538128
|
const backupPath = `${keybindingsPath}.letta-backup`;
|
|
537978
538129
|
try {
|
|
@@ -537988,12 +538139,12 @@ function installKeybinding2(keybindingsPath) {
|
|
|
537988
538139
|
return { success: true, alreadyExists: true };
|
|
537989
538140
|
}
|
|
537990
538141
|
const parentDir = dirname37(keybindingsPath);
|
|
537991
|
-
if (!
|
|
537992
|
-
|
|
538142
|
+
if (!existsSync69(parentDir)) {
|
|
538143
|
+
mkdirSync47(parentDir, { recursive: true });
|
|
537993
538144
|
}
|
|
537994
538145
|
let keybindings = [];
|
|
537995
538146
|
let backupPath = null;
|
|
537996
|
-
if (
|
|
538147
|
+
if (existsSync69(keybindingsPath)) {
|
|
537997
538148
|
backupPath = createBackup2(keybindingsPath);
|
|
537998
538149
|
const content = readFileSync44(keybindingsPath, { encoding: "utf-8" });
|
|
537999
538150
|
const parsed = parseKeybindings2(content);
|
|
@@ -538008,7 +538159,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
538008
538159
|
keybindings.push(SHIFT_ENTER_KEYBINDING2);
|
|
538009
538160
|
const newContent = `${JSON.stringify(keybindings, null, 2)}
|
|
538010
538161
|
`;
|
|
538011
|
-
|
|
538162
|
+
writeFileSync36(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
538012
538163
|
return {
|
|
538013
538164
|
success: true,
|
|
538014
538165
|
backupPath: backupPath ?? undefined
|
|
@@ -538023,7 +538174,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
538023
538174
|
}
|
|
538024
538175
|
function removeKeybinding2(keybindingsPath) {
|
|
538025
538176
|
try {
|
|
538026
|
-
if (!
|
|
538177
|
+
if (!existsSync69(keybindingsPath)) {
|
|
538027
538178
|
return { success: true };
|
|
538028
538179
|
}
|
|
538029
538180
|
const content = readFileSync44(keybindingsPath, { encoding: "utf-8" });
|
|
@@ -538037,7 +538188,7 @@ function removeKeybinding2(keybindingsPath) {
|
|
|
538037
538188
|
const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
|
|
538038
538189
|
const newContent = `${JSON.stringify(filtered, null, 2)}
|
|
538039
538190
|
`;
|
|
538040
|
-
|
|
538191
|
+
writeFileSync36(keybindingsPath, newContent, { encoding: "utf-8" });
|
|
538041
538192
|
return { success: true };
|
|
538042
538193
|
} catch (error54) {
|
|
538043
538194
|
const message = error54 instanceof Error ? error54.message : String(error54);
|
|
@@ -538090,14 +538241,14 @@ function getWezTermConfigPath2() {
|
|
|
538090
538241
|
}
|
|
538091
538242
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
538092
538243
|
if (xdgConfig) {
|
|
538093
|
-
const xdgPath =
|
|
538094
|
-
if (
|
|
538244
|
+
const xdgPath = join82(xdgConfig, "wezterm", "wezterm.lua");
|
|
538245
|
+
if (existsSync69(xdgPath))
|
|
538095
538246
|
return xdgPath;
|
|
538096
538247
|
}
|
|
538097
|
-
const configPath =
|
|
538098
|
-
if (
|
|
538248
|
+
const configPath = join82(homedir49(), ".config", "wezterm", "wezterm.lua");
|
|
538249
|
+
if (existsSync69(configPath))
|
|
538099
538250
|
return configPath;
|
|
538100
|
-
return
|
|
538251
|
+
return join82(homedir49(), ".wezterm.lua");
|
|
538101
538252
|
}
|
|
538102
538253
|
function stripLuaCommentsFromLine2(line, blockCommentEnd) {
|
|
538103
538254
|
let code2 = "";
|
|
@@ -538200,7 +538351,7 @@ ${WEZTERM_DELETE_FIX2}
|
|
|
538200
538351
|
`;
|
|
538201
538352
|
}
|
|
538202
538353
|
function wezTermDeleteFixExists2(configPath) {
|
|
538203
|
-
if (!
|
|
538354
|
+
if (!existsSync69(configPath))
|
|
538204
538355
|
return false;
|
|
538205
538356
|
try {
|
|
538206
538357
|
const content = readFileSync44(configPath, { encoding: "utf-8" });
|
|
@@ -538217,17 +538368,17 @@ function installWezTermDeleteFix2() {
|
|
|
538217
538368
|
}
|
|
538218
538369
|
let content = "";
|
|
538219
538370
|
let backupPath = null;
|
|
538220
|
-
if (
|
|
538371
|
+
if (existsSync69(configPath)) {
|
|
538221
538372
|
backupPath = `${configPath}.letta-backup`;
|
|
538222
538373
|
copyFileSync6(configPath, backupPath);
|
|
538223
538374
|
content = readFileSync44(configPath, { encoding: "utf-8" });
|
|
538224
538375
|
}
|
|
538225
538376
|
content = injectWezTermDeleteFix2(content);
|
|
538226
538377
|
const parentDir = dirname37(configPath);
|
|
538227
|
-
if (!
|
|
538228
|
-
|
|
538378
|
+
if (!existsSync69(parentDir)) {
|
|
538379
|
+
mkdirSync47(parentDir, { recursive: true });
|
|
538229
538380
|
}
|
|
538230
|
-
|
|
538381
|
+
writeFileSync36(configPath, content, { encoding: "utf-8" });
|
|
538231
538382
|
return {
|
|
538232
538383
|
success: true,
|
|
538233
538384
|
backupPath: backupPath ?? undefined
|
|
@@ -538276,9 +538427,9 @@ __export(exports_settings3, {
|
|
|
538276
538427
|
getSetting: () => getSetting2
|
|
538277
538428
|
});
|
|
538278
538429
|
import { homedir as homedir50 } from "node:os";
|
|
538279
|
-
import { join as
|
|
538430
|
+
import { join as join83 } from "node:path";
|
|
538280
538431
|
function getSettingsPath2() {
|
|
538281
|
-
return
|
|
538432
|
+
return join83(homedir50(), ".letta", "settings.json");
|
|
538282
538433
|
}
|
|
538283
538434
|
async function loadSettings2() {
|
|
538284
538435
|
const settingsPath = getSettingsPath2();
|
|
@@ -538315,7 +538466,7 @@ async function getSetting2(key2) {
|
|
|
538315
538466
|
return settings3[key2];
|
|
538316
538467
|
}
|
|
538317
538468
|
function getProjectSettingsPath2() {
|
|
538318
|
-
return
|
|
538469
|
+
return join83(process.cwd(), ".letta", "settings.local.json");
|
|
538319
538470
|
}
|
|
538320
538471
|
async function loadProjectSettings2() {
|
|
538321
538472
|
const settingsPath = getProjectSettingsPath2();
|
|
@@ -538333,7 +538484,7 @@ async function loadProjectSettings2() {
|
|
|
538333
538484
|
}
|
|
538334
538485
|
async function saveProjectSettings2(settings3) {
|
|
538335
538486
|
const settingsPath = getProjectSettingsPath2();
|
|
538336
|
-
const dirPath =
|
|
538487
|
+
const dirPath = join83(process.cwd(), ".letta");
|
|
538337
538488
|
try {
|
|
538338
538489
|
if (!exists(dirPath)) {
|
|
538339
538490
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -539006,7 +539157,7 @@ function parseRegistryHandle2(handle2) {
|
|
|
539006
539157
|
}
|
|
539007
539158
|
async function importAgentFromRegistry2(options3) {
|
|
539008
539159
|
const { tmpdir: tmpdir12 } = await import("node:os");
|
|
539009
|
-
const { join:
|
|
539160
|
+
const { join: join84 } = await import("node:path");
|
|
539010
539161
|
const { writeFile: writeFile23, unlink: unlink5 } = await import("node:fs/promises");
|
|
539011
539162
|
const { author, name } = parseRegistryHandle2(options3.handle);
|
|
539012
539163
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
|
|
@@ -539018,7 +539169,7 @@ async function importAgentFromRegistry2(options3) {
|
|
|
539018
539169
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
539019
539170
|
}
|
|
539020
539171
|
const afContent = await response.text();
|
|
539021
|
-
const tempPath =
|
|
539172
|
+
const tempPath = join84(tmpdir12(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
539022
539173
|
await writeFile23(tempPath, afContent, "utf-8");
|
|
539023
539174
|
try {
|
|
539024
539175
|
const result = await importAgentFromFile2({
|
|
@@ -539072,14 +539223,14 @@ __export(exports_memory_filesystem2, {
|
|
|
539072
539223
|
MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
|
|
539073
539224
|
MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
|
|
539074
539225
|
});
|
|
539075
|
-
import { existsSync as
|
|
539226
|
+
import { existsSync as existsSync70, mkdirSync as mkdirSync48 } from "node:fs";
|
|
539076
539227
|
import { homedir as homedir51 } from "node:os";
|
|
539077
|
-
import { join as
|
|
539228
|
+
import { join as join84, resolve as resolve42 } from "node:path";
|
|
539078
539229
|
function getMemoryFilesystemRoot2(agentId, homeDir = homedir51()) {
|
|
539079
|
-
return
|
|
539230
|
+
return join84(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
539080
539231
|
}
|
|
539081
539232
|
function getMemorySystemDir2(agentId, homeDir = homedir51()) {
|
|
539082
|
-
return
|
|
539233
|
+
return join84(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
|
|
539083
539234
|
}
|
|
539084
539235
|
function getScopedMemoryFilesystemRoot2(agentId, options3 = {}) {
|
|
539085
539236
|
const env6 = options3.env ?? process.env;
|
|
@@ -539115,11 +539266,11 @@ function resolveScopedMemoryDir2(options3 = {}) {
|
|
|
539115
539266
|
function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir51()) {
|
|
539116
539267
|
const root2 = getMemoryFilesystemRoot2(agentId, homeDir);
|
|
539117
539268
|
const systemDir = getMemorySystemDir2(agentId, homeDir);
|
|
539118
|
-
if (!
|
|
539119
|
-
|
|
539269
|
+
if (!existsSync70(root2)) {
|
|
539270
|
+
mkdirSync48(root2, { recursive: true });
|
|
539120
539271
|
}
|
|
539121
|
-
if (!
|
|
539122
|
-
|
|
539272
|
+
if (!existsSync70(systemDir)) {
|
|
539273
|
+
mkdirSync48(systemDir, { recursive: true });
|
|
539123
539274
|
}
|
|
539124
539275
|
}
|
|
539125
539276
|
function stampMemfsTagOnCreateBody2(body3, gitMemoryEnabledTag) {
|
|
@@ -539424,8 +539575,8 @@ __export(exports_secrets_store2, {
|
|
|
539424
539575
|
__testOverrideSecretsBackend: () => __testOverrideSecretsBackend2,
|
|
539425
539576
|
__testOverrideLocalSecretStorage: () => __testOverrideLocalSecretStorage2
|
|
539426
539577
|
});
|
|
539427
|
-
import { existsSync as
|
|
539428
|
-
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";
|
|
539429
539580
|
function __testOverrideSecretsBackend2(backend4) {
|
|
539430
539581
|
testBackendOverride2 = backend4;
|
|
539431
539582
|
}
|
|
@@ -539436,11 +539587,11 @@ function getSecretsBackend2() {
|
|
|
539436
539587
|
return testBackendOverride2 ?? getBackend();
|
|
539437
539588
|
}
|
|
539438
539589
|
function getFileBackedLocalSecretsPath2() {
|
|
539439
|
-
return
|
|
539590
|
+
return join85(getLocalBackendStorageDir(), FILE_BACKED_LOCAL_SECRETS_PATH2);
|
|
539440
539591
|
}
|
|
539441
539592
|
function readFileBackedLocalSecrets2() {
|
|
539442
539593
|
const filePath = getFileBackedLocalSecretsPath2();
|
|
539443
|
-
if (!
|
|
539594
|
+
if (!existsSync71(filePath))
|
|
539444
539595
|
return {};
|
|
539445
539596
|
try {
|
|
539446
539597
|
const parsed = JSON.parse(readFileSync45(filePath, "utf8"));
|
|
@@ -539453,8 +539604,8 @@ function readFileBackedLocalSecrets2() {
|
|
|
539453
539604
|
}
|
|
539454
539605
|
function writeFileBackedLocalSecrets2(secrets2) {
|
|
539455
539606
|
const filePath = getFileBackedLocalSecretsPath2();
|
|
539456
|
-
|
|
539457
|
-
|
|
539607
|
+
mkdirSync49(dirname39(filePath), { mode: 448, recursive: true });
|
|
539608
|
+
writeFileSync37(filePath, `${JSON.stringify({ secrets: secrets2 }, null, 2)}
|
|
539458
539609
|
`, {
|
|
539459
539610
|
encoding: "utf8",
|
|
539460
539611
|
flush: true,
|
|
@@ -539749,7 +539900,7 @@ var init_secrets_store2 = __esm(() => {
|
|
|
539749
539900
|
init_backend2();
|
|
539750
539901
|
init_paths();
|
|
539751
539902
|
init_secrets();
|
|
539752
|
-
FILE_BACKED_LOCAL_SECRETS_PATH2 =
|
|
539903
|
+
FILE_BACKED_LOCAL_SECRETS_PATH2 = join85("secrets", "local-agent-secrets.json");
|
|
539753
539904
|
SECRETS_CACHE_KEY2 = Symbol.for("@letta/secretsCache");
|
|
539754
539905
|
LOCAL_SECRET_NAME_PATTERN2 = /^[A-Z_][A-Z0-9_]*$/;
|
|
539755
539906
|
});
|
|
@@ -542948,21 +543099,21 @@ import { spawn as spawn9, spawnSync as spawnSync3 } from "node:child_process";
|
|
|
542948
543099
|
import {
|
|
542949
543100
|
chmodSync as chmodSync5,
|
|
542950
543101
|
createWriteStream as createWriteStream3,
|
|
542951
|
-
existsSync as
|
|
542952
|
-
mkdirSync as
|
|
543102
|
+
existsSync as existsSync37,
|
|
543103
|
+
mkdirSync as mkdirSync25,
|
|
542953
543104
|
readdirSync as readdirSync12,
|
|
542954
543105
|
renameSync as renameSync3,
|
|
542955
543106
|
rmSync as rmSync7,
|
|
542956
543107
|
statSync as statSync11
|
|
542957
543108
|
} from "node:fs";
|
|
542958
543109
|
import { arch as arch2, homedir as homedir27, platform as platform5 } from "node:os";
|
|
542959
|
-
import { basename as basename19, join as
|
|
543110
|
+
import { basename as basename19, join as join42 } from "node:path";
|
|
542960
543111
|
import { Readable as Readable3 } from "node:stream";
|
|
542961
543112
|
import { pipeline as pipeline6 } from "node:stream/promises";
|
|
542962
543113
|
var PATH_DELIMITERS = new Set([" ", "\t", '"', "'", "="]);
|
|
542963
|
-
var FD_TOOLS_DIR =
|
|
543114
|
+
var FD_TOOLS_DIR = join42(homedir27(), ".letta", "bin");
|
|
542964
543115
|
var FD_BINARY_NAME = platform5() === "win32" ? "fd.exe" : "fd";
|
|
542965
|
-
var FD_LOCAL_PATH =
|
|
543116
|
+
var FD_LOCAL_PATH = join42(FD_TOOLS_DIR, FD_BINARY_NAME);
|
|
542966
543117
|
var FD_DOWNLOAD_REPO = "sharkdp/fd";
|
|
542967
543118
|
var FD_DOWNLOAD_TIMEOUT_MS = 120000;
|
|
542968
543119
|
var FD_NETWORK_TIMEOUT_MS = 1e4;
|
|
@@ -543049,8 +543200,8 @@ function extractTarGzArchive2(archivePath, extractDir) {
|
|
|
543049
543200
|
function getWindowsTarCommand2() {
|
|
543050
543201
|
const systemRoot = process.env.SystemRoot ?? process.env.WINDIR;
|
|
543051
543202
|
if (systemRoot) {
|
|
543052
|
-
const systemTar =
|
|
543053
|
-
if (
|
|
543203
|
+
const systemTar = join42(systemRoot, "System32", "tar.exe");
|
|
543204
|
+
if (existsSync37(systemTar)) {
|
|
543054
543205
|
return systemTar;
|
|
543055
543206
|
}
|
|
543056
543207
|
}
|
|
@@ -543112,7 +543263,7 @@ function findBinaryRecursively2(rootDir, binaryName2) {
|
|
|
543112
543263
|
if (!currentDir)
|
|
543113
543264
|
continue;
|
|
543114
543265
|
for (const entry of readdirSync12(currentDir, { withFileTypes: true })) {
|
|
543115
|
-
const fullPath =
|
|
543266
|
+
const fullPath = join42(currentDir, entry.name);
|
|
543116
543267
|
if (entry.isFile() && entry.name === binaryName2) {
|
|
543117
543268
|
return fullPath;
|
|
543118
543269
|
}
|
|
@@ -543132,10 +543283,10 @@ async function downloadFd() {
|
|
|
543132
543283
|
if (!assetName) {
|
|
543133
543284
|
throw new Error(`Unsupported platform: ${platform5()}/${arch2()}`);
|
|
543134
543285
|
}
|
|
543135
|
-
|
|
543136
|
-
const archivePath =
|
|
543137
|
-
const extractDir =
|
|
543138
|
-
|
|
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 });
|
|
543139
543290
|
try {
|
|
543140
543291
|
await downloadFile3(`https://github.com/${FD_DOWNLOAD_REPO}/releases/download/v${version2}/${assetName}`, archivePath);
|
|
543141
543292
|
if (assetName.endsWith(".tar.gz")) {
|
|
@@ -543163,7 +543314,7 @@ function resolveFdPath() {
|
|
|
543163
543314
|
if (cachedFdPath !== undefined) {
|
|
543164
543315
|
return cachedFdPath;
|
|
543165
543316
|
}
|
|
543166
|
-
if (
|
|
543317
|
+
if (existsSync37(FD_LOCAL_PATH)) {
|
|
543167
543318
|
cachedFdPath = FD_LOCAL_PATH;
|
|
543168
543319
|
return cachedFdPath;
|
|
543169
543320
|
}
|
|
@@ -546203,7 +546354,7 @@ import { createHash as createHash6 } from "node:crypto";
|
|
|
546203
546354
|
|
|
546204
546355
|
// src/cli/subcommands/dream-sources/openhands.ts
|
|
546205
546356
|
import { readdir as readdir12, readFile as readFile19, stat as stat14 } from "node:fs/promises";
|
|
546206
|
-
import { join as
|
|
546357
|
+
import { join as join52 } from "node:path";
|
|
546207
546358
|
var RESULT_TEXT_TRUNCATE_LIMIT = 4000;
|
|
546208
546359
|
function joinTextContent(content) {
|
|
546209
546360
|
if (!Array.isArray(content))
|
|
@@ -546318,7 +546469,7 @@ function eventSequence(fileName) {
|
|
|
546318
546469
|
async function readOpenHandsEventDir(dir) {
|
|
546319
546470
|
let eventsDir = dir;
|
|
546320
546471
|
try {
|
|
546321
|
-
const nested =
|
|
546472
|
+
const nested = join52(dir, "events");
|
|
546322
546473
|
if ((await stat14(nested)).isDirectory()) {
|
|
546323
546474
|
eventsDir = nested;
|
|
546324
546475
|
}
|
|
@@ -546329,7 +546480,7 @@ async function readOpenHandsEventDir(dir) {
|
|
|
546329
546480
|
}
|
|
546330
546481
|
const events = [];
|
|
546331
546482
|
for (const name of fileNames) {
|
|
546332
|
-
const raw2 = await readFile19(
|
|
546483
|
+
const raw2 = await readFile19(join52(eventsDir, name), "utf-8");
|
|
546333
546484
|
const event2 = safeJsonParseOr(raw2, null);
|
|
546334
546485
|
if (event2 && typeof event2 === "object") {
|
|
546335
546486
|
events.push(event2);
|
|
@@ -546407,7 +546558,7 @@ init_memory_filesystem2();
|
|
|
546407
546558
|
init_memory_git();
|
|
546408
546559
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
546409
546560
|
import { mkdir as mkdir13, readFile as readFile21, rm as rm5, writeFile as writeFile15 } from "node:fs/promises";
|
|
546410
|
-
import { basename as basename25, dirname as dirname27, join as
|
|
546561
|
+
import { basename as basename25, dirname as dirname27, join as join53 } from "node:path";
|
|
546411
546562
|
function resolveDreamTarget(spec) {
|
|
546412
546563
|
const fileName = basename25(spec);
|
|
546413
546564
|
if (!fileName) {
|
|
@@ -546508,7 +546659,7 @@ async function syncTargetIntoMemory(agentId, target2, content) {
|
|
|
546508
546659
|
if (committed !== null && stripFrontmatter(committed) === stripFrontmatter(content)) {
|
|
546509
546660
|
return { synced: false };
|
|
546510
546661
|
}
|
|
546511
|
-
const absPath =
|
|
546662
|
+
const absPath = join53(memoryDir, relPath);
|
|
546512
546663
|
await mkdir13(dirname27(absPath), { recursive: true });
|
|
546513
546664
|
await writeFile15(absPath, addManagedFrontmatter(content, target2.kind), "utf-8");
|
|
546514
546665
|
try {
|
|
@@ -547071,14 +547222,14 @@ init_telemetry();
|
|
|
547071
547222
|
// src/websocket/listen-log.ts
|
|
547072
547223
|
import {
|
|
547073
547224
|
appendFileSync as appendFileSync7,
|
|
547074
|
-
existsSync as
|
|
547075
|
-
mkdirSync as
|
|
547225
|
+
existsSync as existsSync46,
|
|
547226
|
+
mkdirSync as mkdirSync32,
|
|
547076
547227
|
readdirSync as readdirSync16,
|
|
547077
547228
|
unlinkSync as unlinkSync7
|
|
547078
547229
|
} from "node:fs";
|
|
547079
547230
|
import { homedir as homedir31 } from "node:os";
|
|
547080
|
-
import { join as
|
|
547081
|
-
var REMOTE_LOG_DIR =
|
|
547231
|
+
import { join as join54 } from "node:path";
|
|
547232
|
+
var REMOTE_LOG_DIR = join54(homedir31(), ".letta", "logs", "remote");
|
|
547082
547233
|
var MAX_LOG_FILES = 10;
|
|
547083
547234
|
function formatTimestamp2() {
|
|
547084
547235
|
const now = new Date;
|
|
@@ -547090,14 +547241,14 @@ function formatTimestamp2() {
|
|
|
547090
547241
|
}
|
|
547091
547242
|
function pruneOldLogs() {
|
|
547092
547243
|
try {
|
|
547093
|
-
if (!
|
|
547244
|
+
if (!existsSync46(REMOTE_LOG_DIR))
|
|
547094
547245
|
return;
|
|
547095
547246
|
const files = readdirSync16(REMOTE_LOG_DIR).filter((f4) => f4.endsWith(".log")).sort();
|
|
547096
547247
|
if (files.length >= MAX_LOG_FILES) {
|
|
547097
547248
|
const toDelete = files.slice(0, files.length - MAX_LOG_FILES + 1);
|
|
547098
547249
|
for (const file3 of toDelete) {
|
|
547099
547250
|
try {
|
|
547100
|
-
unlinkSync7(
|
|
547251
|
+
unlinkSync7(join54(REMOTE_LOG_DIR, file3));
|
|
547101
547252
|
} catch {}
|
|
547102
547253
|
}
|
|
547103
547254
|
}
|
|
@@ -547110,7 +547261,7 @@ class RemoteSessionLog {
|
|
|
547110
547261
|
constructor() {
|
|
547111
547262
|
const now = new Date;
|
|
547112
547263
|
const stamp = now.toISOString().replace(/[:.]/g, "-");
|
|
547113
|
-
this.path =
|
|
547264
|
+
this.path = join54(REMOTE_LOG_DIR, `${stamp}.log`);
|
|
547114
547265
|
}
|
|
547115
547266
|
init() {
|
|
547116
547267
|
this.ensureDir();
|
|
@@ -547137,8 +547288,8 @@ class RemoteSessionLog {
|
|
|
547137
547288
|
if (this.dirCreated)
|
|
547138
547289
|
return;
|
|
547139
547290
|
try {
|
|
547140
|
-
if (!
|
|
547141
|
-
|
|
547291
|
+
if (!existsSync46(REMOTE_LOG_DIR)) {
|
|
547292
|
+
mkdirSync32(REMOTE_LOG_DIR, { recursive: true });
|
|
547142
547293
|
}
|
|
547143
547294
|
this.dirCreated = true;
|
|
547144
547295
|
} catch {}
|
|
@@ -547733,15 +547884,15 @@ init_local_store();
|
|
|
547733
547884
|
import { randomUUID as randomUUID24 } from "node:crypto";
|
|
547734
547885
|
import {
|
|
547735
547886
|
copyFileSync as copyFileSync2,
|
|
547736
|
-
existsSync as
|
|
547737
|
-
mkdirSync as
|
|
547887
|
+
existsSync as existsSync47,
|
|
547888
|
+
mkdirSync as mkdirSync33,
|
|
547738
547889
|
readdirSync as readdirSync17,
|
|
547739
547890
|
readFileSync as readFileSync32,
|
|
547740
|
-
writeFileSync as
|
|
547891
|
+
writeFileSync as writeFileSync24
|
|
547741
547892
|
} from "node:fs";
|
|
547742
|
-
import { join as
|
|
547893
|
+
import { join as join55 } from "node:path";
|
|
547743
547894
|
function readJsonl(path37) {
|
|
547744
|
-
if (!
|
|
547895
|
+
if (!existsSync47(path37))
|
|
547745
547896
|
return [];
|
|
547746
547897
|
return readFileSync32(path37, "utf8").split(`
|
|
547747
547898
|
`).filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
@@ -547753,7 +547904,7 @@ function isPiLocalMessage(value) {
|
|
|
547753
547904
|
return isRecord(value) && typeof value.id === "string" && (value.role === "user" || value.role === "assistant" || value.role === "toolResult") && Object.hasOwn(value, "content");
|
|
547754
547905
|
}
|
|
547755
547906
|
function writeJsonl(path37, items3) {
|
|
547756
|
-
|
|
547907
|
+
writeFileSync24(path37, `${items3.map((item) => JSON.stringify(item)).join(`
|
|
547757
547908
|
`)}
|
|
547758
547909
|
`);
|
|
547759
547910
|
}
|
|
@@ -548022,20 +548173,20 @@ function convertMessages4(messages, mode, nextId2) {
|
|
|
548022
548173
|
}
|
|
548023
548174
|
function migrateLocalBackendTranscripts(input) {
|
|
548024
548175
|
const storageDir = input.storageDir;
|
|
548025
|
-
const conversationsDir =
|
|
548176
|
+
const conversationsDir = join55(storageDir, "conversations");
|
|
548026
548177
|
const result = {
|
|
548027
548178
|
storageDir,
|
|
548028
548179
|
converted: [],
|
|
548029
548180
|
skipped: [],
|
|
548030
548181
|
dryRun: input.dryRun === true
|
|
548031
548182
|
};
|
|
548032
|
-
if (!
|
|
548183
|
+
if (!existsSync47(conversationsDir))
|
|
548033
548184
|
return result;
|
|
548034
548185
|
for (const name of readdirSync17(conversationsDir)) {
|
|
548035
|
-
const conversationDir =
|
|
548036
|
-
const messagesPath =
|
|
548037
|
-
const manifestPath =
|
|
548038
|
-
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);
|
|
548039
548190
|
const existingManifest = hasManifest ? (() => {
|
|
548040
548191
|
try {
|
|
548041
548192
|
return JSON.parse(readFileSync32(manifestPath, "utf8"));
|
|
@@ -548053,8 +548204,8 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
548053
548204
|
if (legacyMessages.length === 0) {
|
|
548054
548205
|
result.skipped.push({ conversationDir, reason: "empty" });
|
|
548055
548206
|
if (!input.dryRun) {
|
|
548056
|
-
|
|
548057
|
-
|
|
548207
|
+
mkdirSync33(conversationDir, { recursive: true });
|
|
548208
|
+
writeFileSync24(manifestPath, `${JSON.stringify(manifest({}), null, 2)}
|
|
548058
548209
|
`);
|
|
548059
548210
|
}
|
|
548060
548211
|
continue;
|
|
@@ -548077,9 +548228,9 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
548077
548228
|
const backupPath = `${messagesPath}.pre-pi-backup-${timestampSuffix()}`;
|
|
548078
548229
|
if (!input.dryRun) {
|
|
548079
548230
|
copyFileSync2(messagesPath, backupPath);
|
|
548080
|
-
const conversationPath =
|
|
548231
|
+
const conversationPath = join55(conversationDir, "conversation.json");
|
|
548081
548232
|
let conversation;
|
|
548082
|
-
if (
|
|
548233
|
+
if (existsSync47(conversationPath)) {
|
|
548083
548234
|
try {
|
|
548084
548235
|
conversation = JSON.parse(readFileSync32(conversationPath, "utf8"));
|
|
548085
548236
|
} catch {
|
|
@@ -548107,12 +548258,12 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
548107
548258
|
}
|
|
548108
548259
|
}
|
|
548109
548260
|
conversation.in_context_message_ids = remapped;
|
|
548110
|
-
|
|
548261
|
+
writeFileSync24(conversationPath, `${JSON.stringify(conversation, null, 2)}
|
|
548111
548262
|
`);
|
|
548112
548263
|
}
|
|
548113
548264
|
} catch {}
|
|
548114
548265
|
}
|
|
548115
|
-
|
|
548266
|
+
writeFileSync24(manifestPath, `${JSON.stringify(manifest({
|
|
548116
548267
|
backupPath,
|
|
548117
548268
|
migratedFrom: repairVersioned ? hasLegacyUiRows ? "versioned-pi-transcript-with-legacy-ui-message-rows" : "versioned-pi-ai-message-jsonl" : undefined
|
|
548118
548269
|
}), null, 2)}
|
|
@@ -548189,9 +548340,9 @@ async function runLocalBackendSubcommand(argv) {
|
|
|
548189
548340
|
init_memory_filesystem2();
|
|
548190
548341
|
init_memory_git();
|
|
548191
548342
|
init_paths();
|
|
548192
|
-
import { cpSync, existsSync as
|
|
548343
|
+
import { cpSync, existsSync as existsSync48, mkdirSync as mkdirSync34, rmSync as rmSync10, statSync as statSync16 } from "node:fs";
|
|
548193
548344
|
import { readdir as readdir13 } from "node:fs/promises";
|
|
548194
|
-
import { dirname as dirname28, join as
|
|
548345
|
+
import { dirname as dirname28, join as join56 } from "node:path";
|
|
548195
548346
|
import { parseArgs as parseArgs11 } from "node:util";
|
|
548196
548347
|
|
|
548197
548348
|
// src/cli/subcommands/memory-tokens.ts
|
|
@@ -548343,7 +548494,7 @@ function formatBackupTimestamp(date6 = new Date) {
|
|
|
548343
548494
|
}
|
|
548344
548495
|
async function listBackups(agentId) {
|
|
548345
548496
|
const agentRoot = getAgentRoot(agentId);
|
|
548346
|
-
if (!
|
|
548497
|
+
if (!existsSync48(agentRoot)) {
|
|
548347
548498
|
return [];
|
|
548348
548499
|
}
|
|
548349
548500
|
const entries = await readdir13(agentRoot, { withFileTypes: true });
|
|
@@ -548353,7 +548504,7 @@ async function listBackups(agentId) {
|
|
|
548353
548504
|
continue;
|
|
548354
548505
|
if (!entry.name.startsWith("memory-backup-"))
|
|
548355
548506
|
continue;
|
|
548356
|
-
const path37 =
|
|
548507
|
+
const path37 = join56(agentRoot, entry.name);
|
|
548357
548508
|
let createdAt = null;
|
|
548358
548509
|
try {
|
|
548359
548510
|
const stat15 = statSync16(path37);
|
|
@@ -548370,7 +548521,7 @@ function resolveBackupPath(agentId, from) {
|
|
|
548370
548521
|
if (from.startsWith("/") || /^[A-Za-z]:[/\\]/.test(from)) {
|
|
548371
548522
|
return from;
|
|
548372
548523
|
}
|
|
548373
|
-
return
|
|
548524
|
+
return join56(getAgentRoot(agentId), from);
|
|
548374
548525
|
}
|
|
548375
548526
|
async function runMemorySubcommand(argv) {
|
|
548376
548527
|
let parsed;
|
|
@@ -548446,14 +548597,14 @@ async function runMemorySubcommand(argv) {
|
|
|
548446
548597
|
}
|
|
548447
548598
|
if (action3 === "backup") {
|
|
548448
548599
|
const root2 = getMemoryRoot(agentId);
|
|
548449
|
-
if (!
|
|
548600
|
+
if (!existsSync48(root2)) {
|
|
548450
548601
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
548451
548602
|
return 1;
|
|
548452
548603
|
}
|
|
548453
548604
|
const agentRoot = getAgentRoot(agentId);
|
|
548454
548605
|
const backupName = `memory-backup-${formatBackupTimestamp()}`;
|
|
548455
|
-
const backupPath =
|
|
548456
|
-
if (
|
|
548606
|
+
const backupPath = join56(agentRoot, backupName);
|
|
548607
|
+
if (existsSync48(backupPath)) {
|
|
548457
548608
|
console.error(`Backup already exists at ${backupPath}`);
|
|
548458
548609
|
return 1;
|
|
548459
548610
|
}
|
|
@@ -548477,7 +548628,7 @@ async function runMemorySubcommand(argv) {
|
|
|
548477
548628
|
return 1;
|
|
548478
548629
|
}
|
|
548479
548630
|
const backupPath = resolveBackupPath(agentId, from);
|
|
548480
|
-
if (!
|
|
548631
|
+
if (!existsSync48(backupPath)) {
|
|
548481
548632
|
console.error(`Backup not found: ${backupPath}`);
|
|
548482
548633
|
return 1;
|
|
548483
548634
|
}
|
|
@@ -548499,11 +548650,11 @@ async function runMemorySubcommand(argv) {
|
|
|
548499
548650
|
return 1;
|
|
548500
548651
|
}
|
|
548501
548652
|
const root2 = getMemoryRoot(agentId);
|
|
548502
|
-
if (!
|
|
548653
|
+
if (!existsSync48(root2)) {
|
|
548503
548654
|
console.error(`Memory directory not found for agent ${agentId}.`);
|
|
548504
548655
|
return 1;
|
|
548505
548656
|
}
|
|
548506
|
-
if (
|
|
548657
|
+
if (existsSync48(out)) {
|
|
548507
548658
|
const stat15 = statSync16(out);
|
|
548508
548659
|
if (stat15.isDirectory()) {
|
|
548509
548660
|
const contents = await readdir13(out);
|
|
@@ -548516,7 +548667,7 @@ async function runMemorySubcommand(argv) {
|
|
|
548516
548667
|
return 1;
|
|
548517
548668
|
}
|
|
548518
548669
|
} else {
|
|
548519
|
-
|
|
548670
|
+
mkdirSync34(out, { recursive: true });
|
|
548520
548671
|
}
|
|
548521
548672
|
cpSync(root2, out, { recursive: true });
|
|
548522
548673
|
console.log(JSON.stringify({ exportedFrom: root2, exportedTo: out, agentId }, null, 2));
|
|
@@ -548910,7 +549061,7 @@ async function runMessagesSubcommand(argv, deps = {}) {
|
|
|
548910
549061
|
// src/cli/subcommands/mods.ts
|
|
548911
549062
|
init_memory_filesystem2();
|
|
548912
549063
|
await init_mod_engine();
|
|
548913
|
-
import { dirname as dirname29, join as
|
|
549064
|
+
import { dirname as dirname29, join as join58 } from "node:path";
|
|
548914
549065
|
import { parseArgs as parseArgs13 } from "node:util";
|
|
548915
549066
|
|
|
548916
549067
|
// src/mods/package-installer.ts
|
|
@@ -548922,15 +549073,15 @@ import {
|
|
|
548922
549073
|
} from "node:child_process";
|
|
548923
549074
|
import {
|
|
548924
549075
|
copyFileSync as copyFileSync3,
|
|
548925
|
-
existsSync as
|
|
549076
|
+
existsSync as existsSync50,
|
|
548926
549077
|
lstatSync as lstatSync3,
|
|
548927
|
-
mkdirSync as
|
|
549078
|
+
mkdirSync as mkdirSync35,
|
|
548928
549079
|
mkdtempSync as mkdtempSync3,
|
|
548929
549080
|
readdirSync as readdirSync19,
|
|
548930
549081
|
readFileSync as readFileSync34,
|
|
548931
549082
|
renameSync as renameSync5,
|
|
548932
549083
|
rmSync as rmSync11,
|
|
548933
|
-
writeFileSync as
|
|
549084
|
+
writeFileSync as writeFileSync25
|
|
548934
549085
|
} from "node:fs";
|
|
548935
549086
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
548936
549087
|
import path37 from "node:path";
|
|
@@ -549070,7 +549221,7 @@ function validatePackageSource(packageDirectory) {
|
|
|
549070
549221
|
};
|
|
549071
549222
|
}
|
|
549072
549223
|
function copyPackageDirectory(sourceRoot, targetRoot) {
|
|
549073
|
-
|
|
549224
|
+
mkdirSync35(targetRoot, { recursive: true });
|
|
549074
549225
|
for (const entry of readdirSync19(sourceRoot, { withFileTypes: true })) {
|
|
549075
549226
|
if (SKIPPED_PACKAGE_COPY_NAMES.has(entry.name))
|
|
549076
549227
|
continue;
|
|
@@ -549085,7 +549236,7 @@ function copyPackageDirectory(sourceRoot, targetRoot) {
|
|
|
549085
549236
|
continue;
|
|
549086
549237
|
}
|
|
549087
549238
|
if (stats.isFile()) {
|
|
549088
|
-
|
|
549239
|
+
mkdirSync35(path37.dirname(targetPath), { recursive: true });
|
|
549089
549240
|
copyFileSync3(sourcePath, targetPath);
|
|
549090
549241
|
continue;
|
|
549091
549242
|
}
|
|
@@ -549125,7 +549276,7 @@ function copyDependencyDirectoryFiltered(params) {
|
|
|
549125
549276
|
continue;
|
|
549126
549277
|
}
|
|
549127
549278
|
if (stats.isFile()) {
|
|
549128
|
-
|
|
549279
|
+
mkdirSync35(path37.dirname(targetPath), { recursive: true });
|
|
549129
549280
|
copyFileSync3(sourcePath, targetPath);
|
|
549130
549281
|
copied = true;
|
|
549131
549282
|
continue;
|
|
@@ -549135,7 +549286,7 @@ function copyDependencyDirectoryFiltered(params) {
|
|
|
549135
549286
|
return copied;
|
|
549136
549287
|
}
|
|
549137
549288
|
function copyDependencyNodeModules(params) {
|
|
549138
|
-
if (!
|
|
549289
|
+
if (!existsSync50(params.sourceNodeModulesDirectory))
|
|
549139
549290
|
return;
|
|
549140
549291
|
copyDependencyDirectoryFiltered({
|
|
549141
549292
|
installedPackageName: params.installedPackageName,
|
|
@@ -549145,7 +549296,7 @@ function copyDependencyNodeModules(params) {
|
|
|
549145
549296
|
}
|
|
549146
549297
|
function copyPackageInternalNodeModules(params) {
|
|
549147
549298
|
const sourceNodeModulesDirectory = path37.join(params.packageDirectory, "node_modules");
|
|
549148
|
-
if (!
|
|
549299
|
+
if (!existsSync50(sourceNodeModulesDirectory))
|
|
549149
549300
|
return;
|
|
549150
549301
|
copyDependencyDirectoryFiltered({
|
|
549151
549302
|
sourceRoot: sourceNodeModulesDirectory,
|
|
@@ -549157,8 +549308,8 @@ function restoreRegistry(registryPath, previousContents) {
|
|
|
549157
549308
|
rmSync11(registryPath, { force: true });
|
|
549158
549309
|
return;
|
|
549159
549310
|
}
|
|
549160
|
-
|
|
549161
|
-
|
|
549311
|
+
mkdirSync35(path37.dirname(registryPath), { recursive: true });
|
|
549312
|
+
writeFileSync25(registryPath, previousContents);
|
|
549162
549313
|
}
|
|
549163
549314
|
function removeIfExists(targetPath) {
|
|
549164
549315
|
if (!targetPath)
|
|
@@ -549167,12 +549318,12 @@ function removeIfExists(targetPath) {
|
|
|
549167
549318
|
}
|
|
549168
549319
|
function restoreDestination(params) {
|
|
549169
549320
|
rmSync11(params.destinationRoot, { force: true, recursive: true });
|
|
549170
|
-
if (params.backupRoot &&
|
|
549321
|
+
if (params.backupRoot && existsSync50(params.backupRoot)) {
|
|
549171
549322
|
renameSync5(params.backupRoot, params.destinationRoot);
|
|
549172
549323
|
}
|
|
549173
549324
|
}
|
|
549174
549325
|
function restoreDestinationIfNeeded(params) {
|
|
549175
|
-
if (!params.backupRoot || !
|
|
549326
|
+
if (!params.backupRoot || !existsSync50(params.backupRoot)) {
|
|
549176
549327
|
rmSync11(params.destinationRoot, { force: true, recursive: true });
|
|
549177
549328
|
return;
|
|
549178
549329
|
}
|
|
@@ -549181,7 +549332,7 @@ function restoreDestinationIfNeeded(params) {
|
|
|
549181
549332
|
function makeSiblingTempDirectory(destinationRoot, label) {
|
|
549182
549333
|
const parent = path37.dirname(destinationRoot);
|
|
549183
549334
|
const baseName = path37.basename(destinationRoot).replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
549184
|
-
|
|
549335
|
+
mkdirSync35(parent, { recursive: true });
|
|
549185
549336
|
return mkdtempSync3(path37.join(parent, `.${baseName}.${label}-`));
|
|
549186
549337
|
}
|
|
549187
549338
|
function installPreparedManagedModPackage(params) {
|
|
@@ -549213,7 +549364,7 @@ function installPreparedManagedModPackage(params) {
|
|
|
549213
549364
|
targetPackageRoot: stagingRoot
|
|
549214
549365
|
});
|
|
549215
549366
|
}
|
|
549216
|
-
if (
|
|
549367
|
+
if (existsSync50(destinationRoot)) {
|
|
549217
549368
|
backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
|
|
549218
549369
|
rmSync11(backupRoot, { force: true, recursive: true });
|
|
549219
549370
|
renameSync5(destinationRoot, backupRoot);
|
|
@@ -549279,7 +549430,7 @@ function getNpmInstallArgs(installSpec) {
|
|
|
549279
549430
|
];
|
|
549280
549431
|
}
|
|
549281
549432
|
function writeNpmInstallManifest(tempRoot) {
|
|
549282
|
-
|
|
549433
|
+
writeFileSync25(path37.join(tempRoot, "package.json"), `${JSON.stringify({
|
|
549283
549434
|
private: true,
|
|
549284
549435
|
name: "letta-managed-mod-install"
|
|
549285
549436
|
}, null, 2)}
|
|
@@ -549496,7 +549647,7 @@ function hasRuntimeDependencies(packageJson) {
|
|
|
549496
549647
|
}
|
|
549497
549648
|
function readPackageJsonIfExists(packageDirectory) {
|
|
549498
549649
|
const packageJsonPath = path37.join(packageDirectory, "package.json");
|
|
549499
|
-
if (!
|
|
549650
|
+
if (!existsSync50(packageJsonPath))
|
|
549500
549651
|
return null;
|
|
549501
549652
|
return readPackageJson(packageJsonPath);
|
|
549502
549653
|
}
|
|
@@ -549510,7 +549661,7 @@ function isRegularModFile(filePath) {
|
|
|
549510
549661
|
}
|
|
549511
549662
|
function inferCompatibilityModEntries(packageDirectory) {
|
|
549512
549663
|
const modsDirectory = path37.join(packageDirectory, "mods");
|
|
549513
|
-
if (
|
|
549664
|
+
if (existsSync50(modsDirectory)) {
|
|
549514
549665
|
const stats = lstatSync3(modsDirectory);
|
|
549515
549666
|
if (stats.isSymbolicLink()) {
|
|
549516
549667
|
throw new Error(`Package mods directory must not be a symlink: mods`);
|
|
@@ -549551,7 +549702,7 @@ function getPackageVersionForGitPackage(params) {
|
|
|
549551
549702
|
}
|
|
549552
549703
|
function writeCompatibilityPackageManifest(params) {
|
|
549553
549704
|
const packageJsonPath = path37.join(params.packageDirectory, "package.json");
|
|
549554
|
-
|
|
549705
|
+
writeFileSync25(packageJsonPath, `${JSON.stringify({
|
|
549555
549706
|
...params.packageJson ?? {},
|
|
549556
549707
|
name: params.packageName,
|
|
549557
549708
|
version: params.version,
|
|
@@ -549782,11 +549933,11 @@ init_package_manifest();
|
|
|
549782
549933
|
init_package_registry();
|
|
549783
549934
|
import {
|
|
549784
549935
|
copyFileSync as copyFileSync4,
|
|
549785
|
-
existsSync as
|
|
549936
|
+
existsSync as existsSync51,
|
|
549786
549937
|
lstatSync as lstatSync4,
|
|
549787
|
-
mkdirSync as
|
|
549938
|
+
mkdirSync as mkdirSync36,
|
|
549788
549939
|
rmSync as rmSync12,
|
|
549789
|
-
writeFileSync as
|
|
549940
|
+
writeFileSync as writeFileSync26
|
|
549790
549941
|
} from "node:fs";
|
|
549791
549942
|
import path38 from "node:path";
|
|
549792
549943
|
var DEFAULT_PACKAGE_VERSION = "0.1.0";
|
|
@@ -549878,7 +550029,7 @@ function scaffoldLocalModPackage(options3) {
|
|
|
549878
550029
|
const sourceFile = readSourceFile(options3.sourceFile);
|
|
549879
550030
|
const packageName = assertValidPackageName(options3.packageName);
|
|
549880
550031
|
const outputDirectory = path38.resolve(options3.outputDirectory ?? defaultOutputDirectory(sourceFile, packageName));
|
|
549881
|
-
if (
|
|
550032
|
+
if (existsSync51(outputDirectory)) {
|
|
549882
550033
|
throw new Error(`Output directory already exists: ${outputDirectory}`);
|
|
549883
550034
|
}
|
|
549884
550035
|
const modFileName = path38.basename(sourceFile);
|
|
@@ -549890,12 +550041,12 @@ function scaffoldLocalModPackage(options3) {
|
|
|
549890
550041
|
const modGuidePath = path38.join(outputDirectory, "MOD.md");
|
|
549891
550042
|
const installCommand = `letta install ${outputDirectory}`;
|
|
549892
550043
|
try {
|
|
549893
|
-
|
|
550044
|
+
mkdirSync36(targetModsDirectory, { recursive: true });
|
|
549894
550045
|
copyFileSync4(sourceFile, targetModPath);
|
|
549895
|
-
|
|
550046
|
+
writeFileSync26(packageJsonPath, `${JSON.stringify(createPackageJson(packageName, manifestEntry), null, 2)}
|
|
549896
550047
|
`);
|
|
549897
|
-
|
|
549898
|
-
|
|
550048
|
+
writeFileSync26(readmePath, createReadme(packageName));
|
|
550049
|
+
writeFileSync26(modGuidePath, createModGuide(packageName, manifestEntry));
|
|
549899
550050
|
} catch (error54) {
|
|
549900
550051
|
rmSync12(outputDirectory, { force: true, recursive: true });
|
|
549901
550052
|
throw error54;
|
|
@@ -549963,7 +550114,7 @@ function getExplicitAgentId(values2) {
|
|
|
549963
550114
|
return typeof explicitAgent === "string" && explicitAgent.trim() ? explicitAgent.trim() : null;
|
|
549964
550115
|
}
|
|
549965
550116
|
function getAgentModsDirectory(agentId) {
|
|
549966
|
-
return
|
|
550117
|
+
return join58(getScopedMemoryFilesystemRoot(agentId), "mods");
|
|
549967
550118
|
}
|
|
549968
550119
|
function directFilesForSource(source2) {
|
|
549969
550120
|
return source2.files.filter((file3) => dirname29(file3) === source2.root);
|
|
@@ -550292,16 +550443,16 @@ async function runSetupSubcommand(argv) {
|
|
|
550292
550443
|
// src/cli/subcommands/skills.ts
|
|
550293
550444
|
import {
|
|
550294
550445
|
cpSync as cpSync2,
|
|
550295
|
-
existsSync as
|
|
550446
|
+
existsSync as existsSync52,
|
|
550296
550447
|
mkdtempSync as mkdtempSync4,
|
|
550297
550448
|
readFileSync as readFileSync35,
|
|
550298
550449
|
rmSync as rmSync13,
|
|
550299
550450
|
statSync as statSync18,
|
|
550300
|
-
writeFileSync as
|
|
550451
|
+
writeFileSync as writeFileSync27
|
|
550301
550452
|
} from "node:fs";
|
|
550302
550453
|
import { mkdir as mkdir14, readdir as readdir14 } from "node:fs/promises";
|
|
550303
550454
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
550304
|
-
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";
|
|
550305
550456
|
import { parseArgs as parseArgs14, TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
|
|
550306
550457
|
init_paths2();
|
|
550307
550458
|
var HERMES_REPO_URL = "https://github.com/NousResearch/hermes-agent.git";
|
|
@@ -550606,14 +550757,14 @@ async function resolveBranchAndSubdir(location) {
|
|
|
550606
550757
|
}
|
|
550607
550758
|
async function cloneSkillSource(location) {
|
|
550608
550759
|
const resolvedLocation = await resolveBranchAndSubdir(location);
|
|
550609
|
-
const tmpDir = mkdtempSync4(
|
|
550760
|
+
const tmpDir = mkdtempSync4(join59(tmpdir9(), "letta-skill-install-"));
|
|
550610
550761
|
const args = ["clone", "--depth", "1"];
|
|
550611
550762
|
if (resolvedLocation.branch) {
|
|
550612
550763
|
args.push("--branch", resolvedLocation.branch);
|
|
550613
550764
|
}
|
|
550614
550765
|
args.push(resolvedLocation.repoUrl, tmpDir);
|
|
550615
550766
|
await execFile16("git", args, { timeout: 120000 });
|
|
550616
|
-
const sourceDir = resolvedLocation.subdir ?
|
|
550767
|
+
const sourceDir = resolvedLocation.subdir ? join59(tmpDir, resolvedLocation.subdir) : tmpDir;
|
|
550617
550768
|
return { tmpDir, sourceDir };
|
|
550618
550769
|
}
|
|
550619
550770
|
function assertDirectSkillFileSize(receivedBytes, maxBytes) {
|
|
@@ -550668,11 +550819,11 @@ async function downloadDirectSkillFileSource(location, options3 = {}) {
|
|
|
550668
550819
|
throw new Error(`Direct skill file download failed for ${location.url}: ${response.status}`);
|
|
550669
550820
|
}
|
|
550670
550821
|
const skillText = await readResponseTextWithLimit(response, MAX_DIRECT_SKILL_FILE_BYTES);
|
|
550671
|
-
const tmpDir = mkdtempSync4(
|
|
550822
|
+
const tmpDir = mkdtempSync4(join59(tmpdir9(), "letta-direct-skill-"));
|
|
550672
550823
|
try {
|
|
550673
|
-
const sourceDir =
|
|
550824
|
+
const sourceDir = join59(tmpDir, "skill");
|
|
550674
550825
|
await mkdir14(sourceDir, { recursive: true });
|
|
550675
|
-
|
|
550826
|
+
writeFileSync27(join59(sourceDir, "SKILL.md"), skillText, "utf8");
|
|
550676
550827
|
return { tmpDir, sourceDir };
|
|
550677
550828
|
} catch (error54) {
|
|
550678
550829
|
rmSync13(tmpDir, { recursive: true, force: true });
|
|
@@ -550713,9 +550864,9 @@ function assertSafeZipMember(name) {
|
|
|
550713
550864
|
}
|
|
550714
550865
|
async function downloadClawHubSkillSource(location) {
|
|
550715
550866
|
const version2 = await resolveClawHubVersion(location);
|
|
550716
|
-
const tmpDir = mkdtempSync4(
|
|
550717
|
-
const zipPath =
|
|
550718
|
-
const sourceDir =
|
|
550867
|
+
const tmpDir = mkdtempSync4(join59(tmpdir9(), "letta-clawhub-skill-"));
|
|
550868
|
+
const zipPath = join59(tmpDir, "skill.zip");
|
|
550869
|
+
const sourceDir = join59(tmpDir, "skill");
|
|
550719
550870
|
await mkdir14(sourceDir, { recursive: true });
|
|
550720
550871
|
const url2 = new URL(`${CLAWHUB_API_BASE_URL}/download`);
|
|
550721
550872
|
url2.searchParams.set("slug", location.slug);
|
|
@@ -550724,7 +550875,7 @@ async function downloadClawHubSkillSource(location) {
|
|
|
550724
550875
|
if (!response.ok) {
|
|
550725
550876
|
throw new Error(`ClawHub download failed for ${location.slug}@${version2}: ${response.status}`);
|
|
550726
550877
|
}
|
|
550727
|
-
|
|
550878
|
+
writeFileSync27(zipPath, Buffer.from(await response.arrayBuffer()));
|
|
550728
550879
|
const { stdout } = await execFile16("unzip", ["-Z1", zipPath], {
|
|
550729
550880
|
timeout: 30000
|
|
550730
550881
|
});
|
|
@@ -550754,7 +550905,7 @@ function sanitizeSkillName(name) {
|
|
|
550754
550905
|
return trimmed;
|
|
550755
550906
|
}
|
|
550756
550907
|
function getSkillName(sourceDir) {
|
|
550757
|
-
const skillMd = readFileSync35(
|
|
550908
|
+
const skillMd = readFileSync35(join59(sourceDir, "SKILL.md"), "utf8");
|
|
550758
550909
|
const { frontmatter } = parseFrontmatter(skillMd);
|
|
550759
550910
|
const frontmatterName = frontmatter.name;
|
|
550760
550911
|
const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename26(sourceDir);
|
|
@@ -550763,18 +550914,18 @@ function getSkillName(sourceDir) {
|
|
|
550763
550914
|
async function installSkillDirectory(params) {
|
|
550764
550915
|
const sourceDir = resolve32(params.sourceDir);
|
|
550765
550916
|
const memoryDir = resolve32(params.memoryDir);
|
|
550766
|
-
const skillMdPath =
|
|
550767
|
-
if (!
|
|
550917
|
+
const skillMdPath = join59(sourceDir, "SKILL.md");
|
|
550918
|
+
if (!existsSync52(skillMdPath)) {
|
|
550768
550919
|
throw new Error("No SKILL.md found in the skill directory.");
|
|
550769
550920
|
}
|
|
550770
550921
|
if (!statSync18(sourceDir).isDirectory()) {
|
|
550771
550922
|
throw new Error(`Skill source is not a directory: ${sourceDir}`);
|
|
550772
550923
|
}
|
|
550773
550924
|
const name = getSkillName(sourceDir);
|
|
550774
|
-
const skillsDir =
|
|
550775
|
-
const targetPath =
|
|
550925
|
+
const skillsDir = join59(memoryDir, "skills");
|
|
550926
|
+
const targetPath = join59(skillsDir, name);
|
|
550776
550927
|
assertInside(skillsDir, targetPath);
|
|
550777
|
-
if (
|
|
550928
|
+
if (existsSync52(targetPath)) {
|
|
550778
550929
|
if (!params.force) {
|
|
550779
550930
|
throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
|
|
550780
550931
|
}
|
|
@@ -550789,17 +550940,17 @@ async function installSkillDirectory(params) {
|
|
|
550789
550940
|
}
|
|
550790
550941
|
async function listSkillDirectories(params) {
|
|
550791
550942
|
const memoryDir = resolve32(params.memoryDir);
|
|
550792
|
-
const skillsDir =
|
|
550793
|
-
if (!
|
|
550943
|
+
const skillsDir = join59(memoryDir, "skills");
|
|
550944
|
+
if (!existsSync52(skillsDir))
|
|
550794
550945
|
return [];
|
|
550795
550946
|
const entries = await readdir14(skillsDir, { withFileTypes: true });
|
|
550796
550947
|
const skills = [];
|
|
550797
550948
|
for (const entry of entries) {
|
|
550798
550949
|
if (!entry.isDirectory())
|
|
550799
550950
|
continue;
|
|
550800
|
-
const skillDir =
|
|
550801
|
-
const skillMdPath =
|
|
550802
|
-
if (!
|
|
550951
|
+
const skillDir = join59(skillsDir, entry.name);
|
|
550952
|
+
const skillMdPath = join59(skillDir, "SKILL.md");
|
|
550953
|
+
if (!existsSync52(skillMdPath))
|
|
550803
550954
|
continue;
|
|
550804
550955
|
let name = entry.name;
|
|
550805
550956
|
let description;
|
|
@@ -550819,11 +550970,11 @@ async function listSkillDirectories(params) {
|
|
|
550819
550970
|
}
|
|
550820
550971
|
async function deleteSkillDirectory(params) {
|
|
550821
550972
|
const memoryDir = resolve32(params.memoryDir);
|
|
550822
|
-
const skillsDir =
|
|
550973
|
+
const skillsDir = join59(memoryDir, "skills");
|
|
550823
550974
|
const name = sanitizeSkillName(params.name);
|
|
550824
|
-
const targetPath =
|
|
550975
|
+
const targetPath = join59(skillsDir, name);
|
|
550825
550976
|
assertInside(skillsDir, targetPath);
|
|
550826
|
-
if (!
|
|
550977
|
+
if (!existsSync52(targetPath)) {
|
|
550827
550978
|
throw new Error(`Skill "${name}" is not installed at ${targetPath}.`);
|
|
550828
550979
|
}
|
|
550829
550980
|
if (!statSync18(targetPath).isDirectory()) {
|
|
@@ -550872,7 +551023,7 @@ async function installSkill(specifier, agentId, force) {
|
|
|
550872
551023
|
tmpDir = downloaded.tmpDir;
|
|
550873
551024
|
const sourceDir = resolve32(downloaded.sourceDir);
|
|
550874
551025
|
assertInside(tmpDir, sourceDir);
|
|
550875
|
-
if (!
|
|
551026
|
+
if (!existsSync52(sourceDir)) {
|
|
550876
551027
|
const missingPath = source2.type === "git" ? source2.location.subdir ?? "." : source2.type === "direct-file" ? source2.location.url : source2.location.slug;
|
|
550877
551028
|
throw new Error(`Skill path not found: ${missingPath}`);
|
|
550878
551029
|
}
|
|
@@ -551326,7 +551477,7 @@ init_secrets();
|
|
|
551326
551477
|
import { randomUUID as randomUUID25 } from "node:crypto";
|
|
551327
551478
|
import { readFileSync as readFileSync36 } from "node:fs";
|
|
551328
551479
|
import { homedir as homedir32 } from "node:os";
|
|
551329
|
-
import { join as
|
|
551480
|
+
import { join as join60, resolve as resolve33 } from "node:path";
|
|
551330
551481
|
var OBSOLETE_SETTINGS_KEYS2 = [
|
|
551331
551482
|
"reflectionBehavior",
|
|
551332
551483
|
"enableSleeptime",
|
|
@@ -551769,7 +551920,7 @@ class SettingsManager2 {
|
|
|
551769
551920
|
return;
|
|
551770
551921
|
const settingsPath = this.getSettingsPath();
|
|
551771
551922
|
const home = process.env.HOME || homedir32();
|
|
551772
|
-
const dirPath =
|
|
551923
|
+
const dirPath = join60(home, ".letta");
|
|
551773
551924
|
try {
|
|
551774
551925
|
if (!exists(dirPath)) {
|
|
551775
551926
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -551810,7 +551961,7 @@ class SettingsManager2 {
|
|
|
551810
551961
|
if (!settings3)
|
|
551811
551962
|
return;
|
|
551812
551963
|
const settingsPath = this.getProjectSettingsPath(workingDirectory);
|
|
551813
|
-
const dirPath =
|
|
551964
|
+
const dirPath = join60(workingDirectory, ".letta");
|
|
551814
551965
|
try {
|
|
551815
551966
|
let existingSettings = {};
|
|
551816
551967
|
if (exists(settingsPath)) {
|
|
@@ -551832,16 +551983,16 @@ class SettingsManager2 {
|
|
|
551832
551983
|
}
|
|
551833
551984
|
getSettingsPath() {
|
|
551834
551985
|
const home = process.env.HOME || homedir32();
|
|
551835
|
-
return
|
|
551986
|
+
return join60(home, ".letta", "settings.json");
|
|
551836
551987
|
}
|
|
551837
551988
|
getProjectSettingsPath(workingDirectory) {
|
|
551838
|
-
return
|
|
551989
|
+
return join60(workingDirectory, ".letta", "settings.json");
|
|
551839
551990
|
}
|
|
551840
551991
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
551841
551992
|
return resolve33(this.getProjectSettingsPath(workingDirectory)) === resolve33(this.getSettingsPath());
|
|
551842
551993
|
}
|
|
551843
551994
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
551844
|
-
return
|
|
551995
|
+
return join60(workingDirectory, ".letta", "settings.local.json");
|
|
551845
551996
|
}
|
|
551846
551997
|
async loadLocalProjectSettings(workingDirectory = process.cwd()) {
|
|
551847
551998
|
const cached3 = this.localProjectSettings.get(workingDirectory);
|
|
@@ -551902,7 +552053,7 @@ class SettingsManager2 {
|
|
|
551902
552053
|
if (!settings3)
|
|
551903
552054
|
return;
|
|
551904
552055
|
const settingsPath = this.getLocalProjectSettingsPath(workingDirectory);
|
|
551905
|
-
const dirPath =
|
|
552056
|
+
const dirPath = join60(workingDirectory, ".letta");
|
|
551906
552057
|
try {
|
|
551907
552058
|
if (!exists(dirPath)) {
|
|
551908
552059
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -552256,7 +552407,7 @@ class SettingsManager2 {
|
|
|
552256
552407
|
});
|
|
552257
552408
|
}
|
|
552258
552409
|
hasLocalLettaDir(workingDirectory = process.cwd()) {
|
|
552259
|
-
const dirPath =
|
|
552410
|
+
const dirPath = join60(workingDirectory, ".letta");
|
|
552260
552411
|
return exists(dirPath);
|
|
552261
552412
|
}
|
|
552262
552413
|
storeOAuthState(state, codeVerifier, redirectUri, provider) {
|
|
@@ -553031,12 +553182,12 @@ EXAMPLES
|
|
|
553031
553182
|
console.log(usage);
|
|
553032
553183
|
}
|
|
553033
553184
|
async function printInfo() {
|
|
553034
|
-
const { join:
|
|
553185
|
+
const { join: join86 } = await import("path");
|
|
553035
553186
|
const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version2));
|
|
553036
553187
|
const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills4(), exports_skills3));
|
|
553037
553188
|
const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
|
|
553038
553189
|
const cwd2 = process.cwd();
|
|
553039
|
-
const skillsDir =
|
|
553190
|
+
const skillsDir = join86(cwd2, SKILLS_DIR3);
|
|
553040
553191
|
const skillsExist = exists3(skillsDir);
|
|
553041
553192
|
await settingsManager2.loadLocalProjectSettings(cwd2);
|
|
553042
553193
|
const pinned = settingsManager2.getPinnedAgents();
|
|
@@ -553610,9 +553761,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
553610
553761
|
}
|
|
553611
553762
|
} else {
|
|
553612
553763
|
const { resolve: resolve43 } = await import("path");
|
|
553613
|
-
const { existsSync:
|
|
553764
|
+
const { existsSync: existsSync72 } = await import("fs");
|
|
553614
553765
|
const resolvedPath = resolve43(fromAfFile);
|
|
553615
|
-
if (!
|
|
553766
|
+
if (!existsSync72(resolvedPath)) {
|
|
553616
553767
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
553617
553768
|
process.exit(1);
|
|
553618
553769
|
}
|
|
@@ -554642,4 +554793,4 @@ Error during initialization: ${message}`);
|
|
|
554642
554793
|
}
|
|
554643
554794
|
main2();
|
|
554644
554795
|
|
|
554645
|
-
//# debugId=
|
|
554796
|
+
//# debugId=EA7311931B35FB9664756E2164756E21
|