@letta-ai/letta-code 0.15.0 → 0.15.1

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.
Files changed (2) hide show
  1. package/letta.js +999 -974
  2. package/package.json +1 -1
package/letta.js CHANGED
@@ -3122,7 +3122,7 @@ var package_default;
3122
3122
  var init_package = __esm(() => {
3123
3123
  package_default = {
3124
3124
  name: "@letta-ai/letta-code",
3125
- version: "0.15.0",
3125
+ version: "0.15.1",
3126
3126
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3127
3127
  type: "module",
3128
3128
  bin: {
@@ -4444,7 +4444,7 @@ var init_memoryConstants = __esm(() => {
4444
4444
  });
4445
4445
 
4446
4446
  // src/agent/prompts/approval_recovery_alert.txt
4447
- var approval_recovery_alert_default = `<system-alert>Automated keep-alive ping. Ignore this message and continue from where you stopped.</system-alert>
4447
+ var approval_recovery_alert_default = `<system-reminder>Automated keep-alive ping. Ignore this message and continue from where you stopped.</system-reminder>
4448
4448
  `;
4449
4449
  var init_approval_recovery_alert = () => {};
4450
4450
 
@@ -4802,7 +4802,7 @@ As we collaborate, I'll build up an understanding of how they think, what they v
4802
4802
  var init_human = () => {};
4803
4803
 
4804
4804
  // src/agent/prompts/interrupt_recovery_alert.txt
4805
- var interrupt_recovery_alert_default = `<system-alert>The user interrupted the active stream.</system-alert>
4805
+ var interrupt_recovery_alert_default = `<system-reminder>The user interrupted the active stream.</system-reminder>
4806
4806
  `;
4807
4807
  var init_interrupt_recovery_alert = () => {};
4808
4808
 
@@ -4940,17 +4940,6 @@ user: Where are errors from the client handled?
4940
4940
  assistant: Clients are marked as failed in the \`connectToServer\` function in src/services/process.ts:712.
4941
4941
  </example>
4942
4942
 
4943
- # Memory
4944
-
4945
- You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities.
4946
- Your memory consists of core memory (composed of memory blocks) and external memory:
4947
- - Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible).
4948
- - External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed.
4949
-
4950
- Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly.
4951
- Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories.
4952
- Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools.
4953
-
4954
4943
  # Skills
4955
4944
  - /<skill-name> (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands.`;
4956
4945
  var init_letta_claude = () => {};
@@ -5074,17 +5063,6 @@ You are producing plain text that will later be styled by the CLI. Follow these
5074
5063
  * Do not provide range of lines
5075
5064
  * Examples: src/app.ts, src/app.ts:42, b/server/index.js#L10, C:\\repo\\project\\main.rs:12:5
5076
5065
 
5077
- ## Memory
5078
-
5079
- You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities.
5080
- Your memory consists of core memory (composed of memory blocks) and external memory:
5081
- - Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible).
5082
- - External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed.
5083
-
5084
- Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly.
5085
- Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories.
5086
- Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools.
5087
-
5088
5066
  ## Skills
5089
5067
  - /<skill-name> (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands.`;
5090
5068
  var init_letta_codex = () => {};
@@ -5170,16 +5148,6 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
5170
5148
  - **Interactive Commands:** Prefer non-interactive commands when it makes sense; however, some commands are only interactive and expect user input during their execution (e.g. ssh, vim). If you choose to execute an interactive command consider letting the user know they can press \\\`ctrl + f\\\` to focus into the shell to provide input.
5171
5149
  - **Remembering Facts:** Use the memory tools available to you to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information. If unsure whether to save something, you can ask the user, "Should I remember that for you?
5172
5150
 
5173
- # Memory
5174
- You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities.
5175
- Your memory consists of core memory (composed of memory blocks) and external memory:
5176
- - Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible).
5177
- - External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed.
5178
-
5179
- Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly.
5180
- Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories.
5181
- Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools.
5182
-
5183
5151
  # Skills
5184
5152
  - /<skill-name> (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands.`;
5185
5153
  var init_letta_gemini = () => {};
@@ -5667,67 +5635,29 @@ If the user asks for help or wants to give feedback inform them of the following
5667
5635
 
5668
5636
  When the user directly asks about Letta Code (eg 'can Letta Code do...', 'does Letta Code have...') or asks in second person (eg 'are you able...', 'can you do...'), first use the WebFetch tool to gather information to answer the question from the Letta Code repository at https://github.com/letta-ai/letta-code.
5669
5637
 
5670
- # Memory
5671
- You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities.
5672
- Your memory consists of memory blocks and external memory:
5673
- - Memory Blocks: Stored as memory blocks, each containing a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and remain constantly available in-context.
5674
- - External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed.
5675
-
5676
- Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly.
5677
- They are the foundation which makes you *you*.
5678
-
5679
5638
  # Skills
5680
5639
  - /<skill-name> (e.g., /commit) is shorthand for users to invoke a skill. When executed, the skill gets expanded to a full prompt. Use the Skill tool to execute them. IMPORTANT: Only use Skill for skills listed in system-reminder messages in the conversation - do not guess or use built-in CLI commands.
5681
5640
  `;
5682
5641
  var init_system_prompt = () => {};
5683
5642
 
5684
5643
  // src/agent/prompts/system_prompt_memfs.txt
5685
- var system_prompt_memfs_default = `
5686
- ## Memory Filesystem
5687
- Your memory is stored in a git repository at \`~/.letta/agents/<agent-id>/memory/\`. This provides full version control, sync with the server, and branching for parallel edits.
5688
-
5689
- ### Structure
5690
- \`\`\`
5691
- ~/.letta/agents/<agent-id>/
5692
- └── memory/ # Git repo root
5693
- ├── .git/
5694
- └── system/ # Blocks in your system prompt
5695
- ├── persona/
5696
- ├── human/
5697
- └── ...
5698
- \`\`\`
5699
-
5700
- ### How It Works
5701
- 1. Each \`.md\` file in \`memory/system/\` maps to a memory block label (e.g., \`memory/system/persona/soul.md\` → label \`system/persona/soul\`)
5702
- 2. Files contain raw block content (no frontmatter)
5703
- 3. Changes pushed to git sync to the API within seconds
5704
- 4. API changes sync to git automatically
5705
- 5. The \`memory_filesystem\` block auto-updates with the current tree view
5706
-
5707
- ### Syncing
5708
- \`\`\`bash
5709
- cd ~/.letta/agents/<agent-id>/memory
5710
-
5711
- # See what changed
5712
- git status
5713
-
5714
- # Commit and push your changes
5715
- git add system/
5716
- git commit -m "<type>: <what changed>" # e.g. "fix: update user prefs", "refactor: reorganize persona blocks"
5717
- git push
5644
+ var system_prompt_memfs_default = "\n# Memory\n\nYou have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities.\n\n## Memory Filesystem\nYour memory is stored in a git repository at `~/.letta/agents/<agent-id>/memory/`. This provides full version control, sync with the server, and create worktrees for parallel edits.\nEach file contains metadata frontmatter include a `description` (the description of the file's contents), `limit` (the character limit), and optional `metadata`.\nThe filesystem tree is always available in your system prompt, along with the contents of files in the `system/` folder.\nYou also have additional external memory (e.g. your message history) that is accessible and that you can bring into context with tools when needed.\n\n## How It Works\n1. Each `.md` file in `memory/system/` is pinned to your system prompt with tags <system/context/{name}.md></system/context/{name}.md>\n2. The `memory_filesystem` block renders the current tree view of all available memory files\n2. Changes pushed to git sync to the API server within seconds\n3. API server changes sync to git automatically\n4. The system prompt is only recompiled with the latest memory on the API on compactions or message resets: your local copy may diverge\n\n## Syncing\n```bash\ncd ~/.letta/agents/<agent-id>/memory\n\n# See what changed\ngit status\n\n# Commit and push your changes\ngit add system/\ngit commit -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 ~/.letta/agents/<agent-id>/memory log --oneline\n```\n";
5645
+ var init_system_prompt_memfs = () => {};
5718
5646
 
5719
- # Get latest from server
5720
- git pull
5721
- \`\`\`
5647
+ // src/agent/prompts/system_prompt_memory.txt
5648
+ var system_prompt_memory_default = `
5649
+ # Memory
5722
5650
 
5723
- The system will remind you when your memory has uncommitted changes. Sync when convenient.
5651
+ You have an advanced memory system that enables you to remember past interactions and continuously improve your own capabilities.
5652
+ Your memory consists of core memory (composed of memory blocks) and external memory:
5653
+ - Memory blocks: Each memory block contains a label (title), description (explaining how this block should influence your behavior), and value (the actual content). Memory blocks have size limits. Memory blocks are embedded within your system instructions and are pinned in-context (so they are always visible).
5654
+ - External memory: Additional memory storage that is accessible and that you can bring into context with tools when needed.
5724
5655
 
5725
- ### History
5726
- \`\`\`bash
5727
- git -C ~/.letta/agents/<agent-id>/memory log --oneline
5728
- \`\`\`
5656
+ Memory blocks are used to modulate and augment your base behavior, follow them closely, and maintain them cleanly.
5657
+ Memory management tools allow you to edit and refine existing memory blocks, create new memory blocks, and query for external memories.
5658
+ Memory blocks are stored in a *virtual filesystem* along with the rest of your agent state (prompts, message history, etc.), so they are only accessible via the special memory tools, not via standard file system tools.
5729
5659
  `;
5730
- var init_system_prompt_memfs = () => {};
5660
+ var init_system_prompt_memory = () => {};
5731
5661
 
5732
5662
  // src/utils/error.ts
5733
5663
  function getErrorMessage2(error) {
@@ -5992,6 +5922,10 @@ cd "$MEMORY_DIR"
5992
5922
  git worktree add "$WORKTREE_DIR/$BRANCH_NAME" -b "$BRANCH_NAME"
5993
5923
  \`\`\`
5994
5924
 
5925
+ If \`git worktree add\` fails because main is locked or busy,
5926
+ retry up to 3 times with backoff (sleep 2, 5, 10 seconds).
5927
+ Never delete \`.git/index.lock\` manually.
5928
+
5995
5929
  All your edits go in \`$WORKTREE_DIR/$BRANCH_NAME/\`.
5996
5930
 
5997
5931
  ### 2. Read existing memory
@@ -6017,17 +5951,37 @@ Write memory files the way the agent would want to read them — clean, actionab
6017
5951
 
6018
5952
  ### 6. Commit
6019
5953
 
5954
+ Use Conventional Commits format with the \`(history-analyzer)\`
5955
+ scope and ⏳ signature:
5956
+
6020
5957
  \`\`\`bash
6021
5958
  cd $WORKTREE_DIR/$BRANCH_NAME
6022
5959
  git add -A
6023
- git commit -m "history-analyzer: [summary of what was learned]
5960
+ git commit -m "<type>(history-analyzer): [summary]
6024
5961
 
6025
5962
  Source: [file path] ([N] prompts, [DATE RANGE])
6026
5963
  Key updates:
6027
5964
  - [file]: [what was added/changed]
6028
- ..."
5965
+ ...
5966
+
5967
+ Generated-By: Letta Code
5968
+ Agent-ID: $LETTA_AGENT_ID
5969
+ Parent-Agent-ID: $LETTA_PARENT_AGENT_ID"
6029
5970
  \`\`\`
6030
5971
 
5972
+ **Commit type** — pick the one that fits:
5973
+ - \`chore\` — routine history ingestion (most common)
5974
+ - \`feat\` — adding wholly new memory blocks/topics
5975
+ - \`refactor\` — reorganizing memory by domain/project
5976
+
5977
+ **Example subjects:**
5978
+ - \`chore(history-analyzer): ingest Claude Code history 2025-09 ⏳\`
5979
+ - \`refactor(history-analyzer): reorganize memory by project domain ⏳\`
5980
+
5981
+ **Trailers:** Omit \`Agent-ID\` or \`Parent-Agent-ID\` if the
5982
+ corresponding environment variable is unset (don't write
5983
+ the literal variable name).
5984
+
6031
5985
  ## Important
6032
5986
 
6033
5987
  - Create your own worktree and work there — do NOT edit the memory dir directly
@@ -7019,11 +6973,14 @@ cd "$MEMORY_DIR"
7019
6973
  git log --oneline -10
7020
6974
  \`\`\`
7021
6975
 
7022
- Look for commits starting with "reflection:" - the most
7023
- recent one tells you when the last reflection ran. When
7024
- searching conversation history in Phase 2, you only need
7025
- to go back to roughly that time. If there are no prior
7026
- reflection commits, search a larger window.
6976
+ Look for reflection commits they may use legacy
6977
+ \`reflection:\` subjects, include 🔮 in the subject line,
6978
+ and/or have a \`(reflection)\` scope (e.g.,
6979
+ \`chore(reflection): ...\`). The most recent one tells you
6980
+ when the last reflection ran. When searching conversation
6981
+ history in Phase 2, you only need to go back to roughly
6982
+ that time. If there are no prior reflection commits, search
6983
+ a larger window.
7027
6984
 
7028
6985
  **Step 1b: Create worktree**
7029
6986
 
@@ -7090,6 +7047,14 @@ to search the parent agent's history, not your own.
7090
7047
  - Prefer substance over trivia.
7091
7048
  - Corrections and frustrations are HIGH priority.
7092
7049
 
7050
+ **If nothing is worth saving** (rare — most conversations
7051
+ have at least something): If after thorough review you
7052
+ genuinely find nothing new worth preserving, skip Phase 4,
7053
+ clean up the worktree (Step 5d), and report "reviewed N
7054
+ messages, no updates needed." But be sure you've looked
7055
+ carefully — corrections, preferences, and project context
7056
+ are easy to overlook.
7057
+
7093
7058
  ### Phase 4: Update Memory Files in Worktree
7094
7059
 
7095
7060
  Edit files in the **worktree**, not the main memory dir:
@@ -7140,55 +7105,169 @@ Read({ file_path: "$WORK/persona/soul.md" })
7140
7105
  - **Attribute when useful** - "Prefers X over Y
7141
7106
  (corrected agent on 2025-12-15)".
7142
7107
 
7143
- ### Phase 5: Commit, Merge, Clean Up
7108
+ ### Phase 5: Merge, Push, and Clean Up (MANDATORY)
7109
+
7110
+ Your reflection has two completion states:
7111
+ - **Complete**: merged to main AND pushed to remote.
7112
+ - **Partially complete**: merged to main, push failed.
7113
+ Clean up the worktree, but report that local main is
7114
+ ahead of remote and needs a push.
7144
7115
 
7145
- After all edits are done:
7116
+ The commit in the worktree is neither — it's an intermediate
7117
+ step. Without at least a merge to main, your work is lost.
7118
+
7119
+ **Step 5a: Commit in worktree**
7146
7120
 
7147
7121
  \`\`\`bash
7148
7122
  MEMORY_DIR=~/.letta/agents/$LETTA_PARENT_AGENT_ID/memory
7149
7123
  WORKTREE_DIR=~/.letta/agents/$LETTA_PARENT_AGENT_ID/memory-worktrees
7150
7124
  cd $WORKTREE_DIR/$BRANCH
7151
-
7152
- # Stage and commit all changes
7153
7125
  git add -A
7154
- git commit -m "reflection: <summary of what was learned>
7126
+ \`\`\`
7127
+
7128
+ Check \`git status\` — if there are no changes to commit,
7129
+ skip straight to Step 5d (cleanup). Report "no updates
7130
+ needed" in your output.
7131
+
7132
+ If there are changes, commit using Conventional Commits
7133
+ format with the \`(reflection)\` scope and 🔮 signature:
7134
+
7135
+ \`\`\`bash
7136
+ git commit -m "<type>(reflection): <summary> 🔮
7155
7137
 
7156
7138
  Reviewed messages from <start-date> to <end-date>.
7157
7139
 
7158
7140
  Updates:
7159
7141
  - <bullet point for each memory update made>
7160
- - <what conversation context prompted each update>"
7142
+ - <what conversation context prompted each update>
7143
+
7144
+ Generated-By: Letta Code
7145
+ Agent-ID: <value of $LETTA_AGENT_ID>
7146
+ Parent-Agent-ID: <value of $LETTA_PARENT_AGENT_ID>"
7147
+ \`\`\`
7148
+
7149
+ **Commit type** — pick the one that fits:
7150
+ - \`chore\` — routine memory consolidation (most common)
7151
+ - \`fix\` — correcting stale or wrong memory entries
7152
+ - \`feat\` — adding a wholly new memory block/topic
7153
+ - \`refactor\` — restructuring existing content
7154
+ - \`docs\` — documentation-style notes
7155
+
7156
+ **Example subjects:**
7157
+ - \`chore(reflection): consolidate recent learnings 🔮\`
7158
+ - \`fix(reflection): correct stale user preference note 🔮\`
7159
+ - \`feat(reflection): add new project context block 🔮\`
7160
+
7161
+ **Trailers:** Omit \`Agent-ID\` or \`Parent-Agent-ID\` if the
7162
+ corresponding environment variable is unset (don't write
7163
+ the literal variable name).
7161
7164
 
7162
- # Merge back to main branch
7165
+ **Step 5b: Pull + merge to main**
7166
+
7167
+ \`\`\`bash
7163
7168
  cd $MEMORY_DIR
7169
+ \`\`\`
7170
+
7171
+ First, check that main is in a clean state (\`git status\`).
7172
+ If a merge or rebase is in progress (lock file, dirty
7173
+ index), wait and retry up to 3 times with backoff (sleep 2,
7174
+ 5, 10 seconds). Never delete \`.git/index.lock\` manually.
7175
+ If still busy after retries, go to Error Handling.
7176
+
7177
+ Pull from remote:
7178
+
7179
+ \`\`\`bash
7180
+ git pull --ff-only
7181
+ \`\`\`
7182
+
7183
+ If \`--ff-only\` fails (remote has diverged), fall back:
7184
+
7185
+ \`\`\`bash
7186
+ git pull --rebase
7187
+ \`\`\`
7188
+
7189
+ If rebase has conflicts, resolve them autonomously to
7190
+ stabilize local \`main\` against remote \`main\` first. In this
7191
+ step, prefer **remote main** content for conflicting files,
7192
+ then run \`git rebase --continue\`.
7193
+
7194
+ Important: do not apply reflection branch content yet during
7195
+ this rebase step. Reflection edits are merged later in this
7196
+ phase with \`git merge $BRANCH --no-edit\`.
7197
+
7198
+ Now merge the reflection branch:
7199
+
7200
+ \`\`\`bash
7164
7201
  git merge $BRANCH --no-edit
7202
+ \`\`\`
7203
+
7204
+ If the merge has conflicts, resolve by preferring reflection
7205
+ branch/worktree content for memory files, stage the resolved
7206
+ files, and complete with \`git commit --no-edit\`.
7207
+
7208
+ If you cannot resolve conflicts after 2 attempts, go to
7209
+ Error Handling.
7210
+
7211
+ **Step 5c: Push to remote**
7212
+
7213
+ \`\`\`bash
7214
+ git push
7215
+ \`\`\`
7216
+
7217
+ If push fails, retry once. If it still fails, report that
7218
+ local main is ahead of remote and needs a push. Proceed to
7219
+ cleanup — the merge succeeded and data is safe on local
7220
+ main.
7221
+
7222
+ **Step 5d: Clean up worktree and branch**
7223
+
7224
+ Only clean up when merge to main completed (success or
7225
+ partially complete):
7165
7226
 
7166
- # Clean up worktree and branch
7227
+ \`\`\`bash
7167
7228
  git worktree remove $WORKTREE_DIR/$BRANCH
7168
7229
  git branch -d $BRANCH
7169
7230
  \`\`\`
7170
7231
 
7171
- If the merge has conflicts, resolve them by preferring
7172
- the worktree's version (your edits are newer).
7232
+ **Step 5e: Verify**
7233
+
7234
+ \`\`\`bash
7235
+ git status
7236
+ git log --oneline -3
7237
+ \`\`\`
7238
+
7239
+ Confirm main is clean and your reflection commit (🔮 in
7240
+ subject) is visible in the log.
7173
7241
 
7174
7242
  ## Error Handling
7175
7243
 
7176
- If anything goes wrong (git not available, memory dir
7177
- not initialized, worktree creation fails, merge conflicts
7178
- you can't resolve, etc.):
7244
+ If anything goes wrong at any phase:
7179
7245
 
7180
- 1. Clean up any partial worktree if possible:
7246
+ 1. Stabilize main first (abort in-progress operations):
7181
7247
  \`\`\`bash
7182
7248
  cd $MEMORY_DIR
7183
- git worktree remove $WORKTREE_DIR/$BRANCH 2>/dev/null
7184
- git branch -d $BRANCH 2>/dev/null
7249
+ git merge --abort 2>/dev/null
7250
+ git rebase --abort 2>/dev/null
7185
7251
  \`\`\`
7186
- 2. Report the error clearly in your output, including:
7252
+
7253
+ 2. Do NOT clean up the worktree or branch on failure —
7254
+ preserve them for debugging and manual recovery.
7255
+
7256
+ 3. Report clearly in your output:
7187
7257
  - What failed and the error message
7188
- - What state things were left in
7189
- - Suggested fix for the main agent or user
7190
- 3. Do NOT leave uncommitted changes in the main memory
7191
- directory.
7258
+ - Worktree path: \`$WORKTREE_DIR/$BRANCH\`
7259
+ - Branch name: \`$BRANCH\`
7260
+ - Whether main has uncommitted/dirty state
7261
+ - Concrete resume commands, e.g.:
7262
+ \`\`\`bash
7263
+ cd ~/.letta/agents/$LETTA_PARENT_AGENT_ID/memory
7264
+ git merge <branch-name> --no-edit
7265
+ git push
7266
+ git worktree remove ../memory-worktrees/<branch-name>
7267
+ git branch -d <branch-name>
7268
+ \`\`\`
7269
+
7270
+ 4. Do NOT leave uncommitted changes on main.
7192
7271
 
7193
7272
  ## Output Format
7194
7273
 
@@ -7221,8 +7300,9 @@ For each edit:
7221
7300
  4. **Don't reorganize** - Add/update, don't restructure
7222
7301
  5. **Be selective** - Few meaningful > many trivial
7223
7302
  6. **No relative dates** - "2025-12-15", not "today"
7224
- 7. **Always commit and merge** - Don't leave dangling
7225
- worktrees or uncommitted changes
7303
+ 7. **Always commit, merge, AND push** - Your work is wasted
7304
+ if it isn't merged to main and pushed to remote. Don't
7305
+ leave dangling worktrees or unsynced changes.
7226
7306
  8. **Report errors clearly** - If something breaks, say
7227
7307
  what happened and suggest a fix
7228
7308
  `;
@@ -7419,6 +7499,7 @@ var init_subagents = __esm(() => {
7419
7499
  var exports_promptAssets = {};
7420
7500
  __export(exports_promptAssets, {
7421
7501
  resolveSystemPrompt: () => resolveSystemPrompt,
7502
+ SYSTEM_PROMPT_MEMORY_ADDON: () => SYSTEM_PROMPT_MEMORY_ADDON,
7422
7503
  SYSTEM_PROMPT_MEMFS_ADDON: () => SYSTEM_PROMPT_MEMFS_ADDON,
7423
7504
  SYSTEM_PROMPTS: () => SYSTEM_PROMPTS,
7424
7505
  SYSTEM_PROMPT: () => SYSTEM_PROMPT,
@@ -7447,7 +7528,7 @@ async function resolveSystemPrompt(systemPromptPreset) {
7447
7528
  }
7448
7529
  return SYSTEM_PROMPT;
7449
7530
  }
7450
- var SYSTEM_PROMPT, SYSTEM_PROMPT_MEMFS_ADDON, PLAN_MODE_REMINDER, SKILL_CREATOR_PROMPT, REMEMBER_PROMPT, MEMORY_CHECK_REMINDER, MEMORY_REFLECTION_REMINDER, APPROVAL_RECOVERY_PROMPT, INTERRUPT_RECOVERY_ALERT, MEMORY_PROMPTS, SYSTEM_PROMPTS;
7531
+ var SYSTEM_PROMPT, SYSTEM_PROMPT_MEMORY_ADDON, SYSTEM_PROMPT_MEMFS_ADDON, PLAN_MODE_REMINDER, SKILL_CREATOR_PROMPT, REMEMBER_PROMPT, MEMORY_CHECK_REMINDER, MEMORY_REFLECTION_REMINDER, APPROVAL_RECOVERY_PROMPT, INTERRUPT_RECOVERY_ALERT, MEMORY_PROMPTS, SYSTEM_PROMPTS;
7451
7532
  var init_promptAssets = __esm(() => {
7452
7533
  init_approval_recovery_alert();
7453
7534
  init_claude();
@@ -7472,7 +7553,9 @@ var init_promptAssets = __esm(() => {
7472
7553
  init_style();
7473
7554
  init_system_prompt();
7474
7555
  init_system_prompt_memfs();
7556
+ init_system_prompt_memory();
7475
7557
  SYSTEM_PROMPT = system_prompt_default;
7558
+ SYSTEM_PROMPT_MEMORY_ADDON = system_prompt_memory_default;
7476
7559
  SYSTEM_PROMPT_MEMFS_ADDON = system_prompt_memfs_default;
7477
7560
  PLAN_MODE_REMINDER = plan_mode_reminder_default;
7478
7561
  SKILL_CREATOR_PROMPT = skill_creator_mode_default;
@@ -31274,11 +31357,11 @@ var init_build2 = __esm(async () => {
31274
31357
  // src/agent/client.ts
31275
31358
  var exports_client = {};
31276
31359
  __export(exports_client, {
31277
- getServerUrl: () => getServerUrl2,
31360
+ getServerUrl: () => getServerUrl,
31278
31361
  getClient: () => getClient2
31279
31362
  });
31280
31363
  import { hostname as hostname2 } from "node:os";
31281
- function getServerUrl2() {
31364
+ function getServerUrl() {
31282
31365
  const settings = settingsManager.getSettings();
31283
31366
  return process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
31284
31367
  }
@@ -31331,10 +31414,12 @@ var init_client2 = __esm(async () => {
31331
31414
  });
31332
31415
 
31333
31416
  // src/constants.ts
31334
- var DEFAULT_AGENT_NAME = "Nameless Agent", INTERRUPTED_BY_USER = "Interrupted by user", SYSTEM_REMINDER_TAG = "system-reminder", SYSTEM_REMINDER_OPEN, SYSTEM_REMINDER_CLOSE, MEMFS_CONFLICT_CHECK_INTERVAL = 5, COMPACTION_SUMMARY_HEADER = "(Earlier messages in this conversation have been compacted to free up context, summarized below)", TOKEN_DISPLAY_THRESHOLD = 100, ELAPSED_DISPLAY_THRESHOLD_MS;
31417
+ var DEFAULT_AGENT_NAME = "Nameless Agent", INTERRUPTED_BY_USER = "Interrupted by user", SYSTEM_REMINDER_TAG = "system-reminder", SYSTEM_REMINDER_OPEN, SYSTEM_REMINDER_CLOSE, SYSTEM_ALERT_TAG = "system-alert", SYSTEM_ALERT_OPEN, SYSTEM_ALERT_CLOSE, MEMFS_CONFLICT_CHECK_INTERVAL = 5, COMPACTION_SUMMARY_HEADER = "(Earlier messages in this conversation have been compacted to free up context, summarized below)", TOKEN_DISPLAY_THRESHOLD = 100, ELAPSED_DISPLAY_THRESHOLD_MS;
31335
31418
  var init_constants = __esm(() => {
31336
31419
  SYSTEM_REMINDER_OPEN = `<${SYSTEM_REMINDER_TAG}>`;
31337
31420
  SYSTEM_REMINDER_CLOSE = `</${SYSTEM_REMINDER_TAG}>`;
31421
+ SYSTEM_ALERT_OPEN = `<${SYSTEM_ALERT_TAG}>`;
31422
+ SYSTEM_ALERT_CLOSE = `</${SYSTEM_ALERT_TAG}>`;
31338
31423
  ELAPSED_DISPLAY_THRESHOLD_MS = 60 * 1000;
31339
31424
  });
31340
31425
 
@@ -33543,11 +33628,23 @@ var init_models2 = __esm(() => {
33543
33628
  context_window: 200000
33544
33629
  }
33545
33630
  },
33631
+ {
33632
+ id: "minimax-m2.5",
33633
+ handle: "minimax/MiniMax-M2.5",
33634
+ label: "MiniMax 2.5",
33635
+ description: "MiniMax's latest coding model",
33636
+ isFeatured: true,
33637
+ free: true,
33638
+ updateArgs: {
33639
+ context_window: 160000,
33640
+ max_output_tokens: 64000
33641
+ }
33642
+ },
33546
33643
  {
33547
33644
  id: "minimax-m2.1",
33548
33645
  handle: "minimax/MiniMax-M2.1",
33549
33646
  label: "MiniMax 2.1",
33550
- description: "MiniMax's latest coding model",
33647
+ description: "MiniMax's latest coding model (legacy)",
33551
33648
  isFeatured: true,
33552
33649
  free: true,
33553
33650
  updateArgs: {
@@ -34090,7 +34187,7 @@ function getMemoryRepoDir(agentId) {
34090
34187
  return join3(getAgentRootDir(agentId), "memory");
34091
34188
  }
34092
34189
  function getGitRemoteUrl(agentId) {
34093
- const baseUrl = getServerUrl2();
34190
+ const baseUrl = getServerUrl();
34094
34191
  return `${baseUrl}/v1/git/${agentId}/state.git`;
34095
34192
  }
34096
34193
  async function getAuthToken() {
@@ -34115,7 +34212,7 @@ async function runGit(cwd2, args, token) {
34115
34212
  };
34116
34213
  }
34117
34214
  async function configureLocalCredentialHelper(dir, token) {
34118
- const baseUrl = getServerUrl2();
34215
+ const baseUrl = getServerUrl();
34119
34216
  const helper = `!f() { echo "username=letta"; echo "password=${token}"; }; f`;
34120
34217
  await runGit(dir, ["config", `credential.${baseUrl}.helper`, helper]);
34121
34218
  debugLog("memfs-git", "Configured local credential helper");
@@ -34865,6 +34962,7 @@ __export(exports_context, {
34865
34962
  setConversationId: () => setConversationId2,
34866
34963
  setAgentContext: () => setAgentContext2,
34867
34964
  getSkillsDirectory: () => getSkillsDirectory,
34965
+ getNoSkills: () => getNoSkills,
34868
34966
  getCurrentAgentId: () => getCurrentAgentId,
34869
34967
  getConversationId: () => getConversationId
34870
34968
  });
@@ -34874,14 +34972,16 @@ function getContext2() {
34874
34972
  global2[CONTEXT_KEY2] = {
34875
34973
  agentId: null,
34876
34974
  skillsDirectory: null,
34975
+ noSkills: false,
34877
34976
  conversationId: null
34878
34977
  };
34879
34978
  }
34880
34979
  return global2[CONTEXT_KEY2];
34881
34980
  }
34882
- function setAgentContext2(agentId, skillsDirectory) {
34981
+ function setAgentContext2(agentId, skillsDirectory, noSkills) {
34883
34982
  context2.agentId = agentId;
34884
34983
  context2.skillsDirectory = skillsDirectory || null;
34984
+ context2.noSkills = noSkills ?? false;
34885
34985
  }
34886
34986
  function setCurrentAgentId(agentId) {
34887
34987
  context2.agentId = agentId;
@@ -34895,6 +34995,9 @@ function getCurrentAgentId() {
34895
34995
  function getSkillsDirectory() {
34896
34996
  return context2.skillsDirectory;
34897
34997
  }
34998
+ function getNoSkills() {
34999
+ return context2.noSkills;
35000
+ }
34898
35001
  function setConversationId2(conversationId) {
34899
35002
  context2.conversationId = conversationId;
34900
35003
  }
@@ -37380,9 +37483,13 @@ var init_process_manager = __esm(() => {
37380
37483
  // src/tools/impl/shellEnv.ts
37381
37484
  var exports_shellEnv = {};
37382
37485
  __export(exports_shellEnv, {
37383
- getShellEnv: () => getShellEnv
37486
+ resolveLettaInvocation: () => resolveLettaInvocation,
37487
+ getShellEnv: () => getShellEnv,
37488
+ ensureLettaShimDir: () => ensureLettaShimDir
37384
37489
  });
37490
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync2 } from "node:fs";
37385
37491
  import { createRequire as createRequire2 } from "node:module";
37492
+ import { tmpdir } from "node:os";
37386
37493
  import * as path3 from "node:path";
37387
37494
  import { fileURLToPath } from "node:url";
37388
37495
  function getRipgrepBinDir() {
@@ -37406,12 +37513,81 @@ function getPackageNodeModulesDir() {
37406
37513
  return;
37407
37514
  }
37408
37515
  }
37516
+ function parseInvocationArgs(raw) {
37517
+ if (!raw)
37518
+ return [];
37519
+ try {
37520
+ const parsed = JSON.parse(raw);
37521
+ if (Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
37522
+ return parsed;
37523
+ }
37524
+ } catch {}
37525
+ return [];
37526
+ }
37527
+ function isDevLettaEntryScript(scriptPath) {
37528
+ const normalized = scriptPath.replaceAll("\\", "/");
37529
+ return normalized.endsWith("/src/index.ts");
37530
+ }
37531
+ function resolveLettaInvocation(env3 = process.env, argv = process.argv, execPath = process.execPath) {
37532
+ const explicitBin = env3.LETTA_CODE_BIN?.trim();
37533
+ if (explicitBin) {
37534
+ return {
37535
+ command: explicitBin,
37536
+ args: parseInvocationArgs(env3[LETTA_BIN_ARGS_ENV])
37537
+ };
37538
+ }
37539
+ const scriptPath = argv[1] || "";
37540
+ if (scriptPath && isDevLettaEntryScript(scriptPath)) {
37541
+ return { command: execPath, args: [scriptPath] };
37542
+ }
37543
+ return null;
37544
+ }
37545
+ function shellEscape(arg) {
37546
+ return `'${arg.replaceAll("'", `'"'"'`)}'`;
37547
+ }
37548
+ function ensureLettaShimDir(invocation) {
37549
+ if (!invocation.command)
37550
+ return null;
37551
+ const shimDir = path3.join(tmpdir(), "letta-code-shell-shim");
37552
+ mkdirSync4(shimDir, { recursive: true });
37553
+ if (process.platform === "win32") {
37554
+ const cmdPath = path3.join(shimDir, "letta.cmd");
37555
+ const quotedCommand = `"${invocation.command.replaceAll('"', '""')}"`;
37556
+ const quotedArgs = invocation.args.map((arg) => `"${arg.replaceAll('"', '""')}"`).join(" ");
37557
+ writeFileSync2(cmdPath, `@echo off\r
37558
+ ${quotedCommand} ${quotedArgs} %*\r
37559
+ `);
37560
+ return shimDir;
37561
+ }
37562
+ const shimPath = path3.join(shimDir, "letta");
37563
+ const commandWithArgs = [invocation.command, ...invocation.args].map(shellEscape).join(" ");
37564
+ writeFileSync2(shimPath, `#!/bin/sh
37565
+ exec ${commandWithArgs} "$@"
37566
+ `, {
37567
+ mode: 493
37568
+ });
37569
+ return shimDir;
37570
+ }
37409
37571
  function getShellEnv() {
37410
37572
  const env3 = { ...process.env };
37573
+ const pathKey = Object.keys(env3).find((k) => k.toUpperCase() === "PATH") || "PATH";
37574
+ const pathPrefixes = [];
37575
+ const lettaInvocation = resolveLettaInvocation(env3);
37576
+ if (lettaInvocation) {
37577
+ env3.LETTA_CODE_BIN = lettaInvocation.command;
37578
+ env3[LETTA_BIN_ARGS_ENV] = JSON.stringify(lettaInvocation.args);
37579
+ const shimDir = ensureLettaShimDir(lettaInvocation);
37580
+ if (shimDir) {
37581
+ pathPrefixes.push(shimDir);
37582
+ }
37583
+ }
37411
37584
  const rgBinDir = getRipgrepBinDir();
37412
37585
  if (rgBinDir) {
37413
- const pathKey = Object.keys(env3).find((k) => k.toUpperCase() === "PATH") || "PATH";
37414
- env3[pathKey] = `${rgBinDir}${path3.delimiter}${env3[pathKey] || ""}`;
37586
+ pathPrefixes.push(rgBinDir);
37587
+ }
37588
+ if (pathPrefixes.length > 0) {
37589
+ const existingPath = env3[pathKey] || "";
37590
+ env3[pathKey] = existingPath ? `${pathPrefixes.join(path3.delimiter)}${path3.delimiter}${existingPath}` : pathPrefixes.join(path3.delimiter);
37415
37591
  }
37416
37592
  try {
37417
37593
  env3.LETTA_AGENT_ID = getCurrentAgentId();
@@ -37423,7 +37599,7 @@ function getShellEnv() {
37423
37599
  env3.LETTA_API_KEY = settings.env.LETTA_API_KEY;
37424
37600
  }
37425
37601
  if (!env3.LETTA_BASE_URL) {
37426
- env3.LETTA_BASE_URL = getServerUrl2();
37602
+ env3.LETTA_BASE_URL = getServerUrl();
37427
37603
  }
37428
37604
  } catch {}
37429
37605
  }
@@ -37440,6 +37616,7 @@ function getShellEnv() {
37440
37616
  }
37441
37617
  return env3;
37442
37618
  }
37619
+ var LETTA_BIN_ARGS_ENV = "LETTA_CODE_BIN_ARGS_JSON";
37443
37620
  var init_shellEnv = __esm(async () => {
37444
37621
  init_context();
37445
37622
  await __promiseAll([
@@ -38122,7 +38299,7 @@ var init_Edit2 = () => {};
38122
38299
 
38123
38300
  // src/cli/helpers/planName.ts
38124
38301
  import { homedir as homedir9 } from "node:os";
38125
- import { join as join8 } from "node:path";
38302
+ import { join as join9 } from "node:path";
38126
38303
  function randomElement(arr) {
38127
38304
  return arr[Math.floor(Math.random() * arr.length)];
38128
38305
  }
@@ -38134,7 +38311,7 @@ function generatePlanName() {
38134
38311
  }
38135
38312
  function generatePlanFilePath() {
38136
38313
  const name = generatePlanName();
38137
- return join8(homedir9(), ".letta", "plans", `${name}.md`);
38314
+ return join9(homedir9(), ".letta", "plans", `${name}.md`);
38138
38315
  }
38139
38316
  var adjectives, nouns;
38140
38317
  var init_planName = __esm(() => {
@@ -38244,7 +38421,7 @@ __export(exports_mode, {
38244
38421
  permissionMode: () => permissionMode2
38245
38422
  });
38246
38423
  import { homedir as homedir10 } from "node:os";
38247
- import { join as join9 } from "node:path";
38424
+ import { join as join10 } from "node:path";
38248
38425
  function getGlobalMode2() {
38249
38426
  const global2 = globalThis;
38250
38427
  if (!global2[MODE_KEY2]) {
@@ -38365,7 +38542,7 @@ class PermissionModeManager2 {
38365
38542
  return "allow";
38366
38543
  }
38367
38544
  if (writeTools.includes(toolName)) {
38368
- const plansDir = join9(homedir10(), ".letta", "plans");
38545
+ const plansDir = join10(homedir10(), ".letta", "plans");
38369
38546
  let targetPath = toolArgs?.file_path || toolArgs?.path;
38370
38547
  if ((toolName === "ApplyPatch" || toolName === "apply_patch") && toolArgs?.input) {
38371
38548
  const input = toolArgs.input;
@@ -40393,7 +40570,7 @@ var init_LS2 = __esm(() => {
40393
40570
 
40394
40571
  // src/tools/impl/LS.ts
40395
40572
  import { readdir as readdir3, stat } from "node:fs/promises";
40396
- import { join as join11, resolve as resolve7 } from "node:path";
40573
+ import { join as join12, resolve as resolve7 } from "node:path";
40397
40574
  async function ls(args) {
40398
40575
  validateRequiredParams(args, ["path"], "LS");
40399
40576
  validateParamTypes(args, LS_default2, "LS");
@@ -40403,7 +40580,7 @@ async function ls(args) {
40403
40580
  const items = await readdir3(dirPath);
40404
40581
  const filteredItems = items.filter((item) => !ignore.some((pattern) => import_picomatch.default.isMatch(item, pattern)));
40405
40582
  const fileInfos = await Promise.all(filteredItems.map(async (item) => {
40406
- const fullPath = join11(dirPath, item);
40583
+ const fullPath = join12(dirPath, item);
40407
40584
  try {
40408
40585
  const stats = await stat(fullPath);
40409
40586
  return {
@@ -40564,12 +40741,12 @@ __export(exports_imageResize_magick, {
40564
40741
  MAX_IMAGE_BYTES: () => MAX_IMAGE_BYTES
40565
40742
  });
40566
40743
  import { execSync } from "node:child_process";
40567
- import { readFileSync as readFileSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
40568
- import { tmpdir } from "node:os";
40569
- import { join as join12 } from "node:path";
40744
+ import { readFileSync as readFileSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
40745
+ import { tmpdir as tmpdir2 } from "node:os";
40746
+ import { join as join13 } from "node:path";
40570
40747
  async function getImageDimensions(buffer) {
40571
- const tempInput = join12(tmpdir(), `image-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
40572
- writeFileSync3(tempInput, buffer);
40748
+ const tempInput = join13(tmpdir2(), `image-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
40749
+ writeFileSync4(tempInput, buffer);
40573
40750
  try {
40574
40751
  const output = execSync(`magick identify -format "%w %h %m" "${tempInput}"`, {
40575
40752
  encoding: "utf-8"
@@ -40591,12 +40768,12 @@ async function compressToFitByteLimit(buffer, currentWidth, currentHeight) {
40591
40768
  if (buffer.length <= MAX_IMAGE_BYTES) {
40592
40769
  return null;
40593
40770
  }
40594
- const tempInput = join12(tmpdir(), `compress-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
40595
- writeFileSync3(tempInput, buffer);
40771
+ const tempInput = join13(tmpdir2(), `compress-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
40772
+ writeFileSync4(tempInput, buffer);
40596
40773
  try {
40597
40774
  const qualities = [85, 70, 55, 40];
40598
40775
  for (const quality of qualities) {
40599
- const tempOutput = join12(tmpdir(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
40776
+ const tempOutput = join13(tmpdir2(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
40600
40777
  try {
40601
40778
  execSync(`magick "${tempInput}" -quality ${quality} "${tempOutput}"`, {
40602
40779
  stdio: "ignore"
@@ -40622,7 +40799,7 @@ async function compressToFitByteLimit(buffer, currentWidth, currentHeight) {
40622
40799
  for (const scale of scales) {
40623
40800
  const scaledWidth = Math.floor(currentWidth * scale);
40624
40801
  const scaledHeight = Math.floor(currentHeight * scale);
40625
- const tempOutput = join12(tmpdir(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
40802
+ const tempOutput = join13(tmpdir2(), `compress-output-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`);
40626
40803
  try {
40627
40804
  execSync(`magick "${tempInput}" -resize ${scaledWidth}x${scaledHeight} -quality 70 "${tempOutput}"`, {
40628
40805
  stdio: "ignore"
@@ -40666,11 +40843,11 @@ async function resizeImageIfNeeded(buffer, inputMediaType) {
40666
40843
  resized: false
40667
40844
  };
40668
40845
  }
40669
- const tempInput = join12(tmpdir(), `resize-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
40670
- writeFileSync3(tempInput, buffer);
40846
+ const tempInput = join13(tmpdir2(), `resize-input-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
40847
+ writeFileSync4(tempInput, buffer);
40671
40848
  try {
40672
40849
  if (needsResize) {
40673
- const tempOutput2 = join12(tmpdir(), `resize-output-${Date.now()}-${Math.random().toString(36).slice(2)}`);
40850
+ const tempOutput2 = join13(tmpdir2(), `resize-output-${Date.now()}-${Math.random().toString(36).slice(2)}`);
40674
40851
  let outputBuffer2;
40675
40852
  let outputMediaType;
40676
40853
  if (format2 === "jpeg" || format2 === "jpg") {
@@ -40701,7 +40878,7 @@ async function resizeImageIfNeeded(buffer, inputMediaType) {
40701
40878
  resized: true
40702
40879
  };
40703
40880
  }
40704
- const tempOutput = join12(tmpdir(), `convert-output-${Date.now()}-${Math.random().toString(36).slice(2)}.png`);
40881
+ const tempOutput = join13(tmpdir2(), `convert-output-${Date.now()}-${Math.random().toString(36).slice(2)}.png`);
40705
40882
  execSync(`magick "${tempInput}" "${tempOutput}"`, {
40706
40883
  stdio: "ignore"
40707
40884
  });
@@ -53971,17 +54148,17 @@ __export(exports_skills, {
53971
54148
  });
53972
54149
  import { existsSync as existsSync7 } from "node:fs";
53973
54150
  import { readdir as readdir5, readFile as readFile3 } from "node:fs/promises";
53974
- import { dirname as dirname4, join as join13 } from "node:path";
54151
+ import { dirname as dirname4, join as join14 } from "node:path";
53975
54152
  import { fileURLToPath as fileURLToPath6 } from "node:url";
53976
54153
  function getBundledSkillsPath() {
53977
54154
  const thisDir = dirname4(fileURLToPath6(import.meta.url));
53978
54155
  if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
53979
- return join13(thisDir, "../skills/builtin");
54156
+ return join14(thisDir, "../skills/builtin");
53980
54157
  }
53981
- return join13(thisDir, "skills");
54158
+ return join14(thisDir, "skills");
53982
54159
  }
53983
54160
  function getAgentSkillsDir(agentId) {
53984
- return join13(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
54161
+ return join14(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
53985
54162
  }
53986
54163
  async function getBundledSkills() {
53987
54164
  const bundledPath = getBundledSkillsPath();
@@ -54004,12 +54181,14 @@ async function discoverSkillsFromDir(skillsPath, source) {
54004
54181
  }
54005
54182
  return { skills, errors };
54006
54183
  }
54007
- async function discoverSkills(projectSkillsPath = join13(process.cwd(), SKILLS_DIR), agentId) {
54184
+ async function discoverSkills(projectSkillsPath = join14(process.cwd(), SKILLS_DIR), agentId, options) {
54008
54185
  const allErrors = [];
54009
54186
  const skillsById = new Map;
54010
- const bundledSkills = await getBundledSkills();
54011
- for (const skill of bundledSkills) {
54012
- skillsById.set(skill.id, skill);
54187
+ if (!options?.skipBundled) {
54188
+ const bundledSkills = await getBundledSkills();
54189
+ for (const skill of bundledSkills) {
54190
+ skillsById.set(skill.id, skill);
54191
+ }
54013
54192
  }
54014
54193
  const globalResult = await discoverSkillsFromDir(GLOBAL_SKILLS_DIR, "global");
54015
54194
  allErrors.push(...globalResult.errors);
@@ -54038,7 +54217,7 @@ async function findSkillFiles(currentPath, rootPath, skills, errors, source) {
54038
54217
  try {
54039
54218
  const entries = await readdir5(currentPath, { withFileTypes: true });
54040
54219
  for (const entry of entries) {
54041
- const fullPath = join13(currentPath, entry.name);
54220
+ const fullPath = join14(currentPath, entry.name);
54042
54221
  if (entry.isDirectory()) {
54043
54222
  await findSkillFiles(fullPath, rootPath, skills, errors, source);
54044
54223
  } else if (entry.isFile() && entry.name.toUpperCase() === "SKILL.MD") {
@@ -54112,7 +54291,7 @@ ${lines.join(`
54112
54291
  }
54113
54292
  var SKILLS_DIR = ".skills", GLOBAL_SKILLS_DIR;
54114
54293
  var init_skills = __esm(() => {
54115
- GLOBAL_SKILLS_DIR = join13(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
54294
+ GLOBAL_SKILLS_DIR = join14(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
54116
54295
  });
54117
54296
 
54118
54297
  // src/tools/impl/skillContentRegistry.ts
@@ -54137,7 +54316,7 @@ var init_skillContentRegistry = __esm(() => {
54137
54316
  // src/tools/impl/Skill.ts
54138
54317
  import { readdirSync as readdirSync3 } from "node:fs";
54139
54318
  import { readFile as readFile4 } from "node:fs/promises";
54140
- import { dirname as dirname5, join as join14 } from "node:path";
54319
+ import { dirname as dirname5, join as join15 } from "node:path";
54141
54320
  function hasAdditionalFiles(skillMdPath) {
54142
54321
  try {
54143
54322
  const skillDir = dirname5(skillMdPath);
@@ -54148,19 +54327,19 @@ function hasAdditionalFiles(skillMdPath) {
54148
54327
  }
54149
54328
  }
54150
54329
  async function readSkillContent(skillId, skillsDir, agentId) {
54151
- const projectSkillPath = join14(skillsDir, skillId, "SKILL.md");
54330
+ const projectSkillPath = join15(skillsDir, skillId, "SKILL.md");
54152
54331
  try {
54153
54332
  const content = await readFile4(projectSkillPath, "utf-8");
54154
54333
  return { content, path: projectSkillPath };
54155
54334
  } catch {}
54156
54335
  if (agentId) {
54157
- const agentSkillPath = join14(getAgentSkillsDir(agentId), skillId, "SKILL.md");
54336
+ const agentSkillPath = join15(getAgentSkillsDir(agentId), skillId, "SKILL.md");
54158
54337
  try {
54159
54338
  const content = await readFile4(agentSkillPath, "utf-8");
54160
54339
  return { content, path: agentSkillPath };
54161
54340
  } catch {}
54162
54341
  }
54163
- const globalSkillPath = join14(GLOBAL_SKILLS_DIR, skillId, "SKILL.md");
54342
+ const globalSkillPath = join15(GLOBAL_SKILLS_DIR, skillId, "SKILL.md");
54164
54343
  try {
54165
54344
  const content = await readFile4(globalSkillPath, "utf-8");
54166
54345
  return { content, path: globalSkillPath };
@@ -54174,8 +54353,8 @@ async function readSkillContent(skillId, skillsDir, agentId) {
54174
54353
  } catch {}
54175
54354
  }
54176
54355
  try {
54177
- const bundledSkillsDir = join14(process.cwd(), "skills", "skills");
54178
- const bundledSkillPath = join14(bundledSkillsDir, skillId, "SKILL.md");
54356
+ const bundledSkillsDir = join15(process.cwd(), "skills", "skills");
54357
+ const bundledSkillPath = join15(bundledSkillsDir, skillId, "SKILL.md");
54179
54358
  const content = await readFile4(bundledSkillPath, "utf-8");
54180
54359
  return { content, path: bundledSkillPath };
54181
54360
  } catch {
@@ -54187,7 +54366,7 @@ async function getResolvedSkillsDir() {
54187
54366
  if (skillsDir) {
54188
54367
  return skillsDir;
54189
54368
  }
54190
- return join14(process.cwd(), SKILLS_DIR);
54369
+ return join15(process.cwd(), SKILLS_DIR);
54191
54370
  }
54192
54371
  async function skill(args) {
54193
54372
  validateRequiredParams(args, ["skill"], "Skill");
@@ -55308,8 +55487,14 @@ async function task(args) {
55308
55487
  maxTurns: args.max_turns
55309
55488
  });
55310
55489
  await waitForBackgroundSubagentLink(subagentId2, null, signal);
55311
- return `Task running in background with ID: ${taskId}
55312
- Output file: ${outputFile2}`;
55490
+ const linkedAgent = getSnapshot2().agents.find((a) => a.id === subagentId2);
55491
+ const agentId = linkedAgent?.agentURL?.split("/agents/")[1] ?? null;
55492
+ const agentIdLine = agentId ? `
55493
+ Agent ID: ${agentId}` : "";
55494
+ return `Task running in background with task ID: ${taskId}${agentIdLine}
55495
+ Output file: ${outputFile2}
55496
+
55497
+ You will be notified automatically when this task completes — a <task-notification> message will be delivered with the result. No need to poll, sleep-wait, or check the output file. Just continue with your current work.`;
55313
55498
  }
55314
55499
  const subagentId = generateSubagentId();
55315
55500
  registerSubagent(subagentId, subagent_type, description, toolCallId, false);
@@ -58644,7 +58829,7 @@ __export(exports_loader, {
58644
58829
  loadPermissions: () => loadPermissions
58645
58830
  });
58646
58831
  import { homedir as homedir11 } from "node:os";
58647
- import { join as join15 } from "node:path";
58832
+ import { join as join16 } from "node:path";
58648
58833
  async function loadPermissions(workingDirectory = process.cwd()) {
58649
58834
  const merged = {
58650
58835
  allow: [],
@@ -58653,10 +58838,10 @@ async function loadPermissions(workingDirectory = process.cwd()) {
58653
58838
  additionalDirectories: []
58654
58839
  };
58655
58840
  const sources = [
58656
- join15(process.env.XDG_CONFIG_HOME || join15(homedir11(), ".config"), "letta", "settings.json"),
58657
- join15(homedir11(), ".letta", "settings.json"),
58658
- join15(workingDirectory, ".letta", "settings.json"),
58659
- join15(workingDirectory, ".letta", "settings.local.json")
58841
+ join16(process.env.XDG_CONFIG_HOME || join16(homedir11(), ".config"), "letta", "settings.json"),
58842
+ join16(homedir11(), ".letta", "settings.json"),
58843
+ join16(workingDirectory, ".letta", "settings.json"),
58844
+ join16(workingDirectory, ".letta", "settings.local.json")
58660
58845
  ];
58661
58846
  for (const settingsPath of sources) {
58662
58847
  try {
@@ -58692,13 +58877,13 @@ async function savePermissionRule(rule, ruleType, scope, workingDirectory = proc
58692
58877
  let settingsPath;
58693
58878
  switch (scope) {
58694
58879
  case "user":
58695
- settingsPath = join15(process.env.XDG_CONFIG_HOME || join15(homedir11(), ".config"), "letta", "settings.json");
58880
+ settingsPath = join16(process.env.XDG_CONFIG_HOME || join16(homedir11(), ".config"), "letta", "settings.json");
58696
58881
  break;
58697
58882
  case "project":
58698
- settingsPath = join15(workingDirectory, ".letta", "settings.json");
58883
+ settingsPath = join16(workingDirectory, ".letta", "settings.json");
58699
58884
  break;
58700
58885
  case "local":
58701
- settingsPath = join15(workingDirectory, ".letta", "settings.local.json");
58886
+ settingsPath = join16(workingDirectory, ".letta", "settings.local.json");
58702
58887
  break;
58703
58888
  }
58704
58889
  let settings = {};
@@ -58723,7 +58908,7 @@ async function savePermissionRule(rule, ruleType, scope, workingDirectory = proc
58723
58908
  }
58724
58909
  }
58725
58910
  async function ensureLocalSettingsIgnored(workingDirectory) {
58726
- const gitignorePath = join15(workingDirectory, ".gitignore");
58911
+ const gitignorePath = join16(workingDirectory, ".gitignore");
58727
58912
  const pattern = ".letta/settings.local.json";
58728
58913
  try {
58729
58914
  let content = "";
@@ -60298,17 +60483,17 @@ __export(exports_skills2, {
60298
60483
  });
60299
60484
  import { existsSync as existsSync8 } from "node:fs";
60300
60485
  import { readdir as readdir6, readFile as readFile5 } from "node:fs/promises";
60301
- import { dirname as dirname8, join as join16 } from "node:path";
60486
+ import { dirname as dirname8, join as join17 } from "node:path";
60302
60487
  import { fileURLToPath as fileURLToPath7 } from "node:url";
60303
60488
  function getBundledSkillsPath2() {
60304
60489
  const thisDir = dirname8(fileURLToPath7(import.meta.url));
60305
60490
  if (thisDir.includes("src/agent") || thisDir.includes("src\\agent")) {
60306
- return join16(thisDir, "../skills/builtin");
60491
+ return join17(thisDir, "../skills/builtin");
60307
60492
  }
60308
- return join16(thisDir, "skills");
60493
+ return join17(thisDir, "skills");
60309
60494
  }
60310
60495
  function getAgentSkillsDir2(agentId) {
60311
- return join16(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
60496
+ return join17(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents", agentId, "skills");
60312
60497
  }
60313
60498
  async function getBundledSkills2() {
60314
60499
  const bundledPath = getBundledSkillsPath2();
@@ -60331,12 +60516,14 @@ async function discoverSkillsFromDir2(skillsPath, source) {
60331
60516
  }
60332
60517
  return { skills, errors };
60333
60518
  }
60334
- async function discoverSkills2(projectSkillsPath = join16(process.cwd(), SKILLS_DIR2), agentId) {
60519
+ async function discoverSkills2(projectSkillsPath = join17(process.cwd(), SKILLS_DIR2), agentId, options) {
60335
60520
  const allErrors = [];
60336
60521
  const skillsById = new Map;
60337
- const bundledSkills = await getBundledSkills2();
60338
- for (const skill2 of bundledSkills) {
60339
- skillsById.set(skill2.id, skill2);
60522
+ if (!options?.skipBundled) {
60523
+ const bundledSkills = await getBundledSkills2();
60524
+ for (const skill2 of bundledSkills) {
60525
+ skillsById.set(skill2.id, skill2);
60526
+ }
60340
60527
  }
60341
60528
  const globalResult = await discoverSkillsFromDir2(GLOBAL_SKILLS_DIR2, "global");
60342
60529
  allErrors.push(...globalResult.errors);
@@ -60365,7 +60552,7 @@ async function findSkillFiles2(currentPath, rootPath, skills, errors, source) {
60365
60552
  try {
60366
60553
  const entries = await readdir6(currentPath, { withFileTypes: true });
60367
60554
  for (const entry of entries) {
60368
- const fullPath = join16(currentPath, entry.name);
60555
+ const fullPath = join17(currentPath, entry.name);
60369
60556
  if (entry.isDirectory()) {
60370
60557
  await findSkillFiles2(fullPath, rootPath, skills, errors, source);
60371
60558
  } else if (entry.isFile() && entry.name.toUpperCase() === "SKILL.MD") {
@@ -60439,7 +60626,7 @@ ${lines.join(`
60439
60626
  }
60440
60627
  var SKILLS_DIR2 = ".skills", GLOBAL_SKILLS_DIR2;
60441
60628
  var init_skills2 = __esm(() => {
60442
- GLOBAL_SKILLS_DIR2 = join16(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
60629
+ GLOBAL_SKILLS_DIR2 = join17(process.env.HOME || process.env.USERPROFILE || "~", ".letta/skills");
60443
60630
  });
60444
60631
 
60445
60632
  // src/utils/fs.ts
@@ -60456,7 +60643,7 @@ import {
60456
60643
  existsSync as existsSync9,
60457
60644
  readFileSync as fsReadFileSync2,
60458
60645
  writeFileSync as fsWriteFileSync2,
60459
- mkdirSync as mkdirSync5
60646
+ mkdirSync as mkdirSync6
60460
60647
  } from "node:fs";
60461
60648
  import { dirname as dirname9 } from "node:path";
60462
60649
  async function readFile6(path19) {
@@ -60465,7 +60652,7 @@ async function readFile6(path19) {
60465
60652
  async function writeFile2(path19, content) {
60466
60653
  const dir = dirname9(path19);
60467
60654
  if (!existsSync9(dir)) {
60468
- mkdirSync5(dir, { recursive: true });
60655
+ mkdirSync6(dir, { recursive: true });
60469
60656
  }
60470
60657
  fsWriteFileSync2(path19, content, { encoding: "utf-8", flush: true });
60471
60658
  }
@@ -60473,7 +60660,7 @@ function exists2(path19) {
60473
60660
  return existsSync9(path19);
60474
60661
  }
60475
60662
  async function mkdir2(path19, options) {
60476
- mkdirSync5(path19, options);
60663
+ mkdirSync6(path19, options);
60477
60664
  }
60478
60665
  async function readJsonFile(path19) {
60479
60666
  const text = await readFile6(path19);
@@ -60787,7 +60974,7 @@ __export(exports_auto_update, {
60787
60974
  import { exec as exec2 } from "node:child_process";
60788
60975
  import { realpathSync as realpathSync2 } from "node:fs";
60789
60976
  import { readdir as readdir7, rm } from "node:fs/promises";
60790
- import { join as join17 } from "node:path";
60977
+ import { join as join18 } from "node:path";
60791
60978
  import { promisify as promisify4 } from "node:util";
60792
60979
  function debugLog2(...args) {
60793
60980
  if (DEBUG) {
@@ -60882,12 +61069,12 @@ async function getNpmGlobalPath() {
60882
61069
  }
60883
61070
  }
60884
61071
  async function cleanupOrphanedDirs(globalPath) {
60885
- const lettaAiDir = join17(globalPath, "lib/node_modules/@letta-ai");
61072
+ const lettaAiDir = join18(globalPath, "lib/node_modules/@letta-ai");
60886
61073
  try {
60887
61074
  const entries = await readdir7(lettaAiDir);
60888
61075
  for (const entry of entries) {
60889
61076
  if (entry.startsWith(".letta-code-")) {
60890
- const orphanPath = join17(lettaAiDir, entry);
61077
+ const orphanPath = join18(lettaAiDir, entry);
60891
61078
  debugLog2("Cleaning orphaned temp directory:", orphanPath);
60892
61079
  await rm(orphanPath, { recursive: true, force: true });
60893
61080
  }
@@ -61106,6 +61293,7 @@ var init_overflow2 = __esm(() => {
61106
61293
  var exports_promptAssets2 = {};
61107
61294
  __export(exports_promptAssets2, {
61108
61295
  resolveSystemPrompt: () => resolveSystemPrompt2,
61296
+ SYSTEM_PROMPT_MEMORY_ADDON: () => SYSTEM_PROMPT_MEMORY_ADDON2,
61109
61297
  SYSTEM_PROMPT_MEMFS_ADDON: () => SYSTEM_PROMPT_MEMFS_ADDON2,
61110
61298
  SYSTEM_PROMPTS: () => SYSTEM_PROMPTS2,
61111
61299
  SYSTEM_PROMPT: () => SYSTEM_PROMPT2,
@@ -61134,7 +61322,7 @@ async function resolveSystemPrompt2(systemPromptPreset) {
61134
61322
  }
61135
61323
  return SYSTEM_PROMPT2;
61136
61324
  }
61137
- var SYSTEM_PROMPT2, SYSTEM_PROMPT_MEMFS_ADDON2, PLAN_MODE_REMINDER2, SKILL_CREATOR_PROMPT2, REMEMBER_PROMPT2, MEMORY_CHECK_REMINDER2, MEMORY_REFLECTION_REMINDER2, APPROVAL_RECOVERY_PROMPT2, INTERRUPT_RECOVERY_ALERT2, MEMORY_PROMPTS2, SYSTEM_PROMPTS2;
61325
+ var SYSTEM_PROMPT2, SYSTEM_PROMPT_MEMORY_ADDON2, SYSTEM_PROMPT_MEMFS_ADDON2, PLAN_MODE_REMINDER2, SKILL_CREATOR_PROMPT2, REMEMBER_PROMPT2, MEMORY_CHECK_REMINDER2, MEMORY_REFLECTION_REMINDER2, APPROVAL_RECOVERY_PROMPT2, INTERRUPT_RECOVERY_ALERT2, MEMORY_PROMPTS2, SYSTEM_PROMPTS2;
61138
61326
  var init_promptAssets2 = __esm(() => {
61139
61327
  init_approval_recovery_alert();
61140
61328
  init_claude();
@@ -61159,7 +61347,9 @@ var init_promptAssets2 = __esm(() => {
61159
61347
  init_style();
61160
61348
  init_system_prompt();
61161
61349
  init_system_prompt_memfs();
61350
+ init_system_prompt_memory();
61162
61351
  SYSTEM_PROMPT2 = system_prompt_default;
61352
+ SYSTEM_PROMPT_MEMORY_ADDON2 = system_prompt_memory_default;
61163
61353
  SYSTEM_PROMPT_MEMFS_ADDON2 = system_prompt_memfs_default;
61164
61354
  PLAN_MODE_REMINDER2 = plan_mode_reminder_default;
61165
61355
  SKILL_CREATOR_PROMPT2 = skill_creator_mode_default;
@@ -61241,7 +61431,7 @@ __export(exports_subagents2, {
61241
61431
  });
61242
61432
  import { existsSync as existsSync11 } from "node:fs";
61243
61433
  import { readdir as readdir8, readFile as readFile7 } from "node:fs/promises";
61244
- import { join as join19 } from "node:path";
61434
+ import { join as join20 } from "node:path";
61245
61435
  function isValidName2(name) {
61246
61436
  return /^[a-z][a-z0-9-]*$/.test(name);
61247
61437
  }
@@ -61332,7 +61522,7 @@ async function discoverSubagentsFromDir2(agentsDir, seenNames, subagents, errors
61332
61522
  if (!entry.isFile() || !entry.name.endsWith(".md")) {
61333
61523
  continue;
61334
61524
  }
61335
- const filePath = join19(agentsDir, entry.name);
61525
+ const filePath = join20(agentsDir, entry.name);
61336
61526
  try {
61337
61527
  const config = await parseSubagentFile2(filePath);
61338
61528
  if (config) {
@@ -61364,7 +61554,7 @@ async function discoverSubagents2(workingDirectory = process.cwd()) {
61364
61554
  const subagents = [];
61365
61555
  const seenNames = new Set;
61366
61556
  await discoverSubagentsFromDir2(GLOBAL_AGENTS_DIR2, seenNames, subagents, errors);
61367
- const projectAgentsDir = join19(workingDirectory, AGENTS_DIR2);
61557
+ const projectAgentsDir = join20(workingDirectory, AGENTS_DIR2);
61368
61558
  await discoverSubagentsFromDir2(projectAgentsDir, seenNames, subagents, errors);
61369
61559
  return { subagents, errors };
61370
61560
  }
@@ -61407,7 +61597,7 @@ var init_subagents2 = __esm(() => {
61407
61597
  recall_default,
61408
61598
  reflection_default
61409
61599
  ];
61410
- GLOBAL_AGENTS_DIR2 = join19(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
61600
+ GLOBAL_AGENTS_DIR2 = join20(process.env.HOME || process.env.USERPROFILE || "~", ".letta/agents");
61411
61601
  VALID_MEMORY_BLOCKS2 = new Set(MEMORY_BLOCK_LABELS);
61412
61602
  cache5 = {
61413
61603
  builtins: null,
@@ -62300,7 +62490,7 @@ var init_cli2 = __esm(() => {
62300
62490
  cliPermissions2 = new CliPermissions2;
62301
62491
  });
62302
62492
 
62303
- // src/agent/approval-recovery.ts
62493
+ // src/agent/turn-recovery-policy.ts
62304
62494
  function isInvalidToolCallIdsError(detail) {
62305
62495
  if (typeof detail !== "string")
62306
62496
  return false;
@@ -62333,6 +62523,50 @@ function getPreStreamErrorAction(detail, conversationBusyRetries, maxConversatio
62333
62523
  }
62334
62524
  return "rethrow";
62335
62525
  }
62526
+ function extractConflictDetail(error) {
62527
+ if (error && typeof error === "object" && "error" in error) {
62528
+ const errObj = error.error;
62529
+ if (errObj && typeof errObj === "object") {
62530
+ const outer = errObj;
62531
+ if (outer.error && typeof outer.error === "object") {
62532
+ const nested = outer.error;
62533
+ if (typeof nested.detail === "string")
62534
+ return nested.detail;
62535
+ if (typeof nested.message === "string")
62536
+ return nested.message;
62537
+ }
62538
+ if (typeof outer.detail === "string")
62539
+ return outer.detail;
62540
+ if (typeof outer.message === "string")
62541
+ return outer.message;
62542
+ }
62543
+ }
62544
+ if (error instanceof Error)
62545
+ return error.message;
62546
+ return "";
62547
+ }
62548
+ function rebuildInputWithFreshDenials(currentInput, serverApprovals, denialReason) {
62549
+ const stripped = currentInput.filter((item) => item?.type !== "approval");
62550
+ if (serverApprovals.length > 0) {
62551
+ const denials = {
62552
+ type: "approval",
62553
+ approvals: serverApprovals.map((a) => ({
62554
+ type: "approval",
62555
+ tool_call_id: a.toolCallId,
62556
+ approve: false,
62557
+ reason: denialReason
62558
+ }))
62559
+ };
62560
+ return [denials, ...stripped];
62561
+ }
62562
+ return stripped;
62563
+ }
62564
+ function shouldAttemptApprovalRecovery(opts) {
62565
+ return opts.approvalPendingDetected && opts.retries < opts.maxRetries;
62566
+ }
62567
+ var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed";
62568
+
62569
+ // src/agent/approval-recovery.ts
62336
62570
  async function fetchRunErrorDetail(runId) {
62337
62571
  if (!runId)
62338
62572
  return null;
@@ -62345,7 +62579,6 @@ async function fetchRunErrorDetail(runId) {
62345
62579
  return null;
62346
62580
  }
62347
62581
  }
62348
- var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed";
62349
62582
  var init_approval_recovery = __esm(async () => {
62350
62583
  await init_client2();
62351
62584
  });
@@ -62617,8 +62850,10 @@ async function updateAgentSystemPromptRaw(agentId, systemPromptContent) {
62617
62850
  }
62618
62851
  async function updateAgentSystemPrompt(agentId, systemPromptId) {
62619
62852
  try {
62620
- const { resolveSystemPrompt: resolveSystemPrompt3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
62621
- const systemPromptContent = await resolveSystemPrompt3(systemPromptId);
62853
+ const { resolveSystemPrompt: resolveSystemPrompt3, SYSTEM_PROMPT_MEMORY_ADDON: SYSTEM_PROMPT_MEMORY_ADDON3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
62854
+ const baseContent = await resolveSystemPrompt3(systemPromptId);
62855
+ const systemPromptContent = `${baseContent}
62856
+ ${SYSTEM_PROMPT_MEMORY_ADDON3}`;
62622
62857
  const updateResult = await updateAgentSystemPromptRaw(agentId, systemPromptContent);
62623
62858
  if (!updateResult.success) {
62624
62859
  return {
@@ -62647,18 +62882,18 @@ async function updateAgentSystemPromptMemfs(agentId, enableMemfs) {
62647
62882
  const client = await getClient2();
62648
62883
  const agent = await client.agents.retrieve(agentId);
62649
62884
  let currentSystemPrompt = agent.system || "";
62650
- const { SYSTEM_PROMPT_MEMFS_ADDON: SYSTEM_PROMPT_MEMFS_ADDON3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
62651
- const memfsHeaderRegex = /\n## Memory Filesystem[\s\S]*?(?=\n# |$)/;
62652
- currentSystemPrompt = currentSystemPrompt.replace(memfsHeaderRegex, "");
62653
- if (enableMemfs) {
62654
- currentSystemPrompt = `${currentSystemPrompt}${SYSTEM_PROMPT_MEMFS_ADDON3}`;
62655
- }
62885
+ const { SYSTEM_PROMPT_MEMFS_ADDON: SYSTEM_PROMPT_MEMFS_ADDON3, SYSTEM_PROMPT_MEMORY_ADDON: SYSTEM_PROMPT_MEMORY_ADDON3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
62886
+ const memoryHeaderRegex = /\n#{1,2} Memory\b[\s\S]*?(?=\n#{1,2} (?!Memory|Filesystem|Structure|How It Works|Syncing|History)[^\n]|$)/;
62887
+ currentSystemPrompt = currentSystemPrompt.replace(memoryHeaderRegex, "");
62888
+ const addon = enableMemfs ? SYSTEM_PROMPT_MEMFS_ADDON3 : SYSTEM_PROMPT_MEMORY_ADDON3;
62889
+ currentSystemPrompt = `${currentSystemPrompt}
62890
+ ${addon}`;
62656
62891
  await client.agents.update(agentId, {
62657
62892
  system: currentSystemPrompt
62658
62893
  });
62659
62894
  return {
62660
62895
  success: true,
62661
- message: enableMemfs ? "System prompt updated to include Memory Filesystem section" : "System prompt updated to remove Memory Filesystem section"
62896
+ message: enableMemfs ? "System prompt updated to include Memory Filesystem section" : "System prompt updated to include standard Memory section"
62662
62897
  };
62663
62898
  } catch (error) {
62664
62899
  return {
@@ -62831,6 +63066,8 @@ async function createAgent(nameOrOptions = DEFAULT_AGENT_NAME, model, embeddingM
62831
63066
  } else {
62832
63067
  systemPromptContent = await resolveSystemPrompt(options.systemPromptPreset);
62833
63068
  }
63069
+ systemPromptContent = `${systemPromptContent}
63070
+ ${SYSTEM_PROMPT_MEMORY_ADDON}`;
62834
63071
  if (options.systemPromptAppend) {
62835
63072
  systemPromptContent = `${systemPromptContent}
62836
63073
 
@@ -62841,6 +63078,9 @@ ${options.systemPromptAppend}`;
62841
63078
  if (isSubagent) {
62842
63079
  tags.push("role:subagent");
62843
63080
  }
63081
+ if (options.tags && Array.isArray(options.tags)) {
63082
+ tags.push(...options.tags);
63083
+ }
62844
63084
  const agentDescription = options.description ?? `Letta Code agent created in ${process.cwd()}`;
62845
63085
  const agent = await client.agents.create({
62846
63086
  agent_type: "letta_v1_agent",
@@ -63098,8 +63338,8 @@ function normalizeLineEndings(s) {
63098
63338
  `).replace(/\r/g, `
63099
63339
  `);
63100
63340
  }
63101
- function removeSystemReminderBlocks(text) {
63102
- return text.replace(new RegExp(`${SYSTEM_REMINDER_OPEN}[\\s\\S]*?${SYSTEM_REMINDER_CLOSE}`, "g"), "").trim();
63341
+ function removeSystemContextBlocks(text) {
63342
+ return text.replace(new RegExp(`${SYSTEM_REMINDER_OPEN}[\\s\\S]*?${SYSTEM_REMINDER_CLOSE}`, "g"), "").replace(new RegExp(`${SYSTEM_ALERT_OPEN}[\\s\\S]*?${SYSTEM_ALERT_CLOSE}`, "g"), "").trim();
63103
63343
  }
63104
63344
  function extractCompactionSummary(text) {
63105
63345
  try {
@@ -63128,14 +63368,14 @@ function renderAssistantContentParts(parts) {
63128
63368
  function renderUserContentParts(parts) {
63129
63369
  if (typeof parts === "string") {
63130
63370
  const normalized = normalizeLineEndings(parts);
63131
- return clip(removeSystemReminderBlocks(normalized), CLIP_CHAR_LIMIT_TEXT);
63371
+ return clip(removeSystemContextBlocks(normalized), CLIP_CHAR_LIMIT_TEXT);
63132
63372
  }
63133
63373
  const rendered = [];
63134
63374
  for (const p of parts) {
63135
63375
  if (p.type === "text") {
63136
63376
  const text = p.text || "";
63137
63377
  const normalized = normalizeLineEndings(text);
63138
- const withoutSystemReminders = removeSystemReminderBlocks(normalized);
63378
+ const withoutSystemReminders = removeSystemContextBlocks(normalized);
63139
63379
  if (!withoutSystemReminders)
63140
63380
  continue;
63141
63381
  rendered.push(clip(withoutSystemReminders, CLIP_CHAR_LIMIT_TEXT));
@@ -63939,6 +64179,13 @@ function resolveAssistantLineId(b, chunk) {
63939
64179
  let canonical = canonicalFromMessageId || canonicalFromOtid || messageId || otid;
63940
64180
  if (!canonical)
63941
64181
  return;
64182
+ if (otid && !canonicalFromOtid && canonicalFromMessageId) {
64183
+ const existingLineId = resolveLineIdForKind(b, canonicalFromMessageId, "assistant");
64184
+ const existingLine = b.byId.get(existingLineId);
64185
+ if (existingLine && existingLine.kind === "assistant" && "phase" in existingLine && existingLine.phase === "finished") {
64186
+ canonical = otid;
64187
+ }
64188
+ }
63942
64189
  if (canonicalFromMessageId && canonicalFromOtid && canonicalFromMessageId !== canonicalFromOtid) {
63943
64190
  const messageLineExists = b.byId.has(canonicalFromMessageId);
63944
64191
  const otidLineExists = b.byId.has(canonicalFromOtid);
@@ -63974,6 +64221,13 @@ function resolveReasoningLineId(b, chunk) {
63974
64221
  let canonical = canonicalFromMessageId || canonicalFromOtid || messageId || otid;
63975
64222
  if (!canonical)
63976
64223
  return;
64224
+ if (otid && !canonicalFromOtid && canonicalFromMessageId) {
64225
+ const existingLineId = resolveLineIdForKind(b, canonicalFromMessageId, "reasoning");
64226
+ const existingLine = b.byId.get(existingLineId);
64227
+ if (existingLine && existingLine.kind === "reasoning" && "phase" in existingLine && existingLine.phase === "finished") {
64228
+ canonical = otid;
64229
+ }
64230
+ }
63977
64231
  if (canonicalFromMessageId && canonicalFromOtid && canonicalFromMessageId !== canonicalFromOtid) {
63978
64232
  const messageLineExists = b.byId.has(canonicalFromMessageId);
63979
64233
  const otidLineExists = b.byId.has(canonicalFromOtid);
@@ -64759,11 +65013,18 @@ ${createAgentLink(runId, agentId, conversationId)}` : baseError;
64759
65013
  }
64760
65014
  return String(e);
64761
65015
  }
65016
+ function getRetryStatusMessage(errorDetail) {
65017
+ if (!errorDetail)
65018
+ return DEFAULT_RETRY_MESSAGE;
65019
+ if (errorDetail.includes("Anthropic API is overloaded"))
65020
+ return "Anthropic API is overloaded, retrying...";
65021
+ return DEFAULT_RETRY_MESSAGE;
65022
+ }
64762
65023
  function createAgentLink(runId, agentId, conversationId) {
64763
65024
  const url = `https://app.letta.com/agents/${agentId}${conversationId ? `?conversation=${conversationId}` : ""}`;
64764
65025
  return `View agent: \x1B]8;;${url}\x1B\\${agentId}\x1B]8;;\x1B\\ (run: ${runId})`;
64765
65026
  }
64766
- var LETTA_USAGE_URL = "https://app.letta.com/settings/organization/usage", LETTA_AGENTS_URL = "https://app.letta.com/projects/default-project/agents", ENCRYPTED_CONTENT_HINT;
65027
+ var LETTA_USAGE_URL = "https://app.letta.com/settings/organization/usage", LETTA_AGENTS_URL = "https://app.letta.com/projects/default-project/agents", ENCRYPTED_CONTENT_HINT, DEFAULT_RETRY_MESSAGE = "Unexpected downstream LLM API error, retrying...";
64767
65028
  var init_errorFormatter = __esm(() => {
64768
65029
  init_error();
64769
65030
  init_errorContext();
@@ -65199,8 +65460,8 @@ function parseRegistryHandle(handle) {
65199
65460
  return { author: parts[0], name: parts[1] };
65200
65461
  }
65201
65462
  async function importAgentFromRegistry(options) {
65202
- const { tmpdir: tmpdir2 } = await import("node:os");
65203
- const { join: join20 } = await import("node:path");
65463
+ const { tmpdir: tmpdir3 } = await import("node:os");
65464
+ const { join: join21 } = await import("node:path");
65204
65465
  const { writeFile: writeFile4, unlink } = await import("node:fs/promises");
65205
65466
  const { author, name } = parseRegistryHandle(options.handle);
65206
65467
  const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
@@ -65212,7 +65473,7 @@ async function importAgentFromRegistry(options) {
65212
65473
  throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
65213
65474
  }
65214
65475
  const afContent = await response.text();
65215
- const tempPath = join20(tmpdir2(), `letta-import-${author}-${name}-${Date.now()}.af`);
65476
+ const tempPath = join21(tmpdir3(), `letta-import-${author}-${name}-${Date.now()}.af`);
65216
65477
  await writeFile4(tempPath, afContent, "utf-8");
65217
65478
  try {
65218
65479
  const result = await importAgentFromFile({
@@ -65292,11 +65553,142 @@ var init_defaults = __esm(async () => {
65292
65553
  name: "Incognito",
65293
65554
  description: INCOGNITO_DESCRIPTION,
65294
65555
  initBlocks: [],
65295
- baseTools: ["web_search", "conversation_search", "fetch_webpage"]
65556
+ baseTools: ["web_search", "fetch_webpage"]
65296
65557
  }
65297
65558
  };
65298
65559
  });
65299
65560
 
65561
+ // src/agent/memoryFilesystem.ts
65562
+ var exports_memoryFilesystem = {};
65563
+ __export(exports_memoryFilesystem, {
65564
+ renderMemoryFilesystemTree: () => renderMemoryFilesystemTree,
65565
+ labelFromRelativePath: () => labelFromRelativePath,
65566
+ getMemorySystemDir: () => getMemorySystemDir,
65567
+ getMemoryFilesystemRoot: () => getMemoryFilesystemRoot,
65568
+ ensureMemoryFilesystemDirs: () => ensureMemoryFilesystemDirs,
65569
+ applyMemfsFlags: () => applyMemfsFlags,
65570
+ MEMORY_SYSTEM_DIR: () => MEMORY_SYSTEM_DIR,
65571
+ MEMORY_FS_ROOT: () => MEMORY_FS_ROOT,
65572
+ MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR,
65573
+ MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR
65574
+ });
65575
+ import { existsSync as existsSync12, mkdirSync as mkdirSync8 } from "node:fs";
65576
+ import { homedir as homedir14 } from "node:os";
65577
+ import { join as join21 } from "node:path";
65578
+ function getMemoryFilesystemRoot(agentId, homeDir = homedir14()) {
65579
+ return join21(homeDir, MEMORY_FS_ROOT, MEMORY_FS_AGENTS_DIR, agentId, MEMORY_FS_MEMORY_DIR);
65580
+ }
65581
+ function getMemorySystemDir(agentId, homeDir = homedir14()) {
65582
+ return join21(getMemoryFilesystemRoot(agentId, homeDir), MEMORY_SYSTEM_DIR);
65583
+ }
65584
+ function ensureMemoryFilesystemDirs(agentId, homeDir = homedir14()) {
65585
+ const root = getMemoryFilesystemRoot(agentId, homeDir);
65586
+ const systemDir = getMemorySystemDir(agentId, homeDir);
65587
+ if (!existsSync12(root)) {
65588
+ mkdirSync8(root, { recursive: true });
65589
+ }
65590
+ if (!existsSync12(systemDir)) {
65591
+ mkdirSync8(systemDir, { recursive: true });
65592
+ }
65593
+ }
65594
+ function labelFromRelativePath(relativePath) {
65595
+ const normalized = relativePath.replace(/\\/g, "/");
65596
+ return normalized.replace(/\.md$/, "");
65597
+ }
65598
+ function renderMemoryFilesystemTree(systemLabels, detachedLabels) {
65599
+ const makeNode = () => ({ children: new Map, isFile: false });
65600
+ const root = makeNode();
65601
+ const insertPath = (base2, label) => {
65602
+ const parts = base2 ? [base2, ...label.split("/")] : label.split("/");
65603
+ let current = root;
65604
+ for (const [i, partName] of parts.entries()) {
65605
+ const part = i === parts.length - 1 ? `${partName}.md` : partName;
65606
+ if (!current.children.has(part)) {
65607
+ current.children.set(part, makeNode());
65608
+ }
65609
+ current = current.children.get(part);
65610
+ if (i === parts.length - 1) {
65611
+ current.isFile = true;
65612
+ }
65613
+ }
65614
+ };
65615
+ for (const label of systemLabels) {
65616
+ insertPath(MEMORY_SYSTEM_DIR, label);
65617
+ }
65618
+ for (const label of detachedLabels) {
65619
+ insertPath(null, label);
65620
+ }
65621
+ if (!root.children.has(MEMORY_SYSTEM_DIR)) {
65622
+ root.children.set(MEMORY_SYSTEM_DIR, makeNode());
65623
+ }
65624
+ const sortedEntries = (node) => {
65625
+ const entries = Array.from(node.children.entries());
65626
+ return entries.sort(([nameA, nodeA], [nameB, nodeB]) => {
65627
+ if (nodeA.isFile !== nodeB.isFile) {
65628
+ return nodeA.isFile ? 1 : -1;
65629
+ }
65630
+ return nameA.localeCompare(nameB);
65631
+ });
65632
+ };
65633
+ const lines = ["/memory/"];
65634
+ const render2 = (node, prefix) => {
65635
+ const entries = sortedEntries(node);
65636
+ entries.forEach(([name, child], index) => {
65637
+ const isLast = index === entries.length - 1;
65638
+ const branch = isLast ? "└──" : "├──";
65639
+ lines.push(`${prefix}${branch} ${name}${child.isFile ? "" : "/"}`);
65640
+ if (child.children.size > 0) {
65641
+ const nextPrefix = `${prefix}${isLast ? " " : "│ "}`;
65642
+ render2(child, nextPrefix);
65643
+ }
65644
+ });
65645
+ };
65646
+ render2(root, "");
65647
+ return lines.join(`
65648
+ `);
65649
+ }
65650
+ async function applyMemfsFlags(agentId, memfsFlag, noMemfsFlag, options) {
65651
+ const { getServerUrl: getServerUrl2 } = await init_client2().then(() => exports_client);
65652
+ const { settingsManager: settingsManager3 } = await init_settings_manager().then(() => exports_settings_manager);
65653
+ if (memfsFlag) {
65654
+ const serverUrl = getServerUrl2();
65655
+ if (!serverUrl.includes("api.letta.com")) {
65656
+ throw new Error("--memfs is only available on Letta Cloud (api.letta.com).");
65657
+ }
65658
+ settingsManager3.setMemfsEnabled(agentId, true);
65659
+ } else if (noMemfsFlag) {
65660
+ settingsManager3.setMemfsEnabled(agentId, false);
65661
+ }
65662
+ const isEnabled = settingsManager3.isMemfsEnabled(agentId);
65663
+ if (isEnabled && memfsFlag) {
65664
+ const { detachMemoryTools: detachMemoryTools2 } = await init_toolset().then(() => exports_toolset);
65665
+ await detachMemoryTools2(agentId);
65666
+ }
65667
+ if (memfsFlag || noMemfsFlag) {
65668
+ const { updateAgentSystemPromptMemfs: updateAgentSystemPromptMemfs2 } = await init_modify().then(() => exports_modify);
65669
+ await updateAgentSystemPromptMemfs2(agentId, isEnabled);
65670
+ }
65671
+ let pullSummary;
65672
+ if (isEnabled) {
65673
+ const { addGitMemoryTag: addGitMemoryTag2, isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2, pullMemory: pullMemory2 } = await init_memoryGit().then(() => exports_memoryGit);
65674
+ await addGitMemoryTag2(agentId);
65675
+ if (!isGitRepo2(agentId)) {
65676
+ await cloneMemoryRepo2(agentId);
65677
+ } else if (options?.pullOnExistingRepo) {
65678
+ const result = await pullMemory2(agentId);
65679
+ pullSummary = result.summary;
65680
+ }
65681
+ }
65682
+ const action = memfsFlag ? "enabled" : noMemfsFlag ? "disabled" : "unchanged";
65683
+ return {
65684
+ action,
65685
+ memoryDir: isEnabled ? getMemoryFilesystemRoot(agentId) : undefined,
65686
+ pullSummary
65687
+ };
65688
+ }
65689
+ var MEMORY_FS_ROOT = ".letta", MEMORY_FS_AGENTS_DIR = "agents", MEMORY_FS_MEMORY_DIR = "memory", MEMORY_SYSTEM_DIR = "system";
65690
+ var init_memoryFilesystem = () => {};
65691
+
65300
65692
  // src/agent/check-approval.ts
65301
65693
  var exports_check_approval = {};
65302
65694
  __export(exports_check_approval, {
@@ -65475,7 +65867,7 @@ __export(exports_headless, {
65475
65867
  handleHeadlessCommand: () => handleHeadlessCommand
65476
65868
  });
65477
65869
  import { parseArgs as parseArgs5 } from "node:util";
65478
- async function handleHeadlessCommand(argv, model, skillsDirectory) {
65870
+ async function handleHeadlessCommand(argv, model, skillsDirectory, noSkills) {
65479
65871
  const settings = settingsManager.getSettings();
65480
65872
  const { values, positionals } = parseArgs5({
65481
65873
  args: argv,
@@ -65513,8 +65905,10 @@ async function handleHeadlessCommand(argv, model, skillsDirectory) {
65513
65905
  "init-blocks": { type: "string" },
65514
65906
  "base-tools": { type: "string" },
65515
65907
  "from-af": { type: "string" },
65908
+ tags: { type: "string" },
65516
65909
  memfs: { type: "boolean" },
65517
65910
  "no-memfs": { type: "boolean" },
65911
+ "no-skills": { type: "boolean" },
65518
65912
  "max-turns": { type: "string" }
65519
65913
  },
65520
65914
  strict: false,
@@ -65611,6 +66005,16 @@ In headless mode, use:
65611
66005
  const fromAfFile = values["from-af"];
65612
66006
  const preLoadSkillsRaw = values["pre-load-skills"];
65613
66007
  const maxTurnsRaw = values["max-turns"];
66008
+ const tagsRaw = values["tags"];
66009
+ let tags;
66010
+ if (tagsRaw !== undefined) {
66011
+ const trimmed = tagsRaw.trim();
66012
+ if (!trimmed || trimmed.toLowerCase() === "none") {
66013
+ tags = [];
66014
+ } else {
66015
+ tags = trimmed.split(",").map((name) => name.trim()).filter((name) => name.length > 0);
66016
+ }
66017
+ }
65614
66018
  let maxTurns;
65615
66019
  if (maxTurnsRaw !== undefined) {
65616
66020
  const parsed = parseInt(maxTurnsRaw, 10);
@@ -65831,7 +66235,8 @@ In headless mode, use:
65831
66235
  initBlocks,
65832
66236
  baseTools,
65833
66237
  memoryBlocks,
65834
- blockValues
66238
+ blockValues,
66239
+ tags
65835
66240
  };
65836
66241
  const result = await createAgent(createOptions);
65837
66242
  agent = result.agent;
@@ -65897,36 +66302,16 @@ In headless mode, use:
65897
66302
  }
65898
66303
  let conversationId;
65899
66304
  const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
65900
- if (memfsFlag) {
65901
- const serverUrl = getServerUrl2();
65902
- if (!serverUrl.includes("api.letta.com")) {
65903
- console.error("--memfs is only available on Letta Cloud (api.letta.com).");
65904
- process.exit(1);
65905
- }
65906
- settingsManager.setMemfsEnabled(agent.id, true);
65907
- } else if (noMemfsFlag) {
65908
- settingsManager.setMemfsEnabled(agent.id, false);
65909
- }
65910
- if (memfsFlag || noMemfsFlag) {
65911
- const { updateAgentSystemPromptMemfs: updateAgentSystemPromptMemfs2 } = await init_modify().then(() => exports_modify);
65912
- await updateAgentSystemPromptMemfs2(agent.id, settingsManager.isMemfsEnabled(agent.id));
65913
- }
65914
- if (settingsManager.isMemfsEnabled(agent.id)) {
65915
- try {
65916
- const { isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2, pullMemory: pullMemory2 } = await init_memoryGit().then(() => exports_memoryGit);
65917
- if (!isGitRepo2(agent.id)) {
65918
- await cloneMemoryRepo2(agent.id);
65919
- } else {
65920
- const result = await pullMemory2(agent.id);
65921
- if (result.summary.includes("CONFLICT")) {
65922
- console.error("Memory has merge conflicts. Run in interactive mode to resolve.");
65923
- process.exit(1);
65924
- }
65925
- }
65926
- } catch (error) {
65927
- console.error(`Memory git sync failed: ${error instanceof Error ? error.message : String(error)}`);
66305
+ try {
66306
+ const { applyMemfsFlags: applyMemfsFlags2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
66307
+ const memfsResult = await applyMemfsFlags2(agent.id, memfsFlag, noMemfsFlag, { pullOnExistingRepo: true });
66308
+ if (memfsResult.pullSummary?.includes("CONFLICT")) {
66309
+ console.error("Memory has merge conflicts. Run in interactive mode to resolve.");
65928
66310
  process.exit(1);
65929
66311
  }
66312
+ } catch (error) {
66313
+ console.error(`Memory git sync failed: ${error instanceof Error ? error.message : String(error)}`);
66314
+ process.exit(1);
65930
66315
  }
65931
66316
  const isolatedBlockLabels = initBlocks === undefined ? [...ISOLATED_BLOCK_LABELS] : ISOLATED_BLOCK_LABELS.filter((label) => initBlocks.includes(label));
65932
66317
  if (specifiedConversationId) {
@@ -65994,7 +66379,7 @@ In headless mode, use:
65994
66379
  }
65995
66380
  } catch {}
65996
66381
  }
65997
- setAgentContext2(agent.id, skillsDirectory);
66382
+ setAgentContext2(agent.id, skillsDirectory, noSkills);
65998
66383
  const outputFormat = values["output-format"] || "text";
65999
66384
  const includePartialMessages = Boolean(values["include-partial-messages"]);
66000
66385
  if (!["text", "json", "stream-json"].includes(outputFormat)) {
@@ -66147,10 +66532,12 @@ ${SYSTEM_REMINDER_CLOSE}
66147
66532
  formatSkillsAsSystemReminder: formatSkillsAsSystemReminder3
66148
66533
  } = await Promise.resolve().then(() => (init_skills(), exports_skills));
66149
66534
  const { getSkillsDirectory: getSkillsDirectory2 } = await Promise.resolve().then(() => (init_context(), exports_context));
66150
- const { join: join20 } = await import("node:path");
66535
+ const { join: join22 } = await import("node:path");
66151
66536
  try {
66152
- const skillsDir = getSkillsDirectory2() || join20(process.cwd(), defaultDir);
66153
- const { skills } = await discoverSkills3(skillsDir, agent.id);
66537
+ const skillsDir = getSkillsDirectory2() || join22(process.cwd(), defaultDir);
66538
+ const { skills } = await discoverSkills3(skillsDir, agent.id, {
66539
+ skipBundled: noSkills
66540
+ });
66154
66541
  const skillsReminder = formatSkillsAsSystemReminder3(skills);
66155
66542
  if (skillsReminder) {
66156
66543
  pushPart(skillsReminder);
@@ -66238,20 +66625,7 @@ ${loadedContents.join(`
66238
66625
  agentId: agent.id
66239
66626
  });
66240
66627
  } catch (preStreamError) {
66241
- let errorDetail = "";
66242
- if (preStreamError instanceof APIError2 && preStreamError.error && typeof preStreamError.error === "object") {
66243
- const errObj = preStreamError.error;
66244
- if (errObj.error && typeof errObj.error === "object" && "detail" in errObj.error) {
66245
- const nested = errObj.error;
66246
- errorDetail = typeof nested.detail === "string" ? nested.detail : "";
66247
- }
66248
- if (!errorDetail && typeof errObj.detail === "string") {
66249
- errorDetail = errObj.detail;
66250
- }
66251
- }
66252
- if (!errorDetail && preStreamError instanceof Error) {
66253
- errorDetail = preStreamError.message;
66254
- }
66628
+ const errorDetail = extractConflictDetail(preStreamError);
66255
66629
  const preStreamAction = getPreStreamErrorAction(errorDetail, conversationBusyRetries, CONVERSATION_BUSY_MAX_RETRIES);
66256
66630
  if (preStreamAction === "resolve_approval_pending") {
66257
66631
  if (outputFormat === "stream-json") {
@@ -67009,8 +67383,8 @@ async function runBidirectionalMode(agent, conversationId, client, _outputFormat
67009
67383
  formatSkillsAsSystemReminder: formatSkillsAsSystemReminder3
67010
67384
  } = await Promise.resolve().then(() => (init_skills(), exports_skills));
67011
67385
  const { getSkillsDirectory: getSkillsDirectory2 } = await Promise.resolve().then(() => (init_context(), exports_context));
67012
- const { join: join20 } = await import("node:path");
67013
- const skillsDir = getSkillsDirectory2() || join20(process.cwd(), defaultDir);
67386
+ const { join: join22 } = await import("node:path");
67387
+ const skillsDir = getSkillsDirectory2() || join22(process.cwd(), defaultDir);
67014
67388
  const { skills } = await discover(skillsDir, agent.id);
67015
67389
  const skillsReminder = formatSkillsAsSystemReminder3(skills);
67016
67390
  if (skillsReminder) {
@@ -67050,21 +67424,9 @@ ${enrichedContent}`;
67050
67424
  agentId: agent.id
67051
67425
  });
67052
67426
  } catch (preStreamError) {
67053
- let errorDetail = "";
67054
- if (preStreamError instanceof APIError2 && preStreamError.error && typeof preStreamError.error === "object") {
67055
- const errObj = preStreamError.error;
67056
- if (errObj.error && typeof errObj.error === "object" && "detail" in errObj.error) {
67057
- const nested = errObj.error;
67058
- errorDetail = typeof nested.detail === "string" ? nested.detail : "";
67059
- }
67060
- if (!errorDetail && typeof errObj.detail === "string") {
67061
- errorDetail = errObj.detail;
67062
- }
67063
- }
67064
- if (!errorDetail && preStreamError instanceof Error) {
67065
- errorDetail = preStreamError.message;
67066
- }
67067
- if (isApprovalPendingError(errorDetail)) {
67427
+ const errorDetail = extractConflictDetail(preStreamError);
67428
+ const preStreamAction = getPreStreamErrorAction(errorDetail, 0, 0);
67429
+ if (preStreamAction === "resolve_approval_pending") {
67068
67430
  const recoveryMsg = {
67069
67431
  type: "recovery",
67070
67432
  recovery_type: "approval_pending",
@@ -67471,29 +67833,6 @@ var init_build3 = __esm(async () => {
67471
67833
  ]);
67472
67834
  });
67473
67835
 
67474
- // src/agent/memoryFilesystem.ts
67475
- import { existsSync as existsSync12, mkdirSync as mkdirSync7 } from "node:fs";
67476
- import { homedir as homedir14 } from "node:os";
67477
- import { join as join20 } from "node:path";
67478
- function getMemoryFilesystemRoot(agentId, homeDir = homedir14()) {
67479
- return join20(homeDir, MEMORY_FS_ROOT, MEMORY_FS_AGENTS_DIR, agentId, MEMORY_FS_MEMORY_DIR);
67480
- }
67481
- function getMemorySystemDir(agentId, homeDir = homedir14()) {
67482
- return join20(getMemoryFilesystemRoot(agentId, homeDir), MEMORY_SYSTEM_DIR);
67483
- }
67484
- function ensureMemoryFilesystemDirs(agentId, homeDir = homedir14()) {
67485
- const root = getMemoryFilesystemRoot(agentId, homeDir);
67486
- const systemDir = getMemorySystemDir(agentId, homeDir);
67487
- if (!existsSync12(root)) {
67488
- mkdirSync7(root, { recursive: true });
67489
- }
67490
- if (!existsSync12(systemDir)) {
67491
- mkdirSync7(systemDir, { recursive: true });
67492
- }
67493
- }
67494
- var MEMORY_FS_ROOT = ".letta", MEMORY_FS_AGENTS_DIR = "agents", MEMORY_FS_MEMORY_DIR = "memory", MEMORY_SYSTEM_DIR = "system";
67495
- var init_memoryFilesystem = () => {};
67496
-
67497
67836
  // src/ralph/mode.ts
67498
67837
  function getDefaultState() {
67499
67838
  return {
@@ -67589,9 +67928,9 @@ __export(exports_settings, {
67589
67928
  getSetting: () => getSetting
67590
67929
  });
67591
67930
  import { homedir as homedir15 } from "node:os";
67592
- import { join as join21 } from "node:path";
67931
+ import { join as join22 } from "node:path";
67593
67932
  function getSettingsPath() {
67594
- return join21(homedir15(), ".letta", "settings.json");
67933
+ return join22(homedir15(), ".letta", "settings.json");
67595
67934
  }
67596
67935
  async function loadSettings() {
67597
67936
  const settingsPath = getSettingsPath();
@@ -67628,7 +67967,7 @@ async function getSetting(key) {
67628
67967
  return settings[key];
67629
67968
  }
67630
67969
  function getProjectSettingsPath() {
67631
- return join21(process.cwd(), ".letta", "settings.local.json");
67970
+ return join22(process.cwd(), ".letta", "settings.local.json");
67632
67971
  }
67633
67972
  async function loadProjectSettings() {
67634
67973
  const settingsPath = getProjectSettingsPath();
@@ -67646,7 +67985,7 @@ async function loadProjectSettings() {
67646
67985
  }
67647
67986
  async function saveProjectSettings(settings) {
67648
67987
  const settingsPath = getProjectSettingsPath();
67649
- const dirPath = join21(process.cwd(), ".letta");
67988
+ const dirPath = join22(process.cwd(), ".letta");
67650
67989
  try {
67651
67990
  if (!exists(dirPath)) {
67652
67991
  await mkdir(dirPath, { recursive: true });
@@ -74014,8 +74353,9 @@ function extractUserMessagePreview2(message) {
74014
74353
  for (let i = content.length - 1;i >= 0; i--) {
74015
74354
  const part = content[i];
74016
74355
  if (part?.type === "text" && part.text) {
74017
- if (part.text.startsWith(SYSTEM_REMINDER_OPEN))
74356
+ if (part.text.startsWith(SYSTEM_REMINDER_OPEN) || part.text.startsWith(SYSTEM_ALERT_OPEN)) {
74018
74357
  continue;
74358
+ }
74019
74359
  textToShow = part.text;
74020
74360
  break;
74021
74361
  }
@@ -75036,8 +75376,8 @@ var init_pasteRegistry = __esm(() => {
75036
75376
  // src/cli/helpers/clipboard.ts
75037
75377
  import { execFileSync as execFileSync2 } from "node:child_process";
75038
75378
  import { existsSync as existsSync13, readFileSync as readFileSync3, statSync as statSync4, unlinkSync as unlinkSync4 } from "node:fs";
75039
- import { tmpdir as tmpdir2 } from "node:os";
75040
- import { basename as basename3, extname as extname5, isAbsolute as isAbsolute13, join as join22, resolve as resolve20 } from "node:path";
75379
+ import { tmpdir as tmpdir3 } from "node:os";
75380
+ import { basename as basename3, extname as extname5, isAbsolute as isAbsolute13, join as join23, resolve as resolve20 } from "node:path";
75041
75381
  function countLines2(text) {
75042
75382
  return (text.match(/\r\n|\r|\n/g) || []).length + 1;
75043
75383
  }
@@ -75105,7 +75445,7 @@ function translatePasteForImages(paste) {
75105
75445
  function getClipboardImageToTempFile() {
75106
75446
  if (process.platform !== "darwin")
75107
75447
  return null;
75108
- const tempPath = join22(tmpdir2(), `letta-clipboard-${Date.now()}.bin`);
75448
+ const tempPath = join23(tmpdir3(), `letta-clipboard-${Date.now()}.bin`);
75109
75449
  try {
75110
75450
  const jxa = `
75111
75451
  ObjC.import('AppKit');
@@ -75743,12 +76083,12 @@ __export(exports_terminalKeybindingInstaller, {
75743
76083
  import {
75744
76084
  copyFileSync,
75745
76085
  existsSync as existsSync14,
75746
- mkdirSync as mkdirSync8,
76086
+ mkdirSync as mkdirSync9,
75747
76087
  readFileSync as readFileSync4,
75748
- writeFileSync as writeFileSync5
76088
+ writeFileSync as writeFileSync6
75749
76089
  } from "node:fs";
75750
76090
  import { homedir as homedir16, platform as platform3 } from "node:os";
75751
- import { dirname as dirname11, join as join23 } from "node:path";
76091
+ import { dirname as dirname11, join as join24 } from "node:path";
75752
76092
  function detectTerminalType() {
75753
76093
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
75754
76094
  return "cursor";
@@ -75780,16 +76120,16 @@ function getKeybindingsPath(terminal) {
75780
76120
  }[terminal];
75781
76121
  const os5 = platform3();
75782
76122
  if (os5 === "darwin") {
75783
- return join23(homedir16(), "Library", "Application Support", appName, "User", "keybindings.json");
76123
+ return join24(homedir16(), "Library", "Application Support", appName, "User", "keybindings.json");
75784
76124
  }
75785
76125
  if (os5 === "win32") {
75786
76126
  const appData = process.env.APPDATA;
75787
76127
  if (!appData)
75788
76128
  return null;
75789
- return join23(appData, appName, "User", "keybindings.json");
76129
+ return join24(appData, appName, "User", "keybindings.json");
75790
76130
  }
75791
76131
  if (os5 === "linux") {
75792
- return join23(homedir16(), ".config", appName, "User", "keybindings.json");
76132
+ return join24(homedir16(), ".config", appName, "User", "keybindings.json");
75793
76133
  }
75794
76134
  return null;
75795
76135
  }
@@ -75841,7 +76181,7 @@ function installKeybinding(keybindingsPath) {
75841
76181
  }
75842
76182
  const parentDir = dirname11(keybindingsPath);
75843
76183
  if (!existsSync14(parentDir)) {
75844
- mkdirSync8(parentDir, { recursive: true });
76184
+ mkdirSync9(parentDir, { recursive: true });
75845
76185
  }
75846
76186
  let keybindings = [];
75847
76187
  let backupPath = null;
@@ -75860,7 +76200,7 @@ function installKeybinding(keybindingsPath) {
75860
76200
  keybindings.push(SHIFT_ENTER_KEYBINDING);
75861
76201
  const newContent = `${JSON.stringify(keybindings, null, 2)}
75862
76202
  `;
75863
- writeFileSync5(keybindingsPath, newContent, { encoding: "utf-8" });
76203
+ writeFileSync6(keybindingsPath, newContent, { encoding: "utf-8" });
75864
76204
  return {
75865
76205
  success: true,
75866
76206
  backupPath: backupPath ?? undefined
@@ -75889,7 +76229,7 @@ function removeKeybinding(keybindingsPath) {
75889
76229
  const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
75890
76230
  const newContent = `${JSON.stringify(filtered, null, 2)}
75891
76231
  `;
75892
- writeFileSync5(keybindingsPath, newContent, { encoding: "utf-8" });
76232
+ writeFileSync6(keybindingsPath, newContent, { encoding: "utf-8" });
75893
76233
  return { success: true };
75894
76234
  } catch (error) {
75895
76235
  const message = error instanceof Error ? error.message : String(error);
@@ -75942,14 +76282,14 @@ function getWezTermConfigPath() {
75942
76282
  }
75943
76283
  const xdgConfig = process.env.XDG_CONFIG_HOME;
75944
76284
  if (xdgConfig) {
75945
- const xdgPath = join23(xdgConfig, "wezterm", "wezterm.lua");
76285
+ const xdgPath = join24(xdgConfig, "wezterm", "wezterm.lua");
75946
76286
  if (existsSync14(xdgPath))
75947
76287
  return xdgPath;
75948
76288
  }
75949
- const configPath = join23(homedir16(), ".config", "wezterm", "wezterm.lua");
76289
+ const configPath = join24(homedir16(), ".config", "wezterm", "wezterm.lua");
75950
76290
  if (existsSync14(configPath))
75951
76291
  return configPath;
75952
- return join23(homedir16(), ".wezterm.lua");
76292
+ return join24(homedir16(), ".wezterm.lua");
75953
76293
  }
75954
76294
  function wezTermDeleteFixExists(configPath) {
75955
76295
  if (!existsSync14(configPath))
@@ -76000,9 +76340,9 @@ ${WEZTERM_DELETE_FIX}
76000
76340
  }
76001
76341
  const parentDir = dirname11(configPath);
76002
76342
  if (!existsSync14(parentDir)) {
76003
- mkdirSync8(parentDir, { recursive: true });
76343
+ mkdirSync9(parentDir, { recursive: true });
76004
76344
  }
76005
- writeFileSync5(configPath, content, { encoding: "utf-8" });
76345
+ writeFileSync6(configPath, content, { encoding: "utf-8" });
76006
76346
  return {
76007
76347
  success: true,
76008
76348
  backupPath: backupPath ?? undefined
@@ -76438,7 +76778,7 @@ __export(exports_custom, {
76438
76778
  });
76439
76779
  import { existsSync as existsSync15 } from "node:fs";
76440
76780
  import { readdir as readdir9, readFile as readFile9 } from "node:fs/promises";
76441
- import { basename as basename4, dirname as dirname12, join as join24 } from "node:path";
76781
+ import { basename as basename4, dirname as dirname12, join as join25 } from "node:path";
76442
76782
  async function getCustomCommands() {
76443
76783
  if (cachedCommands !== null) {
76444
76784
  return cachedCommands;
@@ -76449,7 +76789,7 @@ async function getCustomCommands() {
76449
76789
  function refreshCustomCommands() {
76450
76790
  cachedCommands = null;
76451
76791
  }
76452
- async function discoverCustomCommands(projectPath = join24(process.cwd(), COMMANDS_DIR)) {
76792
+ async function discoverCustomCommands(projectPath = join25(process.cwd(), COMMANDS_DIR)) {
76453
76793
  const commandsById = new Map;
76454
76794
  const userCommands = await discoverFromDirectory(GLOBAL_COMMANDS_DIR, "user");
76455
76795
  for (const cmd of userCommands) {
@@ -76481,7 +76821,7 @@ async function findCommandFiles(currentPath, rootPath, commands2, source) {
76481
76821
  try {
76482
76822
  const entries = await readdir9(currentPath, { withFileTypes: true });
76483
76823
  for (const entry of entries) {
76484
- const fullPath = join24(currentPath, entry.name);
76824
+ const fullPath = join25(currentPath, entry.name);
76485
76825
  if (entry.isDirectory()) {
76486
76826
  await findCommandFiles(fullPath, rootPath, commands2, source);
76487
76827
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -76566,7 +76906,7 @@ async function findCustomCommand(commandName) {
76566
76906
  }
76567
76907
  var COMMANDS_DIR = ".commands", GLOBAL_COMMANDS_DIR, cachedCommands = null;
76568
76908
  var init_custom = __esm(() => {
76569
- GLOBAL_COMMANDS_DIR = join24(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
76909
+ GLOBAL_COMMANDS_DIR = join25(process.env.HOME || process.env.USERPROFILE || "~", ".letta/commands");
76570
76910
  });
76571
76911
 
76572
76912
  // src/cli/components/HelpDialog.tsx
@@ -80879,7 +81219,7 @@ var init_AgentInfoBar = __esm(async () => {
80879
81219
 
80880
81220
  // src/cli/helpers/fileSearch.ts
80881
81221
  import { readdirSync as readdirSync5, statSync as statSync5 } from "node:fs";
80882
- import { join as join25, resolve as resolve21 } from "node:path";
81222
+ import { join as join26, resolve as resolve21 } from "node:path";
80883
81223
  function shouldExcludeEntry(entry) {
80884
81224
  if (entry.startsWith(".")) {
80885
81225
  return true;
@@ -80897,7 +81237,7 @@ function searchDirectoryRecursive(dir, pattern, maxResults = 200, results = [],
80897
81237
  continue;
80898
81238
  }
80899
81239
  try {
80900
- const fullPath = join25(dir, entry);
81240
+ const fullPath = join26(dir, entry);
80901
81241
  const stats = statSync5(fullPath);
80902
81242
  const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
80903
81243
  const matches = pattern.length === 0 || relativePath.toLowerCase().includes(pattern.toLowerCase());
@@ -80952,7 +81292,7 @@ async function searchFiles(query, deep = false) {
80952
81292
  const matchingEntries = entries.filter((entry) => !shouldExcludeEntry(entry)).filter((entry) => searchPattern.length === 0 || entry.toLowerCase().includes(searchPattern.toLowerCase()));
80953
81293
  for (const entry of matchingEntries.slice(0, 50)) {
80954
81294
  try {
80955
- const fullPath = join25(searchDir, entry);
81295
+ const fullPath = join26(searchDir, entry);
80956
81296
  const stats = statSync5(fullPath);
80957
81297
  const relativePath = fullPath.startsWith(process.cwd()) ? fullPath.slice(process.cwd().length + 1) : fullPath;
80958
81298
  results.push({
@@ -81797,7 +82137,8 @@ function Input({
81797
82137
  shouldAnimate = true,
81798
82138
  statusLineText,
81799
82139
  statusLineRight,
81800
- statusLinePadding = 0
82140
+ statusLinePadding = 0,
82141
+ statusLinePrompt
81801
82142
  }) {
81802
82143
  const [value, setValue] = import_react68.useState("");
81803
82144
  const [escapePressed, setEscapePressed] = import_react68.useState(false);
@@ -81810,7 +82151,10 @@ function Input({
81810
82151
  const [cursorPos, setCursorPos] = import_react68.useState(undefined);
81811
82152
  const [currentCursorPosition, setCurrentCursorPosition] = import_react68.useState(0);
81812
82153
  const columns = terminalWidth;
81813
- const contentWidth = Math.max(0, columns - 2);
82154
+ const [isBashMode, setIsBashMode] = import_react68.useState(false);
82155
+ const promptChar = isBashMode ? "!" : statusLinePrompt || ">";
82156
+ const promptVisualWidth = stringWidth(promptChar) + 1;
82157
+ const contentWidth = Math.max(0, columns - promptVisualWidth);
81814
82158
  const interactionEnabled = visible && inputEnabled;
81815
82159
  const reserveInputSpace = !collapseInputWhenDisabled;
81816
82160
  const hideFooter = !interactionEnabled || value.startsWith("/");
@@ -81856,7 +82200,6 @@ function Input({
81856
82200
  const [atStartBoundary, setAtStartBoundary] = import_react68.useState(false);
81857
82201
  const [atEndBoundary, setAtEndBoundary] = import_react68.useState(false);
81858
82202
  const [preferredColumn, setPreferredColumn] = import_react68.useState(null);
81859
- const [isBashMode, setIsBashMode] = import_react68.useState(false);
81860
82203
  import_react68.useEffect(() => {
81861
82204
  if (restoredInput && value === "") {
81862
82205
  setValue(restoredInput);
@@ -82258,12 +82601,12 @@ function Input({
82258
82601
  flexDirection: "row",
82259
82602
  children: [
82260
82603
  /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Box_default, {
82261
- width: 2,
82604
+ width: promptVisualWidth,
82262
82605
  flexShrink: 0,
82263
82606
  children: [
82264
82607
  /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
82265
82608
  color: isBashMode ? colors.bash.prompt : colors.input.prompt,
82266
- children: isBashMode ? "!" : ">"
82609
+ children: promptChar
82267
82610
  }, undefined, false, undefined, this),
82268
82611
  /* @__PURE__ */ jsx_dev_runtime45.jsxDEV(Text2, {
82269
82612
  children: " "
@@ -82363,7 +82706,9 @@ function Input({
82363
82706
  inputChromeHeight,
82364
82707
  statusLineText,
82365
82708
  statusLineRight,
82366
- statusLinePadding
82709
+ statusLinePadding,
82710
+ promptChar,
82711
+ promptVisualWidth
82367
82712
  ]);
82368
82713
  if (!visible) {
82369
82714
  return null;
@@ -82409,6 +82754,7 @@ function formatElapsedLabel(ms) {
82409
82754
  var import_react68, jsx_dev_runtime45, Spinner2, ESC_CLEAR_WINDOW_MS = 2500, FOOTER_WIDTH_STREAMING_DELTA = 2, OSC8_REGEX, InputFooter, StreamingStatus;
82410
82755
  var init_InputRich = __esm(async () => {
82411
82756
  init_source();
82757
+ init_string_width();
82412
82758
  init_oauth();
82413
82759
  init_constants();
82414
82760
  init_mode();
@@ -82712,7 +83058,7 @@ var init_InputRich = __esm(async () => {
82712
83058
  async function connectMcpServer(config, options = {}) {
82713
83059
  const { onEvent, abortSignal } = options;
82714
83060
  const settings = await settingsManager.getSettingsWithSecureTokens();
82715
- const baseUrl = getServerUrl2();
83061
+ const baseUrl = getServerUrl();
82716
83062
  const apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
82717
83063
  if (!apiKey) {
82718
83064
  throw new Error("Missing LETTA_API_KEY");
@@ -84121,7 +84467,7 @@ var init_McpSelector = __esm(async () => {
84121
84467
 
84122
84468
  // src/cli/components/MemfsTreeViewer.tsx
84123
84469
  import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync5, statSync as statSync6 } from "node:fs";
84124
- import { join as join26, relative as relative4 } from "node:path";
84470
+ import { join as join27, relative as relative4 } from "node:path";
84125
84471
  function scanMemoryFilesystem(memoryRoot) {
84126
84472
  const nodes = [];
84127
84473
  const scanDir = (dir, depth, parentIsLast) => {
@@ -84133,8 +84479,8 @@ function scanMemoryFilesystem(memoryRoot) {
84133
84479
  }
84134
84480
  const filtered = entries.filter((name) => !name.startsWith("."));
84135
84481
  const sorted = filtered.sort((a, b) => {
84136
- const aPath = join26(dir, a);
84137
- const bPath = join26(dir, b);
84482
+ const aPath = join27(dir, a);
84483
+ const bPath = join27(dir, b);
84138
84484
  let aIsDir = false;
84139
84485
  let bIsDir = false;
84140
84486
  try {
@@ -84154,7 +84500,7 @@ function scanMemoryFilesystem(memoryRoot) {
84154
84500
  return a.localeCompare(b);
84155
84501
  });
84156
84502
  sorted.forEach((name, index) => {
84157
- const fullPath = join26(dir, name);
84503
+ const fullPath = join27(dir, name);
84158
84504
  let isDir = false;
84159
84505
  try {
84160
84506
  isDir = statSync6(fullPath).isDirectory();
@@ -86612,10 +86958,10 @@ var init_byok_providers = __esm(async () => {
86612
86958
  // src/utils/aws-credentials.ts
86613
86959
  import { readFile as readFile10 } from "node:fs/promises";
86614
86960
  import { homedir as homedir17 } from "node:os";
86615
- import { join as join27 } from "node:path";
86961
+ import { join as join28 } from "node:path";
86616
86962
  async function parseAwsCredentials() {
86617
- const credentialsPath = join27(homedir17(), ".aws", "credentials");
86618
- const configPath = join27(homedir17(), ".aws", "config");
86963
+ const credentialsPath = join28(homedir17(), ".aws", "credentials");
86964
+ const configPath = join28(homedir17(), ".aws", "config");
86619
86965
  const profiles = new Map;
86620
86966
  try {
86621
86967
  const content = await readFile10(credentialsPath, "utf-8");
@@ -87847,7 +88193,7 @@ function SleeptimeSelector({
87847
88193
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87848
88194
  bold: true,
87849
88195
  color: colors.selector.title,
87850
- children: "Configure your sleeptime (reflection) settings"
88196
+ children: "Configure your sleep-time (reflection) settings"
87851
88197
  }, undefined, false, undefined, this),
87852
88198
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Box_default, {
87853
88199
  height: 1
@@ -87862,7 +88208,7 @@ function SleeptimeSelector({
87862
88208
  }, undefined, false, undefined, this),
87863
88209
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87864
88210
  bold: true,
87865
- children: "Trigger:"
88211
+ children: "Trigger event:"
87866
88212
  }, undefined, false, undefined, this),
87867
88213
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87868
88214
  children: " "
@@ -87906,7 +88252,7 @@ function SleeptimeSelector({
87906
88252
  }, undefined, false, undefined, this),
87907
88253
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87908
88254
  bold: true,
87909
- children: "Trigger behavior:"
88255
+ children: "Forced:"
87910
88256
  }, undefined, false, undefined, this),
87911
88257
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87912
88258
  children: " "
@@ -87915,7 +88261,7 @@ function SleeptimeSelector({
87915
88261
  backgroundColor: behavior === "reminder" ? colors.selector.itemHighlighted : undefined,
87916
88262
  color: behavior === "reminder" ? "black" : undefined,
87917
88263
  bold: behavior === "reminder",
87918
- children: " Reminder "
88264
+ children: " No (reminder only) "
87919
88265
  }, undefined, false, undefined, this),
87920
88266
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87921
88267
  children: " "
@@ -87924,7 +88270,7 @@ function SleeptimeSelector({
87924
88270
  backgroundColor: behavior === "auto-launch" ? colors.selector.itemHighlighted : undefined,
87925
88271
  color: behavior === "auto-launch" ? "black" : undefined,
87926
88272
  bold: behavior === "auto-launch",
87927
- children: " Auto-launch "
88273
+ children: " Yes (auto-launch) "
87928
88274
  }, undefined, false, undefined, this)
87929
88275
  ]
87930
88276
  }, undefined, true, undefined, this)
@@ -87970,7 +88316,7 @@ function SleeptimeSelector({
87970
88316
  }, undefined, false, undefined, this),
87971
88317
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87972
88318
  bold: true,
87973
- children: "Trigger:"
88319
+ children: "Trigger event:"
87974
88320
  }, undefined, false, undefined, this),
87975
88321
  /* @__PURE__ */ jsx_dev_runtime57.jsxDEV(Text2, {
87976
88322
  children: " "
@@ -91022,18 +91368,20 @@ function wordWrap(text, width) {
91022
91368
  }
91023
91369
  function splitSystemReminderBlocks(text) {
91024
91370
  const blocks = [];
91025
- const tagOpen = SYSTEM_REMINDER_OPEN;
91026
- const tagClose = SYSTEM_REMINDER_CLOSE;
91371
+ const tags = [
91372
+ { open: SYSTEM_REMINDER_OPEN, close: SYSTEM_REMINDER_CLOSE },
91373
+ { open: SYSTEM_ALERT_OPEN, close: SYSTEM_ALERT_CLOSE }
91374
+ ];
91027
91375
  let remaining = text;
91028
91376
  while (remaining.length > 0) {
91029
- const openIdx = remaining.indexOf(tagOpen);
91030
- if (openIdx === -1) {
91377
+ const nextTag = tags.map((tag) => ({ ...tag, idx: remaining.indexOf(tag.open) })).filter((tag) => tag.idx >= 0).sort((a, b) => a.idx - b.idx)[0];
91378
+ if (!nextTag) {
91031
91379
  if (remaining.trim()) {
91032
91380
  blocks.push({ text: remaining.trim(), isSystemReminder: false });
91033
91381
  }
91034
91382
  break;
91035
91383
  }
91036
- const closeIdx = remaining.indexOf(tagClose, openIdx);
91384
+ const closeIdx = remaining.indexOf(nextTag.close, nextTag.idx);
91037
91385
  if (closeIdx === -1) {
91038
91386
  const literal = remaining.trim();
91039
91387
  if (literal) {
@@ -91041,19 +91389,19 @@ function splitSystemReminderBlocks(text) {
91041
91389
  }
91042
91390
  break;
91043
91391
  }
91044
- if (openIdx > 0) {
91045
- const before = remaining.slice(0, openIdx).trim();
91392
+ if (nextTag.idx > 0) {
91393
+ const before = remaining.slice(0, nextTag.idx).trim();
91046
91394
  if (before) {
91047
91395
  blocks.push({ text: before, isSystemReminder: false });
91048
91396
  }
91049
91397
  }
91050
- const sysBlock = remaining.slice(openIdx, closeIdx + tagClose.length);
91398
+ const sysBlock = remaining.slice(nextTag.idx, closeIdx + nextTag.close.length);
91051
91399
  blocks.push({ text: sysBlock, isSystemReminder: true });
91052
- remaining = remaining.slice(closeIdx + tagClose.length);
91400
+ remaining = remaining.slice(closeIdx + nextTag.close.length);
91053
91401
  }
91054
91402
  return blocks;
91055
91403
  }
91056
- function renderBlock(text, contentWidth, columns, highlighted, colorAnsi) {
91404
+ function renderBlock(text, contentWidth, columns, highlighted, colorAnsi, promptPrefix, continuationPrefix) {
91057
91405
  const inputLines = text.split(`
91058
91406
  `);
91059
91407
  const outputLines = [];
@@ -91071,11 +91419,11 @@ function renderBlock(text, contentWidth, columns, highlighted, colorAnsi) {
91071
91419
  return [];
91072
91420
  const isSingleLine = outputLines.length === 1;
91073
91421
  return outputLines.map((ol, i) => {
91074
- const prefix = i === 0 ? "> " : " ";
91075
- const content = prefix + ol;
91422
+ const prefix = i === 0 ? promptPrefix : continuationPrefix;
91076
91423
  if (!highlighted) {
91077
- return content;
91424
+ return prefix + ol;
91078
91425
  }
91426
+ const content = i === 0 ? `${promptPrefix.slice(0, -1)}${colorAnsi} ${ol}` : `${prefix}${ol}`;
91079
91427
  const visWidth = stringWidth(content);
91080
91428
  if (isSingleLine) {
91081
91429
  return `${colorAnsi}${content}${" ".repeat(COMPACT_PAD)}\x1B[0m`;
@@ -91093,9 +91441,12 @@ var init_UserMessageRich = __esm(async () => {
91093
91441
  await init_Text2();
91094
91442
  import_react89 = __toESM(require_react(), 1);
91095
91443
  jsx_dev_runtime69 = __toESM(require_jsx_dev_runtime(), 1);
91096
- UserMessage = import_react89.memo(({ line }) => {
91444
+ UserMessage = import_react89.memo(({ line, prompt }) => {
91097
91445
  const columns = useTerminalWidth();
91098
- const contentWidth = Math.max(1, columns - 2);
91446
+ const promptPrefix = `${prompt || ">"} `;
91447
+ const prefixWidth = stringWidth(promptPrefix);
91448
+ const continuationPrefix = " ".repeat(prefixWidth);
91449
+ const contentWidth = Math.max(1, columns - prefixWidth);
91099
91450
  const cleanedText = extractTaskNotificationsForDisplay(line.text).cleanedText;
91100
91451
  const displayText = cleanedText.trim();
91101
91452
  if (!displayText) {
@@ -91113,7 +91464,7 @@ var init_UserMessageRich = __esm(async () => {
91113
91464
  if (allLines.length > 0) {
91114
91465
  allLines.push("");
91115
91466
  }
91116
- const blockLines = renderBlock(block.text, contentWidth, columns, !block.isSystemReminder, colorAnsi);
91467
+ const blockLines = renderBlock(block.text, contentWidth, columns, !block.isSystemReminder, colorAnsi, promptPrefix, continuationPrefix);
91117
91468
  allLines.push(...blockLines);
91118
91469
  }
91119
91470
  return /* @__PURE__ */ jsx_dev_runtime69.jsxDEV(Text2, {
@@ -91597,7 +91948,7 @@ var init_memoryReminder = __esm(async () => {
91597
91948
  init_debug();
91598
91949
  await init_settings_manager();
91599
91950
  DEFAULT_REFLECTION_SETTINGS = {
91600
- trigger: "step-count",
91951
+ trigger: "compaction-event",
91601
91952
  behavior: "reminder",
91602
91953
  stepCount: DEFAULT_STEP_COUNT2
91603
91954
  };
@@ -91823,7 +92174,8 @@ function normalizeStatusLineConfig(config) {
91823
92174
  timeout: Math.min(MAX_STATUS_LINE_TIMEOUT_MS, Math.max(1000, config.timeout ?? DEFAULT_STATUS_LINE_TIMEOUT_MS)),
91824
92175
  debounceMs: Math.max(MIN_STATUS_LINE_DEBOUNCE_MS, Math.min(MAX_STATUS_LINE_DEBOUNCE_MS, config.debounceMs ?? DEFAULT_STATUS_LINE_DEBOUNCE_MS)),
91825
92176
  ...refreshIntervalMs !== undefined && { refreshIntervalMs },
91826
- ...config.disabled !== undefined && { disabled: config.disabled }
92177
+ ...config.disabled !== undefined && { disabled: config.disabled },
92178
+ ...config.prompt !== undefined && { prompt: config.prompt }
91827
92179
  };
91828
92180
  }
91829
92181
  function isStatusLineDisabled(workingDirectory = process.cwd()) {
@@ -91874,6 +92226,31 @@ function resolveStatusLineConfig(workingDirectory = process.cwd()) {
91874
92226
  return null;
91875
92227
  }
91876
92228
  }
92229
+ function resolvePromptChar(workingDirectory = process.cwd()) {
92230
+ try {
92231
+ if (isStatusLineDisabled(workingDirectory))
92232
+ return ">";
92233
+ try {
92234
+ const local = settingsManager.getLocalProjectSettings(workingDirectory)?.statusLine;
92235
+ if (local?.prompt !== undefined)
92236
+ return local.prompt;
92237
+ } catch {}
92238
+ try {
92239
+ const project = settingsManager.getProjectSettings(workingDirectory)?.statusLine;
92240
+ if (project?.prompt !== undefined)
92241
+ return project.prompt;
92242
+ } catch {}
92243
+ try {
92244
+ const global2 = settingsManager.getSettings().statusLine;
92245
+ if (global2?.prompt !== undefined)
92246
+ return global2.prompt;
92247
+ } catch {}
92248
+ return ">";
92249
+ } catch (error) {
92250
+ debugLog("statusline", "resolvePromptChar: Failed to resolve prompt", error);
92251
+ return ">";
92252
+ }
92253
+ }
91877
92254
  var MIN_STATUS_LINE_INTERVAL_MS = 1000, DEFAULT_STATUS_LINE_TIMEOUT_MS = 5000, MAX_STATUS_LINE_TIMEOUT_MS = 30000, DEFAULT_STATUS_LINE_DEBOUNCE_MS = 300, MIN_STATUS_LINE_DEBOUNCE_MS = 50, MAX_STATUS_LINE_DEBOUNCE_MS = 5000, MAX_STATUS_LINE_PADDING = 16;
91878
92255
  var init_statusLineConfig = __esm(async () => {
91879
92256
  init_debug();
@@ -91939,7 +92316,8 @@ function formatStatusLineHelp() {
91939
92316
  ' "padding": 2,',
91940
92317
  ' "timeout": 5000,',
91941
92318
  ' "debounceMs": 300,',
91942
- ' "refreshIntervalMs": 10000',
92319
+ ' "refreshIntervalMs": 10000,',
92320
+ ' "prompt": "→"',
91943
92321
  " }",
91944
92322
  "",
91945
92323
  ' type must be "command"',
@@ -91948,6 +92326,7 @@ function formatStatusLineHelp() {
91948
92326
  " timeout command timeout in ms (default 5000, max 30000)",
91949
92327
  " debounceMs event debounce in ms (default 300)",
91950
92328
  " refreshIntervalMs optional polling interval in ms (off by default)",
92329
+ ' prompt custom input prompt character (default ">")',
91951
92330
  "",
91952
92331
  "INPUT (via JSON stdin)",
91953
92332
  fieldList
@@ -92382,6 +92761,7 @@ function useConfigurableStatusLine(inputs) {
92382
92761
  const [executing, setExecuting] = import_react90.useState(false);
92383
92762
  const [lastError, setLastError] = import_react90.useState(null);
92384
92763
  const [padding, setPadding] = import_react90.useState(0);
92764
+ const [prompt, setPrompt] = import_react90.useState(">");
92385
92765
  const inputsRef = import_react90.useRef(inputs);
92386
92766
  const configRef = import_react90.useRef(null);
92387
92767
  const abortRef = import_react90.useRef(null);
@@ -92405,6 +92785,7 @@ function useConfigurableStatusLine(inputs) {
92405
92785
  const resolveActiveConfig = import_react90.useCallback(() => {
92406
92786
  const workingDirectory = inputsRef.current.currentDirectory;
92407
92787
  const config = resolveStatusLineConfig(workingDirectory);
92788
+ setPrompt(resolvePromptChar(workingDirectory));
92408
92789
  if (!config) {
92409
92790
  configRef.current = null;
92410
92791
  abortRef.current?.abort();
@@ -92497,7 +92878,7 @@ function useConfigurableStatusLine(inputs) {
92497
92878
  scheduleDebouncedRun,
92498
92879
  currentDirectory
92499
92880
  ]);
92500
- return { text, rightText, active, executing, lastError, padding };
92881
+ return { text, rightText, active, executing, lastError, padding, prompt };
92501
92882
  }
92502
92883
  var import_react90, RS = "\x1E";
92503
92884
  var init_useConfigurableStatusLine = __esm(async () => {
@@ -92568,7 +92949,7 @@ __export(exports_shellAliases, {
92568
92949
  });
92569
92950
  import { existsSync as existsSync17, readFileSync as readFileSync6 } from "node:fs";
92570
92951
  import { homedir as homedir18 } from "node:os";
92571
- import { join as join28 } from "node:path";
92952
+ import { join as join29 } from "node:path";
92572
92953
  function parseAliasesFromFile(filePath) {
92573
92954
  const aliases = new Map;
92574
92955
  if (!existsSync17(filePath)) {
@@ -92640,7 +93021,7 @@ function loadAliases(forceReload = false) {
92640
93021
  const home = homedir18();
92641
93022
  const allAliases = new Map;
92642
93023
  for (const file of ALIAS_FILES) {
92643
- const filePath = join28(home, file);
93024
+ const filePath = join29(home, file);
92644
93025
  const fileAliases = parseAliasesFromFile(filePath);
92645
93026
  for (const [name, value] of fileAliases) {
92646
93027
  allAliases.set(name, value);
@@ -93783,9 +94164,9 @@ var exports_App = {};
93783
94164
  __export(exports_App, {
93784
94165
  default: () => App2
93785
94166
  });
93786
- import { existsSync as existsSync18, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync6 } from "node:fs";
93787
- import { homedir as homedir19, tmpdir as tmpdir3 } from "node:os";
93788
- import { join as join29 } from "node:path";
94167
+ import { existsSync as existsSync18, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync7 } from "node:fs";
94168
+ import { homedir as homedir19, tmpdir as tmpdir4 } from "node:os";
94169
+ import { join as join30 } from "node:path";
93789
94170
  function getErrorHintForStopReason(stopReason, currentModelId) {
93790
94171
  if (currentModelId === "opus" && stopReason === "llm_api_error" && getModelInfo("bedrock-opus")) {
93791
94172
  return OPUS_BEDROCK_FALLBACK_HINT;
@@ -94036,7 +94417,7 @@ ${SYSTEM_REMINDER_CLOSE}`;
94036
94417
  }
94037
94418
  }
94038
94419
  function stripSystemReminders(text) {
94039
- return text.replace(new RegExp(`${SYSTEM_REMINDER_OPEN}[\\s\\S]*?${SYSTEM_REMINDER_CLOSE}`, "g"), "").trim();
94420
+ return text.replace(new RegExp(`${SYSTEM_REMINDER_OPEN}[\\s\\S]*?${SYSTEM_REMINDER_CLOSE}`, "g"), "").replace(new RegExp(`${SYSTEM_ALERT_OPEN}[\\s\\S]*?${SYSTEM_ALERT_CLOSE}`, "g"), "").trim();
94040
94421
  }
94041
94422
  function formatReflectionSettings(settings) {
94042
94423
  if (settings.trigger === "off") {
@@ -94422,6 +94803,7 @@ function App2({
94422
94803
  restoreQueueOnCancelRef.current = restoreQueueOnCancel;
94423
94804
  }, [restoreQueueOnCancel]);
94424
94805
  const lastSentInputRef = import_react93.useRef(null);
94806
+ const pendingInterruptRecoveryConversationIdRef = import_react93.useRef(null);
94425
94807
  const [dequeueEpoch, setDequeueEpoch] = import_react93.useState(0);
94426
94808
  const lastDequeuedMessageRef = import_react93.useRef(null);
94427
94809
  const [restoredInput, setRestoredInput] = import_react93.useState(null);
@@ -95393,7 +95775,8 @@ ${newState.originalPrompt}`
95393
95775
  abortControllerRef.current = new AbortController;
95394
95776
  const originalInput = currentInput;
95395
95777
  const cacheIsAllUserMsgs = lastSentInputRef.current?.every((m) => m.type === "message" && m.role === "user");
95396
- if (cacheIsAllUserMsgs && lastSentInputRef.current) {
95778
+ const canInjectInterruptRecovery = pendingInterruptRecoveryConversationIdRef.current !== null && pendingInterruptRecoveryConversationIdRef.current === conversationIdRef.current;
95779
+ if (cacheIsAllUserMsgs && lastSentInputRef.current && canInjectInterruptRecovery) {
95397
95780
  currentInput = [
95398
95781
  ...lastSentInputRef.current,
95399
95782
  ...currentInput.map((m) => m.type === "message" && m.role === "user" ? {
@@ -95404,11 +95787,13 @@ ${newState.originalPrompt}`
95404
95787
  ]
95405
95788
  } : m)
95406
95789
  ];
95790
+ pendingInterruptRecoveryConversationIdRef.current = null;
95407
95791
  lastSentInputRef.current = [
95408
95792
  ...lastSentInputRef.current,
95409
95793
  ...originalInput
95410
95794
  ];
95411
95795
  } else {
95796
+ pendingInterruptRecoveryConversationIdRef.current = null;
95412
95797
  lastSentInputRef.current = originalInput;
95413
95798
  }
95414
95799
  if (!allowReentry) {
@@ -95447,21 +95832,26 @@ ${newState.originalPrompt}`
95447
95832
  try {
95448
95833
  stream2 = await sendMessageStream(conversationIdRef.current, currentInput, { agentId: agentIdRef.current });
95449
95834
  } catch (preStreamError) {
95450
- let errorDetail = "";
95451
- if (preStreamError instanceof APIError2 && preStreamError.error && typeof preStreamError.error === "object") {
95452
- const errObj = preStreamError.error;
95453
- if (errObj.error && typeof errObj.error === "object" && "detail" in errObj.error) {
95454
- const nested = errObj.error;
95455
- errorDetail = typeof nested.detail === "string" ? nested.detail : "";
95456
- }
95457
- if (!errorDetail && typeof errObj.detail === "string") {
95458
- errorDetail = errObj.detail;
95835
+ const errorDetail = extractConflictDetail(preStreamError);
95836
+ const preStreamAction = getPreStreamErrorAction(errorDetail, conversationBusyRetriesRef.current, CONVERSATION_BUSY_MAX_RETRIES2);
95837
+ if (shouldAttemptApprovalRecovery({
95838
+ approvalPendingDetected: preStreamAction === "resolve_approval_pending",
95839
+ retries: llmApiErrorRetriesRef.current,
95840
+ maxRetries: LLM_API_ERROR_MAX_RETRIES2
95841
+ })) {
95842
+ llmApiErrorRetriesRef.current += 1;
95843
+ try {
95844
+ const client = await getClient2();
95845
+ const agent = await client.agents.retrieve(agentIdRef.current);
95846
+ const { pendingApprovals: existingApprovals } = await getResumeData2(client, agent, conversationIdRef.current);
95847
+ currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
95848
+ } catch {
95849
+ currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
95459
95850
  }
95851
+ buffersRef.current.interrupted = false;
95852
+ continue;
95460
95853
  }
95461
- if (!errorDetail && preStreamError instanceof Error) {
95462
- errorDetail = preStreamError.message;
95463
- }
95464
- if (isConversationBusyError(errorDetail) && conversationBusyRetriesRef.current < CONVERSATION_BUSY_MAX_RETRIES2) {
95854
+ if (preStreamAction === "retry_conversation_busy") {
95465
95855
  conversationBusyRetriesRef.current += 1;
95466
95856
  const retryDelayMs = CONVERSATION_BUSY_RETRY_BASE_DELAY_MS * 2 ** (conversationBusyRetriesRef.current - 1);
95467
95857
  const statusId = uid4("status");
@@ -95505,7 +95895,7 @@ ${newState.originalPrompt}`
95505
95895
  if (typeof content === "string") {
95506
95896
  textToRestore = stripSystemReminders(content);
95507
95897
  } else if (Array.isArray(content)) {
95508
- textToRestore = content.filter((c) => typeof c === "object" && c !== null && ("type" in c) && c.type === "text" && ("text" in c) && typeof c.text === "string" && !c.text.includes(SYSTEM_REMINDER_OPEN)).map((c) => c.text).join(`
95898
+ textToRestore = content.filter((c) => typeof c === "object" && c !== null && ("type" in c) && c.type === "text" && ("text" in c) && typeof c.text === "string" && !c.text.includes(SYSTEM_REMINDER_OPEN) && !c.text.includes(SYSTEM_ALERT_OPEN)).map((c) => c.text).join(`
95509
95899
  `);
95510
95900
  }
95511
95901
  if (textToRestore.trim()) {
@@ -95630,6 +96020,7 @@ ${newState.originalPrompt}`
95630
96020
  conversationBusyRetriesRef.current = 0;
95631
96021
  lastDequeuedMessageRef.current = null;
95632
96022
  lastSentInputRef.current = null;
96023
+ pendingInterruptRecoveryConversationIdRef.current = null;
95633
96024
  const lastAssistant = Array.from(buffersRef.current.byId.values()).findLast((item) => item.kind === "assistant" && ("text" in item));
95634
96025
  const assistantMessage = lastAssistant && "text" in lastAssistant ? lastAssistant.text : undefined;
95635
96026
  const lastUser = Array.from(buffersRef.current.byId.values()).findLast((item) => item.kind === "user" && ("text" in item));
@@ -95750,6 +96141,7 @@ ${feedback}
95750
96141
  setAutoHandledResults([]);
95751
96142
  setAutoDeniedApprovals([]);
95752
96143
  lastSentInputRef.current = null;
96144
+ pendingInterruptRecoveryConversationIdRef.current = null;
95753
96145
  const approvalsToProcess = approvals && approvals.length > 0 ? approvals : approval ? [approval] : [];
95754
96146
  if (approvalsToProcess.length === 0) {
95755
96147
  appendError(`Unexpected empty approvals with stop reason: ${stopReason}`);
@@ -96080,7 +96472,7 @@ ${feedback}
96080
96472
  if (typeof content === "string") {
96081
96473
  textToRestore = stripSystemReminders(content);
96082
96474
  } else if (Array.isArray(content)) {
96083
- textToRestore = content.filter((c) => typeof c === "object" && c !== null && ("type" in c) && c.type === "text" && ("text" in c) && typeof c.text === "string" && !c.text.includes(SYSTEM_REMINDER_OPEN)).map((c) => c.text).join(`
96475
+ textToRestore = content.filter((c) => typeof c === "object" && c !== null && ("type" in c) && c.type === "text" && ("text" in c) && typeof c.text === "string" && !c.text.includes(SYSTEM_REMINDER_OPEN) && !c.text.includes(SYSTEM_ALERT_OPEN)).map((c) => c.text).join(`
96084
96476
  `);
96085
96477
  }
96086
96478
  if (textToRestore.trim()) {
@@ -96107,26 +96499,20 @@ ${feedback}
96107
96499
  } catch {}
96108
96500
  }
96109
96501
  const approvalPendingDetected = isApprovalPendingError(detailFromRun) || isApprovalPendingError(latestErrorText);
96110
- if (!hasApprovalInPayload && approvalPendingDetected && llmApiErrorRetriesRef.current < LLM_API_ERROR_MAX_RETRIES2) {
96502
+ if (shouldAttemptApprovalRecovery({
96503
+ approvalPendingDetected,
96504
+ retries: llmApiErrorRetriesRef.current,
96505
+ maxRetries: LLM_API_ERROR_MAX_RETRIES2
96506
+ })) {
96111
96507
  llmApiErrorRetriesRef.current += 1;
96112
96508
  try {
96113
96509
  const client = await getClient2();
96114
96510
  const agent = await client.agents.retrieve(agentIdRef.current);
96115
96511
  const { pendingApprovals: existingApprovals } = await getResumeData2(client, agent, conversationIdRef.current);
96116
- if (existingApprovals && existingApprovals.length > 0) {
96117
- const denialResults = existingApprovals.map((approval2) => ({
96118
- type: "approval",
96119
- tool_call_id: approval2.toolCallId,
96120
- approve: false,
96121
- reason: "Auto-denied: stale approval from interrupted session"
96122
- }));
96123
- const approvalPayload = {
96124
- type: "approval",
96125
- approvals: denialResults
96126
- };
96127
- currentInput.unshift(approvalPayload);
96128
- }
96129
- } catch {}
96512
+ currentInput = rebuildInputWithFreshDenials(currentInput, existingApprovals ?? [], "Auto-denied: stale approval from interrupted session");
96513
+ } catch {
96514
+ currentInput = rebuildInputWithFreshDenials(currentInput, [], "");
96515
+ }
96130
96516
  buffersRef.current.interrupted = false;
96131
96517
  continue;
96132
96518
  }
@@ -96136,9 +96522,7 @@ ${feedback}
96136
96522
  const attempt = llmApiErrorRetriesRef.current;
96137
96523
  const delayMs = 1000 * 2 ** (attempt - 1);
96138
96524
  const statusId = uid4("status");
96139
- const statusLines = [
96140
- "Unexpected downstream LLM API error, retrying..."
96141
- ];
96525
+ const statusLines = [getRetryStatusMessage(detailFromRun)];
96142
96526
  buffersRef.current.byId.set(statusId, {
96143
96527
  kind: "status",
96144
96528
  id: statusId,
@@ -96356,11 +96740,18 @@ ${feedback}
96356
96740
  abortControllerRef.current.abort();
96357
96741
  abortControllerRef.current = null;
96358
96742
  }
96743
+ pendingInterruptRecoveryConversationIdRef.current = conversationIdRef.current;
96359
96744
  userCancelledRef.current = true;
96360
96745
  setStreaming(false);
96361
96746
  setIsExecutingTool(false);
96362
96747
  toolResultsInFlightRef.current = false;
96363
96748
  refreshDerived();
96749
+ getClient2().then((client) => {
96750
+ if (conversationIdRef.current === "default") {
96751
+ return client.agents.messages.cancel(agentIdRef.current);
96752
+ }
96753
+ return client.conversations.cancel(conversationIdRef.current);
96754
+ }).catch(() => {});
96364
96755
  setTimeout(() => {
96365
96756
  userCancelledRef.current = false;
96366
96757
  }, 50);
@@ -96381,6 +96772,7 @@ ${feedback}
96381
96772
  abortControllerRef.current.abort();
96382
96773
  abortControllerRef.current = null;
96383
96774
  }
96775
+ pendingInterruptRecoveryConversationIdRef.current = conversationIdRef.current;
96384
96776
  userCancelledRef.current = true;
96385
96777
  conversationGenerationRef.current += 1;
96386
96778
  processingConversationRef.current = 0;
@@ -96446,6 +96838,7 @@ ${feedback}
96446
96838
  if (abortControllerRef.current) {
96447
96839
  abortControllerRef.current.abort();
96448
96840
  }
96841
+ pendingInterruptRecoveryConversationIdRef.current = conversationIdRef.current;
96449
96842
  } catch (e) {
96450
96843
  const errorDetails = formatErrorDetails(e, agentId);
96451
96844
  appendError(`Failed to interrupt stream: ${errorDetails}`);
@@ -96956,7 +97349,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
96956
97349
  return { submitted: true };
96957
97350
  }
96958
97351
  if (trimmed === "/ade") {
96959
- const adeUrl = `https://app.letta.com/agents/${agentId}?conversation=${conversationIdRef.current}`;
97352
+ const adeUrl = conversationIdRef.current === "default" ? `https://app.letta.com/agents/${agentId}` : `https://app.letta.com/agents/${agentId}?conversation=${conversationIdRef.current}`;
96960
97353
  const cmd = commandRunner.start("/ade", "Opening ADE...");
96961
97354
  Promise.resolve().then(() => (init_open(), exports_open)).then(({ default: open2 }) => open2(adeUrl, { wait: false })).catch(() => {});
96962
97355
  cmd.finish(`Opening ADE...
@@ -97110,6 +97503,8 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
97110
97503
  }
97111
97504
  const effective = resolveStatusLineConfig(wd);
97112
97505
  lines2.push(`Effective: ${effective ? `command="${effective.command}" refreshInterval=${effective.refreshIntervalMs ?? "off"} timeout=${effective.timeout}ms debounce=${effective.debounceMs}ms padding=${effective.padding}` : "(inactive)"}`);
97506
+ const effectivePrompt = resolvePromptChar(wd);
97507
+ lines2.push(`Prompt: "${effectivePrompt}"`);
97113
97508
  cmd.finish(lines2.join(`
97114
97509
  `), true);
97115
97510
  } else if (sub === "set") {
@@ -97243,7 +97638,7 @@ ${SYSTEM_REMINDER_CLOSE}` : "";
97243
97638
  try {
97244
97639
  const settings = await settingsManager.getSettingsWithSecureTokens();
97245
97640
  const apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
97246
- const baseUrl = getServerUrl2();
97641
+ const baseUrl = getServerUrl();
97247
97642
  const controller = new AbortController;
97248
97643
  const timeoutId = setTimeout(() => controller.abort(), 5000);
97249
97644
  const res = await fetch(`${baseUrl}/v1/agents/${agentIdRef.current}/context`, {
@@ -97856,10 +98251,10 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
97856
98251
  let fileContent;
97857
98252
  if (skills.length > 0) {
97858
98253
  const { settingsManager: settingsManager3 } = await init_settings_manager().then(() => exports_settings_manager);
97859
- const { getServerUrl: getServerUrl3 } = await init_client2().then(() => exports_client);
98254
+ const { getServerUrl: getServerUrl2 } = await init_client2().then(() => exports_client);
97860
98255
  const settings = await settingsManager3.getSettingsWithSecureTokens();
97861
98256
  const apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
97862
- const baseUrl = getServerUrl3();
98257
+ const baseUrl = getServerUrl2();
97863
98258
  const body = {
97864
98259
  ...exportParams,
97865
98260
  skills
@@ -97880,7 +98275,7 @@ Press Enter to continue, or type anything to cancel.`, false, "running");
97880
98275
  fileContent = await client.agents.exportFile(agentId, exportParams);
97881
98276
  }
97882
98277
  const fileName = exportParams.conversation_id ? `${exportParams.conversation_id}.af` : `${agentId}.af`;
97883
- writeFileSync6(fileName, JSON.stringify(fileContent, null, 2));
98278
+ writeFileSync7(fileName, JSON.stringify(fileContent, null, 2));
97884
98279
  let summary = `AgentFile exported to ${fileName}`;
97885
98280
  if (skills.length > 0) {
97886
98281
  summary += `
@@ -97926,27 +98321,13 @@ Path: ${memoryDir}`;
97926
98321
  return { submitted: true };
97927
98322
  }
97928
98323
  if (subcommand === "enable") {
97929
- const serverUrl = getServerUrl2();
97930
- if (!serverUrl.includes("api.letta.com")) {
97931
- cmd.fail("Memory filesystem is only available on Letta Cloud (api.letta.com).");
97932
- return { submitted: true };
97933
- }
97934
98324
  updateMemorySyncCommand(cmdId, "Enabling memory filesystem...", true, msg, true);
97935
98325
  setCommandRunning(true);
97936
98326
  try {
97937
- const { detachMemoryTools: detachMemoryTools2 } = await init_toolset().then(() => exports_toolset);
97938
- await detachMemoryTools2(agentId);
97939
- settingsManager.setMemfsEnabled(agentId, true);
97940
- const { updateAgentSystemPromptMemfs: updateAgentSystemPromptMemfs2 } = await init_modify().then(() => exports_modify);
97941
- await updateAgentSystemPromptMemfs2(agentId, true);
97942
- const { addGitMemoryTag: addGitMemoryTag2, isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2 } = await init_memoryGit().then(() => exports_memoryGit);
97943
- await addGitMemoryTag2(agentId);
97944
- if (!isGitRepo2(agentId)) {
97945
- await cloneMemoryRepo2(agentId);
97946
- }
97947
- const memoryDir = getMemoryFilesystemRoot(agentId);
98327
+ const { applyMemfsFlags: applyMemfsFlags2 } = await Promise.resolve().then(() => (init_memoryFilesystem(), exports_memoryFilesystem));
98328
+ const result2 = await applyMemfsFlags2(agentId, true, false);
97948
98329
  updateMemorySyncCommand(cmdId, `Memory filesystem enabled (git-backed).
97949
- Path: ${memoryDir}`, true, msg);
98330
+ Path: ${result2.memoryDir}`, true, msg);
97950
98331
  } catch (error) {
97951
98332
  const errorText = error instanceof Error ? error.message : String(error);
97952
98333
  updateMemorySyncCommand(cmdId, `Failed to enable memfs: ${errorText}`, false, msg);
@@ -97983,7 +98364,7 @@ Path: ${memoryDir}`, true, msg);
97983
98364
  updateMemorySyncCommand(cmdId, "No local memory filesystem found to reset.", true, msg);
97984
98365
  return { submitted: true };
97985
98366
  }
97986
- const backupDir = join29(tmpdir3(), `letta-memfs-reset-${agentId}-${Date.now()}`);
98367
+ const backupDir = join30(tmpdir4(), `letta-memfs-reset-${agentId}-${Date.now()}`);
97987
98368
  renameSync2(memoryDir, backupDir);
97988
98369
  ensureMemoryFilesystemDirs(agentId);
97989
98370
  updateMemorySyncCommand(cmdId, `Memory filesystem reset.
@@ -98012,7 +98393,7 @@ Run \`/memfs sync\` to repopulate from API.`, true, msg);
98012
98393
  let backupInfo = "";
98013
98394
  const memoryDir = getMemoryFilesystemRoot(agentId);
98014
98395
  if (existsSync18(memoryDir)) {
98015
- const backupDir = join29(tmpdir3(), `letta-memfs-disable-${agentId}-${Date.now()}`);
98396
+ const backupDir = join30(tmpdir4(), `letta-memfs-disable-${agentId}-${Date.now()}`);
98016
98397
  renameSync2(memoryDir, backupDir);
98017
98398
  backupInfo = `
98018
98399
  Local files backed up to ${backupDir}`;
@@ -98356,7 +98737,7 @@ ${SYSTEM_REMINDER_CLOSE}
98356
98737
  plan: "Read-only mode. Focus on exploration and planning.",
98357
98738
  bypassPermissions: "All tools auto-approved. Bias toward action."
98358
98739
  };
98359
- permissionModeAlert = `<system-alert>Permission mode changed to: ${currentMode}. ${modeDescriptions[currentMode]}</system-alert>
98740
+ permissionModeAlert = `${SYSTEM_REMINDER_OPEN}Permission mode changed to: ${currentMode}. ${modeDescriptions[currentMode]}${SYSTEM_REMINDER_CLOSE}
98360
98741
 
98361
98742
  `;
98362
98743
  lastNotifiedModeRef.current = currentMode;
@@ -98394,9 +98775,11 @@ ${SYSTEM_REMINDER_CLOSE}
98394
98775
  if (!discoveredSkillsRef.current) {
98395
98776
  try {
98396
98777
  const { discoverSkills: discover, SKILLS_DIR: defaultDir } = await Promise.resolve().then(() => (init_skills(), exports_skills));
98397
- const { getSkillsDirectory: getSkillsDirectory2 } = await Promise.resolve().then(() => (init_context(), exports_context));
98398
- const skillsDir = getSkillsDirectory2() || join29(process.cwd(), defaultDir);
98399
- const { skills } = await discover(skillsDir, agentId);
98778
+ const { getSkillsDirectory: getSkillsDirectory2, getNoSkills: getNoSkills2 } = await Promise.resolve().then(() => (init_context(), exports_context));
98779
+ const skillsDir = getSkillsDirectory2() || join30(process.cwd(), defaultDir);
98780
+ const { skills } = await discover(skillsDir, agentId, {
98781
+ skipBundled: getNoSkills2()
98782
+ });
98400
98783
  discoveredSkillsRef.current = skills;
98401
98784
  } catch {
98402
98785
  discoveredSkillsRef.current = [];
@@ -99783,7 +100166,7 @@ ${guidance}`);
99783
100166
  }
99784
100167
  if (!planFileExists()) {
99785
100168
  const planFilePath = permissionMode2.getPlanFilePath();
99786
- const plansDir = join29(homedir19(), ".letta", "plans");
100169
+ const plansDir = join30(homedir19(), ".letta", "plans");
99787
100170
  handlePlanKeepPlanning(`You must write your plan to a plan file before exiting plan mode.
99788
100171
  ` + (planFilePath ? `Plan file path: ${planFilePath}
99789
100172
  ` : "") + `Use a write tool to create your plan in ${plansDir}, then use ExitPlanMode to present the plan to the user.`);
@@ -100069,7 +100452,8 @@ Plan file path: ${planFilePath}`;
100069
100452
  loadingState: "ready",
100070
100453
  ...item.snapshot
100071
100454
  }, undefined, false, undefined, this) : item.kind === "user" ? /* @__PURE__ */ jsx_dev_runtime70.jsxDEV(UserMessage, {
100072
- line: item
100455
+ line: item,
100456
+ prompt: statusLine.prompt
100073
100457
  }, undefined, false, undefined, this) : item.kind === "reasoning" ? /* @__PURE__ */ jsx_dev_runtime70.jsxDEV(ReasoningMessage, {
100074
100458
  line: item
100075
100459
  }, undefined, false, undefined, this) : item.kind === "assistant" ? /* @__PURE__ */ jsx_dev_runtime70.jsxDEV(AssistantMessage, {
@@ -100156,7 +100540,8 @@ Plan file path: ${planFilePath}`;
100156
100540
  allowPersistence: currentApprovalContext?.allowPersistence ?? true,
100157
100541
  showPreview: showApprovalPreview
100158
100542
  }, undefined, false, undefined, this) : ln.kind === "user" ? /* @__PURE__ */ jsx_dev_runtime70.jsxDEV(UserMessage, {
100159
- line: ln
100543
+ line: ln,
100544
+ prompt: statusLine.prompt
100160
100545
  }, undefined, false, undefined, this) : ln.kind === "reasoning" ? /* @__PURE__ */ jsx_dev_runtime70.jsxDEV(ReasoningMessage, {
100161
100546
  line: ln
100162
100547
  }, undefined, false, undefined, this) : ln.kind === "assistant" ? /* @__PURE__ */ jsx_dev_runtime70.jsxDEV(AssistantMessage, {
@@ -100337,7 +100722,8 @@ Plan file path: ${planFilePath}`;
100337
100722
  shouldAnimate,
100338
100723
  statusLineText: statusLine.text || undefined,
100339
100724
  statusLineRight: statusLine.rightText || undefined,
100340
- statusLinePadding: statusLine.padding || 0
100725
+ statusLinePadding: statusLine.padding || 0,
100726
+ statusLinePrompt: statusLine.prompt
100341
100727
  }, undefined, false, undefined, this)
100342
100728
  }, undefined, false, undefined, this),
100343
100729
  activeOverlay === "model" && /* @__PURE__ */ jsx_dev_runtime70.jsxDEV(ModelSelector, {
@@ -100999,12 +101385,12 @@ __export(exports_terminalKeybindingInstaller2, {
100999
101385
  import {
101000
101386
  copyFileSync as copyFileSync2,
101001
101387
  existsSync as existsSync19,
101002
- mkdirSync as mkdirSync9,
101388
+ mkdirSync as mkdirSync10,
101003
101389
  readFileSync as readFileSync8,
101004
- writeFileSync as writeFileSync7
101390
+ writeFileSync as writeFileSync8
101005
101391
  } from "node:fs";
101006
101392
  import { homedir as homedir20, platform as platform5 } from "node:os";
101007
- import { dirname as dirname13, join as join30 } from "node:path";
101393
+ import { dirname as dirname13, join as join31 } from "node:path";
101008
101394
  function detectTerminalType2() {
101009
101395
  if (process.env.CURSOR_TRACE_ID || process.env.CURSOR_CHANNEL) {
101010
101396
  return "cursor";
@@ -101036,16 +101422,16 @@ function getKeybindingsPath2(terminal) {
101036
101422
  }[terminal];
101037
101423
  const os6 = platform5();
101038
101424
  if (os6 === "darwin") {
101039
- return join30(homedir20(), "Library", "Application Support", appName, "User", "keybindings.json");
101425
+ return join31(homedir20(), "Library", "Application Support", appName, "User", "keybindings.json");
101040
101426
  }
101041
101427
  if (os6 === "win32") {
101042
101428
  const appData = process.env.APPDATA;
101043
101429
  if (!appData)
101044
101430
  return null;
101045
- return join30(appData, appName, "User", "keybindings.json");
101431
+ return join31(appData, appName, "User", "keybindings.json");
101046
101432
  }
101047
101433
  if (os6 === "linux") {
101048
- return join30(homedir20(), ".config", appName, "User", "keybindings.json");
101434
+ return join31(homedir20(), ".config", appName, "User", "keybindings.json");
101049
101435
  }
101050
101436
  return null;
101051
101437
  }
@@ -101097,7 +101483,7 @@ function installKeybinding2(keybindingsPath) {
101097
101483
  }
101098
101484
  const parentDir = dirname13(keybindingsPath);
101099
101485
  if (!existsSync19(parentDir)) {
101100
- mkdirSync9(parentDir, { recursive: true });
101486
+ mkdirSync10(parentDir, { recursive: true });
101101
101487
  }
101102
101488
  let keybindings = [];
101103
101489
  let backupPath = null;
@@ -101116,7 +101502,7 @@ function installKeybinding2(keybindingsPath) {
101116
101502
  keybindings.push(SHIFT_ENTER_KEYBINDING2);
101117
101503
  const newContent = `${JSON.stringify(keybindings, null, 2)}
101118
101504
  `;
101119
- writeFileSync7(keybindingsPath, newContent, { encoding: "utf-8" });
101505
+ writeFileSync8(keybindingsPath, newContent, { encoding: "utf-8" });
101120
101506
  return {
101121
101507
  success: true,
101122
101508
  backupPath: backupPath ?? undefined
@@ -101145,7 +101531,7 @@ function removeKeybinding2(keybindingsPath) {
101145
101531
  const filtered = keybindings.filter((kb) => !(kb.key?.toLowerCase() === "shift+enter" && kb.command === "workbench.action.terminal.sendSequence" && kb.when?.includes("terminalFocus")));
101146
101532
  const newContent = `${JSON.stringify(filtered, null, 2)}
101147
101533
  `;
101148
- writeFileSync7(keybindingsPath, newContent, { encoding: "utf-8" });
101534
+ writeFileSync8(keybindingsPath, newContent, { encoding: "utf-8" });
101149
101535
  return { success: true };
101150
101536
  } catch (error) {
101151
101537
  const message = error instanceof Error ? error.message : String(error);
@@ -101198,14 +101584,14 @@ function getWezTermConfigPath2() {
101198
101584
  }
101199
101585
  const xdgConfig = process.env.XDG_CONFIG_HOME;
101200
101586
  if (xdgConfig) {
101201
- const xdgPath = join30(xdgConfig, "wezterm", "wezterm.lua");
101587
+ const xdgPath = join31(xdgConfig, "wezterm", "wezterm.lua");
101202
101588
  if (existsSync19(xdgPath))
101203
101589
  return xdgPath;
101204
101590
  }
101205
- const configPath = join30(homedir20(), ".config", "wezterm", "wezterm.lua");
101591
+ const configPath = join31(homedir20(), ".config", "wezterm", "wezterm.lua");
101206
101592
  if (existsSync19(configPath))
101207
101593
  return configPath;
101208
- return join30(homedir20(), ".wezterm.lua");
101594
+ return join31(homedir20(), ".wezterm.lua");
101209
101595
  }
101210
101596
  function wezTermDeleteFixExists2(configPath) {
101211
101597
  if (!existsSync19(configPath))
@@ -101256,9 +101642,9 @@ ${WEZTERM_DELETE_FIX2}
101256
101642
  }
101257
101643
  const parentDir = dirname13(configPath);
101258
101644
  if (!existsSync19(parentDir)) {
101259
- mkdirSync9(parentDir, { recursive: true });
101645
+ mkdirSync10(parentDir, { recursive: true });
101260
101646
  }
101261
- writeFileSync7(configPath, content, { encoding: "utf-8" });
101647
+ writeFileSync8(configPath, content, { encoding: "utf-8" });
101262
101648
  return {
101263
101649
  success: true,
101264
101650
  backupPath: backupPath ?? undefined
@@ -101304,9 +101690,9 @@ __export(exports_settings2, {
101304
101690
  getSetting: () => getSetting2
101305
101691
  });
101306
101692
  import { homedir as homedir21 } from "node:os";
101307
- import { join as join31 } from "node:path";
101693
+ import { join as join32 } from "node:path";
101308
101694
  function getSettingsPath2() {
101309
- return join31(homedir21(), ".letta", "settings.json");
101695
+ return join32(homedir21(), ".letta", "settings.json");
101310
101696
  }
101311
101697
  async function loadSettings2() {
101312
101698
  const settingsPath = getSettingsPath2();
@@ -101343,7 +101729,7 @@ async function getSetting2(key) {
101343
101729
  return settings[key];
101344
101730
  }
101345
101731
  function getProjectSettingsPath2() {
101346
- return join31(process.cwd(), ".letta", "settings.local.json");
101732
+ return join32(process.cwd(), ".letta", "settings.local.json");
101347
101733
  }
101348
101734
  async function loadProjectSettings2() {
101349
101735
  const settingsPath = getProjectSettingsPath2();
@@ -101361,7 +101747,7 @@ async function loadProjectSettings2() {
101361
101747
  }
101362
101748
  async function saveProjectSettings2(settings) {
101363
101749
  const settingsPath = getProjectSettingsPath2();
101364
- const dirPath = join31(process.cwd(), ".letta");
101750
+ const dirPath = join32(process.cwd(), ".letta");
101365
101751
  try {
101366
101752
  if (!exists(dirPath)) {
101367
101753
  await mkdir(dirPath, { recursive: true });
@@ -101623,7 +102009,7 @@ var init_defaults2 = __esm(async () => {
101623
102009
  name: "Incognito",
101624
102010
  description: INCOGNITO_DESCRIPTION2,
101625
102011
  initBlocks: [],
101626
- baseTools: ["web_search", "conversation_search", "fetch_webpage"]
102012
+ baseTools: ["web_search", "fetch_webpage"]
101627
102013
  }
101628
102014
  };
101629
102015
  });
@@ -101741,6 +102127,8 @@ async function createAgent2(nameOrOptions = DEFAULT_AGENT_NAME, model, embedding
101741
102127
  } else {
101742
102128
  systemPromptContent = await resolveSystemPrompt(options.systemPromptPreset);
101743
102129
  }
102130
+ systemPromptContent = `${systemPromptContent}
102131
+ ${SYSTEM_PROMPT_MEMORY_ADDON}`;
101744
102132
  if (options.systemPromptAppend) {
101745
102133
  systemPromptContent = `${systemPromptContent}
101746
102134
 
@@ -101751,6 +102139,9 @@ ${options.systemPromptAppend}`;
101751
102139
  if (isSubagent) {
101752
102140
  tags.push("role:subagent");
101753
102141
  }
102142
+ if (options.tags && Array.isArray(options.tags)) {
102143
+ tags.push(...options.tags);
102144
+ }
101754
102145
  const agentDescription = options.description ?? `Letta Code agent created in ${process.cwd()}`;
101755
102146
  const agent = await client.agents.create({
101756
102147
  agent_type: "letta_v1_agent",
@@ -101932,8 +102323,8 @@ function parseRegistryHandle2(handle) {
101932
102323
  return { author: parts[0], name: parts[1] };
101933
102324
  }
101934
102325
  async function importAgentFromRegistry2(options) {
101935
- const { tmpdir: tmpdir4 } = await import("node:os");
101936
- const { join: join32 } = await import("node:path");
102326
+ const { tmpdir: tmpdir5 } = await import("node:os");
102327
+ const { join: join33 } = await import("node:path");
101937
102328
  const { writeFile: writeFile5, unlink } = await import("node:fs/promises");
101938
102329
  const { author, name } = parseRegistryHandle2(options.handle);
101939
102330
  const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
@@ -101945,7 +102336,7 @@ async function importAgentFromRegistry2(options) {
101945
102336
  throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
101946
102337
  }
101947
102338
  const afContent = await response.text();
101948
- const tempPath = join32(tmpdir4(), `letta-import-${author}-${name}-${Date.now()}.af`);
102339
+ const tempPath = join33(tmpdir5(), `letta-import-${author}-${name}-${Date.now()}.af`);
101949
102340
  await writeFile5(tempPath, afContent, "utf-8");
101950
102341
  try {
101951
102342
  const result = await importAgentFromFile2({
@@ -102102,8 +102493,10 @@ async function updateAgentSystemPromptRaw2(agentId, systemPromptContent) {
102102
102493
  }
102103
102494
  async function updateAgentSystemPrompt2(agentId, systemPromptId) {
102104
102495
  try {
102105
- const { resolveSystemPrompt: resolveSystemPrompt3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
102106
- const systemPromptContent = await resolveSystemPrompt3(systemPromptId);
102496
+ const { resolveSystemPrompt: resolveSystemPrompt3, SYSTEM_PROMPT_MEMORY_ADDON: SYSTEM_PROMPT_MEMORY_ADDON3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
102497
+ const baseContent = await resolveSystemPrompt3(systemPromptId);
102498
+ const systemPromptContent = `${baseContent}
102499
+ ${SYSTEM_PROMPT_MEMORY_ADDON3}`;
102107
102500
  const updateResult = await updateAgentSystemPromptRaw2(agentId, systemPromptContent);
102108
102501
  if (!updateResult.success) {
102109
102502
  return {
@@ -102132,18 +102525,18 @@ async function updateAgentSystemPromptMemfs2(agentId, enableMemfs) {
102132
102525
  const client = await getClient2();
102133
102526
  const agent = await client.agents.retrieve(agentId);
102134
102527
  let currentSystemPrompt = agent.system || "";
102135
- const { SYSTEM_PROMPT_MEMFS_ADDON: SYSTEM_PROMPT_MEMFS_ADDON3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
102136
- const memfsHeaderRegex = /\n## Memory Filesystem[\s\S]*?(?=\n# |$)/;
102137
- currentSystemPrompt = currentSystemPrompt.replace(memfsHeaderRegex, "");
102138
- if (enableMemfs) {
102139
- currentSystemPrompt = `${currentSystemPrompt}${SYSTEM_PROMPT_MEMFS_ADDON3}`;
102140
- }
102528
+ const { SYSTEM_PROMPT_MEMFS_ADDON: SYSTEM_PROMPT_MEMFS_ADDON3, SYSTEM_PROMPT_MEMORY_ADDON: SYSTEM_PROMPT_MEMORY_ADDON3 } = await Promise.resolve().then(() => (init_promptAssets(), exports_promptAssets));
102529
+ const memoryHeaderRegex = /\n#{1,2} Memory\b[\s\S]*?(?=\n#{1,2} (?!Memory|Filesystem|Structure|How It Works|Syncing|History)[^\n]|$)/;
102530
+ currentSystemPrompt = currentSystemPrompt.replace(memoryHeaderRegex, "");
102531
+ const addon = enableMemfs ? SYSTEM_PROMPT_MEMFS_ADDON3 : SYSTEM_PROMPT_MEMORY_ADDON3;
102532
+ currentSystemPrompt = `${currentSystemPrompt}
102533
+ ${addon}`;
102141
102534
  await client.agents.update(agentId, {
102142
102535
  system: currentSystemPrompt
102143
102536
  });
102144
102537
  return {
102145
102538
  success: true,
102146
- message: enableMemfs ? "System prompt updated to include Memory Filesystem section" : "System prompt updated to remove Memory Filesystem section"
102539
+ message: enableMemfs ? "System prompt updated to include Memory Filesystem section" : "System prompt updated to include standard Memory section"
102147
102540
  };
102148
102541
  } catch (error) {
102149
102542
  return {
@@ -102160,488 +102553,136 @@ var init_modify2 = __esm(async () => {
102160
102553
  ]);
102161
102554
  });
102162
102555
 
102163
- // src/tools/toolset.ts
102164
- var exports_toolset2 = {};
102165
- __export(exports_toolset2, {
102166
- switchToolsetForModel: () => switchToolsetForModel2,
102167
- reattachMemoryTool: () => reattachMemoryTool2,
102168
- forceToolsetSwitch: () => forceToolsetSwitch2,
102169
- ensureCorrectMemoryTool: () => ensureCorrectMemoryTool2,
102170
- detachMemoryTools: () => detachMemoryTools2,
102171
- MEMORY_TOOL_NAMES: () => MEMORY_TOOL_NAMES2
102172
- });
102173
- async function ensureCorrectMemoryTool2(agentId, modelIdentifier, useMemoryPatch) {
102174
- const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
102175
- const client = await getClient2();
102176
- const shouldUsePatch = useMemoryPatch !== undefined ? useMemoryPatch : isOpenAIModel(resolvedModel);
102177
- try {
102178
- const agentWithTools = await client.agents.retrieve(agentId, {
102179
- include: ["agent.tools"]
102180
- });
102181
- const currentTools = agentWithTools.tools || [];
102182
- const mapByName = new Map(currentTools.map((t) => [t.name, t.id]));
102183
- const hasAnyMemoryTool = mapByName.has("memory") || mapByName.has("memory_apply_patch");
102184
- if (!hasAnyMemoryTool) {
102185
- return;
102186
- }
102187
- const desiredMemoryTool = shouldUsePatch ? "memory_apply_patch" : "memory";
102188
- const otherMemoryTool = desiredMemoryTool === "memory" ? "memory_apply_patch" : "memory";
102189
- let desiredId = mapByName.get(desiredMemoryTool);
102190
- if (!desiredId) {
102191
- const resp = await client.tools.list({ name: desiredMemoryTool });
102192
- desiredId = resp.items[0]?.id;
102193
- }
102194
- if (!desiredId) {
102195
- return;
102196
- }
102197
- const otherId = mapByName.get(otherMemoryTool);
102198
- if (mapByName.has(desiredMemoryTool) && !otherId) {
102199
- return;
102200
- }
102201
- const currentIds = currentTools.map((t) => t.id).filter((id) => typeof id === "string");
102202
- const newIds = new Set(currentIds);
102203
- if (otherId)
102204
- newIds.delete(otherId);
102205
- newIds.add(desiredId);
102206
- const updatedRules = (agentWithTools.tool_rules || []).map((r) => r.tool_name === otherMemoryTool ? { ...r, tool_name: desiredMemoryTool } : r);
102207
- await client.agents.update(agentId, {
102208
- tool_ids: Array.from(newIds),
102209
- tool_rules: updatedRules
102210
- });
102211
- } catch (err) {
102212
- console.warn(`Warning: Failed to sync memory tool: ${err instanceof Error ? err.message : String(err)}`);
102213
- }
102214
- }
102215
- async function detachMemoryTools2(agentId) {
102216
- const client = await getClient2();
102217
- try {
102218
- const agentWithTools = await client.agents.retrieve(agentId, {
102219
- include: ["agent.tools"]
102220
- });
102221
- const currentTools = agentWithTools.tools || [];
102222
- let detachedAny = false;
102223
- for (const tool of currentTools) {
102224
- if (tool.name && MEMORY_TOOL_NAMES2.has(tool.name)) {
102225
- if (tool.id) {
102226
- await client.agents.tools.detach(tool.id, { agent_id: agentId });
102227
- detachedAny = true;
102228
- }
102229
- }
102230
- }
102231
- return detachedAny;
102232
- } catch (err) {
102233
- console.warn(`Warning: Failed to detach memory tools: ${err instanceof Error ? err.message : String(err)}`);
102234
- return false;
102235
- }
102236
- }
102237
- async function reattachMemoryTool2(agentId, modelIdentifier) {
102238
- const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
102239
- const client = await getClient2();
102240
- const shouldUsePatch = isOpenAIModel(resolvedModel);
102241
- try {
102242
- const agentWithTools = await client.agents.retrieve(agentId, {
102243
- include: ["agent.tools"]
102244
- });
102245
- const currentTools = agentWithTools.tools || [];
102246
- const mapByName = new Map(currentTools.map((t) => [t.name, t.id]));
102247
- const desiredMemoryTool = shouldUsePatch ? "memory_apply_patch" : "memory";
102248
- if (mapByName.has(desiredMemoryTool)) {
102249
- return;
102250
- }
102251
- const resp = await client.tools.list({ name: desiredMemoryTool });
102252
- const toolId = resp.items[0]?.id;
102253
- if (!toolId) {
102254
- console.warn(`Memory tool "${desiredMemoryTool}" not found on server`);
102255
- return;
102256
- }
102257
- await client.agents.tools.attach(toolId, { agent_id: agentId });
102258
- } catch (err) {
102259
- console.warn(`Warning: Failed to reattach memory tool: ${err instanceof Error ? err.message : String(err)}`);
102260
- }
102261
- }
102262
- async function forceToolsetSwitch2(toolsetName, agentId) {
102263
- let modelForLoading;
102264
- if (toolsetName === "none") {
102265
- clearToolsWithLock();
102266
- return;
102267
- } else if (toolsetName === "codex") {
102268
- await loadSpecificTools([...CODEX_TOOLS2]);
102269
- modelForLoading = "openai/gpt-4";
102270
- } else if (toolsetName === "codex_snake") {
102271
- await loadTools("openai/gpt-4");
102272
- modelForLoading = "openai/gpt-4";
102273
- } else if (toolsetName === "gemini") {
102274
- await loadSpecificTools([...GEMINI_TOOLS2]);
102275
- modelForLoading = "google_ai/gemini-3-pro-preview";
102276
- } else if (toolsetName === "gemini_snake") {
102277
- await loadTools("google_ai/gemini-3-pro-preview");
102278
- modelForLoading = "google_ai/gemini-3-pro-preview";
102279
- } else {
102280
- await loadTools("anthropic/claude-sonnet-4");
102281
- modelForLoading = "anthropic/claude-sonnet-4";
102282
- }
102283
- const useMemoryPatch = toolsetName === "codex" || toolsetName === "codex_snake";
102284
- await ensureCorrectMemoryTool2(agentId, modelForLoading, useMemoryPatch);
102285
- }
102286
- async function switchToolsetForModel2(modelIdentifier, agentId) {
102287
- const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
102288
- await loadTools(resolvedModel);
102289
- const loadedAfterPrimary = getToolNames().length;
102290
- if (loadedAfterPrimary === 0 && !toolFilter.isActive()) {
102291
- await loadTools();
102292
- if (getToolNames().length === 0) {
102293
- throw new Error(`Failed to load any Letta tools for model "${resolvedModel}".`);
102294
- }
102295
- }
102296
- await ensureCorrectMemoryTool2(agentId, resolvedModel);
102297
- const { isGeminiModel: isGeminiModel3 } = await init_manager3().then(() => exports_manager2);
102298
- const toolsetName = isOpenAIModel(resolvedModel) ? "codex" : isGeminiModel3(resolvedModel) ? "gemini" : "default";
102299
- return toolsetName;
102300
- }
102301
- var CODEX_TOOLS2, GEMINI_TOOLS2, MEMORY_TOOL_NAMES2;
102302
- var init_toolset2 = __esm(async () => {
102303
- init_model();
102304
- init_filter();
102305
- await __promiseAll([
102306
- init_client2(),
102307
- init_manager3()
102308
- ]);
102309
- CODEX_TOOLS2 = OPENAI_PASCAL_TOOLS;
102310
- GEMINI_TOOLS2 = GEMINI_PASCAL_TOOLS;
102311
- MEMORY_TOOL_NAMES2 = new Set([
102312
- "memory",
102313
- "memory_apply_patch",
102314
- "memory_insert",
102315
- "memory_replace",
102316
- "memory_rethink"
102317
- ]);
102318
- });
102319
-
102320
- // src/agent/memoryGit.ts
102321
- var exports_memoryGit2 = {};
102322
- __export(exports_memoryGit2, {
102323
- removeGitMemoryTag: () => removeGitMemoryTag2,
102324
- pullMemory: () => pullMemory2,
102325
- isGitRepo: () => isGitRepo2,
102326
- getMemoryRepoDir: () => getMemoryRepoDir2,
102327
- getMemoryGitStatus: () => getMemoryGitStatus2,
102328
- getAgentRootDir: () => getAgentRootDir2,
102329
- cloneMemoryRepo: () => cloneMemoryRepo2,
102330
- addGitMemoryTag: () => addGitMemoryTag2,
102331
- PRE_COMMIT_HOOK_SCRIPT: () => PRE_COMMIT_HOOK_SCRIPT2
102332
- });
102333
- import { execFile as execFileCb2 } from "node:child_process";
102334
- import {
102335
- chmodSync as chmodSync2,
102336
- existsSync as existsSync20,
102337
- mkdirSync as mkdirSync10,
102338
- renameSync as renameSync3,
102339
- rmSync as rmSync3,
102340
- writeFileSync as writeFileSync8
102341
- } from "node:fs";
102556
+ // src/agent/memoryFilesystem.ts
102557
+ var exports_memoryFilesystem2 = {};
102558
+ __export(exports_memoryFilesystem2, {
102559
+ renderMemoryFilesystemTree: () => renderMemoryFilesystemTree2,
102560
+ labelFromRelativePath: () => labelFromRelativePath2,
102561
+ getMemorySystemDir: () => getMemorySystemDir2,
102562
+ getMemoryFilesystemRoot: () => getMemoryFilesystemRoot2,
102563
+ ensureMemoryFilesystemDirs: () => ensureMemoryFilesystemDirs2,
102564
+ applyMemfsFlags: () => applyMemfsFlags2,
102565
+ MEMORY_SYSTEM_DIR: () => MEMORY_SYSTEM_DIR2,
102566
+ MEMORY_FS_ROOT: () => MEMORY_FS_ROOT2,
102567
+ MEMORY_FS_MEMORY_DIR: () => MEMORY_FS_MEMORY_DIR2,
102568
+ MEMORY_FS_AGENTS_DIR: () => MEMORY_FS_AGENTS_DIR2
102569
+ });
102570
+ import { existsSync as existsSync20, mkdirSync as mkdirSync11 } from "node:fs";
102342
102571
  import { homedir as homedir22 } from "node:os";
102343
- import { join as join32 } from "node:path";
102344
- import { promisify as promisify10 } from "node:util";
102345
- function getAgentRootDir2(agentId) {
102346
- return join32(homedir22(), ".letta", "agents", agentId);
102572
+ import { join as join33 } from "node:path";
102573
+ function getMemoryFilesystemRoot2(agentId, homeDir = homedir22()) {
102574
+ return join33(homeDir, MEMORY_FS_ROOT2, MEMORY_FS_AGENTS_DIR2, agentId, MEMORY_FS_MEMORY_DIR2);
102347
102575
  }
102348
- function getMemoryRepoDir2(agentId) {
102349
- return join32(getAgentRootDir2(agentId), "memory");
102576
+ function getMemorySystemDir2(agentId, homeDir = homedir22()) {
102577
+ return join33(getMemoryFilesystemRoot2(agentId, homeDir), MEMORY_SYSTEM_DIR2);
102350
102578
  }
102351
- function getGitRemoteUrl2(agentId) {
102352
- const baseUrl = getServerUrl2();
102353
- return `${baseUrl}/v1/git/${agentId}/state.git`;
102354
- }
102355
- async function getAuthToken2() {
102356
- const client = await getClient2();
102357
- return client._options?.apiKey ?? "";
102358
- }
102359
- async function runGit2(cwd2, args, token) {
102360
- const authArgs = token ? [
102361
- "-c",
102362
- `http.extraHeader=Authorization: Basic ${Buffer.from(`letta:${token}`).toString("base64")}`
102363
- ] : [];
102364
- const allArgs = [...authArgs, ...args];
102365
- debugLog("memfs-git", `git ${args.join(" ")} (in ${cwd2})`);
102366
- const result = await execFile9("git", allArgs, {
102367
- cwd: cwd2,
102368
- maxBuffer: 10 * 1024 * 1024,
102369
- timeout: 60000
102370
- });
102371
- return {
102372
- stdout: result.stdout?.toString() ?? "",
102373
- stderr: result.stderr?.toString() ?? ""
102374
- };
102375
- }
102376
- async function configureLocalCredentialHelper2(dir, token) {
102377
- const baseUrl = getServerUrl2();
102378
- const helper = `!f() { echo "username=letta"; echo "password=${token}"; }; f`;
102379
- await runGit2(dir, ["config", `credential.${baseUrl}.helper`, helper]);
102380
- debugLog("memfs-git", "Configured local credential helper");
102381
- }
102382
- function installPreCommitHook2(dir) {
102383
- const hooksDir = join32(dir, ".git", "hooks");
102384
- const hookPath = join32(hooksDir, "pre-commit");
102385
- if (!existsSync20(hooksDir)) {
102386
- mkdirSync10(hooksDir, { recursive: true });
102579
+ function ensureMemoryFilesystemDirs2(agentId, homeDir = homedir22()) {
102580
+ const root = getMemoryFilesystemRoot2(agentId, homeDir);
102581
+ const systemDir = getMemorySystemDir2(agentId, homeDir);
102582
+ if (!existsSync20(root)) {
102583
+ mkdirSync11(root, { recursive: true });
102584
+ }
102585
+ if (!existsSync20(systemDir)) {
102586
+ mkdirSync11(systemDir, { recursive: true });
102387
102587
  }
102388
- writeFileSync8(hookPath, PRE_COMMIT_HOOK_SCRIPT2, "utf-8");
102389
- chmodSync2(hookPath, 493);
102390
- debugLog("memfs-git", "Installed pre-commit hook");
102391
102588
  }
102392
- function isGitRepo2(agentId) {
102393
- return existsSync20(join32(getMemoryRepoDir2(agentId), ".git"));
102589
+ function labelFromRelativePath2(relativePath) {
102590
+ const normalized = relativePath.replace(/\\/g, "/");
102591
+ return normalized.replace(/\.md$/, "");
102394
102592
  }
102395
- async function cloneMemoryRepo2(agentId) {
102396
- const token = await getAuthToken2();
102397
- const url = getGitRemoteUrl2(agentId);
102398
- const dir = getMemoryRepoDir2(agentId);
102399
- debugLog("memfs-git", `Cloning ${url} → ${dir}`);
102400
- if (!existsSync20(dir)) {
102401
- mkdirSync10(dir, { recursive: true });
102402
- await runGit2(dir, ["clone", url, "."], token);
102403
- } else if (!existsSync20(join32(dir, ".git"))) {
102404
- const tmpDir = `${dir}-git-clone-tmp`;
102405
- try {
102406
- if (existsSync20(tmpDir)) {
102407
- rmSync3(tmpDir, { recursive: true, force: true });
102593
+ function renderMemoryFilesystemTree2(systemLabels, detachedLabels) {
102594
+ const makeNode = () => ({ children: new Map, isFile: false });
102595
+ const root = makeNode();
102596
+ const insertPath = (base2, label) => {
102597
+ const parts = base2 ? [base2, ...label.split("/")] : label.split("/");
102598
+ let current = root;
102599
+ for (const [i, partName] of parts.entries()) {
102600
+ const part = i === parts.length - 1 ? `${partName}.md` : partName;
102601
+ if (!current.children.has(part)) {
102602
+ current.children.set(part, makeNode());
102408
102603
  }
102409
- mkdirSync10(tmpDir, { recursive: true });
102410
- await runGit2(tmpDir, ["clone", url, "."], token);
102411
- renameSync3(join32(tmpDir, ".git"), join32(dir, ".git"));
102412
- await runGit2(dir, ["checkout", "--", "."], token);
102413
- debugLog("memfs-git", "Migrated existing memory directory to git repo");
102414
- } finally {
102415
- if (existsSync20(tmpDir)) {
102416
- rmSync3(tmpDir, { recursive: true, force: true });
102604
+ current = current.children.get(part);
102605
+ if (i === parts.length - 1) {
102606
+ current.isFile = true;
102417
102607
  }
102418
102608
  }
102609
+ };
102610
+ for (const label of systemLabels) {
102611
+ insertPath(MEMORY_SYSTEM_DIR2, label);
102419
102612
  }
102420
- await configureLocalCredentialHelper2(dir, token);
102421
- installPreCommitHook2(dir);
102422
- }
102423
- async function pullMemory2(agentId) {
102424
- const token = await getAuthToken2();
102425
- const dir = getMemoryRepoDir2(agentId);
102426
- await configureLocalCredentialHelper2(dir, token);
102427
- installPreCommitHook2(dir);
102428
- try {
102429
- const { stdout, stderr } = await runGit2(dir, ["pull", "--ff-only"]);
102430
- const output = stdout + stderr;
102431
- const updated = !output.includes("Already up to date");
102432
- return {
102433
- updated,
102434
- summary: updated ? output.trim() : "Already up to date"
102435
- };
102436
- } catch {
102437
- debugWarn("memfs-git", "Fast-forward pull failed, trying rebase");
102438
- try {
102439
- const { stdout, stderr } = await runGit2(dir, ["pull", "--rebase"]);
102440
- return { updated: true, summary: (stdout + stderr).trim() };
102441
- } catch (rebaseErr) {
102442
- const msg = rebaseErr instanceof Error ? rebaseErr.message : String(rebaseErr);
102443
- debugWarn("memfs-git", `Pull failed: ${msg}`);
102444
- return { updated: false, summary: `Pull failed: ${msg}` };
102445
- }
102446
- }
102447
- }
102448
- async function getMemoryGitStatus2(agentId) {
102449
- const dir = getMemoryRepoDir2(agentId);
102450
- const { stdout: statusOut } = await runGit2(dir, ["status", "--porcelain"]);
102451
- const dirty = statusOut.trim().length > 0;
102452
- let aheadOfRemote = false;
102453
- try {
102454
- const { stdout: revListOut } = await runGit2(dir, [
102455
- "rev-list",
102456
- "--count",
102457
- "@{u}..HEAD"
102458
- ]);
102459
- const aheadCount = parseInt(revListOut.trim(), 10);
102460
- aheadOfRemote = aheadCount > 0;
102461
- } catch {}
102462
- const parts = [];
102463
- if (dirty) {
102464
- const changedFiles = statusOut.trim().split(`
102465
- `).filter((l) => l.trim()).map((l) => l.trim());
102466
- parts.push(`${changedFiles.length} uncommitted change(s)`);
102613
+ for (const label of detachedLabels) {
102614
+ insertPath(null, label);
102467
102615
  }
102468
- if (aheadOfRemote) {
102469
- parts.push("local commits not pushed to remote");
102616
+ if (!root.children.has(MEMORY_SYSTEM_DIR2)) {
102617
+ root.children.set(MEMORY_SYSTEM_DIR2, makeNode());
102470
102618
  }
102471
- return {
102472
- dirty,
102473
- aheadOfRemote,
102474
- summary: parts.length > 0 ? parts.join(", ") : "clean"
102619
+ const sortedEntries = (node) => {
102620
+ const entries = Array.from(node.children.entries());
102621
+ return entries.sort(([nameA, nodeA], [nameB, nodeB]) => {
102622
+ if (nodeA.isFile !== nodeB.isFile) {
102623
+ return nodeA.isFile ? 1 : -1;
102624
+ }
102625
+ return nameA.localeCompare(nameB);
102626
+ });
102475
102627
  };
102628
+ const lines = ["/memory/"];
102629
+ const render2 = (node, prefix) => {
102630
+ const entries = sortedEntries(node);
102631
+ entries.forEach(([name, child], index) => {
102632
+ const isLast = index === entries.length - 1;
102633
+ const branch = isLast ? "└──" : "├──";
102634
+ lines.push(`${prefix}${branch} ${name}${child.isFile ? "" : "/"}`);
102635
+ if (child.children.size > 0) {
102636
+ const nextPrefix = `${prefix}${isLast ? " " : "│ "}`;
102637
+ render2(child, nextPrefix);
102638
+ }
102639
+ });
102640
+ };
102641
+ render2(root, "");
102642
+ return lines.join(`
102643
+ `);
102476
102644
  }
102477
- async function addGitMemoryTag2(agentId) {
102478
- const client = await getClient2();
102479
- try {
102480
- const agent = await client.agents.retrieve(agentId);
102481
- const tags = agent.tags || [];
102482
- if (!tags.includes(GIT_MEMORY_ENABLED_TAG2)) {
102483
- await client.agents.update(agentId, {
102484
- tags: [...tags, GIT_MEMORY_ENABLED_TAG2]
102485
- });
102486
- debugLog("memfs-git", `Added ${GIT_MEMORY_ENABLED_TAG2} tag`);
102645
+ async function applyMemfsFlags2(agentId, memfsFlag, noMemfsFlag, options) {
102646
+ const { getServerUrl: getServerUrl2 } = await init_client2().then(() => exports_client);
102647
+ const { settingsManager: settingsManager3 } = await init_settings_manager().then(() => exports_settings_manager);
102648
+ if (memfsFlag) {
102649
+ const serverUrl = getServerUrl2();
102650
+ if (!serverUrl.includes("api.letta.com")) {
102651
+ throw new Error("--memfs is only available on Letta Cloud (api.letta.com).");
102487
102652
  }
102488
- } catch (err) {
102489
- debugWarn("memfs-git", `Failed to add git-memory tag: ${err instanceof Error ? err.message : String(err)}`);
102653
+ settingsManager3.setMemfsEnabled(agentId, true);
102654
+ } else if (noMemfsFlag) {
102655
+ settingsManager3.setMemfsEnabled(agentId, false);
102490
102656
  }
102491
- }
102492
- async function removeGitMemoryTag2(agentId) {
102493
- const client = await getClient2();
102494
- try {
102495
- const agent = await client.agents.retrieve(agentId);
102496
- const tags = agent.tags || [];
102497
- if (tags.includes(GIT_MEMORY_ENABLED_TAG2)) {
102498
- await client.agents.update(agentId, {
102499
- tags: tags.filter((t) => t !== GIT_MEMORY_ENABLED_TAG2)
102500
- });
102501
- debugLog("memfs-git", `Removed ${GIT_MEMORY_ENABLED_TAG2} tag`);
102657
+ const isEnabled = settingsManager3.isMemfsEnabled(agentId);
102658
+ if (isEnabled && memfsFlag) {
102659
+ const { detachMemoryTools: detachMemoryTools2 } = await init_toolset().then(() => exports_toolset);
102660
+ await detachMemoryTools2(agentId);
102661
+ }
102662
+ if (memfsFlag || noMemfsFlag) {
102663
+ const { updateAgentSystemPromptMemfs: updateAgentSystemPromptMemfs3 } = await init_modify().then(() => exports_modify);
102664
+ await updateAgentSystemPromptMemfs3(agentId, isEnabled);
102665
+ }
102666
+ let pullSummary;
102667
+ if (isEnabled) {
102668
+ const { addGitMemoryTag: addGitMemoryTag2, isGitRepo: isGitRepo2, cloneMemoryRepo: cloneMemoryRepo2, pullMemory: pullMemory2 } = await init_memoryGit().then(() => exports_memoryGit);
102669
+ await addGitMemoryTag2(agentId);
102670
+ if (!isGitRepo2(agentId)) {
102671
+ await cloneMemoryRepo2(agentId);
102672
+ } else if (options?.pullOnExistingRepo) {
102673
+ const result = await pullMemory2(agentId);
102674
+ pullSummary = result.summary;
102502
102675
  }
102503
- } catch (err) {
102504
- debugWarn("memfs-git", `Failed to remove git-memory tag: ${err instanceof Error ? err.message : String(err)}`);
102505
102676
  }
102677
+ const action = memfsFlag ? "enabled" : noMemfsFlag ? "disabled" : "unchanged";
102678
+ return {
102679
+ action,
102680
+ memoryDir: isEnabled ? getMemoryFilesystemRoot2(agentId) : undefined,
102681
+ pullSummary
102682
+ };
102506
102683
  }
102507
- var execFile9, GIT_MEMORY_ENABLED_TAG2 = "git-memory-enabled", PRE_COMMIT_HOOK_SCRIPT2 = `#!/usr/bin/env bash
102508
- # Validate frontmatter in staged memory .md files
102509
- # Installed by Letta Code CLI
102510
-
102511
- AGENT_EDITABLE_KEYS="description limit"
102512
- PROTECTED_KEYS="read_only"
102513
- ALL_KNOWN_KEYS="description limit read_only"
102514
- errors=""
102515
-
102516
- # Helper: extract a frontmatter value from content
102517
- get_fm_value() {
102518
- local content="$1" key="$2"
102519
- local closing_line
102520
- closing_line=$(echo "$content" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
102521
- [ -z "$closing_line" ] && return
102522
- echo "$content" | tail -n +2 | head -n $((closing_line - 1)) | grep "^$key:" | cut -d: -f2- | sed 's/^ *//;s/ *$//'
102523
- }
102524
-
102525
- for file in $(git diff --cached --name-only --diff-filter=ACM | grep '^memory/.*\\.md$'); do
102526
- staged=$(git show ":$file")
102527
-
102528
- # Frontmatter is required
102529
- first_line=$(echo "$staged" | head -1)
102530
- if [ "$first_line" != "---" ]; then
102531
- errors="$errors\\n $file: missing frontmatter (must start with ---)"
102532
- continue
102533
- fi
102534
-
102535
- # Check frontmatter is properly closed
102536
- closing_line=$(echo "$staged" | tail -n +2 | grep -n '^---$' | head -1 | cut -d: -f1)
102537
- if [ -z "$closing_line" ]; then
102538
- errors="$errors\\n $file: frontmatter opened but never closed (missing closing ---)"
102539
- continue
102540
- fi
102541
-
102542
- # Check read_only protection against HEAD version
102543
- head_content=$(git show "HEAD:$file" 2>/dev/null || true)
102544
- if [ -n "$head_content" ]; then
102545
- head_ro=$(get_fm_value "$head_content" "read_only")
102546
- if [ "$head_ro" = "true" ]; then
102547
- errors="$errors\\n $file: file is read_only and cannot be modified"
102548
- continue
102549
- fi
102550
- fi
102551
-
102552
- # Extract frontmatter lines
102553
- frontmatter=$(echo "$staged" | tail -n +2 | head -n $((closing_line - 1)))
102554
-
102555
- # Track required fields
102556
- has_description=false
102557
- has_limit=false
102558
-
102559
- # Validate each line
102560
- while IFS= read -r line; do
102561
- [ -z "$line" ] && continue
102562
-
102563
- key=$(echo "$line" | cut -d: -f1 | tr -d ' ')
102564
- value=$(echo "$line" | cut -d: -f2- | sed 's/^ *//;s/ *$//')
102565
-
102566
- # Check key is known
102567
- known=false
102568
- for k in $ALL_KNOWN_KEYS; do
102569
- if [ "$key" = "$k" ]; then
102570
- known=true
102571
- break
102572
- fi
102573
- done
102574
- if [ "$known" = "false" ]; then
102575
- errors="$errors\\n $file: unknown frontmatter key '$key' (allowed: $ALL_KNOWN_KEYS)"
102576
- continue
102577
- fi
102578
-
102579
- # Check if agent is trying to modify a protected key
102580
- for k in $PROTECTED_KEYS; do
102581
- if [ "$key" = "$k" ]; then
102582
- # Compare against HEAD — if value changed (or key was added), reject
102583
- if [ -n "$head_content" ]; then
102584
- head_val=$(get_fm_value "$head_content" "$key")
102585
- if [ "$value" != "$head_val" ]; then
102586
- errors="$errors\\n $file: '$key' is a protected field and cannot be changed by the agent"
102587
- fi
102588
- else
102589
- # New file with read_only — agent shouldn't set this
102590
- errors="$errors\\n $file: '$key' is a protected field and cannot be set by the agent"
102591
- fi
102592
- fi
102593
- done
102594
-
102595
- # Validate value types
102596
- case "$key" in
102597
- limit)
102598
- has_limit=true
102599
- if ! echo "$value" | grep -qE '^[0-9]+$' || [ "$value" = "0" ]; then
102600
- errors="$errors\\n $file: 'limit' must be a positive integer, got '$value'"
102601
- fi
102602
- ;;
102603
- description)
102604
- has_description=true
102605
- if [ -z "$value" ]; then
102606
- errors="$errors\\n $file: 'description' must not be empty"
102607
- fi
102608
- ;;
102609
- esac
102610
- done <<< "$frontmatter"
102611
-
102612
- # Check required fields
102613
- if [ "$has_description" = "false" ]; then
102614
- errors="$errors\\n $file: missing required field 'description'"
102615
- fi
102616
- if [ "$has_limit" = "false" ]; then
102617
- errors="$errors\\n $file: missing required field 'limit'"
102618
- fi
102619
-
102620
- # Check if protected keys were removed (existed in HEAD but not in staged)
102621
- if [ -n "$head_content" ]; then
102622
- for k in $PROTECTED_KEYS; do
102623
- head_val=$(get_fm_value "$head_content" "$k")
102624
- if [ -n "$head_val" ]; then
102625
- staged_val=$(get_fm_value "$staged" "$k")
102626
- if [ -z "$staged_val" ]; then
102627
- errors="$errors\\n $file: '$k' is a protected field and cannot be removed by the agent"
102628
- fi
102629
- fi
102630
- done
102631
- fi
102632
- done
102633
-
102634
- if [ -n "$errors" ]; then
102635
- echo "Frontmatter validation failed:"
102636
- echo -e "$errors"
102637
- exit 1
102638
- fi
102639
- `;
102640
- var init_memoryGit2 = __esm(async () => {
102641
- init_debug();
102642
- await init_client2();
102643
- execFile9 = promisify10(execFileCb2);
102644
- });
102684
+ var MEMORY_FS_ROOT2 = ".letta", MEMORY_FS_AGENTS_DIR2 = "agents", MEMORY_FS_MEMORY_DIR2 = "memory", MEMORY_SYSTEM_DIR2 = "system";
102685
+ var init_memoryFilesystem2 = () => {};
102645
102686
 
102646
102687
  // src/index.ts
102647
102688
  import { parseArgs as parseArgs6 } from "util";
@@ -102905,10 +102946,6 @@ init_oauth();
102905
102946
  init_timing();
102906
102947
  await init_settings_manager();
102907
102948
  import { hostname } from "node:os";
102908
- function getServerUrl() {
102909
- const settings = settingsManager.getSettings();
102910
- return process.env.LETTA_BASE_URL || settings.env?.LETTA_BASE_URL || LETTA_CLOUD_API_URL;
102911
- }
102912
102949
  async function getClient() {
102913
102950
  const settings = await settingsManager.getSettingsWithSecureTokens();
102914
102951
  let apiKey = process.env.LETTA_API_KEY || settings.env?.LETTA_API_KEY;
@@ -102958,15 +102995,17 @@ function getContext() {
102958
102995
  global2[CONTEXT_KEY] = {
102959
102996
  agentId: null,
102960
102997
  skillsDirectory: null,
102998
+ noSkills: false,
102961
102999
  conversationId: null
102962
103000
  };
102963
103001
  }
102964
103002
  return global2[CONTEXT_KEY];
102965
103003
  }
102966
103004
  var context = getContext();
102967
- function setAgentContext(agentId, skillsDirectory) {
103005
+ function setAgentContext(agentId, skillsDirectory, noSkills) {
102968
103006
  context.agentId = agentId;
102969
103007
  context.skillsDirectory = skillsDirectory || null;
103008
+ context.noSkills = noSkills ?? false;
102970
103009
  }
102971
103010
  function setConversationId(conversationId) {
102972
103011
  context.conversationId = conversationId;
@@ -103043,8 +103082,9 @@ function extractUserMessagePreview(message) {
103043
103082
  for (let i = content.length - 1;i >= 0; i--) {
103044
103083
  const part = content[i];
103045
103084
  if (part?.type === "text" && part.text) {
103046
- if (part.text.startsWith(SYSTEM_REMINDER_OPEN))
103085
+ if (part.text.startsWith(SYSTEM_REMINDER_OPEN) || part.text.startsWith(SYSTEM_ALERT_OPEN)) {
103047
103086
  continue;
103087
+ }
103048
103088
  textToShow = part.text;
103049
103089
  break;
103050
103090
  }
@@ -106270,12 +106310,12 @@ EXAMPLES
106270
106310
  console.log(usage);
106271
106311
  }
106272
106312
  async function printInfo() {
106273
- const { join: join33 } = await import("path");
106313
+ const { join: join34 } = await import("path");
106274
106314
  const { getVersion: getVersion3 } = await Promise.resolve().then(() => (init_version2(), exports_version));
106275
106315
  const { SKILLS_DIR: SKILLS_DIR3 } = await Promise.resolve().then(() => (init_skills2(), exports_skills2));
106276
106316
  const { exists: exists3 } = await Promise.resolve().then(() => (init_fs2(), exports_fs));
106277
106317
  const cwd2 = process.cwd();
106278
- const skillsDir = join33(cwd2, SKILLS_DIR3);
106318
+ const skillsDir = join34(cwd2, SKILLS_DIR3);
106279
106319
  const skillsExist = exists3(skillsDir);
106280
106320
  await settingsManager2.loadLocalProjectSettings(cwd2);
106281
106321
  const localPinned = settingsManager2.getLocalPinnedAgents(cwd2);
@@ -106476,8 +106516,10 @@ Auto-update failed due to filesystem issue (ENOTEMPTY).`);
106476
106516
  "pre-load-skills": { type: "string" },
106477
106517
  "from-af": { type: "string" },
106478
106518
  import: { type: "string" },
106519
+ tags: { type: "string" },
106479
106520
  memfs: { type: "boolean" },
106480
106521
  "no-memfs": { type: "boolean" },
106522
+ "no-skills": { type: "boolean" },
106481
106523
  "max-turns": { type: "string" }
106482
106524
  },
106483
106525
  strict: true,
@@ -106556,6 +106598,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
106556
106598
  const skillsDirectory = values.skills ?? undefined;
106557
106599
  const memfsFlag = values.memfs;
106558
106600
  const noMemfsFlag = values["no-memfs"];
106601
+ const noSkillsFlag = values["no-skills"];
106559
106602
  const fromAfFile = values.import ?? values["from-af"];
106560
106603
  const isHeadless = values.prompt || values.run || !process.stdin.isTTY;
106561
106604
  if (command && !isHeadless) {
@@ -106821,7 +106864,7 @@ Error: ${message}`);
106821
106864
  await loadTools2(modelForTools);
106822
106865
  markMilestone2("TOOLS_LOADED");
106823
106866
  const { handleHeadlessCommand: handleHeadlessCommand2 } = await init_headless().then(() => exports_headless);
106824
- await handleHeadlessCommand2(process.argv, specifiedModel, skillsDirectory);
106867
+ await handleHeadlessCommand2(process.argv, specifiedModel, skillsDirectory, noSkillsFlag);
106825
106868
  return;
106826
106869
  }
106827
106870
  markMilestone2("TUI_MODE_START");
@@ -107269,32 +107312,14 @@ Error: ${message}`);
107269
107312
  }
107270
107313
  } catch {}
107271
107314
  }
107272
- setAgentContext(agent.id, skillsDirectory2);
107315
+ setAgentContext(agent.id, skillsDirectory2, noSkillsFlag);
107273
107316
  const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
107274
- if (memfsFlag) {
107275
- const serverUrl = getServerUrl();
107276
- if (!serverUrl.includes("api.letta.com")) {
107277
- console.error("--memfs is only available on Letta Cloud (api.letta.com).");
107278
- process.exit(1);
107279
- }
107280
- settingsManager2.setMemfsEnabled(agent.id, true);
107281
- } else if (noMemfsFlag) {
107282
- settingsManager2.setMemfsEnabled(agent.id, false);
107283
- }
107284
- if (settingsManager2.isMemfsEnabled(agent.id) && memfsFlag) {
107285
- const { detachMemoryTools: detachMemoryTools3 } = await init_toolset2().then(() => exports_toolset2);
107286
- await detachMemoryTools3(agent.id);
107287
- }
107288
- if (memfsFlag || noMemfsFlag) {
107289
- const { updateAgentSystemPromptMemfs: updateAgentSystemPromptMemfs3 } = await init_modify2().then(() => exports_modify2);
107290
- await updateAgentSystemPromptMemfs3(agent.id, settingsManager2.isMemfsEnabled(agent.id));
107291
- }
107292
- if (settingsManager2.isMemfsEnabled(agent.id)) {
107293
- const { addGitMemoryTag: addGitMemoryTag3, isGitRepo: isGitRepo3, cloneMemoryRepo: cloneMemoryRepo3 } = await init_memoryGit2().then(() => exports_memoryGit2);
107294
- await addGitMemoryTag3(agent.id);
107295
- if (!isGitRepo3(agent.id)) {
107296
- await cloneMemoryRepo3(agent.id);
107297
- }
107317
+ try {
107318
+ const { applyMemfsFlags: applyMemfsFlags3 } = await Promise.resolve().then(() => (init_memoryFilesystem2(), exports_memoryFilesystem2));
107319
+ await applyMemfsFlags3(agent.id, memfsFlag, noMemfsFlag);
107320
+ } catch (error) {
107321
+ console.error(error instanceof Error ? error.message : String(error));
107322
+ process.exit(1);
107298
107323
  }
107299
107324
  const isResumingProject = !shouldCreateNew && !!resumingAgentId;
107300
107325
  const isReusingExistingAgent = !shouldCreateNew && !fromAfFile2 && agent && agent.id;
@@ -107547,4 +107572,4 @@ Error during initialization: ${message}`);
107547
107572
  }
107548
107573
  main();
107549
107574
 
107550
- //# debugId=3372F396AE7A3CDF64756E2164756E21
107575
+ //# debugId=90C1BD0F21F7961E64756E2164756E21