@letta-ai/letta-code 0.14.13 → 0.14.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.14.13",
3
+ "version": "0.14.15",
4
4
  "description": "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -100,6 +100,7 @@ await copyToResolved(
100
100
  "ink/build/hooks/use-input.js",
101
101
  );
102
102
  await copyToResolved("vendor/ink/build/devtools.js", "ink/build/devtools.js");
103
+ await copyToResolved("vendor/ink/build/log-update.js", "ink/build/log-update.js");
103
104
 
104
105
  // ink-text-input (optional vendor with externalCursorOffset support)
105
106
  await copyToResolved(
@@ -49,6 +49,7 @@ The memory subagent works directly on the memfs `system/` directory. After it fi
49
49
  ```typescript
50
50
  Task({
51
51
  subagent_type: "memory",
52
+ run_in_background: true,
52
53
  description: "Decompose and reorganize memory files",
53
54
  prompt: `You are decomposing and reorganizing memory files in ~/.letta/agents/${LETTA_AGENT_ID}/memory/system/ to improve clarity and focus.
54
55
 
@@ -162,14 +163,16 @@ Bash({
162
163
  description: "Backup memfs directory before defrag"
163
164
  })
164
165
 
165
- // Step 2: Spawn subagent to decompose and reorganize
166
+ // Step 2: Spawn subagent to decompose and reorganize (runs async in background)
166
167
  Task({
167
168
  subagent_type: "memory",
169
+ run_in_background: true,
168
170
  description: "Decompose and reorganize memory files",
169
171
  prompt: "Decompose and reorganize memory files in ~/.letta/agents/$LETTA_AGENT_ID/memory/system/. These files sync directly to API blocks via memfs. Be aggressive about splitting large multi-section blocks into many smaller, single-purpose blocks using hierarchical / naming. Skip memory_filesystem.md and .sync-state.json. Structure with markdown headers and bullets. Remove redundancy and speculation. Resolve contradictions. Organize logically. Each block should have ONE clear purpose. Report files created, modified, deleted, before/after character counts, and rationale for changes."
170
172
  })
171
173
 
172
174
  // No Step 3 needed — memfs sync handles propagation to API blocks
175
+ // Check progress with /task <task_id>, restart CLI to sync when done
173
176
  ```
174
177
 
175
178
  ## Rollback
@@ -0,0 +1,63 @@
1
+ import ansiEscapes from 'ansi-escapes';
2
+ import cliCursor from 'cli-cursor';
3
+
4
+ const create = (stream, { showCursor = false } = {}) => {
5
+ let previousLineCount = 0;
6
+ let previousOutput = '';
7
+ let hasHiddenCursor = false;
8
+
9
+ const renderWithClearedLineEnds = (output) => {
10
+ const lines = output.split('\n');
11
+ return lines.map((line) => line + ansiEscapes.eraseEndLine).join('\n');
12
+ };
13
+
14
+ const render = (str) => {
15
+ if (!showCursor && !hasHiddenCursor) {
16
+ cliCursor.hide();
17
+ hasHiddenCursor = true;
18
+ }
19
+
20
+ const output = str + '\n';
21
+ if (output === previousOutput) {
22
+ return;
23
+ }
24
+
25
+ // Keep existing line-count semantics used by Ink's bundled log-update.
26
+ const nextLineCount = output.split('\n').length;
27
+
28
+ // Avoid eraseLines() pre-clear flashes by repainting in place:
29
+ // move to start of previous frame, rewrite each line while erasing EOL,
30
+ // then clear any trailing old lines if the frame got shorter.
31
+ if (previousLineCount > 1) {
32
+ stream.write(ansiEscapes.cursorUp(previousLineCount - 1));
33
+ }
34
+ stream.write(renderWithClearedLineEnds(output));
35
+ if (nextLineCount < previousLineCount) {
36
+ stream.write(ansiEscapes.eraseDown);
37
+ }
38
+
39
+ previousOutput = output;
40
+ previousLineCount = nextLineCount;
41
+ };
42
+
43
+ render.clear = () => {
44
+ stream.write(ansiEscapes.eraseLines(previousLineCount));
45
+ previousOutput = '';
46
+ previousLineCount = 0;
47
+ };
48
+
49
+ render.done = () => {
50
+ previousOutput = '';
51
+ previousLineCount = 0;
52
+ if (!showCursor) {
53
+ cliCursor.show();
54
+ hasHiddenCursor = false;
55
+ }
56
+ };
57
+
58
+ return render;
59
+ };
60
+
61
+ const logUpdate = { create };
62
+ export default logUpdate;
63
+