@letta-ai/letta-code 0.33.2 → 0.33.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-presets.js +15 -30
  3. package/dist/agent-presets.js.map +3 -3
  4. package/dist/gateway-core.js +3 -2
  5. package/dist/gateway-core.js.map +3 -3
  6. package/dist/mcp-client.js +2 -2
  7. package/dist/mcp-client.js.map +1 -1
  8. package/dist/types/agent/approval-execution.d.ts.map +1 -1
  9. package/dist/types/agent/cloud-managed-system-prompt.d.ts +10 -0
  10. package/dist/types/agent/cloud-managed-system-prompt.d.ts.map +1 -0
  11. package/dist/types/agent/create-agent-request.d.ts +4 -0
  12. package/dist/types/agent/create-agent-request.d.ts.map +1 -1
  13. package/dist/types/agent/legacy-default-system-prompt-hashes.d.ts +14 -0
  14. package/dist/types/agent/legacy-default-system-prompt-hashes.d.ts.map +1 -0
  15. package/dist/types/agent/memory-conflict-repair.d.ts +5 -4
  16. package/dist/types/agent/memory-conflict-repair.d.ts.map +1 -1
  17. package/dist/types/agent/memory-constraints-audit.d.ts +19 -0
  18. package/dist/types/agent/memory-constraints-audit.d.ts.map +1 -0
  19. package/dist/types/agent/memory-constraints.d.ts.map +1 -1
  20. package/dist/types/agent/memory-filesystem.d.ts.map +1 -1
  21. package/dist/types/agent/memory-format.d.ts +1 -3
  22. package/dist/types/agent/memory-format.d.ts.map +1 -1
  23. package/dist/types/agent/memory-git-hooks.d.ts +7 -0
  24. package/dist/types/agent/memory-git-hooks.d.ts.map +1 -1
  25. package/dist/types/agent/memory-git.d.ts +3 -12
  26. package/dist/types/agent/memory-git.d.ts.map +1 -1
  27. package/dist/types/agent/modify.d.ts +1 -1
  28. package/dist/types/agent/modify.d.ts.map +1 -1
  29. package/dist/types/agent/subagent-state.d.ts +5 -1
  30. package/dist/types/agent/subagent-state.d.ts.map +1 -1
  31. package/dist/types/agent/subagents/child-send-tracking.d.ts +1 -1
  32. package/dist/types/agent/subagents/child-send-tracking.d.ts.map +1 -1
  33. package/dist/types/agent/subagents/remote-turn-wait.d.ts.map +1 -1
  34. package/dist/types/agent/system-prompt-versioning.d.ts +8 -0
  35. package/dist/types/agent/system-prompt-versioning.d.ts.map +1 -1
  36. package/dist/types/backend/api/conversation-enqueue.d.ts +10 -0
  37. package/dist/types/backend/api/conversation-enqueue.d.ts.map +1 -1
  38. package/dist/types/backend/local/initial-memory.d.ts +7 -0
  39. package/dist/types/backend/local/initial-memory.d.ts.map +1 -0
  40. package/dist/types/backend/local/local-backend.d.ts.map +1 -1
  41. package/dist/types/backend/local/local-store.d.ts +66 -26
  42. package/dist/types/backend/local/local-store.d.ts.map +1 -1
  43. package/dist/types/backend/local/local-transcript.d.ts +171 -0
  44. package/dist/types/backend/local/local-transcript.d.ts.map +1 -0
  45. package/dist/types/backend/local/local-types.d.ts +8 -0
  46. package/dist/types/backend/local/local-types.d.ts.map +1 -1
  47. package/dist/types/backend/local/system-prompt-compilation.d.ts.map +1 -1
  48. package/dist/types/channels/message-channel-tool-definition.d.ts.map +1 -1
  49. package/dist/types/cli/helpers/tool-name-mapping.d.ts.map +1 -1
  50. package/dist/types/headless-super-run-wait.d.ts +7 -11
  51. package/dist/types/headless-super-run-wait.d.ts.map +1 -1
  52. package/dist/types/mods/disabled-mod-adapter.d.ts.map +1 -1
  53. package/dist/types/mods/event-emitter.d.ts +2 -0
  54. package/dist/types/mods/event-emitter.d.ts.map +1 -1
  55. package/dist/types/mods/mod-adapter.d.ts.map +1 -1
  56. package/dist/types/permissions/checker.d.ts.map +1 -1
  57. package/dist/types/permissions/cross-agent-guard.d.ts +1 -1
  58. package/dist/types/permissions/mode.d.ts.map +1 -1
  59. package/dist/types/permissions/workspace-sandbox.d.ts.map +1 -1
  60. package/dist/types/queue/queue-runtime.d.ts +2 -0
  61. package/dist/types/queue/queue-runtime.d.ts.map +1 -1
  62. package/dist/types/queue/turn-queue-runtime.d.ts +23 -0
  63. package/dist/types/queue/turn-queue-runtime.d.ts.map +1 -0
  64. package/dist/types/reminders/catalog.d.ts +1 -1
  65. package/dist/types/reminders/catalog.d.ts.map +1 -1
  66. package/dist/types/reminders/disk-space.d.ts +47 -0
  67. package/dist/types/reminders/disk-space.d.ts.map +1 -0
  68. package/dist/types/reminders/engine.d.ts.map +1 -1
  69. package/dist/types/reminders/state.d.ts +2 -0
  70. package/dist/types/reminders/state.d.ts.map +1 -1
  71. package/dist/types/telemetry/event-queue.d.ts +32 -0
  72. package/dist/types/telemetry/event-queue.d.ts.map +1 -0
  73. package/dist/types/telemetry/index.d.ts +1 -0
  74. package/dist/types/telemetry/index.d.ts.map +1 -1
  75. package/dist/types/tools/external-tool-background-eligibility.d.ts +24 -0
  76. package/dist/types/tools/external-tool-background-eligibility.d.ts.map +1 -0
  77. package/dist/types/tools/external-tool-background.d.ts +28 -0
  78. package/dist/types/tools/external-tool-background.d.ts.map +1 -0
  79. package/dist/types/tools/external-tool-types.d.ts +44 -0
  80. package/dist/types/tools/external-tool-types.d.ts.map +1 -0
  81. package/dist/types/tools/impl/bash.d.ts.map +1 -1
  82. package/dist/types/tools/impl/exec-command.d.ts.map +1 -1
  83. package/dist/types/tools/impl/external-coding-agent.d.ts +2 -0
  84. package/dist/types/tools/impl/external-coding-agent.d.ts.map +1 -1
  85. package/dist/types/tools/impl/github-pull-request-diff.d.ts +7 -0
  86. package/dist/types/tools/impl/github-pull-request-diff.d.ts.map +1 -0
  87. package/dist/types/tools/impl/github-pull-request-query.d.ts +4 -0
  88. package/dist/types/tools/impl/github-pull-request-query.d.ts.map +1 -0
  89. package/dist/types/tools/impl/github-pull-request-state.d.ts +11 -0
  90. package/dist/types/tools/impl/github-pull-request-state.d.ts.map +1 -0
  91. package/dist/types/tools/impl/github-pull-request-types.d.ts +53 -0
  92. package/dist/types/tools/impl/github-pull-request-types.d.ts.map +1 -0
  93. package/dist/types/tools/impl/github-pull-request-watch.d.ts +16 -0
  94. package/dist/types/tools/impl/github-pull-request-watch.d.ts.map +1 -0
  95. package/dist/types/tools/impl/memory-task-lifecycle.d.ts +9 -8
  96. package/dist/types/tools/impl/memory-task-lifecycle.d.ts.map +1 -1
  97. package/dist/types/tools/impl/monitor.d.ts +20 -0
  98. package/dist/types/tools/impl/monitor.d.ts.map +1 -1
  99. package/dist/types/tools/impl/process_manager.d.ts +1 -1
  100. package/dist/types/tools/impl/process_manager.d.ts.map +1 -1
  101. package/dist/types/tools/impl/shell-env.d.ts +1 -1
  102. package/dist/types/tools/impl/shell-env.d.ts.map +1 -1
  103. package/dist/types/tools/impl/truncation.d.ts +0 -16
  104. package/dist/types/tools/impl/truncation.d.ts.map +1 -1
  105. package/dist/types/tools/impl/watch-pr.d.ts +32 -0
  106. package/dist/types/tools/impl/watch-pr.d.ts.map +1 -0
  107. package/dist/types/tools/impl/windows-command-safety.d.ts +9 -0
  108. package/dist/types/tools/impl/windows-command-safety.d.ts.map +1 -0
  109. package/dist/types/tools/impl/workflow.d.ts +3 -2
  110. package/dist/types/tools/impl/workflow.d.ts.map +1 -1
  111. package/dist/types/tools/manager.d.ts +3 -55
  112. package/dist/types/tools/manager.d.ts.map +1 -1
  113. package/dist/types/tools/removed-tools.d.ts.map +1 -1
  114. package/dist/types/tools/task-tool-assets.d.ts +9 -0
  115. package/dist/types/tools/task-tool-assets.d.ts.map +1 -1
  116. package/dist/types/tools/tool-definitions.d.ts +1 -79
  117. package/dist/types/tools/tool-definitions.d.ts.map +1 -1
  118. package/dist/types/tools/toolset-catalog.d.ts +1 -1
  119. package/dist/types/tools/toolset-catalog.d.ts.map +1 -1
  120. package/dist/types/types/background-process-protocol.d.ts +1 -1
  121. package/dist/types/types/background-process-protocol.d.ts.map +1 -1
  122. package/dist/types/types/external-tool-protocol.d.ts +4 -0
  123. package/dist/types/types/external-tool-protocol.d.ts.map +1 -1
  124. package/dist/types/types/loop-status-protocol.d.ts +31 -0
  125. package/dist/types/types/loop-status-protocol.d.ts.map +1 -1
  126. package/dist/types/types/protocol_v2.d.ts +3 -29
  127. package/dist/types/types/protocol_v2.d.ts.map +1 -1
  128. package/dist/types/utils/message-queue-bridge.d.ts +3 -0
  129. package/dist/types/utils/message-queue-bridge.d.ts.map +1 -1
  130. package/dist/types/utils/task-notifications.d.ts +1 -1
  131. package/dist/types/utils/task-notifications.d.ts.map +1 -1
  132. package/dist/types/websocket/listener/outbound-wire.d.ts.map +1 -1
  133. package/dist/types/websocket/listener/protocol-outbound.d.ts +0 -10
  134. package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
  135. package/dist/types/websocket/listener/queue.d.ts.map +1 -1
  136. package/dist/types/websocket/listener/runtime.d.ts +2 -0
  137. package/dist/types/websocket/listener/runtime.d.ts.map +1 -1
  138. package/dist/types/websocket/listener/turn-correlation.d.ts +1 -0
  139. package/dist/types/websocket/listener/turn-correlation.d.ts.map +1 -1
  140. package/dist/types/websocket/listener/types.d.ts +4 -0
  141. package/dist/types/websocket/listener/types.d.ts.map +1 -1
  142. package/letta.js +15043 -14689
  143. package/package.json +2 -1
  144. package/scripts/agent-watch/verify-pr-identity.test.ts +52 -0
  145. package/scripts/agent-watch/verify-pr-identity.ts +13 -4
  146. package/scripts/isolated-unit-tests.json +5 -10
  147. package/scripts/postinstall-patches.js +53 -3
  148. package/scripts/source-file-size-baseline.json +9 -11
  149. package/scripts/stage-pypi-deps.mjs +10 -1
  150. package/skills/submitting-feedback/SKILL.md +2 -0
  151. package/dist/types/agent/memory-markdown.d.ts +0 -25
  152. package/dist/types/agent/memory-markdown.d.ts.map +0 -1
  153. package/dist/types/tools/impl/memory-apply-patch.d.ts +0 -10
  154. package/dist/types/tools/impl/memory-apply-patch.d.ts.map +0 -1
  155. package/dist/types/tools/impl/memory.d.ts +0 -20
  156. package/dist/types/tools/impl/memory.d.ts.map +0 -1
  157. package/dist/types/tools/memory-tool-assets.d.ts +0 -6
  158. package/dist/types/tools/memory-tool-assets.d.ts.map +0 -1
  159. package/dist/types/tools/tool-permissions.d.ts +0 -7
  160. package/dist/types/tools/tool-permissions.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.33.2",
3
+ "version": "0.33.4",
4
4
  "lettaStartupLogProtocol": 1,
5
5
  "description": "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
6
6
  "type": "module",
@@ -138,6 +138,7 @@
138
138
  "@modelcontextprotocol/sdk": "1.30.0",
139
139
  "@pierre/diffs": "1.2.2",
140
140
  "@scarf/scarf": "^1.4.0",
141
+ "@shikijs/langs": "4.0.2",
141
142
  "cron-parser": "^5.6.1",
142
143
  "cross-spawn": "^7.0.6",
143
144
  "glob": "^13.0.0",
@@ -23,11 +23,13 @@ function pullRequest(
23
23
  function enforce(
24
24
  pullRequests: WatcherPullRequest[],
25
25
  closed: string[] = [],
26
+ pullRequestState: "draft" | "ready" = "draft",
26
27
  ): WatcherPullRequest | null {
27
28
  return enforceWatcherPrIdentity({
28
29
  repo: "letta-ai/letta-code",
29
30
  marker,
30
31
  expectedLogin: "amelia-letta",
32
+ pullRequestState,
31
33
  pullRequests,
32
34
  closePullRequest: (candidate) => closed.push(candidate.url),
33
35
  });
@@ -58,6 +60,20 @@ describe("enforceWatcherPrIdentity", () => {
58
60
  expect(closed).toHaveLength(1);
59
61
  });
60
62
 
63
+ test("returns the matching Amelia ready PR when ready is required", () => {
64
+ expect(
65
+ enforce([pullRequest({ isDraft: false })], [], "ready")?.number,
66
+ ).toBe(123);
67
+ });
68
+
69
+ test("closes and rejects a draft PR when ready is required", () => {
70
+ const closed: string[] = [];
71
+ expect(() => enforce([pullRequest()], closed, "ready")).toThrow(
72
+ "state=ready",
73
+ );
74
+ expect(closed).toHaveLength(1);
75
+ });
76
+
61
77
  test("rejects duplicate valid PRs", () => {
62
78
  expect(() =>
63
79
  enforce([
@@ -78,6 +94,19 @@ describe("parseArgs", () => {
78
94
  );
79
95
  });
80
96
 
97
+ test("requires the expected pull request state", () => {
98
+ expect(() =>
99
+ parseArgs([
100
+ "--repo",
101
+ "letta-ai/letta-code",
102
+ "--marker",
103
+ marker,
104
+ "--expected-login",
105
+ "amelia-letta",
106
+ ]),
107
+ ).toThrow("--pull-request-state is required");
108
+ });
109
+
81
110
  test("parses a complete invocation", () => {
82
111
  expect(
83
112
  parseArgs([
@@ -87,11 +116,34 @@ describe("parseArgs", () => {
87
116
  marker,
88
117
  "--expected-login",
89
118
  "amelia-letta",
119
+ "--pull-request-state",
120
+ "draft",
90
121
  ]),
91
122
  ).toEqual({
92
123
  repo: "letta-ai/letta-code",
93
124
  marker,
94
125
  expectedLogin: "amelia-letta",
126
+ pullRequestState: "draft",
127
+ });
128
+ });
129
+
130
+ test("parses a ready pull request requirement", () => {
131
+ expect(
132
+ parseArgs([
133
+ "--repo",
134
+ "letta-ai/letta-cloud",
135
+ "--marker",
136
+ marker,
137
+ "--expected-login",
138
+ "amelia-letta",
139
+ "--pull-request-state",
140
+ "ready",
141
+ ]),
142
+ ).toEqual({
143
+ repo: "letta-ai/letta-cloud",
144
+ marker,
145
+ expectedLogin: "amelia-letta",
146
+ pullRequestState: "ready",
95
147
  });
96
148
  });
97
149
  });
@@ -13,6 +13,7 @@ export interface WatcherPullRequest {
13
13
  interface Args {
14
14
  expectedLogin: string;
15
15
  marker: string;
16
+ pullRequestState: "draft" | "ready";
16
17
  repo: string;
17
18
  }
18
19
 
@@ -30,7 +31,7 @@ export function enforceWatcherPrIdentity(
30
31
  const invalid = matches.filter(
31
32
  (pullRequest) =>
32
33
  pullRequest.author?.login !== options.expectedLogin ||
33
- !pullRequest.isDraft,
34
+ pullRequest.isDraft !== (options.pullRequestState === "draft"),
34
35
  );
35
36
 
36
37
  for (const pullRequest of invalid) options.closePullRequest(pullRequest);
@@ -43,7 +44,7 @@ export function enforceWatcherPrIdentity(
43
44
  )
44
45
  .join(", ");
45
46
  throw new Error(
46
- `Closed watcher PRs that did not match author=${options.expectedLogin} and draft=true: ${details}`,
47
+ `Closed watcher PRs that did not match author=${options.expectedLogin} and state=${options.pullRequestState}: ${details}`,
47
48
  );
48
49
  }
49
50
  if (matches.length > 1) {
@@ -58,12 +59,19 @@ export function parseArgs(argv: string[]): Args {
58
59
  let repo = "";
59
60
  let marker = "";
60
61
  let expectedLogin = "";
62
+ let pullRequestState: "draft" | "ready" | undefined;
61
63
  for (let index = 0; index < argv.length; index += 1) {
62
64
  const argument = argv[index];
63
65
  if (argument === "--repo") repo = argv[++index] ?? "";
64
66
  else if (argument === "--marker") marker = argv[++index] ?? "";
65
67
  else if (argument === "--expected-login") {
66
68
  expectedLogin = argv[++index] ?? "";
69
+ } else if (argument === "--pull-request-state") {
70
+ const state = argv[++index];
71
+ if (state !== "draft" && state !== "ready") {
72
+ throw new Error("--pull-request-state must be draft or ready");
73
+ }
74
+ pullRequestState = state;
67
75
  } else {
68
76
  throw new Error(`Unknown argument: ${argument}`);
69
77
  }
@@ -71,7 +79,8 @@ export function parseArgs(argv: string[]): Args {
71
79
  if (!/^[^/]+\/[^/]+$/.test(repo)) throw new Error("--repo is required");
72
80
  if (!marker) throw new Error("--marker is required");
73
81
  if (!expectedLogin) throw new Error("--expected-login is required");
74
- return { repo, marker, expectedLogin };
82
+ if (!pullRequestState) throw new Error("--pull-request-state is required");
83
+ return { repo, marker, expectedLogin, pullRequestState };
75
84
  }
76
85
 
77
86
  function runGh(args: string[]): string {
@@ -111,7 +120,7 @@ function main(): void {
111
120
  });
112
121
  console.log(
113
122
  verified
114
- ? `Verified Amelia draft PR: ${verified.url}`
123
+ ? `Verified Amelia ${args.pullRequestState} PR: ${verified.url}`
115
124
  : `No open PR contains marker ${JSON.stringify(args.marker)}`,
116
125
  );
117
126
  }
@@ -175,16 +175,6 @@
175
175
  "timeoutMs": 30000,
176
176
  "reason": "Spawns real Git processes and mutates HOME, USER_CWD, cwd, and runtime singletons."
177
177
  },
178
- {
179
- "path": "src/tools/memory-apply-patch.test.ts",
180
- "timeoutMs": 15000,
181
- "reason": "Uses a top-level Bun module mock for the backend client."
182
- },
183
- {
184
- "path": "src/tools/memory-tool.test.ts",
185
- "timeoutMs": 15000,
186
- "reason": "Uses a top-level Bun module mock for the backend client."
187
- },
188
178
  {
189
179
  "path": "src/agent/available-models.test.ts",
190
180
  "timeoutMs": 15000,
@@ -200,6 +190,11 @@
200
190
  "timeoutMs": 15000,
201
191
  "reason": "Uses a top-level Bun module mock for the backend client."
202
192
  },
193
+ {
194
+ "path": "src/websocket/app-server-openai.test.ts",
195
+ "timeoutMs": 30000,
196
+ "reason": "Starts a real App Server and swaps the process-global backend while exercising persistent LocalBackend conversation state."
197
+ },
203
198
  {
204
199
  "path": "src/websocket/listen-client-concurrency.test.ts",
205
200
  "timeoutMs": 30000,
@@ -171,11 +171,17 @@ await patchInkRuntime([
171
171
  },
172
172
  {
173
173
  before: [
174
+ // Current patched state from the 8 MiB follow-up on this branch.
175
+ " fullStaticOutput;\n staticOutputRepaintPending = false;\n isCi = () => isInCi && !this.options.stdout.isTTY;\n // Cap the retained static transcript tail (in UTF-16 code units). Ink keeps\n // fullStaticOutput so overflow frames and static repaints can rewrite the\n // newest tail after a viewport clear. Overflow uses 2J+H (no 3J) so emulator\n // scrollback keeps older history; 8 MiB is a UX-sized rewrite window (256 KB\n // is one large Read/git diff) and bounds per-frame write volume. Uncapped,\n // the string grows with the whole session and is re-serialized on overflow.\n staticOutputRetainLimit = 8 * 1024 * 1024;\n retainStaticOutput = (value) => {\n if (value.length <= this.staticOutputRetainLimit) {\n return value;\n }\n const cut = value.indexOf('\\n', value.length - this.staticOutputRetainLimit);\n return '\\u001B[0m' + (cut === -1 ? value.slice(value.length - this.staticOutputRetainLimit) : value.slice(cut + 1));\n };\n exitPromise;",
176
+ // Current patched state from this PR's first commit (256 KB cap).
177
+ " fullStaticOutput;\n staticOutputRepaintPending = false;\n isCi = () => isInCi && !this.options.stdout.isTTY;\n // Cap the retained static transcript tail (in UTF-16 code units). Ink keeps\n // fullStaticOutput so overflow frames and static repaints can rewrite the\n // transcript after clearing the terminal; uncapped it grows linearly with\n // the whole session transcript and is re-serialized on every overflow frame.\n staticOutputRetainLimit = 256 * 1024;\n retainStaticOutput = (value) => {\n if (value.length <= this.staticOutputRetainLimit) {\n return value;\n }\n const cut = value.indexOf('\\n', value.length - this.staticOutputRetainLimit);\n return '\\u001B[0m' + (cut === -1 ? value.slice(value.length - this.staticOutputRetainLimit) : value.slice(cut + 1));\n };\n exitPromise;",
178
+ // Current patched state from a previous install (transition path).
179
+ " fullStaticOutput;\n staticOutputRepaintPending = false;\n isCi = () => isInCi && !this.options.stdout.isTTY;\n exitPromise;",
174
180
  " fullStaticOutput;\n staticOutputRepaintPending = false;\n exitPromise;",
175
181
  " fullStaticOutput;\n exitPromise;",
176
182
  ],
177
183
  after:
178
- " fullStaticOutput;\n staticOutputRepaintPending = false;\n isCi = () => isInCi && !this.options.stdout.isTTY;\n exitPromise;",
184
+ " fullStaticOutput;\n staticOutputRepaintPending = false;\n isCi = () => isInCi && !this.options.stdout.isTTY;\n // Cap the retained static transcript tail (in UTF-16 code units). Ink keeps\n // fullStaticOutput so overflow frames and static repaints can rewrite the\n // newest tail after a viewport clear. Overflow uses 2J+H (no 3J) so emulator\n // scrollback keeps older history; 2 MiB is a UX-sized rewrite window (256 KB\n // is one large Read/git diff) and bounds per-frame write volume. Uncapped,\n // the string grows with the whole session and is re-serialized on overflow.\n staticOutputRetainLimit = 2 * 1024 * 1024;\n retainStaticOutput = (value) => {\n if (value.length <= this.staticOutputRetainLimit) {\n return value;\n }\n const cut = value.indexOf('\\n', value.length - this.staticOutputRetainLimit);\n return '\\u001B[0m' + (cut === -1 ? value.slice(value.length - this.staticOutputRetainLimit) : value.slice(cut + 1));\n };\n exitPromise;",
179
185
  },
180
186
  {
181
187
  before: " if (isInCi) {",
@@ -191,9 +197,53 @@ await patchInkRuntime([
191
197
  after: " if (!this.isCi() && !this.options.debug) {",
192
198
  },
193
199
  {
194
- before: " if (this.options.debug) {",
195
- after:
200
+ before: [
201
+ // Current patched state from a previous install (transition path).
196
202
  " if (this.staticOutputRepaintPending && (this.options.debug || this.isCi())) {\n if (this.options.stdout.isTTY) {\n this.fullStaticOutput = hasStaticOutput ? staticOutput : '';\n this.repaintStaticOutput(output);\n return;\n }\n this.staticOutputRepaintPending = false;\n }\n if (this.options.debug) {",
203
+ " if (this.options.debug) {",
204
+ ],
205
+ after:
206
+ " if (this.staticOutputRepaintPending && (this.options.debug || this.isCi())) {\n if (this.options.stdout.isTTY) {\n this.fullStaticOutput = this.retainStaticOutput(hasStaticOutput ? staticOutput : '');\n this.repaintStaticOutput(output);\n return;\n }\n this.staticOutputRepaintPending = false;\n }\n if (this.options.debug) {",
207
+ },
208
+ {
209
+ // Bound steady-state growth: route every append through the tail cap.
210
+ before: "this.fullStaticOutput += staticOutput;",
211
+ after:
212
+ "this.fullStaticOutput = this.retainStaticOutput(this.fullStaticOutput + staticOutput);",
213
+ all: true,
214
+ },
215
+ {
216
+ // Overflow frames: do not replay fullStaticOutput and do not clear the
217
+ // screen. 2J erases on-screen transcript rows without saving them
218
+ // (xterm.js) or copies every live frame into history (tmux
219
+ // scroll-on-clear). Clip the live output to its last rows - 1 lines
220
+ // (approval/input sit at the bottom of AppView) so log-update's cursor-up
221
+ // region always fits on screen, then take the normal log-update path:
222
+ // new static rows scroll into history above the live region, the live
223
+ // region is rewritten in place, and unchanged frames are skipped.
224
+ // lastOutput keeps the clipped frame, so console redraws and later diffs
225
+ // match the screen. fullStaticOutput stays for the one-shot #4032 repaint.
226
+ before: [
227
+ // Current branch: 2J+H replace of the live tail clipped to rows lines.
228
+ " if (hasStaticOutput) {\n this.options.stdout.write(staticOutput + '\\n'.repeat(this.options.stdout.rows || 1));\n }\n if (hasStaticOutput || output !== this.lastOutput) {\n const rows = this.options.stdout.rows || 1;\n const liveLines = output.split('\\n');\n this.options.stdout.write('\\u001B[2J\\u001B[H' + (liveLines.length > rows ? liveLines.slice(-rows).join('\\n') : output));\n }\n this.lastOutput = output;\n return;",
229
+ // Earlier: clip kept the top of the live tree (hides input/approval).
230
+ " if (hasStaticOutput) {\n this.options.stdout.write(staticOutput + '\\n'.repeat(this.options.stdout.rows || 1));\n }\n if (hasStaticOutput || output !== this.lastOutput) {\n const rows = this.options.stdout.rows || 1;\n const liveLines = output.split('\\n');\n this.options.stdout.write('\\u001B[2J\\u001B[H' + (liveLines.length > rows ? liveLines.slice(0, rows).join('\\n') : output));\n }\n this.lastOutput = output;\n return;",
231
+ // Earlier: scroll increment then 2J+H the unclipped live region
232
+ // (still scrolls when outputHeight > rows).
233
+ " if (hasStaticOutput) {\n this.options.stdout.write(staticOutput + '\\n'.repeat(this.options.stdout.rows || 1));\n }\n if (hasStaticOutput || output !== this.lastOutput) {\n this.options.stdout.write('\\u001B[2J\\u001B[H' + output);\n }\n this.lastOutput = output;\n return;",
234
+ // Earlier: append increment and live with no viewport replace.
235
+ " if (hasStaticOutput) {\n this.options.stdout.write(staticOutput);\n }\n if (output !== this.lastOutput) {\n this.options.stdout.write(output);\n }\n this.lastOutput = output;\n return;",
236
+ // Earlier: increment immediately followed by 2J (erases the item).
237
+ " if (hasStaticOutput || output !== this.lastOutput) {\n this.options.stdout.write((hasStaticOutput ? staticOutput : '') + '\\u001B[2J\\u001B[H' + output);\n }\n this.lastOutput = output;\n return;",
238
+ // Earlier: 2J+H but still replayed the retained tail.
239
+ " if (hasStaticOutput || output !== this.lastOutput) {\n this.options.stdout.write('\\u001B[2J\\u001B[H' + this.fullStaticOutput + output);\n }\n this.lastOutput = output;\n return;",
240
+ // Earlier: skip-no-change guard still used clearTerminal (3J).
241
+ " if (hasStaticOutput || output !== this.lastOutput) {\n this.options.stdout.write(ansiEscapes.clearTerminal + this.fullStaticOutput + output);\n }\n this.lastOutput = output;\n return;",
242
+ // Pristine Ink / earlier patched state: always-rewrite overflow.
243
+ " this.options.stdout.write(ansiEscapes.clearTerminal + this.fullStaticOutput + output);\n this.lastOutput = output;\n return;",
244
+ ],
245
+ after:
246
+ " const liveOutput = output.split('\\n').slice(-Math.max(1, (this.options.stdout.rows || 1) - 1)).join('\\n');\n if (hasStaticOutput) {\n this.log.clear();\n this.options.stdout.write(staticOutput);\n this.log(liveOutput);\n }\n else if (liveOutput !== this.lastOutput) {\n this.throttledLog(liveOutput);\n }\n this.lastOutput = liveOutput;\n return;",
197
247
  },
198
248
  {
199
249
  before: " if (outputHeight >= this.options.stdout.rows) {",
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "src/agent/client-skills.test.ts": 1134,
3
- "src/agent/memory-git.ts": 2092,
4
- "src/backend/local-backend.test.ts": 2473,
5
- "src/backend/local/local-backend.ts": 1005,
6
- "src/backend/local/local-store.ts": 3457,
3
+ "src/agent/memory-git.ts": 2013,
4
+ "src/backend/local-backend.test.ts": 2472,
5
+ "src/backend/local/local-store.ts": 3276,
7
6
  "src/backend/pi-stream-adapter.test.ts": 1255,
8
- "src/cli/app/AppCoordinator.tsx": 5110,
7
+ "src/cli/app/AppCoordinator.tsx": 5109,
9
8
  "src/cli/app/AppView.tsx": 1735,
10
9
  "src/cli/app/use-approval-flow.ts": 1163,
11
10
  "src/cli/app/use-configuration-handlers.ts": 1417,
@@ -22,7 +21,7 @@
22
21
  "src/cli/subcommands/skills.ts": 1264,
23
22
  "src/headless.ts": 4788,
24
23
  "src/hooks/integration.test.ts": 1147,
25
- "src/index.ts": 2597,
24
+ "src/index.ts": 2578,
26
25
  "src/mods/learning-harness.ts": 2434,
27
26
  "src/mods/mod-engine.test.ts": 2153,
28
27
  "src/mods/mod-engine.ts": 1838,
@@ -34,13 +33,12 @@
34
33
  "src/providers/chatgpt-usage-service.ts": 1112,
35
34
  "src/settings-manager.test.ts": 1635,
36
35
  "src/settings-manager.ts": 2101,
37
- "src/tools/manager.ts": 2709,
36
+ "src/tools/manager.ts": 2649,
38
37
  "src/tools/tool-execution-context.test.ts": 1092,
39
- "src/types/protocol_v2.ts": 2574,
40
- "src/websocket/listen-client-concurrency.test.ts": 2666,
38
+ "src/types/protocol_v2.ts": 2550,
39
+ "src/websocket/listen-client-concurrency.test.ts": 2663,
41
40
  "src/websocket/listen-client-protocol.test.ts": 5759,
42
41
  "src/websocket/listener/commands/memory.ts": 1114,
43
42
  "src/websocket/listener/file-commands.ts": 1053,
44
- "src/websocket/listener/protocol-inbound.ts": 2111,
45
- "src/websocket/listener/protocol-outbound.ts": 1022
43
+ "src/websocket/listener/protocol-inbound.ts": 2111
46
44
  }
@@ -13,7 +13,16 @@ import { dirname, join, resolve } from "node:path";
13
13
  const root = process.cwd();
14
14
  const app = resolve(process.argv[2]);
15
15
  // sharp-electron is only reachable under Electron, never our bundled Node.
16
- const roots = ["ws", "@vscode/ripgrep", "node-pty", "grammy", "@pierre/diffs"];
16
+ // @shikijs/langs is external in the bundle so lazily-loaded grammars
17
+ // (LET-13149) resolve from here at runtime.
18
+ const roots = [
19
+ "ws",
20
+ "@vscode/ripgrep",
21
+ "node-pty",
22
+ "grammy",
23
+ "@pierre/diffs",
24
+ "@shikijs/langs",
25
+ ];
17
26
 
18
27
  function locate(name, from) {
19
28
  for (let dir = from; ; dir = dirname(dir)) {
@@ -7,6 +7,8 @@ description: Submits user-approved product feedback and bug reports about Letta
7
7
 
8
8
  Use this skill for product and developer feedback about Letta Code: reproducible bugs, broken features, confusing product behavior, and requested changes to the software or its developer-facing behavior.
9
9
 
10
+ If the user wants help or to give feedback on Letta Code, point them to discord.gg/letta or https://github.com/letta-ai/letta-code/issues.
11
+
10
12
  Do **not** use this skill when the user corrects how the current agent should behave, communicate, remember, or work with them. Treat that as learning: make the appropriate memory edit so the correction changes the agent's future behavior. A user's frustration with the agent is not by itself product feedback and is not a reason to offer feedback submission.
11
13
 
12
14
  If the user says yes, or directly asks you to submit feedback:
@@ -1,25 +0,0 @@
1
- import { type LocalMemoryFormat } from "./memory-format";
2
- export interface MemoryMarkdownFrontmatter {
3
- name?: string;
4
- description?: string;
5
- read_only?: string;
6
- }
7
- export interface ParsedMemoryMarkdown {
8
- frontmatter: MemoryMarkdownFrontmatter;
9
- body: string;
10
- }
11
- export declare function defaultMemoryName(label: string): string;
12
- export declare function parseMemoryMarkdown(options: {
13
- content: string;
14
- relativePath: string;
15
- format: LocalMemoryFormat;
16
- errorPrefix: string;
17
- }): ParsedMemoryMarkdown;
18
- export declare function renderMemoryMarkdown(options: {
19
- frontmatter: MemoryMarkdownFrontmatter;
20
- body: string;
21
- relativePath: string;
22
- format: LocalMemoryFormat;
23
- errorPrefix: string;
24
- }): string;
25
- //# sourceMappingURL=memory-markdown.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-markdown.d.ts","sourceRoot":"","sources":["../../../src/agent/memory-markdown.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,yBAAyB,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;CACd;AAgCD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOvD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,oBAAoB,CAqEvB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,WAAW,EAAE,yBAAyB,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CA8BT"}
@@ -1,10 +0,0 @@
1
- interface MemoryApplyPatchArgs {
2
- reason: string;
3
- input: string;
4
- }
5
- interface MemoryApplyPatchResult {
6
- message: string;
7
- }
8
- export declare function memory_apply_patch(args: MemoryApplyPatchArgs): Promise<MemoryApplyPatchResult>;
9
- export {};
10
- //# sourceMappingURL=memory-apply-patch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-apply-patch.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/memory-apply-patch.ts"],"names":[],"mappings":"AAuDA,UAAU,oBAAoB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,sBAAsB;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AA6CD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,sBAAsB,CAAC,CA4DjC"}
@@ -1,20 +0,0 @@
1
- type MemoryCommand = "str_replace" | "insert" | "delete" | "rename" | "update_description" | "create";
2
- interface MemoryArgs {
3
- command: MemoryCommand;
4
- reason: string;
5
- file_path?: string;
6
- old_path?: string;
7
- new_path?: string;
8
- old_string?: string;
9
- new_string?: string;
10
- insert_line?: number;
11
- insert_text?: string;
12
- description?: string;
13
- file_text?: string;
14
- }
15
- interface MemoryResult {
16
- message: string;
17
- }
18
- export declare function memory(args: MemoryArgs): Promise<MemoryResult>;
19
- export {};
20
- //# sourceMappingURL=memory.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/tools/impl/memory.ts"],"names":[],"mappings":"AAgCA,KAAK,aAAa,GACd,aAAa,GACb,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,oBAAoB,GACpB,QAAQ,CAAC;AAEb,UAAU,UAAU;IAClB,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6CD,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CA0DpE"}
@@ -1,6 +0,0 @@
1
- import type { JsonSchema } from "./model-facing-tool";
2
- export declare function resolveBackendSpecificToolAssets(name: string, description: string, inputSchema: JsonSchema): Promise<{
3
- description: string;
4
- inputSchema: JsonSchema;
5
- }>;
6
- //# sourceMappingURL=memory-tool-assets.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-tool-assets.d.ts","sourceRoot":"","sources":["../../../src/tools/memory-tool-assets.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOtD,wBAAsB,gCAAgC,CACpD,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,UAAU,GACtB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,UAAU,CAAA;CAAE,CAAC,CA0D3D"}
@@ -1,7 +0,0 @@
1
- import type { ToolApprovalPolicy } from "../mods/types";
2
- import type { ToolName } from "./tool-definitions";
3
- export declare const TOOL_PERMISSIONS: Record<ToolName, {
4
- requiresApproval: boolean;
5
- approvalPolicy?: ToolApprovalPolicy;
6
- }>;
7
- //# sourceMappingURL=tool-permissions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tool-permissions.d.ts","sourceRoot":"","sources":["../../../src/tools/tool-permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGnD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CACnC,QAAQ,EACR;IAAE,gBAAgB,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,kBAAkB,CAAA;CAAE,CAmCnE,CAAC"}