@letta-ai/letta-code 0.27.23 → 0.27.25
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 +87 -17
- package/dist/agent-presets.js.map +2 -2
- package/dist/types/agent/model-catalog.d.ts +6 -25
- package/dist/types/agent/model-catalog.d.ts.map +1 -1
- package/dist/types/types/protocol_v2.d.ts +16 -0
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/letta.js +773 -364
- package/package.json +2 -1
- package/scripts/check-skill-frontmatter.js +116 -0
- package/scripts/check.js +1 -0
- package/skills/context-doctor/SKILL.md +2 -1
- package/skills/creating-mods/SKILL.md +1 -1
- package/skills/creating-mods/references/ui.md +40 -1
- package/skills/initializing-memory/SKILL.md +2 -1
package/letta.js
CHANGED
|
@@ -4672,7 +4672,7 @@ var package_default;
|
|
|
4672
4672
|
var init_package = __esm(() => {
|
|
4673
4673
|
package_default = {
|
|
4674
4674
|
name: "@letta-ai/letta-code",
|
|
4675
|
-
version: "0.27.
|
|
4675
|
+
version: "0.27.25",
|
|
4676
4676
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
4677
4677
|
type: "module",
|
|
4678
4678
|
packageManager: "bun@1.3.0",
|
|
@@ -4769,6 +4769,7 @@ var init_package = __esm(() => {
|
|
|
4769
4769
|
"check:filename-casing": "node scripts/check-filename-casing.js",
|
|
4770
4770
|
"check:test-mock-isolation": "bun run scripts/check-test-mock-isolation.js",
|
|
4771
4771
|
"check:test-coverage": "node scripts/check-test-coverage.cjs",
|
|
4772
|
+
"check:skill-frontmatter": "node scripts/check-skill-frontmatter.js",
|
|
4772
4773
|
"check:bundled-skill-scripts": "node scripts/check-bundled-skill-scripts.js",
|
|
4773
4774
|
check: "bun run scripts/check.js",
|
|
4774
4775
|
dev: "node scripts/dev.cjs",
|
|
@@ -4909,7 +4910,7 @@ async function forkConversation(conversationId, options = {}) {
|
|
|
4909
4910
|
...options.agentId ? { agent_id: options.agentId } : {},
|
|
4910
4911
|
...options.hidden !== undefined ? { hidden: options.hidden } : {}
|
|
4911
4912
|
};
|
|
4912
|
-
return apiRequest("POST", `/v1/conversations/${encodeURIComponent(conversationId)}/fork`, undefined, { query });
|
|
4913
|
+
return apiRequest("POST", `/v1/conversations/${encodeURIComponent(conversationId)}/fork`, undefined, { query, ...options.headers ? { headers: options.headers } : {} });
|
|
4913
4914
|
}
|
|
4914
4915
|
async function updateConversationDescription(conversationId, body) {
|
|
4915
4916
|
return apiRequest("PATCH", `/v1/conversations/${encodeURIComponent(conversationId)}`, body);
|
|
@@ -6533,11 +6534,13 @@ var init_skill_sources = __esm(() => {
|
|
|
6533
6534
|
// src/agent/context.ts
|
|
6534
6535
|
var exports_context = {};
|
|
6535
6536
|
__export(exports_context, {
|
|
6537
|
+
setCurrentAgentName: () => setCurrentAgentName,
|
|
6536
6538
|
setCurrentAgentId: () => setCurrentAgentId,
|
|
6537
6539
|
setConversationId: () => setConversationId,
|
|
6538
6540
|
setAgentContext: () => setAgentContext,
|
|
6539
6541
|
getSkillsDirectory: () => getSkillsDirectory,
|
|
6540
6542
|
getSkillSources: () => getSkillSources,
|
|
6543
|
+
getCurrentAgentName: () => getCurrentAgentName,
|
|
6541
6544
|
getCurrentAgentId: () => getCurrentAgentId,
|
|
6542
6545
|
getConversationId: () => getConversationId
|
|
6543
6546
|
});
|
|
@@ -6546,6 +6549,7 @@ function getContext() {
|
|
|
6546
6549
|
if (!global2[CONTEXT_KEY]) {
|
|
6547
6550
|
global2[CONTEXT_KEY] = {
|
|
6548
6551
|
agentId: null,
|
|
6552
|
+
agentName: null,
|
|
6549
6553
|
skillsDirectory: null,
|
|
6550
6554
|
skillSources: [...ALL_SKILL_SOURCES],
|
|
6551
6555
|
conversationId: null
|
|
@@ -6553,24 +6557,43 @@ function getContext() {
|
|
|
6553
6557
|
}
|
|
6554
6558
|
return global2[CONTEXT_KEY];
|
|
6555
6559
|
}
|
|
6556
|
-
function setAgentContext(agentId, skillsDirectory, skillSources) {
|
|
6560
|
+
function setAgentContext(agentId, skillsDirectory, skillSources, agentName) {
|
|
6557
6561
|
context.agentId = agentId;
|
|
6562
|
+
context.agentName = normalizeAgentName(agentName);
|
|
6558
6563
|
context.skillsDirectory = skillsDirectory || null;
|
|
6559
6564
|
context.skillSources = skillSources !== undefined ? [...skillSources] : [...ALL_SKILL_SOURCES];
|
|
6560
6565
|
if (getRuntimeContext()) {
|
|
6561
6566
|
updateRuntimeContext({
|
|
6562
6567
|
agentId,
|
|
6568
|
+
agentName: context.agentName,
|
|
6563
6569
|
skillsDirectory: skillsDirectory || null,
|
|
6564
6570
|
skillSources: skillSources !== undefined ? [...skillSources] : [...ALL_SKILL_SOURCES]
|
|
6565
6571
|
});
|
|
6566
6572
|
}
|
|
6567
6573
|
}
|
|
6568
6574
|
function setCurrentAgentId(agentId) {
|
|
6575
|
+
const agentChanged = context.agentId !== agentId;
|
|
6569
6576
|
context.agentId = agentId;
|
|
6577
|
+
if (agentId === null || agentChanged) {
|
|
6578
|
+
context.agentName = null;
|
|
6579
|
+
}
|
|
6570
6580
|
if (getRuntimeContext()) {
|
|
6571
|
-
updateRuntimeContext({
|
|
6581
|
+
updateRuntimeContext({
|
|
6582
|
+
agentId,
|
|
6583
|
+
...agentId === null || agentChanged ? { agentName: null } : {}
|
|
6584
|
+
});
|
|
6572
6585
|
}
|
|
6573
6586
|
}
|
|
6587
|
+
function setCurrentAgentName(agentName) {
|
|
6588
|
+
context.agentName = normalizeAgentName(agentName);
|
|
6589
|
+
if (getRuntimeContext()) {
|
|
6590
|
+
updateRuntimeContext({ agentName: context.agentName });
|
|
6591
|
+
}
|
|
6592
|
+
}
|
|
6593
|
+
function normalizeAgentName(agentName) {
|
|
6594
|
+
const trimmed = typeof agentName === "string" ? agentName.trim() : "";
|
|
6595
|
+
return trimmed || null;
|
|
6596
|
+
}
|
|
6574
6597
|
function getCurrentAgentId() {
|
|
6575
6598
|
const runtimeContext = getRuntimeContext();
|
|
6576
6599
|
if (runtimeContext && "agentId" in runtimeContext) {
|
|
@@ -6584,6 +6607,14 @@ function getCurrentAgentId() {
|
|
|
6584
6607
|
}
|
|
6585
6608
|
return context.agentId;
|
|
6586
6609
|
}
|
|
6610
|
+
function getCurrentAgentName() {
|
|
6611
|
+
const runtimeContext = getRuntimeContext();
|
|
6612
|
+
if (runtimeContext && "agentName" in runtimeContext) {
|
|
6613
|
+
const trimmed = runtimeContext.agentName?.trim();
|
|
6614
|
+
return trimmed || null;
|
|
6615
|
+
}
|
|
6616
|
+
return context.agentName;
|
|
6617
|
+
}
|
|
6587
6618
|
function getSkillsDirectory() {
|
|
6588
6619
|
const runtimeContext = getRuntimeContext();
|
|
6589
6620
|
if (runtimeContext && "skillsDirectory" in runtimeContext) {
|
|
@@ -141240,6 +141271,10 @@ There are two ways to change memory:
|
|
|
141240
141271
|
- **The \`memory\` tool (shorthand).** Use it for small, targeted edits. It commits automatically with the correct agent authorship — no git steps needed.
|
|
141241
141272
|
- **Direct file edits (full control).** For larger changes — restructuring directories, rewriting several blocks — edit the projected files directly, then commit:
|
|
141242
141273
|
|
|
141274
|
+
Memory markdown files must start with YAML frontmatter containing a non-empty \`description:\` field. The \`memory\` and \`memory_apply_patch\` tools add and preserve this automatically; when using raw file edits, preserve existing frontmatter or add it before committing. The MemFS pre-commit hook enforces this requirement, rejects unknown keys, and prevents changes to protected \`read_only\` files. Skill \`SKILL.md\` files use their own skill frontmatter format.
|
|
141275
|
+
|
|
141276
|
+
\`$AGENT_NAME\` is normally populated when the runtime knows the current agent name, but direct shell environments can still miss it. Use a non-empty author name fallback when committing directly.
|
|
141277
|
+
|
|
141243
141278
|
\`\`\`bash
|
|
141244
141279
|
cd "$MEMORY_DIR"
|
|
141245
141280
|
|
|
@@ -141247,8 +141282,9 @@ cd "$MEMORY_DIR"
|
|
|
141247
141282
|
git status
|
|
141248
141283
|
|
|
141249
141284
|
# Commit your changes
|
|
141250
|
-
git add
|
|
141251
|
-
|
|
141285
|
+
git add <specific files>
|
|
141286
|
+
author_name="\${AGENT_NAME:-$AGENT_ID}"
|
|
141287
|
+
git commit --author="$author_name <$AGENT_ID@letta.com>" -m "<type>: <what changed>"
|
|
141252
141288
|
\`\`\`
|
|
141253
141289
|
|
|
141254
141290
|
Your context is git-tracked, so you can always inspect or revert past changes:
|
|
@@ -144697,7 +144733,8 @@ var init_models7 = __esm(() => {
|
|
|
144697
144733
|
context_window: 140000,
|
|
144698
144734
|
max_output_tokens: 28000,
|
|
144699
144735
|
parallel_tool_calls: true
|
|
144700
|
-
}
|
|
144736
|
+
},
|
|
144737
|
+
isFeatured: true
|
|
144701
144738
|
},
|
|
144702
144739
|
{
|
|
144703
144740
|
id: "auto-chat",
|
|
@@ -144722,7 +144759,8 @@ var init_models7 = __esm(() => {
|
|
|
144722
144759
|
context_window: 200000,
|
|
144723
144760
|
max_output_tokens: 28000,
|
|
144724
144761
|
parallel_tool_calls: true
|
|
144725
|
-
}
|
|
144762
|
+
},
|
|
144763
|
+
isFeatured: true
|
|
144726
144764
|
},
|
|
144727
144765
|
{
|
|
144728
144766
|
id: "fable",
|
|
@@ -144731,7 +144769,7 @@ var init_models7 = __esm(() => {
|
|
|
144731
144769
|
description: "Fable 5 (high reasoning)",
|
|
144732
144770
|
isFeatured: true,
|
|
144733
144771
|
updateArgs: {
|
|
144734
|
-
context_window:
|
|
144772
|
+
context_window: 200000,
|
|
144735
144773
|
max_output_tokens: 128000,
|
|
144736
144774
|
enable_reasoner: true,
|
|
144737
144775
|
reasoning_effort: "high",
|
|
@@ -144744,7 +144782,7 @@ var init_models7 = __esm(() => {
|
|
|
144744
144782
|
label: "Fable 5",
|
|
144745
144783
|
description: "Fable 5 (low reasoning)",
|
|
144746
144784
|
updateArgs: {
|
|
144747
|
-
context_window:
|
|
144785
|
+
context_window: 200000,
|
|
144748
144786
|
max_output_tokens: 128000,
|
|
144749
144787
|
enable_reasoner: true,
|
|
144750
144788
|
reasoning_effort: "low",
|
|
@@ -144758,7 +144796,7 @@ var init_models7 = __esm(() => {
|
|
|
144758
144796
|
label: "Fable 5",
|
|
144759
144797
|
description: "Fable 5 (med reasoning)",
|
|
144760
144798
|
updateArgs: {
|
|
144761
|
-
context_window:
|
|
144799
|
+
context_window: 200000,
|
|
144762
144800
|
max_output_tokens: 128000,
|
|
144763
144801
|
enable_reasoner: true,
|
|
144764
144802
|
reasoning_effort: "medium",
|
|
@@ -144772,7 +144810,7 @@ var init_models7 = __esm(() => {
|
|
|
144772
144810
|
label: "Fable 5",
|
|
144773
144811
|
description: "Fable 5 (extra-high reasoning)",
|
|
144774
144812
|
updateArgs: {
|
|
144775
|
-
context_window:
|
|
144813
|
+
context_window: 200000,
|
|
144776
144814
|
max_output_tokens: 128000,
|
|
144777
144815
|
enable_reasoner: true,
|
|
144778
144816
|
reasoning_effort: "xhigh",
|
|
@@ -144785,7 +144823,74 @@ var init_models7 = __esm(() => {
|
|
|
144785
144823
|
label: "Fable 5",
|
|
144786
144824
|
description: "Fable 5 (max reasoning)",
|
|
144787
144825
|
updateArgs: {
|
|
144788
|
-
context_window:
|
|
144826
|
+
context_window: 200000,
|
|
144827
|
+
max_output_tokens: 128000,
|
|
144828
|
+
enable_reasoner: true,
|
|
144829
|
+
reasoning_effort: "max",
|
|
144830
|
+
parallel_tool_calls: true
|
|
144831
|
+
}
|
|
144832
|
+
},
|
|
144833
|
+
{
|
|
144834
|
+
id: "fable-1m",
|
|
144835
|
+
handle: "anthropic/claude-fable-5",
|
|
144836
|
+
label: "Fable 5 1M",
|
|
144837
|
+
description: "Claude Fable 5 with 1M token context window (high reasoning)",
|
|
144838
|
+
updateArgs: {
|
|
144839
|
+
context_window: 950000,
|
|
144840
|
+
max_output_tokens: 128000,
|
|
144841
|
+
enable_reasoner: true,
|
|
144842
|
+
reasoning_effort: "high",
|
|
144843
|
+
parallel_tool_calls: true
|
|
144844
|
+
}
|
|
144845
|
+
},
|
|
144846
|
+
{
|
|
144847
|
+
id: "fable-1m-low",
|
|
144848
|
+
handle: "anthropic/claude-fable-5",
|
|
144849
|
+
label: "Fable 5 1M",
|
|
144850
|
+
description: "Fable 5 1M (low reasoning)",
|
|
144851
|
+
updateArgs: {
|
|
144852
|
+
context_window: 950000,
|
|
144853
|
+
max_output_tokens: 128000,
|
|
144854
|
+
enable_reasoner: true,
|
|
144855
|
+
reasoning_effort: "low",
|
|
144856
|
+
max_reasoning_tokens: 4000,
|
|
144857
|
+
parallel_tool_calls: true
|
|
144858
|
+
}
|
|
144859
|
+
},
|
|
144860
|
+
{
|
|
144861
|
+
id: "fable-1m-medium",
|
|
144862
|
+
handle: "anthropic/claude-fable-5",
|
|
144863
|
+
label: "Fable 5 1M",
|
|
144864
|
+
description: "Fable 5 1M (med reasoning)",
|
|
144865
|
+
updateArgs: {
|
|
144866
|
+
context_window: 950000,
|
|
144867
|
+
max_output_tokens: 128000,
|
|
144868
|
+
enable_reasoner: true,
|
|
144869
|
+
reasoning_effort: "medium",
|
|
144870
|
+
max_reasoning_tokens: 12000,
|
|
144871
|
+
parallel_tool_calls: true
|
|
144872
|
+
}
|
|
144873
|
+
},
|
|
144874
|
+
{
|
|
144875
|
+
id: "fable-1m-xhigh",
|
|
144876
|
+
handle: "anthropic/claude-fable-5",
|
|
144877
|
+
label: "Fable 5 1M",
|
|
144878
|
+
description: "Fable 5 1M (extra-high reasoning)",
|
|
144879
|
+
updateArgs: {
|
|
144880
|
+
context_window: 950000,
|
|
144881
|
+
max_output_tokens: 128000,
|
|
144882
|
+
enable_reasoner: true,
|
|
144883
|
+
reasoning_effort: "xhigh",
|
|
144884
|
+
parallel_tool_calls: true
|
|
144885
|
+
}
|
|
144886
|
+
},
|
|
144887
|
+
{
|
|
144888
|
+
id: "fable-1m-max",
|
|
144889
|
+
handle: "anthropic/claude-fable-5",
|
|
144890
|
+
label: "Fable 5 1M",
|
|
144891
|
+
description: "Fable 5 1M (max reasoning)",
|
|
144892
|
+
updateArgs: {
|
|
144893
|
+
context_window: 950000,
|
|
144789
144894
|
max_output_tokens: 128000,
|
|
144790
144895
|
enable_reasoner: true,
|
|
144791
144896
|
reasoning_effort: "max",
|
|
@@ -144884,8 +144989,7 @@ var init_models7 = __esm(() => {
|
|
|
144884
144989
|
reasoning_effort: "high",
|
|
144885
144990
|
enable_reasoner: true,
|
|
144886
144991
|
parallel_tool_calls: true
|
|
144887
|
-
}
|
|
144888
|
-
isFeatured: true
|
|
144992
|
+
}
|
|
144889
144993
|
},
|
|
144890
144994
|
{
|
|
144891
144995
|
id: "opus-4.8-1m-no-reasoning",
|
|
@@ -145148,7 +145252,6 @@ var init_models7 = __esm(() => {
|
|
|
145148
145252
|
handle: "anthropic/claude-sonnet-4-6",
|
|
145149
145253
|
label: "Sonnet 4.6 1M",
|
|
145150
145254
|
description: "Claude Sonnet 4.6 with 1M token context window (high reasoning)",
|
|
145151
|
-
isFeatured: true,
|
|
145152
145255
|
updateArgs: {
|
|
145153
145256
|
context_window: 9500000,
|
|
145154
145257
|
max_output_tokens: 128000,
|
|
@@ -146030,7 +146133,6 @@ var init_models7 = __esm(() => {
|
|
|
146030
146133
|
handle: "openai/gpt-5.4",
|
|
146031
146134
|
label: "GPT-5.4",
|
|
146032
146135
|
description: "OpenAI's most capable model (high reasoning)",
|
|
146033
|
-
isFeatured: true,
|
|
146034
146136
|
updateArgs: {
|
|
146035
146137
|
reasoning_effort: "high",
|
|
146036
146138
|
verbosity: "medium",
|
|
@@ -146187,7 +146289,6 @@ var init_models7 = __esm(() => {
|
|
|
146187
146289
|
handle: "openai/gpt-5.4-mini",
|
|
146188
146290
|
label: "GPT-5.4 Mini",
|
|
146189
146291
|
description: "Fast, efficient GPT-5.4 variant (med reasoning)",
|
|
146190
|
-
isFeatured: true,
|
|
146191
146292
|
updateArgs: {
|
|
146192
146293
|
reasoning_effort: "medium",
|
|
146193
146294
|
verbosity: "low",
|
|
@@ -146400,7 +146501,8 @@ var init_models7 = __esm(() => {
|
|
|
146400
146501
|
context_window: 1048576,
|
|
146401
146502
|
max_output_tokens: 384000,
|
|
146402
146503
|
parallel_tool_calls: true
|
|
146403
|
-
}
|
|
146504
|
+
},
|
|
146505
|
+
isFeatured: true
|
|
146404
146506
|
},
|
|
146405
146507
|
{
|
|
146406
146508
|
id: "glm-5.2",
|
|
@@ -146444,7 +146546,6 @@ var init_models7 = __esm(() => {
|
|
|
146444
146546
|
handle: "minimax/MiniMax-M2.7",
|
|
146445
146547
|
label: "MiniMax 2.7",
|
|
146446
146548
|
description: "MiniMax's M2.7 coding model",
|
|
146447
|
-
isFeatured: true,
|
|
146448
146549
|
free: true,
|
|
146449
146550
|
updateArgs: {
|
|
146450
146551
|
context_window: 160000,
|
|
@@ -151819,12 +151920,14 @@ var init_commands = __esm(() => {
|
|
|
151819
151920
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
151820
151921
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile6 } from "node:fs/promises";
|
|
151821
151922
|
import { basename as basename6, extname as extname3, join as join12 } from "node:path";
|
|
151822
|
-
function mapSlackThreadMessage(message) {
|
|
151923
|
+
async function mapSlackThreadMessage(message, attachmentOptions) {
|
|
151924
|
+
const attachments = await resolveSlackMessageAttachments(message, attachmentOptions);
|
|
151823
151925
|
return {
|
|
151824
151926
|
text: resolveSlackThreadMessageText(message),
|
|
151825
151927
|
userId: isNonEmptyString2(message.user) ? message.user : undefined,
|
|
151826
151928
|
botId: isNonEmptyString2(message.bot_id) ? message.bot_id : undefined,
|
|
151827
|
-
ts: isNonEmptyString2(message.ts) ? message.ts : undefined
|
|
151929
|
+
ts: isNonEmptyString2(message.ts) ? message.ts : undefined,
|
|
151930
|
+
...attachments.length > 0 ? { attachments } : {}
|
|
151828
151931
|
};
|
|
151829
151932
|
}
|
|
151830
151933
|
function asRecord(value) {
|
|
@@ -152128,12 +152231,11 @@ function collectSlackFiles(rawEvent) {
|
|
|
152128
152231
|
}
|
|
152129
152232
|
return Array.from(deduped.values()).slice(0, MAX_SLACK_ATTACHMENTS);
|
|
152130
152233
|
}
|
|
152131
|
-
async function
|
|
152132
|
-
|
|
152133
|
-
if (files.length === 0) {
|
|
152234
|
+
async function resolveSlackFilesAsAttachments(params) {
|
|
152235
|
+
if (params.files.length === 0) {
|
|
152134
152236
|
return [];
|
|
152135
152237
|
}
|
|
152136
|
-
const resolved = await Promise.all(files.map((file3) => downloadSlackAttachment({
|
|
152238
|
+
const resolved = await Promise.all(params.files.map((file3) => downloadSlackAttachment({
|
|
152137
152239
|
accountId: params.accountId,
|
|
152138
152240
|
token: params.token,
|
|
152139
152241
|
file: file3,
|
|
@@ -152141,6 +152243,44 @@ async function resolveSlackInboundAttachments(params) {
|
|
|
152141
152243
|
}).catch(() => null)));
|
|
152142
152244
|
return resolved.filter((attachment) => Boolean(attachment));
|
|
152143
152245
|
}
|
|
152246
|
+
function resolveSlackThreadAttachmentOptions(params) {
|
|
152247
|
+
if (!isNonEmptyString2(params.accountId) || !isNonEmptyString2(params.token)) {
|
|
152248
|
+
return;
|
|
152249
|
+
}
|
|
152250
|
+
return {
|
|
152251
|
+
accountId: params.accountId,
|
|
152252
|
+
token: params.token,
|
|
152253
|
+
transcribeVoice: params.transcribeVoice
|
|
152254
|
+
};
|
|
152255
|
+
}
|
|
152256
|
+
function hasSlackThreadMessageContent(message, attachmentOptions) {
|
|
152257
|
+
if (resolveSlackThreadMessageText(message)) {
|
|
152258
|
+
return true;
|
|
152259
|
+
}
|
|
152260
|
+
return Boolean(attachmentOptions && collectSlackFiles(message).length > 0);
|
|
152261
|
+
}
|
|
152262
|
+
function hasHydratedSlackThreadMessageContent(message) {
|
|
152263
|
+
return message.text.length > 0 || Boolean(message.attachments?.length);
|
|
152264
|
+
}
|
|
152265
|
+
async function resolveSlackMessageAttachments(message, attachmentOptions) {
|
|
152266
|
+
if (!attachmentOptions) {
|
|
152267
|
+
return [];
|
|
152268
|
+
}
|
|
152269
|
+
return resolveSlackFilesAsAttachments({
|
|
152270
|
+
accountId: attachmentOptions.accountId,
|
|
152271
|
+
token: attachmentOptions.token,
|
|
152272
|
+
files: collectSlackFiles(message),
|
|
152273
|
+
transcribeVoice: attachmentOptions.transcribeVoice
|
|
152274
|
+
});
|
|
152275
|
+
}
|
|
152276
|
+
async function resolveSlackInboundAttachments(params) {
|
|
152277
|
+
return resolveSlackFilesAsAttachments({
|
|
152278
|
+
accountId: params.accountId,
|
|
152279
|
+
token: params.token,
|
|
152280
|
+
files: collectSlackFiles(params.rawEvent),
|
|
152281
|
+
transcribeVoice: params.transcribeVoice
|
|
152282
|
+
});
|
|
152283
|
+
}
|
|
152144
152284
|
async function resolveSlackThreadStarter(params) {
|
|
152145
152285
|
try {
|
|
152146
152286
|
const response = await params.client.conversations.replies({
|
|
@@ -152153,16 +152293,12 @@ async function resolveSlackThreadStarter(params) {
|
|
|
152153
152293
|
if (!message) {
|
|
152154
152294
|
return null;
|
|
152155
152295
|
}
|
|
152156
|
-
const
|
|
152157
|
-
if (!
|
|
152296
|
+
const attachmentOptions = resolveSlackThreadAttachmentOptions(params);
|
|
152297
|
+
if (!hasSlackThreadMessageContent(message, attachmentOptions)) {
|
|
152158
152298
|
return null;
|
|
152159
152299
|
}
|
|
152160
|
-
|
|
152161
|
-
|
|
152162
|
-
userId: isNonEmptyString2(message.user) ? message.user : undefined,
|
|
152163
|
-
botId: isNonEmptyString2(message.bot_id) ? message.bot_id : undefined,
|
|
152164
|
-
ts: isNonEmptyString2(message.ts) ? message.ts : undefined
|
|
152165
|
-
};
|
|
152300
|
+
const mapped3 = await mapSlackThreadMessage(message, attachmentOptions);
|
|
152301
|
+
return hasHydratedSlackThreadMessageContent(mapped3) ? mapped3 : null;
|
|
152166
152302
|
} catch {
|
|
152167
152303
|
return null;
|
|
152168
152304
|
}
|
|
@@ -152174,6 +152310,7 @@ async function resolveSlackThreadHistory(params) {
|
|
|
152174
152310
|
}
|
|
152175
152311
|
const fetchLimit = 200;
|
|
152176
152312
|
const retained = [];
|
|
152313
|
+
const attachmentOptions = resolveSlackThreadAttachmentOptions(params);
|
|
152177
152314
|
let cursor;
|
|
152178
152315
|
try {
|
|
152179
152316
|
do {
|
|
@@ -152185,8 +152322,7 @@ async function resolveSlackThreadHistory(params) {
|
|
|
152185
152322
|
...cursor ? { cursor } : {}
|
|
152186
152323
|
});
|
|
152187
152324
|
for (const message of response.messages ?? []) {
|
|
152188
|
-
|
|
152189
|
-
if (!text) {
|
|
152325
|
+
if (!hasSlackThreadMessageContent(message, attachmentOptions)) {
|
|
152190
152326
|
continue;
|
|
152191
152327
|
}
|
|
152192
152328
|
if (params.currentMessageTs && message.ts === params.currentMessageTs) {
|
|
@@ -152203,7 +152339,8 @@ async function resolveSlackThreadHistory(params) {
|
|
|
152203
152339
|
const nextCursor = response.response_metadata?.next_cursor;
|
|
152204
152340
|
cursor = typeof nextCursor === "string" && nextCursor.trim().length > 0 ? nextCursor.trim() : undefined;
|
|
152205
152341
|
} while (cursor);
|
|
152206
|
-
|
|
152342
|
+
const mapped3 = await Promise.all(retained.map((message) => mapSlackThreadMessage(message, attachmentOptions)));
|
|
152343
|
+
return mapped3.filter(hasHydratedSlackThreadMessageContent);
|
|
152207
152344
|
} catch {
|
|
152208
152345
|
return [];
|
|
152209
152346
|
}
|
|
@@ -152214,6 +152351,7 @@ async function resolveSlackChannelHistory(params) {
|
|
|
152214
152351
|
return [];
|
|
152215
152352
|
}
|
|
152216
152353
|
const fetchLimit = Math.min(Math.max(maxMessages * 3, maxMessages), 100);
|
|
152354
|
+
const attachmentOptions = resolveSlackThreadAttachmentOptions(params);
|
|
152217
152355
|
try {
|
|
152218
152356
|
const response = await params.client.conversations.history({
|
|
152219
152357
|
channel: params.channelId,
|
|
@@ -152225,9 +152363,10 @@ async function resolveSlackChannelHistory(params) {
|
|
|
152225
152363
|
if (message.ts === params.beforeTs) {
|
|
152226
152364
|
return false;
|
|
152227
152365
|
}
|
|
152228
|
-
return
|
|
152366
|
+
return hasSlackThreadMessageContent(message, attachmentOptions);
|
|
152229
152367
|
}).slice(0, fetchLimit).reverse();
|
|
152230
|
-
|
|
152368
|
+
const mapped3 = await Promise.all(retained.slice(-maxMessages).map((message) => mapSlackThreadMessage(message, attachmentOptions)));
|
|
152369
|
+
return mapped3.filter(hasHydratedSlackThreadMessageContent);
|
|
152231
152370
|
} catch {
|
|
152232
152371
|
return [];
|
|
152233
152372
|
}
|
|
@@ -153193,22 +153332,30 @@ function createSlackAdapter(config3) {
|
|
|
153193
153332
|
return msg;
|
|
153194
153333
|
}
|
|
153195
153334
|
const slackApp = await ensureApp();
|
|
153335
|
+
const threadAttachmentParams = {
|
|
153336
|
+
accountId: config3.accountId,
|
|
153337
|
+
token: config3.botToken,
|
|
153338
|
+
transcribeVoice: config3.transcribeVoice === true
|
|
153339
|
+
};
|
|
153196
153340
|
const starter = shouldHydrateExistingThreadContext && isFirstRouteTurn ? await resolveSlackThreadStarter({
|
|
153197
153341
|
channelId: msg.chatId,
|
|
153198
153342
|
threadTs: msg.threadId,
|
|
153199
|
-
client: slackApp.client
|
|
153343
|
+
client: slackApp.client,
|
|
153344
|
+
...threadAttachmentParams
|
|
153200
153345
|
}) : null;
|
|
153201
153346
|
const resolvedHistory = shouldHydrateExistingThreadContext ? await resolveSlackThreadHistory({
|
|
153202
153347
|
channelId: msg.chatId,
|
|
153203
153348
|
threadTs: msg.threadId,
|
|
153204
153349
|
client: slackApp.client,
|
|
153205
153350
|
currentMessageTs: msg.messageId,
|
|
153206
|
-
limit: INITIAL_SLACK_THREAD_HISTORY_LIMIT
|
|
153351
|
+
limit: INITIAL_SLACK_THREAD_HISTORY_LIMIT,
|
|
153352
|
+
...threadAttachmentParams
|
|
153207
153353
|
}) : await resolveSlackChannelHistory({
|
|
153208
153354
|
channelId: msg.chatId,
|
|
153209
153355
|
beforeTs: msg.messageId,
|
|
153210
153356
|
client: slackApp.client,
|
|
153211
|
-
limit: INITIAL_SLACK_THREAD_HISTORY_LIMIT
|
|
153357
|
+
limit: INITIAL_SLACK_THREAD_HISTORY_LIMIT,
|
|
153358
|
+
...threadAttachmentParams
|
|
153212
153359
|
});
|
|
153213
153360
|
const history = shouldHydrateExistingThreadContext && !isFirstRouteTurn ? resolvedHistory.filter((entry) => isNonEmptyString3(entry.botId)) : resolvedHistory;
|
|
153214
153361
|
if (!starter && history.length === 0) {
|
|
@@ -153244,7 +153391,8 @@ function createSlackAdapter(config3) {
|
|
|
153244
153391
|
messageId: starter.ts,
|
|
153245
153392
|
senderId: starter.userId ?? starter.botId,
|
|
153246
153393
|
senderName: resolveThreadSenderName(starter.userId, starter.botId),
|
|
153247
|
-
text: starter.text
|
|
153394
|
+
text: starter.text,
|
|
153395
|
+
...starter.attachments?.length ? { attachments: starter.attachments } : {}
|
|
153248
153396
|
}
|
|
153249
153397
|
} : {},
|
|
153250
153398
|
...history.length > 0 ? {
|
|
@@ -153252,7 +153400,8 @@ function createSlackAdapter(config3) {
|
|
|
153252
153400
|
messageId: entry.ts,
|
|
153253
153401
|
senderId: entry.userId ?? entry.botId,
|
|
153254
153402
|
senderName: resolveThreadSenderName(entry.userId, entry.botId),
|
|
153255
|
-
text: entry.text
|
|
153403
|
+
text: entry.text,
|
|
153404
|
+
...entry.attachments?.length ? { attachments: entry.attachments } : {}
|
|
153256
153405
|
}))
|
|
153257
153406
|
} : {}
|
|
153258
153407
|
}
|
|
@@ -159822,6 +159971,15 @@ function escapeXmlText(text) {
|
|
|
159822
159971
|
function escapeXmlAttribute(text) {
|
|
159823
159972
|
return escapeXmlText(text).replace(/"/g, """).replace(/'/g, "'");
|
|
159824
159973
|
}
|
|
159974
|
+
function hasNotificationAttachmentPaths(msg) {
|
|
159975
|
+
if (msg.attachments?.length) {
|
|
159976
|
+
return true;
|
|
159977
|
+
}
|
|
159978
|
+
if (msg.threadContext?.starter?.attachments?.length) {
|
|
159979
|
+
return true;
|
|
159980
|
+
}
|
|
159981
|
+
return Boolean(msg.threadContext?.history?.some((entry) => entry.attachments?.length));
|
|
159982
|
+
}
|
|
159825
159983
|
function buildChannelReminderText(msg) {
|
|
159826
159984
|
const localTime = escapeXmlText(getLocalTime());
|
|
159827
159985
|
const escapedChannel = escapeXmlText(msg.channel);
|
|
@@ -159857,7 +160015,7 @@ function buildChannelReminderText(msg) {
|
|
|
159857
160015
|
if (msg.channel === "signal") {
|
|
159858
160016
|
lines.splice(lines.length - 2, 0, 'On Signal, MessageChannel also supports action="react" with emoji + messageId, and action="upload-file" with media. Replies are sent as the linked Signal account through signal-cli-rest-api.');
|
|
159859
160017
|
}
|
|
159860
|
-
if (msg
|
|
160018
|
+
if (hasNotificationAttachmentPaths(msg)) {
|
|
159861
160019
|
lines.splice(lines.length - 2, 0, "If this notification includes attachment local_path values, you may be able to inspect those files using local file or image tools available in your current toolset (for example Read or ViewImage), using the local_path.");
|
|
159862
160020
|
}
|
|
159863
160021
|
return lines.join(`
|
|
@@ -159948,8 +160106,13 @@ function buildThreadContextEntryXml(tagName, entry) {
|
|
|
159948
160106
|
attrs.push(`message_id="${escapeXmlAttribute(entry.messageId)}"`);
|
|
159949
160107
|
}
|
|
159950
160108
|
const attrString = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
160109
|
+
const body = [
|
|
160110
|
+
...entry.text ? [escapeXmlText(entry.text)] : [],
|
|
160111
|
+
...(entry.attachments ?? []).map(buildAttachmentXml)
|
|
160112
|
+
].join(`
|
|
160113
|
+
`);
|
|
159951
160114
|
return `<${tagName}${attrString}>
|
|
159952
|
-
${
|
|
160115
|
+
${body}
|
|
159953
160116
|
</${tagName}>`;
|
|
159954
160117
|
}
|
|
159955
160118
|
function buildThreadContextXml(msg) {
|
|
@@ -167949,6 +168112,10 @@ function getShellEnv() {
|
|
|
167949
168112
|
if (agentId) {
|
|
167950
168113
|
env3.LETTA_AGENT_ID = agentId;
|
|
167951
168114
|
env3.AGENT_ID = agentId;
|
|
168115
|
+
const agentName = getCurrentAgentName()?.trim() || env3.AGENT_NAME?.trim();
|
|
168116
|
+
if (agentName) {
|
|
168117
|
+
env3.AGENT_NAME = agentName;
|
|
168118
|
+
}
|
|
167952
168119
|
try {
|
|
167953
168120
|
const localBackendNoMemfs = isLocalBackendMemfsDisabledForProcess();
|
|
167954
168121
|
const localBackendEnabled = process.env.LETTA_LOCAL_BACKEND_EXPERIMENTAL === "1" || process.env.LETTA_LOCAL_BACKEND_EXPERIMENTAL?.toLowerCase() === "true";
|
|
@@ -363661,7 +363828,7 @@ function getMemoryGitIdentityEnvOverrides(command, workdir) {
|
|
|
363661
363828
|
if (!scopedToMemoryDir) {
|
|
363662
363829
|
return;
|
|
363663
363830
|
}
|
|
363664
|
-
const agentName = (
|
|
363831
|
+
const agentName = getCurrentAgentNameOrEnv() || agentId;
|
|
363665
363832
|
const agentEmail = `${agentId}@letta.com`;
|
|
363666
363833
|
return {
|
|
363667
363834
|
GIT_AUTHOR_NAME: agentName,
|
|
@@ -363679,6 +363846,14 @@ function getCurrentAgentIdOrEnv() {
|
|
|
363679
363846
|
} catch {}
|
|
363680
363847
|
return (process.env.LETTA_AGENT_ID || process.env.AGENT_ID || "").trim();
|
|
363681
363848
|
}
|
|
363849
|
+
function getCurrentAgentNameOrEnv() {
|
|
363850
|
+
const scopedName = getCurrentAgentName()?.trim();
|
|
363851
|
+
if (scopedName) {
|
|
363852
|
+
return scopedName;
|
|
363853
|
+
}
|
|
363854
|
+
const envName = process.env.AGENT_NAME?.trim();
|
|
363855
|
+
return envName || null;
|
|
363856
|
+
}
|
|
363682
363857
|
function containsGitCommitInvocation(command) {
|
|
363683
363858
|
const segments = command.split(/&&|\|\||;|\|/).map((segment) => segment.trim()).filter(Boolean);
|
|
363684
363859
|
for (const segment of segments) {
|
|
@@ -373739,6 +373914,7 @@ async function prepareToolExecutionContextForScope(params) {
|
|
|
373739
373914
|
agent: agent2,
|
|
373740
373915
|
runtimeContext: {
|
|
373741
373916
|
agentId,
|
|
373917
|
+
agentName: agent2.name ?? null,
|
|
373742
373918
|
conversationId: scopedConversationId,
|
|
373743
373919
|
workingDirectory,
|
|
373744
373920
|
...channelToolScope.channels.length > 0 ? { channelToolScope } : {},
|
|
@@ -438900,6 +439076,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
438900
439076
|
conversationId
|
|
438901
439077
|
});
|
|
438902
439078
|
setCurrentAgentId(agentId);
|
|
439079
|
+
setCurrentAgentName(listenAgentMetadata?.name ?? null);
|
|
438903
439080
|
setConversationId(conversationId);
|
|
438904
439081
|
if (isDebugEnabled()) {
|
|
438905
439082
|
console.log(`[Listen] Handling message: agentId=${agentId}, requestedConversationId=${requestedConversationId}, conversationId=${conversationId}`);
|
|
@@ -438959,6 +439136,7 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
438959
439136
|
lastRunAt: cachedAgent.last_run_completion ?? null
|
|
438960
439137
|
};
|
|
438961
439138
|
}
|
|
439139
|
+
setCurrentAgentName(listenAgentMetadata?.name ?? cachedAgent?.name ?? null);
|
|
438962
439140
|
const { parts: reminderParts } = await buildSharedReminderParts(buildListenReminderContext({
|
|
438963
439141
|
agentId: agentId || "",
|
|
438964
439142
|
conversationId,
|
|
@@ -440884,6 +441062,15 @@ var init_file_commands = __esm(async () => {
|
|
|
440884
441062
|
ignoreConfigCache = new Map;
|
|
440885
441063
|
});
|
|
440886
441064
|
|
|
441065
|
+
// src/agent/acting-user.ts
|
|
441066
|
+
function actingUserRequestOptions(actingUserId) {
|
|
441067
|
+
if (!actingUserId) {
|
|
441068
|
+
return;
|
|
441069
|
+
}
|
|
441070
|
+
return { headers: { [ACTING_USER_ID_HEADER]: actingUserId } };
|
|
441071
|
+
}
|
|
441072
|
+
var ACTING_USER_ID_HEADER = "X-Letta-Acting-User-Id";
|
|
441073
|
+
|
|
440887
441074
|
// src/agent/max-context.ts
|
|
440888
441075
|
function buildModelHandleFromConfig4(config3) {
|
|
440889
441076
|
if (!config3)
|
|
@@ -441286,10 +441473,15 @@ function buildDoctorMessage(args) {
|
|
|
441286
441473
|
## Memory filesystem
|
|
441287
441474
|
|
|
441288
441475
|
Memory filesystem is enabled. Memory directory: \`${args.memoryDir}\`
|
|
441476
|
+
` : "";
|
|
441477
|
+
const skillRepairSection = args.skillNameFrontmatterRepairReport ? `
|
|
441478
|
+
## Automatic skill metadata repair
|
|
441479
|
+
|
|
441480
|
+
${args.skillNameFrontmatterRepairReport}
|
|
441289
441481
|
` : "";
|
|
441290
441482
|
return `${SYSTEM_REMINDER_OPEN}
|
|
441291
441483
|
The user has requested a memory structure check via /doctor.
|
|
441292
|
-
${memfsSection}
|
|
441484
|
+
${memfsSection}${skillRepairSection}
|
|
441293
441485
|
## 1. Invoke the context-doctor skill
|
|
441294
441486
|
|
|
441295
441487
|
Use the \`Skill\` tool with \`skill: "context-doctor"\` to load guidance for memory structure refinement.
|
|
@@ -441307,6 +441499,150 @@ var init_init_command = __esm(() => {
|
|
|
441307
441499
|
init_git_context();
|
|
441308
441500
|
});
|
|
441309
441501
|
|
|
441502
|
+
// src/cli/helpers/skill-name-frontmatter-repair.ts
|
|
441503
|
+
import { readdir as readdir11, readFile as readFile18, stat as stat13, writeFile as writeFile14 } from "node:fs/promises";
|
|
441504
|
+
import { basename as basename23, dirname as dirname24, join as join48, relative as relative10 } from "node:path";
|
|
441505
|
+
async function pathExists(path36) {
|
|
441506
|
+
try {
|
|
441507
|
+
await stat13(path36);
|
|
441508
|
+
return true;
|
|
441509
|
+
} catch {
|
|
441510
|
+
return false;
|
|
441511
|
+
}
|
|
441512
|
+
}
|
|
441513
|
+
async function findSkillMarkdownFiles(root2) {
|
|
441514
|
+
const entries = await readdir11(root2, { withFileTypes: true });
|
|
441515
|
+
const files = [];
|
|
441516
|
+
for (const entry of entries) {
|
|
441517
|
+
if (entry.name === ".git" || entry.name === "node_modules") {
|
|
441518
|
+
continue;
|
|
441519
|
+
}
|
|
441520
|
+
const fullPath = join48(root2, entry.name);
|
|
441521
|
+
if (entry.isSymbolicLink()) {
|
|
441522
|
+
continue;
|
|
441523
|
+
}
|
|
441524
|
+
if (entry.isDirectory()) {
|
|
441525
|
+
files.push(...await findSkillMarkdownFiles(fullPath));
|
|
441526
|
+
continue;
|
|
441527
|
+
}
|
|
441528
|
+
if (entry.isFile() && entry.name === "SKILL.md") {
|
|
441529
|
+
files.push(fullPath);
|
|
441530
|
+
}
|
|
441531
|
+
}
|
|
441532
|
+
return files;
|
|
441533
|
+
}
|
|
441534
|
+
function formatYamlScalar(value) {
|
|
441535
|
+
if (/^[A-Za-z0-9_-]+$/.test(value)) {
|
|
441536
|
+
return value;
|
|
441537
|
+
}
|
|
441538
|
+
return JSON.stringify(value);
|
|
441539
|
+
}
|
|
441540
|
+
function isNonEmptyNameLine(line) {
|
|
441541
|
+
const match4 = line.match(/^\s*name\s*:\s*(.*?)\s*$/);
|
|
441542
|
+
return !!match4?.[1]?.trim();
|
|
441543
|
+
}
|
|
441544
|
+
function repairSkillNameFrontmatterContent(content, skillName) {
|
|
441545
|
+
if (!skillName.trim()) {
|
|
441546
|
+
return {
|
|
441547
|
+
content,
|
|
441548
|
+
changed: false,
|
|
441549
|
+
reason: "skill directory name is empty"
|
|
441550
|
+
};
|
|
441551
|
+
}
|
|
441552
|
+
const match4 = content.match(FRONTMATTER_REGEX2);
|
|
441553
|
+
if (!match4) {
|
|
441554
|
+
return {
|
|
441555
|
+
content,
|
|
441556
|
+
changed: false,
|
|
441557
|
+
reason: "missing YAML frontmatter"
|
|
441558
|
+
};
|
|
441559
|
+
}
|
|
441560
|
+
const opening2 = match4[1] ?? "";
|
|
441561
|
+
const frontmatter = match4[2] ?? "";
|
|
441562
|
+
const closing2 = match4[3] ?? "";
|
|
441563
|
+
const newline = opening2.includes(`\r
|
|
441564
|
+
`) ? `\r
|
|
441565
|
+
` : `
|
|
441566
|
+
`;
|
|
441567
|
+
const lines = frontmatter.replace(/\r\n/g, `
|
|
441568
|
+
`).split(`
|
|
441569
|
+
`);
|
|
441570
|
+
const nameLineIndex = lines.findIndex((line) => /^\s*name\s*:/.test(line));
|
|
441571
|
+
if (nameLineIndex >= 0 && isNonEmptyNameLine(lines[nameLineIndex] ?? "")) {
|
|
441572
|
+
return { content, changed: false };
|
|
441573
|
+
}
|
|
441574
|
+
const nameLine = `name: ${formatYamlScalar(skillName.trim())}`;
|
|
441575
|
+
if (nameLineIndex >= 0) {
|
|
441576
|
+
lines[nameLineIndex] = nameLine;
|
|
441577
|
+
} else {
|
|
441578
|
+
lines.unshift(nameLine);
|
|
441579
|
+
}
|
|
441580
|
+
const nextContent = `${opening2}${lines.join(newline)}${closing2}${content.slice(match4[0].length)}`;
|
|
441581
|
+
return { content: nextContent, changed: true };
|
|
441582
|
+
}
|
|
441583
|
+
async function repairMissingSkillNameFrontmatter(memoryDir) {
|
|
441584
|
+
const result = {
|
|
441585
|
+
scanned: 0,
|
|
441586
|
+
repaired: [],
|
|
441587
|
+
skipped: []
|
|
441588
|
+
};
|
|
441589
|
+
if (!memoryDir) {
|
|
441590
|
+
return result;
|
|
441591
|
+
}
|
|
441592
|
+
const skillsDir = join48(memoryDir, "skills");
|
|
441593
|
+
if (!await pathExists(skillsDir)) {
|
|
441594
|
+
return result;
|
|
441595
|
+
}
|
|
441596
|
+
let skillFiles;
|
|
441597
|
+
try {
|
|
441598
|
+
skillFiles = await findSkillMarkdownFiles(skillsDir);
|
|
441599
|
+
} catch (error54) {
|
|
441600
|
+
result.skipped.push({
|
|
441601
|
+
path: "skills/",
|
|
441602
|
+
reason: `failed to scan skills directory: ${error54 instanceof Error ? error54.message : String(error54)}`
|
|
441603
|
+
});
|
|
441604
|
+
return result;
|
|
441605
|
+
}
|
|
441606
|
+
for (const skillFile of skillFiles.sort()) {
|
|
441607
|
+
const displayPath = relative10(memoryDir, skillFile).replace(/\\/g, "/");
|
|
441608
|
+
result.scanned++;
|
|
441609
|
+
try {
|
|
441610
|
+
const content = await readFile18(skillFile, "utf8");
|
|
441611
|
+
const repair3 = repairSkillNameFrontmatterContent(content, basename23(dirname24(skillFile)));
|
|
441612
|
+
if (repair3.reason) {
|
|
441613
|
+
result.skipped.push({ path: displayPath, reason: repair3.reason });
|
|
441614
|
+
continue;
|
|
441615
|
+
}
|
|
441616
|
+
if (!repair3.changed) {
|
|
441617
|
+
continue;
|
|
441618
|
+
}
|
|
441619
|
+
await writeFile14(skillFile, repair3.content, "utf8");
|
|
441620
|
+
result.repaired.push(displayPath);
|
|
441621
|
+
} catch (error54) {
|
|
441622
|
+
result.skipped.push({
|
|
441623
|
+
path: displayPath,
|
|
441624
|
+
reason: error54 instanceof Error ? error54.message : String(error54)
|
|
441625
|
+
});
|
|
441626
|
+
}
|
|
441627
|
+
}
|
|
441628
|
+
return result;
|
|
441629
|
+
}
|
|
441630
|
+
function formatSkillNameFrontmatterRepairReport(result) {
|
|
441631
|
+
const sections = [];
|
|
441632
|
+
if (result.repaired.length > 0) {
|
|
441633
|
+
sections.push(`- Added missing \`name:\` frontmatter to ${result.repaired.length} skill${result.repaired.length === 1 ? "" : "s"}: ${result.repaired.map((path36) => `\`${path36}\``).join(", ")}`);
|
|
441634
|
+
}
|
|
441635
|
+
if (result.skipped.length > 0) {
|
|
441636
|
+
sections.push(`- Could not automatically repair ${result.skipped.length} skill${result.skipped.length === 1 ? "" : "s"}: ${result.skipped.map((item) => `\`${item.path}\` (${item.reason})`).join(", ")}`);
|
|
441637
|
+
}
|
|
441638
|
+
return sections.join(`
|
|
441639
|
+
`);
|
|
441640
|
+
}
|
|
441641
|
+
var FRONTMATTER_REGEX2;
|
|
441642
|
+
var init_skill_name_frontmatter_repair = __esm(() => {
|
|
441643
|
+
FRONTMATTER_REGEX2 = /^(---\r?\n)([\s\S]*?)(\r?\n---(?:\r?\n|$))/;
|
|
441644
|
+
});
|
|
441645
|
+
|
|
441310
441646
|
// src/websocket/listener/commands/secrets.ts
|
|
441311
441647
|
function markSecretsReminderRefreshPending(runtime, agentId) {
|
|
441312
441648
|
const prefix = `agent:${agentId}::conversation:`;
|
|
@@ -441411,7 +441747,10 @@ async function handleExecuteCommand(command, socket, conversationRuntime, opts)
|
|
|
441411
441747
|
let output;
|
|
441412
441748
|
switch (command.command_id) {
|
|
441413
441749
|
case "clear":
|
|
441414
|
-
output = await handleClearCommand(socket, conversationRuntime,
|
|
441750
|
+
output = await handleClearCommand(socket, conversationRuntime, {
|
|
441751
|
+
...opts,
|
|
441752
|
+
actingUserId: command.runtime.acting_user_id
|
|
441753
|
+
});
|
|
441415
441754
|
break;
|
|
441416
441755
|
case "doctor":
|
|
441417
441756
|
output = await handleDoctorCommand(socket, conversationRuntime, opts);
|
|
@@ -441698,7 +442037,7 @@ async function handleClearCommand(_socket, conversationRuntime, opts) {
|
|
|
441698
442037
|
}
|
|
441699
442038
|
const conversation = await backend4.createConversation({
|
|
441700
442039
|
agent_id: agentId
|
|
441701
|
-
});
|
|
442040
|
+
}, actingUserRequestOptions(opts.actingUserId));
|
|
441702
442041
|
clearConversationRuntimeState(conversationRuntime);
|
|
441703
442042
|
conversationRuntime.conversationId = conversation.id;
|
|
441704
442043
|
emitListenerStatus(conversationRuntime.listener, opts.onStatusChange, opts.connectionId);
|
|
@@ -441711,7 +442050,13 @@ async function handleDoctorCommand(socket, conversationRuntime, opts) {
|
|
|
441711
442050
|
}
|
|
441712
442051
|
const { context: gitContext } = gatherInitGitContext();
|
|
441713
442052
|
const memoryDir = settingsManager.isMemfsEnabled(agentId) ? getScopedMemoryFilesystemRoot(agentId) : undefined;
|
|
441714
|
-
const
|
|
442053
|
+
const skillNameFrontmatterRepair = await repairMissingSkillNameFrontmatter(memoryDir);
|
|
442054
|
+
const skillNameFrontmatterRepairReport = formatSkillNameFrontmatterRepairReport(skillNameFrontmatterRepair);
|
|
442055
|
+
const doctorMessage = buildDoctorMessage({
|
|
442056
|
+
gitContext,
|
|
442057
|
+
memoryDir,
|
|
442058
|
+
skillNameFrontmatterRepairReport
|
|
442059
|
+
});
|
|
441715
442060
|
await handleIncomingMessage({
|
|
441716
442061
|
type: "message",
|
|
441717
442062
|
agentId,
|
|
@@ -441898,6 +442243,7 @@ var init_commands2 = __esm(async () => {
|
|
|
441898
442243
|
init_error_formatter();
|
|
441899
442244
|
init_init_command();
|
|
441900
442245
|
init_memory_reminder();
|
|
442246
|
+
init_skill_name_frontmatter_repair();
|
|
441901
442247
|
init_command_runtime();
|
|
441902
442248
|
init_constants();
|
|
441903
442249
|
init_hooks2();
|
|
@@ -442088,7 +442434,7 @@ async function handleAgentConversationManagementCommand(parsed, socket, safeSock
|
|
|
442088
442434
|
}
|
|
442089
442435
|
if (parsed.type === "conversation_create") {
|
|
442090
442436
|
try {
|
|
442091
|
-
const conversation = await backend4.createConversation(parsed.body);
|
|
442437
|
+
const conversation = await backend4.createConversation(parsed.body, actingUserRequestOptions(parsed.acting_user_id));
|
|
442092
442438
|
safeSocketSend(socket, {
|
|
442093
442439
|
type: "conversation_create_response",
|
|
442094
442440
|
request_id: parsed.request_id,
|
|
@@ -442150,7 +442496,8 @@ async function handleAgentConversationManagementCommand(parsed, socket, safeSock
|
|
|
442150
442496
|
try {
|
|
442151
442497
|
const conversation = await backend4.forkConversation(parsed.conversation_id, {
|
|
442152
442498
|
...typeof parsed.body?.agent_id === "string" ? { agentId: parsed.body.agent_id } : {},
|
|
442153
|
-
...typeof parsed.body?.hidden === "boolean" ? { hidden: parsed.body.hidden } : {}
|
|
442499
|
+
...typeof parsed.body?.hidden === "boolean" ? { hidden: parsed.body.hidden } : {},
|
|
442500
|
+
...actingUserRequestOptions(parsed.acting_user_id) ?? {}
|
|
442154
442501
|
});
|
|
442155
442502
|
safeSocketSend(socket, {
|
|
442156
442503
|
type: "conversation_fork_response",
|
|
@@ -443606,7 +443953,7 @@ __export(exports_memory_scanner, {
|
|
|
443606
443953
|
getFileNodes: () => getFileNodes
|
|
443607
443954
|
});
|
|
443608
443955
|
import { readdirSync as readdirSync15, readFileSync as readFileSync31, statSync as statSync16 } from "node:fs";
|
|
443609
|
-
import { join as
|
|
443956
|
+
import { join as join49, relative as relative11 } from "node:path";
|
|
443610
443957
|
function scanMemoryFilesystem(memoryRoot) {
|
|
443611
443958
|
const nodes = [];
|
|
443612
443959
|
const scanDir = (dir, depth, parentIsLast) => {
|
|
@@ -443618,8 +443965,8 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
443618
443965
|
}
|
|
443619
443966
|
const filtered = entries.filter((name) => !name.startsWith("."));
|
|
443620
443967
|
const sorted = filtered.sort((a2, b3) => {
|
|
443621
|
-
const aPath =
|
|
443622
|
-
const bPath =
|
|
443968
|
+
const aPath = join49(dir, a2);
|
|
443969
|
+
const bPath = join49(dir, b3);
|
|
443623
443970
|
let aIsDir = false;
|
|
443624
443971
|
let bIsDir = false;
|
|
443625
443972
|
try {
|
|
@@ -443639,14 +443986,14 @@ function scanMemoryFilesystem(memoryRoot) {
|
|
|
443639
443986
|
return a2.localeCompare(b3);
|
|
443640
443987
|
});
|
|
443641
443988
|
sorted.forEach((name, index) => {
|
|
443642
|
-
const fullPath =
|
|
443989
|
+
const fullPath = join49(dir, name);
|
|
443643
443990
|
let isDir = false;
|
|
443644
443991
|
try {
|
|
443645
443992
|
isDir = statSync16(fullPath).isDirectory();
|
|
443646
443993
|
} catch {
|
|
443647
443994
|
return;
|
|
443648
443995
|
}
|
|
443649
|
-
const relativePath =
|
|
443996
|
+
const relativePath = relative11(memoryRoot, fullPath).replace(/\\/g, "/");
|
|
443650
443997
|
const isLast = index === sorted.length - 1;
|
|
443651
443998
|
nodes.push({
|
|
443652
443999
|
name: isDir ? `${name}/` : name,
|
|
@@ -443711,9 +444058,9 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
443711
444058
|
const { scanMemoryFilesystem: scanMemoryFilesystem2, getFileNodes: getFileNodes2, readFileContent: readFileContent2 } = await Promise.resolve().then(() => (init_memory_scanner(), exports_memory_scanner));
|
|
443712
444059
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => exports_frontmatter);
|
|
443713
444060
|
const { existsSync: existsSync46, statSync: statSync17 } = await import("node:fs");
|
|
443714
|
-
const { join:
|
|
444061
|
+
const { join: join50, posix: posix4 } = await import("node:path");
|
|
443715
444062
|
const memoryRoot = getMemoryFilesystemRoot2(parsed.agent_id);
|
|
443716
|
-
let memfsInitialized = existsSync46(
|
|
444063
|
+
let memfsInitialized = existsSync46(join50(memoryRoot, ".git"));
|
|
443717
444064
|
const memfsEnabled = memfsInitialized ? true : await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
443718
444065
|
if (!memfsEnabled) {
|
|
443719
444066
|
safeSocketSend(socket, {
|
|
@@ -443731,7 +444078,7 @@ async function handleListMemoryCommand(parsed, socket, safeSocketSend, overrides
|
|
|
443731
444078
|
await ensureLocalMemfsCheckout2(parsed.agent_id, {
|
|
443732
444079
|
pullOnExistingRepo: true
|
|
443733
444080
|
});
|
|
443734
|
-
memfsInitialized = existsSync46(
|
|
444081
|
+
memfsInitialized = existsSync46(join50(memoryRoot, ".git"));
|
|
443735
444082
|
if (!memfsInitialized) {
|
|
443736
444083
|
throw new Error("MemFS is enabled, but the local memory checkout could not be initialized.");
|
|
443737
444084
|
}
|
|
@@ -444030,33 +444377,33 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
444030
444377
|
ensureLocalMemfsCheckout: ensureLocalMemfsCheckout2,
|
|
444031
444378
|
isMemfsEnabledOnServer: isMemfsEnabledOnServer2
|
|
444032
444379
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
444033
|
-
const { readFile:
|
|
444380
|
+
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
444034
444381
|
const { existsSync: existsSync46 } = await import("node:fs");
|
|
444035
|
-
const { isAbsolute: isAbsolute23, join:
|
|
444382
|
+
const { isAbsolute: isAbsolute23, join: join50, normalize: normalize5, relative: relative12, sep: sep5 } = await import("node:path");
|
|
444036
444383
|
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
444037
444384
|
sendFailure("path must be a non-empty relative path");
|
|
444038
444385
|
return;
|
|
444039
444386
|
}
|
|
444040
444387
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
444041
|
-
const absolutePath = normalize5(
|
|
444042
|
-
const rel =
|
|
444388
|
+
const absolutePath = normalize5(join50(memoryRoot, parsed.path));
|
|
444389
|
+
const rel = relative12(memoryRoot, absolutePath);
|
|
444043
444390
|
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
444044
444391
|
sendFailure("path must resolve inside the memory root");
|
|
444045
444392
|
return;
|
|
444046
444393
|
}
|
|
444047
|
-
if (!existsSync46(
|
|
444394
|
+
if (!existsSync46(join50(memoryRoot, ".git"))) {
|
|
444048
444395
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
444049
444396
|
if (!enabled) {
|
|
444050
444397
|
sendFailure("memfs is not enabled for this agent");
|
|
444051
444398
|
return;
|
|
444052
444399
|
}
|
|
444053
444400
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
444054
|
-
if (!existsSync46(
|
|
444401
|
+
if (!existsSync46(join50(memoryRoot, ".git"))) {
|
|
444055
444402
|
sendFailure("failed to initialize local memory checkout");
|
|
444056
444403
|
return;
|
|
444057
444404
|
}
|
|
444058
444405
|
}
|
|
444059
|
-
const buffer = await
|
|
444406
|
+
const buffer = await readFile19(absolutePath);
|
|
444060
444407
|
const content = encoding === "base64" ? buffer.toString("base64") : buffer.toString("utf-8");
|
|
444061
444408
|
const pathspec = rel.split(sep5).join("/");
|
|
444062
444409
|
safeSocketSend(socket, {
|
|
@@ -444096,35 +444443,35 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
444096
444443
|
isMemfsEnabledOnServer: isMemfsEnabledOnServer2
|
|
444097
444444
|
} = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
444098
444445
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
444099
|
-
const { writeFile:
|
|
444446
|
+
const { writeFile: writeFile15, mkdir: mkdir12 } = await import("node:fs/promises");
|
|
444100
444447
|
const { existsSync: existsSync46 } = await import("node:fs");
|
|
444101
|
-
const { dirname:
|
|
444448
|
+
const { dirname: dirname25, isAbsolute: isAbsolute23, join: join50, normalize: normalize5, relative: relative12, sep: sep5 } = await import("node:path");
|
|
444102
444449
|
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
444103
444450
|
sendFailure("write_memory_file: path must be a non-empty relative path");
|
|
444104
444451
|
return;
|
|
444105
444452
|
}
|
|
444106
444453
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
444107
|
-
const absolutePath = normalize5(
|
|
444108
|
-
const rel =
|
|
444454
|
+
const absolutePath = normalize5(join50(memoryRoot, parsed.path));
|
|
444455
|
+
const rel = relative12(memoryRoot, absolutePath);
|
|
444109
444456
|
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
444110
444457
|
sendFailure("write_memory_file: path must resolve inside the memory root");
|
|
444111
444458
|
return;
|
|
444112
444459
|
}
|
|
444113
|
-
if (!existsSync46(
|
|
444460
|
+
if (!existsSync46(join50(memoryRoot, ".git"))) {
|
|
444114
444461
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
444115
444462
|
if (!enabled) {
|
|
444116
444463
|
sendFailure("write_memory_file: memfs is not enabled for this agent");
|
|
444117
444464
|
return;
|
|
444118
444465
|
}
|
|
444119
444466
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
444120
|
-
if (!existsSync46(
|
|
444467
|
+
if (!existsSync46(join50(memoryRoot, ".git"))) {
|
|
444121
444468
|
sendFailure("write_memory_file: failed to initialize local memory checkout");
|
|
444122
444469
|
return;
|
|
444123
444470
|
}
|
|
444124
444471
|
}
|
|
444125
444472
|
const buffer = encoding === "base64" ? Buffer.from(parsed.content, "base64") : Buffer.from(parsed.content, "utf-8");
|
|
444126
|
-
await mkdir12(
|
|
444127
|
-
await
|
|
444473
|
+
await mkdir12(dirname25(absolutePath), { recursive: true });
|
|
444474
|
+
await writeFile15(absolutePath, buffer);
|
|
444128
444475
|
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
444129
444476
|
const backend4 = getBackend2();
|
|
444130
444477
|
const memorySyncMode = backend4.capabilities.localMemfs && !backend4.capabilities.remoteMemfs ? "local" : undefined;
|
|
@@ -444201,26 +444548,26 @@ function handleMemoryProtocolCommand(parsed, context3) {
|
|
|
444201
444548
|
const { commitMemoryWrite: commitMemoryWrite2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
444202
444549
|
const { unlink: unlink5 } = await import("node:fs/promises");
|
|
444203
444550
|
const { existsSync: existsSync46 } = await import("node:fs");
|
|
444204
|
-
const { isAbsolute: isAbsolute23, join:
|
|
444551
|
+
const { isAbsolute: isAbsolute23, join: join50, normalize: normalize5, relative: relative12, sep: sep5 } = await import("node:path");
|
|
444205
444552
|
if (isAbsolute23(parsed.path) || parsed.path.length === 0) {
|
|
444206
444553
|
sendFailure("delete_memory_file: path must be a non-empty relative path");
|
|
444207
444554
|
return;
|
|
444208
444555
|
}
|
|
444209
444556
|
const memoryRoot = getScopedMemoryFilesystemRoot2(parsed.agent_id);
|
|
444210
|
-
const absolutePath = normalize5(
|
|
444211
|
-
const rel =
|
|
444557
|
+
const absolutePath = normalize5(join50(memoryRoot, parsed.path));
|
|
444558
|
+
const rel = relative12(memoryRoot, absolutePath);
|
|
444212
444559
|
if (rel.startsWith("..") || rel === "" || isAbsolute23(rel) || rel.split(sep5).includes("..")) {
|
|
444213
444560
|
sendFailure("delete_memory_file: path must resolve inside the memory root");
|
|
444214
444561
|
return;
|
|
444215
444562
|
}
|
|
444216
|
-
if (!existsSync46(
|
|
444563
|
+
if (!existsSync46(join50(memoryRoot, ".git"))) {
|
|
444217
444564
|
const enabled = await isMemfsEnabledOnServer2(parsed.agent_id);
|
|
444218
444565
|
if (!enabled) {
|
|
444219
444566
|
sendFailure("delete_memory_file: memfs is not enabled for this agent");
|
|
444220
444567
|
return;
|
|
444221
444568
|
}
|
|
444222
444569
|
await ensureLocalMemfsCheckout2(parsed.agent_id);
|
|
444223
|
-
if (!existsSync46(
|
|
444570
|
+
if (!existsSync46(join50(memoryRoot, ".git"))) {
|
|
444224
444571
|
sendFailure("delete_memory_file: failed to initialize local memory checkout");
|
|
444225
444572
|
return;
|
|
444226
444573
|
}
|
|
@@ -444640,9 +444987,9 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
444640
444987
|
symlinkSync: symlinkSync2,
|
|
444641
444988
|
unlinkSync: unlinkSync7
|
|
444642
444989
|
} = await import("node:fs");
|
|
444643
|
-
const { basename:
|
|
444644
|
-
const lettaHome = process.env.LETTA_HOME ||
|
|
444645
|
-
const globalSkillsDir =
|
|
444990
|
+
const { basename: basename24, join: join50 } = await import("node:path");
|
|
444991
|
+
const lettaHome = process.env.LETTA_HOME || join50(process.env.HOME || process.env.USERPROFILE || "~", ".letta");
|
|
444992
|
+
const globalSkillsDir = join50(lettaHome, "skills");
|
|
444646
444993
|
if (parsed.type === "skill_enable") {
|
|
444647
444994
|
try {
|
|
444648
444995
|
if (!existsSync46(parsed.skill_path)) {
|
|
@@ -444654,7 +445001,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
444654
445001
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
444655
445002
|
return true;
|
|
444656
445003
|
}
|
|
444657
|
-
const skillMdPath =
|
|
445004
|
+
const skillMdPath = join50(parsed.skill_path, "SKILL.md");
|
|
444658
445005
|
if (!existsSync46(skillMdPath)) {
|
|
444659
445006
|
safeSocketSend(socket, {
|
|
444660
445007
|
type: "skill_enable_response",
|
|
@@ -444664,12 +445011,12 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
444664
445011
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
444665
445012
|
return true;
|
|
444666
445013
|
}
|
|
444667
|
-
const linkName =
|
|
444668
|
-
const linkPath =
|
|
445014
|
+
const linkName = basename24(parsed.skill_path);
|
|
445015
|
+
const linkPath = join50(globalSkillsDir, linkName);
|
|
444669
445016
|
mkdirSync31(globalSkillsDir, { recursive: true });
|
|
444670
445017
|
if (existsSync46(linkPath)) {
|
|
444671
|
-
const
|
|
444672
|
-
if (
|
|
445018
|
+
const stat14 = lstatSync3(linkPath);
|
|
445019
|
+
if (stat14.isSymbolicLink()) {
|
|
444673
445020
|
if (process.platform === "win32") {
|
|
444674
445021
|
rmdirSync(linkPath);
|
|
444675
445022
|
} else {
|
|
@@ -444708,7 +445055,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
444708
445055
|
}
|
|
444709
445056
|
if (parsed.type === "skill_disable") {
|
|
444710
445057
|
try {
|
|
444711
|
-
const linkPath =
|
|
445058
|
+
const linkPath = join50(globalSkillsDir, parsed.name);
|
|
444712
445059
|
if (!existsSync46(linkPath)) {
|
|
444713
445060
|
safeSocketSend(socket, {
|
|
444714
445061
|
type: "skill_disable_response",
|
|
@@ -444718,8 +445065,8 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
|
|
|
444718
445065
|
}, "listener_skill_send_failed", "listener_skill_command");
|
|
444719
445066
|
return true;
|
|
444720
445067
|
}
|
|
444721
|
-
const
|
|
444722
|
-
if (!
|
|
445068
|
+
const stat14 = lstatSync3(linkPath);
|
|
445069
|
+
if (!stat14.isSymbolicLink()) {
|
|
444723
445070
|
safeSocketSend(socket, {
|
|
444724
445071
|
type: "skill_disable_response",
|
|
444725
445072
|
request_id: parsed.request_id,
|
|
@@ -449652,7 +449999,7 @@ var init_listen_client = __esm(async () => {
|
|
|
449652
449999
|
|
|
449653
450000
|
// src/backend/local/transcript-search.ts
|
|
449654
450001
|
import { existsSync as existsSync49, readdirSync as readdirSync18, readFileSync as readFileSync33, statSync as statSync18 } from "node:fs";
|
|
449655
|
-
import { join as
|
|
450002
|
+
import { join as join53 } from "node:path";
|
|
449656
450003
|
function readJsonFile3(path37) {
|
|
449657
450004
|
if (!existsSync49(path37))
|
|
449658
450005
|
return;
|
|
@@ -449873,11 +450220,11 @@ function collectConversationMessages(input) {
|
|
|
449873
450220
|
return [];
|
|
449874
450221
|
if (input.conversationId && conversation.id !== input.conversationId)
|
|
449875
450222
|
return [];
|
|
449876
|
-
const messagesPath =
|
|
450223
|
+
const messagesPath = join53(conversationDir, "messages.jsonl");
|
|
449877
450224
|
const rows = readJsonlFile2(messagesPath);
|
|
449878
450225
|
if (rows.length === 0)
|
|
449879
450226
|
return [];
|
|
449880
|
-
const manifest2 = readJsonFile3(
|
|
450227
|
+
const manifest2 = readJsonFile3(join53(conversationDir, "manifest.json"));
|
|
449881
450228
|
const format5 = transcriptFormat(manifest2, rows);
|
|
449882
450229
|
if (!format5)
|
|
449883
450230
|
return [];
|
|
@@ -449898,11 +450245,11 @@ function collectConversationMessages(input) {
|
|
|
449898
450245
|
});
|
|
449899
450246
|
}
|
|
449900
450247
|
function conversationDirectories(storageDir) {
|
|
449901
|
-
const conversationsDir =
|
|
450248
|
+
const conversationsDir = join53(storageDir, "conversations");
|
|
449902
450249
|
if (!existsSync49(conversationsDir))
|
|
449903
450250
|
return [];
|
|
449904
450251
|
try {
|
|
449905
|
-
return readdirSync18(conversationsDir).map((entry) =>
|
|
450252
|
+
return readdirSync18(conversationsDir).map((entry) => join53(conversationsDir, entry)).filter((entryPath) => statSync18(entryPath).isDirectory());
|
|
449906
450253
|
} catch {
|
|
449907
450254
|
return [];
|
|
449908
450255
|
}
|
|
@@ -449926,7 +450273,7 @@ function searchLocalTranscriptMessages(storageDir, body3) {
|
|
|
449926
450273
|
const endDate = typeof body3.end_date === "string" ? body3.end_date : undefined;
|
|
449927
450274
|
const includeHidden = body3.include_hidden === true;
|
|
449928
450275
|
const records = conversationDirectories(storageDir).flatMap((conversationDir) => {
|
|
449929
|
-
const conversation = conversationSearchRecord(readJsonFile3(
|
|
450276
|
+
const conversation = conversationSearchRecord(readJsonFile3(join53(conversationDir, "conversation.json")));
|
|
449930
450277
|
if (!conversation)
|
|
449931
450278
|
return [];
|
|
449932
450279
|
if (conversation.hidden && !includeHidden)
|
|
@@ -451805,7 +452152,7 @@ import {
|
|
|
451805
452152
|
unlinkSync as unlinkSync8
|
|
451806
452153
|
} from "node:fs";
|
|
451807
452154
|
import { homedir as homedir32 } from "node:os";
|
|
451808
|
-
import { join as
|
|
452155
|
+
import { join as join57 } from "node:path";
|
|
451809
452156
|
import { format as format5 } from "node:util";
|
|
451810
452157
|
function isDebugEnabled2() {
|
|
451811
452158
|
const lettaDebug = process.env.LETTA_DEBUG;
|
|
@@ -451836,8 +452183,8 @@ class DebugLogFile2 {
|
|
|
451836
452183
|
const telem = process.env.LETTA_CODE_TELEM;
|
|
451837
452184
|
if (telem === "0" || telem === "false")
|
|
451838
452185
|
return;
|
|
451839
|
-
this.agentDir =
|
|
451840
|
-
this.logPath =
|
|
452186
|
+
this.agentDir = join57(DEBUG_LOG_DIR2, agentId);
|
|
452187
|
+
this.logPath = join57(this.agentDir, `${sessionId}.log`);
|
|
451841
452188
|
this.dirCreated = false;
|
|
451842
452189
|
this.pruneOldSessions();
|
|
451843
452190
|
}
|
|
@@ -451885,7 +452232,7 @@ class DebugLogFile2 {
|
|
|
451885
452232
|
const toDelete = files.slice(0, files.length - MAX_SESSION_FILES3 + 1);
|
|
451886
452233
|
for (const file3 of toDelete) {
|
|
451887
452234
|
try {
|
|
451888
|
-
unlinkSync8(
|
|
452235
|
+
unlinkSync8(join57(this.agentDir, file3));
|
|
451889
452236
|
} catch {}
|
|
451890
452237
|
}
|
|
451891
452238
|
}
|
|
@@ -451910,7 +452257,7 @@ function debugWarn2(prefix, message, ...args) {
|
|
|
451910
452257
|
}
|
|
451911
452258
|
var DEBUG_LOG_DIR2, MAX_SESSION_FILES3 = 5, DEFAULT_TAIL_LINES2 = 50, debugLogFile2;
|
|
451912
452259
|
var init_debug2 = __esm(() => {
|
|
451913
|
-
DEBUG_LOG_DIR2 =
|
|
452260
|
+
DEBUG_LOG_DIR2 = join57(homedir32(), ".letta", "logs", "debug");
|
|
451914
452261
|
debugLogFile2 = new DebugLogFile2;
|
|
451915
452262
|
});
|
|
451916
452263
|
|
|
@@ -451945,15 +452292,15 @@ __export(exports_skills3, {
|
|
|
451945
452292
|
GLOBAL_SKILLS_DIR: () => GLOBAL_SKILLS_DIR2
|
|
451946
452293
|
});
|
|
451947
452294
|
import { existsSync as existsSync54 } from "node:fs";
|
|
451948
|
-
import { readdir as
|
|
451949
|
-
import { dirname as
|
|
452295
|
+
import { readdir as readdir14, readFile as readFile19, realpath as realpath5, stat as stat14 } from "node:fs/promises";
|
|
452296
|
+
import { dirname as dirname28, join as join58 } from "node:path";
|
|
451950
452297
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
451951
452298
|
function getBundledSkillsPath2() {
|
|
451952
|
-
const thisDir =
|
|
452299
|
+
const thisDir = dirname28(fileURLToPath8(import.meta.url));
|
|
451953
452300
|
if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
|
|
451954
|
-
return
|
|
452301
|
+
return join58(thisDir, "../skills/builtin");
|
|
451955
452302
|
}
|
|
451956
|
-
return
|
|
452303
|
+
return join58(thisDir, "skills");
|
|
451957
452304
|
}
|
|
451958
452305
|
function compareSkills2(a2, b3) {
|
|
451959
452306
|
return a2.id.localeCompare(b3.id) || a2.source.localeCompare(b3.source) || a2.path.localeCompare(b3.path);
|
|
@@ -452000,7 +452347,7 @@ function isSkillAvailableForAgent2(skill2, agentId) {
|
|
|
452000
452347
|
return true;
|
|
452001
452348
|
}
|
|
452002
452349
|
function getAgentSkillsDir2(agentId) {
|
|
452003
|
-
return
|
|
452350
|
+
return join58(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "memory/skills");
|
|
452004
452351
|
}
|
|
452005
452352
|
async function getBundledSkills2() {
|
|
452006
452353
|
const bundledPath = getBundledSkillsPath2();
|
|
@@ -452023,7 +452370,7 @@ async function discoverSkillsFromDir2(skillsPath, source2) {
|
|
|
452023
452370
|
}
|
|
452024
452371
|
return { skills, errors: errors7 };
|
|
452025
452372
|
}
|
|
452026
|
-
async function discoverSkills2(projectSkillsPath =
|
|
452373
|
+
async function discoverSkills2(projectSkillsPath = join58(process.cwd(), SKILLS_DIR2), agentId, options3) {
|
|
452027
452374
|
const allErrors = [];
|
|
452028
452375
|
const skillsById = new Map;
|
|
452029
452376
|
const sourceSet = new Set(options3?.sources ?? ALL_SKILL_SOURCES);
|
|
@@ -452076,14 +452423,14 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors7, source2,
|
|
|
452076
452423
|
return;
|
|
452077
452424
|
}
|
|
452078
452425
|
try {
|
|
452079
|
-
const entries = await
|
|
452426
|
+
const entries = await readdir14(currentPath, { withFileTypes: true });
|
|
452080
452427
|
for (const entry of entries) {
|
|
452081
|
-
const fullPath =
|
|
452428
|
+
const fullPath = join58(currentPath, entry.name);
|
|
452082
452429
|
try {
|
|
452083
452430
|
let isDirectory = entry.isDirectory();
|
|
452084
452431
|
let isFile = entry.isFile();
|
|
452085
452432
|
if (entry.isSymbolicLink()) {
|
|
452086
|
-
const entryStat = await
|
|
452433
|
+
const entryStat = await stat14(fullPath);
|
|
452087
452434
|
isDirectory = entryStat.isDirectory();
|
|
452088
452435
|
isFile = entryStat.isFile();
|
|
452089
452436
|
}
|
|
@@ -452117,7 +452464,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors7, source2,
|
|
|
452117
452464
|
}
|
|
452118
452465
|
}
|
|
452119
452466
|
async function parseSkillFile2(filePath, rootPath, source2) {
|
|
452120
|
-
const content = await
|
|
452467
|
+
const content = await readFile19(filePath, "utf-8");
|
|
452121
452468
|
const { frontmatter, body: body3 } = parseFrontmatter(content);
|
|
452122
452469
|
const normalizedRoot = rootPath.endsWith("/") ? rootPath.slice(0, -1) : rootPath;
|
|
452123
452470
|
const relativePath = filePath.slice(normalizedRoot.length + 1);
|
|
@@ -452169,17 +452516,17 @@ var LOCAL_AGENT_EXCLUDED_BUNDLED_SKILLS2, PROJECT_SKILLS_DIR2, SKILLS_DIR2 = ".s
|
|
|
452169
452516
|
var init_skills4 = __esm(() => {
|
|
452170
452517
|
init_skill_sources();
|
|
452171
452518
|
LOCAL_AGENT_EXCLUDED_BUNDLED_SKILLS2 = new Set(["image-generation"]);
|
|
452172
|
-
PROJECT_SKILLS_DIR2 =
|
|
452173
|
-
GLOBAL_SKILLS_DIR2 =
|
|
452519
|
+
PROJECT_SKILLS_DIR2 = join58(".agents", "skills");
|
|
452520
|
+
GLOBAL_SKILLS_DIR2 = join58(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
|
|
452174
452521
|
});
|
|
452175
452522
|
|
|
452176
452523
|
// src/utils/fs.ts
|
|
452177
452524
|
var exports_fs = {};
|
|
452178
452525
|
__export(exports_fs, {
|
|
452179
452526
|
writeJsonFile: () => writeJsonFile2,
|
|
452180
|
-
writeFile: () =>
|
|
452527
|
+
writeFile: () => writeFile16,
|
|
452181
452528
|
readJsonFile: () => readJsonFile4,
|
|
452182
|
-
readFile: () =>
|
|
452529
|
+
readFile: () => readFile20,
|
|
452183
452530
|
mkdir: () => mkdir13,
|
|
452184
452531
|
exists: () => exists2
|
|
452185
452532
|
});
|
|
@@ -452189,12 +452536,12 @@ import {
|
|
|
452189
452536
|
writeFileSync as fsWriteFileSync2,
|
|
452190
452537
|
mkdirSync as mkdirSync37
|
|
452191
452538
|
} from "node:fs";
|
|
452192
|
-
import { dirname as
|
|
452193
|
-
async function
|
|
452539
|
+
import { dirname as dirname29 } from "node:path";
|
|
452540
|
+
async function readFile20(path39) {
|
|
452194
452541
|
return fsReadFileSync2(path39, { encoding: "utf-8" });
|
|
452195
452542
|
}
|
|
452196
|
-
async function
|
|
452197
|
-
const dir =
|
|
452543
|
+
async function writeFile16(path39, content) {
|
|
452544
|
+
const dir = dirname29(path39);
|
|
452198
452545
|
if (!existsSync55(dir)) {
|
|
452199
452546
|
mkdirSync37(dir, { recursive: true });
|
|
452200
452547
|
}
|
|
@@ -452207,14 +452554,14 @@ async function mkdir13(path39, options3) {
|
|
|
452207
452554
|
mkdirSync37(path39, options3);
|
|
452208
452555
|
}
|
|
452209
452556
|
async function readJsonFile4(path39) {
|
|
452210
|
-
const text2 = await
|
|
452557
|
+
const text2 = await readFile20(path39);
|
|
452211
452558
|
return JSON.parse(text2);
|
|
452212
452559
|
}
|
|
452213
452560
|
async function writeJsonFile2(path39, data, options3) {
|
|
452214
452561
|
const indent = options3?.indent ?? 2;
|
|
452215
452562
|
const content = `${JSON.stringify(data, null, indent)}
|
|
452216
452563
|
`;
|
|
452217
|
-
await
|
|
452564
|
+
await writeFile16(path39, content);
|
|
452218
452565
|
}
|
|
452219
452566
|
var init_fs2 = () => {};
|
|
452220
452567
|
|
|
@@ -452413,8 +452760,8 @@ import {
|
|
|
452413
452760
|
execFile as execFile16
|
|
452414
452761
|
} from "node:child_process";
|
|
452415
452762
|
import { accessSync as accessSync2, constants as constants4, realpathSync as realpathSync6 } from "node:fs";
|
|
452416
|
-
import { readdir as
|
|
452417
|
-
import { dirname as
|
|
452763
|
+
import { readdir as readdir15, rm as rm5 } from "node:fs/promises";
|
|
452764
|
+
import { dirname as dirname30, join as join59 } from "node:path";
|
|
452418
452765
|
import { promisify as promisify14 } from "node:util";
|
|
452419
452766
|
function debugLog4(...args) {
|
|
452420
452767
|
if (DEBUG2) {
|
|
@@ -452489,7 +452836,7 @@ function getResolvedEntrypoint2() {
|
|
|
452489
452836
|
}
|
|
452490
452837
|
}
|
|
452491
452838
|
function findInstalledPackagePath2(resolvedPath) {
|
|
452492
|
-
const marker = `${
|
|
452839
|
+
const marker = `${join59("node_modules", "@letta-ai", "letta-code")}`;
|
|
452493
452840
|
const index = resolvedPath.lastIndexOf(marker);
|
|
452494
452841
|
if (index === -1) {
|
|
452495
452842
|
return null;
|
|
@@ -452528,7 +452875,7 @@ function getSelfUpdateStatus2() {
|
|
|
452528
452875
|
manual_command: manualCommand
|
|
452529
452876
|
};
|
|
452530
452877
|
}
|
|
452531
|
-
const packageParentPath =
|
|
452878
|
+
const packageParentPath = dirname30(installPath);
|
|
452532
452879
|
const writable = canWritePath2(installPath) && canWritePath2(packageParentPath);
|
|
452533
452880
|
return {
|
|
452534
452881
|
supported: true,
|
|
@@ -452638,12 +452985,12 @@ async function getNpmGlobalPath2() {
|
|
|
452638
452985
|
}
|
|
452639
452986
|
}
|
|
452640
452987
|
async function cleanupOrphanedDirs2(globalPath) {
|
|
452641
|
-
const lettaAiDir =
|
|
452988
|
+
const lettaAiDir = join59(globalPath, "lib/node_modules/@letta-ai");
|
|
452642
452989
|
try {
|
|
452643
|
-
const entries = await
|
|
452990
|
+
const entries = await readdir15(lettaAiDir);
|
|
452644
452991
|
for (const entry of entries) {
|
|
452645
452992
|
if (entry.startsWith(".letta-code-")) {
|
|
452646
|
-
const orphanPath =
|
|
452993
|
+
const orphanPath = join59(lettaAiDir, entry);
|
|
452647
452994
|
debugLog4("Cleaning orphaned temp directory:", orphanPath);
|
|
452648
452995
|
await rm5(orphanPath, { recursive: true, force: true });
|
|
452649
452996
|
}
|
|
@@ -453175,7 +453522,7 @@ __export(exports_bootstrap_tools, {
|
|
|
453175
453522
|
});
|
|
453176
453523
|
import { existsSync as existsSync57, mkdirSync as mkdirSync39, writeFileSync as writeFileSync28 } from "node:fs";
|
|
453177
453524
|
import { homedir as homedir34 } from "node:os";
|
|
453178
|
-
import { join as
|
|
453525
|
+
import { join as join61 } from "node:path";
|
|
453179
453526
|
async function bootstrapBaseToolsIfNeeded() {
|
|
453180
453527
|
if (existsSync57(MARKER_PATH))
|
|
453181
453528
|
return;
|
|
@@ -453183,7 +453530,7 @@ async function bootstrapBaseToolsIfNeeded() {
|
|
|
453183
453530
|
try {
|
|
453184
453531
|
const success2 = await addBaseToolsToServer();
|
|
453185
453532
|
if (success2) {
|
|
453186
|
-
mkdirSync39(
|
|
453533
|
+
mkdirSync39(join61(homedir34(), ".letta"), { recursive: true });
|
|
453187
453534
|
writeFileSync28(MARKER_PATH, new Date().toISOString(), "utf-8");
|
|
453188
453535
|
}
|
|
453189
453536
|
} catch (err) {
|
|
@@ -453194,7 +453541,7 @@ var MARKER_PATH;
|
|
|
453194
453541
|
var init_bootstrap_tools = __esm(() => {
|
|
453195
453542
|
init_debug();
|
|
453196
453543
|
init_create6();
|
|
453197
|
-
MARKER_PATH =
|
|
453544
|
+
MARKER_PATH = join61(homedir34(), ".letta", ".bootstrapped");
|
|
453198
453545
|
});
|
|
453199
453546
|
|
|
453200
453547
|
// src/tools/filter.ts
|
|
@@ -453637,7 +453984,7 @@ function validateRegistryHandleOrThrow2(handle2) {
|
|
|
453637
453984
|
}
|
|
453638
453985
|
|
|
453639
453986
|
// src/headless-mod-adapter.ts
|
|
453640
|
-
import { join as
|
|
453987
|
+
import { join as join62 } from "node:path";
|
|
453641
453988
|
function isHeadlessMemfsEnabled(agentId) {
|
|
453642
453989
|
try {
|
|
453643
453990
|
return settingsManager.isMemfsEnabled(agentId);
|
|
@@ -453708,7 +454055,7 @@ function createHeadlessModContext(options3) {
|
|
|
453708
454055
|
};
|
|
453709
454056
|
}
|
|
453710
454057
|
function createHeadlessModAdapter(options3) {
|
|
453711
|
-
const agentModsDirectory = isHeadlessMemfsEnabled(options3.agent.id) ?
|
|
454058
|
+
const agentModsDirectory = isHeadlessMemfsEnabled(options3.agent.id) ? join62(getScopedMemoryFilesystemRoot(options3.agent.id), "mods") : undefined;
|
|
453712
454059
|
return createModAdapter({
|
|
453713
454060
|
...agentModsDirectory ? { agentModsDirectory } : {},
|
|
453714
454061
|
...options3.cacheDirectory ? { cacheDirectory: options3.cacheDirectory } : {},
|
|
@@ -453793,7 +454140,7 @@ async function writeWireMessageAsync(msg) {
|
|
|
453793
454140
|
|
|
453794
454141
|
// src/skills/builtin/creating-skills/scripts/validate-skill.ts
|
|
453795
454142
|
import { existsSync as existsSync58, readFileSync as readFileSync38 } from "node:fs";
|
|
453796
|
-
import { basename as
|
|
454143
|
+
import { basename as basename25, join as join63, resolve as resolve34 } from "node:path";
|
|
453797
454144
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
453798
454145
|
function parseQuotedScalar(value) {
|
|
453799
454146
|
if (value.startsWith('"')) {
|
|
@@ -453890,7 +454237,7 @@ function parseFrontmatter2(source2) {
|
|
|
453890
454237
|
return parseFrontmatterFallback(source2);
|
|
453891
454238
|
}
|
|
453892
454239
|
function validateSkill(skillPath) {
|
|
453893
|
-
const skillMdPath =
|
|
454240
|
+
const skillMdPath = join63(skillPath, "SKILL.md");
|
|
453894
454241
|
if (!existsSync58(skillMdPath)) {
|
|
453895
454242
|
return { valid: false, message: "SKILL.md not found" };
|
|
453896
454243
|
}
|
|
@@ -453953,7 +454300,7 @@ function validateSkill(skillPath) {
|
|
|
453953
454300
|
message: `Name is too long (${trimmedName.length} characters). Maximum is ${MAX_SKILL_NAME_LENGTH} characters.`
|
|
453954
454301
|
};
|
|
453955
454302
|
}
|
|
453956
|
-
const dirName =
|
|
454303
|
+
const dirName = basename25(skillPath);
|
|
453957
454304
|
if (trimmedName !== dirName) {
|
|
453958
454305
|
warnings.push(`Name '${trimmedName}' doesn't match directory name '${dirName}'. For portability, these should match.`);
|
|
453959
454306
|
}
|
|
@@ -454057,8 +454404,8 @@ __export(exports_import, {
|
|
|
454057
454404
|
extractSkillsFromAf: () => extractSkillsFromAf
|
|
454058
454405
|
});
|
|
454059
454406
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
454060
|
-
import { access as access2, chmod, mkdir as mkdir14, readFile as
|
|
454061
|
-
import { dirname as
|
|
454407
|
+
import { access as access2, chmod, mkdir as mkdir14, readFile as readFile21, writeFile as writeFile17 } from "node:fs/promises";
|
|
454408
|
+
import { dirname as dirname31, isAbsolute as isAbsolute24, relative as relative12, resolve as resolve35, sep as sep6, win32 as win325 } from "node:path";
|
|
454062
454409
|
function validateImportedSkillName(name) {
|
|
454063
454410
|
const trimmedName = name.trim();
|
|
454064
454411
|
if (trimmedName !== name || trimmedName.length === 0 || trimmedName.length > MAX_SKILL_NAME_LENGTH || trimmedName === "." || trimmedName === ".." || !IMPORTED_SKILL_NAME_PATTERN.test(trimmedName)) {
|
|
@@ -454069,7 +454416,7 @@ function validateImportedSkillName(name) {
|
|
|
454069
454416
|
function assertPathInside(parent, child) {
|
|
454070
454417
|
const parentPath = resolve35(parent);
|
|
454071
454418
|
const childPath = resolve35(child);
|
|
454072
|
-
const relativePath =
|
|
454419
|
+
const relativePath = relative12(parentPath, childPath);
|
|
454073
454420
|
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep6}`) || isAbsolute24(relativePath)) {
|
|
454074
454421
|
throw new Error(`Imported skill file path escapes skill directory: ${child}`);
|
|
454075
454422
|
}
|
|
@@ -454158,7 +454505,7 @@ async function importAgentFromFile(options3) {
|
|
|
454158
454505
|
}
|
|
454159
454506
|
async function extractSkillsFromAf(afPath, destDir) {
|
|
454160
454507
|
const extracted = [];
|
|
454161
|
-
const content = await
|
|
454508
|
+
const content = await readFile21(afPath, "utf-8");
|
|
454162
454509
|
const afData = JSON.parse(content);
|
|
454163
454510
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
454164
454511
|
return [];
|
|
@@ -454186,8 +454533,8 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
454186
454533
|
}
|
|
454187
454534
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
454188
454535
|
const fullPath = resolveImportedSkillFilePath(skillDir, filePath);
|
|
454189
|
-
await mkdir14(
|
|
454190
|
-
await
|
|
454536
|
+
await mkdir14(dirname31(fullPath), { recursive: true });
|
|
454537
|
+
await writeFile17(fullPath, content, "utf-8");
|
|
454191
454538
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
454192
454539
|
if (isScript) {
|
|
454193
454540
|
try {
|
|
@@ -454239,8 +454586,8 @@ function parseRegistryHandle(handle2) {
|
|
|
454239
454586
|
}
|
|
454240
454587
|
async function importAgentFromRegistry(options3) {
|
|
454241
454588
|
const { tmpdir: tmpdir10 } = await import("node:os");
|
|
454242
|
-
const { join:
|
|
454243
|
-
const { writeFile:
|
|
454589
|
+
const { join: join64 } = await import("node:path");
|
|
454590
|
+
const { writeFile: writeFile18, unlink: unlink5 } = await import("node:fs/promises");
|
|
454244
454591
|
const { author, name } = parseRegistryHandle(options3.handle);
|
|
454245
454592
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
|
|
454246
454593
|
const response = await fetch(rawUrl);
|
|
@@ -454251,8 +454598,8 @@ async function importAgentFromRegistry(options3) {
|
|
|
454251
454598
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
454252
454599
|
}
|
|
454253
454600
|
const afContent = await response.text();
|
|
454254
|
-
const tempPath =
|
|
454255
|
-
await
|
|
454601
|
+
const tempPath = join64(tmpdir10(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
454602
|
+
await writeFile18(tempPath, afContent, "utf-8");
|
|
454256
454603
|
try {
|
|
454257
454604
|
const result = await importAgentFromFile({
|
|
454258
454605
|
filePath: tempPath,
|
|
@@ -454283,6 +454630,7 @@ var exports_defaults = {};
|
|
|
454283
454630
|
__export(exports_defaults, {
|
|
454284
454631
|
selectDefaultAgentModel: () => selectDefaultAgentModel,
|
|
454285
454632
|
ensureDefaultAgents: () => ensureDefaultAgents,
|
|
454633
|
+
TUTOR_TAG: () => TUTOR_TAG,
|
|
454286
454634
|
MEMO_TAG: () => MEMO_TAG,
|
|
454287
454635
|
DEFAULT_AGENT_CONFIGS: () => DEFAULT_AGENT_CONFIGS
|
|
454288
454636
|
});
|
|
@@ -454350,29 +454698,39 @@ async function ensureDefaultAgents(backend4, options3) {
|
|
|
454350
454698
|
if (!settingsManager.shouldCreateDefaultAgents()) {
|
|
454351
454699
|
return null;
|
|
454352
454700
|
}
|
|
454701
|
+
const personality = options3?.personality ?? "memo";
|
|
454353
454702
|
try {
|
|
454354
454703
|
const { isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
454355
454704
|
const willAutoEnableMemfs = backend4.capabilities.remoteMemfs && await isLettaCloud2();
|
|
454356
454705
|
const memoryPromptMode = backend4.capabilities.localMemfs ? "local-memfs" : willAutoEnableMemfs ? "memfs" : undefined;
|
|
454357
|
-
const
|
|
454706
|
+
const model = await resolveDefaultAgentModel(backend4, options3?.preferredModel);
|
|
454707
|
+
const createOptions = personality === "tutorial" ? {
|
|
454708
|
+
...await buildCreateAgentOptionsForPersonality2({
|
|
454709
|
+
personalityId: "tutorial",
|
|
454710
|
+
model
|
|
454711
|
+
}),
|
|
454712
|
+
memoryPromptMode
|
|
454713
|
+
} : {
|
|
454358
454714
|
...DEFAULT_AGENT_CONFIGS.memo,
|
|
454359
|
-
model
|
|
454715
|
+
model,
|
|
454360
454716
|
memoryPromptMode
|
|
454361
|
-
}
|
|
454362
|
-
|
|
454717
|
+
};
|
|
454718
|
+
const { agent: agent2 } = await createAgent(createOptions);
|
|
454719
|
+
await addTagToAgent(backend4, agent2.id, personality === "tutorial" ? TUTOR_TAG : MEMO_TAG);
|
|
454363
454720
|
settingsManager.pinAgent(agent2.id);
|
|
454364
454721
|
return agent2;
|
|
454365
454722
|
} catch (err) {
|
|
454366
454723
|
throw new Error(`Failed to create default agents: ${err instanceof Error ? err.message : String(err)}`);
|
|
454367
454724
|
}
|
|
454368
454725
|
}
|
|
454369
|
-
var MEMO_TAG = "default:memo", MEMO_PERSONA, MEMO_HUMAN, MEMO_DESCRIPTION = "The default Letta Code agent with persistent memory", DEFAULT_AGENT_CONFIGS;
|
|
454726
|
+
var MEMO_TAG = "default:memo", TUTOR_TAG = "default:tutorial", MEMO_PERSONA, MEMO_HUMAN, MEMO_DESCRIPTION = "The default Letta Code agent with persistent memory", DEFAULT_AGENT_CONFIGS;
|
|
454370
454727
|
var init_defaults = __esm(() => {
|
|
454371
454728
|
init_client2();
|
|
454372
454729
|
init_settings_manager();
|
|
454373
454730
|
init_create6();
|
|
454374
454731
|
init_memory5();
|
|
454375
454732
|
init_model();
|
|
454733
|
+
init_personality();
|
|
454376
454734
|
init_prompt_assets();
|
|
454377
454735
|
MEMO_PERSONA = parseMdxFrontmatter(MEMORY_PROMPTS["persona_memo.mdx"] ?? "").body;
|
|
454378
454736
|
MEMO_HUMAN = parseMdxFrontmatter(MEMORY_PROMPTS["human_memo.mdx"] ?? "").body;
|
|
@@ -455269,7 +455627,7 @@ Current session AGENT_ID=${process.env.AGENT_ID}; --backend local switches to a
|
|
|
455269
455627
|
await settingsManager.loadLocalProjectSettings();
|
|
455270
455628
|
settingsManager.persistSession(agent2.id, conversationId);
|
|
455271
455629
|
}
|
|
455272
|
-
setAgentContext(agent2.id, skillsDirectory, resolvedSkillSources);
|
|
455630
|
+
setAgentContext(agent2.id, skillsDirectory, resolvedSkillSources, agent2.name ?? null);
|
|
455273
455631
|
const outputFormat = values2["output-format"] || "text";
|
|
455274
455632
|
const includePartialMessages = Boolean(values2["include-partial-messages"]);
|
|
455275
455633
|
if (!["text", "json", "stream-json"].includes(outputFormat)) {
|
|
@@ -457863,7 +458221,7 @@ var BYTES_PER_TOKEN = 4;
|
|
|
457863
458221
|
|
|
457864
458222
|
// src/cli/helpers/window-title-config.ts
|
|
457865
458223
|
import { homedir as homedir36 } from "node:os";
|
|
457866
|
-
import { basename as
|
|
458224
|
+
import { basename as basename26, resolve as resolve36 } from "node:path";
|
|
457867
458225
|
function isWindowTitleField(value) {
|
|
457868
458226
|
return WINDOW_TITLE_FIELDS.includes(value);
|
|
457869
458227
|
}
|
|
@@ -458022,7 +458380,7 @@ function terminalTitleProjectName(data) {
|
|
|
458022
458380
|
if (!directory)
|
|
458023
458381
|
return null;
|
|
458024
458382
|
const resolved = resolve36(directory);
|
|
458025
|
-
const name =
|
|
458383
|
+
const name = basename26(resolved) || formatDirectoryDisplay(resolved) || resolved;
|
|
458026
458384
|
return truncateTerminalTitlePart(name, 24);
|
|
458027
458385
|
}
|
|
458028
458386
|
function titleDirectory(data) {
|
|
@@ -459297,7 +459655,7 @@ import {
|
|
|
459297
459655
|
writeFileSync as writeFileSync30
|
|
459298
459656
|
} from "node:fs";
|
|
459299
459657
|
import { homedir as homedir37, platform as platform9 } from "node:os";
|
|
459300
|
-
import { dirname as
|
|
459658
|
+
import { dirname as dirname32, join as join65 } from "node:path";
|
|
459301
459659
|
function detectTerminalType() {
|
|
459302
459660
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
459303
459661
|
return "cursor";
|
|
@@ -459329,16 +459687,16 @@ function getKeybindingsPath(terminal) {
|
|
|
459329
459687
|
}[terminal];
|
|
459330
459688
|
const os9 = platform9();
|
|
459331
459689
|
if (os9 === "darwin") {
|
|
459332
|
-
return
|
|
459690
|
+
return join65(homedir37(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
459333
459691
|
}
|
|
459334
459692
|
if (os9 === "win32") {
|
|
459335
459693
|
const appData = process.env.APPDATA;
|
|
459336
459694
|
if (!appData)
|
|
459337
459695
|
return null;
|
|
459338
|
-
return
|
|
459696
|
+
return join65(appData, appName, "User", "keybindings.json");
|
|
459339
459697
|
}
|
|
459340
459698
|
if (os9 === "linux") {
|
|
459341
|
-
return
|
|
459699
|
+
return join65(homedir37(), ".config", appName, "User", "keybindings.json");
|
|
459342
459700
|
}
|
|
459343
459701
|
return null;
|
|
459344
459702
|
}
|
|
@@ -459388,7 +459746,7 @@ function installKeybinding(keybindingsPath) {
|
|
|
459388
459746
|
if (keybindingExists(keybindingsPath)) {
|
|
459389
459747
|
return { success: true, alreadyExists: true };
|
|
459390
459748
|
}
|
|
459391
|
-
const parentDir =
|
|
459749
|
+
const parentDir = dirname32(keybindingsPath);
|
|
459392
459750
|
if (!existsSync60(parentDir)) {
|
|
459393
459751
|
mkdirSync41(parentDir, { recursive: true });
|
|
459394
459752
|
}
|
|
@@ -459491,14 +459849,14 @@ function getWezTermConfigPath() {
|
|
|
459491
459849
|
}
|
|
459492
459850
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
459493
459851
|
if (xdgConfig) {
|
|
459494
|
-
const xdgPath =
|
|
459852
|
+
const xdgPath = join65(xdgConfig, "wezterm", "wezterm.lua");
|
|
459495
459853
|
if (existsSync60(xdgPath))
|
|
459496
459854
|
return xdgPath;
|
|
459497
459855
|
}
|
|
459498
|
-
const configPath =
|
|
459856
|
+
const configPath = join65(homedir37(), ".config", "wezterm", "wezterm.lua");
|
|
459499
459857
|
if (existsSync60(configPath))
|
|
459500
459858
|
return configPath;
|
|
459501
|
-
return
|
|
459859
|
+
return join65(homedir37(), ".wezterm.lua");
|
|
459502
459860
|
}
|
|
459503
459861
|
function stripLuaCommentsFromLine(line, blockCommentEnd) {
|
|
459504
459862
|
let code2 = "";
|
|
@@ -459624,7 +459982,7 @@ function installWezTermDeleteFix() {
|
|
|
459624
459982
|
content = readFileSync40(configPath, { encoding: "utf-8" });
|
|
459625
459983
|
}
|
|
459626
459984
|
content = injectWezTermDeleteFix(content);
|
|
459627
|
-
const parentDir =
|
|
459985
|
+
const parentDir = dirname32(configPath);
|
|
459628
459986
|
if (!existsSync60(parentDir)) {
|
|
459629
459987
|
mkdirSync41(parentDir, { recursive: true });
|
|
459630
459988
|
}
|
|
@@ -459677,9 +460035,9 @@ __export(exports_settings2, {
|
|
|
459677
460035
|
getSetting: () => getSetting
|
|
459678
460036
|
});
|
|
459679
460037
|
import { homedir as homedir38 } from "node:os";
|
|
459680
|
-
import { join as
|
|
460038
|
+
import { join as join66 } from "node:path";
|
|
459681
460039
|
function getSettingsPath() {
|
|
459682
|
-
return
|
|
460040
|
+
return join66(homedir38(), ".letta", "settings.json");
|
|
459683
460041
|
}
|
|
459684
460042
|
async function loadSettings() {
|
|
459685
460043
|
const settingsPath = getSettingsPath();
|
|
@@ -459716,7 +460074,7 @@ async function getSetting(key2) {
|
|
|
459716
460074
|
return settings3[key2];
|
|
459717
460075
|
}
|
|
459718
460076
|
function getProjectSettingsPath() {
|
|
459719
|
-
return
|
|
460077
|
+
return join66(process.cwd(), ".letta", "settings.local.json");
|
|
459720
460078
|
}
|
|
459721
460079
|
async function loadProjectSettings() {
|
|
459722
460080
|
const settingsPath = getProjectSettingsPath();
|
|
@@ -459734,7 +460092,7 @@ async function loadProjectSettings() {
|
|
|
459734
460092
|
}
|
|
459735
460093
|
async function saveProjectSettings(settings3) {
|
|
459736
460094
|
const settingsPath = getProjectSettingsPath();
|
|
459737
|
-
const dirPath =
|
|
460095
|
+
const dirPath = join66(process.cwd(), ".letta");
|
|
459738
460096
|
try {
|
|
459739
460097
|
if (!exists(dirPath)) {
|
|
459740
460098
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -460765,10 +461123,10 @@ var init_InlineBashApproval = __esm(async () => {
|
|
|
460765
461123
|
});
|
|
460766
461124
|
|
|
460767
461125
|
// src/cli/components/DiffRenderer.tsx
|
|
460768
|
-
import { relative as
|
|
461126
|
+
import { relative as relative13 } from "node:path";
|
|
460769
461127
|
function formatDisplayPath4(filePath) {
|
|
460770
461128
|
const cwd2 = process.cwd();
|
|
460771
|
-
const relativePath =
|
|
461129
|
+
const relativePath = relative13(cwd2, filePath);
|
|
460772
461130
|
if (relativePath.startsWith("..")) {
|
|
460773
461131
|
return filePath;
|
|
460774
461132
|
}
|
|
@@ -461127,10 +461485,10 @@ var init_DiffRenderer = __esm(async () => {
|
|
|
461127
461485
|
});
|
|
461128
461486
|
|
|
461129
461487
|
// src/cli/components/AdvancedDiffRenderer.tsx
|
|
461130
|
-
import { relative as
|
|
461488
|
+
import { relative as relative14 } from "node:path";
|
|
461131
461489
|
function formatRelativePath(filePath) {
|
|
461132
461490
|
const cwd2 = process.cwd();
|
|
461133
|
-
const relativePath =
|
|
461491
|
+
const relativePath = relative14(cwd2, filePath);
|
|
461134
461492
|
return relativePath.startsWith("..") ? relativePath : `./${relativePath}`;
|
|
461135
461493
|
}
|
|
461136
461494
|
function padLeft(n, width) {
|
|
@@ -461412,7 +461770,7 @@ function AdvancedDiffRenderer(props) {
|
|
|
461412
461770
|
}
|
|
461413
461771
|
const { hunks } = result;
|
|
461414
461772
|
const filePath = props.filePath;
|
|
461415
|
-
const
|
|
461773
|
+
const relative15 = formatRelativePath(filePath);
|
|
461416
461774
|
const lang41 = languageFromPath(filePath);
|
|
461417
461775
|
const shouldHighlight = lang41 && !exceedsAdvancedDiffHighlightLimits(hunks);
|
|
461418
461776
|
const hunkSyntaxLines = [];
|
|
@@ -461435,7 +461793,7 @@ function AdvancedDiffRenderer(props) {
|
|
|
461435
461793
|
const rows = buildAdvancedDiffRows(hunks, hunkSyntaxLines);
|
|
461436
461794
|
const maxDisplayNo = rows.reduce((m4, r5) => Math.max(m4, r5.displayNo), 1);
|
|
461437
461795
|
const gutterWidth = String(maxDisplayNo).length;
|
|
461438
|
-
const header = props.kind === "write" ? `Wrote changes to ${
|
|
461796
|
+
const header = props.kind === "write" ? `Wrote changes to ${relative15}` : `Updated ${relative15}`;
|
|
461439
461797
|
if (rows.length === 0) {
|
|
461440
461798
|
const noChangesGutter = 4;
|
|
461441
461799
|
return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Box_default, {
|
|
@@ -461486,7 +461844,7 @@ function AdvancedDiffRenderer(props) {
|
|
|
461486
461844
|
"No changes to ",
|
|
461487
461845
|
/* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text2, {
|
|
461488
461846
|
bold: true,
|
|
461489
|
-
children:
|
|
461847
|
+
children: relative15
|
|
461490
461848
|
}, undefined, false, undefined, this),
|
|
461491
461849
|
" (file content identical)"
|
|
461492
461850
|
]
|
|
@@ -461592,9 +461950,9 @@ function getHeaderText(fileEdit) {
|
|
|
461592
461950
|
} else if (operations.length === 1) {
|
|
461593
461951
|
const op = operations[0];
|
|
461594
461952
|
if (op) {
|
|
461595
|
-
const { relative:
|
|
461953
|
+
const { relative: relative16 } = __require("node:path");
|
|
461596
461954
|
const cwd3 = process.cwd();
|
|
461597
|
-
const relPath2 =
|
|
461955
|
+
const relPath2 = relative16(cwd3, op.path);
|
|
461598
461956
|
const displayPath2 = relPath2.startsWith("..") ? op.path : relPath2;
|
|
461599
461957
|
if (op.kind === "add") {
|
|
461600
461958
|
return `Write to ${displayPath2}?`;
|
|
@@ -461608,9 +461966,9 @@ function getHeaderText(fileEdit) {
|
|
|
461608
461966
|
}
|
|
461609
461967
|
return "Apply patch?";
|
|
461610
461968
|
}
|
|
461611
|
-
const { relative:
|
|
461969
|
+
const { relative: relative15 } = __require("node:path");
|
|
461612
461970
|
const cwd2 = process.cwd();
|
|
461613
|
-
const relPath =
|
|
461971
|
+
const relPath = relative15(cwd2, fileEdit.filePath);
|
|
461614
461972
|
const displayPath = relPath.startsWith("..") ? fileEdit.filePath : relPath;
|
|
461615
461973
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
461616
461974
|
const { existsSync: existsSync61 } = __require("node:fs");
|
|
@@ -461793,9 +462151,9 @@ var init_InlineFileEditApproval = __esm(async () => {
|
|
|
461793
462151
|
children: fileEdit.patchInput ? /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
|
|
461794
462152
|
flexDirection: "column",
|
|
461795
462153
|
children: parsePatchOperations2(fileEdit.patchInput).map((op, idx) => {
|
|
461796
|
-
const { relative:
|
|
462154
|
+
const { relative: relative15 } = __require("node:path");
|
|
461797
462155
|
const cwd2 = process.cwd();
|
|
461798
|
-
const relPath =
|
|
462156
|
+
const relPath = relative15(cwd2, op.path);
|
|
461799
462157
|
const displayPath = relPath.startsWith("..") ? op.path : relPath;
|
|
461800
462158
|
const diffKey = fileEdit.toolCallId ? `${fileEdit.toolCallId}:${op.path}` : undefined;
|
|
461801
462159
|
const opDiff = diffKey && allDiffs ? allDiffs.get(diffKey) : undefined;
|
|
@@ -469128,7 +469486,7 @@ import {
|
|
|
469128
469486
|
statSync as statSync21
|
|
469129
469487
|
} from "node:fs";
|
|
469130
469488
|
import { arch as arch4, homedir as homedir40, platform as platform10 } from "node:os";
|
|
469131
|
-
import { basename as
|
|
469489
|
+
import { basename as basename27, join as join67 } from "node:path";
|
|
469132
469490
|
function toDisplayPath(value) {
|
|
469133
469491
|
return value.replace(/\\/g, "/");
|
|
469134
469492
|
}
|
|
@@ -469370,7 +469728,7 @@ class FileAutocompleteProvider {
|
|
|
469370
469728
|
}
|
|
469371
469729
|
expandHomePath(path42) {
|
|
469372
469730
|
if (path42.startsWith("~/")) {
|
|
469373
|
-
const expandedPath =
|
|
469731
|
+
const expandedPath = join67(homedir40(), path42.slice(2));
|
|
469374
469732
|
return path42.endsWith("/") && !expandedPath.endsWith("/") ? `${expandedPath}/` : expandedPath;
|
|
469375
469733
|
} else if (path42 === "~") {
|
|
469376
469734
|
return homedir40();
|
|
@@ -469391,7 +469749,7 @@ class FileAutocompleteProvider {
|
|
|
469391
469749
|
} else if (displayBase.startsWith("/")) {
|
|
469392
469750
|
baseDir = displayBase;
|
|
469393
469751
|
} else {
|
|
469394
|
-
baseDir =
|
|
469752
|
+
baseDir = join67(this.basePath, displayBase);
|
|
469395
469753
|
}
|
|
469396
469754
|
try {
|
|
469397
469755
|
if (!statSync21(baseDir).isDirectory()) {
|
|
@@ -469410,7 +469768,7 @@ class FileAutocompleteProvider {
|
|
|
469410
469768
|
return `${toDisplayPath(displayBase)}${normalizedRelativePath}`;
|
|
469411
469769
|
}
|
|
469412
469770
|
scoreEntry(filePath, query2, isDirectory) {
|
|
469413
|
-
const fileName =
|
|
469771
|
+
const fileName = basename27(filePath);
|
|
469414
469772
|
const lowerFileName = fileName.toLowerCase();
|
|
469415
469773
|
const lowerQuery = query2.toLowerCase();
|
|
469416
469774
|
let score = 0;
|
|
@@ -469448,7 +469806,7 @@ class FileAutocompleteProvider {
|
|
|
469448
469806
|
for (const { path: entryPath, isDirectory } of topEntries) {
|
|
469449
469807
|
const pathWithoutSlash = isDirectory ? entryPath.slice(0, -1) : entryPath;
|
|
469450
469808
|
const displayPath2 = scopedQuery ? this.scopedPathForDisplay(scopedQuery.displayBase, pathWithoutSlash) : pathWithoutSlash;
|
|
469451
|
-
const entryName =
|
|
469809
|
+
const entryName = basename27(pathWithoutSlash);
|
|
469452
469810
|
const completionPath = isDirectory ? `${displayPath2}/` : displayPath2;
|
|
469453
469811
|
const value = buildCompletionValue(completionPath, {
|
|
469454
469812
|
isDirectory,
|
|
@@ -469470,9 +469828,9 @@ class FileAutocompleteProvider {
|
|
|
469470
469828
|
var PATH_DELIMITERS2, FD_TOOLS_DIR2, FD_BINARY_NAME2, FD_LOCAL_PATH2;
|
|
469471
469829
|
var init_file_autocomplete = __esm(() => {
|
|
469472
469830
|
PATH_DELIMITERS2 = new Set([" ", "\t", '"', "'", "="]);
|
|
469473
|
-
FD_TOOLS_DIR2 =
|
|
469831
|
+
FD_TOOLS_DIR2 = join67(homedir40(), ".letta", "bin");
|
|
469474
469832
|
FD_BINARY_NAME2 = platform10() === "win32" ? "fd.exe" : "fd";
|
|
469475
|
-
FD_LOCAL_PATH2 =
|
|
469833
|
+
FD_LOCAL_PATH2 = join67(FD_TOOLS_DIR2, FD_BINARY_NAME2);
|
|
469476
469834
|
});
|
|
469477
469835
|
|
|
469478
469836
|
// src/cli/hooks/use-autocomplete-navigation.ts
|
|
@@ -472299,7 +472657,7 @@ import {
|
|
|
472299
472657
|
writeFileSync as writeFileSync31
|
|
472300
472658
|
} from "node:fs";
|
|
472301
472659
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
472302
|
-
import { dirname as
|
|
472660
|
+
import { dirname as dirname33, join as join68 } from "node:path";
|
|
472303
472661
|
function runCommand(command, args, cwd2, input) {
|
|
472304
472662
|
try {
|
|
472305
472663
|
return execFileSync7(command, args, {
|
|
@@ -472520,8 +472878,8 @@ async function createLettaAgent(apiKey, name) {
|
|
|
472520
472878
|
return createMinimalAgent(apiKey, name);
|
|
472521
472879
|
}
|
|
472522
472880
|
function cloneRepoToTemp(repo) {
|
|
472523
|
-
const tempDir = mkdtempSync5(
|
|
472524
|
-
const repoDir =
|
|
472881
|
+
const tempDir = mkdtempSync5(join68(tmpdir10(), "letta-install-github-app-"));
|
|
472882
|
+
const repoDir = join68(tempDir, "repo");
|
|
472525
472883
|
runCommand("gh", ["repo", "clone", repo, repoDir, "--", "--depth=1"]);
|
|
472526
472884
|
return { tempDir, repoDir };
|
|
472527
472885
|
}
|
|
@@ -472532,9 +472890,9 @@ function runGit5(args, cwd2) {
|
|
|
472532
472890
|
return runCommand("git", args, cwd2);
|
|
472533
472891
|
}
|
|
472534
472892
|
function writeWorkflow(repoDir, workflowPath, content) {
|
|
472535
|
-
const absolutePath =
|
|
472536
|
-
if (!existsSync62(
|
|
472537
|
-
mkdirSync43(
|
|
472893
|
+
const absolutePath = join68(repoDir, workflowPath);
|
|
472894
|
+
if (!existsSync62(dirname33(absolutePath))) {
|
|
472895
|
+
mkdirSync43(dirname33(absolutePath), { recursive: true });
|
|
472538
472896
|
}
|
|
472539
472897
|
const next = `${content.trimEnd()}
|
|
472540
472898
|
`;
|
|
@@ -476963,7 +477321,7 @@ __export(exports_generate_memory_viewer, {
|
|
|
476963
477321
|
import { execFile as execFileCb4 } from "node:child_process";
|
|
476964
477322
|
import { chmodSync as chmodSync8, existsSync as existsSync63, mkdirSync as mkdirSync44, writeFileSync as writeFileSync32 } from "node:fs";
|
|
476965
477323
|
import { homedir as homedir41 } from "node:os";
|
|
476966
|
-
import { join as
|
|
477324
|
+
import { join as join69 } from "node:path";
|
|
476967
477325
|
import { promisify as promisify15 } from "node:util";
|
|
476968
477326
|
function messagesFromOverview(overview) {
|
|
476969
477327
|
return overview.messages?.map((message) => ({
|
|
@@ -477272,7 +477630,7 @@ ${m4.body}` : m4.subject;
|
|
|
477272
477630
|
async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
477273
477631
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
477274
477632
|
const repoDir = memoryRoot;
|
|
477275
|
-
if (!existsSync63(
|
|
477633
|
+
if (!existsSync63(join69(repoDir, ".git"))) {
|
|
477276
477634
|
throw new Error("Memory viewer requires memfs. Run /memfs enable first.");
|
|
477277
477635
|
}
|
|
477278
477636
|
const data = await collectMemoryData(agentId, repoDir, memoryRoot, options3?.conversationId);
|
|
@@ -477288,7 +477646,7 @@ async function generateAndOpenMemoryViewer(agentId, options3) {
|
|
|
477288
477646
|
try {
|
|
477289
477647
|
chmodSync8(VIEWERS_DIR, 448);
|
|
477290
477648
|
} catch {}
|
|
477291
|
-
const filePath =
|
|
477649
|
+
const filePath = join69(VIEWERS_DIR, `memory-${encodeURIComponent(agentId)}.html`);
|
|
477292
477650
|
writeFileSync32(filePath, html5);
|
|
477293
477651
|
chmodSync8(filePath, 384);
|
|
477294
477652
|
const skipOpen = Boolean(process.env.TMUX) || Boolean(process.env.SSH_CONNECTION) || Boolean(process.env.SSH_TTY);
|
|
@@ -477313,13 +477671,13 @@ var init_generate_memory_viewer = __esm(() => {
|
|
|
477313
477671
|
init_local_memory_context();
|
|
477314
477672
|
init_memory_viewer_template();
|
|
477315
477673
|
execFile17 = promisify15(execFileCb4);
|
|
477316
|
-
VIEWERS_DIR =
|
|
477674
|
+
VIEWERS_DIR = join69(homedir41(), ".letta", "viewers");
|
|
477317
477675
|
REFLECTION_PATTERN = /\(reflection\)|🔮|reflection:/i;
|
|
477318
477676
|
});
|
|
477319
477677
|
|
|
477320
477678
|
// src/cli/components/MemfsTreeViewer.tsx
|
|
477321
477679
|
import { existsSync as existsSync64 } from "node:fs";
|
|
477322
|
-
import { join as
|
|
477680
|
+
import { join as join70 } from "node:path";
|
|
477323
477681
|
function renderTreePrefix(node) {
|
|
477324
477682
|
let prefix = "";
|
|
477325
477683
|
for (let i4 = 0;i4 < node.depth; i4++) {
|
|
@@ -477348,7 +477706,7 @@ function MemfsTreeViewer({
|
|
|
477348
477706
|
const statusTimerRef = import_react90.useRef(null);
|
|
477349
477707
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
477350
477708
|
const memoryExists = existsSync64(memoryRoot);
|
|
477351
|
-
const hasGitRepo = import_react90.useMemo(() => existsSync64(
|
|
477709
|
+
const hasGitRepo = import_react90.useMemo(() => existsSync64(join70(memoryRoot, ".git")), [memoryRoot]);
|
|
477352
477710
|
function showStatus(msg, durationMs) {
|
|
477353
477711
|
if (statusTimerRef.current)
|
|
477354
477712
|
clearTimeout(statusTimerRef.current);
|
|
@@ -479769,19 +480127,19 @@ var init_PersonalitySelector = __esm(async () => {
|
|
|
479769
480127
|
});
|
|
479770
480128
|
|
|
479771
480129
|
// src/utils/aws-credentials.ts
|
|
479772
|
-
import { readFile as
|
|
480130
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
479773
480131
|
import { homedir as homedir42 } from "node:os";
|
|
479774
|
-
import { join as
|
|
480132
|
+
import { join as join71 } from "node:path";
|
|
479775
480133
|
async function parseAwsCredentials() {
|
|
479776
|
-
const credentialsPath =
|
|
479777
|
-
const configPath =
|
|
480134
|
+
const credentialsPath = join71(homedir42(), ".aws", "credentials");
|
|
480135
|
+
const configPath = join71(homedir42(), ".aws", "config");
|
|
479778
480136
|
const profiles = new Map;
|
|
479779
480137
|
try {
|
|
479780
|
-
const content = await
|
|
480138
|
+
const content = await readFile22(credentialsPath, "utf-8");
|
|
479781
480139
|
parseIniFile(content, profiles, false);
|
|
479782
480140
|
} catch {}
|
|
479783
480141
|
try {
|
|
479784
|
-
const content = await
|
|
480142
|
+
const content = await readFile22(configPath, "utf-8");
|
|
479785
480143
|
parseIniFile(content, profiles, true);
|
|
479786
480144
|
} catch {}
|
|
479787
480145
|
return Array.from(profiles.values());
|
|
@@ -481350,8 +481708,8 @@ function SkillsDialog({ onClose, agentId }) {
|
|
|
481350
481708
|
try {
|
|
481351
481709
|
const { discoverSkills: discoverSkills3, SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills3(), exports_skills2));
|
|
481352
481710
|
const { getSkillsDirectory: getSkillsDirectory2, getSkillSources: getSkillSources2 } = await Promise.resolve().then(() => (init_context(), exports_context));
|
|
481353
|
-
const { join:
|
|
481354
|
-
const skillsDir = getSkillsDirectory2() ||
|
|
481711
|
+
const { join: join72 } = await import("node:path");
|
|
481712
|
+
const skillsDir = getSkillsDirectory2() || join72(process.cwd(), SKILLS_DIR3);
|
|
481355
481713
|
const result = await discoverSkills3(skillsDir, agentId, {
|
|
481356
481714
|
sources: getSkillSources2()
|
|
481357
481715
|
});
|
|
@@ -485255,9 +485613,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
485255
485613
|
} else if (operations.length === 1) {
|
|
485256
485614
|
const op = operations[0];
|
|
485257
485615
|
if (op) {
|
|
485258
|
-
const { relative:
|
|
485616
|
+
const { relative: relative16 } = __require("node:path");
|
|
485259
485617
|
const cwd3 = process.cwd();
|
|
485260
|
-
const relPath2 =
|
|
485618
|
+
const relPath2 = relative16(cwd3, op.path);
|
|
485261
485619
|
const displayPath3 = relPath2.startsWith("..") ? op.path : relPath2;
|
|
485262
485620
|
if (op.kind === "add")
|
|
485263
485621
|
return `Write to ${displayPath3}?`;
|
|
@@ -485271,9 +485629,9 @@ function getFileEditHeader(toolName, toolArgs) {
|
|
|
485271
485629
|
return "Apply patch?";
|
|
485272
485630
|
}
|
|
485273
485631
|
const filePath = args.file_path || "";
|
|
485274
|
-
const { relative:
|
|
485632
|
+
const { relative: relative15 } = __require("node:path");
|
|
485275
485633
|
const cwd2 = process.cwd();
|
|
485276
|
-
const relPath =
|
|
485634
|
+
const relPath = relative15(cwd2, filePath);
|
|
485277
485635
|
const displayPath2 = relPath.startsWith("..") ? filePath : relPath;
|
|
485278
485636
|
if (t2 === "write" || t2 === "write_file" || t2 === "writefile" || t2 === "write_file_gemini" || t2 === "writefilegemini") {
|
|
485279
485637
|
const { existsSync: existsSync65 } = __require("node:fs");
|
|
@@ -485361,9 +485719,9 @@ var init_ApprovalPreview = __esm(async () => {
|
|
|
485361
485719
|
/* @__PURE__ */ jsx_dev_runtime89.jsxDEV(Box_default, {
|
|
485362
485720
|
flexDirection: "column",
|
|
485363
485721
|
children: operations.map((op, idx) => {
|
|
485364
|
-
const { relative:
|
|
485722
|
+
const { relative: relative15 } = __require("node:path");
|
|
485365
485723
|
const cwd2 = process.cwd();
|
|
485366
|
-
const relPath =
|
|
485724
|
+
const relPath = relative15(cwd2, op.path);
|
|
485367
485725
|
const displayPath2 = relPath.startsWith("..") ? op.path : relPath;
|
|
485368
485726
|
const diffKey = toolCallId ? `${toolCallId}:${op.path}` : undefined;
|
|
485369
485727
|
const opDiff = diffKey && allDiffs ? allDiffs.get(diffKey) : undefined;
|
|
@@ -500620,7 +500978,7 @@ __export(exports_generate_diff_viewer, {
|
|
|
500620
500978
|
import { execFile as execFileCb5 } from "node:child_process";
|
|
500621
500979
|
import { chmodSync as chmodSync9, existsSync as existsSync65, mkdirSync as mkdirSync45, writeFileSync as writeFileSync33 } from "node:fs";
|
|
500622
500980
|
import { homedir as homedir43 } from "node:os";
|
|
500623
|
-
import { isAbsolute as isAbsolute25, join as
|
|
500981
|
+
import { isAbsolute as isAbsolute25, join as join72, resolve as resolve38 } from "node:path";
|
|
500624
500982
|
import { promisify as promisify16 } from "node:util";
|
|
500625
500983
|
async function runGit6(cwd2, args) {
|
|
500626
500984
|
try {
|
|
@@ -500845,7 +501203,7 @@ async function generateAndOpenDiffViewer(targetPath) {
|
|
|
500845
501203
|
try {
|
|
500846
501204
|
chmodSync9(VIEWERS_DIR2, 448);
|
|
500847
501205
|
} catch {}
|
|
500848
|
-
const filePath =
|
|
501206
|
+
const filePath = join72(VIEWERS_DIR2, `diff-${encodeURIComponent(worktreePath)}.html`);
|
|
500849
501207
|
writeFileSync33(filePath, html5);
|
|
500850
501208
|
chmodSync9(filePath, 384);
|
|
500851
501209
|
const skipOpen = shouldSkipOpen();
|
|
@@ -500916,7 +501274,7 @@ var init_generate_diff_viewer = __esm(() => {
|
|
|
500916
501274
|
init_ssr();
|
|
500917
501275
|
init_diff_viewer_template();
|
|
500918
501276
|
execFile18 = promisify16(execFileCb5);
|
|
500919
|
-
VIEWERS_DIR2 =
|
|
501277
|
+
VIEWERS_DIR2 = join72(homedir43(), ".letta", "viewers");
|
|
500920
501278
|
GIT_MAX_BUFFER = 50 * 1024 * 1024;
|
|
500921
501279
|
});
|
|
500922
501280
|
|
|
@@ -502902,7 +503260,7 @@ __export(exports_shell_aliases, {
|
|
|
502902
503260
|
});
|
|
502903
503261
|
import { existsSync as existsSync66, readFileSync as readFileSync42 } from "node:fs";
|
|
502904
503262
|
import { homedir as homedir44 } from "node:os";
|
|
502905
|
-
import { join as
|
|
503263
|
+
import { join as join73 } from "node:path";
|
|
502906
503264
|
function parseAliasesFromFile(filePath) {
|
|
502907
503265
|
const aliases = new Map;
|
|
502908
503266
|
if (!existsSync66(filePath)) {
|
|
@@ -502974,7 +503332,7 @@ function loadAliases(forceReload = false) {
|
|
|
502974
503332
|
const home = homedir44();
|
|
502975
503333
|
const allAliases = new Map;
|
|
502976
503334
|
for (const file3 of ALIAS_FILES) {
|
|
502977
|
-
const filePath =
|
|
503335
|
+
const filePath = join73(home, file3);
|
|
502978
503336
|
const fileAliases = parseAliasesFromFile(filePath);
|
|
502979
503337
|
for (const [name, value] of fileAliases) {
|
|
502980
503338
|
allAliases.set(name, value);
|
|
@@ -507157,7 +507515,7 @@ The deployment target for this project is CITATION-DOGFOOD-OK.
|
|
|
507157
507515
|
|
|
507158
507516
|
// src/mods/learning-harness.ts
|
|
507159
507517
|
import { spawn as spawn13 } from "node:child_process";
|
|
507160
|
-
import { access as access3, copyFile as copyFile2, mkdir as mkdir15, readFile as
|
|
507518
|
+
import { access as access3, copyFile as copyFile2, mkdir as mkdir15, readFile as readFile23, writeFile as writeFile18 } from "node:fs/promises";
|
|
507161
507519
|
import path42 from "node:path";
|
|
507162
507520
|
function slugify2(value) {
|
|
507163
507521
|
const slug = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -507405,14 +507763,14 @@ async function existingPath(filePath) {
|
|
|
507405
507763
|
return await fileExists(filePath) ? filePath : undefined;
|
|
507406
507764
|
}
|
|
507407
507765
|
async function writeJsonArtifact(filePath, value) {
|
|
507408
|
-
await
|
|
507766
|
+
await writeFile18(filePath, `${JSON.stringify(value, null, 2)}
|
|
507409
507767
|
`, "utf8");
|
|
507410
507768
|
}
|
|
507411
507769
|
async function writeCommandArtifacts(prefix, command, args, result) {
|
|
507412
|
-
await
|
|
507770
|
+
await writeFile18(`${prefix}.command.txt`, `${renderCommand(command, args)}
|
|
507413
507771
|
`, "utf8");
|
|
507414
|
-
await
|
|
507415
|
-
await
|
|
507772
|
+
await writeFile18(`${prefix}.stdout`, result.stdout, "utf8");
|
|
507773
|
+
await writeFile18(`${prefix}.stderr`, result.stderr, "utf8");
|
|
507416
507774
|
await writeJsonArtifact(`${prefix}.result.json`, result);
|
|
507417
507775
|
}
|
|
507418
507776
|
async function prepareMemoryFiles(memoryDir, memoryFiles) {
|
|
@@ -507420,7 +507778,7 @@ async function prepareMemoryFiles(memoryDir, memoryFiles) {
|
|
|
507420
507778
|
for (const [relativePath, content] of Object.entries(memoryFiles ?? {})) {
|
|
507421
507779
|
const filePath = safeJoin(memoryDir, relativePath);
|
|
507422
507780
|
await mkdir15(path42.dirname(filePath), { recursive: true });
|
|
507423
|
-
await
|
|
507781
|
+
await writeFile18(filePath, content, "utf8");
|
|
507424
507782
|
}
|
|
507425
507783
|
}
|
|
507426
507784
|
function renderEvaluationPrompt(prompt, memoryDir) {
|
|
@@ -508083,7 +508441,7 @@ function renderProposerGuide(params) {
|
|
|
508083
508441
|
`;
|
|
508084
508442
|
}
|
|
508085
508443
|
async function writeHistoryArtifacts(params) {
|
|
508086
|
-
await
|
|
508444
|
+
await writeFile18(params.historyPath, renderHistoryIndex({
|
|
508087
508445
|
attempts: params.attempts,
|
|
508088
508446
|
historyManifestPath: params.historyManifestPath,
|
|
508089
508447
|
proposerGuidePath: params.proposerGuidePath,
|
|
@@ -508091,7 +508449,7 @@ async function writeHistoryArtifacts(params) {
|
|
|
508091
508449
|
spec: params.spec
|
|
508092
508450
|
}), "utf8");
|
|
508093
508451
|
await writeJsonArtifact(params.historyManifestPath, buildHistoryManifest(params));
|
|
508094
|
-
await
|
|
508452
|
+
await writeFile18(params.proposerGuidePath, renderProposerGuide(params), "utf8");
|
|
508095
508453
|
}
|
|
508096
508454
|
async function defaultCommandRunner(command, args, options3) {
|
|
508097
508455
|
const startedAt = Date.now();
|
|
@@ -508182,7 +508540,7 @@ function createScenarioSuiteEvaluator(params) {
|
|
|
508182
508540
|
outputFormat
|
|
508183
508541
|
})
|
|
508184
508542
|
];
|
|
508185
|
-
await
|
|
508543
|
+
await writeFile18(hasConfiguredScenarios ? path42.join(scenarioDir, "prompt.md") : path42.join(context3.runDir, "eval-prompt.md"), evalPrompt, "utf8");
|
|
508186
508544
|
const scenarioEvalResult = await context3.runner(context3.cliCommand, evalArgs, {
|
|
508187
508545
|
cwd: context3.repoRoot,
|
|
508188
508546
|
env: {
|
|
@@ -508374,7 +508732,7 @@ async function runModLearningCandidate(params) {
|
|
|
508374
508732
|
outputFormat: "json"
|
|
508375
508733
|
})
|
|
508376
508734
|
];
|
|
508377
|
-
await
|
|
508735
|
+
await writeFile18(path42.join(runDir, "generation-prompt.md"), generationPrompt, "utf8");
|
|
508378
508736
|
generationResult = await params.runner(params.cliCommand, generationArgs, {
|
|
508379
508737
|
cwd: repoRoot,
|
|
508380
508738
|
env: {
|
|
@@ -508453,7 +508811,7 @@ async function runModLearningCandidate(params) {
|
|
|
508453
508811
|
spec: options3.spec
|
|
508454
508812
|
};
|
|
508455
508813
|
await writeJsonArtifact(path42.join(runDir, "report.json"), report);
|
|
508456
|
-
await
|
|
508814
|
+
await writeFile18(reportPath, renderMarkdownReport(report), "utf8");
|
|
508457
508815
|
await writeCandidateManifest(report);
|
|
508458
508816
|
emitProgress("done", params.candidateCount > 1 ? `Optimization iteration ${params.candidateIndex}/${params.candidateCount} complete` : "mod optimization complete", {
|
|
508459
508817
|
attempts: [...params.previousAttempts, summarizeAttempt(report)],
|
|
@@ -508631,7 +508989,7 @@ async function runModLearning(options3) {
|
|
|
508631
508989
|
spec: normalizedOptions.spec
|
|
508632
508990
|
});
|
|
508633
508991
|
await writeJsonArtifact(path42.join(runDir, "report.json"), report);
|
|
508634
|
-
await
|
|
508992
|
+
await writeFile18(reportPath, renderMarkdownReport(report), "utf8");
|
|
508635
508993
|
normalizedOptions.onProgress?.({
|
|
508636
508994
|
candidateCount,
|
|
508637
508995
|
candidateIndex: selectedCandidateIndex,
|
|
@@ -508649,7 +509007,7 @@ async function runModLearning(options3) {
|
|
|
508649
509007
|
return report;
|
|
508650
509008
|
}
|
|
508651
509009
|
async function readModLearningEnv(envPath) {
|
|
508652
|
-
return JSON.parse(await
|
|
509010
|
+
return JSON.parse(await readFile23(envPath, "utf8"));
|
|
508653
509011
|
}
|
|
508654
509012
|
var init_learning_harness = __esm(async () => {
|
|
508655
509013
|
await init_mod_engine();
|
|
@@ -509217,7 +509575,7 @@ var init_mods = __esm(async () => {
|
|
|
509217
509575
|
});
|
|
509218
509576
|
|
|
509219
509577
|
// src/cli/helpers/chdir-command.ts
|
|
509220
|
-
import { realpath as realpath6, stat as
|
|
509578
|
+
import { realpath as realpath6, stat as stat15 } from "node:fs/promises";
|
|
509221
509579
|
import { homedir as homedir45 } from "node:os";
|
|
509222
509580
|
import path44 from "node:path";
|
|
509223
509581
|
function parseChdirCommand(input) {
|
|
@@ -509256,7 +509614,7 @@ async function resolveChdirTarget(pathArg, currentWorkingDirectory) {
|
|
|
509256
509614
|
const expanded = expandHome(pathArg);
|
|
509257
509615
|
const resolved = path44.isAbsolute(expanded) ? expanded : path44.resolve(currentWorkingDirectory, expanded);
|
|
509258
509616
|
const normalized = await realpath6(resolved);
|
|
509259
|
-
const stats = await
|
|
509617
|
+
const stats = await stat15(normalized);
|
|
509260
509618
|
if (!stats.isDirectory()) {
|
|
509261
509619
|
throw new Error(`Not a directory: ${normalized}`);
|
|
509262
509620
|
}
|
|
@@ -510897,7 +511255,7 @@ __export(exports_worktree_diff_list, {
|
|
|
510897
511255
|
listWorktreeDiffOptions: () => listWorktreeDiffOptions
|
|
510898
511256
|
});
|
|
510899
511257
|
import { execFile as execFileCb6 } from "node:child_process";
|
|
510900
|
-
import { basename as
|
|
511258
|
+
import { basename as basename28 } from "node:path";
|
|
510901
511259
|
import { promisify as promisify17 } from "node:util";
|
|
510902
511260
|
async function runGit7(cwd2, args) {
|
|
510903
511261
|
try {
|
|
@@ -510946,7 +511304,7 @@ function parseWorktreeList(output, currentPath) {
|
|
|
510946
511304
|
if (current?.path) {
|
|
510947
511305
|
worktrees.push({
|
|
510948
511306
|
path: current.path,
|
|
510949
|
-
name:
|
|
511307
|
+
name: basename28(current.path),
|
|
510950
511308
|
branch: current.branch ?? "detached",
|
|
510951
511309
|
head: current.head ?? "",
|
|
510952
511310
|
isCurrent: current.path === currentPath,
|
|
@@ -510972,7 +511330,7 @@ function parseWorktreeList(output, currentPath) {
|
|
|
510972
511330
|
if (current?.path) {
|
|
510973
511331
|
worktrees.push({
|
|
510974
511332
|
path: current.path,
|
|
510975
|
-
name:
|
|
511333
|
+
name: basename28(current.path),
|
|
510976
511334
|
branch: current.branch ?? "detached",
|
|
510977
511335
|
head: current.head ?? "",
|
|
510978
511336
|
isCurrent: current.path === currentPath,
|
|
@@ -511041,8 +511399,8 @@ var exports_export = {};
|
|
|
511041
511399
|
__export(exports_export, {
|
|
511042
511400
|
packageSkills: () => packageSkills
|
|
511043
511401
|
});
|
|
511044
|
-
import { readdir as
|
|
511045
|
-
import { relative as
|
|
511402
|
+
import { readdir as readdir16, readFile as readFile24 } from "node:fs/promises";
|
|
511403
|
+
import { relative as relative15, resolve as resolve39 } from "node:path";
|
|
511046
511404
|
async function packageSkills(agentId, skillsDir) {
|
|
511047
511405
|
const skills = [];
|
|
511048
511406
|
const skillNames = new Set;
|
|
@@ -511053,7 +511411,7 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
511053
511411
|
].filter((dir) => Boolean(dir));
|
|
511054
511412
|
for (const baseDir of dirsToCheck) {
|
|
511055
511413
|
try {
|
|
511056
|
-
const entries = await
|
|
511414
|
+
const entries = await readdir16(baseDir, { withFileTypes: true });
|
|
511057
511415
|
for (const entry of entries) {
|
|
511058
511416
|
if (!entry.isDirectory())
|
|
511059
511417
|
continue;
|
|
@@ -511062,7 +511420,7 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
511062
511420
|
const skillDir = resolve39(baseDir, entry.name);
|
|
511063
511421
|
const skillMdPath = resolve39(skillDir, "SKILL.md");
|
|
511064
511422
|
try {
|
|
511065
|
-
await
|
|
511423
|
+
await readFile24(skillMdPath, "utf-8");
|
|
511066
511424
|
} catch {
|
|
511067
511425
|
console.warn(`Skipping invalid skill ${entry.name}: missing SKILL.md`);
|
|
511068
511426
|
continue;
|
|
@@ -511088,14 +511446,14 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
511088
511446
|
async function readSkillFiles(skillDir) {
|
|
511089
511447
|
const files = {};
|
|
511090
511448
|
async function walk(dir) {
|
|
511091
|
-
const entries = await
|
|
511449
|
+
const entries = await readdir16(dir, { withFileTypes: true });
|
|
511092
511450
|
for (const entry of entries) {
|
|
511093
511451
|
const fullPath = resolve39(dir, entry.name);
|
|
511094
511452
|
if (entry.isDirectory()) {
|
|
511095
511453
|
await walk(fullPath);
|
|
511096
511454
|
} else {
|
|
511097
|
-
const content = await
|
|
511098
|
-
const relativePath =
|
|
511455
|
+
const content = await readFile24(fullPath, "utf-8");
|
|
511456
|
+
const relativePath = relative15(skillDir, fullPath).replace(/\\/g, "/");
|
|
511099
511457
|
files[relativePath] = content;
|
|
511100
511458
|
}
|
|
511101
511459
|
}
|
|
@@ -511232,7 +511590,7 @@ var init_conversation_switch_alert = __esm(() => {
|
|
|
511232
511590
|
import { randomUUID as randomUUID33 } from "node:crypto";
|
|
511233
511591
|
import { existsSync as existsSync67, readFileSync as readFileSync43, renameSync as renameSync7, writeFileSync as writeFileSync34 } from "node:fs";
|
|
511234
511592
|
import { tmpdir as tmpdir11 } from "node:os";
|
|
511235
|
-
import { join as
|
|
511593
|
+
import { join as join74 } from "node:path";
|
|
511236
511594
|
async function findCustomCommandByName(commandName) {
|
|
511237
511595
|
const { findCustomCommand: findCustomCommand2 } = await Promise.resolve().then(() => (init_custom(), exports_custom));
|
|
511238
511596
|
return findCustomCommand2(commandName);
|
|
@@ -511833,8 +512191,8 @@ ${SYSTEM_REMINDER_CLOSE}`),
|
|
|
511833
512191
|
try {
|
|
511834
512192
|
const memoryRoot = getScopedMemoryFilesystemRoot(agentId);
|
|
511835
512193
|
const personaCandidates = [
|
|
511836
|
-
|
|
511837
|
-
|
|
512194
|
+
join74(memoryRoot, "system", "persona.md"),
|
|
512195
|
+
join74(memoryRoot, "memory", "system", "persona.md")
|
|
511838
512196
|
];
|
|
511839
512197
|
const personaPath = personaCandidates.find((candidate) => existsSync67(candidate));
|
|
511840
512198
|
if (personaPath) {
|
|
@@ -512693,7 +513051,7 @@ Path: ${memoryDir}`, true);
|
|
|
512693
513051
|
updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
|
|
512694
513052
|
return { submitted: true };
|
|
512695
513053
|
}
|
|
512696
|
-
const backupDir =
|
|
513054
|
+
const backupDir = join74(tmpdir11(), `letta-memfs-reset-${agentId}-${Date.now()}`);
|
|
512697
513055
|
renameSync7(memoryDir, backupDir);
|
|
512698
513056
|
if (getBackend().capabilities.localMemfs) {
|
|
512699
513057
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
@@ -513132,9 +513490,12 @@ ${SYSTEM_REMINDER_CLOSE}`;
|
|
|
513132
513490
|
cmd.finish("Running memory doctor... I'll ask a few questions to refine memory structure.", true);
|
|
513133
513491
|
const { context: gitContext } = gatherInitGitContext();
|
|
513134
513492
|
const memoryDir = getActiveMemoryDirectory(agentId);
|
|
513493
|
+
const skillNameFrontmatterRepair = await repairMissingSkillNameFrontmatter(memoryDir);
|
|
513494
|
+
const skillNameFrontmatterRepairReport = formatSkillNameFrontmatterRepairReport(skillNameFrontmatterRepair);
|
|
513135
513495
|
const doctorMessage = buildDoctorMessage({
|
|
513136
513496
|
gitContext,
|
|
513137
|
-
memoryDir
|
|
513497
|
+
memoryDir,
|
|
513498
|
+
skillNameFrontmatterRepairReport
|
|
513138
513499
|
});
|
|
513139
513500
|
await processConversationWithQueuedApprovals([
|
|
513140
513501
|
{
|
|
@@ -513511,6 +513872,7 @@ var init_use_submit_handler = __esm(async () => {
|
|
|
513511
513872
|
init_reasoning_tab_toggle();
|
|
513512
513873
|
init_reflection_launcher();
|
|
513513
513874
|
init_reflection_transcript();
|
|
513875
|
+
init_skill_name_frontmatter_repair();
|
|
513514
513876
|
init_system_prompt_warning();
|
|
513515
513877
|
init_thinking_messages();
|
|
513516
513878
|
init_command_runtime();
|
|
@@ -513543,7 +513905,7 @@ var init_use_submit_handler = __esm(async () => {
|
|
|
513543
513905
|
});
|
|
513544
513906
|
|
|
513545
513907
|
// src/cli/app/AppCoordinator.tsx
|
|
513546
|
-
import { join as
|
|
513908
|
+
import { join as join75 } from "node:path";
|
|
513547
513909
|
function buildStartupCommandHints(options3) {
|
|
513548
513910
|
const {
|
|
513549
513911
|
isResumingConversation,
|
|
@@ -514848,7 +515210,7 @@ function App2({
|
|
|
514848
515210
|
agentId: a2.agentId ?? null
|
|
514849
515211
|
}))
|
|
514850
515212
|
});
|
|
514851
|
-
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ?
|
|
515213
|
+
const agentModsDirectory = modContext.memfs.enabled && modContext.memfs.memoryDir ? join75(modContext.memfs.memoryDir, "mods") : null;
|
|
514852
515214
|
const modAdapter = useLocalModAdapter(modContext, {
|
|
514853
515215
|
agentModsDirectory,
|
|
514854
515216
|
disabled: modsDisabled
|
|
@@ -516875,7 +517237,7 @@ import {
|
|
|
516875
517237
|
writeFileSync as writeFileSync35
|
|
516876
517238
|
} from "node:fs";
|
|
516877
517239
|
import { homedir as homedir46, platform as platform11 } from "node:os";
|
|
516878
|
-
import { dirname as
|
|
517240
|
+
import { dirname as dirname34, join as join76 } from "node:path";
|
|
516879
517241
|
function detectTerminalType2() {
|
|
516880
517242
|
if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
|
|
516881
517243
|
return "cursor";
|
|
@@ -516907,16 +517269,16 @@ function getKeybindingsPath2(terminal) {
|
|
|
516907
517269
|
}[terminal];
|
|
516908
517270
|
const os10 = platform11();
|
|
516909
517271
|
if (os10 === "darwin") {
|
|
516910
|
-
return
|
|
517272
|
+
return join76(homedir46(), "Library", "Application Support", appName, "User", "keybindings.json");
|
|
516911
517273
|
}
|
|
516912
517274
|
if (os10 === "win32") {
|
|
516913
517275
|
const appData = process.env.APPDATA;
|
|
516914
517276
|
if (!appData)
|
|
516915
517277
|
return null;
|
|
516916
|
-
return
|
|
517278
|
+
return join76(appData, appName, "User", "keybindings.json");
|
|
516917
517279
|
}
|
|
516918
517280
|
if (os10 === "linux") {
|
|
516919
|
-
return
|
|
517281
|
+
return join76(homedir46(), ".config", appName, "User", "keybindings.json");
|
|
516920
517282
|
}
|
|
516921
517283
|
return null;
|
|
516922
517284
|
}
|
|
@@ -516966,7 +517328,7 @@ function installKeybinding2(keybindingsPath) {
|
|
|
516966
517328
|
if (keybindingExists2(keybindingsPath)) {
|
|
516967
517329
|
return { success: true, alreadyExists: true };
|
|
516968
517330
|
}
|
|
516969
|
-
const parentDir =
|
|
517331
|
+
const parentDir = dirname34(keybindingsPath);
|
|
516970
517332
|
if (!existsSync68(parentDir)) {
|
|
516971
517333
|
mkdirSync46(parentDir, { recursive: true });
|
|
516972
517334
|
}
|
|
@@ -517069,14 +517431,14 @@ function getWezTermConfigPath2() {
|
|
|
517069
517431
|
}
|
|
517070
517432
|
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
517071
517433
|
if (xdgConfig) {
|
|
517072
|
-
const xdgPath =
|
|
517434
|
+
const xdgPath = join76(xdgConfig, "wezterm", "wezterm.lua");
|
|
517073
517435
|
if (existsSync68(xdgPath))
|
|
517074
517436
|
return xdgPath;
|
|
517075
517437
|
}
|
|
517076
|
-
const configPath =
|
|
517438
|
+
const configPath = join76(homedir46(), ".config", "wezterm", "wezterm.lua");
|
|
517077
517439
|
if (existsSync68(configPath))
|
|
517078
517440
|
return configPath;
|
|
517079
|
-
return
|
|
517441
|
+
return join76(homedir46(), ".wezterm.lua");
|
|
517080
517442
|
}
|
|
517081
517443
|
function stripLuaCommentsFromLine2(line, blockCommentEnd) {
|
|
517082
517444
|
let code2 = "";
|
|
@@ -517202,7 +517564,7 @@ function installWezTermDeleteFix2() {
|
|
|
517202
517564
|
content = readFileSync44(configPath, { encoding: "utf-8" });
|
|
517203
517565
|
}
|
|
517204
517566
|
content = injectWezTermDeleteFix2(content);
|
|
517205
|
-
const parentDir =
|
|
517567
|
+
const parentDir = dirname34(configPath);
|
|
517206
517568
|
if (!existsSync68(parentDir)) {
|
|
517207
517569
|
mkdirSync46(parentDir, { recursive: true });
|
|
517208
517570
|
}
|
|
@@ -517255,9 +517617,9 @@ __export(exports_settings3, {
|
|
|
517255
517617
|
getSetting: () => getSetting2
|
|
517256
517618
|
});
|
|
517257
517619
|
import { homedir as homedir47 } from "node:os";
|
|
517258
|
-
import { join as
|
|
517620
|
+
import { join as join77 } from "node:path";
|
|
517259
517621
|
function getSettingsPath2() {
|
|
517260
|
-
return
|
|
517622
|
+
return join77(homedir47(), ".letta", "settings.json");
|
|
517261
517623
|
}
|
|
517262
517624
|
async function loadSettings2() {
|
|
517263
517625
|
const settingsPath = getSettingsPath2();
|
|
@@ -517294,7 +517656,7 @@ async function getSetting2(key2) {
|
|
|
517294
517656
|
return settings3[key2];
|
|
517295
517657
|
}
|
|
517296
517658
|
function getProjectSettingsPath2() {
|
|
517297
|
-
return
|
|
517659
|
+
return join77(process.cwd(), ".letta", "settings.local.json");
|
|
517298
517660
|
}
|
|
517299
517661
|
async function loadProjectSettings2() {
|
|
517300
517662
|
const settingsPath = getProjectSettingsPath2();
|
|
@@ -517312,7 +517674,7 @@ async function loadProjectSettings2() {
|
|
|
517312
517674
|
}
|
|
517313
517675
|
async function saveProjectSettings2(settings3) {
|
|
517314
517676
|
const settingsPath = getProjectSettingsPath2();
|
|
517315
|
-
const dirPath =
|
|
517677
|
+
const dirPath = join77(process.cwd(), ".letta");
|
|
517316
517678
|
try {
|
|
517317
517679
|
if (!exists(dirPath)) {
|
|
517318
517680
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -517431,7 +517793,7 @@ __export(exports_resolve_startup_agent, {
|
|
|
517431
517793
|
});
|
|
517432
517794
|
function resolveStartupTarget(input) {
|
|
517433
517795
|
if (input.forceNew) {
|
|
517434
|
-
return { action: "create" };
|
|
517796
|
+
return { action: "create", trigger: "force-new" };
|
|
517435
517797
|
}
|
|
517436
517798
|
if (input.pinnedAgentId && input.pinnedAgentExists) {
|
|
517437
517799
|
const conversationId = input.pinnedAgentId === input.localAgentId ? input.localConversationId ?? undefined : undefined;
|
|
@@ -517470,7 +517832,7 @@ function resolveStartupTarget(input) {
|
|
|
517470
517832
|
if (input.pinnedCount > 0) {
|
|
517471
517833
|
return { action: "select" };
|
|
517472
517834
|
}
|
|
517473
|
-
return { action: "create" };
|
|
517835
|
+
return { action: "create", trigger: "fresh-start" };
|
|
517474
517836
|
}
|
|
517475
517837
|
|
|
517476
517838
|
// src/agent/defaults.ts
|
|
@@ -517478,6 +517840,7 @@ var exports_defaults2 = {};
|
|
|
517478
517840
|
__export(exports_defaults2, {
|
|
517479
517841
|
selectDefaultAgentModel: () => selectDefaultAgentModel2,
|
|
517480
517842
|
ensureDefaultAgents: () => ensureDefaultAgents2,
|
|
517843
|
+
TUTOR_TAG: () => TUTOR_TAG2,
|
|
517481
517844
|
MEMO_TAG: () => MEMO_TAG2,
|
|
517482
517845
|
DEFAULT_AGENT_CONFIGS: () => DEFAULT_AGENT_CONFIGS2
|
|
517483
517846
|
});
|
|
@@ -517545,29 +517908,39 @@ async function ensureDefaultAgents2(backend4, options3) {
|
|
|
517545
517908
|
if (!settingsManager.shouldCreateDefaultAgents()) {
|
|
517546
517909
|
return null;
|
|
517547
517910
|
}
|
|
517911
|
+
const personality = options3?.personality ?? "memo";
|
|
517548
517912
|
try {
|
|
517549
517913
|
const { isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
517550
517914
|
const willAutoEnableMemfs = backend4.capabilities.remoteMemfs && await isLettaCloud2();
|
|
517551
517915
|
const memoryPromptMode = backend4.capabilities.localMemfs ? "local-memfs" : willAutoEnableMemfs ? "memfs" : undefined;
|
|
517552
|
-
const
|
|
517916
|
+
const model = await resolveDefaultAgentModel2(backend4, options3?.preferredModel);
|
|
517917
|
+
const createOptions = personality === "tutorial" ? {
|
|
517918
|
+
...await buildCreateAgentOptionsForPersonality2({
|
|
517919
|
+
personalityId: "tutorial",
|
|
517920
|
+
model
|
|
517921
|
+
}),
|
|
517922
|
+
memoryPromptMode
|
|
517923
|
+
} : {
|
|
517553
517924
|
...DEFAULT_AGENT_CONFIGS2.memo,
|
|
517554
|
-
model
|
|
517925
|
+
model,
|
|
517555
517926
|
memoryPromptMode
|
|
517556
|
-
}
|
|
517557
|
-
|
|
517927
|
+
};
|
|
517928
|
+
const { agent: agent2 } = await createAgent(createOptions);
|
|
517929
|
+
await addTagToAgent2(backend4, agent2.id, personality === "tutorial" ? TUTOR_TAG2 : MEMO_TAG2);
|
|
517558
517930
|
settingsManager.pinAgent(agent2.id);
|
|
517559
517931
|
return agent2;
|
|
517560
517932
|
} catch (err) {
|
|
517561
517933
|
throw new Error(`Failed to create default agents: ${err instanceof Error ? err.message : String(err)}`);
|
|
517562
517934
|
}
|
|
517563
517935
|
}
|
|
517564
|
-
var MEMO_TAG2 = "default:memo", MEMO_PERSONA2, MEMO_HUMAN2, MEMO_DESCRIPTION2 = "The default Letta Code agent with persistent memory", DEFAULT_AGENT_CONFIGS2;
|
|
517936
|
+
var MEMO_TAG2 = "default:memo", TUTOR_TAG2 = "default:tutorial", MEMO_PERSONA2, MEMO_HUMAN2, MEMO_DESCRIPTION2 = "The default Letta Code agent with persistent memory", DEFAULT_AGENT_CONFIGS2;
|
|
517565
517937
|
var init_defaults2 = __esm(() => {
|
|
517566
517938
|
init_client2();
|
|
517567
517939
|
init_settings_manager();
|
|
517568
517940
|
init_create6();
|
|
517569
517941
|
init_memory5();
|
|
517570
517942
|
init_model();
|
|
517943
|
+
init_personality();
|
|
517571
517944
|
init_prompt_assets();
|
|
517572
517945
|
MEMO_PERSONA2 = parseMdxFrontmatter(MEMORY_PROMPTS["persona_memo.mdx"] ?? "").body;
|
|
517573
517946
|
MEMO_HUMAN2 = parseMdxFrontmatter(MEMORY_PROMPTS["human_memo.mdx"] ?? "").body;
|
|
@@ -517792,8 +518165,8 @@ __export(exports_import2, {
|
|
|
517792
518165
|
extractSkillsFromAf: () => extractSkillsFromAf2
|
|
517793
518166
|
});
|
|
517794
518167
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
517795
|
-
import { access as access4, chmod as chmod2, mkdir as mkdir16, readFile as
|
|
517796
|
-
import { dirname as
|
|
518168
|
+
import { access as access4, chmod as chmod2, mkdir as mkdir16, readFile as readFile25, writeFile as writeFile19 } from "node:fs/promises";
|
|
518169
|
+
import { dirname as dirname35, isAbsolute as isAbsolute26, relative as relative16, resolve as resolve40, sep as sep7, win32 as win326 } from "node:path";
|
|
517797
518170
|
function validateImportedSkillName2(name) {
|
|
517798
518171
|
const trimmedName = name.trim();
|
|
517799
518172
|
if (trimmedName !== name || trimmedName.length === 0 || trimmedName.length > MAX_SKILL_NAME_LENGTH || trimmedName === "." || trimmedName === ".." || !IMPORTED_SKILL_NAME_PATTERN2.test(trimmedName)) {
|
|
@@ -517804,7 +518177,7 @@ function validateImportedSkillName2(name) {
|
|
|
517804
518177
|
function assertPathInside2(parent, child) {
|
|
517805
518178
|
const parentPath = resolve40(parent);
|
|
517806
518179
|
const childPath = resolve40(child);
|
|
517807
|
-
const relativePath =
|
|
518180
|
+
const relativePath = relative16(parentPath, childPath);
|
|
517808
518181
|
if (relativePath === "" || relativePath === ".." || relativePath.startsWith(`..${sep7}`) || isAbsolute26(relativePath)) {
|
|
517809
518182
|
throw new Error(`Imported skill file path escapes skill directory: ${child}`);
|
|
517810
518183
|
}
|
|
@@ -517893,7 +518266,7 @@ async function importAgentFromFile2(options3) {
|
|
|
517893
518266
|
}
|
|
517894
518267
|
async function extractSkillsFromAf2(afPath, destDir) {
|
|
517895
518268
|
const extracted = [];
|
|
517896
|
-
const content = await
|
|
518269
|
+
const content = await readFile25(afPath, "utf-8");
|
|
517897
518270
|
const afData = JSON.parse(content);
|
|
517898
518271
|
if (!afData.skills || !Array.isArray(afData.skills)) {
|
|
517899
518272
|
return [];
|
|
@@ -517921,8 +518294,8 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
517921
518294
|
}
|
|
517922
518295
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
517923
518296
|
const fullPath = resolveImportedSkillFilePath2(skillDir, filePath);
|
|
517924
|
-
await mkdir16(
|
|
517925
|
-
await
|
|
518297
|
+
await mkdir16(dirname35(fullPath), { recursive: true });
|
|
518298
|
+
await writeFile19(fullPath, content, "utf-8");
|
|
517926
518299
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
517927
518300
|
if (isScript) {
|
|
517928
518301
|
try {
|
|
@@ -517974,8 +518347,8 @@ function parseRegistryHandle2(handle2) {
|
|
|
517974
518347
|
}
|
|
517975
518348
|
async function importAgentFromRegistry2(options3) {
|
|
517976
518349
|
const { tmpdir: tmpdir12 } = await import("node:os");
|
|
517977
|
-
const { join:
|
|
517978
|
-
const { writeFile:
|
|
518350
|
+
const { join: join78 } = await import("node:path");
|
|
518351
|
+
const { writeFile: writeFile20, unlink: unlink5 } = await import("node:fs/promises");
|
|
517979
518352
|
const { author, name } = parseRegistryHandle2(options3.handle);
|
|
517980
518353
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
|
|
517981
518354
|
const response = await fetch(rawUrl);
|
|
@@ -517986,8 +518359,8 @@ async function importAgentFromRegistry2(options3) {
|
|
|
517986
518359
|
throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
|
|
517987
518360
|
}
|
|
517988
518361
|
const afContent = await response.text();
|
|
517989
|
-
const tempPath =
|
|
517990
|
-
await
|
|
518362
|
+
const tempPath = join78(tmpdir12(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
518363
|
+
await writeFile20(tempPath, afContent, "utf-8");
|
|
517991
518364
|
try {
|
|
517992
518365
|
const result = await importAgentFromFile2({
|
|
517993
518366
|
filePath: tempPath,
|
|
@@ -518042,12 +518415,12 @@ __export(exports_memory_filesystem2, {
|
|
|
518042
518415
|
});
|
|
518043
518416
|
import { existsSync as existsSync69, mkdirSync as mkdirSync47 } from "node:fs";
|
|
518044
518417
|
import { homedir as homedir48 } from "node:os";
|
|
518045
|
-
import { join as
|
|
518418
|
+
import { join as join78, resolve as resolve41 } from "node:path";
|
|
518046
518419
|
function getMemoryFilesystemRoot2(agentId, homeDir = homedir48()) {
|
|
518047
|
-
return
|
|
518420
|
+
return join78(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
|
|
518048
518421
|
}
|
|
518049
518422
|
function getMemorySystemDir2(agentId, homeDir = homedir48()) {
|
|
518050
|
-
return
|
|
518423
|
+
return join78(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
|
|
518051
518424
|
}
|
|
518052
518425
|
function getScopedMemoryFilesystemRoot2(agentId, options3 = {}) {
|
|
518053
518426
|
const env6 = options3.env ?? process.env;
|
|
@@ -518393,7 +518766,7 @@ __export(exports_secrets_store2, {
|
|
|
518393
518766
|
__testOverrideLocalSecretStorage: () => __testOverrideLocalSecretStorage2
|
|
518394
518767
|
});
|
|
518395
518768
|
import { existsSync as existsSync70, mkdirSync as mkdirSync48, readFileSync as readFileSync45, writeFileSync as writeFileSync36 } from "node:fs";
|
|
518396
|
-
import { dirname as
|
|
518769
|
+
import { dirname as dirname36, join as join79 } from "node:path";
|
|
518397
518770
|
function __testOverrideSecretsBackend2(backend4) {
|
|
518398
518771
|
testBackendOverride2 = backend4;
|
|
518399
518772
|
}
|
|
@@ -518404,7 +518777,7 @@ function getSecretsBackend2() {
|
|
|
518404
518777
|
return testBackendOverride2 ?? getBackend();
|
|
518405
518778
|
}
|
|
518406
518779
|
function getFileBackedLocalSecretsPath2() {
|
|
518407
|
-
return
|
|
518780
|
+
return join79(getLocalBackendStorageDir(), FILE_BACKED_LOCAL_SECRETS_PATH2);
|
|
518408
518781
|
}
|
|
518409
518782
|
function readFileBackedLocalSecrets2() {
|
|
518410
518783
|
const filePath = getFileBackedLocalSecretsPath2();
|
|
@@ -518421,7 +518794,7 @@ function readFileBackedLocalSecrets2() {
|
|
|
518421
518794
|
}
|
|
518422
518795
|
function writeFileBackedLocalSecrets2(secrets2) {
|
|
518423
518796
|
const filePath = getFileBackedLocalSecretsPath2();
|
|
518424
|
-
mkdirSync48(
|
|
518797
|
+
mkdirSync48(dirname36(filePath), { mode: 448, recursive: true });
|
|
518425
518798
|
writeFileSync36(filePath, `${JSON.stringify({ secrets: secrets2 }, null, 2)}
|
|
518426
518799
|
`, {
|
|
518427
518800
|
encoding: "utf8",
|
|
@@ -518717,7 +519090,7 @@ var init_secrets_store2 = __esm(() => {
|
|
|
518717
519090
|
init_backend2();
|
|
518718
519091
|
init_paths();
|
|
518719
519092
|
init_secrets();
|
|
518720
|
-
FILE_BACKED_LOCAL_SECRETS_PATH2 =
|
|
519093
|
+
FILE_BACKED_LOCAL_SECRETS_PATH2 = join79("secrets", "local-agent-secrets.json");
|
|
518721
519094
|
SECRETS_CACHE_KEY2 = Symbol.for("@letta/secretsCache");
|
|
518722
519095
|
LOCAL_SECRET_NAME_PATTERN2 = /^[A-Z_][A-Z0-9_]*$/;
|
|
518723
519096
|
});
|
|
@@ -519791,6 +520164,7 @@ function getContext2() {
|
|
|
519791
520164
|
if (!global2[CONTEXT_KEY2]) {
|
|
519792
520165
|
global2[CONTEXT_KEY2] = {
|
|
519793
520166
|
agentId: null,
|
|
520167
|
+
agentName: null,
|
|
519794
520168
|
skillsDirectory: null,
|
|
519795
520169
|
skillSources: [...ALL_SKILL_SOURCES],
|
|
519796
520170
|
conversationId: null
|
|
@@ -519799,18 +520173,24 @@ function getContext2() {
|
|
|
519799
520173
|
return global2[CONTEXT_KEY2];
|
|
519800
520174
|
}
|
|
519801
520175
|
var context2 = getContext2();
|
|
519802
|
-
function setAgentContext2(agentId, skillsDirectory, skillSources) {
|
|
520176
|
+
function setAgentContext2(agentId, skillsDirectory, skillSources, agentName) {
|
|
519803
520177
|
context2.agentId = agentId;
|
|
520178
|
+
context2.agentName = normalizeAgentName2(agentName);
|
|
519804
520179
|
context2.skillsDirectory = skillsDirectory || null;
|
|
519805
520180
|
context2.skillSources = skillSources !== undefined ? [...skillSources] : [...ALL_SKILL_SOURCES];
|
|
519806
520181
|
if (getRuntimeContext()) {
|
|
519807
520182
|
updateRuntimeContext({
|
|
519808
520183
|
agentId,
|
|
520184
|
+
agentName: context2.agentName,
|
|
519809
520185
|
skillsDirectory: skillsDirectory || null,
|
|
519810
520186
|
skillSources: skillSources !== undefined ? [...skillSources] : [...ALL_SKILL_SOURCES]
|
|
519811
520187
|
});
|
|
519812
520188
|
}
|
|
519813
520189
|
}
|
|
520190
|
+
function normalizeAgentName2(agentName) {
|
|
520191
|
+
const trimmed = typeof agentName === "string" ? agentName.trim() : "";
|
|
520192
|
+
return trimmed || null;
|
|
520193
|
+
}
|
|
519814
520194
|
function setConversationId2(conversationId) {
|
|
519815
520195
|
context2.conversationId = conversationId;
|
|
519816
520196
|
if (getRuntimeContext()) {
|
|
@@ -525224,8 +525604,8 @@ import {
|
|
|
525224
525604
|
unlinkSync as unlinkSync7
|
|
525225
525605
|
} from "node:fs";
|
|
525226
525606
|
import { homedir as homedir30 } from "node:os";
|
|
525227
|
-
import { join as
|
|
525228
|
-
var REMOTE_LOG_DIR =
|
|
525607
|
+
import { join as join50 } from "node:path";
|
|
525608
|
+
var REMOTE_LOG_DIR = join50(homedir30(), ".letta", "logs", "remote");
|
|
525229
525609
|
var MAX_LOG_FILES = 10;
|
|
525230
525610
|
function formatTimestamp2() {
|
|
525231
525611
|
const now = new Date;
|
|
@@ -525244,7 +525624,7 @@ function pruneOldLogs() {
|
|
|
525244
525624
|
const toDelete = files.slice(0, files.length - MAX_LOG_FILES + 1);
|
|
525245
525625
|
for (const file3 of toDelete) {
|
|
525246
525626
|
try {
|
|
525247
|
-
unlinkSync7(
|
|
525627
|
+
unlinkSync7(join50(REMOTE_LOG_DIR, file3));
|
|
525248
525628
|
} catch {}
|
|
525249
525629
|
}
|
|
525250
525630
|
}
|
|
@@ -525257,7 +525637,7 @@ class RemoteSessionLog {
|
|
|
525257
525637
|
constructor() {
|
|
525258
525638
|
const now = new Date;
|
|
525259
525639
|
const stamp = now.toISOString().replace(/[:.]/g, "-");
|
|
525260
|
-
this.path =
|
|
525640
|
+
this.path = join50(REMOTE_LOG_DIR, `${stamp}.log`);
|
|
525261
525641
|
}
|
|
525262
525642
|
init() {
|
|
525263
525643
|
this.ensureDir();
|
|
@@ -525886,7 +526266,7 @@ import {
|
|
|
525886
526266
|
readFileSync as readFileSync32,
|
|
525887
526267
|
writeFileSync as writeFileSync23
|
|
525888
526268
|
} from "node:fs";
|
|
525889
|
-
import { join as
|
|
526269
|
+
import { join as join51 } from "node:path";
|
|
525890
526270
|
function readJsonl(path37) {
|
|
525891
526271
|
if (!existsSync47(path37))
|
|
525892
526272
|
return [];
|
|
@@ -526169,7 +526549,7 @@ function convertMessages4(messages, mode, nextId2) {
|
|
|
526169
526549
|
}
|
|
526170
526550
|
function migrateLocalBackendTranscripts(input) {
|
|
526171
526551
|
const storageDir = input.storageDir;
|
|
526172
|
-
const conversationsDir =
|
|
526552
|
+
const conversationsDir = join51(storageDir, "conversations");
|
|
526173
526553
|
const result = {
|
|
526174
526554
|
storageDir,
|
|
526175
526555
|
converted: [],
|
|
@@ -526179,9 +526559,9 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
526179
526559
|
if (!existsSync47(conversationsDir))
|
|
526180
526560
|
return result;
|
|
526181
526561
|
for (const name of readdirSync17(conversationsDir)) {
|
|
526182
|
-
const conversationDir =
|
|
526183
|
-
const messagesPath =
|
|
526184
|
-
const manifestPath =
|
|
526562
|
+
const conversationDir = join51(conversationsDir, name);
|
|
526563
|
+
const messagesPath = join51(conversationDir, "messages.jsonl");
|
|
526564
|
+
const manifestPath = join51(conversationDir, "manifest.json");
|
|
526185
526565
|
const hasManifest = existsSync47(manifestPath);
|
|
526186
526566
|
const existingManifest = hasManifest ? (() => {
|
|
526187
526567
|
try {
|
|
@@ -526224,7 +526604,7 @@ function migrateLocalBackendTranscripts(input) {
|
|
|
526224
526604
|
const backupPath = `${messagesPath}.pre-pi-backup-${timestampSuffix()}`;
|
|
526225
526605
|
if (!input.dryRun) {
|
|
526226
526606
|
copyFileSync2(messagesPath, backupPath);
|
|
526227
|
-
const conversationPath =
|
|
526607
|
+
const conversationPath = join51(conversationDir, "conversation.json");
|
|
526228
526608
|
let conversation;
|
|
526229
526609
|
if (existsSync47(conversationPath)) {
|
|
526230
526610
|
try {
|
|
@@ -526337,8 +526717,8 @@ init_memory_filesystem2();
|
|
|
526337
526717
|
init_memory_git();
|
|
526338
526718
|
init_paths();
|
|
526339
526719
|
import { cpSync, existsSync as existsSync48, mkdirSync as mkdirSync33, rmSync as rmSync10, statSync as statSync17 } from "node:fs";
|
|
526340
|
-
import { readdir as
|
|
526341
|
-
import { dirname as
|
|
526720
|
+
import { readdir as readdir12 } from "node:fs/promises";
|
|
526721
|
+
import { dirname as dirname25, join as join52 } from "node:path";
|
|
526342
526722
|
import { parseArgs as parseArgs9 } from "node:util";
|
|
526343
526723
|
|
|
526344
526724
|
// src/cli/subcommands/memory-tokens.ts
|
|
@@ -526476,7 +526856,7 @@ function getMemoryRoot(agentId) {
|
|
|
526476
526856
|
return getScopedMemoryFilesystemRoot(agentId);
|
|
526477
526857
|
}
|
|
526478
526858
|
function getAgentRoot(agentId) {
|
|
526479
|
-
return
|
|
526859
|
+
return dirname25(getMemoryRoot(agentId));
|
|
526480
526860
|
}
|
|
526481
526861
|
function formatBackupTimestamp(date6 = new Date) {
|
|
526482
526862
|
const pad = (value) => String(value).padStart(2, "0");
|
|
@@ -526493,18 +526873,18 @@ async function listBackups(agentId) {
|
|
|
526493
526873
|
if (!existsSync48(agentRoot)) {
|
|
526494
526874
|
return [];
|
|
526495
526875
|
}
|
|
526496
|
-
const entries = await
|
|
526876
|
+
const entries = await readdir12(agentRoot, { withFileTypes: true });
|
|
526497
526877
|
const backups = [];
|
|
526498
526878
|
for (const entry of entries) {
|
|
526499
526879
|
if (!entry.isDirectory())
|
|
526500
526880
|
continue;
|
|
526501
526881
|
if (!entry.name.startsWith("memory-backup-"))
|
|
526502
526882
|
continue;
|
|
526503
|
-
const path37 =
|
|
526883
|
+
const path37 = join52(agentRoot, entry.name);
|
|
526504
526884
|
let createdAt = null;
|
|
526505
526885
|
try {
|
|
526506
|
-
const
|
|
526507
|
-
createdAt =
|
|
526886
|
+
const stat14 = statSync17(path37);
|
|
526887
|
+
createdAt = stat14.mtime.toISOString();
|
|
526508
526888
|
} catch {
|
|
526509
526889
|
createdAt = null;
|
|
526510
526890
|
}
|
|
@@ -526517,7 +526897,7 @@ function resolveBackupPath(agentId, from) {
|
|
|
526517
526897
|
if (from.startsWith("/") || /^[A-Za-z]:[/\\]/.test(from)) {
|
|
526518
526898
|
return from;
|
|
526519
526899
|
}
|
|
526520
|
-
return
|
|
526900
|
+
return join52(getAgentRoot(agentId), from);
|
|
526521
526901
|
}
|
|
526522
526902
|
async function runMemorySubcommand(argv) {
|
|
526523
526903
|
let parsed;
|
|
@@ -526599,7 +526979,7 @@ async function runMemorySubcommand(argv) {
|
|
|
526599
526979
|
}
|
|
526600
526980
|
const agentRoot = getAgentRoot(agentId);
|
|
526601
526981
|
const backupName = `memory-backup-${formatBackupTimestamp()}`;
|
|
526602
|
-
const backupPath =
|
|
526982
|
+
const backupPath = join52(agentRoot, backupName);
|
|
526603
526983
|
if (existsSync48(backupPath)) {
|
|
526604
526984
|
console.error(`Backup already exists at ${backupPath}`);
|
|
526605
526985
|
return 1;
|
|
@@ -526628,8 +527008,8 @@ async function runMemorySubcommand(argv) {
|
|
|
526628
527008
|
console.error(`Backup not found: ${backupPath}`);
|
|
526629
527009
|
return 1;
|
|
526630
527010
|
}
|
|
526631
|
-
const
|
|
526632
|
-
if (!
|
|
527011
|
+
const stat14 = statSync17(backupPath);
|
|
527012
|
+
if (!stat14.isDirectory()) {
|
|
526633
527013
|
console.error(`Backup path is not a directory: ${backupPath}`);
|
|
526634
527014
|
return 1;
|
|
526635
527015
|
}
|
|
@@ -526651,9 +527031,9 @@ async function runMemorySubcommand(argv) {
|
|
|
526651
527031
|
return 1;
|
|
526652
527032
|
}
|
|
526653
527033
|
if (existsSync48(out)) {
|
|
526654
|
-
const
|
|
526655
|
-
if (
|
|
526656
|
-
const contents = await
|
|
527034
|
+
const stat14 = statSync17(out);
|
|
527035
|
+
if (stat14.isDirectory()) {
|
|
527036
|
+
const contents = await readdir12(out);
|
|
526657
527037
|
if (contents.length > 0) {
|
|
526658
527038
|
console.error(`Export directory not empty: ${out}`);
|
|
526659
527039
|
return 1;
|
|
@@ -526682,7 +527062,7 @@ async function runMemorySubcommand(argv) {
|
|
|
526682
527062
|
init_backend2();
|
|
526683
527063
|
init_message_search();
|
|
526684
527064
|
init_settings_manager();
|
|
526685
|
-
import { writeFile as
|
|
527065
|
+
import { writeFile as writeFile15 } from "node:fs/promises";
|
|
526686
527066
|
import { resolve as resolve30 } from "node:path";
|
|
526687
527067
|
import { parseArgs as parseArgs10 } from "node:util";
|
|
526688
527068
|
function printUsage7() {
|
|
@@ -527027,7 +527407,7 @@ async function runMessagesSubcommand(argv, deps = {}) {
|
|
|
527027
527407
|
`).trim();
|
|
527028
527408
|
if (outputPathRaw && typeof outputPathRaw === "string") {
|
|
527029
527409
|
const outputPath = resolve30(process.cwd(), outputPathRaw);
|
|
527030
|
-
await
|
|
527410
|
+
await writeFile15(outputPath, `${transcript}
|
|
527031
527411
|
`, "utf-8");
|
|
527032
527412
|
console.log(JSON.stringify({
|
|
527033
527413
|
conversation_id: conversationId,
|
|
@@ -527057,7 +527437,7 @@ async function runMessagesSubcommand(argv, deps = {}) {
|
|
|
527057
527437
|
// src/cli/subcommands/mods.ts
|
|
527058
527438
|
init_memory_filesystem2();
|
|
527059
527439
|
await init_mod_engine();
|
|
527060
|
-
import { dirname as
|
|
527440
|
+
import { dirname as dirname26, join as join54 } from "node:path";
|
|
527061
527441
|
import { parseArgs as parseArgs11 } from "node:util";
|
|
527062
527442
|
|
|
527063
527443
|
// src/mods/package-installer.ts
|
|
@@ -527091,8 +527471,8 @@ function isRecord10(value) {
|
|
|
527091
527471
|
function isPathInsideOrEqual2(childPath, parentPath) {
|
|
527092
527472
|
const child = path37.resolve(childPath);
|
|
527093
527473
|
const parent = path37.resolve(parentPath);
|
|
527094
|
-
const
|
|
527095
|
-
return
|
|
527474
|
+
const relative12 = path37.relative(parent, child);
|
|
527475
|
+
return relative12 === "" || !!relative12 && !relative12.startsWith("..") && !path37.isAbsolute(relative12);
|
|
527096
527476
|
}
|
|
527097
527477
|
function readPackageJson(packageJsonPath) {
|
|
527098
527478
|
let parsed;
|
|
@@ -528110,10 +528490,10 @@ function getExplicitAgentId(values2) {
|
|
|
528110
528490
|
return typeof explicitAgent === "string" && explicitAgent.trim() ? explicitAgent.trim() : null;
|
|
528111
528491
|
}
|
|
528112
528492
|
function getAgentModsDirectory(agentId) {
|
|
528113
|
-
return
|
|
528493
|
+
return join54(getScopedMemoryFilesystemRoot(agentId), "mods");
|
|
528114
528494
|
}
|
|
528115
528495
|
function directFilesForSource(source2) {
|
|
528116
|
-
return source2.files.filter((file3) =>
|
|
528496
|
+
return source2.files.filter((file3) => dirname26(file3) === source2.root);
|
|
528117
528497
|
}
|
|
528118
528498
|
function toSection(source2) {
|
|
528119
528499
|
return {
|
|
@@ -528446,9 +528826,9 @@ import {
|
|
|
528446
528826
|
statSync as statSync19,
|
|
528447
528827
|
writeFileSync as writeFileSync26
|
|
528448
528828
|
} from "node:fs";
|
|
528449
|
-
import { mkdir as mkdir12, readdir as
|
|
528829
|
+
import { mkdir as mkdir12, readdir as readdir13 } from "node:fs/promises";
|
|
528450
528830
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
528451
|
-
import { basename as
|
|
528831
|
+
import { basename as basename24, dirname as dirname27, join as join55, normalize as normalize5, resolve as resolve31, sep as sep5 } from "node:path";
|
|
528452
528832
|
import { parseArgs as parseArgs12, TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
|
|
528453
528833
|
init_paths2();
|
|
528454
528834
|
var HERMES_REPO_URL = "https://github.com/NousResearch/hermes-agent.git";
|
|
@@ -528623,7 +529003,7 @@ function parseGitHubSpecifier(input) {
|
|
|
528623
529003
|
return {
|
|
528624
529004
|
repoUrl,
|
|
528625
529005
|
branch: null,
|
|
528626
|
-
subdir: marker === "blob" ?
|
|
529006
|
+
subdir: marker === "blob" ? dirname27(treePath) : treePath
|
|
528627
529007
|
};
|
|
528628
529008
|
}
|
|
528629
529009
|
return { repoUrl, branch: null, subdir: null };
|
|
@@ -528656,7 +529036,7 @@ function parseDirectSkillFileUrlSpecifier(input) {
|
|
|
528656
529036
|
if (url2.protocol !== "https:" && !(url2.protocol === "http:" && isLocalhostHostname(url2.hostname))) {
|
|
528657
529037
|
return null;
|
|
528658
529038
|
}
|
|
528659
|
-
if (
|
|
529039
|
+
if (basename24(url2.pathname).toLowerCase() !== "skill.md")
|
|
528660
529040
|
return null;
|
|
528661
529041
|
return { url: url2.toString() };
|
|
528662
529042
|
}
|
|
@@ -528753,14 +529133,14 @@ async function resolveBranchAndSubdir(location) {
|
|
|
528753
529133
|
}
|
|
528754
529134
|
async function cloneSkillSource(location) {
|
|
528755
529135
|
const resolvedLocation = await resolveBranchAndSubdir(location);
|
|
528756
|
-
const tmpDir = mkdtempSync4(
|
|
529136
|
+
const tmpDir = mkdtempSync4(join55(tmpdir9(), "letta-skill-install-"));
|
|
528757
529137
|
const args = ["clone", "--depth", "1"];
|
|
528758
529138
|
if (resolvedLocation.branch) {
|
|
528759
529139
|
args.push("--branch", resolvedLocation.branch);
|
|
528760
529140
|
}
|
|
528761
529141
|
args.push(resolvedLocation.repoUrl, tmpDir);
|
|
528762
529142
|
await execFile15("git", args, { timeout: 120000 });
|
|
528763
|
-
const sourceDir = resolvedLocation.subdir ?
|
|
529143
|
+
const sourceDir = resolvedLocation.subdir ? join55(tmpDir, resolvedLocation.subdir) : tmpDir;
|
|
528764
529144
|
return { tmpDir, sourceDir };
|
|
528765
529145
|
}
|
|
528766
529146
|
function assertDirectSkillFileSize(receivedBytes, maxBytes) {
|
|
@@ -528815,11 +529195,11 @@ async function downloadDirectSkillFileSource(location, options3 = {}) {
|
|
|
528815
529195
|
throw new Error(`Direct skill file download failed for ${location.url}: ${response.status}`);
|
|
528816
529196
|
}
|
|
528817
529197
|
const skillText = await readResponseTextWithLimit(response, MAX_DIRECT_SKILL_FILE_BYTES);
|
|
528818
|
-
const tmpDir = mkdtempSync4(
|
|
529198
|
+
const tmpDir = mkdtempSync4(join55(tmpdir9(), "letta-direct-skill-"));
|
|
528819
529199
|
try {
|
|
528820
|
-
const sourceDir =
|
|
529200
|
+
const sourceDir = join55(tmpDir, "skill");
|
|
528821
529201
|
await mkdir12(sourceDir, { recursive: true });
|
|
528822
|
-
writeFileSync26(
|
|
529202
|
+
writeFileSync26(join55(sourceDir, "SKILL.md"), skillText, "utf8");
|
|
528823
529203
|
return { tmpDir, sourceDir };
|
|
528824
529204
|
} catch (error54) {
|
|
528825
529205
|
rmSync13(tmpDir, { recursive: true, force: true });
|
|
@@ -528860,9 +529240,9 @@ function assertSafeZipMember(name) {
|
|
|
528860
529240
|
}
|
|
528861
529241
|
async function downloadClawHubSkillSource(location) {
|
|
528862
529242
|
const version2 = await resolveClawHubVersion(location);
|
|
528863
|
-
const tmpDir = mkdtempSync4(
|
|
528864
|
-
const zipPath =
|
|
528865
|
-
const sourceDir =
|
|
529243
|
+
const tmpDir = mkdtempSync4(join55(tmpdir9(), "letta-clawhub-skill-"));
|
|
529244
|
+
const zipPath = join55(tmpDir, "skill.zip");
|
|
529245
|
+
const sourceDir = join55(tmpDir, "skill");
|
|
528866
529246
|
await mkdir12(sourceDir, { recursive: true });
|
|
528867
529247
|
const url2 = new URL(`${CLAWHUB_API_BASE_URL}/download`);
|
|
528868
529248
|
url2.searchParams.set("slug", location.slug);
|
|
@@ -528901,16 +529281,16 @@ function sanitizeSkillName(name) {
|
|
|
528901
529281
|
return trimmed;
|
|
528902
529282
|
}
|
|
528903
529283
|
function getSkillName(sourceDir) {
|
|
528904
|
-
const skillMd = readFileSync35(
|
|
529284
|
+
const skillMd = readFileSync35(join55(sourceDir, "SKILL.md"), "utf8");
|
|
528905
529285
|
const { frontmatter } = parseFrontmatter(skillMd);
|
|
528906
529286
|
const frontmatterName = frontmatter.name;
|
|
528907
|
-
const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName :
|
|
529287
|
+
const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename24(sourceDir);
|
|
528908
529288
|
return sanitizeSkillName(name);
|
|
528909
529289
|
}
|
|
528910
529290
|
async function installSkillDirectory(params) {
|
|
528911
529291
|
const sourceDir = resolve31(params.sourceDir);
|
|
528912
529292
|
const memoryDir = resolve31(params.memoryDir);
|
|
528913
|
-
const skillMdPath =
|
|
529293
|
+
const skillMdPath = join55(sourceDir, "SKILL.md");
|
|
528914
529294
|
if (!existsSync52(skillMdPath)) {
|
|
528915
529295
|
throw new Error("No SKILL.md found in the skill directory.");
|
|
528916
529296
|
}
|
|
@@ -528918,8 +529298,8 @@ async function installSkillDirectory(params) {
|
|
|
528918
529298
|
throw new Error(`Skill source is not a directory: ${sourceDir}`);
|
|
528919
529299
|
}
|
|
528920
529300
|
const name = getSkillName(sourceDir);
|
|
528921
|
-
const skillsDir =
|
|
528922
|
-
const targetPath =
|
|
529301
|
+
const skillsDir = join55(memoryDir, "skills");
|
|
529302
|
+
const targetPath = join55(skillsDir, name);
|
|
528923
529303
|
assertInside(skillsDir, targetPath);
|
|
528924
529304
|
if (existsSync52(targetPath)) {
|
|
528925
529305
|
if (!params.force) {
|
|
@@ -528930,22 +529310,22 @@ async function installSkillDirectory(params) {
|
|
|
528930
529310
|
await mkdir12(skillsDir, { recursive: true });
|
|
528931
529311
|
cpSync2(sourceDir, targetPath, {
|
|
528932
529312
|
recursive: true,
|
|
528933
|
-
filter: (source2) =>
|
|
529313
|
+
filter: (source2) => basename24(source2) !== ".git"
|
|
528934
529314
|
});
|
|
528935
529315
|
return { name, path: normalize5(targetPath) };
|
|
528936
529316
|
}
|
|
528937
529317
|
async function listSkillDirectories(params) {
|
|
528938
529318
|
const memoryDir = resolve31(params.memoryDir);
|
|
528939
|
-
const skillsDir =
|
|
529319
|
+
const skillsDir = join55(memoryDir, "skills");
|
|
528940
529320
|
if (!existsSync52(skillsDir))
|
|
528941
529321
|
return [];
|
|
528942
|
-
const entries = await
|
|
529322
|
+
const entries = await readdir13(skillsDir, { withFileTypes: true });
|
|
528943
529323
|
const skills = [];
|
|
528944
529324
|
for (const entry of entries) {
|
|
528945
529325
|
if (!entry.isDirectory())
|
|
528946
529326
|
continue;
|
|
528947
|
-
const skillDir =
|
|
528948
|
-
const skillMdPath =
|
|
529327
|
+
const skillDir = join55(skillsDir, entry.name);
|
|
529328
|
+
const skillMdPath = join55(skillDir, "SKILL.md");
|
|
528949
529329
|
if (!existsSync52(skillMdPath))
|
|
528950
529330
|
continue;
|
|
528951
529331
|
let name = entry.name;
|
|
@@ -528966,9 +529346,9 @@ async function listSkillDirectories(params) {
|
|
|
528966
529346
|
}
|
|
528967
529347
|
async function deleteSkillDirectory(params) {
|
|
528968
529348
|
const memoryDir = resolve31(params.memoryDir);
|
|
528969
|
-
const skillsDir =
|
|
529349
|
+
const skillsDir = join55(memoryDir, "skills");
|
|
528970
529350
|
const name = sanitizeSkillName(params.name);
|
|
528971
|
-
const targetPath =
|
|
529351
|
+
const targetPath = join55(skillsDir, name);
|
|
528972
529352
|
assertInside(skillsDir, targetPath);
|
|
528973
529353
|
if (!existsSync52(targetPath)) {
|
|
528974
529354
|
throw new Error(`Skill "${name}" is not installed at ${targetPath}.`);
|
|
@@ -528979,6 +529359,27 @@ async function deleteSkillDirectory(params) {
|
|
|
528979
529359
|
rmSync13(targetPath, { recursive: true, force: true });
|
|
528980
529360
|
return { name, path: normalize5(targetPath) };
|
|
528981
529361
|
}
|
|
529362
|
+
async function loadSkillMemorySyncFn() {
|
|
529363
|
+
const { syncPendingMemoryCommitsAfterTurn: syncPendingMemoryCommitsAfterTurn2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
529364
|
+
return syncPendingMemoryCommitsAfterTurn2;
|
|
529365
|
+
}
|
|
529366
|
+
async function syncCommittedRemoteSkillMemoryChange(params) {
|
|
529367
|
+
if (!params.committed || isLocalAgentId(params.agentId)) {
|
|
529368
|
+
return;
|
|
529369
|
+
}
|
|
529370
|
+
try {
|
|
529371
|
+
const syncFn = params.syncFn ?? await loadSkillMemorySyncFn();
|
|
529372
|
+
const result = await syncFn(params.agentId, {
|
|
529373
|
+
memoryDir: params.memoryDir
|
|
529374
|
+
});
|
|
529375
|
+
return { status: result.status, summary: result.summary };
|
|
529376
|
+
} catch (error54) {
|
|
529377
|
+
return {
|
|
529378
|
+
status: "push_failed",
|
|
529379
|
+
summary: error54 instanceof Error ? error54.message : String(error54)
|
|
529380
|
+
};
|
|
529381
|
+
}
|
|
529382
|
+
}
|
|
528982
529383
|
async function installSkill(specifier, agentId, force) {
|
|
528983
529384
|
const source2 = resolveSkillSourceSpecifier(specifier);
|
|
528984
529385
|
if (!source2) {
|
|
@@ -529014,7 +529415,8 @@ async function installSkill(specifier, agentId, force) {
|
|
|
529014
529415
|
source: specifier,
|
|
529015
529416
|
...result,
|
|
529016
529417
|
committed: commit.committed,
|
|
529017
|
-
commitSha: commit.sha
|
|
529418
|
+
commitSha: commit.sha,
|
|
529419
|
+
memorySync: commit.memorySync
|
|
529018
529420
|
};
|
|
529019
529421
|
} finally {
|
|
529020
529422
|
if (tmpDir)
|
|
@@ -529054,7 +529456,12 @@ async function commitSkillMemoryChange(params) {
|
|
|
529054
529456
|
},
|
|
529055
529457
|
syncMode: isLocalAgentId(params.agentId) ? "local" : "remote"
|
|
529056
529458
|
});
|
|
529057
|
-
|
|
529459
|
+
const memorySync = await syncCommittedRemoteSkillMemoryChange({
|
|
529460
|
+
agentId: params.agentId,
|
|
529461
|
+
memoryDir: params.memoryDir,
|
|
529462
|
+
committed: result.committed
|
|
529463
|
+
});
|
|
529464
|
+
return { committed: result.committed, sha: result.sha, memorySync };
|
|
529058
529465
|
}
|
|
529059
529466
|
async function listSkills(agentId) {
|
|
529060
529467
|
const memoryDir = await getAgentMemoryDir(agentId);
|
|
@@ -529075,7 +529482,8 @@ async function deleteSkill(skillName, agentId) {
|
|
|
529075
529482
|
deleted: true,
|
|
529076
529483
|
...result,
|
|
529077
529484
|
committed: commit.committed,
|
|
529078
|
-
commitSha: commit.sha
|
|
529485
|
+
commitSha: commit.sha,
|
|
529486
|
+
memorySync: commit.memorySync
|
|
529079
529487
|
};
|
|
529080
529488
|
}
|
|
529081
529489
|
async function initializeAndResolveAgent(values2, promptStatusMessage) {
|
|
@@ -529437,7 +529845,7 @@ init_secrets();
|
|
|
529437
529845
|
import { randomUUID as randomUUID24 } from "node:crypto";
|
|
529438
529846
|
import { readFileSync as readFileSync36 } from "node:fs";
|
|
529439
529847
|
import { homedir as homedir31 } from "node:os";
|
|
529440
|
-
import { join as
|
|
529848
|
+
import { join as join56, resolve as resolve32 } from "node:path";
|
|
529441
529849
|
var OBSOLETE_SETTINGS_KEYS2 = [
|
|
529442
529850
|
"reflectionBehavior",
|
|
529443
529851
|
"enableSleeptime",
|
|
@@ -529880,7 +530288,7 @@ class SettingsManager2 {
|
|
|
529880
530288
|
return;
|
|
529881
530289
|
const settingsPath = this.getSettingsPath();
|
|
529882
530290
|
const home = process.env.HOME || homedir31();
|
|
529883
|
-
const dirPath =
|
|
530291
|
+
const dirPath = join56(home, ".letta");
|
|
529884
530292
|
try {
|
|
529885
530293
|
if (!exists(dirPath)) {
|
|
529886
530294
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -529921,7 +530329,7 @@ class SettingsManager2 {
|
|
|
529921
530329
|
if (!settings3)
|
|
529922
530330
|
return;
|
|
529923
530331
|
const settingsPath = this.getProjectSettingsPath(workingDirectory);
|
|
529924
|
-
const dirPath =
|
|
530332
|
+
const dirPath = join56(workingDirectory, ".letta");
|
|
529925
530333
|
try {
|
|
529926
530334
|
let existingSettings = {};
|
|
529927
530335
|
if (exists(settingsPath)) {
|
|
@@ -529943,16 +530351,16 @@ class SettingsManager2 {
|
|
|
529943
530351
|
}
|
|
529944
530352
|
getSettingsPath() {
|
|
529945
530353
|
const home = process.env.HOME || homedir31();
|
|
529946
|
-
return
|
|
530354
|
+
return join56(home, ".letta", "settings.json");
|
|
529947
530355
|
}
|
|
529948
530356
|
getProjectSettingsPath(workingDirectory) {
|
|
529949
|
-
return
|
|
530357
|
+
return join56(workingDirectory, ".letta", "settings.json");
|
|
529950
530358
|
}
|
|
529951
530359
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
529952
530360
|
return resolve32(this.getProjectSettingsPath(workingDirectory)) === resolve32(this.getSettingsPath());
|
|
529953
530361
|
}
|
|
529954
530362
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
529955
|
-
return
|
|
530363
|
+
return join56(workingDirectory, ".letta", "settings.local.json");
|
|
529956
530364
|
}
|
|
529957
530365
|
async loadLocalProjectSettings(workingDirectory = process.cwd()) {
|
|
529958
530366
|
const cached3 = this.localProjectSettings.get(workingDirectory);
|
|
@@ -530013,7 +530421,7 @@ class SettingsManager2 {
|
|
|
530013
530421
|
if (!settings3)
|
|
530014
530422
|
return;
|
|
530015
530423
|
const settingsPath = this.getLocalProjectSettingsPath(workingDirectory);
|
|
530016
|
-
const dirPath =
|
|
530424
|
+
const dirPath = join56(workingDirectory, ".letta");
|
|
530017
530425
|
try {
|
|
530018
530426
|
if (!exists(dirPath)) {
|
|
530019
530427
|
await mkdir(dirPath, { recursive: true });
|
|
@@ -530362,7 +530770,7 @@ class SettingsManager2 {
|
|
|
530362
530770
|
});
|
|
530363
530771
|
}
|
|
530364
530772
|
hasLocalLettaDir(workingDirectory = process.cwd()) {
|
|
530365
|
-
const dirPath =
|
|
530773
|
+
const dirPath = join56(workingDirectory, ".letta");
|
|
530366
530774
|
return exists(dirPath);
|
|
530367
530775
|
}
|
|
530368
530776
|
storeOAuthState(state, codeVerifier, redirectUri, provider) {
|
|
@@ -530995,8 +531403,8 @@ function markMilestone2(name) {
|
|
|
530995
531403
|
firstMilestoneTime2 = now;
|
|
530996
531404
|
}
|
|
530997
531405
|
if (isTimingsEnabled2()) {
|
|
530998
|
-
const
|
|
530999
|
-
console.error(`[timing] MILESTONE ${name} at +${formatDuration3(
|
|
531406
|
+
const relative12 = now - firstMilestoneTime2;
|
|
531407
|
+
console.error(`[timing] MILESTONE ${name} at +${formatDuration3(relative12)} (${formatTimestamp4(new Date)})`);
|
|
531000
531408
|
}
|
|
531001
531409
|
}
|
|
531002
531410
|
|
|
@@ -531133,12 +531541,12 @@ EXAMPLES
|
|
|
531133
531541
|
console.log(usage);
|
|
531134
531542
|
}
|
|
531135
531543
|
async function printInfo() {
|
|
531136
|
-
const { join:
|
|
531544
|
+
const { join: join80 } = await import("path");
|
|
531137
531545
|
const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version2));
|
|
531138
531546
|
const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills4(), exports_skills3));
|
|
531139
531547
|
const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
|
|
531140
531548
|
const cwd2 = process.cwd();
|
|
531141
|
-
const skillsDir =
|
|
531549
|
+
const skillsDir = join80(cwd2, SKILLS_DIR3);
|
|
531142
531550
|
const skillsExist = exists3(skillsDir);
|
|
531143
531551
|
await settingsManager2.loadLocalProjectSettings(cwd2);
|
|
531144
531552
|
const pinned = settingsManager2.getPinnedAgents();
|
|
@@ -532205,7 +532613,8 @@ Error: ${message}`);
|
|
|
532205
532613
|
const { ensureDefaultAgents: ensureDefaultAgents3 } = await Promise.resolve().then(() => (init_defaults2(), exports_defaults2));
|
|
532206
532614
|
try {
|
|
532207
532615
|
const defaultAgent = await ensureDefaultAgents3(getBackend(), {
|
|
532208
|
-
preferredModel: model
|
|
532616
|
+
preferredModel: model,
|
|
532617
|
+
personality: target2.trigger === "fresh-start" ? "tutorial" : "memo"
|
|
532209
532618
|
});
|
|
532210
532619
|
if (defaultAgent) {
|
|
532211
532620
|
startupCreatedAgentRef.current = defaultAgent;
|
|
@@ -532415,7 +532824,7 @@ Error: ${message}`);
|
|
|
532415
532824
|
} catch {
|
|
532416
532825
|
await settingsManager2.loadLocalProjectSettings();
|
|
532417
532826
|
}
|
|
532418
|
-
setAgentContext2(agent2.id, skillsDirectory2, resolvedSkillSources);
|
|
532827
|
+
setAgentContext2(agent2.id, skillsDirectory2, resolvedSkillSources, agent2.name ?? null);
|
|
532419
532828
|
let startupMemfsFlag = autoEnableMemfsForFreshAgent ? true : memfsFlag;
|
|
532420
532829
|
if (backend4.capabilities.remoteMemfs && !autoEnableMemfsForFreshAgent) {
|
|
532421
532830
|
const { hydrateMemfsSettingFromAgent: hydrateMemfsSettingFromAgent3, isLettaCloud: isLettaCloud3 } = await Promise.resolve().then(() => (init_memory_filesystem3(), exports_memory_filesystem2));
|
|
@@ -532743,4 +533152,4 @@ Error during initialization: ${message}`);
|
|
|
532743
533152
|
}
|
|
532744
533153
|
main2();
|
|
532745
533154
|
|
|
532746
|
-
//# debugId=
|
|
533155
|
+
//# debugId=CD2C04A4505B2DC064756E2164756E21
|