@letta-ai/letta-code 0.34.23 → 0.34.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/app-server-client.cjs +2 -2
  2. package/dist/app-server-client.cjs.map +3 -3
  3. package/dist/app-server-client.js +2 -2
  4. package/dist/app-server-client.js.map +3 -3
  5. package/dist/gateway-core.js +7 -4
  6. package/dist/gateway-core.js.map +3 -3
  7. package/dist/mcp-client.js +2 -2
  8. package/dist/mcp-client.js.map +1 -1
  9. package/dist/mcp-oauth.js +2 -2
  10. package/dist/mcp-oauth.js.map +1 -1
  11. package/dist/types/agent/memory-constraints.d.ts +1 -1
  12. package/dist/types/agent/turn-recovery-policy.d.ts +3 -3
  13. package/dist/types/agent/turn-recovery-policy.d.ts.map +1 -1
  14. package/dist/types/backend/api/schedules.d.ts +6 -5
  15. package/dist/types/backend/api/schedules.d.ts.map +1 -1
  16. package/dist/types/backend/api/unified-mcp.d.ts.map +1 -1
  17. package/dist/types/backend/dev/fake-headless-backend.d.ts +1 -0
  18. package/dist/types/backend/dev/fake-headless-backend.d.ts.map +1 -1
  19. package/dist/types/backend/dev/provider-turn-executor.d.ts.map +1 -1
  20. package/dist/types/backend/local/local-conversation-key.d.ts +6 -0
  21. package/dist/types/backend/local/local-conversation-key.d.ts.map +1 -0
  22. package/dist/types/backend/local/local-store.d.ts.map +1 -1
  23. package/dist/types/channels/control-request-coordinator.d.ts.map +1 -1
  24. package/dist/types/cli/helpers/git-context.d.ts +5 -2
  25. package/dist/types/cli/helpers/git-context.d.ts.map +1 -1
  26. package/dist/types/cron/cron-file.d.ts +2 -3
  27. package/dist/types/cron/cron-file.d.ts.map +1 -1
  28. package/dist/types/cron/process-identity.d.ts +9 -0
  29. package/dist/types/cron/process-identity.d.ts.map +1 -1
  30. package/dist/types/cron/runner.d.ts +2 -2
  31. package/dist/types/cron/runner.d.ts.map +1 -1
  32. package/dist/types/cron/scheduler.d.ts +3 -2
  33. package/dist/types/cron/scheduler.d.ts.map +1 -1
  34. package/dist/types/permissions/checker.d.ts +8 -0
  35. package/dist/types/permissions/checker.d.ts.map +1 -1
  36. package/dist/types/queue/queue-runtime.d.ts +7 -19
  37. package/dist/types/queue/queue-runtime.d.ts.map +1 -1
  38. package/dist/types/tools/impl/shell-launchers.d.ts.map +1 -1
  39. package/dist/types/tools/impl/wake.d.ts +4 -2
  40. package/dist/types/tools/impl/wake.d.ts.map +1 -1
  41. package/dist/types/types/app-server-info.d.ts +0 -2
  42. package/dist/types/types/app-server-info.d.ts.map +1 -1
  43. package/dist/types/types/protocol.d.ts +2 -3
  44. package/dist/types/types/protocol.d.ts.map +1 -1
  45. package/dist/types/types/protocol_v2.d.ts +1 -1
  46. package/dist/types/types/protocol_v2.d.ts.map +1 -1
  47. package/dist/types/types/schedule-protocol.d.ts +2 -2
  48. package/dist/types/types/schedule-protocol.d.ts.map +1 -1
  49. package/dist/types/utils/rename-sync-with-retry.d.ts +3 -0
  50. package/dist/types/utils/rename-sync-with-retry.d.ts.map +1 -0
  51. package/dist/types/websocket/listener/connection.d.ts +2 -0
  52. package/dist/types/websocket/listener/connection.d.ts.map +1 -1
  53. package/dist/types/websocket/listener/constants.d.ts +1 -0
  54. package/dist/types/websocket/listener/constants.d.ts.map +1 -1
  55. package/dist/types/websocket/listener/device-git-context.d.ts.map +1 -1
  56. package/dist/types/websocket/listener/interrupted-turn-record.d.ts.map +1 -1
  57. package/dist/types/websocket/listener/interrupted-turn-storage.d.ts.map +1 -1
  58. package/dist/types/websocket/listener/queue.d.ts +1 -2
  59. package/dist/types/websocket/listener/queue.d.ts.map +1 -1
  60. package/dist/types/websocket/listener/recovery-lineage-sidecar.d.ts.map +1 -1
  61. package/dist/types/websocket/listener/turn-correlation.d.ts +0 -8
  62. package/dist/types/websocket/listener/turn-correlation.d.ts.map +1 -1
  63. package/dist/types/websocket/listener/turn-finished-replay.d.ts.map +1 -1
  64. package/dist/types/websocket/listener/types.d.ts +14 -1
  65. package/dist/types/websocket/listener/types.d.ts.map +1 -1
  66. package/letta.js +876 -614
  67. package/npm-shrinkwrap.json +18 -18
  68. package/package.json +7 -4
  69. package/scripts/build-pypi.py +6 -6
  70. package/scripts/claude-watch/runtime-probe.test.ts +1 -1
  71. package/scripts/claude-watch/runtime-sandbox.ts +1 -1
  72. package/scripts/codex-watch/release-analysis.test.ts +70 -0
  73. package/scripts/codex-watch/release-analysis.ts +5 -5
  74. package/scripts/source-file-size-baseline.json +3 -3
  75. package/skills/maintaining-deferred-memory/SKILL.md +2 -0
  76. package/skills/scheduling-tasks/SKILL.md +1 -1
  77. package/skills/working-across-computers/references/connect-a-computer-for-remote-access.md +2 -2
  78. package/dist/types/websocket/listener/mcp-originator-scope.d.ts +0 -9
  79. package/dist/types/websocket/listener/mcp-originator-scope.d.ts.map +0 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.34.23",
3
+ "version": "0.34.25",
4
4
  "lockfileVersion": 3,
5
5
  "packages": {
6
6
  "node_modules/@alcalzone/ansi-tokenize": {
@@ -3047,9 +3047,9 @@
3047
3047
  }
3048
3048
  },
3049
3049
  "node_modules/es-toolkit": {
3050
- "version": "1.52.0",
3051
- "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.52.0.tgz",
3052
- "integrity": "sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==",
3050
+ "version": "1.53.0",
3051
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.53.0.tgz",
3052
+ "integrity": "sha512-3+AYXp9fmJ/UhHBMYj2/U+RaUouMD90SzoItyDOB2Za7W6dB7fQApFGnZPl2MF6K8/Tv1koh1JyirSx/kju6Pw==",
3053
3053
  "license": "MIT",
3054
3054
  "workspaces": [
3055
3055
  "docs",
@@ -3519,9 +3519,9 @@
3519
3519
  }
3520
3520
  },
3521
3521
  "node_modules/hono": {
3522
- "version": "4.13.13",
3523
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.13.tgz",
3524
- "integrity": "sha512-CQ46U0ZkAGmbT/4UxdzzGJpacP2IeKgY4a5/tOI9AABbpOMfK739wfDXmv1usCk+3RkKj1hQy4/fjhiwa2xlrA==",
3522
+ "version": "4.13.14",
3523
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.14.tgz",
3524
+ "integrity": "sha512-yhRLQ21U6qa9Hsu2N7Qcbh8tE+WKEcoErjIo56LeSGiGXGp9sA7UpE86Ui9uexb61KakiGwuHMn2QdV7w6i6kQ==",
3525
3525
  "license": "MIT",
3526
3526
  "engines": {
3527
3527
  "node": ">=16.9.0"
@@ -3687,9 +3687,9 @@
3687
3687
  }
3688
3688
  },
3689
3689
  "node_modules/ip-address": {
3690
- "version": "10.7.4",
3691
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.4.tgz",
3692
- "integrity": "sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==",
3690
+ "version": "10.7.5",
3691
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.5.tgz",
3692
+ "integrity": "sha512-t2v0rkILYv9WXmSL7TpAaU3HXgaFYOPUcH3QHgwQ++gpJuH3bqyMy4Fvt/DJCTKwzH3Cf+bAp5W/mFL39KPLzA==",
3693
3693
  "license": "MIT",
3694
3694
  "engines": {
3695
3695
  "node": ">= 12"
@@ -5248,14 +5248,14 @@
5248
5248
  }
5249
5249
  },
5250
5250
  "node_modules/unist-util-visit": {
5251
- "version": "5.1.0",
5252
- "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
5253
- "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
5251
+ "version": "5.2.0",
5252
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.2.0.tgz",
5253
+ "integrity": "sha512-fpsYs/VVoZxfGY9/j3FQpZmN8wdLJaV1Pt38AaJNZu9uKIHcFU3halCdBveEq1HGKO1OEfJY65w1zvoFV1b3qQ==",
5254
5254
  "license": "MIT",
5255
5255
  "dependencies": {
5256
5256
  "@types/unist": "^3.0.0",
5257
5257
  "unist-util-is": "^6.0.0",
5258
- "unist-util-visit-parents": "^6.0.0"
5258
+ "unist-util-visit-parents": "^6.1.0"
5259
5259
  },
5260
5260
  "funding": {
5261
5261
  "type": "opencollective",
@@ -5263,9 +5263,9 @@
5263
5263
  }
5264
5264
  },
5265
5265
  "node_modules/unist-util-visit-parents": {
5266
- "version": "6.0.2",
5267
- "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
5268
- "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
5266
+ "version": "6.1.0",
5267
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.1.0.tgz",
5268
+ "integrity": "sha512-vKXxz6O38sKDj1mtx/k2cWvkkFBuYGx6uGrlzBkVeWCRF/F8sdI0j3Wbkz/5rVNRRuVc8UrgRdbCxNhmYXgP3w==",
5269
5269
  "license": "MIT",
5270
5270
  "dependencies": {
5271
5271
  "@types/unist": "^3.0.0",
@@ -5456,7 +5456,7 @@
5456
5456
  },
5457
5457
  "": {
5458
5458
  "name": "@letta-ai/letta-code",
5459
- "version": "0.34.23",
5459
+ "version": "0.34.25",
5460
5460
  "dependencies": {
5461
5461
  "@earendil-works/pi-ai": "^0.99.1",
5462
5462
  "@janhapke/sharp-electron": "0.35.3-electron.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.34.23",
3
+ "version": "0.34.25",
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",
@@ -143,7 +143,7 @@
143
143
  "license": "Apache-2.0",
144
144
  "engines": {
145
145
  "bun": ">=1.3.2",
146
- "node": ">=22.19.0"
146
+ "node": "^22.23.4 || ^24.22.1 || ^26.12.1"
147
147
  },
148
148
  "publishConfig": {
149
149
  "access": "public"
@@ -220,7 +220,7 @@
220
220
  "prepublishOnly": "bun run runtime-graph:verify && bun run build",
221
221
  "postinstall": "node scripts/postinstall-patches.js || echo letta: vendor patches skipped && node -e \"try{require('fs').chmodSync(require('path').join(require.resolve('node-pty/package.json'),'../prebuilds/darwin-arm64/spawn-helper'),0o755)}catch(e){}\" || true",
222
222
  "mod-learning:memory-citations": "bun scripts/mod-learning/learn-mod.ts --env docs/examples/mods/learning/memory-citations.env.json",
223
- "test:built-entrypoints": "LETTA_TEST_CLI_BUNDLE=\"$PWD/letta.js\" LETTA_TEST_BUILT_ARTIFACT=1 bun test src/cli/subcommands/lifecycle-output.test.ts src/websocket/app-server-dream.test.ts --timeout 60000"
223
+ "test:built-entrypoints": "LETTA_TEST_CLI_BUNDLE=\"$PWD/letta.js\" LETTA_TEST_BUILT_ARTIFACT=1 bun test src/subcommand-exit.test.ts src/cli/subcommands/lifecycle-output.test.ts src/websocket/app-server-dream.test.ts --timeout 60000"
224
224
  },
225
225
  "lint-staged": {
226
226
  "*.{ts,tsx,js,jsx,json}": [
@@ -275,5 +275,8 @@
275
275
  },
276
276
  "lettaLifecycleProtocol": 1,
277
277
  "lettaRuntimeGraphProtocol": 1,
278
- "lettaRuntimeGraphSha512": "sha512-xHwgmxBsCCiYY3o9bJl2DPx84chNPq1OsLFGac23DBEoU+h6hGCcX7rZezQxutCYhG/yFzjQ65L3pZ5j6BzNbg=="
278
+ "lettaRuntimeGraphSha512": "sha512-75ArKlsNj6BLjfiYR7ejV9jl0U3L7r1mXtWLYoNBVFkpR+NgT29dy3I6c7xawN3klfWjTCPVa5kpHtS7gVbD0A==",
279
+ "patchedDependencies": {
280
+ "@earendil-works/pi-ai@0.99.1": "patches/@earendil-works%2Fpi-ai@0.99.1.patch"
281
+ }
279
282
  }
@@ -21,33 +21,33 @@ import zipfile
21
21
  from pathlib import Path
22
22
 
23
23
  ROOT = Path(__file__).resolve().parents[1]
24
- NODE = "22.19.0"
24
+ NODE = "22.23.4"
25
25
  # Official nodejs.org SHASUMS256.txt; pin the archive, not only the version.
26
26
  TARGETS = {
27
27
  ("Linux", "x86_64"): (
28
28
  "linux-x64",
29
29
  "manylinux_2_28_x86_64",
30
- "d36e56998220085782c0ca965f9d51b7726335aed2f5fc7321c6c0ad233aa96d",
30
+ "b8492284c76a54baf58d61668dd0e41ee0fc98adabf9503d30f05d08f55b4406",
31
31
  ),
32
32
  ("Linux", "aarch64"): (
33
33
  "linux-arm64",
34
34
  "manylinux_2_28_aarch64",
35
- "d32817b937219b8f131a28546035183d79e7fd17a86e38ccb8772901a7cd9009",
35
+ "f7a1e486dbc8b286847815b477d4fb5e9fb963ed4489c3e1588853d685f589f9",
36
36
  ),
37
37
  ("Darwin", "arm64"): (
38
38
  "darwin-arm64",
39
39
  "macosx_14_0_arm64",
40
- "c59006db713c770d6ec63ae16cb3edc11f49ee093b5c415d667bb4f436c6526d",
40
+ "c9e1dbc748b33ed2d14f42445191ecaf14c56259c7a9a26d0042c49ec2b66428",
41
41
  ),
42
42
  ("Darwin", "x86_64"): (
43
43
  "darwin-x64",
44
44
  "macosx_14_0_x86_64",
45
- "3cfed4795cd97277559763c5f56e711852d2cc2420bda1cea30c8aa9ac77ce0c",
45
+ "efcc2b0db6f94bf53eddb038fe2b370277a042bd29e4f19b8f8e23598795b819",
46
46
  ),
47
47
  ("Windows", "AMD64"): (
48
48
  "win-x64",
49
49
  "win_amd64",
50
- "ea3fad0e67a991d8477d8c01344b56e69c676ccb733f065b22436994b1253f86",
50
+ "cbc74b5e0982c9dbb41525fd8fb5dcd32fbee237863f7829072f4639a1ce5f20",
51
51
  ),
52
52
  }
53
53
 
@@ -140,7 +140,7 @@ describe("command planning", () => {
140
140
  const serialized = sandboxed.args.join(" ");
141
141
  expect(sandboxed.command).toBe("/usr/bin/docker");
142
142
  expect(serialized).toContain("/tmp/probe-root:/watch:rw");
143
- expect(serialized).toContain("node:22.18.0-bookworm@sha256:");
143
+ expect(serialized).toContain("node:22.23.4-bookworm@sha256:");
144
144
  expect(serialized).toContain("--cap-drop ALL");
145
145
  expect(serialized).toContain("--read-only");
146
146
  expect(serialized).toContain("--env ANTHROPIC_API_KEY");
@@ -1,7 +1,7 @@
1
1
  import { spawn } from "node:child_process";
2
2
 
3
3
  const RUNTIME_SANDBOX_IMAGE =
4
- "node:22.18.0-bookworm@sha256:3266bc9e8bee1acc8a77386eefaf574987d2729b8c5ec35b0dbd6ddbc40b0ce2";
4
+ "node:22.23.4-bookworm@sha256:63538dfe497cc29dfafdda25ada09b46db68a3f4cc205abf1f5d6bf0913f3384";
5
5
  const AUTH_ENV_KEYS = ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"] as const;
6
6
 
7
7
  export interface CommandSpec {
@@ -115,6 +115,76 @@ describe("Codex GitHub release fetch", () => {
115
115
  expect(sleeps).toEqual([1000, 2000]);
116
116
  });
117
117
 
118
+ test("retries a disconnected successful response body", async () => {
119
+ const sleeps: number[] = [];
120
+ let requests = 0;
121
+ const releases = await listStableReleases({
122
+ fetchImpl: (async () => {
123
+ requests++;
124
+ if (requests === 1) {
125
+ return new Response(
126
+ new ReadableStream({
127
+ pull(controller) {
128
+ controller.error(new TypeError("fetch failed: ECONNRESET"));
129
+ },
130
+ }),
131
+ { status: 200 },
132
+ );
133
+ }
134
+ return Response.json(STABLES);
135
+ }) as typeof fetch,
136
+ sleep: async (delayMs) => {
137
+ sleeps.push(delayMs);
138
+ },
139
+ });
140
+
141
+ expect(requests).toBe(2);
142
+ expect(sleeps).toEqual([1000]);
143
+ expect(releases).toEqual(STABLES);
144
+ });
145
+
146
+ test("stops retrying disconnected bodies at the existing budget", async () => {
147
+ const sleeps: number[] = [];
148
+ let requests = 0;
149
+ const result = listStableReleases({
150
+ fetchImpl: (async () => {
151
+ requests++;
152
+ return new Response(
153
+ new ReadableStream({
154
+ pull(controller) {
155
+ controller.error(new TypeError("fetch failed: ECONNRESET"));
156
+ },
157
+ }),
158
+ );
159
+ }) as typeof fetch,
160
+ sleep: async (delayMs) => {
161
+ sleeps.push(delayMs);
162
+ },
163
+ });
164
+
165
+ await expect(result).rejects.toThrow("after 3 attempts");
166
+ expect(requests).toBe(3);
167
+ expect(sleeps).toEqual([1000, 2000]);
168
+ });
169
+
170
+ test("does not retry malformed JSON", async () => {
171
+ const sleeps: number[] = [];
172
+ let requests = 0;
173
+ const result = listStableReleases({
174
+ fetchImpl: (async () => {
175
+ requests++;
176
+ return new Response("not JSON");
177
+ }) as typeof fetch,
178
+ sleep: async (delayMs) => {
179
+ sleeps.push(delayMs);
180
+ },
181
+ });
182
+
183
+ await expect(result).rejects.toBeInstanceOf(SyntaxError);
184
+ expect(requests).toBe(1);
185
+ expect(sleeps).toEqual([]);
186
+ });
187
+
118
188
  test("fails immediately on a client error", async () => {
119
189
  const sleeps: number[] = [];
120
190
  let requests = 0;
@@ -190,8 +190,7 @@ export async function listStableReleases(
190
190
 
191
191
  for (let page = 1; page <= 10; page++) {
192
192
  const url = `https://api.github.com/repos/${CODEX_REPO}/releases?per_page=100&page=${page}`;
193
- const res = await fetchGitHubReleasesPage(url, headers, fetchImpl, sleep);
194
- const batch = (await res.json()) as Release[];
193
+ const batch = await fetchGitHubReleasesPage(url, headers, fetchImpl, sleep);
195
194
  releases.push(...batch);
196
195
  if (batch.length < 100) break;
197
196
  }
@@ -205,12 +204,15 @@ async function fetchGitHubReleasesPage(
205
204
  headers: Record<string, string>,
206
205
  fetchImpl: typeof fetch,
207
206
  sleep: (delayMs: number) => Promise<void>,
208
- ): Promise<Response> {
207
+ ): Promise<Release[]> {
209
208
  for (let attempt = 1; ; attempt++) {
210
209
  let response: Response;
211
210
  try {
212
211
  response = await fetchImpl(url, { headers });
212
+ // A successful fetch can still lose its connection while reading the body.
213
+ if (response.ok) return (await response.json()) as Release[];
213
214
  } catch (error) {
215
+ if (error instanceof SyntaxError) throw error;
214
216
  if (attempt === GITHUB_RELEASES_FETCH_ATTEMPTS) {
215
217
  throw new Error(
216
218
  `GitHub releases API request failed after ${attempt} attempts: ${String(error)}`,
@@ -221,8 +223,6 @@ async function fetchGitHubReleasesPage(
221
223
  continue;
222
224
  }
223
225
 
224
- if (response.ok) return response;
225
-
226
226
  const message = `GitHub releases API failed (${response.status}): ${await response.text()}`;
227
227
  if (response.status < 500 || attempt === GITHUB_RELEASES_FETCH_ATTEMPTS) {
228
228
  throw new Error(message);
@@ -2,13 +2,13 @@
2
2
  "src/agent/client-skills.test.ts": 1132,
3
3
  "src/agent/memory-git.ts": 2013,
4
4
  "src/backend/local-backend.test.ts": 2472,
5
- "src/backend/local/local-store.ts": 3261,
5
+ "src/backend/local/local-store.ts": 3260,
6
6
  "src/backend/pi-stream-adapter.test.ts": 1255,
7
7
  "src/cli/app/AppCoordinator.tsx": 5131,
8
8
  "src/cli/app/AppView.tsx": 1732,
9
9
  "src/cli/app/use-approval-flow.ts": 1099,
10
10
  "src/cli/app/use-configuration-handlers.ts": 1417,
11
- "src/cli/app/use-conversation-loop.ts": 2899,
11
+ "src/cli/app/use-conversation-loop.ts": 2878,
12
12
  "src/cli/app/use-submit-handler.ts": 3797,
13
13
  "src/cli/components/AgentSelector.tsx": 1104,
14
14
  "src/cli/components/InputRich.tsx": 2124,
@@ -34,7 +34,7 @@
34
34
  "src/settings-manager.ts": 2092,
35
35
  "src/tools/manager.ts": 2609,
36
36
  "src/tools/tool-execution-context.test.ts": 1092,
37
- "src/types/protocol_v2.ts": 2411,
37
+ "src/types/protocol_v2.ts": 2409,
38
38
  "src/websocket/listen-client-concurrency.test.ts": 2554,
39
39
  "src/websocket/listen-client-protocol.test.ts": 5664,
40
40
  "src/websocket/listener/commands/memory.ts": 1114,
@@ -58,6 +58,8 @@ Discovery runs through the `MEMORY.md` chain, one level at a time:
58
58
 
59
59
  After adding or moving a file, trace the path a future request would take from root `MEMORY.md` to the file. If any step depends on knowing the file already exists, fix the index.
60
60
 
61
+ Indexes are the only way the agent finds deferred memory: it opens a file only when every entry on the path from root names what it is looking for. Keep them accurate as memory changes. Whenever you add, move, or substantially change what a directory holds, reread its entry in each parent `MEMORY.md` up to root and rewrite it to name the topics the directory now covers, in the words a future request would use. An entry written when the directory was new goes stale as it fills, and a topic no entry mentions is effectively lost.
62
+
61
63
  ## Design for progressive disclosure
62
64
 
63
65
  Each level should give the agent enough to decide whether to go deeper, and nothing it would have to read past to decide.
@@ -23,7 +23,7 @@ Execution determines schedule ownership; there is no runner selection flag:
23
23
  - In a managed Cloud sandbox, schedules are durable Cloud schedules and run in the agent's Cloud sandbox.
24
24
  - On a user-managed computer or self-hosted runtime, schedules are local and fire only while a Letta session is running there.
25
25
 
26
- From a managed Cloud sandbox, `--computer <deviceId>` can run the scheduled work on a specific connected computer. Get the device ID from `letta computers list`. If that computer is offline at fire time, execution falls back to the Cloud sandbox. Local execution cannot target another computer.
26
+ From a managed Cloud sandbox, `--computer <deviceId>` can run the scheduled work on a specific connected computer. Get the device ID from `letta computers list`. If that computer is offline at fire time, that occurrence fails (`TARGET_DEVICE_UNAVAILABLE`) and does not run; omit `--computer` to run in the Cloud sandbox. Local execution cannot target another computer.
27
27
 
28
28
  Creation and execution follow those rules, while management commands still show and cancel both local and Cloud inventory. This keeps schedules created by older CLI versions visible without changing where new schedules run.
29
29
 
@@ -18,7 +18,7 @@ curl -sS -X POST "$LETTA_BASE_URL/v1/environments/connect-token" \
18
18
 
19
19
  The response is `{ "deviceCode": "...", "organizationId": "...", "expiresIn": 900 }`. A 403 means this sandbox key does not resolve to an owner; tell the user and fall back to Option 2.
20
20
 
21
- Ask the user to install [Node.js 22.19 or newer](https://nodejs.org/en/download) if they do not have it, then run this **on the computer they want to connect**, filling in both values from the response:
21
+ Ask the user to install [Node.js ^22.23.4, ^24.22.1, or ^26.12.1](https://nodejs.org/en/download) if they do not have it, then run this **on the computer they want to connect**, filling in both values from the response:
22
22
 
23
23
  ```bash
24
24
  npm install -g @letta-ai/letta-code
@@ -31,7 +31,7 @@ The command signs in as the owner. Send it only to that person: a DM, or the thr
31
31
 
32
32
  ## Option 2: CLI server (browser sign-in)
33
33
 
34
- Ask the user to install [Node.js 22.19 or newer](https://nodejs.org/en/download), then run these commands in a terminal **on the target computer**:
34
+ Ask the user to install [Node.js ^22.23.4, ^24.22.1, or ^26.12.1](https://nodejs.org/en/download), then run these commands in a terminal **on the target computer**:
35
35
 
36
36
  ```bash
37
37
  npm install -g @letta-ai/letta-code
@@ -1,9 +0,0 @@
1
- import type { IncomingMessage } from "./types";
2
- export type McpOriginatorScope = {
3
- superRunId: string;
4
- tokenPresent: boolean;
5
- } | null;
6
- export declare function getMcpOriginatorScope(message?: Pick<IncomingMessage, "mcpOriginatorSuperRunId" | "mcpOriginatorTokenPresent">): McpOriginatorScope;
7
- export declare function sameMcpOriginatorScope(a: McpOriginatorScope, b: McpOriginatorScope): boolean;
8
- export declare function getEffectiveMcpOriginatorId(message: Pick<IncomingMessage, "mcpOriginatorSuperRunId" | "mcpOriginatorTokenPresent">): string | undefined;
9
- //# sourceMappingURL=mcp-originator-scope.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mcp-originator-scope.d.ts","sourceRoot":"","sources":["../../../../src/websocket/listener/mcp-originator-scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;CACvB,GAAG,IAAI,CAAC;AAET,wBAAgB,qBAAqB,CACnC,OAAO,CAAC,EAAE,IAAI,CACZ,eAAe,EACf,yBAAyB,GAAG,2BAA2B,CACxD,GACA,kBAAkB,CAOpB;AAED,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,kBAAkB,EACrB,CAAC,EAAE,kBAAkB,GACpB,OAAO,CAIT;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,IAAI,CACX,eAAe,EACf,yBAAyB,GAAG,2BAA2B,CACxD,GACA,MAAM,GAAG,SAAS,CAIpB"}