@letta-ai/letta-code 0.21.9 → 0.21.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/letta.js +512 -154
- package/package.json +1 -1
- package/skills/context_doctor/SKILL.md +11 -11
- package/skills/dispatching-coding-agents/SKILL.md +1 -1
- package/skills/initializing-memory/SKILL.md +563 -98
- package/skills/syncing-memory-filesystem/SKILL.md +1 -2
- package/skills/migrating-from-codex-and-claude-code/SKILL.md +0 -162
- package/skills/migrating-from-codex-and-claude-code/references/claude-format.md +0 -212
- package/skills/migrating-from-codex-and-claude-code/references/codex-format.md +0 -229
- /package/skills/{migrating-from-codex-and-claude-code/scripts/detect.sh → initializing-memory/scripts/detect-history.sh} +0 -0
- /package/skills/{migrating-from-codex-and-claude-code → initializing-memory}/scripts/list-sessions.sh +0 -0
- /package/skills/{migrating-from-codex-and-claude-code/scripts/search.sh → initializing-memory/scripts/search-history.sh} +0 -0
- /package/skills/{migrating-from-codex-and-claude-code → initializing-memory}/scripts/view-session.sh +0 -0
package/letta.js
CHANGED
|
@@ -3269,7 +3269,7 @@ var package_default;
|
|
|
3269
3269
|
var init_package = __esm(() => {
|
|
3270
3270
|
package_default = {
|
|
3271
3271
|
name: "@letta-ai/letta-code",
|
|
3272
|
-
version: "0.21.
|
|
3272
|
+
version: "0.21.10",
|
|
3273
3273
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
3274
3274
|
type: "module",
|
|
3275
3275
|
bin: {
|
|
@@ -3535,6 +3535,7 @@ var init_secrets = __esm(async () => {
|
|
|
3535
3535
|
// src/settings-manager.ts
|
|
3536
3536
|
var exports_settings_manager = {};
|
|
3537
3537
|
__export(exports_settings_manager, {
|
|
3538
|
+
shouldPersistSessionState: () => shouldPersistSessionState,
|
|
3538
3539
|
settingsManager: () => settingsManager
|
|
3539
3540
|
});
|
|
3540
3541
|
import { randomUUID } from "node:crypto";
|
|
@@ -3543,6 +3544,9 @@ import { join as join2, resolve } from "node:path";
|
|
|
3543
3544
|
function isSubagentProcess() {
|
|
3544
3545
|
return process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
|
3545
3546
|
}
|
|
3547
|
+
function shouldPersistSessionState() {
|
|
3548
|
+
return process.env.LETTA_CODE_AGENT_ROLE !== "subagent" && process.env.LETTA_DISABLE_SESSION_PERSIST !== "1";
|
|
3549
|
+
}
|
|
3546
3550
|
function normalizeBaseUrl(baseUrl) {
|
|
3547
3551
|
let normalized = baseUrl.replace(/^https?:\/\//, "");
|
|
3548
3552
|
normalized = normalized.replace(/\/$/, "");
|
|
@@ -5484,7 +5488,6 @@ var init_memory_check_reminder = () => {};
|
|
|
5484
5488
|
var memory_filesystem_default = `---
|
|
5485
5489
|
label: memory_filesystem
|
|
5486
5490
|
description: Filesystem view of memory blocks (system + user)
|
|
5487
|
-
limit: 8000
|
|
5488
5491
|
---
|
|
5489
5492
|
|
|
5490
5493
|
/memory/
|
|
@@ -6577,7 +6580,7 @@ When applying memory in responses, integrate it naturally — like a colleague w
|
|
|
6577
6580
|
var init_system_prompt_blocks = () => {};
|
|
6578
6581
|
|
|
6579
6582
|
// src/agent/prompts/system_prompt_memfs.md
|
|
6580
|
-
var system_prompt_memfs_default = "# Memory\n\nYour memory is
|
|
6583
|
+
var system_prompt_memfs_default = "# Memory\n\nYour memory is projected onto the local memory filesystem (MemFS) at `$MEMORY_DIR` (usually `~/.letta/agents/$AGENT_ID/memory/`), including your memory blocks (in-context in the system prompt) and external memory. This projection makes it easy for you to modify your own context with filesystem operations which also include git tracking. Local changes are only propagated to your actual state on a successful push to remote, and the system prompt is only recompiled on compactions or new conversations (so may be stale). \n\n## Memory structure\nYou are responsible to maintaining a clear memory structure. All memory files are markdown with YAML frontmatter (`description`, optional `metadata`).\n\n**In-context memory** (`system/`): Memory files in `system/` correspond to memory blocks, which are pinned directly into your system prompt — visible at all times. This is your most valuable real estate: reserve it for durable knowledge that helps across sessions (user identity, persona, project architecture, conventions, gotchas). Do NOT store transient items here like specific commits, current work items, or session-specific notes — those dilute the signal.\n\n**External memory**: Files outside `system/` follow progressive disclosure — an index of files and descriptions is kept in the system prompt, but full contents must be retrieved on demand (e.g. by reading the file). Skills are a special type of external memory stored in the `skills/` folder. Use `[[path]]` to index files from memory blocks, or create discovery paths between related context (e.g. `[[reference/project/architecture.md]]` or `[[skills/using-slack/SKILL.md]]`).\n\n**Recall** (conversation history): Your full message history is searchable even after messages leave your context window. Use the recall subagent to retrieve past discussions, decisions, and context from earlier sessions.\n\n## Syncing\n\nChanges you commit and push sync to the Letta server within seconds, and server-side changes sync back automatically.\n\n```bash\ncd \"$MEMORY_DIR\"\n\n# See what changed\ngit status\n\n# Commit and push your changes\ngit add .\ngit commit --author=\"$AGENT_NAME <$AGENT_ID@letta.com>\" -m \"<type>: <what changed>\" # e.g. \"fix: update user prefs\", \"refactor: reorganize persona blocks\"\ngit push\n\n# Get latest from server\ngit pull\n```\nThe system will remind you when your memory has uncommitted changes. Sync when convenient.\n\n## History\n```bash\ngit -C \"$MEMORY_DIR\" log --oneline\n```\n";
|
|
6581
6584
|
var init_system_prompt_memfs = () => {};
|
|
6582
6585
|
|
|
6583
6586
|
// src/utils/error.ts
|
|
@@ -6708,12 +6711,6 @@ async function loadMemoryBlocksFromMdx() {
|
|
|
6708
6711
|
if (frontmatter.description) {
|
|
6709
6712
|
block.description = frontmatter.description;
|
|
6710
6713
|
}
|
|
6711
|
-
if (frontmatter.limit) {
|
|
6712
|
-
const limit2 = parseInt(frontmatter.limit, 10);
|
|
6713
|
-
if (!Number.isNaN(limit2) && limit2 > 0) {
|
|
6714
|
-
block.limit = limit2;
|
|
6715
|
-
}
|
|
6716
|
-
}
|
|
6717
6714
|
if (READ_ONLY_BLOCK_LABELS.includes(label)) {
|
|
6718
6715
|
block.read_only = true;
|
|
6719
6716
|
}
|
|
@@ -6840,7 +6837,7 @@ var history_analyzer_default = `---
|
|
|
6840
6837
|
name: history-analyzer
|
|
6841
6838
|
description: Analyze Claude Code or Codex conversation history and directly update agent memory files with insights
|
|
6842
6839
|
tools: Read, Write, Bash, Glob, Grep
|
|
6843
|
-
skills:
|
|
6840
|
+
skills:
|
|
6844
6841
|
model: auto
|
|
6845
6842
|
memoryBlocks: none
|
|
6846
6843
|
mode: stateless
|
|
@@ -6858,19 +6855,64 @@ Your memory files form the parent agent's identity and knowledge. Follow these p
|
|
|
6858
6855
|
- **Generalize, don't memorize**: Distill patterns from repeated observations. "Always use uv, never pip (corrected 10+ times)" is valuable; a single offhand mention is not. Look for signal through repetition.
|
|
6859
6856
|
- **System/ is the core program**: Only durable, generalizable knowledge belongs in \`system/\`. Distilled preferences, behavioral rules, project gotchas, conventions enforced through corrections. Evidence trails, raw session summaries, and verbose context go outside \`system/\`.
|
|
6860
6857
|
- **Progressive disclosure**: Frontmatter descriptions should let the agent decide whether to load a file without reading it. Summaries and principles in \`system/\`; detail and evidence outside it, linked with \`[[path]]\`.
|
|
6861
|
-
- **Identity continuity**:
|
|
6858
|
+
- **Identity continuity**: This history IS the agent's past. These are memories of working with this user — you're reconstructing lived experience, not analyzing external data. Write findings as learned knowledge ("I've seen Sarah correct this 10+ times"), not research summaries ("The user appears to prefer...").
|
|
6862
6859
|
- **Preserve and connect**: If a memory file already has good content, extend it — don't replace it. Use \`[[path]]\` links to connect new findings to existing memory.
|
|
6860
|
+
- **Promote findings into canonical memory**: Don't leave durable insights trapped in generic ingestion files if they can be promoted into focused memory like \`system/human/identity.md\`, \`system/human/prefs/workflow.md\`, or \`system/<project>/gotchas.md\`.
|
|
6863
6861
|
|
|
6864
6862
|
## Goal
|
|
6865
6863
|
|
|
6866
|
-
Distill actionable knowledge from conversation history into well-organized memory.
|
|
6864
|
+
Distill actionable knowledge from conversation history into well-organized memory. You MUST produce findings in all three categories below — missing any category is a failure.
|
|
6865
|
+
|
|
6866
|
+
This is not a request for a thin recap. Your output should be detailed enough that the parent agent can use it in future sessions without rereading the history chunk.
|
|
6867
|
+
|
|
6868
|
+
### Required Output Categories
|
|
6869
|
+
|
|
6870
|
+
You MUST extract and document all three:
|
|
6871
|
+
|
|
6872
|
+
**1. User Personality & Identity** (REQUIRED)
|
|
6873
|
+
- How would you describe them as a person? (e.g., "pragmatic builder who values shipping over perfection")
|
|
6874
|
+
- What drives them? What are their goals? (e.g., "building tools that reduce friction for developers")
|
|
6875
|
+
- Communication style beyond just "direct" — do they joke? Use sarcasm? Have catchphrases?
|
|
6876
|
+
- Quirks, linguistic patterns, unique attributes
|
|
6877
|
+
- Pattern-match to common personas if applicable (e.g., "scrappy startup engineer", "meticulous architect")
|
|
6878
|
+
|
|
6879
|
+
**2. Hard Rules & Preferences** (REQUIRED)
|
|
6880
|
+
- Coding preferences with enforcement evidence (e.g., "Use uv — corrected 10+ times")
|
|
6881
|
+
- Workflow patterns (testing habits, commit style, tool choices)
|
|
6882
|
+
- What frustrates them and why
|
|
6883
|
+
- Explicit "always/never" statements
|
|
6884
|
+
|
|
6885
|
+
**3. Project Context** (REQUIRED)
|
|
6886
|
+
- Codebase structures, conventions, patterns
|
|
6887
|
+
- Gotchas discovered through debugging
|
|
6888
|
+
- Which files are safe to edit vs deprecated
|
|
6889
|
+
- Environment quirks
|
|
6890
|
+
|
|
6891
|
+
If you cannot extract meaningful findings for ANY category, explicitly state why (e.g., "Insufficient data for personality analysis — only 5 prompts, all about a single bug fix").
|
|
6892
|
+
|
|
6893
|
+
### Quality Bar
|
|
6867
6894
|
|
|
6868
|
-
|
|
6869
|
-
- **
|
|
6870
|
-
- **
|
|
6871
|
-
- **
|
|
6895
|
+
When sufficient data exists, aim to extract at least:
|
|
6896
|
+
- **5+ durable findings** for user personality / identity
|
|
6897
|
+
- **8+ durable findings** for hard rules / preferences
|
|
6898
|
+
- **8+ durable findings** for project context
|
|
6872
6899
|
|
|
6873
|
-
|
|
6900
|
+
If you produce materially fewer findings in a category, explain why the chunk truly lacked signal.
|
|
6901
|
+
|
|
6902
|
+
Avoid low-value summaries like:
|
|
6903
|
+
- "User is direct"
|
|
6904
|
+
- "Project uses TypeScript"
|
|
6905
|
+
- "Uses conventional commits"
|
|
6906
|
+
|
|
6907
|
+
These are insufficient unless paired with concrete operational detail, enforcement patterns, or repo-specific implications.
|
|
6908
|
+
|
|
6909
|
+
### What NOT to Store
|
|
6910
|
+
One-off events, session-by-session summaries, anything that can be retrieved from conversation history on demand.
|
|
6911
|
+
|
|
6912
|
+
### What TO Preserve
|
|
6913
|
+
Focus on understanding **why** the user reacted the way they did — what mistake or behavior triggered the correction? The pattern matters more than the quote. For example, don't just record "user said stop adding stuff" — record that the agent was over-engineering by adding abstractions when a simple flag change was needed. Quotes can serve as supporting evidence, but the real value is the behavioral pattern and what to do differently.
|
|
6914
|
+
|
|
6915
|
+
Keep specific correction counts ("corrected 10+ times"), specific file paths, and specific gotchas with context. Specificity is identity; vague summaries are forgettable.
|
|
6874
6916
|
|
|
6875
6917
|
## Workflow
|
|
6876
6918
|
|
|
@@ -6888,12 +6930,29 @@ git worktree add "$WORKTREE_DIR/$BRANCH_NAME" -b "$BRANCH_NAME"
|
|
|
6888
6930
|
If worktree creation fails (locked index), retry up to 3 times with backoff (sleep 2, 5, 10). Never delete \`.git/index.lock\` manually. All edits go in \`$WORKTREE_DIR/$BRANCH_NAME/\`.
|
|
6889
6931
|
|
|
6890
6932
|
### 2. Read existing memory
|
|
6891
|
-
|
|
6892
|
-
Read all files in your worktree's \`system/\` directory. Understand what's already there so you can extend it, not duplicate it.
|
|
6933
|
+
Read the memory files in your worktree, to understand what already exists in the memory filesystem.
|
|
6893
6934
|
|
|
6894
6935
|
### 3. Read and analyze history
|
|
6895
6936
|
|
|
6896
|
-
|
|
6937
|
+
Your prompt will specify a pre-split JSONL chunk file and its source format. Use these patterns to read it:
|
|
6938
|
+
|
|
6939
|
+
**Claude Code** (\`~/.claude/\`):
|
|
6940
|
+
- \`history.jsonl\` — each line: \`.display\` (prompt text), \`.timestamp\` (unix ms), \`.project\` (working dir), \`.sessionId\`
|
|
6941
|
+
- Session files at \`~/.claude/projects/<encoded-path>/<session-uuid>.jsonl\` (path encoding: \`/\` → \`-\`)
|
|
6942
|
+
- User messages: \`jq 'select(.type == "user") | .message.content'\`
|
|
6943
|
+
- Assistant text: \`jq 'select(.type == "assistant") | .message.content[] | select(.type == "text") | .text'\`
|
|
6944
|
+
- Tool calls: \`jq 'select(.type == "assistant") | .message.content[] | select(.type == "tool_use") | {name, input}'\`
|
|
6945
|
+
- Summaries: \`jq 'select(.type == "summary") | .summary'\`
|
|
6946
|
+
|
|
6947
|
+
**OpenAI Codex** (\`~/.codex/\`):
|
|
6948
|
+
- \`history.jsonl\` — each line: \`.text\` (prompt text), \`.ts\` (unix seconds) — no project path
|
|
6949
|
+
- Session files at \`~/.codex/sessions/<year>/<month>/<day>/rollout-*.jsonl\`
|
|
6950
|
+
- Session metadata (first line): \`jq 'select(.type == "session_meta") | .payload.cwd'\` (to get project dir)
|
|
6951
|
+
- User messages: \`jq 'select(.type == "event_msg" and .payload.type == "user_message") | .payload.message'\`
|
|
6952
|
+
- Assistant text: \`jq 'select(.type == "response_item" and .payload.type == "message") | .payload.content[] | select(.type == "output_text") | .text'\`
|
|
6953
|
+
- Tool calls: \`jq 'select(.type == "response_item" and .payload.type == "function_call") | {name: .payload.name, args: .payload.arguments}'\`
|
|
6954
|
+
|
|
6955
|
+
**Key format difference**: Claude uses \`.timestamp\` (milliseconds) and \`.display\`; Codex uses \`.ts\` (seconds) and \`.text\`.
|
|
6897
6956
|
|
|
6898
6957
|
Look for **repeated patterns**, not isolated events:
|
|
6899
6958
|
- Count correction frequency — 10 corrections on the same topic >> 1 mention
|
|
@@ -6901,38 +6960,70 @@ Look for **repeated patterns**, not isolated events:
|
|
|
6901
6960
|
- Implicit preferences revealed by what commands they run, what patterns they follow
|
|
6902
6961
|
- Frustration signals — "no", "undo", rapid corrections, /clear, model switches
|
|
6903
6962
|
|
|
6963
|
+
**For personality analysis**, look beyond the reaction to what caused it:
|
|
6964
|
+
- What agent behaviors triggered corrections? (over-engineering, wrong tool, verbose explanations, etc.)
|
|
6965
|
+
- What agent behaviors got positive responses? (fast fixes, running tests unprompted, etc.)
|
|
6966
|
+
- How do they phrase requests? (imperative, collaborative, questioning?)
|
|
6967
|
+
- What topics excite them vs bore them?
|
|
6968
|
+
- What's their tolerance for explanation vs "just fix it"?
|
|
6969
|
+
- How do they handle mistakes — their own and the agent's?
|
|
6970
|
+
|
|
6904
6971
|
### 4. Update memory files
|
|
6905
6972
|
|
|
6906
6973
|
**Content placement:**
|
|
6907
6974
|
- \`system/\`: Generalized rules, distilled preferences, project gotchas, identity. Keep files lean — bullets, short lines, scannable.
|
|
6908
6975
|
- Outside \`system/\`: Evidence, detailed history, verbose context. Link from system/ with \`[[path]]\`.
|
|
6909
6976
|
|
|
6977
|
+
**Preferred canonical paths:**
|
|
6978
|
+
- \`system/human/identity.md\`
|
|
6979
|
+
- \`system/human/prefs/communication.md\`
|
|
6980
|
+
- \`system/human/prefs/workflow.md\`
|
|
6981
|
+
- \`system/human/prefs/coding.md\`
|
|
6982
|
+
- \`system/<project>/conventions.md\`
|
|
6983
|
+
- \`system/<project>/gotchas.md\`
|
|
6984
|
+
|
|
6985
|
+
If the current memory uses a more compressed layout, extend it carefully, but prefer splitting into these focused files when there is enough material to justify the move.
|
|
6986
|
+
|
|
6910
6987
|
**File structure:**
|
|
6911
6988
|
- Use the project's **real name** as directory prefix (e.g. \`my-app/conventions.md\`), not generic \`project/\`
|
|
6912
6989
|
- One concept per file, nested with \`/\` paths
|
|
6913
6990
|
- Every file needs a meaningful \`description\` in frontmatter
|
|
6914
6991
|
- Write for the agent's future self — clean, actionable, no clutter
|
|
6915
6992
|
|
|
6993
|
+
Each durable finding should include at least one of:
|
|
6994
|
+
- correction frequency or intensity
|
|
6995
|
+
- concrete commands that worked or failed
|
|
6996
|
+
- concrete file or directory paths
|
|
6997
|
+
- date range or source reference for future lookup
|
|
6998
|
+
- why the rule matters in practice
|
|
6999
|
+
|
|
6916
7000
|
You can also cite the files if you want to note where something came from (e.g. \`(from: ~/.claude/history.jsonl)\`).
|
|
6917
7001
|
|
|
6918
7002
|
### 5. Commit
|
|
6919
7003
|
|
|
7004
|
+
Before writing the commit, resolve the actual ID values:
|
|
7005
|
+
\`\`\`bash
|
|
7006
|
+
echo "AGENT_ID=$LETTA_AGENT_ID"
|
|
7007
|
+
echo "PARENT_AGENT_ID=$LETTA_PARENT_AGENT_ID"
|
|
7008
|
+
\`\`\`
|
|
7009
|
+
|
|
7010
|
+
Use the printed values (e.g., \`agent-abc123...\`) in the trailers. If a variable is empty or unset, omit that trailer. Never write a literal variable name like \`$LETTA_AGENT_ID\` or \`$AGENT_ID\` in the commit message.
|
|
7011
|
+
|
|
6920
7012
|
\`\`\`bash
|
|
6921
7013
|
cd $WORKTREE_DIR/$BRANCH_NAME
|
|
6922
7014
|
git add -A
|
|
6923
|
-
git commit -m "<type>(history-analyzer):
|
|
7015
|
+
git commit --author="History Analyzer <<ACTUAL_AGENT_ID>@letta.com>" -m "<type>(history-analyzer): <summary> ⏳
|
|
6924
7016
|
|
|
6925
7017
|
Source: [file path] ([N] prompts, [DATE RANGE])
|
|
6926
|
-
|
|
6927
|
-
|
|
7018
|
+
|
|
7019
|
+
Updates:
|
|
7020
|
+
- <what changed and why>
|
|
6928
7021
|
|
|
6929
7022
|
Generated-By: Letta Code
|
|
6930
7023
|
Agent-ID: <ACTUAL_AGENT_ID>
|
|
6931
7024
|
Parent-Agent-ID: <ACTUAL_PARENT_AGENT_ID>"
|
|
6932
7025
|
\`\`\`
|
|
6933
7026
|
|
|
6934
|
-
Resolve \`ACTUAL_AGENT_ID\` and \`ACTUAL_PARENT_AGENT_ID\` by running \`echo $LETTA_AGENT_ID\` and \`echo $LETTA_PARENT_AGENT_ID\` first. Never write literal variable names in the commit message. Omit trailers if the variable is empty.
|
|
6935
|
-
|
|
6936
7027
|
**Commit types**: \`chore\` (routine ingestion), \`feat\` (new memory topics), \`refactor\` (reorganizing by domain).
|
|
6937
7028
|
|
|
6938
7029
|
## Rules
|
|
@@ -6940,7 +7031,8 @@ Resolve \`ACTUAL_AGENT_ID\` and \`ACTUAL_PARENT_AGENT_ID\` by running \`echo $LE
|
|
|
6940
7031
|
- Work in your worktree — do NOT edit the memory dir directly
|
|
6941
7032
|
- Do NOT merge into main — the parent agent handles merging
|
|
6942
7033
|
- Preserve existing content — extend or refine, don't replace
|
|
6943
|
-
-
|
|
7034
|
+
- Preserve specificity — specific quotes, correction counts, and file paths are more valuable than vague summaries. Don't compress away the details that give the parent agent its character and grounding.
|
|
7035
|
+
- **REQUIRED**: You MUST produce findings for all three output categories (Personality, Rules, Project). If any category lacks data, explicitly state why.
|
|
6944
7036
|
`;
|
|
6945
7037
|
var init_history_analyzer = () => {};
|
|
6946
7038
|
|
|
@@ -53756,7 +53848,7 @@ If a directory has more than 1,000 entries, only the first 1,000 will be shown.`
|
|
|
53756
53848
|
var init_LS = () => {};
|
|
53757
53849
|
|
|
53758
53850
|
// src/tools/descriptions/Memory.md
|
|
53759
|
-
var Memory_default =
|
|
53851
|
+
var Memory_default = "# Memory\nA convinience tool for memories stored in the memory directory (`$MEMORY_DIR`) that automatically commits and pushes changes. \n\nFiles stored inside of `system/` eventually become part of the agent's system prompt, so are always in the context window and do not need to be re-read. Other files only have metadata in the system prompt, so may need to be explicitly read to be updated. \n\nSupported operations on memory files: \n- `str_replace`\n- `insert`\n- `delete` (files, or directories recursively)\n- `rename` (path rename only)\n- `update_description`\n- `create`\nMore general operations can be performanced through directory modifying the files. \n\nPath formats accepted:\n- relative memory file paths (e.g. `system/contacts.md`, `reference/project/team.md`)\n- absolute paths only when they are inside `$MEMORY_DIR`\n\nNote: absolute paths outside `$MEMORY_DIR` are rejected.\n\nWhen creating or deleting files, check for `[[path]]` references in other memory files that may need to be added or updated. Keeping references consistent ensures future discoverability.\n\nExamples:\n\n```python\n# Replace text in a memory file \nmemory(command=\"str_replace\", reason=\"Update theme preference\", path=\"system/human/preferences.md\", old_string=\"theme: dark\", new_string=\"theme: light\")\n\n# Insert text at line 5\nmemory(command=\"insert\", reason=\"Add note about meeting\", path=\"reference/history/meeting-notes.md\", insert_line=5, insert_text=\"New note here\")\n\n# Delete a memory file \nmemory(command=\"delete\", reason=\"Remove stale notes\", path=\"reference/history/old_notes.md\")\n\n# Rename a memory file \nmemory(command=\"rename\", reason=\"Promote temp notes\", old_path=\"reference/history/temp.md\", new_path=\"reference/history/permanent.md\")\n\n# Update a block description\nmemory(command=\"update_description\", reason=\"Clarify coding prefs block\", path=\"system/human/prefs/coding.md\", description=\"Dr. Wooders' coding preferences.\")\n\n# Create a block with starting text\nmemory(command=\"create\", reason=\"Track coding preferences\", path=\"system/human/prefs/coding.md\", description=\"The user's coding preferences.\", file_text=\"The user seems to add type hints to all of their Python code.\")\n\n# Create an empty block\nmemory(command=\"create\", reason=\"Create coding preferences block\", path=\"reference/history/coding_preferences.md\", description=\"The user's coding preferences.\")\n```\n";
|
|
53760
53852
|
var init_Memory = () => {};
|
|
53761
53853
|
|
|
53762
53854
|
// src/tools/descriptions/MemoryApplyPatch.md
|
|
@@ -65799,6 +65891,9 @@ function parseResultFromStdout(stdout, agentId) {
|
|
|
65799
65891
|
};
|
|
65800
65892
|
}
|
|
65801
65893
|
}
|
|
65894
|
+
function resolveSubagentWorkingDirectory(env3 = process.env, fallbackCwd = process.cwd()) {
|
|
65895
|
+
return env3.USER_CWD || fallbackCwd;
|
|
65896
|
+
}
|
|
65802
65897
|
function resolveSubagentLauncher(cliArgs, options = {}) {
|
|
65803
65898
|
const env3 = options.env ?? process.env;
|
|
65804
65899
|
const argv = options.argv ?? process.argv;
|
|
@@ -65913,8 +66008,9 @@ async function executeSubagent(type, config, model, userPrompt, baseURL, subagen
|
|
|
65913
66008
|
const settings = await settingsManager.getSettingsWithSecureTokens();
|
|
65914
66009
|
const inheritedApiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
|
|
65915
66010
|
const inheritedBaseUrl = process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL;
|
|
66011
|
+
const subagentWorkingDirectory = resolveSubagentWorkingDirectory();
|
|
65916
66012
|
const proc2 = spawn4(launcher.command, launcher.args, {
|
|
65917
|
-
cwd:
|
|
66013
|
+
cwd: subagentWorkingDirectory,
|
|
65918
66014
|
env: {
|
|
65919
66015
|
...process.env,
|
|
65920
66016
|
...inheritedApiKey && { LETTA_API_KEY: inheritedApiKey },
|
|
@@ -77097,6 +77193,7 @@ function requestApprovalOverWS(runtime, socket, requestId, controlRequest) {
|
|
|
77097
77193
|
controlRequest
|
|
77098
77194
|
});
|
|
77099
77195
|
runtime.listener.approvalRuntimeKeyByRequestId.set(requestId, runtime.key);
|
|
77196
|
+
runtime.lastStopReason = "requires_approval";
|
|
77100
77197
|
setLoopStatus(runtime, "WAITING_ON_APPROVAL");
|
|
77101
77198
|
emitLoopStatusIfOpen(runtime.listener, {
|
|
77102
77199
|
agent_id: runtime.agentId,
|
|
@@ -77565,6 +77662,74 @@ var init_permissionMode = __esm(() => {
|
|
|
77565
77662
|
init_remote_settings();
|
|
77566
77663
|
});
|
|
77567
77664
|
|
|
77665
|
+
// src/websocket/listener/recoverable-notices.ts
|
|
77666
|
+
function getRecoverableStatusNoticeVisibility(kind) {
|
|
77667
|
+
switch (kind) {
|
|
77668
|
+
case "stale_approval_conflict_recovery":
|
|
77669
|
+
return "debug_only";
|
|
77670
|
+
default:
|
|
77671
|
+
return "transcript";
|
|
77672
|
+
}
|
|
77673
|
+
}
|
|
77674
|
+
function getRecoverableRetryNoticeVisibility(kind, attempt) {
|
|
77675
|
+
switch (kind) {
|
|
77676
|
+
case "transient_provider_retry":
|
|
77677
|
+
return attempt === 1 ? "debug_only" : "transcript";
|
|
77678
|
+
default:
|
|
77679
|
+
return "transcript";
|
|
77680
|
+
}
|
|
77681
|
+
}
|
|
77682
|
+
function isDesktopDebugPanelMirrorEnabled() {
|
|
77683
|
+
return process.env.LETTA_DESKTOP_DEBUG_PANEL === "1";
|
|
77684
|
+
}
|
|
77685
|
+
function mirrorRecoverableNoticeToDesktopDebugPanel(message) {
|
|
77686
|
+
if (!isDesktopDebugPanelMirrorEnabled()) {
|
|
77687
|
+
return;
|
|
77688
|
+
}
|
|
77689
|
+
try {
|
|
77690
|
+
process.stderr.write(`${DESKTOP_DEBUG_PANEL_INFO_PREFIX} ${message}
|
|
77691
|
+
`);
|
|
77692
|
+
} catch {}
|
|
77693
|
+
}
|
|
77694
|
+
function emitRecoverableStatusNotice(socket, runtime, params) {
|
|
77695
|
+
const visibility = getRecoverableStatusNoticeVisibility(params.kind);
|
|
77696
|
+
if (visibility === "debug_only") {
|
|
77697
|
+
debugLog("recovery", `Debug-only lifecycle notice (${params.kind}): ${params.message}`);
|
|
77698
|
+
mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
|
|
77699
|
+
return;
|
|
77700
|
+
}
|
|
77701
|
+
emitStatusDelta(socket, runtime, {
|
|
77702
|
+
message: params.message,
|
|
77703
|
+
level: params.level,
|
|
77704
|
+
runId: params.runId,
|
|
77705
|
+
agentId: params.agentId,
|
|
77706
|
+
conversationId: params.conversationId
|
|
77707
|
+
});
|
|
77708
|
+
}
|
|
77709
|
+
function emitRecoverableRetryNotice(socket, runtime, params) {
|
|
77710
|
+
const visibility = getRecoverableRetryNoticeVisibility(params.kind, params.attempt);
|
|
77711
|
+
if (visibility === "debug_only") {
|
|
77712
|
+
debugLog("recovery", `Debug-only retry notice (${params.kind}, attempt ${params.attempt}/${params.maxAttempts}): ${params.message}`);
|
|
77713
|
+
mirrorRecoverableNoticeToDesktopDebugPanel(params.message);
|
|
77714
|
+
return;
|
|
77715
|
+
}
|
|
77716
|
+
emitRetryDelta(socket, runtime, {
|
|
77717
|
+
message: params.message,
|
|
77718
|
+
reason: params.reason,
|
|
77719
|
+
attempt: params.attempt,
|
|
77720
|
+
maxAttempts: params.maxAttempts,
|
|
77721
|
+
delayMs: params.delayMs,
|
|
77722
|
+
runId: params.runId,
|
|
77723
|
+
agentId: params.agentId,
|
|
77724
|
+
conversationId: params.conversationId
|
|
77725
|
+
});
|
|
77726
|
+
}
|
|
77727
|
+
var DESKTOP_DEBUG_PANEL_INFO_PREFIX = "[LETTA_DESKTOP_DEBUG_PANEL_INFO]";
|
|
77728
|
+
var init_recoverable_notices = __esm(async () => {
|
|
77729
|
+
init_debug();
|
|
77730
|
+
await init_protocol_outbound();
|
|
77731
|
+
});
|
|
77732
|
+
|
|
77568
77733
|
// node_modules/diff/libesm/diff/base.js
|
|
77569
77734
|
class Diff {
|
|
77570
77735
|
diff(oldStr, newStr, options = {}) {
|
|
@@ -79646,9 +79811,6 @@ async function resolveStaleApprovals(runtime, socket, abortSignal, deps = {}) {
|
|
|
79646
79811
|
];
|
|
79647
79812
|
let pendingNeedsUserInput = [...needsUserInput];
|
|
79648
79813
|
if (pendingNeedsUserInput.length > 0) {
|
|
79649
|
-
runtime.lastStopReason = "requires_approval";
|
|
79650
|
-
setLoopStatus(runtime, "WAITING_ON_APPROVAL", scope);
|
|
79651
|
-
emitRuntimeStateUpdates(runtime, scope);
|
|
79652
79814
|
while (pendingNeedsUserInput.length > 0) {
|
|
79653
79815
|
const ac = pendingNeedsUserInput.shift();
|
|
79654
79816
|
if (!ac) {
|
|
@@ -80177,11 +80339,6 @@ async function handleApprovalStop(params) {
|
|
|
80177
80339
|
if (shouldInterrupt()) {
|
|
80178
80340
|
return interruptTermination();
|
|
80179
80341
|
}
|
|
80180
|
-
runtime.lastStopReason = "requires_approval";
|
|
80181
|
-
setLoopStatus(runtime, "WAITING_ON_APPROVAL", {
|
|
80182
|
-
agent_id: agentId,
|
|
80183
|
-
conversation_id: conversationId
|
|
80184
|
-
});
|
|
80185
80342
|
while (pendingNeedsUserInput.length > 0) {
|
|
80186
80343
|
const ac = pendingNeedsUserInput.shift();
|
|
80187
80344
|
if (!ac) {
|
|
@@ -80817,7 +80974,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
80817
80974
|
latestErrorText
|
|
80818
80975
|
})) {
|
|
80819
80976
|
postStopApprovalRecoveryRetries += 1;
|
|
80820
|
-
|
|
80977
|
+
emitRecoverableStatusNotice(socket, runtime, {
|
|
80978
|
+
kind: "stale_approval_conflict_recovery",
|
|
80821
80979
|
message: "Recovering from stale approval conflict after interrupted/reconnected turn",
|
|
80822
80980
|
level: "warning",
|
|
80823
80981
|
runId: lastRunId || undefined,
|
|
@@ -80913,7 +81071,8 @@ async function handleIncomingMessage(msg, socket, runtime, onStatusChange, conne
|
|
|
80913
81071
|
detail: errorDetail
|
|
80914
81072
|
});
|
|
80915
81073
|
const retryMessage = getRetryStatusMessage(errorDetail) || `LLM API error encountered, retrying (attempt ${attempt}/${LLM_API_ERROR_MAX_RETRIES})...`;
|
|
80916
|
-
|
|
81074
|
+
emitRecoverableRetryNotice(socket, runtime, {
|
|
81075
|
+
kind: "transient_provider_retry",
|
|
80917
81076
|
message: retryMessage,
|
|
80918
81077
|
reason: "llm_api_error",
|
|
80919
81078
|
attempt,
|
|
@@ -81113,6 +81272,7 @@ var init_turn = __esm(async () => {
|
|
|
81113
81272
|
init_toolset(),
|
|
81114
81273
|
init_interrupts(),
|
|
81115
81274
|
init_protocol_outbound(),
|
|
81275
|
+
init_recoverable_notices(),
|
|
81116
81276
|
init_recovery(),
|
|
81117
81277
|
init_send(),
|
|
81118
81278
|
init_turn_approval()
|
|
@@ -81436,7 +81596,7 @@ function buildLoopStatus(runtime, params) {
|
|
|
81436
81596
|
const conversationRuntime = getConversationRuntime(listener, scopedAgentId, scopedConversationId);
|
|
81437
81597
|
const interruptedCacheActive = hasInterruptedCacheForScope(listener, scope);
|
|
81438
81598
|
const recovered = getRecoveredApprovalStateForScope(listener, scope);
|
|
81439
|
-
const status = interruptedCacheActive ? !conversationRuntime?.isProcessing ? "WAITING_ON_INPUT" : conversationRuntime?.loopStatus ?? "WAITING_ON_INPUT" : recovered && recovered.pendingRequestIds.size > 0 && conversationRuntime?.loopStatus === "WAITING_ON_INPUT" ? "WAITING_ON_APPROVAL" : conversationRuntime?.loopStatus ?? "WAITING_ON_INPUT";
|
|
81599
|
+
const status = interruptedCacheActive ? !conversationRuntime?.isProcessing ? "WAITING_ON_INPUT" : conversationRuntime?.loopStatus === "WAITING_ON_APPROVAL" ? "WAITING_ON_INPUT" : conversationRuntime?.loopStatus ?? "WAITING_ON_INPUT" : recovered && recovered.pendingRequestIds.size > 0 && conversationRuntime?.loopStatus === "WAITING_ON_INPUT" ? "WAITING_ON_APPROVAL" : conversationRuntime?.loopStatus ?? "WAITING_ON_INPUT";
|
|
81440
81600
|
return {
|
|
81441
81601
|
status,
|
|
81442
81602
|
active_run_ids: interruptedCacheActive && !conversationRuntime?.isProcessing ? [] : conversationRuntime?.activeRunId ? [conversationRuntime.activeRunId] : []
|
|
@@ -81598,9 +81758,6 @@ function resolveSubagentScopeForSnapshot(runtime, scope) {
|
|
|
81598
81758
|
function buildSubagentSnapshot(runtime, scope) {
|
|
81599
81759
|
const runtimeScope = resolveSubagentScopeForSnapshot(runtime, scope);
|
|
81600
81760
|
return getSubagents().filter((a) => {
|
|
81601
|
-
if (a.status !== "pending" && a.status !== "running") {
|
|
81602
|
-
return false;
|
|
81603
|
-
}
|
|
81604
81761
|
if (a.silent && a.isBackground !== true) {
|
|
81605
81762
|
return false;
|
|
81606
81763
|
}
|
|
@@ -85336,7 +85493,7 @@ var init_skills2 = __esm(() => {
|
|
|
85336
85493
|
var exports_fs = {};
|
|
85337
85494
|
__export(exports_fs, {
|
|
85338
85495
|
writeJsonFile: () => writeJsonFile,
|
|
85339
|
-
writeFile: () =>
|
|
85496
|
+
writeFile: () => writeFile7,
|
|
85340
85497
|
readJsonFile: () => readJsonFile,
|
|
85341
85498
|
readFile: () => readFile9,
|
|
85342
85499
|
mkdir: () => mkdir6,
|
|
@@ -85352,7 +85509,7 @@ import { dirname as dirname13 } from "node:path";
|
|
|
85352
85509
|
async function readFile9(path23) {
|
|
85353
85510
|
return fsReadFileSync2(path23, { encoding: "utf-8" });
|
|
85354
85511
|
}
|
|
85355
|
-
async function
|
|
85512
|
+
async function writeFile7(path23, content) {
|
|
85356
85513
|
const dir = dirname13(path23);
|
|
85357
85514
|
if (!existsSync25(dir)) {
|
|
85358
85515
|
mkdirSync17(dir, { recursive: true });
|
|
@@ -85373,7 +85530,7 @@ async function writeJsonFile(path23, data, options) {
|
|
|
85373
85530
|
const indent = options?.indent ?? 2;
|
|
85374
85531
|
const content = `${JSON.stringify(data, null, indent)}
|
|
85375
85532
|
`;
|
|
85376
|
-
await
|
|
85533
|
+
await writeFile7(path23, content);
|
|
85377
85534
|
}
|
|
85378
85535
|
var init_fs2 = () => {};
|
|
85379
85536
|
|
|
@@ -85398,7 +85555,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85398
85555
|
}
|
|
85399
85556
|
const wasRaw = process.stdin.isRaw;
|
|
85400
85557
|
const wasFlowing = process.stdin.readableFlowing;
|
|
85401
|
-
return new Promise((
|
|
85558
|
+
return new Promise((resolve26) => {
|
|
85402
85559
|
let response = "";
|
|
85403
85560
|
let resolved = false;
|
|
85404
85561
|
const cleanup = () => {
|
|
@@ -85415,7 +85572,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85415
85572
|
};
|
|
85416
85573
|
const timeout = setTimeout(() => {
|
|
85417
85574
|
cleanup();
|
|
85418
|
-
|
|
85575
|
+
resolve26(null);
|
|
85419
85576
|
}, timeoutMs);
|
|
85420
85577
|
const onData = (data) => {
|
|
85421
85578
|
response += data.toString();
|
|
@@ -85425,7 +85582,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85425
85582
|
if (match3) {
|
|
85426
85583
|
clearTimeout(timeout);
|
|
85427
85584
|
cleanup();
|
|
85428
|
-
|
|
85585
|
+
resolve26({
|
|
85429
85586
|
r: parseHexComponent(match3[1] ?? "0"),
|
|
85430
85587
|
g: parseHexComponent(match3[2] ?? "0"),
|
|
85431
85588
|
b: parseHexComponent(match3[3] ?? "0")
|
|
@@ -85440,7 +85597,7 @@ async function queryTerminalBackground(timeoutMs = 100) {
|
|
|
85440
85597
|
} catch {
|
|
85441
85598
|
clearTimeout(timeout);
|
|
85442
85599
|
cleanup();
|
|
85443
|
-
|
|
85600
|
+
resolve26(null);
|
|
85444
85601
|
}
|
|
85445
85602
|
});
|
|
85446
85603
|
}
|
|
@@ -86649,10 +86806,10 @@ __export(exports_setup, {
|
|
|
86649
86806
|
runSetup: () => runSetup
|
|
86650
86807
|
});
|
|
86651
86808
|
async function runSetup() {
|
|
86652
|
-
return new Promise((
|
|
86809
|
+
return new Promise((resolve27) => {
|
|
86653
86810
|
const { waitUntilExit } = render_default(import_react32.default.createElement(SetupUI, {
|
|
86654
86811
|
onComplete: () => {
|
|
86655
|
-
|
|
86812
|
+
resolve27();
|
|
86656
86813
|
}
|
|
86657
86814
|
}));
|
|
86658
86815
|
waitUntilExit().catch((error) => {
|
|
@@ -87127,6 +87284,20 @@ function validateRegistryHandleOrThrow2(handle) {
|
|
|
87127
87284
|
}
|
|
87128
87285
|
}
|
|
87129
87286
|
|
|
87287
|
+
// src/runtime-context.ts
|
|
87288
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
87289
|
+
function getCurrentWorkingDirectory() {
|
|
87290
|
+
const workingDirectory = runtimeContextStorage.getStore()?.workingDirectory;
|
|
87291
|
+
if (typeof workingDirectory === "string" && workingDirectory.length > 0) {
|
|
87292
|
+
return workingDirectory;
|
|
87293
|
+
}
|
|
87294
|
+
return process.env.USER_CWD || process.cwd();
|
|
87295
|
+
}
|
|
87296
|
+
var runtimeContextStorage;
|
|
87297
|
+
var init_runtime_context = __esm(() => {
|
|
87298
|
+
runtimeContextStorage = new AsyncLocalStorage;
|
|
87299
|
+
});
|
|
87300
|
+
|
|
87130
87301
|
// src/agent/github-utils.ts
|
|
87131
87302
|
var exports_github_utils = {};
|
|
87132
87303
|
__export(exports_github_utils, {
|
|
@@ -87167,11 +87338,11 @@ __export(exports_import, {
|
|
|
87167
87338
|
extractSkillsFromAf: () => extractSkillsFromAf
|
|
87168
87339
|
});
|
|
87169
87340
|
import { createReadStream } from "node:fs";
|
|
87170
|
-
import { chmod, mkdir as mkdir7, readFile as readFile10, writeFile as
|
|
87171
|
-
import { dirname as dirname14, resolve as
|
|
87341
|
+
import { chmod, mkdir as mkdir7, readFile as readFile10, writeFile as writeFile8 } from "node:fs/promises";
|
|
87342
|
+
import { dirname as dirname14, resolve as resolve27 } from "node:path";
|
|
87172
87343
|
async function importAgentFromFile(options) {
|
|
87173
87344
|
const client = await getClient();
|
|
87174
|
-
const resolvedPath =
|
|
87345
|
+
const resolvedPath = resolve27(options.filePath);
|
|
87175
87346
|
const file = createReadStream(resolvedPath);
|
|
87176
87347
|
const importResponse = await client.agents.importFile({
|
|
87177
87348
|
file,
|
|
@@ -87206,7 +87377,7 @@ async function extractSkillsFromAf(afPath, destDir) {
|
|
|
87206
87377
|
return [];
|
|
87207
87378
|
}
|
|
87208
87379
|
for (const skill2 of afData.skills) {
|
|
87209
|
-
const skillDir =
|
|
87380
|
+
const skillDir = resolve27(destDir, skill2.name);
|
|
87210
87381
|
await mkdir7(skillDir, { recursive: true });
|
|
87211
87382
|
if (skill2.files) {
|
|
87212
87383
|
await writeSkillFiles(skillDir, skill2.files);
|
|
@@ -87226,9 +87397,9 @@ async function writeSkillFiles(skillDir, files) {
|
|
|
87226
87397
|
}
|
|
87227
87398
|
}
|
|
87228
87399
|
async function writeSkillFile(skillDir, filePath, content) {
|
|
87229
|
-
const fullPath =
|
|
87400
|
+
const fullPath = resolve27(skillDir, filePath);
|
|
87230
87401
|
await mkdir7(dirname14(fullPath), { recursive: true });
|
|
87231
|
-
await
|
|
87402
|
+
await writeFile8(fullPath, content, "utf-8");
|
|
87232
87403
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
87233
87404
|
if (isScript) {
|
|
87234
87405
|
try {
|
|
@@ -87281,7 +87452,7 @@ function parseRegistryHandle(handle) {
|
|
|
87281
87452
|
async function importAgentFromRegistry(options) {
|
|
87282
87453
|
const { tmpdir: tmpdir4 } = await import("node:os");
|
|
87283
87454
|
const { join: join35 } = await import("node:path");
|
|
87284
|
-
const { writeFile:
|
|
87455
|
+
const { writeFile: writeFile9, unlink: unlink3 } = await import("node:fs/promises");
|
|
87285
87456
|
const { author, name } = parseRegistryHandle(options.handle);
|
|
87286
87457
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
|
|
87287
87458
|
const response = await fetch(rawUrl);
|
|
@@ -87293,7 +87464,7 @@ async function importAgentFromRegistry(options) {
|
|
|
87293
87464
|
}
|
|
87294
87465
|
const afContent = await response.text();
|
|
87295
87466
|
const tempPath = join35(tmpdir4(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
87296
|
-
await
|
|
87467
|
+
await writeFile9(tempPath, afContent, "utf-8");
|
|
87297
87468
|
try {
|
|
87298
87469
|
const result = await importAgentFromFile({
|
|
87299
87470
|
filePath: tempPath,
|
|
@@ -87524,7 +87695,7 @@ async function prepareHeadlessToolExecutionContext(params) {
|
|
|
87524
87695
|
agentId: params.agentId,
|
|
87525
87696
|
conversationId: params.conversationId,
|
|
87526
87697
|
overrideModel: params.overrideModel,
|
|
87527
|
-
workingDirectory:
|
|
87698
|
+
workingDirectory: getCurrentWorkingDirectory(),
|
|
87528
87699
|
exclude: ["AskUserQuestion"]
|
|
87529
87700
|
});
|
|
87530
87701
|
return {
|
|
@@ -87532,6 +87703,20 @@ async function prepareHeadlessToolExecutionContext(params) {
|
|
|
87532
87703
|
availableTools: preparedToolContext.preparedToolContext.clientTools.map((tool) => tool.name)
|
|
87533
87704
|
};
|
|
87534
87705
|
}
|
|
87706
|
+
async function flushAndExit(code) {
|
|
87707
|
+
const flushWritable = (stream2) => new Promise((resolve28) => {
|
|
87708
|
+
if (stream2.destroyed || stream2.writableEnded) {
|
|
87709
|
+
resolve28();
|
|
87710
|
+
return;
|
|
87711
|
+
}
|
|
87712
|
+
stream2.write("", () => resolve28());
|
|
87713
|
+
});
|
|
87714
|
+
await Promise.allSettled([
|
|
87715
|
+
flushWritable(process.stdout),
|
|
87716
|
+
flushWritable(process.stderr)
|
|
87717
|
+
]);
|
|
87718
|
+
process.exit(code);
|
|
87719
|
+
}
|
|
87535
87720
|
async function handleHeadlessCommand(parsedArgs, model, skillsDirectoryOverride, skillSourcesOverride, systemInfoReminderEnabledOverride) {
|
|
87536
87721
|
const { values, positionals } = parsedArgs;
|
|
87537
87722
|
telemetry.setSurface("headless");
|
|
@@ -87602,6 +87787,7 @@ In headless mode, use:
|
|
|
87602
87787
|
let forceNewConversation = values.new ?? false;
|
|
87603
87788
|
const fromAgentId = values["from-agent"];
|
|
87604
87789
|
let agent = null;
|
|
87790
|
+
let autoEnableMemfsForFreshAgent = false;
|
|
87605
87791
|
let specifiedAgentId = values.agent;
|
|
87606
87792
|
const specifiedAgentName = values.name;
|
|
87607
87793
|
let specifiedConversationId = values.conversation;
|
|
@@ -87884,7 +88070,7 @@ In headless mode, use:
|
|
|
87884
88070
|
}
|
|
87885
88071
|
if (!agent && forceNew) {
|
|
87886
88072
|
const updateArgs = getModelUpdateArgs2(model);
|
|
87887
|
-
const { isLettaCloud: isLettaCloud2
|
|
88073
|
+
const { isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
87888
88074
|
const willAutoEnableMemfs = shouldAutoEnableMemfsForNewAgent && await isLettaCloud2();
|
|
87889
88075
|
const effectiveMemoryMode = requestedMemoryPromptMode ?? (willAutoEnableMemfs ? "memfs" : undefined);
|
|
87890
88076
|
const createOptions = {
|
|
@@ -87904,13 +88090,11 @@ In headless mode, use:
|
|
|
87904
88090
|
};
|
|
87905
88091
|
const result = await createAgent(createOptions);
|
|
87906
88092
|
agent = result.agent;
|
|
87907
|
-
|
|
87908
|
-
await enableMemfsIfCloud2(agent.id);
|
|
87909
|
-
}
|
|
88093
|
+
autoEnableMemfsForFreshAgent = willAutoEnableMemfs;
|
|
87910
88094
|
}
|
|
87911
88095
|
if (!agent) {
|
|
87912
88096
|
await settingsManager.loadLocalProjectSettings();
|
|
87913
|
-
const localAgentId = settingsManager.getLocalLastAgentId(
|
|
88097
|
+
const localAgentId = settingsManager.getLocalLastAgentId(getCurrentWorkingDirectory());
|
|
87914
88098
|
if (localAgentId) {
|
|
87915
88099
|
try {
|
|
87916
88100
|
agent = await client.agents.retrieve(localAgentId);
|
|
@@ -87965,13 +88149,14 @@ In headless mode, use:
|
|
|
87965
88149
|
let conversationId;
|
|
87966
88150
|
let effectiveReflectionSettings;
|
|
87967
88151
|
const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
|
88152
|
+
const startupMemfsFlag = autoEnableMemfsForFreshAgent ? true : memfsFlag;
|
|
87968
88153
|
let memfsBgPromise;
|
|
87969
88154
|
const secretsAgentId = agent?.id;
|
|
87970
88155
|
const secretsInitPromise = secretsAgentId ? init_secretsStore().then(() => exports_secretsStore).then(({ initSecretsFromServer: initSecretsFromServer2 }) => initSecretsFromServer2(secretsAgentId)) : Promise.resolve();
|
|
87971
88156
|
if (memfsStartupPolicy === "skip") {
|
|
87972
88157
|
try {
|
|
87973
88158
|
const { applyMemfsFlags: applyMemfsFlags2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
87974
|
-
await applyMemfsFlags2(agent.id,
|
|
88159
|
+
await applyMemfsFlags2(agent.id, startupMemfsFlag, noMemfsFlag, {
|
|
87975
88160
|
pullOnExistingRepo: false,
|
|
87976
88161
|
agentTags: agent.tags,
|
|
87977
88162
|
skipPromptUpdate: forceNew
|
|
@@ -87983,7 +88168,7 @@ In headless mode, use:
|
|
|
87983
88168
|
}
|
|
87984
88169
|
} else if (memfsStartupPolicy === "background") {
|
|
87985
88170
|
const { applyMemfsFlags: applyMemfsFlags2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
87986
|
-
memfsBgPromise = applyMemfsFlags2(agent.id,
|
|
88171
|
+
memfsBgPromise = applyMemfsFlags2(agent.id, startupMemfsFlag, noMemfsFlag, {
|
|
87987
88172
|
pullOnExistingRepo: true,
|
|
87988
88173
|
agentTags: agent.tags,
|
|
87989
88174
|
skipPromptUpdate: forceNew
|
|
@@ -87994,7 +88179,7 @@ In headless mode, use:
|
|
|
87994
88179
|
} else {
|
|
87995
88180
|
try {
|
|
87996
88181
|
const { applyMemfsFlags: applyMemfsFlags2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
|
|
87997
|
-
const memfsResult = await applyMemfsFlags2(agent.id,
|
|
88182
|
+
const memfsResult = await applyMemfsFlags2(agent.id, startupMemfsFlag, noMemfsFlag, {
|
|
87998
88183
|
pullOnExistingRepo: true,
|
|
87999
88184
|
agentTags: agent.tags,
|
|
88000
88185
|
skipPromptUpdate: forceNew
|
|
@@ -88097,7 +88282,7 @@ In headless mode, use:
|
|
|
88097
88282
|
}
|
|
88098
88283
|
markMilestone("HEADLESS_CONVERSATION_READY");
|
|
88099
88284
|
setConversationId2(conversationId);
|
|
88100
|
-
if (
|
|
88285
|
+
if (shouldPersistSessionState()) {
|
|
88101
88286
|
await settingsManager.loadLocalProjectSettings();
|
|
88102
88287
|
settingsManager.persistSession(agent.id, conversationId);
|
|
88103
88288
|
}
|
|
@@ -88136,7 +88321,7 @@ In headless mode, use:
|
|
|
88136
88321
|
conversation_id: conversationId,
|
|
88137
88322
|
model: agent.llm_config?.model ?? "",
|
|
88138
88323
|
tools: availableTools,
|
|
88139
|
-
cwd:
|
|
88324
|
+
cwd: getCurrentWorkingDirectory(),
|
|
88140
88325
|
mcp_servers: [],
|
|
88141
88326
|
permission_mode: "",
|
|
88142
88327
|
slash_commands: [],
|
|
@@ -88297,6 +88482,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
88297
88482
|
},
|
|
88298
88483
|
state: sharedReminderState,
|
|
88299
88484
|
sessionContextReminderEnabled: systemInfoReminderEnabled,
|
|
88485
|
+
workingDirectory: getCurrentWorkingDirectory(),
|
|
88300
88486
|
reflectionSettings: effectiveReflectionSettings,
|
|
88301
88487
|
skillSources: resolvedSkillSources,
|
|
88302
88488
|
resolvePlanModeReminder: async () => {
|
|
@@ -88470,7 +88656,7 @@ ${loadedContents.join(`
|
|
|
88470
88656
|
} else {
|
|
88471
88657
|
console.error(`Conversation is busy, waiting ${Math.round(retryDelayMs / 1000)}s and retrying...`);
|
|
88472
88658
|
}
|
|
88473
|
-
await new Promise((
|
|
88659
|
+
await new Promise((resolve28) => setTimeout(resolve28, retryDelayMs));
|
|
88474
88660
|
continue;
|
|
88475
88661
|
}
|
|
88476
88662
|
}
|
|
@@ -88519,7 +88705,7 @@ ${loadedContents.join(`
|
|
|
88519
88705
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
88520
88706
|
console.error(`Transient API error before streaming (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
88521
88707
|
}
|
|
88522
|
-
await new Promise((
|
|
88708
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
88523
88709
|
conversationBusyRetries = 0;
|
|
88524
88710
|
continue;
|
|
88525
88711
|
}
|
|
@@ -88758,7 +88944,7 @@ ${loadedContents.join(`
|
|
|
88758
88944
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
88759
88945
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
88760
88946
|
}
|
|
88761
|
-
await new Promise((
|
|
88947
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
88762
88948
|
refreshCurrentInputOtids();
|
|
88763
88949
|
continue;
|
|
88764
88950
|
}
|
|
@@ -88844,7 +89030,7 @@ ${loadedContents.join(`
|
|
|
88844
89030
|
} else {
|
|
88845
89031
|
console.error(`Empty LLM response, retrying (attempt ${attempt} of ${EMPTY_RESPONSE_MAX_RETRIES2})...`);
|
|
88846
89032
|
}
|
|
88847
|
-
await new Promise((
|
|
89033
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
88848
89034
|
refreshCurrentInputOtids();
|
|
88849
89035
|
continue;
|
|
88850
89036
|
}
|
|
@@ -88872,7 +89058,7 @@ ${loadedContents.join(`
|
|
|
88872
89058
|
const delaySeconds = Math.round(delayMs / 1000);
|
|
88873
89059
|
console.error(`LLM API error encountered (attempt ${attempt} of ${LLM_API_ERROR_MAX_RETRIES2}), retrying in ${delaySeconds}s...`);
|
|
88874
89060
|
}
|
|
88875
|
-
await new Promise((
|
|
89061
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
88876
89062
|
refreshCurrentInputOtids();
|
|
88877
89063
|
continue;
|
|
88878
89064
|
}
|
|
@@ -89001,6 +89187,7 @@ ${loadedContents.join(`
|
|
|
89001
89187
|
}
|
|
89002
89188
|
markMilestone("HEADLESS_COMPLETE");
|
|
89003
89189
|
reportAllMilestones();
|
|
89190
|
+
await flushAndExit(0);
|
|
89004
89191
|
}
|
|
89005
89192
|
async function runBidirectionalMode(agent, conversationId, client, _outputFormat, includePartialMessages, availableTools, skillSources, systemInfoReminderEnabled, reflectionSettings) {
|
|
89006
89193
|
const sessionId = agent.id;
|
|
@@ -89013,7 +89200,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89013
89200
|
conversation_id: conversationId,
|
|
89014
89201
|
model: agent.llm_config?.model,
|
|
89015
89202
|
tools: availableTools,
|
|
89016
|
-
cwd:
|
|
89203
|
+
cwd: getCurrentWorkingDirectory(),
|
|
89017
89204
|
memfs_enabled: settingsManager.isMemfsEnabled(agent.id),
|
|
89018
89205
|
skill_sources: skillSources,
|
|
89019
89206
|
system_info_reminder_enabled: systemInfoReminderEnabled,
|
|
@@ -89205,9 +89392,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89205
89392
|
const syntheticUserLine = serializeQueuedMessageAsUserLine(queuedMessage);
|
|
89206
89393
|
maybeNotifyBlocked(syntheticUserLine);
|
|
89207
89394
|
if (lineResolver) {
|
|
89208
|
-
const
|
|
89395
|
+
const resolve28 = lineResolver;
|
|
89209
89396
|
lineResolver = null;
|
|
89210
|
-
|
|
89397
|
+
resolve28(syntheticUserLine);
|
|
89211
89398
|
return;
|
|
89212
89399
|
}
|
|
89213
89400
|
lineQueue.push(syntheticUserLine);
|
|
@@ -89215,9 +89402,9 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89215
89402
|
rl.on("line", (line) => {
|
|
89216
89403
|
maybeNotifyBlocked(line);
|
|
89217
89404
|
if (lineResolver) {
|
|
89218
|
-
const
|
|
89405
|
+
const resolve28 = lineResolver;
|
|
89219
89406
|
lineResolver = null;
|
|
89220
|
-
|
|
89407
|
+
resolve28(line);
|
|
89221
89408
|
} else {
|
|
89222
89409
|
lineQueue.push(line);
|
|
89223
89410
|
}
|
|
@@ -89226,17 +89413,17 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89226
89413
|
setMessageQueueAdder(null);
|
|
89227
89414
|
msgQueueRuntime.clear("shutdown");
|
|
89228
89415
|
if (lineResolver) {
|
|
89229
|
-
const
|
|
89416
|
+
const resolve28 = lineResolver;
|
|
89230
89417
|
lineResolver = null;
|
|
89231
|
-
|
|
89418
|
+
resolve28(null);
|
|
89232
89419
|
}
|
|
89233
89420
|
});
|
|
89234
89421
|
async function getNextLine() {
|
|
89235
89422
|
if (lineQueue.length > 0) {
|
|
89236
89423
|
return lineQueue.shift() ?? null;
|
|
89237
89424
|
}
|
|
89238
|
-
return new Promise((
|
|
89239
|
-
lineResolver =
|
|
89425
|
+
return new Promise((resolve28) => {
|
|
89426
|
+
lineResolver = resolve28;
|
|
89240
89427
|
});
|
|
89241
89428
|
}
|
|
89242
89429
|
async function requestPermission(toolCallId, toolName, toolInput) {
|
|
@@ -89655,6 +89842,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89655
89842
|
},
|
|
89656
89843
|
state: sharedReminderState,
|
|
89657
89844
|
sessionContextReminderEnabled: systemInfoReminderEnabled,
|
|
89845
|
+
workingDirectory: getCurrentWorkingDirectory(),
|
|
89658
89846
|
reflectionSettings,
|
|
89659
89847
|
skillSources,
|
|
89660
89848
|
resolvePlanModeReminder: async () => {
|
|
@@ -89739,7 +89927,7 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
|
|
|
89739
89927
|
uuid: `retry-bidir-${randomUUID8()}`
|
|
89740
89928
|
};
|
|
89741
89929
|
console.log(JSON.stringify(retryMsg));
|
|
89742
|
-
await new Promise((
|
|
89930
|
+
await new Promise((resolve28) => setTimeout(resolve28, delayMs));
|
|
89743
89931
|
continue;
|
|
89744
89932
|
}
|
|
89745
89933
|
throw preStreamError;
|
|
@@ -89980,6 +90168,7 @@ var init_headless = __esm(async () => {
|
|
|
89980
90168
|
init_constants();
|
|
89981
90169
|
init_diffPreview();
|
|
89982
90170
|
init_queueRuntime();
|
|
90171
|
+
init_runtime_context();
|
|
89983
90172
|
init_interactivePolicy();
|
|
89984
90173
|
init_debug();
|
|
89985
90174
|
init_timing();
|
|
@@ -90034,10 +90223,10 @@ async function detectAndEnableKittyProtocol() {
|
|
|
90034
90223
|
detectionComplete = true;
|
|
90035
90224
|
return;
|
|
90036
90225
|
}
|
|
90037
|
-
return new Promise((
|
|
90226
|
+
return new Promise((resolve28) => {
|
|
90038
90227
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
90039
90228
|
detectionComplete = true;
|
|
90040
|
-
|
|
90229
|
+
resolve28();
|
|
90041
90230
|
return;
|
|
90042
90231
|
}
|
|
90043
90232
|
const originalRawMode = process.stdin.isRaw;
|
|
@@ -90070,7 +90259,7 @@ async function detectAndEnableKittyProtocol() {
|
|
|
90070
90259
|
console.error("[kitty] protocol query unsupported; enabled anyway (best-effort)");
|
|
90071
90260
|
}
|
|
90072
90261
|
detectionComplete = true;
|
|
90073
|
-
|
|
90262
|
+
resolve28();
|
|
90074
90263
|
};
|
|
90075
90264
|
const handleData = (data) => {
|
|
90076
90265
|
if (timeoutId === undefined) {
|
|
@@ -112256,7 +112445,7 @@ var init_pasteRegistry = __esm(() => {
|
|
|
112256
112445
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
112257
112446
|
import { existsSync as existsSync29, readFileSync as readFileSync16, statSync as statSync10, unlinkSync as unlinkSync10 } from "node:fs";
|
|
112258
112447
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
112259
|
-
import { basename as basename4, extname as extname5, isAbsolute as isAbsolute18, join as join38, resolve as
|
|
112448
|
+
import { basename as basename4, extname as extname5, isAbsolute as isAbsolute18, join as join38, resolve as resolve28 } from "node:path";
|
|
112260
112449
|
function countLines2(text) {
|
|
112261
112450
|
return (text.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
112262
112451
|
}
|
|
@@ -112304,7 +112493,7 @@ function translatePasteForImages(paste) {
|
|
|
112304
112493
|
} catch {}
|
|
112305
112494
|
}
|
|
112306
112495
|
if (!isAbsolute18(filePath))
|
|
112307
|
-
filePath =
|
|
112496
|
+
filePath = resolve28(process.cwd(), filePath);
|
|
112308
112497
|
const ext3 = extname5(filePath || "").toLowerCase();
|
|
112309
112498
|
if (IMAGE_EXTS.has(ext3) && existsSync29(filePath) && statSync10(filePath).isFile()) {
|
|
112310
112499
|
const buf = readFileSync16(filePath);
|
|
@@ -113450,9 +113639,16 @@ var init_registry = __esm(async () => {
|
|
|
113450
113639
|
}
|
|
113451
113640
|
},
|
|
113452
113641
|
"/reflect": {
|
|
113453
|
-
desc: "Launch
|
|
113642
|
+
desc: "Launch reflection (/reflect [transcript_file])",
|
|
113643
|
+
args: "[transcript_file]",
|
|
113454
113644
|
order: 50,
|
|
113455
|
-
|
|
113645
|
+
handler: () => {
|
|
113646
|
+
return "Launching reflection agent...";
|
|
113647
|
+
}
|
|
113648
|
+
},
|
|
113649
|
+
"/reflection": {
|
|
113650
|
+
desc: "Alias for /reflect",
|
|
113651
|
+
args: "[transcript_file]",
|
|
113456
113652
|
handler: () => {
|
|
113457
113653
|
return "Launching reflection agent...";
|
|
113458
113654
|
}
|
|
@@ -113812,14 +114008,6 @@ Location: ${keybindingsPath}`;
|
|
|
113812
114008
|
return "Clearing credentials...";
|
|
113813
114009
|
}
|
|
113814
114010
|
},
|
|
113815
|
-
"/empanada": {
|
|
113816
|
-
desc: "Order empanadas from Empanada Empire",
|
|
113817
|
-
order: 44.5,
|
|
113818
|
-
args: "[address]",
|
|
113819
|
-
handler: () => {
|
|
113820
|
-
return "Checking Empanada Empire...";
|
|
113821
|
-
}
|
|
113822
|
-
},
|
|
113823
114011
|
"/ralph": {
|
|
113824
114012
|
desc: 'Start Ralph Wiggum loop (/ralph [prompt] [--completion-promise "X"] [--max-iterations N])',
|
|
113825
114013
|
order: 45,
|
|
@@ -114324,11 +114512,11 @@ var init_HelpDialog = __esm(async () => {
|
|
|
114324
114512
|
|
|
114325
114513
|
// src/hooks/writer.ts
|
|
114326
114514
|
import { homedir as homedir31 } from "node:os";
|
|
114327
|
-
import { resolve as
|
|
114515
|
+
import { resolve as resolve29 } from "node:path";
|
|
114328
114516
|
function isProjectSettingsPathCollidingWithGlobal2(workingDirectory) {
|
|
114329
114517
|
const home = process.env.HOME || homedir31();
|
|
114330
|
-
const globalSettingsPath =
|
|
114331
|
-
const projectSettingsPath =
|
|
114518
|
+
const globalSettingsPath = resolve29(home, ".letta", "settings.json");
|
|
114519
|
+
const projectSettingsPath = resolve29(workingDirectory, ".letta", "settings.json");
|
|
114332
114520
|
return globalSettingsPath === projectSettingsPath;
|
|
114333
114521
|
}
|
|
114334
114522
|
function loadHooksFromLocation(location, workingDirectory = process.cwd()) {
|
|
@@ -116966,7 +117154,7 @@ var init_AgentInfoBar = __esm(async () => {
|
|
|
116966
117154
|
|
|
116967
117155
|
// src/cli/helpers/fileSearch.ts
|
|
116968
117156
|
import { readdirSync as readdirSync13, statSync as statSync11 } from "node:fs";
|
|
116969
|
-
import { join as join41, relative as relative15, resolve as
|
|
117157
|
+
import { join as join41, relative as relative15, resolve as resolve30 } from "node:path";
|
|
116970
117158
|
function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [], depth = 0, maxDepth = 10, lowerPattern = pattern.toLowerCase()) {
|
|
116971
117159
|
if (results.length >= maxResults || depth >= maxDepth) {
|
|
116972
117160
|
return results;
|
|
@@ -117009,7 +117197,7 @@ async function searchFiles(query, deep = false) {
|
|
|
117009
117197
|
const dirPart = query.slice(0, lastSlashIndex);
|
|
117010
117198
|
const pattern = query.slice(lastSlashIndex + 1);
|
|
117011
117199
|
try {
|
|
117012
|
-
const resolvedDir =
|
|
117200
|
+
const resolvedDir = resolve30(getIndexRoot(), dirPart);
|
|
117013
117201
|
try {
|
|
117014
117202
|
statSync11(resolvedDir);
|
|
117015
117203
|
searchDir = resolvedDir;
|
|
@@ -131808,7 +131996,7 @@ async function executeStatusLineCommand(command, payload, options) {
|
|
|
131808
131996
|
};
|
|
131809
131997
|
}
|
|
131810
131998
|
function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory, startTime) {
|
|
131811
|
-
return new Promise((
|
|
131999
|
+
return new Promise((resolve31, reject) => {
|
|
131812
132000
|
const [executable, ...args] = launcher;
|
|
131813
132001
|
if (!executable) {
|
|
131814
132002
|
reject(new Error("Empty launcher"));
|
|
@@ -131821,7 +132009,7 @@ function runWithLauncher(launcher, inputJson, timeout, signal, workingDirectory,
|
|
|
131821
132009
|
const safeResolve = (result) => {
|
|
131822
132010
|
if (!resolved) {
|
|
131823
132011
|
resolved = true;
|
|
131824
|
-
|
|
132012
|
+
resolve31(result);
|
|
131825
132013
|
}
|
|
131826
132014
|
};
|
|
131827
132015
|
let child;
|
|
@@ -132998,14 +133186,14 @@ __export(exports_export, {
|
|
|
132998
133186
|
packageSkills: () => packageSkills
|
|
132999
133187
|
});
|
|
133000
133188
|
import { readdir as readdir10, readFile as readFile13 } from "node:fs/promises";
|
|
133001
|
-
import { relative as relative16, resolve as
|
|
133189
|
+
import { relative as relative16, resolve as resolve31 } from "node:path";
|
|
133002
133190
|
async function packageSkills(agentId, skillsDir) {
|
|
133003
133191
|
const skills = [];
|
|
133004
133192
|
const skillNames = new Set;
|
|
133005
133193
|
const dirsToCheck = skillsDir ? [skillsDir] : [
|
|
133006
133194
|
agentId && getAgentSkillsDir(agentId),
|
|
133007
|
-
|
|
133008
|
-
|
|
133195
|
+
resolve31(process.cwd(), ".skills"),
|
|
133196
|
+
resolve31(process.env.HOME || "~", ".letta", "skills")
|
|
133009
133197
|
].filter((dir) => Boolean(dir));
|
|
133010
133198
|
for (const baseDir of dirsToCheck) {
|
|
133011
133199
|
try {
|
|
@@ -133015,8 +133203,8 @@ async function packageSkills(agentId, skillsDir) {
|
|
|
133015
133203
|
continue;
|
|
133016
133204
|
if (skillNames.has(entry.name))
|
|
133017
133205
|
continue;
|
|
133018
|
-
const skillDir =
|
|
133019
|
-
const skillMdPath =
|
|
133206
|
+
const skillDir = resolve31(baseDir, entry.name);
|
|
133207
|
+
const skillMdPath = resolve31(skillDir, "SKILL.md");
|
|
133020
133208
|
try {
|
|
133021
133209
|
await readFile13(skillMdPath, "utf-8");
|
|
133022
133210
|
} catch {
|
|
@@ -133046,7 +133234,7 @@ async function readSkillFiles(skillDir) {
|
|
|
133046
133234
|
async function walk(dir) {
|
|
133047
133235
|
const entries = await readdir10(dir, { withFileTypes: true });
|
|
133048
133236
|
for (const entry of entries) {
|
|
133049
|
-
const fullPath =
|
|
133237
|
+
const fullPath = resolve31(dir, entry.name);
|
|
133050
133238
|
if (entry.isDirectory()) {
|
|
133051
133239
|
await walk(fullPath);
|
|
133052
133240
|
} else {
|
|
@@ -135530,7 +135718,7 @@ ${newState.originalPrompt}`,
|
|
|
135530
135718
|
cancelled = true;
|
|
135531
135719
|
break;
|
|
135532
135720
|
}
|
|
135533
|
-
await new Promise((
|
|
135721
|
+
await new Promise((resolve32) => setTimeout(resolve32, 100));
|
|
135534
135722
|
}
|
|
135535
135723
|
buffersRef.current.byId.delete(statusId);
|
|
135536
135724
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
@@ -135594,7 +135782,7 @@ ${newState.originalPrompt}`,
|
|
|
135594
135782
|
cancelled = true;
|
|
135595
135783
|
break;
|
|
135596
135784
|
}
|
|
135597
|
-
await new Promise((
|
|
135785
|
+
await new Promise((resolve32) => setTimeout(resolve32, 100));
|
|
135598
135786
|
}
|
|
135599
135787
|
if (retryStatusId) {
|
|
135600
135788
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -136352,7 +136540,7 @@ ${feedback}
|
|
|
136352
136540
|
});
|
|
136353
136541
|
buffersRef.current.order.push(statusId);
|
|
136354
136542
|
refreshDerived();
|
|
136355
|
-
await new Promise((
|
|
136543
|
+
await new Promise((resolve32) => setTimeout(resolve32, delayMs));
|
|
136356
136544
|
buffersRef.current.byId.delete(statusId);
|
|
136357
136545
|
buffersRef.current.order = buffersRef.current.order.filter((id) => id !== statusId);
|
|
136358
136546
|
refreshDerived();
|
|
@@ -136412,7 +136600,7 @@ ${feedback}
|
|
|
136412
136600
|
cancelled = true;
|
|
136413
136601
|
break;
|
|
136414
136602
|
}
|
|
136415
|
-
await new Promise((
|
|
136603
|
+
await new Promise((resolve32) => setTimeout(resolve32, 100));
|
|
136416
136604
|
}
|
|
136417
136605
|
if (retryStatusId) {
|
|
136418
136606
|
buffersRef.current.byId.delete(retryStatusId);
|
|
@@ -143626,11 +143814,11 @@ __export(exports_import2, {
|
|
|
143626
143814
|
extractSkillsFromAf: () => extractSkillsFromAf2
|
|
143627
143815
|
});
|
|
143628
143816
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
143629
|
-
import { chmod as chmod2, mkdir as mkdir8, readFile as readFile14, writeFile as
|
|
143630
|
-
import { dirname as dirname19, resolve as
|
|
143817
|
+
import { chmod as chmod2, mkdir as mkdir8, readFile as readFile14, writeFile as writeFile9 } from "node:fs/promises";
|
|
143818
|
+
import { dirname as dirname19, resolve as resolve32 } from "node:path";
|
|
143631
143819
|
async function importAgentFromFile2(options) {
|
|
143632
143820
|
const client = await getClient();
|
|
143633
|
-
const resolvedPath =
|
|
143821
|
+
const resolvedPath = resolve32(options.filePath);
|
|
143634
143822
|
const file = createReadStream2(resolvedPath);
|
|
143635
143823
|
const importResponse = await client.agents.importFile({
|
|
143636
143824
|
file,
|
|
@@ -143665,7 +143853,7 @@ async function extractSkillsFromAf2(afPath, destDir) {
|
|
|
143665
143853
|
return [];
|
|
143666
143854
|
}
|
|
143667
143855
|
for (const skill2 of afData.skills) {
|
|
143668
|
-
const skillDir =
|
|
143856
|
+
const skillDir = resolve32(destDir, skill2.name);
|
|
143669
143857
|
await mkdir8(skillDir, { recursive: true });
|
|
143670
143858
|
if (skill2.files) {
|
|
143671
143859
|
await writeSkillFiles2(skillDir, skill2.files);
|
|
@@ -143685,9 +143873,9 @@ async function writeSkillFiles2(skillDir, files) {
|
|
|
143685
143873
|
}
|
|
143686
143874
|
}
|
|
143687
143875
|
async function writeSkillFile2(skillDir, filePath, content) {
|
|
143688
|
-
const fullPath =
|
|
143876
|
+
const fullPath = resolve32(skillDir, filePath);
|
|
143689
143877
|
await mkdir8(dirname19(fullPath), { recursive: true });
|
|
143690
|
-
await
|
|
143878
|
+
await writeFile9(fullPath, content, "utf-8");
|
|
143691
143879
|
const isScript = filePath.startsWith("scripts/") || content.trimStart().startsWith("#!");
|
|
143692
143880
|
if (isScript) {
|
|
143693
143881
|
try {
|
|
@@ -143740,7 +143928,7 @@ function parseRegistryHandle2(handle) {
|
|
|
143740
143928
|
async function importAgentFromRegistry2(options) {
|
|
143741
143929
|
const { tmpdir: tmpdir7 } = await import("node:os");
|
|
143742
143930
|
const { join: join50 } = await import("node:path");
|
|
143743
|
-
const { writeFile:
|
|
143931
|
+
const { writeFile: writeFile10, unlink: unlink3 } = await import("node:fs/promises");
|
|
143744
143932
|
const { author, name } = parseRegistryHandle2(options.handle);
|
|
143745
143933
|
const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
|
|
143746
143934
|
const response = await fetch(rawUrl);
|
|
@@ -143752,7 +143940,7 @@ async function importAgentFromRegistry2(options) {
|
|
|
143752
143940
|
}
|
|
143753
143941
|
const afContent = await response.text();
|
|
143754
143942
|
const tempPath = join50(tmpdir7(), `letta-import-${author}-${name}-${Date.now()}.af`);
|
|
143755
|
-
await
|
|
143943
|
+
await writeFile10(tempPath, afContent, "utf-8");
|
|
143756
143944
|
try {
|
|
143757
143945
|
const result = await importAgentFromFile2({
|
|
143758
143946
|
filePath: tempPath,
|
|
@@ -148687,12 +148875,15 @@ async function runMemfsSubcommand(argv) {
|
|
|
148687
148875
|
|
|
148688
148876
|
// src/cli/subcommands/messages.ts
|
|
148689
148877
|
await init_client2();
|
|
148878
|
+
import { writeFile as writeFile6 } from "node:fs/promises";
|
|
148879
|
+
import { resolve as resolve23 } from "node:path";
|
|
148690
148880
|
import { parseArgs as parseArgs8 } from "node:util";
|
|
148691
148881
|
function printUsage5() {
|
|
148692
148882
|
console.log(`
|
|
148693
148883
|
Usage:
|
|
148694
148884
|
letta messages search --query <text> [options]
|
|
148695
148885
|
letta messages list [options]
|
|
148886
|
+
letta messages transcript --conversation <id> [options]
|
|
148696
148887
|
|
|
148697
148888
|
Search options:
|
|
148698
148889
|
--query <text> Search query (required)
|
|
@@ -148714,6 +148905,16 @@ List options:
|
|
|
148714
148905
|
--start-date <date> Client-side filter: after this date (ISO format)
|
|
148715
148906
|
--end-date <date> Client-side filter: before this date (ISO format)
|
|
148716
148907
|
|
|
148908
|
+
Transcript options:
|
|
148909
|
+
--conversation <id> Conversation ID to export (required)
|
|
148910
|
+
--conversation-id <id> Alias for --conversation
|
|
148911
|
+
--agent <id> Required when conversation is "default"
|
|
148912
|
+
--agent-id <id> Alias for --agent
|
|
148913
|
+
--limit <n> Page size while fetching (default: 100)
|
|
148914
|
+
--max-pages <n> Max pagination pages to fetch (default: 200)
|
|
148915
|
+
--out <path> Write transcript text to file
|
|
148916
|
+
--output <path> Alias for --out
|
|
148917
|
+
|
|
148717
148918
|
Notes:
|
|
148718
148919
|
- Output is JSON only.
|
|
148719
148920
|
- Uses CLI auth; override with LETTA_API_KEY/LETTA_BASE_URL if needed.
|
|
@@ -148755,7 +148956,12 @@ var MESSAGES_OPTIONS = {
|
|
|
148755
148956
|
"agent-id": { type: "string" },
|
|
148756
148957
|
after: { type: "string" },
|
|
148757
148958
|
before: { type: "string" },
|
|
148758
|
-
order: { type: "string" }
|
|
148959
|
+
order: { type: "string" },
|
|
148960
|
+
conversation: { type: "string" },
|
|
148961
|
+
"conversation-id": { type: "string" },
|
|
148962
|
+
"max-pages": { type: "string" },
|
|
148963
|
+
out: { type: "string" },
|
|
148964
|
+
output: { type: "string" }
|
|
148759
148965
|
};
|
|
148760
148966
|
function parseMessagesArgs(argv) {
|
|
148761
148967
|
return parseArgs8({
|
|
@@ -148782,6 +148988,115 @@ async function runMessagesSubcommand(argv) {
|
|
|
148782
148988
|
}
|
|
148783
148989
|
try {
|
|
148784
148990
|
const client = await getClient();
|
|
148991
|
+
const renderText = (value) => {
|
|
148992
|
+
if (typeof value === "string")
|
|
148993
|
+
return value;
|
|
148994
|
+
if (!Array.isArray(value))
|
|
148995
|
+
return "";
|
|
148996
|
+
return value.map((part) => {
|
|
148997
|
+
if (part && typeof part === "object" && "type" in part && part.type === "text" && "text" in part) {
|
|
148998
|
+
return typeof part.text === "string" ? part.text : "";
|
|
148999
|
+
}
|
|
149000
|
+
return "";
|
|
149001
|
+
}).filter((text) => text.length > 0).join(`
|
|
149002
|
+
`);
|
|
149003
|
+
};
|
|
149004
|
+
const renderUnknown = (value) => {
|
|
149005
|
+
if (typeof value === "string")
|
|
149006
|
+
return value;
|
|
149007
|
+
if (value === null || value === undefined)
|
|
149008
|
+
return "";
|
|
149009
|
+
try {
|
|
149010
|
+
return JSON.stringify(value);
|
|
149011
|
+
} catch {
|
|
149012
|
+
return String(value);
|
|
149013
|
+
}
|
|
149014
|
+
};
|
|
149015
|
+
const safeTypeLabel = (msg) => msg.message_type || "unknown_message";
|
|
149016
|
+
const formatEntry = (msg) => {
|
|
149017
|
+
const timestamp = msg.date || "unknown-time";
|
|
149018
|
+
const type = safeTypeLabel(msg);
|
|
149019
|
+
if (type === "user_message") {
|
|
149020
|
+
const text = renderText(msg.content);
|
|
149021
|
+
return [`[${timestamp}] user`, text || "(empty)"];
|
|
149022
|
+
}
|
|
149023
|
+
if (type === "assistant_message") {
|
|
149024
|
+
const text = renderText(msg.content);
|
|
149025
|
+
return [`[${timestamp}] assistant`, text || "(empty)"];
|
|
149026
|
+
}
|
|
149027
|
+
if (type === "reasoning_message") {
|
|
149028
|
+
return [
|
|
149029
|
+
`[${timestamp}] reasoning`,
|
|
149030
|
+
msg.reasoning && msg.reasoning.length > 0 ? msg.reasoning : "(empty)"
|
|
149031
|
+
];
|
|
149032
|
+
}
|
|
149033
|
+
if (type === "tool_call_message" || type === "approval_request_message") {
|
|
149034
|
+
const calls = Array.isArray(msg.tool_calls) ? msg.tool_calls : msg.tool_call ? [msg.tool_call] : [];
|
|
149035
|
+
if (calls.length === 0) {
|
|
149036
|
+
return [`[${timestamp}] ${type}`, "(no tool call payload)"];
|
|
149037
|
+
}
|
|
149038
|
+
return calls.flatMap((call) => {
|
|
149039
|
+
const header = `[${timestamp}] tool_call ${call.name || "unknown"} (${call.tool_call_id || "no-id"})`;
|
|
149040
|
+
const args = call.arguments ? call.arguments : "{}";
|
|
149041
|
+
return [header, args];
|
|
149042
|
+
});
|
|
149043
|
+
}
|
|
149044
|
+
if (type === "tool_return_message") {
|
|
149045
|
+
const returns = Array.isArray(msg.tool_returns) ? msg.tool_returns : [
|
|
149046
|
+
{
|
|
149047
|
+
tool_call_id: msg.tool_call_id,
|
|
149048
|
+
status: msg.status,
|
|
149049
|
+
tool_return: msg.tool_return,
|
|
149050
|
+
func_response: msg.func_response
|
|
149051
|
+
}
|
|
149052
|
+
];
|
|
149053
|
+
return returns.flatMap((ret) => {
|
|
149054
|
+
const header = `[${timestamp}] tool_return (${ret.tool_call_id || "no-id"}) status=${ret.status || "unknown"}`;
|
|
149055
|
+
const body = renderUnknown(ret.tool_return ?? ret.func_response);
|
|
149056
|
+
return [header, body || "(empty)"];
|
|
149057
|
+
});
|
|
149058
|
+
}
|
|
149059
|
+
const fallbackText = renderText(msg.content) || renderUnknown(msg.content) || "(no content)";
|
|
149060
|
+
return [`[${timestamp}] ${type}`, fallbackText];
|
|
149061
|
+
};
|
|
149062
|
+
const sortChronological3 = (messages) => {
|
|
149063
|
+
return [...messages].sort((a, b) => {
|
|
149064
|
+
const ta = a.date ? new Date(a.date).getTime() : 0;
|
|
149065
|
+
const tb = b.date ? new Date(b.date).getTime() : 0;
|
|
149066
|
+
return ta - tb;
|
|
149067
|
+
});
|
|
149068
|
+
};
|
|
149069
|
+
const fetchConversationMessages = async (conversationId, agentIdForDefault, pageLimit, maxPages) => {
|
|
149070
|
+
const collected = [];
|
|
149071
|
+
const seenIds = new Set;
|
|
149072
|
+
let cursorBefore;
|
|
149073
|
+
for (let pageIndex = 0;pageIndex < maxPages; pageIndex += 1) {
|
|
149074
|
+
const page = await client.conversations.messages.list(conversationId, {
|
|
149075
|
+
limit: pageLimit,
|
|
149076
|
+
order: "desc",
|
|
149077
|
+
...conversationId === "default" && agentIdForDefault ? { agent_id: agentIdForDefault } : {},
|
|
149078
|
+
...cursorBefore ? { before: cursorBefore } : {}
|
|
149079
|
+
});
|
|
149080
|
+
const items = page.getPaginatedItems();
|
|
149081
|
+
if (items.length === 0) {
|
|
149082
|
+
break;
|
|
149083
|
+
}
|
|
149084
|
+
let newItems = 0;
|
|
149085
|
+
for (const item of items) {
|
|
149086
|
+
const id = item.id;
|
|
149087
|
+
if (id && !seenIds.has(id)) {
|
|
149088
|
+
seenIds.add(id);
|
|
149089
|
+
collected.push(item);
|
|
149090
|
+
newItems += 1;
|
|
149091
|
+
}
|
|
149092
|
+
}
|
|
149093
|
+
cursorBefore = items[items.length - 1]?.id;
|
|
149094
|
+
if (newItems === 0 || items.length < pageLimit) {
|
|
149095
|
+
break;
|
|
149096
|
+
}
|
|
149097
|
+
}
|
|
149098
|
+
return sortChronological3(collected);
|
|
149099
|
+
};
|
|
148785
149100
|
if (action === "search") {
|
|
148786
149101
|
const query = parsed.values.query;
|
|
148787
149102
|
if (!query || typeof query !== "string") {
|
|
@@ -148846,6 +149161,44 @@ async function runMessagesSubcommand(argv) {
|
|
|
148846
149161
|
console.log(JSON.stringify(sorted, null, 2));
|
|
148847
149162
|
return 0;
|
|
148848
149163
|
}
|
|
149164
|
+
if (action === "transcript") {
|
|
149165
|
+
const conversationId = parsed.values.conversation || parsed.values["conversation-id"];
|
|
149166
|
+
if (!conversationId || typeof conversationId !== "string") {
|
|
149167
|
+
console.error("Missing conversation id. Pass --conversation <id> or --conversation-id <id>.");
|
|
149168
|
+
return 1;
|
|
149169
|
+
}
|
|
149170
|
+
const agentId = getAgentId5(parsed.values.agent, parsed.values["agent-id"]);
|
|
149171
|
+
if (conversationId === "default" && !agentId) {
|
|
149172
|
+
console.error('Conversation "default" requires an agent id. Set LETTA_AGENT_ID or pass --agent/--agent-id.');
|
|
149173
|
+
return 1;
|
|
149174
|
+
}
|
|
149175
|
+
const pageLimit = Math.max(1, parseLimit3(parsed.values.limit, 100));
|
|
149176
|
+
const maxPages = Math.max(1, parseLimit3(parsed.values["max-pages"], 200));
|
|
149177
|
+
const outputPathRaw = parsed.values.out || parsed.values.output;
|
|
149178
|
+
const messages = await fetchConversationMessages(conversationId, agentId || undefined, pageLimit, maxPages);
|
|
149179
|
+
const transcript = messages.flatMap((msg) => formatEntry(msg)).join(`
|
|
149180
|
+
|
|
149181
|
+
`).trim();
|
|
149182
|
+
if (outputPathRaw && typeof outputPathRaw === "string") {
|
|
149183
|
+
const outputPath = resolve23(process.cwd(), outputPathRaw);
|
|
149184
|
+
await writeFile6(outputPath, `${transcript}
|
|
149185
|
+
`, "utf-8");
|
|
149186
|
+
console.log(JSON.stringify({
|
|
149187
|
+
conversation_id: conversationId,
|
|
149188
|
+
agent_id: agentId || null,
|
|
149189
|
+
message_count: messages.length,
|
|
149190
|
+
output_path: outputPath
|
|
149191
|
+
}, null, 2));
|
|
149192
|
+
return 0;
|
|
149193
|
+
}
|
|
149194
|
+
console.log(JSON.stringify({
|
|
149195
|
+
conversation_id: conversationId,
|
|
149196
|
+
agent_id: agentId || null,
|
|
149197
|
+
message_count: messages.length,
|
|
149198
|
+
transcript
|
|
149199
|
+
}, null, 2));
|
|
149200
|
+
return 0;
|
|
149201
|
+
}
|
|
148849
149202
|
} catch (error) {
|
|
148850
149203
|
console.error(error instanceof Error ? error.message : String(error));
|
|
148851
149204
|
return 1;
|
|
@@ -148886,7 +149239,7 @@ async function runSubcommand(argv) {
|
|
|
148886
149239
|
init_readOnlyShell();
|
|
148887
149240
|
init_shell_command_normalization();
|
|
148888
149241
|
import { homedir as homedir23 } from "node:os";
|
|
148889
|
-
import { isAbsolute as isAbsolute16, join as join29, relative as relative12, resolve as
|
|
149242
|
+
import { isAbsolute as isAbsolute16, join as join29, relative as relative12, resolve as resolve24 } from "node:path";
|
|
148890
149243
|
var MODE_KEY2 = Symbol.for("@letta/permissionMode");
|
|
148891
149244
|
var PLAN_FILE_KEY2 = Symbol.for("@letta/planFilePath");
|
|
148892
149245
|
var MODE_BEFORE_PLAN_KEY2 = Symbol.for("@letta/permissionModeBeforePlan");
|
|
@@ -148922,12 +149275,12 @@ function resolvePlanTargetPath2(targetPath, workingDirectory) {
|
|
|
148922
149275
|
if (!trimmedPath)
|
|
148923
149276
|
return null;
|
|
148924
149277
|
if (trimmedPath.startsWith("~/")) {
|
|
148925
|
-
return
|
|
149278
|
+
return resolve24(homedir23(), trimmedPath.slice(2));
|
|
148926
149279
|
}
|
|
148927
149280
|
if (isAbsolute16(trimmedPath)) {
|
|
148928
|
-
return
|
|
149281
|
+
return resolve24(trimmedPath);
|
|
148929
149282
|
}
|
|
148930
|
-
return
|
|
149283
|
+
return resolve24(workingDirectory, trimmedPath);
|
|
148931
149284
|
}
|
|
148932
149285
|
function isPathInPlansDir2(path23, plansDir) {
|
|
148933
149286
|
if (!path23.endsWith(".md"))
|
|
@@ -149203,7 +149556,7 @@ await __promiseAll([
|
|
|
149203
149556
|
]);
|
|
149204
149557
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
149205
149558
|
import { homedir as homedir24 } from "node:os";
|
|
149206
|
-
import { join as join30, resolve as
|
|
149559
|
+
import { join as join30, resolve as resolve25 } from "node:path";
|
|
149207
149560
|
var DEFAULT_SETTINGS3 = {
|
|
149208
149561
|
lastAgent: null,
|
|
149209
149562
|
tokenStreaming: false,
|
|
@@ -149228,6 +149581,9 @@ var DEFAULT_LETTA_API_URL2 = "https://api.letta.com";
|
|
|
149228
149581
|
function isSubagentProcess2() {
|
|
149229
149582
|
return process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
|
149230
149583
|
}
|
|
149584
|
+
function shouldPersistSessionState2() {
|
|
149585
|
+
return process.env.LETTA_CODE_AGENT_ROLE !== "subagent" && process.env.LETTA_DISABLE_SESSION_PERSIST !== "1";
|
|
149586
|
+
}
|
|
149231
149587
|
function normalizeBaseUrl2(baseUrl) {
|
|
149232
149588
|
let normalized = baseUrl.replace(/^https?:\/\//, "");
|
|
149233
149589
|
normalized = normalized.replace(/\/$/, "");
|
|
@@ -149654,7 +150010,7 @@ class SettingsManager2 {
|
|
|
149654
150010
|
return join30(workingDirectory, ".letta", "settings.json");
|
|
149655
150011
|
}
|
|
149656
150012
|
isProjectSettingsPathCollidingWithGlobal(workingDirectory) {
|
|
149657
|
-
return
|
|
150013
|
+
return resolve25(this.getProjectSettingsPath(workingDirectory)) === resolve25(this.getSettingsPath());
|
|
149658
150014
|
}
|
|
149659
150015
|
getLocalProjectSettingsPath(workingDirectory) {
|
|
149660
150016
|
return join30(workingDirectory, ".letta", "settings.local.json");
|
|
@@ -150616,8 +150972,8 @@ function acquireSwitchLock2() {
|
|
|
150616
150972
|
const lock = getSwitchLock2();
|
|
150617
150973
|
lock.refCount++;
|
|
150618
150974
|
if (lock.refCount === 1) {
|
|
150619
|
-
lock.promise = new Promise((
|
|
150620
|
-
lock.resolve =
|
|
150975
|
+
lock.promise = new Promise((resolve26) => {
|
|
150976
|
+
lock.resolve = resolve26;
|
|
150621
150977
|
});
|
|
150622
150978
|
}
|
|
150623
150979
|
}
|
|
@@ -150888,6 +151244,7 @@ SUBCOMMANDS (JSON-only)
|
|
|
150888
151244
|
letta agents list [--query <text> | --name <name> | --tags <tags>]
|
|
150889
151245
|
letta messages search --query <text> [--all-agents]
|
|
150890
151246
|
letta messages list [--agent <id>]
|
|
151247
|
+
letta messages transcript --conversation <id> [--out <path>]
|
|
150891
151248
|
letta blocks list --agent <id>
|
|
150892
151249
|
letta blocks copy --block-id <id> [--label <label>] [--agent <id>] [--override]
|
|
150893
151250
|
letta blocks attach --block-id <id> [--agent <id>] [--read-only] [--override]
|
|
@@ -151076,14 +151433,6 @@ async function main() {
|
|
|
151076
151433
|
}
|
|
151077
151434
|
const { checkAndAutoUpdate: checkAndAutoUpdate2 } = await init_auto_update().then(() => exports_auto_update);
|
|
151078
151435
|
const autoUpdatePromise = startStartupAutoUpdateCheck(checkAndAutoUpdate2);
|
|
151079
|
-
const { startDockerVersionCheck: startDockerVersionCheck2 } = await init_startup_docker_check().then(() => exports_startup_docker_check);
|
|
151080
|
-
startDockerVersionCheck2().catch(() => {});
|
|
151081
|
-
const { cleanupOldOverflowFiles: cleanupOldOverflowFiles2 } = await Promise.resolve().then(() => (init_overflow2(), exports_overflow));
|
|
151082
|
-
Promise.resolve().then(() => {
|
|
151083
|
-
try {
|
|
151084
|
-
cleanupOldOverflowFiles2(process.cwd());
|
|
151085
|
-
} catch {}
|
|
151086
|
-
});
|
|
151087
151436
|
const processedArgs = preprocessCliArgs(process.argv);
|
|
151088
151437
|
let values;
|
|
151089
151438
|
let positionals;
|
|
@@ -151109,7 +151458,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
151109
151458
|
printHelp();
|
|
151110
151459
|
const helpDelayMs = Number.parseInt(process.env.LETTA_TEST_HELP_EXIT_DELAY_MS ?? "", 10);
|
|
151111
151460
|
if (Number.isFinite(helpDelayMs) && helpDelayMs > 0) {
|
|
151112
|
-
await new Promise((
|
|
151461
|
+
await new Promise((resolve33) => setTimeout(resolve33, helpDelayMs));
|
|
151113
151462
|
}
|
|
151114
151463
|
process.exit(0);
|
|
151115
151464
|
}
|
|
@@ -151194,6 +151543,16 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
151194
151543
|
const isHeadless = values.prompt || values.run || !process.stdin.isTTY;
|
|
151195
151544
|
telemetry2.setSurface(isHeadless ? "headless" : "tui");
|
|
151196
151545
|
telemetry2.init();
|
|
151546
|
+
if (!isHeadless) {
|
|
151547
|
+
const { startDockerVersionCheck: startDockerVersionCheck2 } = await init_startup_docker_check().then(() => exports_startup_docker_check);
|
|
151548
|
+
startDockerVersionCheck2().catch(() => {});
|
|
151549
|
+
const { cleanupOldOverflowFiles: cleanupOldOverflowFiles2 } = await Promise.resolve().then(() => (init_overflow2(), exports_overflow));
|
|
151550
|
+
Promise.resolve().then(() => {
|
|
151551
|
+
try {
|
|
151552
|
+
cleanupOldOverflowFiles2(process.cwd());
|
|
151553
|
+
} catch {}
|
|
151554
|
+
});
|
|
151555
|
+
}
|
|
151197
151556
|
if (command && !isHeadless) {
|
|
151198
151557
|
console.error(`Error: Unknown command or argument "${command}"`);
|
|
151199
151558
|
console.error("Run 'letta --help' for usage information.");
|
|
@@ -151321,9 +151680,9 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
|
|
|
151321
151680
|
process.exit(1);
|
|
151322
151681
|
}
|
|
151323
151682
|
} else {
|
|
151324
|
-
const { resolve:
|
|
151683
|
+
const { resolve: resolve33 } = await import("path");
|
|
151325
151684
|
const { existsSync: existsSync40 } = await import("fs");
|
|
151326
|
-
const resolvedPath =
|
|
151685
|
+
const resolvedPath = resolve33(fromAfFile);
|
|
151327
151686
|
if (!existsSync40(resolvedPath)) {
|
|
151328
151687
|
console.error(`Error: AgentFile not found: ${resolvedPath}`);
|
|
151329
151688
|
process.exit(1);
|
|
@@ -151798,6 +152157,7 @@ Error: ${message}`);
|
|
|
151798
152157
|
setLoadingState("initializing");
|
|
151799
152158
|
const { createAgent: createAgent3 } = await init_create3().then(() => exports_create2);
|
|
151800
152159
|
let agent = null;
|
|
152160
|
+
let autoEnableMemfsForFreshAgent = false;
|
|
151801
152161
|
if (fromAfFile2) {
|
|
151802
152162
|
setLoadingState("importing");
|
|
151803
152163
|
let result;
|
|
@@ -151882,10 +152242,7 @@ Error: ${message}`);
|
|
|
151882
152242
|
});
|
|
151883
152243
|
agent = result.agent;
|
|
151884
152244
|
setAgentProvenance(result.provenance);
|
|
151885
|
-
|
|
151886
|
-
const { enableMemfsIfCloud: enableMemfsIfCloud3 } = await Promise.resolve().then(() => (init_memoryFilesystem2(), exports_memoryFilesystem2));
|
|
151887
|
-
await enableMemfsIfCloud3(agent.id);
|
|
151888
|
-
}
|
|
152245
|
+
autoEnableMemfsForFreshAgent = willAutoEnableMemfs;
|
|
151889
152246
|
}
|
|
151890
152247
|
if (!agent && resumingAgentId) {
|
|
151891
152248
|
try {
|
|
@@ -151908,11 +152265,12 @@ Error: ${message}`);
|
|
|
151908
152265
|
settingsManager2.updateLocalProjectSettings({ lastAgent: agent.id });
|
|
151909
152266
|
settingsManager2.updateSettings({ lastAgent: agent.id });
|
|
151910
152267
|
setAgentContext(agent.id, skillsDirectory2, resolvedSkillSources);
|
|
151911
|
-
const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
|
151912
152268
|
const agentId2 = agent.id;
|
|
151913
152269
|
const agentTags = agent.tags ?? undefined;
|
|
151914
|
-
const
|
|
151915
|
-
|
|
152270
|
+
const startupMemfsFlag = autoEnableMemfsForFreshAgent ? true : memfsFlag;
|
|
152271
|
+
const memfsSyncPromise = Promise.resolve().then(() => (init_memoryFilesystem2(), exports_memoryFilesystem2)).then(({ applyMemfsFlags: applyMemfsFlags3 }) => applyMemfsFlags3(agentId2, startupMemfsFlag, noMemfsFlag, {
|
|
152272
|
+
agentTags,
|
|
152273
|
+
skipPromptUpdate: shouldCreateNew
|
|
151916
152274
|
}));
|
|
151917
152275
|
const secretsInitPromise = init_secretsStore2().then(() => exports_secretsStore2).then(({ initSecretsFromServer: initSecretsFromServer3 }) => initSecretsFromServer3(agentId2));
|
|
151918
152276
|
const isResumingProject = !shouldCreateNew && !!resumingAgentId;
|
|
@@ -152053,7 +152411,7 @@ Error: ${message}`);
|
|
|
152053
152411
|
}
|
|
152054
152412
|
}
|
|
152055
152413
|
}
|
|
152056
|
-
if (
|
|
152414
|
+
if (shouldPersistSessionState2()) {
|
|
152057
152415
|
settingsManager2.persistSession(agent.id, conversationIdToUse);
|
|
152058
152416
|
}
|
|
152059
152417
|
setAgentId(agent.id);
|
|
@@ -152199,4 +152557,4 @@ Error during initialization: ${message}`);
|
|
|
152199
152557
|
}
|
|
152200
152558
|
main();
|
|
152201
152559
|
|
|
152202
|
-
//# debugId=
|
|
152560
|
+
//# debugId=275910C1663139CA64756E2164756E21
|