@letta-ai/letta-code 0.34.36 → 0.34.37

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 (70) hide show
  1. package/dist/app-server-client.cjs +46 -1
  2. package/dist/app-server-client.cjs.map +3 -3
  3. package/dist/app-server-client.js +46 -1
  4. package/dist/app-server-client.js.map +3 -3
  5. package/dist/mcp-client.js +2 -2
  6. package/dist/mcp-client.js.map +1 -1
  7. package/dist/mcp-oauth.js +2 -2
  8. package/dist/mcp-oauth.js.map +1 -1
  9. package/dist/types/agent/memory-git-hooks.d.ts +2 -0
  10. package/dist/types/agent/memory-git-hooks.d.ts.map +1 -1
  11. package/dist/types/agent/subagent-state.d.ts +32 -0
  12. package/dist/types/agent/subagent-state.d.ts.map +1 -1
  13. package/dist/types/app-server-client.d.ts.map +1 -1
  14. package/dist/types/backend/api/environments.d.ts +2 -0
  15. package/dist/types/backend/api/environments.d.ts.map +1 -1
  16. package/dist/types/backend/local/initial-memory.d.ts +1 -0
  17. package/dist/types/backend/local/initial-memory.d.ts.map +1 -1
  18. package/dist/types/cron/runner.d.ts.map +1 -1
  19. package/dist/types/headless-super-run-wait.d.ts +2 -0
  20. package/dist/types/headless-super-run-wait.d.ts.map +1 -1
  21. package/dist/types/queue/queue-runtime.d.ts +2 -0
  22. package/dist/types/queue/queue-runtime.d.ts.map +1 -1
  23. package/dist/types/reminders/disk-space.d.ts +12 -0
  24. package/dist/types/reminders/disk-space.d.ts.map +1 -1
  25. package/dist/types/runtime-context.d.ts +6 -0
  26. package/dist/types/runtime-context.d.ts.map +1 -1
  27. package/dist/types/tools/impl/claude-stream-session.d.ts +18 -1
  28. package/dist/types/tools/impl/claude-stream-session.d.ts.map +1 -1
  29. package/dist/types/tools/impl/codex-app-server-payloads.d.ts +19 -0
  30. package/dist/types/tools/impl/codex-app-server-payloads.d.ts.map +1 -0
  31. package/dist/types/tools/impl/codex-app-server.d.ts +7 -3
  32. package/dist/types/tools/impl/codex-app-server.d.ts.map +1 -1
  33. package/dist/types/tools/impl/external-coding-agent-task.d.ts.map +1 -1
  34. package/dist/types/tools/impl/external-coding-agent.d.ts +26 -1
  35. package/dist/types/tools/impl/external-coding-agent.d.ts.map +1 -1
  36. package/dist/types/tools/impl/external-tool-call.d.ts +2 -0
  37. package/dist/types/tools/impl/external-tool-call.d.ts.map +1 -1
  38. package/dist/types/tools/impl/monitor-timeout.d.ts +13 -1
  39. package/dist/types/tools/impl/monitor-timeout.d.ts.map +1 -1
  40. package/dist/types/tools/impl/native-session-capture.d.ts +1 -0
  41. package/dist/types/tools/impl/native-session-capture.d.ts.map +1 -1
  42. package/dist/types/tools/impl/remote-external-coding-agent.d.ts.map +1 -1
  43. package/dist/types/tools/impl/send-agent-message.d.ts +2 -0
  44. package/dist/types/tools/impl/send-agent-message.d.ts.map +1 -1
  45. package/dist/types/tools/impl/task-transcript.d.ts +33 -0
  46. package/dist/types/tools/impl/task-transcript.d.ts.map +1 -1
  47. package/dist/types/tools/impl/task.d.ts.map +1 -1
  48. package/dist/types/tools/impl/workflow.d.ts.map +1 -1
  49. package/dist/types/tools/tool-definitions.d.ts.map +1 -1
  50. package/dist/types/tools/toolset.d.ts +2 -0
  51. package/dist/types/tools/toolset.d.ts.map +1 -1
  52. package/dist/types/types/protocol_v2.d.ts +5 -1
  53. package/dist/types/types/protocol_v2.d.ts.map +1 -1
  54. package/dist/types/utils/message-queue-bridge.d.ts +2 -0
  55. package/dist/types/utils/message-queue-bridge.d.ts.map +1 -1
  56. package/dist/types/utils/process-liveness.d.ts.map +1 -1
  57. package/dist/types/utils/task-notifications.d.ts +2 -0
  58. package/dist/types/utils/task-notifications.d.ts.map +1 -1
  59. package/dist/types/websocket/listener/protocol-outbound.d.ts +2 -4
  60. package/dist/types/websocket/listener/protocol-outbound.d.ts.map +1 -1
  61. package/dist/types/websocket/listener/queue.d.ts.map +1 -1
  62. package/dist/types/websocket/listener/subagent-state-cache.d.ts +16 -0
  63. package/dist/types/websocket/listener/subagent-state-cache.d.ts.map +1 -0
  64. package/dist/types/websocket/listener/types.d.ts +2 -0
  65. package/dist/types/websocket/listener/types.d.ts.map +1 -1
  66. package/letta.js +1355 -578
  67. package/npm-shrinkwrap.json +14 -14
  68. package/package.json +2 -2
  69. package/scripts/isolated-unit-tests.json +6 -0
  70. package/scripts/source-file-size-baseline.json +1 -2
package/letta.js CHANGED
@@ -6077,7 +6077,7 @@ var package_default;
6077
6077
  var init_package = __esm(() => {
6078
6078
  package_default = {
6079
6079
  name: "@letta-ai/letta-code",
6080
- version: "0.34.36",
6080
+ version: "0.34.37",
6081
6081
  lettaStartupLogProtocol: 1,
6082
6082
  lettaConfigDirProtocol: 1,
6083
6083
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
@@ -6355,7 +6355,7 @@ var init_package = __esm(() => {
6355
6355
  },
6356
6356
  lettaLifecycleProtocol: 1,
6357
6357
  lettaRuntimeGraphProtocol: 1,
6358
- lettaRuntimeGraphSha512: "sha512-tPPjQGBLt5+vA9W+Mv4yvHjYDOzBSNPnlU8rxk0g42xKGYf9HCuWpRA2cR5XvB6ETJFjJmcjMOcHZmQVjiwNuA==",
6358
+ lettaRuntimeGraphSha512: "sha512-WqLO/tmUfIp8hKqBdQE1lQtkR5VxOaoI/Ajy8QoRz3N1f0x2/gRcyGbTKlonrJrkKMNXyKJMWYtqAbudmdmrog==",
6359
6359
  patchedDependencies: {
6360
6360
  "@earendil-works/pi-ai@0.99.1": "patches/@earendil-works%2Fpi-ai@0.99.1.patch"
6361
6361
  }
@@ -97760,7 +97760,10 @@ async function getProcessStartTime(pid) {
97760
97760
  "-NoProfile",
97761
97761
  "-Command",
97762
97762
  `(Get-Process -Id ${pid}).StartTime.ToFileTimeUtc()`
97763
- ]) : await promisify2(execFile)("ps", ["-o", "lstart=", "-p", String(pid)], { env: { ...process.env, TZ: "UTC", LC_ALL: "C" } });
97763
+ ], { timeout: PROCESS_START_LOOKUP_TIMEOUT_MS, windowsHide: true }) : await promisify2(execFile)("ps", ["-o", "lstart=", "-p", String(pid)], {
97764
+ env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
97765
+ timeout: PROCESS_START_LOOKUP_TIMEOUT_MS
97766
+ });
97764
97767
  const started = stdout.trim();
97765
97768
  return started.length > 0 ? started : null;
97766
97769
  } catch {
@@ -97802,7 +97805,7 @@ function isPidReusedByNonLetta(pid, getCommand = getProcessCommand) {
97802
97805
  const argv0 = command.split(/\s+/)[0] ?? "";
97803
97806
  return basename4(argv0) !== basename4(process.execPath);
97804
97807
  }
97805
- var ownStartTime;
97808
+ var PROCESS_START_LOOKUP_TIMEOUT_MS = 5000, ownStartTime;
97806
97809
  var init_process_liveness = () => {};
97807
97810
 
97808
97811
  // src/utils/sleep.ts
@@ -102660,12 +102663,14 @@ function installPreCommitHookWithPolicy(dir, policy) {
102660
102663
  function installPreCommitHook(dir, allowRootMemoryLayout = false) {
102661
102664
  installPreCommitHookWithPolicy(dir, allowRootMemoryLayout ? "root-marker" : "legacy-only");
102662
102665
  }
102663
- function installLocalMemoryPreCommitHook(dir) {
102664
- const hasRootMarker = existsSync5(join9(dir, "MEMORY.md")) || spawnSync("git", ["cat-file", "-e", "HEAD:MEMORY.md"], {
102666
+ function hasRootMemoryMarker(dir) {
102667
+ return existsSync5(join9(dir, "MEMORY.md")) || spawnSync("git", ["cat-file", "-e", "HEAD:MEMORY.md"], {
102665
102668
  cwd: dir,
102666
102669
  stdio: "ignore"
102667
102670
  }).status === 0;
102668
- installPreCommitHookWithPolicy(dir, hasRootMarker ? "root-marker" : "legacy-only");
102671
+ }
102672
+ function installLocalMemoryPreCommitHook(dir) {
102673
+ installPreCommitHookWithPolicy(dir, hasRootMemoryMarker(dir) ? "root-marker" : "legacy-only");
102669
102674
  }
102670
102675
  function installSharedMemoryPreCommitHook(dir) {
102671
102676
  installPreCommitHookWithPolicy(dir, "shared-memory");
@@ -120521,14 +120526,25 @@ __export(exports_personality, {
120521
120526
  applyPersonalityToMemory: () => applyPersonalityToMemory
120522
120527
  });
120523
120528
  import { execFile as execFileCb2 } from "node:child_process";
120524
- import { existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync10 } from "node:fs";
120525
- import { dirname as dirname11, join as join24 } from "node:path";
120529
+ import {
120530
+ existsSync as existsSync17,
120531
+ mkdirSync as mkdirSync11,
120532
+ readdirSync as readdirSync4,
120533
+ readFileSync as readFileSync10,
120534
+ rmdirSync,
120535
+ rmSync as rmSync5,
120536
+ writeFileSync as writeFileSync10
120537
+ } from "node:fs";
120538
+ import { basename as basename6, dirname as dirname11, join as join24 } from "node:path";
120526
120539
  import { promisify as promisify5 } from "node:util";
120527
120540
  function ensureTrailingNewline2(content) {
120528
120541
  return `${content.trimEnd()}
120529
120542
  `;
120530
120543
  }
120531
- function getMemoryFileRelativePathForRepo(repoDir, primaryRelativePath, legacyRelativePath) {
120544
+ function getMemoryFileRelativePathForRepo(repoDir, rootRelativePath, primaryRelativePath, legacyRelativePath) {
120545
+ if (existsSync17(join24(repoDir, rootRelativePath)) || hasRootMemoryMarker(repoDir)) {
120546
+ return rootRelativePath;
120547
+ }
120532
120548
  const primaryPath = join24(repoDir, primaryRelativePath);
120533
120549
  if (existsSync17(primaryPath)) {
120534
120550
  return primaryRelativePath;
@@ -120543,10 +120559,10 @@ function getMemoryFileRelativePathForRepo(repoDir, primaryRelativePath, legacyRe
120543
120559
  return primaryRelativePath;
120544
120560
  }
120545
120561
  function getPersonaRelativePathForRepo(repoDir) {
120546
- return getMemoryFileRelativePathForRepo(repoDir, PRIMARY_PERSONA_RELATIVE_PATH, LEGACY_PERSONA_RELATIVE_PATH);
120562
+ return getMemoryFileRelativePathForRepo(repoDir, ROOT_PERSONA_RELATIVE_PATH, PRIMARY_PERSONA_RELATIVE_PATH, LEGACY_PERSONA_RELATIVE_PATH);
120547
120563
  }
120548
120564
  function getHumanRelativePathForRepo(repoDir) {
120549
- return getMemoryFileRelativePathForRepo(repoDir, PRIMARY_HUMAN_RELATIVE_PATH, LEGACY_HUMAN_RELATIVE_PATH);
120565
+ return getMemoryFileRelativePathForRepo(repoDir, ROOT_HUMAN_RELATIVE_PATH, PRIMARY_HUMAN_RELATIVE_PATH, LEGACY_HUMAN_RELATIVE_PATH);
120550
120566
  }
120551
120567
  async function resolvePersonalityMemoryPromptMode(environment2) {
120552
120568
  if (environment2 === "local")
@@ -120661,22 +120677,64 @@ async function getMemoryCommitAuthor(agentId) {
120661
120677
  authorEmail: `${agentId}@letta.com`
120662
120678
  };
120663
120679
  }
120664
- function applyPersonalityFiles(filesToUpdate) {
120680
+ function buildRootMemoryFile(relativePath, templatePromptAssetName, body, description) {
120681
+ const { frontmatter, body: normalizedBody } = parseMdxFrontmatter(buildDefaultMemoryFile(templatePromptAssetName, body, description));
120682
+ const name = memoryNameFromPath(basename6(relativePath));
120683
+ return `${serializeFrontmatter({
120684
+ name,
120685
+ description: frontmatter.description?.trim() || name
120686
+ })}
120687
+
120688
+ ${ensureTrailingNewline2(normalizedBody.trim())}`;
120689
+ }
120690
+ function applyPersonalityFiles(filesToUpdate, undoLog) {
120665
120691
  const changedPaths = [];
120666
120692
  for (const file of filesToUpdate) {
120667
120693
  const existingContent = existsSync17(file.absolutePath) ? readFileSync10(file.absolutePath, "utf-8") : null;
120694
+ if (file.onlyIfBlank && existingContent !== null && existingContent.replace(FRONTMATTER_REGEX, "").trim()) {
120695
+ continue;
120696
+ }
120668
120697
  const nextContent = existingContent ? replaceBodyPreservingFrontmatter(existingContent, file.content, {
120669
120698
  description: file.description
120670
- }) : buildDefaultMemoryFile(file.templatePromptAssetName, file.content, file.description);
120699
+ }) : file.relativePath.includes("/") ? buildDefaultMemoryFile(file.templatePromptAssetName, file.content, file.description) : buildRootMemoryFile(file.relativePath, file.templatePromptAssetName, file.content, file.description);
120671
120700
  if (existingContent !== null && normalizeComparableContent(existingContent) === normalizeComparableContent(nextContent)) {
120672
120701
  continue;
120673
120702
  }
120703
+ const createdDirs = [];
120704
+ for (let dir = dirname11(file.absolutePath);!existsSync17(dir); dir = dirname11(dir)) {
120705
+ createdDirs.push(dir);
120706
+ }
120707
+ undoLog.push({
120708
+ absolutePath: file.absolutePath,
120709
+ previousContent: existingContent,
120710
+ createdDirs
120711
+ });
120674
120712
  mkdirSync11(dirname11(file.absolutePath), { recursive: true });
120675
120713
  writeFileSync10(file.absolutePath, nextContent, "utf-8");
120676
120714
  changedPaths.push(file.relativePath);
120677
120715
  }
120678
120716
  return changedPaths;
120679
120717
  }
120718
+ async function undoPersonalityFiles(repoDir, undoLog) {
120719
+ if (undoLog.length === 0)
120720
+ return;
120721
+ for (const entry of [...undoLog].reverse()) {
120722
+ try {
120723
+ if (entry.previousContent === null) {
120724
+ rmSync5(entry.absolutePath, { force: true });
120725
+ } else {
120726
+ writeFileSync10(entry.absolutePath, entry.previousContent, "utf-8");
120727
+ }
120728
+ for (const dir of entry.createdDirs) {
120729
+ if (existsSync17(dir) && readdirSync4(dir).length === 0)
120730
+ rmdirSync(dir);
120731
+ }
120732
+ } catch {}
120733
+ }
120734
+ try {
120735
+ await execFile4("git", ["reset", "-q", "--", ...undoLog.map((entry) => entry.absolutePath)], { cwd: repoDir, timeout: 1e4 });
120736
+ } catch {}
120737
+ }
120680
120738
  async function applyPersonalityToMemory(params) {
120681
120739
  const personality = getPersonalityOption(params.personalityId);
120682
120740
  const isLocalMemfs = getBackend().capabilities.localMemfs;
@@ -120709,11 +120767,30 @@ async function applyPersonalityToMemory(params) {
120709
120767
  absolutePath: humanPath,
120710
120768
  templatePromptAssetName: blockDefinitions.human.templatePromptAssetName,
120711
120769
  content: blockDefinitions.human.value,
120712
- description: blockDefinitions.human.description
120770
+ description: blockDefinitions.human.description,
120771
+ onlyIfBlank: true
120713
120772
  }
120714
120773
  ];
120715
- const changedPaths = applyPersonalityFiles(filesToUpdate);
120716
- if (changedPaths.length === 0) {
120774
+ const commitMessage = params.commitMessage ?? `chore(personality): switch to ${personality.label}`;
120775
+ const undoLog = [];
120776
+ let commitResult = null;
120777
+ try {
120778
+ const changedPaths = applyPersonalityFiles(filesToUpdate, undoLog);
120779
+ if (changedPaths.length > 0) {
120780
+ const author = await getMemoryCommitAuthor(params.agentId);
120781
+ commitResult = await commitMemoryWrite({
120782
+ memoryDir: repoDir,
120783
+ pathspecs: changedPaths,
120784
+ reason: commitMessage,
120785
+ author,
120786
+ syncMode: isLocalMemfs ? "local" : "remote"
120787
+ });
120788
+ }
120789
+ } catch (error4) {
120790
+ await undoPersonalityFiles(repoDir, undoLog);
120791
+ throw error4;
120792
+ }
120793
+ if (!commitResult) {
120717
120794
  return {
120718
120795
  changed: false,
120719
120796
  personality,
@@ -120721,16 +120798,8 @@ async function applyPersonalityToMemory(params) {
120721
120798
  humanRelativePath
120722
120799
  };
120723
120800
  }
120724
- const commitMessage = params.commitMessage ?? `chore(personality): switch to ${personality.label}`;
120725
- const author = await getMemoryCommitAuthor(params.agentId);
120726
- const commitResult = await commitMemoryWrite({
120727
- memoryDir: repoDir,
120728
- pathspecs: changedPaths,
120729
- reason: commitMessage,
120730
- author,
120731
- syncMode: isLocalMemfs ? "local" : "remote"
120732
- });
120733
120801
  if (!commitResult.committed) {
120802
+ await undoPersonalityFiles(repoDir, undoLog);
120734
120803
  return {
120735
120804
  changed: false,
120736
120805
  personality,
@@ -120746,14 +120815,16 @@ async function applyPersonalityToMemory(params) {
120746
120815
  commitMessage
120747
120816
  };
120748
120817
  }
120749
- var execFile4, PRIMARY_PERSONA_RELATIVE_PATH = "system/persona.md", LEGACY_PERSONA_RELATIVE_PATH = "memory/system/persona.md", PRIMARY_HUMAN_RELATIVE_PATH = "system/human.md", LEGACY_HUMAN_RELATIVE_PATH = "memory/system/human.md";
120818
+ var execFile4, PRIMARY_PERSONA_RELATIVE_PATH = "system/persona.md", LEGACY_PERSONA_RELATIVE_PATH = "memory/system/persona.md", PRIMARY_HUMAN_RELATIVE_PATH = "system/human.md", LEGACY_HUMAN_RELATIVE_PATH = "memory/system/human.md", ROOT_PERSONA_RELATIVE_PATH = "persona.md", ROOT_HUMAN_RELATIVE_PATH = "human.md";
120750
120819
  var init_personality = __esm(() => {
120751
120820
  init_backend2();
120752
120821
  init_server_url();
120822
+ init_initial_memory();
120753
120823
  init_settings_manager();
120754
120824
  init_memory3();
120755
120825
  init_memory_filesystem2();
120756
120826
  init_memory_git();
120827
+ init_memory_git_hooks();
120757
120828
  init_personality_presets();
120758
120829
  execFile4 = promisify5(execFileCb2);
120759
120830
  });
@@ -147019,12 +147090,12 @@ function mergeObjects(target2, ...sources) {
147019
147090
  });
147020
147091
  return target2;
147021
147092
  }
147022
- function basename6(path8) {
147093
+ function basename7(path8) {
147023
147094
  const idx = ~path8.lastIndexOf("/") || ~path8.lastIndexOf("\\");
147024
147095
  if (idx === 0) {
147025
147096
  return path8;
147026
147097
  } else if (~idx === path8.length - 1) {
147027
- return basename6(path8.substring(0, path8.length - 1));
147098
+ return basename7(path8.substring(0, path8.length - 1));
147028
147099
  } else {
147029
147100
  return path8.substr(~idx + 1);
147030
147101
  }
@@ -148267,7 +148338,7 @@ var CAPTURING_REGEX_SOURCE, RegexSource = class {
148267
148338
  this._contentNameIsCapturing = RegexSource.hasCaptures(this._contentName);
148268
148339
  }
148269
148340
  get debugName() {
148270
- const location = this.$location ? `${basename6(this.$location.filename)}:${this.$location.line}` : "unknown";
148341
+ const location = this.$location ? `${basename7(this.$location.filename)}:${this.$location.line}` : "unknown";
148271
148342
  return `${this.constructor.name}#${this.id} @ ${location}`;
148272
148343
  }
148273
148344
  getName(lineText, captureIndices) {
@@ -156956,16 +157027,16 @@ function clipStyledSpans(spans, maxColumns) {
156956
157027
  return { spans: clipped, clipped: false };
156957
157028
  }
156958
157029
  function languageFromPath(filePath) {
156959
- const basename7 = filePath.split("/").pop() ?? filePath;
156960
- const lower2 = basename7.toLowerCase();
157030
+ const basename8 = filePath.split("/").pop() ?? filePath;
157031
+ const lower2 = basename8.toLowerCase();
156961
157032
  if (lower2 === "makefile")
156962
157033
  return "makefile";
156963
157034
  if (lower2 === "dockerfile")
156964
157035
  return "dockerfile";
156965
- const dotIdx = basename7.lastIndexOf(".");
157036
+ const dotIdx = basename8.lastIndexOf(".");
156966
157037
  if (dotIdx < 0)
156967
157038
  return;
156968
- const ext = basename7.slice(dotIdx + 1).toLowerCase();
157039
+ const ext = basename8.slice(dotIdx + 1).toLowerCase();
156969
157040
  return Object.hasOwn(EXT_TO_LANG, ext) ? EXT_TO_LANG[ext] : undefined;
156970
157041
  }
156971
157042
  function highlightCommand(command) {
@@ -158097,7 +158168,7 @@ var init_paste_registry = __esm(() => {
158097
158168
  import { execFileSync as execFileSync4 } from "node:child_process";
158098
158169
  import { existsSync as existsSync20, readFileSync as readFileSync13, statSync as statSync6, unlinkSync as unlinkSync5 } from "node:fs";
158099
158170
  import { tmpdir as tmpdir6 } from "node:os";
158100
- import { basename as basename7, extname, isAbsolute as isAbsolute5, join as join28, resolve as resolve11 } from "node:path";
158171
+ import { basename as basename8, extname, isAbsolute as isAbsolute5, join as join28, resolve as resolve11 } from "node:path";
158101
158172
  function countLines(text2) {
158102
158173
  return (text2.match(/\r\n|\r|\n/g) || []).length + 1;
158103
158174
  }
@@ -158175,7 +158246,7 @@ function translatePasteForImages(paste) {
158175
158246
  const id2 = allocateImage({
158176
158247
  data: b64,
158177
158248
  mediaType: mt,
158178
- filename: basename7(filePath)
158249
+ filename: basename8(filePath)
158179
158250
  });
158180
158251
  s3 = `[Image #${id2}]`;
158181
158252
  }
@@ -159481,13 +159552,13 @@ import {
159481
159552
  createWriteStream as createWriteStream2,
159482
159553
  existsSync as existsSync21,
159483
159554
  mkdirSync as mkdirSync12,
159484
- readdirSync as readdirSync4,
159555
+ readdirSync as readdirSync5,
159485
159556
  renameSync as renameSync4,
159486
- rmSync as rmSync5,
159557
+ rmSync as rmSync6,
159487
159558
  statSync as statSync7
159488
159559
  } from "node:fs";
159489
159560
  import { arch, homedir as homedir6, platform as platform3 } from "node:os";
159490
- import { basename as basename8, join as join29 } from "node:path";
159561
+ import { basename as basename9, join as join29 } from "node:path";
159491
159562
  import { Readable as Readable2 } from "node:stream";
159492
159563
  import { pipeline as pipeline4 } from "node:stream/promises";
159493
159564
  function toDisplayPath(value) {
@@ -159817,7 +159888,7 @@ function findBinaryRecursively(rootDir, binaryName) {
159817
159888
  const currentDir = stack.pop();
159818
159889
  if (!currentDir)
159819
159890
  continue;
159820
- for (const entry of readdirSync4(currentDir, { withFileTypes: true })) {
159891
+ for (const entry of readdirSync5(currentDir, { withFileTypes: true })) {
159821
159892
  const fullPath = join29(currentDir, entry.name);
159822
159893
  if (entry.isFile() && entry.name === binaryName) {
159823
159894
  return fullPath;
@@ -159860,8 +159931,8 @@ async function downloadFd() {
159860
159931
  chmodSync4(FD_LOCAL_PATH, 493);
159861
159932
  }
159862
159933
  } finally {
159863
- rmSync5(archivePath, { force: true });
159864
- rmSync5(extractDir, { recursive: true, force: true });
159934
+ rmSync6(archivePath, { force: true });
159935
+ rmSync6(extractDir, { recursive: true, force: true });
159865
159936
  }
159866
159937
  return FD_LOCAL_PATH;
159867
159938
  }
@@ -159998,7 +160069,7 @@ class FileAutocompleteProvider {
159998
160069
  return `${toDisplayPath(displayBase)}${normalizedRelativePath}`;
159999
160070
  }
160000
160071
  scoreEntry(filePath, query3, isDirectory) {
160001
- const fileName = basename8(filePath);
160072
+ const fileName = basename9(filePath);
160002
160073
  const lowerFileName = fileName.toLowerCase();
160003
160074
  const lowerQuery = query3.toLowerCase();
160004
160075
  let score = 0;
@@ -160036,7 +160107,7 @@ class FileAutocompleteProvider {
160036
160107
  for (const { path: entryPath, isDirectory } of topEntries) {
160037
160108
  const pathWithoutSlash = isDirectory ? entryPath.slice(0, -1) : entryPath;
160038
160109
  const displayPath = scopedQuery ? this.scopedPathForDisplay(scopedQuery.displayBase, pathWithoutSlash) : pathWithoutSlash;
160039
- const entryName = basename8(pathWithoutSlash);
160110
+ const entryName = basename9(pathWithoutSlash);
160040
160111
  const completionPath = isDirectory ? `${displayPath}/` : displayPath;
160041
160112
  const value = buildCompletionValue(completionPath, {
160042
160113
  isDirectory,
@@ -160186,14 +160257,14 @@ var init_local = __esm(() => {
160186
160257
  });
160187
160258
 
160188
160259
  // src/cli/helpers/local-agent-listing.ts
160189
- import { existsSync as existsSync22, readdirSync as readdirSync5, readFileSync as readFileSync14, statSync as statSync8 } from "node:fs";
160260
+ import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync14, statSync as statSync8 } from "node:fs";
160190
160261
  import { join as join30 } from "node:path";
160191
160262
  function listLocalAgentsFromDisk() {
160192
160263
  const storageDir = getLocalBackendStorageDir();
160193
160264
  const agentsDir = join30(storageDir, "agents");
160194
160265
  if (!existsSync22(agentsDir))
160195
160266
  return [];
160196
- const files = readdirSync5(agentsDir).filter((f4) => f4.endsWith(".json"));
160267
+ const files = readdirSync6(agentsDir).filter((f4) => f4.endsWith(".json"));
160197
160268
  const agents = [];
160198
160269
  for (const file of files) {
160199
160270
  try {
@@ -164766,7 +164837,7 @@ __export(exports_runtime_deps, {
164766
164837
  import { existsSync as existsSync26 } from "node:fs";
164767
164838
  import { mkdir as mkdir4, symlink, writeFile as writeFile5 } from "node:fs/promises";
164768
164839
  import { createRequire as createRequire3 } from "node:module";
164769
- import { basename as basename9, join as join33 } from "node:path";
164840
+ import { basename as basename10, join as join33 } from "node:path";
164770
164841
  import { pathToFileURL } from "node:url";
164771
164842
  function getPackageDisplayName(packageSpec) {
164772
164843
  if (!packageSpec.startsWith("@")) {
@@ -164917,7 +164988,7 @@ async function ensureChannelRuntimeInstalled(channelId) {
164917
164988
  return false;
164918
164989
  }
164919
164990
  const spec = getChannelPluginMetadata(channelId);
164920
- const packageLabels = spec.runtimePackages.map((pkg) => basename9(getPackageDisplayName(pkg)));
164991
+ const packageLabels = spec.runtimePackages.map((pkg) => basename10(getPackageDisplayName(pkg)));
164921
164992
  console.log(`[Channels] Installing ${spec.displayName} runtime dependencies (${packageLabels.join(", ")})...`);
164922
164993
  await installChannelRuntime(channelId);
164923
164994
  console.log(`[Channels] ${spec.displayName} runtime dependencies installed.`);
@@ -166112,9 +166183,9 @@ __export(exports_transcription, {
166112
166183
  isTranscriptionConfigured: () => isTranscriptionConfigured
166113
166184
  });
166114
166185
  import { execFileSync as execFileSync5 } from "node:child_process";
166115
- import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync19, rmSync as rmSync6 } from "node:fs";
166186
+ import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync19, rmSync as rmSync7 } from "node:fs";
166116
166187
  import { tmpdir as tmpdir7 } from "node:os";
166117
- import { basename as basename10, extname as extname2, join as join34 } from "node:path";
166188
+ import { basename as basename11, extname as extname2, join as join34 } from "node:path";
166118
166189
  function audioMimeTypeForPath(localPath) {
166119
166190
  switch (extname2(localPath).toLowerCase()) {
166120
166191
  case ".flac":
@@ -166143,7 +166214,7 @@ function prepareOpenAiTranscriptionFile(localPath) {
166143
166214
  return { localPath };
166144
166215
  }
166145
166216
  const tempDir = mkdtempSync3(join34(tmpdir7(), "letta-transcription-"));
166146
- const convertedPath = join34(tempDir, `${basename10(localPath)}.m4a`);
166217
+ const convertedPath = join34(tempDir, `${basename11(localPath)}.m4a`);
166147
166218
  try {
166148
166219
  execFileSync5("ffmpeg", [
166149
166220
  "-y",
@@ -166157,12 +166228,12 @@ function prepareOpenAiTranscriptionFile(localPath) {
166157
166228
  convertedPath
166158
166229
  ], { stdio: "ignore", timeout: TRANSCRIPTION_TIMEOUT_MS });
166159
166230
  } catch (error4) {
166160
- rmSync6(tempDir, { recursive: true, force: true });
166231
+ rmSync7(tempDir, { recursive: true, force: true });
166161
166232
  throw new Error(`Unsupported audio format ${extname2(localPath).replace(/^\./, "") || "unknown"}; ffmpeg conversion failed. ffmpeg is required to transcribe this audio format; install ffmpeg on the channel listener machine. ${error4 instanceof Error ? error4.message : String(error4)}`);
166162
166233
  }
166163
166234
  return {
166164
166235
  localPath: convertedPath,
166165
- cleanup: () => rmSync6(tempDir, { recursive: true, force: true })
166236
+ cleanup: () => rmSync7(tempDir, { recursive: true, force: true })
166166
166237
  };
166167
166238
  }
166168
166239
  function isTranscriptionConfigured() {
@@ -166180,7 +166251,7 @@ async function transcribeAudioFile(localPath) {
166180
166251
  const prepared = prepareOpenAiTranscriptionFile(localPath);
166181
166252
  try {
166182
166253
  const buffer = readFileSync19(prepared.localPath);
166183
- const filename = basename10(prepared.localPath);
166254
+ const filename = basename11(prepared.localPath);
166184
166255
  const formData = new FormData;
166185
166256
  const blob = new Blob([buffer], {
166186
166257
  type: audioMimeTypeForPath(prepared.localPath)
@@ -166237,7 +166308,7 @@ var init_transcription = __esm(() => {
166237
166308
  // src/channels/telegram/media.ts
166238
166309
  import { randomUUID as randomUUID13 } from "node:crypto";
166239
166310
  import { mkdir as mkdir5, writeFile as writeFile6 } from "node:fs/promises";
166240
- import { basename as basename11, extname as extname3, join as join35 } from "node:path";
166311
+ import { basename as basename12, extname as extname3, join as join35 } from "node:path";
166241
166312
  function normalizeTelegramMimeType(mimeType) {
166242
166313
  const normalized = mimeType?.split(";")[0]?.trim().toLowerCase();
166243
166314
  return normalized || undefined;
@@ -166395,7 +166466,7 @@ function inferUploadMethodFromMimeType(mimeType) {
166395
166466
  return null;
166396
166467
  }
166397
166468
  function detectTelegramUploadMethod(filePath, fileName) {
166398
- const inferredName = (fileName ?? basename11(filePath)).toLowerCase();
166469
+ const inferredName = (fileName ?? basename12(filePath)).toLowerCase();
166399
166470
  const extension = extname3(inferredName);
166400
166471
  const mimeType = inferMimeTypeFromName(inferredName);
166401
166472
  const byMimeType = inferUploadMethodFromMimeType(mimeType);
@@ -166506,7 +166577,7 @@ function buildTelegramFileUrl(token2, filePath) {
166506
166577
  return `https://api.telegram.org/file/bot${token2}/${filePath}`;
166507
166578
  }
166508
166579
  function inferAttachmentFileName(params) {
166509
- const hintedName = params.candidate.name?.trim() || basename11(params.remotePath) || "attachment";
166580
+ const hintedName = params.candidate.name?.trim() || basename12(params.remotePath) || "attachment";
166510
166581
  if (extname3(hintedName)) {
166511
166582
  return hintedName;
166512
166583
  }
@@ -169896,7 +169967,7 @@ var init_attachment_download = __esm(() => {
169896
169967
 
169897
169968
  // src/channels/slack/file-upload.ts
169898
169969
  import { readFile as readFile7 } from "node:fs/promises";
169899
- import { basename as basename12, extname as extname4 } from "node:path";
169970
+ import { basename as basename13, extname as extname4 } from "node:path";
169900
169971
  function resolveUploadMimeType(filePath) {
169901
169972
  switch (extname4(filePath).toLowerCase()) {
169902
169973
  case ".png":
@@ -169923,7 +169994,7 @@ async function uploadSlackFile(slackClient, msg) {
169923
169994
  throw new Error("mediaPath is required for Slack file uploads.");
169924
169995
  }
169925
169996
  const buffer = await readFile7(msg.mediaPath);
169926
- const uploadFileName = msg.fileName ?? basename12(msg.mediaPath);
169997
+ const uploadFileName = msg.fileName ?? basename13(msg.mediaPath);
169927
169998
  const uploadTitle = msg.title ?? uploadFileName;
169928
169999
  const uploadMimeType = resolveUploadMimeType(uploadFileName);
169929
170000
  const uploadUrlResp = await slackClient.files.getUploadURLExternal({
@@ -173198,18 +173269,22 @@ function unescapeXml(str) {
173198
173269
  function resolveNotificationScope(parentScope) {
173199
173270
  const runtime = getRuntimeContext();
173200
173271
  const actingUserId = runtime?.suppressActingUserFallback ? null : runtime?.actingUserId;
173272
+ const clientMessageIds = runtime?.resolveClientMessageIds?.() ?? [];
173273
+ const correlation = clientMessageIds.length > 0 ? { clientMessageIds } : {};
173201
173274
  if (parentScope?.agentId) {
173202
173275
  return {
173203
173276
  agentId: parentScope.agentId,
173204
173277
  conversationId: parentScope.conversationId || "default",
173205
- actingUserId
173278
+ actingUserId,
173279
+ ...correlation
173206
173280
  };
173207
173281
  }
173208
173282
  try {
173209
173283
  return {
173210
173284
  agentId: getCurrentAgentId(),
173211
173285
  conversationId: getConversationId() ?? "default",
173212
- actingUserId
173286
+ actingUserId,
173287
+ ...correlation
173213
173288
  };
173214
173289
  } catch {
173215
173290
  return;
@@ -174664,7 +174739,7 @@ var init_typing_controller2 = __esm(() => {
174664
174739
  });
174665
174740
 
174666
174741
  // src/channels/discord/adapter.ts
174667
- import { basename as basename13 } from "node:path";
174742
+ import { basename as basename14 } from "node:path";
174668
174743
  function createDiscordAdapter(config) {
174669
174744
  let client = null;
174670
174745
  let running = false;
@@ -175210,7 +175285,7 @@ function createDiscordAdapter(config) {
175210
175285
  files: [
175211
175286
  {
175212
175287
  attachment: msg.mediaPath,
175213
- name: msg.fileName ?? basename13(msg.mediaPath)
175288
+ name: msg.fileName ?? basename14(msg.mediaPath)
175214
175289
  }
175215
175290
  ]
175216
175291
  });
@@ -175729,7 +175804,7 @@ var init_attachment_policy = __esm(() => {
175729
175804
  // src/channels/whatsapp/media.ts
175730
175805
  import { randomUUID as randomUUID20 } from "node:crypto";
175731
175806
  import { mkdir as mkdir7, writeFile as writeFile8 } from "node:fs/promises";
175732
- import { basename as basename14, extname as extname6, join as join39 } from "node:path";
175807
+ import { basename as basename15, extname as extname6, join as join39 } from "node:path";
175733
175808
  function unwrapWhatsAppMessageContent(message) {
175734
175809
  if (!message || typeof message !== "object")
175735
175810
  return null;
@@ -175932,7 +176007,7 @@ function buildWhatsAppOutboundPayload(msg, resolvedMedia) {
175932
176007
  return { text: msg.text };
175933
176008
  }
175934
176009
  const mediaPath = resolvedMedia?.mediaPath ?? msg.mediaPath;
175935
- const fileName = resolvedMedia ? basename14(mediaPath) : msg.fileName || basename14(mediaPath);
176010
+ const fileName = resolvedMedia ? basename15(mediaPath) : msg.fileName || basename15(mediaPath);
175936
176011
  const extension = resolvedMedia ? extname6(mediaPath).toLowerCase() : getWhatsAppOutboundMediaExtension(msg);
175937
176012
  const caption = msg.text?.trim() || msg.title?.trim() || undefined;
175938
176013
  if (WHATSAPP_IMAGE_EXTENSIONS.has(extension)) {
@@ -176834,7 +176909,7 @@ var init_state = __esm(() => {
176834
176909
  });
176835
176910
 
176836
176911
  // src/channels/whatsapp/session.ts
176837
- import { mkdirSync as mkdirSync20, readFileSync as readFileSync23, rmSync as rmSync7, writeFileSync as writeFileSync17 } from "node:fs";
176912
+ import { mkdirSync as mkdirSync20, readFileSync as readFileSync23, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "node:fs";
176838
176913
  import { join as join40 } from "node:path";
176839
176914
  function shouldDropLine(line) {
176840
176915
  if (typeof line !== "string")
@@ -176945,7 +177020,7 @@ function acquireWhatsAppSessionLease(accountId, options = {}) {
176945
177020
  if (activeSessionLeases.get(accountId) === lockDir) {
176946
177021
  activeSessionLeases.delete(accountId);
176947
177022
  }
176948
- rmSync7(lockDir, { recursive: true, force: true });
177023
+ rmSync8(lockDir, { recursive: true, force: true });
176949
177024
  }
176950
177025
  };
176951
177026
  } catch (error4) {
@@ -176954,7 +177029,7 @@ function acquireWhatsAppSessionLease(accountId, options = {}) {
176954
177029
  }
176955
177030
  const owner = readLeaseOwner(lockDir);
176956
177031
  if (owner.pid && !isProcessAlive2(owner.pid)) {
176957
- rmSync7(lockDir, { recursive: true, force: true });
177032
+ rmSync8(lockDir, { recursive: true, force: true });
176958
177033
  continue;
176959
177034
  }
176960
177035
  const ownerLabel = owner.pid ? `PID ${owner.pid}${owner.command ? ` (${owner.command})` : ""}` : "an unknown live process";
@@ -178531,14 +178606,14 @@ import { randomUUID as randomUUID24 } from "node:crypto";
178531
178606
  import {
178532
178607
  copyFileSync as copyFileSync2,
178533
178608
  mkdirSync as mkdirSync21,
178534
- readdirSync as readdirSync6,
178609
+ readdirSync as readdirSync7,
178535
178610
  readFileSync as readFileSync24,
178536
178611
  realpathSync as realpathSync5,
178537
178612
  statSync as statSync11
178538
178613
  } from "node:fs";
178539
178614
  import { homedir as homedir9 } from "node:os";
178540
178615
  import {
178541
- basename as basename15,
178616
+ basename as basename16,
178542
178617
  extname as extname7,
178543
178618
  isAbsolute as isAbsolute8,
178544
178619
  join as join42,
@@ -178654,7 +178729,7 @@ function getSignalAttachmentSearchDirs() {
178654
178729
  const dirs = [];
178655
178730
  const localShare = join42(homedir9(), ".local", "share");
178656
178731
  try {
178657
- for (const entry of readdirSync6(localShare, { withFileTypes: true })) {
178732
+ for (const entry of readdirSync7(localShare, { withFileTypes: true })) {
178658
178733
  if (!entry.isDirectory() || !entry.name.startsWith("signal-cli")) {
178659
178734
  continue;
178660
178735
  }
@@ -178757,7 +178832,7 @@ function resolveRecentSignalAttachmentPath(params) {
178757
178832
  for (const baseDir of getSignalAttachmentSearchDirs()) {
178758
178833
  let entries;
178759
178834
  try {
178760
- entries = readdirSync6(baseDir, { withFileTypes: true });
178835
+ entries = readdirSync7(baseDir, { withFileTypes: true });
178761
178836
  } catch {
178762
178837
  continue;
178763
178838
  }
@@ -178797,13 +178872,13 @@ function resolveSignalAttachmentFileName(attachment, sourcePath) {
178797
178872
  if (hintedName && !hintedName.includes("/") && !hintedName.includes("\\")) {
178798
178873
  return hintedName;
178799
178874
  }
178800
- return basename15(sourcePath) || "attachment";
178875
+ return basename16(sourcePath) || "attachment";
178801
178876
  }
178802
178877
  function copySignalAttachment(params) {
178803
178878
  const sourceStat = statSync11(params.sourcePath);
178804
178879
  const sizeBytes = typeof params.attachment.size === "number" && params.attachment.size >= 0 ? params.attachment.size : sourceStat.size;
178805
178880
  if (sizeBytes > params.maxBytes || sourceStat.size > params.maxBytes) {
178806
- console.warn(`[Signal] Skipping attachment ${params.attachment.filename ?? params.attachment.id ?? basename15(params.sourcePath)}: ${Math.max(sizeBytes, sourceStat.size)} bytes exceeds Signal download limit (${params.maxBytes} bytes).`);
178881
+ console.warn(`[Signal] Skipping attachment ${params.attachment.filename ?? params.attachment.id ?? basename16(params.sourcePath)}: ${Math.max(sizeBytes, sourceStat.size)} bytes exceeds Signal download limit (${params.maxBytes} bytes).`);
178807
178882
  return null;
178808
178883
  }
178809
178884
  const fileName = resolveSignalAttachmentFileName(params.attachment, params.sourcePath);
@@ -180319,7 +180394,7 @@ __export(exports_plugin_registry, {
180319
180394
  getChannelDisplayName: () => getChannelDisplayName,
180320
180395
  __testClearUserChannelPluginCache: () => __testClearUserChannelPluginCache
180321
180396
  });
180322
- import { existsSync as existsSync29, readdirSync as readdirSync7, readFileSync as readFileSync25 } from "node:fs";
180397
+ import { existsSync as existsSync29, readdirSync as readdirSync8, readFileSync as readFileSync25 } from "node:fs";
180323
180398
  import { resolve as resolve13, sep as sep3 } from "node:path";
180324
180399
  import { pathToFileURL as pathToFileURL2 } from "node:url";
180325
180400
  function isValidChannelId(value) {
@@ -180415,7 +180490,7 @@ function discoverUserChannelRegistrations() {
180415
180490
  }
180416
180491
  let entries;
180417
180492
  try {
180418
- entries = readdirSync7(channelsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
180493
+ entries = readdirSync8(channelsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
180419
180494
  } catch {
180420
180495
  return registrations;
180421
180496
  }
@@ -193926,7 +194001,7 @@ import {
193926
194001
  mkdirSync as mkdirSync23,
193927
194002
  readFileSync as readFileSync28,
193928
194003
  renameSync as renameSync7,
193929
- rmSync as rmSync8,
194004
+ rmSync as rmSync9,
193930
194005
  statSync as statSync12,
193931
194006
  writeFileSync as writeFileSync19
193932
194007
  } from "node:fs";
@@ -194019,7 +194094,7 @@ function isLockStale(lockDir) {
194019
194094
  }
194020
194095
  function stealLock(lockDir) {
194021
194096
  try {
194022
- rmSync8(lockDir, { recursive: true, force: true });
194097
+ rmSync9(lockDir, { recursive: true, force: true });
194023
194098
  } catch {}
194024
194099
  }
194025
194100
  function acquireLock() {
@@ -194041,7 +194116,7 @@ function acquireLock() {
194041
194116
  try {
194042
194117
  const current = readLockOwner(lockDir);
194043
194118
  if (current && current.token === token2) {
194044
- rmSync8(lockDir, { recursive: true, force: true });
194119
+ rmSync9(lockDir, { recursive: true, force: true });
194045
194120
  }
194046
194121
  } catch {}
194047
194122
  }
@@ -211690,7 +211765,7 @@ var init_mcp_client = __esm(() => {
211690
211765
  init_streamableHttp();
211691
211766
  DEFAULT_CLIENT_INFO = {
211692
211767
  name: "letta-code",
211693
- version: "0.34.36"
211768
+ version: "0.34.37"
211694
211769
  };
211695
211770
  });
211696
211771
 
@@ -213803,7 +213878,7 @@ import {
213803
213878
  linkSync as linkSync2,
213804
213879
  mkdirSync as mkdirSync26,
213805
213880
  readFileSync as readFileSync30,
213806
- rmSync as rmSync9,
213881
+ rmSync as rmSync10,
213807
213882
  writeFileSync as writeFileSync21
213808
213883
  } from "node:fs";
213809
213884
  import { link as link3, mkdir as mkdir8, readFile as readFile8, rm as rm5, writeFile as writeFile9 } from "node:fs/promises";
@@ -213859,7 +213934,7 @@ function createInitializedTokenLinkSync(targetPath, ownerToken) {
213859
213934
  acquisitionError = error5;
213860
213935
  }
213861
213936
  try {
213862
- rmSync9(candidatePath, { force: true });
213937
+ rmSync10(candidatePath, { force: true });
213863
213938
  } catch {}
213864
213939
  return acquisitionError;
213865
213940
  }
@@ -213878,7 +213953,7 @@ async function createInitializedTokenLink(targetPath, ownerToken) {
213878
213953
  function cleanupRecoveryClaimsSync(lockPath, staleToken, deepestClaim) {
213879
213954
  for (let depth = deepestClaim;depth >= 0; depth--) {
213880
213955
  try {
213881
- rmSync9(getRecoveryClaimPath(lockPath, staleToken, depth), {
213956
+ rmSync10(getRecoveryClaimPath(lockPath, staleToken, depth), {
213882
213957
  force: true
213883
213958
  });
213884
213959
  } catch {}
@@ -213924,7 +213999,7 @@ function recoverStaleLockSync(lockPath, staleToken, recoveryOwner) {
213924
213999
  }
213925
214000
  if (readFileSync30(lockPath, "utf-8") !== staleToken)
213926
214001
  return false;
213927
- rmSync9(lockPath, { force: true });
214002
+ rmSync10(lockPath, { force: true });
213928
214003
  return true;
213929
214004
  } catch {
213930
214005
  return false;
@@ -213988,7 +214063,7 @@ function reclaimAbandonedLockSync(lockPath, allowDuringAcquisition = false) {
213988
214063
  abandonedLock = null;
213989
214064
  return false;
213990
214065
  }
213991
- rmSync9(handle2.lockPath, { force: true });
214066
+ rmSync10(handle2.lockPath, { force: true });
213992
214067
  abandonedLock = null;
213993
214068
  return true;
213994
214069
  } catch (error5) {
@@ -214121,7 +214196,7 @@ function releaseRemoteSettingsLockSync(handle2) {
214121
214196
  if (readFileSync30(handle2.lockPath, "utf-8") !== handle2.ownerToken) {
214122
214197
  released = true;
214123
214198
  } else {
214124
- rmSync9(handle2.lockPath, { force: true });
214199
+ rmSync10(handle2.lockPath, { force: true });
214125
214200
  released = true;
214126
214201
  }
214127
214202
  } catch (error5) {
@@ -214182,10 +214257,10 @@ import { randomUUID as randomUUID29 } from "node:crypto";
214182
214257
  import {
214183
214258
  existsSync as existsSync33,
214184
214259
  mkdirSync as mkdirSync27,
214185
- readdirSync as readdirSync8,
214260
+ readdirSync as readdirSync9,
214186
214261
  readFileSync as readFileSync31,
214187
214262
  renameSync as renameSync8,
214188
- rmSync as rmSync10,
214263
+ rmSync as rmSync11,
214189
214264
  writeFileSync as writeFileSync22
214190
214265
  } from "node:fs";
214191
214266
  import { readFile as readFile9, rm as rm6, writeFile as writeFile10 } from "node:fs/promises";
@@ -214255,7 +214330,7 @@ function readCwdRepairJournals(settingsPath) {
214255
214330
  const prefix = getCwdRepairJournalPrefix(settingsPath);
214256
214331
  let names2;
214257
214332
  try {
214258
- names2 = readdirSync8(directory).filter((name) => name.startsWith(prefix) && (name.endsWith(".json") || name.endsWith(".tmp")));
214333
+ names2 = readdirSync9(directory).filter((name) => name.startsWith(prefix) && (name.endsWith(".json") || name.endsWith(".tmp")));
214259
214334
  } catch {
214260
214335
  return [];
214261
214336
  }
@@ -214320,14 +214395,14 @@ function writeCwdRepairJournal(settingsPath, patch2) {
214320
214395
  return null;
214321
214396
  } finally {
214322
214397
  try {
214323
- rmSync10(tempPath, { force: true });
214398
+ rmSync11(tempPath, { force: true });
214324
214399
  } catch {}
214325
214400
  }
214326
214401
  }
214327
214402
  function cleanupCwdRepairJournals(journals) {
214328
214403
  for (const journal of journals) {
214329
214404
  try {
214330
- rmSync10(journal.path, { force: true });
214405
+ rmSync11(journal.path, { force: true });
214331
214406
  } catch {}
214332
214407
  }
214333
214408
  }
@@ -214472,7 +214547,7 @@ function persistRemoteSettingsSync(generation3) {
214472
214547
  return false;
214473
214548
  } finally {
214474
214549
  try {
214475
- rmSync10(tempPath, { force: true });
214550
+ rmSync11(tempPath, { force: true });
214476
214551
  } catch {}
214477
214552
  releaseRemoteSettingsLockSync(lock);
214478
214553
  }
@@ -214827,21 +214902,21 @@ import {
214827
214902
  lstatSync,
214828
214903
  mkdirSync as mkdirSync28,
214829
214904
  openSync as openSync5,
214830
- readdirSync as readdirSync9,
214905
+ readdirSync as readdirSync10,
214831
214906
  readFileSync as readFileSync32,
214832
214907
  readSync as readSync2,
214833
- rmdirSync,
214834
- rmSync as rmSync11,
214908
+ rmdirSync as rmdirSync2,
214909
+ rmSync as rmSync12,
214835
214910
  unlinkSync as unlinkSync8,
214836
214911
  writeFileSync as writeFileSync23
214837
214912
  } from "node:fs";
214838
- import { basename as basename16, dirname as dirname16, join as join44 } from "node:path";
214913
+ import { basename as basename17, dirname as dirname16, join as join44 } from "node:path";
214839
214914
  function installCandidateDirectory(candidatePath, lockPath, hooks) {
214840
214915
  mkdirSync28(lockPath, { mode: 448 });
214841
214916
  const directoryIdentity = pathIdentity(lockPath);
214842
214917
  if (!directoryIdentity)
214843
214918
  return false;
214844
- const names2 = readdirSync9(candidatePath);
214919
+ const names2 = readdirSync10(candidatePath);
214845
214920
  if (names2.length !== 1)
214846
214921
  throw new Error("Invalid durable lock candidate");
214847
214922
  const candidateOwnerPath = join44(candidatePath, names2[0]);
@@ -214856,7 +214931,7 @@ function installCandidateDirectory(candidatePath, lockPath, hooks) {
214856
214931
  return false;
214857
214932
  throw error5;
214858
214933
  }
214859
- const installingNames = readdirSync9(lockPath);
214934
+ const installingNames = readdirSync10(lockPath);
214860
214935
  if (!hasPathIdentity(lockPath, directoryIdentity) || installingNames.length !== 1 || installingNames[0] !== INSTALLING_OWNER_NAME) {
214861
214936
  if (sameFile(candidateOwnerPath, installingOwnerPath)) {
214862
214937
  unlinkSync8(installingOwnerPath);
@@ -214872,7 +214947,7 @@ function installCandidateDirectory(candidatePath, lockPath, hooks) {
214872
214947
  hooks.afterInstallingOwnerUnlink?.(lockPath);
214873
214948
  fsyncDirectory(lockPath);
214874
214949
  unlinkSync8(candidateOwnerPath);
214875
- rmdirSync(candidatePath);
214950
+ rmdirSync2(candidatePath);
214876
214951
  return true;
214877
214952
  }
214878
214953
  function fsyncDirectory(path12, platform5 = process.platform) {
@@ -214957,7 +215032,7 @@ function ownerFileName(owner) {
214957
215032
  return `${owner.pid}-${owner.token}.json`;
214958
215033
  }
214959
215034
  function readOwnerDirectory(lockPath, afterRead) {
214960
- const names2 = readdirSync9(lockPath);
215035
+ const names2 = readdirSync10(lockPath);
214961
215036
  if (names2.length === 0)
214962
215037
  return null;
214963
215038
  if (names2.length > 2) {
@@ -215040,7 +215115,7 @@ function removeDirectoryIfEmpty(path12, parent, expectedIdentity) {
215040
215115
  if (expectedIdentity && !hasPathIdentity(path12, expectedIdentity))
215041
215116
  return false;
215042
215117
  try {
215043
- rmdirSync(path12);
215118
+ rmdirSync2(path12);
215044
215119
  fsyncDirectory(parent);
215045
215120
  return true;
215046
215121
  } catch (error5) {
@@ -215070,8 +215145,8 @@ function removeDeadOwner(lockPath, parent, ownerPath, afterOwnerUnlink) {
215070
215145
  return true;
215071
215146
  }
215072
215147
  function sweepDeadCandidates(lockPath, parent, isOwnerAlive, ignoredPath) {
215073
- const prefix = `${basename16(lockPath)}.candidate-`;
215074
- const allCandidates = readdirSync9(parent, { withFileTypes: true }).filter((entry) => entry.name.startsWith(prefix) && entry.isDirectory());
215148
+ const prefix = `${basename17(lockPath)}.candidate-`;
215149
+ const allCandidates = readdirSync10(parent, { withFileTypes: true }).filter((entry) => entry.name.startsWith(prefix) && entry.isDirectory());
215075
215150
  let hasUnresolvedCandidate = allCandidates.length > MAX_CANDIDATE_SWEEP;
215076
215151
  const candidates2 = allCandidates.slice(0, MAX_CANDIDATE_SWEEP);
215077
215152
  for (const entry of candidates2) {
@@ -215100,7 +215175,7 @@ function sweepDeadCandidates(lockPath, parent, isOwnerAlive, ignoredPath) {
215100
215175
  hasUnresolvedCandidate = true;
215101
215176
  continue;
215102
215177
  }
215103
- rmSync11(candidatePath, { recursive: true, force: true });
215178
+ rmSync12(candidatePath, { recursive: true, force: true });
215104
215179
  fsyncDirectory(parent);
215105
215180
  continue;
215106
215181
  }
@@ -215119,7 +215194,7 @@ function sweepDeadCandidates(lockPath, parent, isOwnerAlive, ignoredPath) {
215119
215194
  hasUnresolvedCandidate = true;
215120
215195
  continue;
215121
215196
  }
215122
- rmSync11(candidatePath, { recursive: true, force: true });
215197
+ rmSync12(candidatePath, { recursive: true, force: true });
215123
215198
  fsyncDirectory(parent);
215124
215199
  continue;
215125
215200
  }
@@ -215157,7 +215232,7 @@ function prepareCandidate(lockPath, parent, owner) {
215157
215232
  return candidatePath;
215158
215233
  } catch (error5) {
215159
215234
  try {
215160
- rmSync11(candidatePath, { recursive: true, force: true });
215235
+ rmSync12(candidatePath, { recursive: true, force: true });
215161
215236
  fsyncDirectory(parent);
215162
215237
  } catch {}
215163
215238
  throw error5;
@@ -215322,7 +215397,7 @@ function acquireDurableFileLock(path12, options = {}) {
215322
215397
  removeDeadOwner(lockPath, parent, join44(lockPath, ownerFileName(owner)));
215323
215398
  } catch {}
215324
215399
  try {
215325
- rmSync11(candidatePath, { recursive: true, force: true });
215400
+ rmSync12(candidatePath, { recursive: true, force: true });
215326
215401
  fsyncDirectory(parent);
215327
215402
  } catch {}
215328
215403
  throw error5;
@@ -215356,7 +215431,7 @@ var init_durable_file_lock = __esm(() => {
215356
215431
  });
215357
215432
 
215358
215433
  // src/websocket/listener/interrupted-turn-input-ownership.ts
215359
- import { readdirSync as readdirSync10 } from "node:fs";
215434
+ import { readdirSync as readdirSync11 } from "node:fs";
215360
215435
  import { join as join45 } from "node:path";
215361
215436
  function decodeMainFilenameScopes(file) {
215362
215437
  if (!file.endsWith(".json"))
@@ -215378,7 +215453,7 @@ function listInterruptedTurnMainSnapshot(directory, readRecord) {
215378
215453
  try {
215379
215454
  const records = [];
215380
215455
  const unreadableScopes = new Map;
215381
- for (const file of readdirSync10(directory).filter((entry) => entry.endsWith(".json"))) {
215456
+ for (const file of readdirSync11(directory).filter((entry) => entry.endsWith(".json"))) {
215382
215457
  const record6 = readRecord(join45(directory, file));
215383
215458
  if (record6) {
215384
215459
  records.push(record6);
@@ -215854,7 +215929,7 @@ Do not use this tool for root memory files (already loaded) or skills/ (use Skil
215854
215929
  var init_Memory = () => {};
215855
215930
 
215856
215931
  // src/tools/descriptions/Monitor.md
215857
- var Monitor_default = 'Start a background monitor that streams events from a long-running script. Each stdout line is an event — you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you\'re waiting for the user to answer a question.\n\nPick by how many notifications you need:\n- **One** ("tell me when the server is ready / the build finishes") → use **Bash with `run_in_background`** and a command that exits when the condition is true, e.g. `until grep -q "Ready in" dev.log; do sleep 0.5; done`. You get a single completion notification when it exits.\n- **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") → Monitor with an unbounded command (`tail -f`, `inotifywait -m`, `while true`).\n- **One per occurrence, until a known end** ("emit each CI step result, stop when the run completes") → Monitor with a command that emits lines and then exits.\n\nYour script\'s stdout is the event stream. Each line becomes a notification. Exit ends the watch.\n # Each matching log line is an event\n tail -f /var/log/app.log | grep --line-buffered "ERROR"\n # Each file change is an event\n inotifywait -m --format \'%e %f\' /watched/dir\n # Node script that emits events as they arrive (e.g. WebSocket listener)\n node watch-for-events.js\n\nFor open github.com pull requests, use WatchPR instead. It covers the whole PR surface and keeps watching after CI finishes. Use Monitor only when WatchPR does not apply.\n\n**Don\'t use an unbounded command for a single notification.** `tail -f`, `inotifywait -m`, and `while true` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For "tell me when X is ready," use Bash `run_in_background` with an `until` loop instead (one notification, ends in seconds). Note that `tail -f log | grep -m 1 ...` does *not* fix this: if the log goes quiet after the match, `tail` never receives SIGPIPE and the pipeline hangs anyway.\n\n- Every pipe stage must flush per line or matches sit in its buffer unseen: `grep` needs `--line-buffered`, `awk` needs `fflush()`. `head` cannot flush at all — `| head -N` delivers nothing until N matches accumulate, then ends the stream.\n- In poll loops, handle transient failures (`curl ... || true`) — one failed request shouldn\'t kill the monitor.\n- Poll intervals: 30s+ for remote APIs (rate limits), 0.5–1s for local checks.\n- Write a specific `description` — it appears in every notification ("errors in deploy.log" not "watching logs").\n- Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications — for a command you run directly (e.g. `python train.py 2>&1 | grep --line-buffered ...`), merge stderr with `2>&1` so its failures reach your filter. (No effect on `tail -f` of an existing log — that file only contains what its writer redirected.)\n\n**Coverage — silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit — and silence looks identical to "still running." Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.\n # Wrong — silent on crash, hang, or any non-success exit\n tail -f run.log | grep --line-buffered "elapsed_steps="\n # Right — one alternation covering progress + the failure signatures you\'d act on\n tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"\n\nFor poll loops checking job state, emit on every terminal status (`succeeded|failed|cancelled|timeout`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it — some extra noise is better than missing a crashloop.\n\n**Output volume**: Every stdout line is a conversation message, so the filter should be selective — but selective means "the lines you\'d act on," not "only good news." Never pipe raw logs; filter to exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.\n\nStdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.\n\nThe script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout → killed. Set `persistent: true` for session-length watches (log tails, long-lived event streams). In managed Cloud sandboxes, every monitor stops at the per-sandbox cap configured by LETTA_MONITOR_MAX_TIMEOUT_MS (default 1 hour, clamped to 1 hour through 7 days), including persistent monitors; elsewhere persistent monitors run until TaskStop or session end. Call Monitor again to re-arm it if you still need to watch. For much longer Cloud waits, schedule a Wake or cron (which does not keep the sandbox running between turns) and combine it with shorter monitors. Use TaskStop to cancel early.\n\nWhen someone is waiting on the result, set `backup_after_seconds` (e.g. 900). If the monitor goes that long without an event, a durable Wake brings you back to check the real state, so a queued, hung, or dead watch can\'t leave them waiting in silence.\n\n**ws source** — open a WebSocket and stream each incoming text frame as an event. No shell, no polling: the server pushes, you get notified.\n ws: {url: \'wss://events.example.com/stream\', protocols: [\'v1\']},\n description: \'deploy events\',\n\nEach text frame becomes one notification (multiline frames stay as one event). Binary frames are reported as `[binary frame, N bytes]` rather than passed through. Socket close ends the watch with the close code surfaced; errors are surfaced before close. Same rate limiting as bash — a firehose will be suppressed and eventually stopped, so subscribe to a filtered feed where one exists.\n\nPrefer this over `command: \'websocat wss://…\'` — it avoids the extra process and line-buffering pitfalls. Use bash when you need to transform or filter frames with shell tools before they become events.\n\n**script source** — a JavaScript watch loop with the same globals as CodeMode (including `decide()`), plus `emit(text)` (one event) and `sleep(ms)`. Tool calls and `decide()` share one rate limit; `decide()` spends money on every call, so call it only when an observed change needs judgment, not on every poll. Returning or throwing ends the watch.\n';
215932
+ var Monitor_default = 'Start a background monitor that streams events from a long-running script. Each stdout line is an event — you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you\'re waiting for the user to answer a question.\n\nPick by how many notifications you need:\n- **One** ("tell me when the server is ready / the build finishes") → use **Bash with `run_in_background`** and a command that exits when the condition is true, e.g. `until grep -q "Ready in" dev.log; do sleep 0.5; done`. You get a single completion notification when it exits.\n- **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") → Monitor with an unbounded command (`tail -f`, `inotifywait -m`, `while true`).\n- **One per occurrence, until a known end** ("emit each CI step result, stop when the run completes") → Monitor with a command that emits lines and then exits.\n\nYour script\'s stdout is the event stream. Each line becomes a notification. Exit ends the watch.\n # Each matching log line is an event\n tail -f /var/log/app.log | grep --line-buffered "ERROR"\n # Each file change is an event\n inotifywait -m --format \'%e %f\' /watched/dir\n # Node script that emits events as they arrive (e.g. WebSocket listener)\n node watch-for-events.js\n\nFor open github.com pull requests, use WatchPR instead. It covers the whole PR surface and keeps watching after CI finishes. Use Monitor only when WatchPR does not apply.\n\n**Don\'t use an unbounded command for a single notification.** `tail -f`, `inotifywait -m`, and `while true` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For "tell me when X is ready," use Bash `run_in_background` with an `until` loop instead (one notification, ends in seconds). Note that `tail -f log | grep -m 1 ...` does *not* fix this: if the log goes quiet after the match, `tail` never receives SIGPIPE and the pipeline hangs anyway.\n\n- Every pipe stage must flush per line or matches sit in its buffer unseen: `grep` needs `--line-buffered`, `awk` needs `fflush()`. `head` cannot flush at all — `| head -N` delivers nothing until N matches accumulate, then ends the stream.\n- In poll loops, handle transient failures (`curl ... || true`) — one failed request shouldn\'t kill the monitor.\n- Poll intervals: 30s+ for remote APIs (rate limits), 0.5–1s for local checks.\n- Write a specific `description` — it appears in every notification ("errors in deploy.log" not "watching logs").\n- Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications — for a command you run directly (e.g. `python train.py 2>&1 | grep --line-buffered ...`), merge stderr with `2>&1` so its failures reach your filter. (No effect on `tail -f` of an existing log — that file only contains what its writer redirected.)\n\n**Coverage — silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit — and silence looks identical to "still running." Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.\n # Wrong — silent on crash, hang, or any non-success exit\n tail -f run.log | grep --line-buffered "elapsed_steps="\n # Right — one alternation covering progress + the failure signatures you\'d act on\n tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"\n\nFor poll loops checking job state, emit on every terminal status (`succeeded|failed|cancelled|timeout`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it — some extra noise is better than missing a crashloop.\n\n**Output volume**: Every stdout line is a conversation message, so the filter should be selective — but selective means "the lines you\'d act on," not "only good news." Never pipe raw logs; filter to exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.\n\nStdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.\n\nThe script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout → killed. Set `persistent: true` for session-length watches (log tails, long-lived event streams). In managed Cloud sandboxes, every monitor, including persistent ones, stops after {{MONITOR_MAX_TIMEOUT}} (this sandbox\'s monitor cap); elsewhere persistent monitors run until TaskStop or session end. Call Monitor again to re-arm it if you still need to watch. For much longer Cloud waits, schedule a Wake or cron (which does not keep the sandbox running between turns) and combine it with shorter monitors. Use TaskStop to cancel early.\n\nWhen someone is waiting on the result, set `backup_after_seconds` (e.g. 900). If the monitor goes that long without an event, a durable Wake brings you back to check the real state, so a queued, hung, or dead watch can\'t leave them waiting in silence.\n\n**ws source** — open a WebSocket and stream each incoming text frame as an event. No shell, no polling: the server pushes, you get notified.\n ws: {url: \'wss://events.example.com/stream\', protocols: [\'v1\']},\n description: \'deploy events\',\n\nEach text frame becomes one notification (multiline frames stay as one event). Binary frames are reported as `[binary frame, N bytes]` rather than passed through. Socket close ends the watch with the close code surfaced; errors are surfaced before close. Same rate limiting as bash — a firehose will be suppressed and eventually stopped, so subscribe to a filtered feed where one exists.\n\nPrefer this over `command: \'websocat wss://…\'` — it avoids the extra process and line-buffering pitfalls. Use bash when you need to transform or filter frames with shell tools before they become events.\n\n**script source** — a JavaScript watch loop with the same globals as CodeMode (including `decide()`), plus `emit(text)` (one event) and `sleep(ms)`. Tool calls and `decide()` share one rate limit; `decide()` spends money on every call, so call it only when an observed change needs judgment, not on every poll. Returning or throwing ends the watch.\n';
215858
215933
  var init_Monitor = () => {};
215859
215934
 
215860
215935
  // src/tools/descriptions/Read.md
@@ -216370,13 +216445,13 @@ var ViewImage_default = `View a local image file from the filesystem when visual
216370
216445
  var init_ViewImage = () => {};
216371
216446
 
216372
216447
  // src/tools/descriptions/Wake.md
216373
- var Wake_default = "Schedule a future turn for the current conversation. Wake is the durable, time-based counterpart to Monitor: use Monitor when ongoing work can emit an event, and Wake when you need to act at a future time even if nothing emits one.\n\nWake is always self-bound. It cannot target another agent, conversation, or computer.\n\n- `create`: provide `name`, `prompt`, and exactly one of `after_seconds`, `scheduled_at`, or `cron`.\n- `list`: list active and paused wakes for this conversation.\n- `cancel`: provide the `id` returned by create or list.\n\nUse `after_seconds` for ordinary follow-ups such as checking again in five minutes. `scheduled_at` must be RFC 3339 with `Z` or an explicit UTC offset. `cron` is a recurring five-field UTC expression and cannot run more often than hourly.\n\nFor calendar requests such as “tomorrow at 9am,” resolve the date in the user's timezone and pass `scheduled_at` with an explicit offset. Infer a reasonable timezone from available context instead of asking a redundant follow-up. State the timezone you used in the confirmation (for example, “Scheduled for 9:00 AM PT”) so the user can correct the assumption.\n\nWakes created in a managed Cloud sandbox survive sandbox shutdown. Wakes created on a user-managed computer or self-hosted runtime use its local scheduler and only fire while a listener is active. List and cancel include both local and Cloud wakes already bound to this conversation, so older wakes remain manageable. The create result warns when no listener currently owns local schedules.\n\nFor advanced scheduling, load the `scheduling-tasks` skill and use `letta cron`. The CLI can target fresh, default, or other conversations and, from managed Cloud, connected computers; it can also inspect run history and manage schedules outside the current conversation.\n";
216448
+ var Wake_default = "Schedule a future turn for the current conversation. Wake is the durable, time-based counterpart to Monitor: use Monitor when ongoing work can emit an event, and Wake when you need to act at a future time even if nothing emits one.\n\nWake is always self-bound. It cannot target another agent, conversation, or computer.\n\n- `create`: provide `name`, `prompt`, and exactly one of `after_seconds`, `scheduled_at`, or `cron`.\n- `list`: list active and paused wakes for this conversation.\n- `cancel`: provide the `id` returned by create or list.\n\nWrite `prompt` as a note to your future self, not a script: what you are waiting on, what you planned and why, and what to check before acting. When the wake fires, the situation or people's wishes may have changed since you wrote it.\n\nUse `after_seconds` for ordinary follow-ups such as checking again in five minutes. `scheduled_at` must be RFC 3339 with `Z` or an explicit UTC offset. `cron` is a recurring five-field UTC expression and cannot run more often than hourly.\n\nFor calendar requests such as “tomorrow at 9am,” resolve the date in the user's timezone and pass `scheduled_at` with an explicit offset. Infer a reasonable timezone from available context instead of asking a redundant follow-up. State the timezone you used in the confirmation (for example, “Scheduled for 9:00 AM PT”) so the user can correct the assumption.\n\nWakes created in a managed Cloud sandbox survive sandbox shutdown. Wakes created on a user-managed computer or self-hosted runtime use its local scheduler and only fire while a listener is active. List and cancel include both local and Cloud wakes already bound to this conversation, so older wakes remain manageable. The create result warns when no listener currently owns local schedules.\n\nFor advanced scheduling, load the `scheduling-tasks` skill and use `letta cron`. The CLI can target fresh, default, or other conversations and, from managed Cloud, connected computers; it can also inspect run history and manage schedules outside the current conversation.\n";
216374
216449
  var init_Wake = () => {};
216375
216450
 
216376
216451
  // src/tools/descriptions/WatchPR.md
216377
216452
  var WatchPR_default = `Watch one open github.com pull request until it merges, closes, is stopped with TaskStop, or the session ends.
216378
216453
 
216379
- In managed Cloud sandboxes, WatchPR also stops after the per-sandbox cap configured by LETTA_MONITOR_MAX_TIMEOUT_MS (default 1 hour, clamped to 1 hour through 7 days) and sends a timeout notification. Call WatchPR again to re-arm it if you still need to watch. For much longer waits, use Wake or cron (which does not keep the sandbox running between turns) and combine it with shorter watches. Local watches have no duration limit.
216454
+ In managed Cloud sandboxes, WatchPR also stops after {{MONITOR_MAX_TIMEOUT}} (this sandbox's monitor cap) and sends a timeout notification. Call WatchPR again to re-arm it if you still need to watch. For much longer waits, use Wake or cron (which does not keep the sandbox running between turns) and combine it with shorter watches. Local watches have no duration limit.
216380
216455
 
216381
216456
  Use WatchPR instead of writing a Monitor or shell polling loop when you need ongoing notifications about a PR. Start at most one watch per PR. It reports:
216382
216457
 
@@ -217845,8 +217920,8 @@ function isGitExecutable(command) {
217845
217920
  }
217846
217921
  function isShellExecutable(command) {
217847
217922
  const normalized = command.replace(/\\/g, "/").toLowerCase();
217848
- const basename17 = path13.basename(normalized);
217849
- return basename17 === "bash" || basename17 === "sh" || basename17 === "zsh" || basename17 === "ash" || basename17 === "cmd.exe" || basename17.includes("powershell") || basename17.includes("pwsh");
217923
+ const basename18 = path13.basename(normalized);
217924
+ return basename18 === "bash" || basename18 === "sh" || basename18 === "zsh" || basename18 === "ash" || basename18 === "cmd.exe" || basename18.includes("powershell") || basename18.includes("pwsh");
217850
217925
  }
217851
217926
  function extractShellCommandArgument(launcher, startIndex) {
217852
217927
  const argIndex = launcher.findIndex((token2, index) => {
@@ -218220,9 +218295,9 @@ import {
218220
218295
  createWriteStream as createWriteStream3,
218221
218296
  existsSync as existsSync34,
218222
218297
  mkdirSync as mkdirSync29,
218223
- readdirSync as readdirSync11,
218298
+ readdirSync as readdirSync12,
218224
218299
  renameSync as renameSync9,
218225
- rmSync as rmSync12
218300
+ rmSync as rmSync13
218226
218301
  } from "node:fs";
218227
218302
  import { createRequire as createRequire4 } from "node:module";
218228
218303
  import { arch as arch3, platform as platform5 } from "node:os";
@@ -218309,7 +218384,7 @@ function findBinaryRecursively2(rootDir, binaryFileName) {
218309
218384
  const currentDir = stack.pop();
218310
218385
  if (!currentDir)
218311
218386
  continue;
218312
- const entries = readdirSync11(currentDir, { withFileTypes: true });
218387
+ const entries = readdirSync12(currentDir, { withFileTypes: true });
218313
218388
  for (const entry of entries) {
218314
218389
  const fullPath = join47(currentDir, entry.name);
218315
218390
  if (entry.isFile() && entry.name === binaryFileName) {
@@ -218456,8 +218531,8 @@ async function downloadRipgrep() {
218456
218531
  chmodSync8(binaryPath, 493);
218457
218532
  }
218458
218533
  } finally {
218459
- rmSync12(archivePath, { force: true });
218460
- rmSync12(extractDir, { recursive: true, force: true });
218534
+ rmSync13(archivePath, { force: true });
218535
+ rmSync13(extractDir, { recursive: true, force: true });
218461
218536
  }
218462
218537
  if (!commandWorks(binaryPath)) {
218463
218538
  throw new Error(`${config2.name} installed to ${binaryPath} but failed --version validation`);
@@ -219044,8 +219119,8 @@ function hasPathSeparator(executable) {
219044
219119
  return executable.includes("/") || executable.includes("\\");
219045
219120
  }
219046
219121
  function hasFileExtension(executable) {
219047
- const basename18 = executable.split(/[\\/]/).pop() ?? executable;
219048
- return /\.[^.]+$/.test(basename18);
219122
+ const basename19 = executable.split(/[\\/]/).pop() ?? executable;
219123
+ return /\.[^.]+$/.test(basename19);
219049
219124
  }
219050
219125
  function shellCandidateExists(candidate) {
219051
219126
  try {
@@ -220446,7 +220521,7 @@ var init_availability = __esm(() => {
220446
220521
 
220447
220522
  // src/permissions/memory-paths.ts
220448
220523
  import { homedir as homedir10 } from "node:os";
220449
- import { basename as basename18, dirname as dirname21, isAbsolute as isAbsolute14, resolve as resolve17 } from "node:path";
220524
+ import { basename as basename19, dirname as dirname21, isAbsolute as isAbsolute14, resolve as resolve17 } from "node:path";
220450
220525
  function normalizeMemoryPath(path16) {
220451
220526
  const resolvedPath = resolve17(expandHomePath(path16));
220452
220527
  const normalized = resolvedPath.replace(/\\/g, "/");
@@ -220491,7 +220566,7 @@ function addRootAndSiblingWorktree(root2, acc) {
220491
220566
  return;
220492
220567
  }
220493
220568
  acc.add(normalizedRoot);
220494
- const leaf = basename18(normalizedRoot);
220569
+ const leaf = basename19(normalizedRoot);
220495
220570
  if (leaf === "memory") {
220496
220571
  acc.add(normalizeMemoryPath(resolve17(dirname21(normalizedRoot), "memory-worktrees")));
220497
220572
  }
@@ -220574,7 +220649,7 @@ var init_memory_paths = __esm(() => {
220574
220649
  // src/permissions/sandbox-policy.ts
220575
220650
  import { existsSync as existsSync37, realpathSync as realpathSync6 } from "node:fs";
220576
220651
  import { homedir as homedir11 } from "node:os";
220577
- import { basename as basename19, dirname as dirname22, isAbsolute as isAbsolute15, join as join51, resolve as resolve18 } from "node:path";
220652
+ import { basename as basename20, dirname as dirname22, isAbsolute as isAbsolute15, join as join51, resolve as resolve18 } from "node:path";
220578
220653
  function getCrossBackendAgentsTreeRoots(options = {}) {
220579
220654
  const homeDir = options.homeDir;
220580
220655
  const env6 = options.env ?? process.env;
@@ -220603,7 +220678,7 @@ function canonicalizeRoot(input) {
220603
220678
  let dir = abs;
220604
220679
  const tail2 = [];
220605
220680
  while (!existsSync37(dir)) {
220606
- tail2.unshift(basename19(dir));
220681
+ tail2.unshift(basename20(dir));
220607
220682
  const parent = dirname22(dir);
220608
220683
  if (parent === dir) {
220609
220684
  return normalizeSandboxPath(abs);
@@ -220637,8 +220712,8 @@ function deriveSelfAgentRootsForTrees(memoryRoots, agentsTreeRoots = getCrossBac
220637
220712
  const canon = canonicalizeRoot(root2);
220638
220713
  const containingTree = canonicalTrees.find((tree) => canon !== tree && isWithinRoot(canon, tree));
220639
220714
  if (containingTree) {
220640
- const leaf = basename19(canon);
220641
- const parentLeaf = basename19(dirname22(canon));
220715
+ const leaf = basename20(canon);
220716
+ const parentLeaf = basename20(dirname22(canon));
220642
220717
  out.add(leaf === "memory" || leaf === "memory-worktrees" ? dirname22(canon) : parentLeaf === "memory-worktrees" || parentLeaf === "memory" && leaf === ".git" ? dirname22(dirname22(canon)) : canon);
220643
220718
  continue;
220644
220719
  }
@@ -221855,8 +221930,8 @@ function resolveRemovalTarget(rawTarget, cwd2, env6) {
221855
221930
  let target2 = expandEnvironment(rawTarget, env6).replace(/[),]+$/g, "").replace(/(?<=[\\/:])\$(?:env:)?[A-Za-z_][A-Za-z0-9_]*/gi, "").replaceAll("/", "\\");
221856
221931
  if (!target2 || target2 === "*")
221857
221932
  return null;
221858
- const basename20 = win323.basename(target2);
221859
- if (basename20.includes("*") || basename20.includes("?")) {
221933
+ const basename21 = win323.basename(target2);
221934
+ if (basename21.includes("*") || basename21.includes("?")) {
221860
221935
  target2 = win323.dirname(target2);
221861
221936
  }
221862
221937
  return win323.normalize(win323.resolve(cwd2, target2));
@@ -221939,7 +222014,7 @@ __export(exports_bash, {
221939
222014
  bash: () => bash,
221940
222015
  __setShellProcessStarterForTests: () => __setShellProcessStarterForTests
221941
222016
  });
221942
- import { rmSync as rmSync13 } from "node:fs";
222017
+ import { rmSync as rmSync14 } from "node:fs";
221943
222018
  function __setShellProcessStarterForTests(starter) {
221944
222019
  shellProcessStarter = starter ?? startShellProcess;
221945
222020
  }
@@ -222280,7 +222355,7 @@ async function bash(args) {
222280
222355
  ]) : await settledOutcome;
222281
222356
  if (outcome.type === "settled") {
222282
222357
  backgroundProcesses.delete(bashId);
222283
- rmSync13(outputFile, { force: true });
222358
+ rmSync14(outputFile, { force: true });
222284
222359
  const { result: result2 } = outcome;
222285
222360
  const output = [foregroundOutput.stdout, foregroundOutput.stderr].filter(Boolean).join(`
222286
222361
  `);
@@ -222478,7 +222553,7 @@ async function checkDiskSpaceNow(path17, options = {}) {
222478
222553
  }
222479
222554
  }
222480
222555
  async function watchDiskSpaceDuring(path17, deliver, work, options = {}) {
222481
- if (!isManagedCloudRuntime(options.env))
222556
+ if (!isManagedCloudRuntime(options.env) || sandboxPollTimer)
222482
222557
  return work();
222483
222558
  const check5 = () => void checkDiskSpaceNow(path17, options).then((text2) => {
222484
222559
  if (text2)
@@ -222493,6 +222568,31 @@ async function watchDiskSpaceDuring(path17, deliver, work, options = {}) {
222493
222568
  check5();
222494
222569
  }
222495
222570
  }
222571
+ function watchSandboxDiskSpace(getPath, deliver, options = {}) {
222572
+ try {
222573
+ if (!isManagedCloudRuntime(options.env))
222574
+ return () => {};
222575
+ if (sandboxPollTimer)
222576
+ clearInterval(sandboxPollTimer);
222577
+ const timer = setInterval(() => {
222578
+ try {
222579
+ checkDiskSpaceNow(getPath(), options).then((text2) => {
222580
+ if (text2)
222581
+ deliver(text2);
222582
+ }).catch(() => {});
222583
+ } catch {}
222584
+ }, options.intervalMs ?? DISK_SPACE_POLL_INTERVAL_MS);
222585
+ timer.unref?.();
222586
+ sandboxPollTimer = timer;
222587
+ return () => {
222588
+ clearInterval(timer);
222589
+ if (sandboxPollTimer === timer)
222590
+ sandboxPollTimer = null;
222591
+ };
222592
+ } catch {
222593
+ return () => {};
222594
+ }
222595
+ }
222496
222596
  function deliverDiskSpaceReminder(text2, parentScope) {
222497
222597
  if (!isQueueBridgeConnected()) {
222498
222598
  pendingRequestReminder = text2;
@@ -222530,7 +222630,7 @@ function evaluateDiskSpaceReminder(input) {
222530
222630
  return { text: null, notified: input.notified };
222531
222631
  }
222532
222632
  }
222533
- var LOW_DISK_USED_FRACTION = 0.9, LOW_DISK_AVAILABLE_BYTES, DISK_SPACE_CHECK_INTERVAL_MS = 60000, cache5, CRITICAL_DISK_USED_FRACTION = 0.95, DISK_SPACE_POLL_INTERVAL_MS = 30000, pushedLevel = 0, pendingRequestReminder = null;
222633
+ var LOW_DISK_USED_FRACTION = 0.9, LOW_DISK_AVAILABLE_BYTES, DISK_SPACE_CHECK_INTERVAL_MS = 60000, cache5, CRITICAL_DISK_USED_FRACTION = 0.95, DISK_SPACE_POLL_INTERVAL_MS = 30000, pushedLevel = 0, sandboxPollTimer = null, pendingRequestReminder = null;
222534
222634
  var init_disk_space = __esm(() => {
222535
222635
  init_constants2();
222536
222636
  init_message_queue_bridge();
@@ -223857,6 +223957,10 @@ var init_hooks = __esm(() => {
223857
223957
  });
223858
223958
 
223859
223959
  // src/agent/subagent-state.ts
223960
+ function excerptProgressText(value, max2) {
223961
+ const line = value.replace(/\s+/g, " ").trim();
223962
+ return line.length > max2 ? `${line.slice(0, max2)}…` : line;
223963
+ }
223860
223964
  function updateSnapshot() {
223861
223965
  const agents = Array.from(store2.agents.values());
223862
223966
  const now2 = Date.now();
@@ -223885,6 +223989,9 @@ function unrefTimer2(timer) {
223885
223989
  timer.unref();
223886
223990
  }
223887
223991
  }
223992
+ function isPublished(agent) {
223993
+ return agent.published === true || agent.result !== undefined;
223994
+ }
223888
223995
  function scheduleCompletedSubagentCleanup(id2) {
223889
223996
  const agent = store2.agents.get(id2);
223890
223997
  if (!agent || agent.status !== "completed" && agent.status !== "error") {
@@ -223909,7 +224016,7 @@ function armCompletedSubagentCleanup(id2) {
223909
224016
  }
223910
224017
  store2.agents.delete(id2);
223911
224018
  notifyListeners();
223912
- }, agent.result !== undefined ? publishedResultRetentionMs : completedSubagentRetentionMs);
224019
+ }, isPublished(agent) ? publishedResultRetentionMs : completedSubagentRetentionMs);
223913
224020
  unrefTimer2(timer);
223914
224021
  completedSubagentCleanupTimers.set(id2, timer);
223915
224022
  }
@@ -223989,6 +224096,25 @@ function addToolCall(subagentId, toolCallId, toolName2, toolArgs) {
223989
224096
  store2.agents.set(subagentId, updatedAgent);
223990
224097
  notifyListeners();
223991
224098
  }
224099
+ function addProgressText(subagentId, text2, now2 = () => new Date) {
224100
+ const agent = store2.agents.get(subagentId);
224101
+ if (!agent)
224102
+ return;
224103
+ const excerpt = excerptProgressText(text2, PROGRESS_TEXT_CHARS);
224104
+ const previous = agent.progressTexts?.at(-1);
224105
+ if (!excerpt || previous?.text === excerpt)
224106
+ return;
224107
+ const count = (agent.progressTextCount ?? 0) + 1;
224108
+ store2.agents.set(subagentId, {
224109
+ ...agent,
224110
+ progressTexts: [
224111
+ ...agent.progressTexts ?? [],
224112
+ { id: `text-${count}`, at: now2().toISOString(), text: excerpt }
224113
+ ].slice(-MAX_PROGRESS_TEXTS),
224114
+ progressTextCount: count
224115
+ });
224116
+ notifyListeners();
224117
+ }
223992
224118
  function completeSubagent(id2, result2) {
223993
224119
  const agent = store2.agents.get(id2);
223994
224120
  if (!agent)
@@ -223999,6 +224125,7 @@ function completeSubagent(id2, result2) {
223999
224125
  error: result2.error,
224000
224126
  stopFailed: undefined,
224001
224127
  ...result2.result !== undefined ? { result: result2.result } : {},
224128
+ ...result2.published ? { published: true } : {},
224002
224129
  durationMs: Date.now() - agent.startTime,
224003
224130
  totalTokens: result2.totalTokens ?? agent.totalTokens,
224004
224131
  maxToolCallsSeen: Math.max(agent.maxToolCallsSeen, agent.toolCalls.length)
@@ -224052,7 +224179,7 @@ function subscribeToSubagentLifecycle(listener) {
224052
224179
  function clearCompletedSubagents() {
224053
224180
  let removedAny = false;
224054
224181
  for (const [id2, agent] of store2.agents.entries()) {
224055
- if (agent.result !== undefined)
224182
+ if (isPublished(agent))
224056
224183
  continue;
224057
224184
  if (agent.cancelPending)
224058
224185
  continue;
@@ -224185,7 +224312,7 @@ function emitStreamEvent(subagentId, event) {
224185
224312
  listener(subagentId, event);
224186
224313
  }
224187
224314
  }
224188
- var store2, cachedSnapshot, cachedLifecycleItems, DEFAULT_COMPLETED_SUBAGENT_RETENTION_MS = 30000, completedSubagentRetentionMs, DEFAULT_PUBLISHED_RESULT_RETENTION_MS, publishedResultRetentionMs, completedSubagentCleanupTimers, subagentCounter = 0, subagentAbortHooks, streamEventListeners;
224315
+ var PROGRESS_TEXT_CHARS = 300, MAX_PROGRESS_TEXTS = 20, store2, cachedSnapshot, cachedLifecycleItems, DEFAULT_COMPLETED_SUBAGENT_RETENTION_MS = 30000, completedSubagentRetentionMs, DEFAULT_PUBLISHED_RESULT_RETENTION_MS, publishedResultRetentionMs, completedSubagentCleanupTimers, subagentCounter = 0, subagentAbortHooks, streamEventListeners;
224189
224316
  var init_subagent_state = __esm(() => {
224190
224317
  store2 = {
224191
224318
  agents: new Map,
@@ -225172,7 +225299,7 @@ import {
225172
225299
  closeSync as closeSync6,
225173
225300
  existsSync as existsSync39,
225174
225301
  openSync as openSync6,
225175
- readdirSync as readdirSync13,
225302
+ readdirSync as readdirSync14,
225176
225303
  readFileSync as readFileSync33,
225177
225304
  readSync as readSync3,
225178
225305
  realpathSync as realpathSync7,
@@ -225216,7 +225343,7 @@ function isHidden2(name) {
225216
225343
  return name.startsWith(".");
225217
225344
  }
225218
225345
  function findByBasename(dir, name, root2 = dir, found = []) {
225219
- for (const entry of readdirSync13(dir, { withFileTypes: true })) {
225346
+ for (const entry of readdirSync14(dir, { withFileTypes: true })) {
225220
225347
  if (found.length >= 5)
225221
225348
  break;
225222
225349
  if (isHidden2(entry.name) || dir === root2 && entry.name === "skills") {
@@ -225290,7 +225417,7 @@ function lastEditedByChild(dir, names2) {
225290
225417
  return bump(name, stat6.mtimeMs);
225291
225418
  if (!stat6.isDirectory())
225292
225419
  return;
225293
- for (const entry of readdirSync13(path18, { withFileTypes: true })) {
225420
+ for (const entry of readdirSync14(path18, { withFileTypes: true })) {
225294
225421
  if (!isHidden2(entry.name))
225295
225422
  walkMtime(join53(path18, entry.name), name);
225296
225423
  }
@@ -225332,7 +225459,7 @@ function lastEditedByChild(dir, names2) {
225332
225459
  return edited;
225333
225460
  }
225334
225461
  function renderDirectory(memoryDir, relPath, fullPath) {
225335
- const entries = readdirSync13(fullPath, { withFileTypes: true }).filter((entry) => !isHidden2(entry.name) && (entry.isDirectory() || entry.isFile() && entry.name !== INDEX));
225462
+ const entries = readdirSync14(fullPath, { withFileTypes: true }).filter((entry) => !isHidden2(entry.name) && (entry.isDirectory() || entry.isFile() && entry.name !== INDEX));
225336
225463
  const edited = lastEditedByChild(fullPath, entries.map((entry) => entry.name));
225337
225464
  const shown = entries.sort((a2, b3) => (edited.get(b3.name) ?? 0) - (edited.get(a2.name) ?? 0) || a2.name.localeCompare(b3.name)).slice(0, LIMITS.MEMORY_MAX_ENTRIES);
225338
225465
  const fileLines = shown.filter((entry) => entry.isFile()).map((entry) => {
@@ -230936,7 +231063,7 @@ var init_approval_result_normalization = __esm(() => {
230936
231063
  // src/agent/client-skills-watcher.ts
230937
231064
  import {
230938
231065
  existsSync as existsSync41,
230939
- readdirSync as readdirSync14,
231066
+ readdirSync as readdirSync15,
230940
231067
  realpathSync as realpathSync8,
230941
231068
  statSync as statSync18,
230942
231069
  watch as watch2
@@ -230975,7 +231102,7 @@ function collectSymlinkDirectoryTargets(path19, targets, visited2) {
230975
231102
  }
230976
231103
  visited2.add(realPath);
230977
231104
  try {
230978
- const entries = readdirSync14(path19, {
231105
+ const entries = readdirSync15(path19, {
230979
231106
  encoding: "utf8",
230980
231107
  withFileTypes: true
230981
231108
  });
@@ -235751,7 +235878,7 @@ var init_workflow_engine = __esm(() => {
235751
235878
  });
235752
235879
 
235753
235880
  // src/tools/impl/code-mode.ts
235754
- import { rmSync as rmSync14 } from "node:fs";
235881
+ import { rmSync as rmSync15 } from "node:fs";
235755
235882
  function truncateResult(text2) {
235756
235883
  if (text2.length <= MAX_NOTIFICATION_RESULT_CHARS)
235757
235884
  return text2;
@@ -235881,7 +236008,7 @@ ${outcome.text}
235881
236008
  signal?.removeEventListener("abort", forwardAbort);
235882
236009
  if (first !== "yield") {
235883
236010
  backgroundProcesses.delete(taskId);
235884
- rmSync14(outputFile, { force: true });
236011
+ rmSync15(outputFile, { force: true });
235885
236012
  if (first.ok)
235886
236013
  return { content: first.text, status: "success" };
235887
236014
  return {
@@ -236411,7 +236538,7 @@ var init_memory_reminder = __esm(() => {
236411
236538
  });
236412
236539
 
236413
236540
  // src/agent/system-prompt-size.ts
236414
- import { existsSync as existsSync45, readdirSync as readdirSync15, readFileSync as readFileSync36 } from "node:fs";
236541
+ import { existsSync as existsSync45, readdirSync as readdirSync16, readFileSync as readFileSync36 } from "node:fs";
236415
236542
  import { join as join60 } from "node:path";
236416
236543
  function estimateSystemTokens(text2) {
236417
236544
  return Math.ceil(Buffer.byteLength(text2, "utf8") / SYSTEM_PROMPT_BYTES_PER_TOKEN);
@@ -236424,7 +236551,7 @@ function walkMarkdownFiles(dir) {
236424
236551
  return [];
236425
236552
  }
236426
236553
  const out = [];
236427
- const entries = readdirSync15(dir, { withFileTypes: true });
236554
+ const entries = readdirSync16(dir, { withFileTypes: true });
236428
236555
  for (const entry of entries) {
236429
236556
  if (entry.name.startsWith(".")) {
236430
236557
  continue;
@@ -236445,7 +236572,7 @@ function estimateSystemPromptSize(memoryDir, localMemfs = false) {
236445
236572
  return { total: 0, files: [] };
236446
236573
  }
236447
236574
  const memoryFormat = detectMemoryFormat(memoryDir, localMemfs);
236448
- const files = memoryFormat === "memfs-v2" ? readdirSync15(memoryDir, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".") && entry.isFile() && entry.name.endsWith(".md")).map((entry) => join60(memoryDir, entry.name)).sort() : walkMarkdownFiles(join60(memoryDir, "system")).sort();
236575
+ const files = memoryFormat === "memfs-v2" ? readdirSync16(memoryDir, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".") && entry.isFile() && entry.name.endsWith(".md")).map((entry) => join60(memoryDir, entry.name)).sort() : walkMarkdownFiles(join60(memoryDir, "system")).sort();
236449
236576
  const rows = [];
236450
236577
  for (const filePath of files) {
236451
236578
  const text2 = readFileSync36(filePath, "utf8");
@@ -237325,6 +237452,30 @@ var init_stream_observers = __esm(() => {
237325
237452
  init_debug();
237326
237453
  });
237327
237454
 
237455
+ // src/websocket/listener/subagent-state-cache.ts
237456
+ function clearSubagentSnapshotCache(owner) {
237457
+ lastSubagentSnapshotByOwner.delete(owner);
237458
+ }
237459
+ function shouldEmitSubagentSnapshot(owner, scope, snapshot2, options) {
237460
+ const snapshotJson = JSON.stringify(snapshot2);
237461
+ const cacheKey = `${scope?.agent_id ?? ""}:${scope?.conversation_id ?? ""}`;
237462
+ let scopeCache = lastSubagentSnapshotByOwner.get(owner);
237463
+ if (!scopeCache) {
237464
+ scopeCache = new Map;
237465
+ lastSubagentSnapshotByOwner.set(owner, scopeCache);
237466
+ }
237467
+ const previousJson = scopeCache.get(cacheKey) ?? EMPTY_SNAPSHOT_JSON;
237468
+ if (options?.onlyIfChanged && previousJson === snapshotJson) {
237469
+ return false;
237470
+ }
237471
+ scopeCache.set(cacheKey, snapshotJson);
237472
+ return true;
237473
+ }
237474
+ var EMPTY_SNAPSHOT_JSON = "[]", lastSubagentSnapshotByOwner;
237475
+ var init_subagent_state_cache = __esm(() => {
237476
+ lastSubagentSnapshotByOwner = new WeakMap;
237477
+ });
237478
+
237328
237479
  // src/websocket/listener/inbound-queue.ts
237329
237480
  function getInboundClientMessageId(incoming) {
237330
237481
  return getInboundClientMessageIds(incoming)[0];
@@ -237437,7 +237588,6 @@ __export(exports_protocol_outbound, {
237437
237588
  refreshDeviceGitContext: () => refreshDeviceGitContext,
237438
237589
  isSystemReminderPart: () => isSystemReminderPart,
237439
237590
  emitSubagentStateUpdate: () => emitSubagentStateUpdate,
237440
- emitSubagentStateIfOpen: () => emitSubagentStateIfOpen,
237441
237591
  emitStreamDelta: () => emitStreamDelta,
237442
237592
  emitStatusDelta: () => emitStatusDelta,
237443
237593
  emitStateSync: () => emitStateSync,
@@ -237909,26 +238059,22 @@ function buildSubagentSnapshot(runtime, scope) {
237909
238059
  parent_conversation_id: a2.parentConversationId,
237910
238060
  start_time: a2.startTime,
237911
238061
  tool_calls: a2.toolCalls,
238062
+ ...a2.progressTexts?.length ? { progress_texts: a2.progressTexts } : {},
237912
238063
  total_tokens: a2.totalTokens,
237913
238064
  duration_ms: a2.durationMs,
237914
238065
  error: a2.error,
237915
238066
  ...a2.result !== undefined ? { result: a2.result } : {}
237916
238067
  }));
237917
238068
  }
237918
- function emitSubagentStateUpdate(socket, runtime, scope, routing = TO_SUBSCRIBERS) {
237919
- const message = {
237920
- type: "update_subagent_state",
237921
- subagents: buildSubagentSnapshot(runtime, scope)
237922
- };
238069
+ function emitSubagentStateUpdate(socket, runtime, scope, routing = TO_SUBSCRIBERS, options) {
238070
+ const subagents = buildSubagentSnapshot(runtime, scope);
238071
+ const cacheScope = resolveSubagentScopeForSnapshot(runtime, scope);
238072
+ const cacheOwner = getListenerRuntime(runtime) ?? socket;
238073
+ if (!shouldEmitSubagentSnapshot(cacheOwner, cacheScope, subagents, options))
238074
+ return;
238075
+ const message = { type: "update_subagent_state", subagents };
237923
238076
  emitProtocolV2Message(socket, runtime, message, scope, routing);
237924
238077
  }
237925
- function emitSubagentStateIfOpen(runtime, scope) {
237926
- const listener = getListenerRuntime(runtime);
237927
- const transport3 = listener?.transport ?? listener?.socket;
237928
- if (transport3 && isListenerTransportOpen(transport3)) {
237929
- emitSubagentStateUpdate(transport3, runtime, scope);
237930
- }
237931
- }
237932
238078
  function emitCanonicalMessageDelta(socket, runtime, delta2, scope, routing = TO_SUBSCRIBERS) {
237933
238079
  return emitStreamDelta(socket, runtime, delta2, scope, undefined, routing);
237934
238080
  }
@@ -237996,6 +238142,7 @@ var init_protocol_outbound = __esm(async () => {
237996
238142
  init_permission_mode();
237997
238143
  init_protocol_outbound_routing();
237998
238144
  init_stream_observers();
238145
+ init_subagent_state_cache();
237999
238146
  init_transport2();
238000
238147
  await __promiseAll([
238001
238148
  init_connection(),
@@ -241497,6 +241644,7 @@ __export(exports_environments3, {
241497
241644
  isEnvironmentOnline: () => isEnvironmentOnline,
241498
241645
  getTeleportStatus: () => getTeleportStatus,
241499
241646
  getEnvironmentConnection: () => getEnvironmentConnection,
241647
+ environmentMatchesSelector: () => environmentMatchesSelector,
241500
241648
  describeEnvironment: () => describeEnvironment,
241501
241649
  createAgentSandbox: () => createAgentSandbox
241502
241650
  });
@@ -241542,15 +241690,16 @@ async function resolveDesktopEnvironmentConnectionId(list = listEnvironments) {
241542
241690
  }
241543
241691
  return { connectionId: environment2.connectionId, environment: environment2 };
241544
241692
  }
241693
+ function environmentMatchesSelector(environment2, selector) {
241694
+ return environment2.connectionId === selector || environment2.id === selector || environment2.deviceId === selector || environment2.connectionName === selector;
241695
+ }
241545
241696
  async function resolveEnvironmentConnectionId(selector, list = listEnvironments) {
241546
241697
  const trimmed = selector.trim();
241547
241698
  if (!trimmed) {
241548
241699
  throw new Error("Computer selector must not be empty");
241549
241700
  }
241550
241701
  const response = await list({ limit: 100 });
241551
- const matches3 = response.connections.filter((environment3) => {
241552
- return environment3.connectionId === trimmed || environment3.id === trimmed || environment3.deviceId === trimmed || environment3.connectionName === trimmed;
241553
- });
241702
+ const matches3 = response.connections.filter((environment3) => environmentMatchesSelector(environment3, trimmed));
241554
241703
  if (matches3.length === 0) {
241555
241704
  throw new Error(`Computer "${trimmed}" not found. Run \`letta computers list\` to discover available computers.`);
241556
241705
  }
@@ -241691,6 +241840,34 @@ async function lookupEnvironmentForTarget(deviceId) {
241691
241840
  return null;
241692
241841
  }
241693
241842
  }
241843
+ async function resolveTargetDeviceSelector(selector) {
241844
+ let environments2;
241845
+ let response;
241846
+ try {
241847
+ environments2 = await Promise.resolve().then(() => (init_environments3(), exports_environments3));
241848
+ response = await environments2.listEnvironments({ limit: 100 });
241849
+ } catch {
241850
+ return null;
241851
+ }
241852
+ const matches3 = response.connections.filter((environment3) => environments2.environmentMatchesSelector(environment3, selector));
241853
+ if (matches3.length === 0) {
241854
+ if (response.hasNextPage)
241855
+ return null;
241856
+ return {
241857
+ error: `Computer "${selector}" not found. Run \`letta computers list\` and pass its deviceId (or name).`
241858
+ };
241859
+ }
241860
+ if (new Set(matches3.map((environment3) => environment3.deviceId)).size > 1) {
241861
+ return {
241862
+ error: `Computer "${selector}" is ambiguous. Matched: ${matches3.map(environments2.describeEnvironment).join(", ")}. Pass a deviceId instead.`
241863
+ };
241864
+ }
241865
+ matches3.sort((a2, b3) => Math.max(b3.lastHeartbeat ?? 0, b3.lastSeenAt) - Math.max(a2.lastHeartbeat ?? 0, a2.lastSeenAt));
241866
+ const environment2 = matches3[0];
241867
+ if (!environment2)
241868
+ return null;
241869
+ return { deviceId: environment2.deviceId, environment: environment2 };
241870
+ }
241694
241871
  async function resolveCronCreatePlacement(params) {
241695
241872
  const resolved2 = await resolveCronRunnerForAgent(params.agentId);
241696
241873
  if ("error" in resolved2)
@@ -241701,12 +241878,24 @@ async function resolveCronCreatePlacement(params) {
241701
241878
  error: "--computer is only available from a managed Cloud sandbox. Run the schedule on this computer instead."
241702
241879
  };
241703
241880
  }
241704
- if (targetDeviceId) {
241705
- const validity = validateTargetDevice(targetDeviceId, await lookupEnvironmentForTarget(targetDeviceId));
241706
- if (!validity.ok)
241707
- return validity;
241708
- }
241709
- return { runner: resolved2.runner, targetDeviceId };
241881
+ if (!targetDeviceId)
241882
+ return { runner: resolved2.runner };
241883
+ const selectorValidity = validateTargetDevice(targetDeviceId, null);
241884
+ if (!selectorValidity.ok)
241885
+ return selectorValidity;
241886
+ const resolution = await resolveTargetDeviceSelector(targetDeviceId);
241887
+ if (!resolution) {
241888
+ const validity2 = validateTargetDevice(targetDeviceId, await lookupEnvironmentForTarget(targetDeviceId));
241889
+ if (!validity2.ok)
241890
+ return validity2;
241891
+ return { runner: resolved2.runner, targetDeviceId };
241892
+ }
241893
+ if ("error" in resolution)
241894
+ return resolution;
241895
+ const validity = validateTargetDevice(resolution.deviceId, resolution.environment);
241896
+ if (!validity.ok)
241897
+ return validity;
241898
+ return { runner: resolved2.runner, targetDeviceId: resolution.deviceId };
241710
241899
  }
241711
241900
  function buildCloudScheduleInput(params) {
241712
241901
  const notes = [];
@@ -242548,17 +242737,30 @@ var init_monitor_script = __esm(() => {
242548
242737
 
242549
242738
  // src/tools/impl/monitor-timeout.ts
242550
242739
  function getMonitorMaxTimeoutMs() {
242551
- const value = process.env.LETTA_MONITOR_MAX_TIMEOUT_MS;
242740
+ const seconds = process.env.LETTA_MONITOR_MAX_TIMEOUT_SECONDS;
242741
+ const value = seconds || process.env.LETTA_MONITOR_MAX_TIMEOUT_MS;
242552
242742
  if (!value || !/^\d+$/.test(value))
242553
242743
  return DEFAULT_MAX_TIMEOUT_MS;
242554
- const parsed = Number(value);
242555
- if (!Number.isInteger(parsed) || parsed <= 0)
242744
+ const parsed = seconds ? Number(value) * 1000 : Number(value);
242745
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
242556
242746
  return DEFAULT_MAX_TIMEOUT_MS;
242747
+ }
242557
242748
  return Math.min(SEVEN_DAYS_MS, Math.max(DEFAULT_MAX_TIMEOUT_MS, parsed));
242558
242749
  }
242559
- var DEFAULT_MAX_TIMEOUT_MS = 3600000, SEVEN_DAYS_MS;
242750
+ function formatMonitorMaxTimeout(timeoutMs = getMonitorMaxTimeoutMs()) {
242751
+ const days = timeoutMs >= 2 * DAY_MS && timeoutMs % DAY_MS === 0;
242752
+ const value = days ? timeoutMs / DAY_MS : Math.round(timeoutMs / HOUR_MS * 100) / 100;
242753
+ const unit = days ? "day" : "hour";
242754
+ return `${value} ${unit}${value === 1 ? "" : "s"}`;
242755
+ }
242756
+ function applyMonitorMaxTimeout(text2, timeoutMs = getMonitorMaxTimeoutMs()) {
242757
+ return text2.replaceAll("{{MONITOR_MAX_TIMEOUT}}", formatMonitorMaxTimeout(timeoutMs));
242758
+ }
242759
+ var HOUR_MS = 3600000, DAY_MS, DEFAULT_MAX_TIMEOUT_MS, SEVEN_DAYS_MS;
242560
242760
  var init_monitor_timeout = __esm(() => {
242561
- SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
242761
+ DAY_MS = 24 * HOUR_MS;
242762
+ DEFAULT_MAX_TIMEOUT_MS = HOUR_MS;
242763
+ SEVEN_DAYS_MS = 7 * DAY_MS;
242562
242764
  });
242563
242765
 
242564
242766
  // src/tools/impl/monitor.ts
@@ -244149,6 +244351,8 @@ function noReplyMessage(receipt) {
244149
244351
  }
244150
244352
  async function waitForAcceptedSuperRun(receipt, signal, deps) {
244151
244353
  const pollMs = deps.pollMs ?? 1000;
244354
+ const runLinkGraceMs = deps.runLinkGraceMs ?? DEFAULT_RUN_LINK_GRACE_MS;
244355
+ let completedWithoutRunSince;
244152
244356
  const sleep11 = deps.sleep ?? ((ms, waitSignal) => delay3(ms, undefined, { signal: waitSignal }));
244153
244357
  while (true) {
244154
244358
  signal.throwIfAborted();
@@ -244164,6 +244368,11 @@ async function waitForAcceptedSuperRun(receipt, signal, deps) {
244164
244368
  }
244165
244369
  const runId = exact.run_ids[0];
244166
244370
  if (!runId) {
244371
+ completedWithoutRunSince ??= Date.now();
244372
+ if (Date.now() - completedWithoutRunSince < runLinkGraceMs) {
244373
+ await sleep11(pollMs, signal);
244374
+ continue;
244375
+ }
244167
244376
  throw new RemoteExecutionFailed(`Remote Super Run ${exact.id} completed without a correlated child run.`);
244168
244377
  }
244169
244378
  const run = await retryRead(() => deps.run(runId, AbortSignal.any([signal, AbortSignal.timeout(30000)])), signal, sleep11, `Remote child run read for ${runId} failed`);
@@ -244187,7 +244396,7 @@ async function waitForAcceptedSuperRun(receipt, signal, deps) {
244187
244396
  };
244188
244397
  }
244189
244398
  }
244190
- var RemoteExecutionFailed;
244399
+ var RemoteExecutionFailed, DEFAULT_RUN_LINK_GRACE_MS = 60000;
244191
244400
  var init_headless_super_run_wait = __esm(() => {
244192
244401
  init_letta_client();
244193
244402
  init_conversation_enqueue();
@@ -244475,9 +244684,10 @@ import { createInterface as createInterface8 } from "node:readline";
244475
244684
  function errorMessage2(error5) {
244476
244685
  return error5 instanceof Error ? error5.message : String(error5);
244477
244686
  }
244478
- function userInput(prompt) {
244687
+ function userInput(prompt, uuid5) {
244479
244688
  return `${JSON.stringify({
244480
244689
  type: "user",
244690
+ uuid: uuid5,
244481
244691
  message: {
244482
244692
  role: "user",
244483
244693
  content: [{ type: "text", text: prompt }]
@@ -244502,6 +244712,7 @@ function buildClaudeStreamArgs(options) {
244502
244712
  "--output-format",
244503
244713
  "stream-json",
244504
244714
  "--include-partial-messages",
244715
+ "--replay-user-messages",
244505
244716
  "--permission-mode",
244506
244717
  "bypassPermissions"
244507
244718
  ];
@@ -244549,19 +244760,29 @@ function rejectTurnWaiters(session3, error5) {
244549
244760
  waiter.reject(error5);
244550
244761
  session3.turnWaiters.clear();
244551
244762
  }
244763
+ function clearBackgroundCap(session3) {
244764
+ if (session3.backgroundCapTimer)
244765
+ clearTimeout(session3.backgroundCapTimer);
244766
+ session3.backgroundCapTimer = undefined;
244767
+ }
244552
244768
  function markTurnStarted(session3) {
244553
244769
  session3.interruptible = true;
244770
+ session3.idleOnBackgroundTasks = false;
244771
+ clearBackgroundCap(session3);
244554
244772
  if (session3.awaitingReplacementStart) {
244555
244773
  session3.awaitingReplacementStart = false;
244556
244774
  session3.pendingSteers = 0;
244557
244775
  session3.suppressedResult = undefined;
244558
244776
  }
244777
+ resolveTurnWaiters(session3);
244778
+ }
244779
+ function resolveTurnWaiters(session3) {
244559
244780
  for (const waiter of session3.turnWaiters)
244560
244781
  waiter.resolve();
244561
244782
  session3.turnWaiters.clear();
244562
244783
  }
244563
244784
  function waitForTurnStart(session3, signal) {
244564
- if (session3.interruptible)
244785
+ if (session3.interruptible || session3.idleOnBackgroundTasks)
244565
244786
  return Promise.resolve();
244566
244787
  if (session3.settled) {
244567
244788
  return Promise.reject(new Error("Claude Code session is no longer active"));
@@ -244594,9 +244815,8 @@ function settle(session3, result3) {
244594
244815
  if (session3.settled)
244595
244816
  return;
244596
244817
  session3.settled = true;
244597
- session3.removeUpstreamAbort();
244598
- if (sessions.get(session3.sessionId) === session3)
244599
- sessions.delete(session3.sessionId);
244818
+ session3.idleOnBackgroundTasks = false;
244819
+ clearBackgroundCap(session3);
244600
244820
  const completedError = new Error("Claude Code session completed");
244601
244821
  rejectControls(session3, completedError);
244602
244822
  rejectTurnWaiters(session3, completedError);
@@ -244614,8 +244834,21 @@ function writeRaw(stdin, data) {
244614
244834
  });
244615
244835
  });
244616
244836
  }
244617
- function writeInput(stdin, prompt) {
244618
- return writeRaw(stdin, userInput(prompt));
244837
+ function writeInput(session3, prompt) {
244838
+ const uuid5 = randomUUID36();
244839
+ session3.latestInputUuid = uuid5;
244840
+ session3.latestInputStarted = false;
244841
+ return writeRaw(session3.transport.process.stdin, userInput(prompt, uuid5));
244842
+ }
244843
+ function acknowledgeInput(session3, uuid5) {
244844
+ if (typeof uuid5 !== "string" || !session3.latestInputUuid)
244845
+ return;
244846
+ session3.acknowledgesInputs = true;
244847
+ if (uuid5 === session3.latestInputUuid)
244848
+ session3.latestInputStarted = true;
244849
+ }
244850
+ function isStaleResult(session3) {
244851
+ return session3.acknowledgesInputs && !session3.latestInputStarted;
244619
244852
  }
244620
244853
  function closeInput(session3) {
244621
244854
  if (!session3.transport.process.stdin.destroyed && !session3.transport.process.stdin.writableEnded) {
@@ -244656,15 +244889,31 @@ function handleControlResponse(session3, value) {
244656
244889
  pending2.reject(new Error(detail));
244657
244890
  }
244658
244891
  }
244892
+ function reportText(session3, messageId, text2) {
244893
+ if (!session3.onText || typeof text2 !== "string" || !text2.trim())
244894
+ return;
244895
+ const key2 = `${typeof messageId === "string" ? messageId : ""}\x00${text2.slice(0, 1000)}`;
244896
+ if (session3.seenTextBlocks.has(key2))
244897
+ return;
244898
+ session3.seenTextBlocks.add(key2);
244899
+ try {
244900
+ session3.onText(text2);
244901
+ } catch {}
244902
+ }
244659
244903
  function handleAssistant(session3, value) {
244660
- if (!session3.onToolCall)
244904
+ if (!session3.onToolCall && !session3.onText)
244661
244905
  return;
244662
- const content = readRecord(value.message)?.content;
244906
+ const message = readRecord(value.message);
244907
+ const content = message?.content;
244663
244908
  if (!Array.isArray(content))
244664
244909
  return;
244665
244910
  for (const entry of content) {
244666
244911
  const block = readRecord(entry);
244667
- if (block?.type !== "tool_use" || typeof block.id !== "string" || typeof block.name !== "string" || session3.seenToolCallIds.has(block.id))
244912
+ if (block?.type === "text") {
244913
+ reportText(session3, message?.id, block.text);
244914
+ continue;
244915
+ }
244916
+ if (!session3.onToolCall || block?.type !== "tool_use" || typeof block.id !== "string" || typeof block.name !== "string" || session3.seenToolCallIds.has(block.id))
244668
244917
  continue;
244669
244918
  session3.seenToolCallIds.add(block.id);
244670
244919
  try {
@@ -244677,6 +244926,8 @@ function handleAssistant(session3, value) {
244677
244926
  }
244678
244927
  }
244679
244928
  function settleResult(session3, value) {
244929
+ if (session3.settled)
244930
+ return;
244680
244931
  if (typeof value.result === "string")
244681
244932
  session3.report = value.result;
244682
244933
  closeInput(session3);
@@ -244686,6 +244937,41 @@ function settleResult(session3, value) {
244686
244937
  settle(session3, successResult(session3));
244687
244938
  }
244688
244939
  }
244940
+ function handleBackgroundTasksChanged(session3, value) {
244941
+ if (Array.isArray(value.tasks))
244942
+ session3.backgroundTasks = value.tasks;
244943
+ }
244944
+ function holdResult(session3, value) {
244945
+ if (session3.settled)
244946
+ return;
244947
+ const capMs = session3.backgroundCapMs;
244948
+ if (typeof value.result === "string")
244949
+ session3.report = value.result;
244950
+ session3.provisionalResult = value;
244951
+ session3.idleOnBackgroundTasks = true;
244952
+ resolveTurnWaiters(session3);
244953
+ clearBackgroundCap(session3);
244954
+ session3.backgroundCapTimer = setTimeout(() => {
244955
+ session3.backgroundCapTimer = undefined;
244956
+ if (session3.settled)
244957
+ return;
244958
+ const minutes = Math.round(capMs / 60000);
244959
+ const note = `[Claude Code background tasks were still running ${minutes} minute(s) after its last result; reporting that result.]`;
244960
+ const text2 = typeof value.result === "string" ? value.result : session3.report;
244961
+ settleResult(session3, {
244962
+ ...value,
244963
+ result: text2 ? `${text2}
244964
+
244965
+ ${note}` : note
244966
+ });
244967
+ }, capMs);
244968
+ }
244969
+ function finishResult(session3, value) {
244970
+ if (session3.backgroundTasks.length > 0)
244971
+ holdResult(session3, value);
244972
+ else
244973
+ settleResult(session3, value);
244974
+ }
244689
244975
  function handleResult(session3, value) {
244690
244976
  session3.interruptible = false;
244691
244977
  session3.resultCount++;
@@ -244694,7 +244980,9 @@ function handleResult(session3, value) {
244694
244980
  session3.suppressedResult = value;
244695
244981
  return;
244696
244982
  }
244697
- settleResult(session3, value);
244983
+ if (isStaleResult(session3))
244984
+ return;
244985
+ finishResult(session3, value);
244698
244986
  }
244699
244987
  async function launchSession(options, deps) {
244700
244988
  const sessionId = options.resumeSessionId ?? options.sessionId ?? deps.createSessionId?.() ?? randomUUID36();
@@ -244731,6 +245019,10 @@ async function launchSession(options, deps) {
244731
245019
  const completion = new Promise((done) => {
244732
245020
  resolve35 = done;
244733
245021
  });
245022
+ let resolveExit;
245023
+ const exit = new Promise((done) => {
245024
+ resolveExit = done;
245025
+ });
244734
245026
  const session3 = {
244735
245027
  sessionId,
244736
245028
  transport: transport3,
@@ -244740,11 +245032,21 @@ async function launchSession(options, deps) {
244740
245032
  report: "",
244741
245033
  protocolError: undefined,
244742
245034
  settled: false,
245035
+ exited: false,
245036
+ exit,
245037
+ latestInputUuid: undefined,
245038
+ latestInputStarted: false,
245039
+ acknowledgesInputs: false,
244743
245040
  pendingSteers: 0,
244744
245041
  interruptible: false,
244745
245042
  awaitingReplacementStart: false,
244746
245043
  suppressedResult: undefined,
244747
245044
  resultCount: 0,
245045
+ backgroundTasks: [],
245046
+ provisionalResult: undefined,
245047
+ idleOnBackgroundTasks: false,
245048
+ backgroundCapMs: deps.backgroundTaskWaitCapMs ?? BACKGROUND_TASK_WAIT_CAP_MS,
245049
+ backgroundCapTimer: undefined,
244748
245050
  turnWaiters: new Set,
244749
245051
  writeLock: Promise.resolve(),
244750
245052
  completion,
@@ -244753,7 +245055,9 @@ async function launchSession(options, deps) {
244753
245055
  abortController,
244754
245056
  removeUpstreamAbort,
244755
245057
  onToolCall: options.onToolCall,
244756
- seenToolCallIds: new Set
245058
+ seenToolCallIds: new Set,
245059
+ onText: options.onText,
245060
+ seenTextBlocks: new Set
244757
245061
  };
244758
245062
  sessions.set(sessionId, session3);
244759
245063
  transport3.process.stderr.setEncoding("utf8");
@@ -244768,8 +245072,14 @@ async function launchSession(options, deps) {
244768
245072
  const value = JSON.parse(line);
244769
245073
  if (value.type === "control_response") {
244770
245074
  handleControlResponse(session3, value);
245075
+ } else if (value.type === "user" && value.isReplay === true) {
245076
+ acknowledgeInput(session3, value.uuid);
245077
+ } else if (value.type === "command_lifecycle" && (value.state === "started" || value.state === "completed")) {
245078
+ acknowledgeInput(session3, value.command_uuid);
244771
245079
  } else if (value.type === "result") {
244772
245080
  handleResult(session3, value);
245081
+ } else if (value.type === "system" && value.subtype === "background_tasks_changed") {
245082
+ handleBackgroundTasksChanged(session3, value);
244773
245083
  } else if (value.type === "assistant") {
244774
245084
  handleAssistant(session3, value);
244775
245085
  } else if (value.type === "stream_event" && readRecord(value.event)?.type === "message_start") {
@@ -244782,6 +245092,10 @@ async function launchSession(options, deps) {
244782
245092
  transport3.completion.then(({ exitCode, exitSignal }) => {
244783
245093
  if (session3.settled)
244784
245094
  return;
245095
+ if (session3.provisionalResult && exitCode === 0 && !transport3.wasAborted()) {
245096
+ settleResult(session3, session3.provisionalResult);
245097
+ return;
245098
+ }
244785
245099
  const detail = session3.stderr.trim();
244786
245100
  const protocolDetail = session3.protocolError ? `; protocol error: ${session3.protocolError}` : "";
244787
245101
  const oomDetail = exitCode === 143 || exitSignal === "SIGTERM" || exitSignal === "SIGKILL" ? "; possibly out of memory" : "";
@@ -244791,9 +245105,15 @@ async function launchSession(options, deps) {
244791
245105
  }).catch((error5) => {
244792
245106
  rejectControls(session3, new Error(errorMessage2(error5)));
244793
245107
  settle(session3, failResult(session3, error5));
245108
+ }).finally(() => {
245109
+ session3.exited = true;
245110
+ removeUpstreamAbort();
245111
+ if (sessions.get(sessionId) === session3)
245112
+ sessions.delete(sessionId);
245113
+ resolveExit();
244794
245114
  });
244795
245115
  try {
244796
- await writeInput(transport3.process.stdin, options.prompt);
245116
+ await writeInput(session3, options.prompt);
244797
245117
  } catch (error5) {
244798
245118
  settle(session3, failResult(session3, error5));
244799
245119
  abortController.abort(error5);
@@ -244805,12 +245125,51 @@ async function launchSession(options, deps) {
244805
245125
  options.onStarted?.(sessionId);
244806
245126
  return session3;
244807
245127
  }
245128
+ async function waitForSettledExit(session3, deps, signal) {
245129
+ if (session3.exited)
245130
+ return;
245131
+ const graceMs = deps.settledExitGraceMs ?? SETTLED_EXIT_GRACE_MS;
245132
+ let timer;
245133
+ let onAbort;
245134
+ const cancelled = new Promise((_4, reject2) => {
245135
+ onAbort = () => reject2(signal?.reason instanceof Error ? signal.reason : new Error("Claude Code turn cancelled"));
245136
+ signal?.addEventListener("abort", onAbort, { once: true });
245137
+ if (signal?.aborted)
245138
+ onAbort();
245139
+ });
245140
+ cancelled.catch(() => {
245141
+ return;
245142
+ });
245143
+ try {
245144
+ const exitedInTime = await Promise.race([
245145
+ session3.exit.then(() => true),
245146
+ new Promise((resolve35) => {
245147
+ timer = setTimeout(() => resolve35(false), graceMs);
245148
+ }),
245149
+ cancelled
245150
+ ]);
245151
+ if (!exitedInTime) {
245152
+ session3.abortController.abort(new Error("Claude Code process replaced by a new turn"));
245153
+ await Promise.race([session3.exit, cancelled]);
245154
+ }
245155
+ } finally {
245156
+ if (timer)
245157
+ clearTimeout(timer);
245158
+ if (onAbort)
245159
+ signal?.removeEventListener("abort", onAbort);
245160
+ }
245161
+ }
244808
245162
  async function startSession(options, deps) {
244809
245163
  const key2 = options.resumeSessionId ?? options.sessionId;
244810
245164
  if (key2) {
244811
- const active = sessions.get(key2);
244812
- if (active && !active.settled)
244813
- return active;
245165
+ for (;; ) {
245166
+ const existing = sessions.get(key2);
245167
+ if (!existing)
245168
+ break;
245169
+ if (!existing.settled)
245170
+ return existing;
245171
+ await waitForSettledExit(existing, deps, options.signal);
245172
+ }
244814
245173
  }
244815
245174
  return launchSession(options, deps);
244816
245175
  }
@@ -244835,6 +245194,14 @@ async function steerSession(session3, prompt, signal) {
244835
245194
  await withWriteLock(session3, async () => {
244836
245195
  signal?.throwIfAborted();
244837
245196
  await waitForTurnStart(session3, signal);
245197
+ if (session3.idleOnBackgroundTasks) {
245198
+ if (session3.settled || sessions.get(session3.sessionId) !== session3) {
245199
+ throw new Error("Claude Code session is no longer active");
245200
+ }
245201
+ session3.idleOnBackgroundTasks = false;
245202
+ await writeInput(session3, prompt);
245203
+ return;
245204
+ }
244838
245205
  if (session3.settled || sessions.get(session3.sessionId) !== session3) {
244839
245206
  throw new Error("Claude Code session is no longer active");
244840
245207
  }
@@ -244859,7 +245226,7 @@ async function steerSession(session3, prompt, signal) {
244859
245226
  await response;
244860
245227
  interruptAcknowledged = true;
244861
245228
  signal?.throwIfAborted();
244862
- await writeInput(session3.transport.process.stdin, prompt);
245229
+ await writeInput(session3, prompt);
244863
245230
  session3.awaitingReplacementStart = true;
244864
245231
  session3.suppressedResult = undefined;
244865
245232
  } catch (error5) {
@@ -244872,7 +245239,7 @@ async function steerSession(session3, prompt, signal) {
244872
245239
  } else if (session3.suppressedResult) {
244873
245240
  const suppressed = session3.suppressedResult;
244874
245241
  session3.suppressedResult = undefined;
244875
- settleResult(session3, suppressed);
245242
+ finishResult(session3, suppressed);
244876
245243
  } else if (session3.resultCount === resultCount && !session3.settled && sessions.get(session3.sessionId) === session3) {
244877
245244
  markTurnStarted(session3);
244878
245245
  }
@@ -244884,42 +245251,144 @@ async function steerSession(session3, prompt, signal) {
244884
245251
  }
244885
245252
  });
244886
245253
  }
244887
- async function sendClaudeMessage(options, deps = {}) {
244888
- options.signal?.throwIfAborted();
244889
- const active = sessions.get(options.sessionId);
244890
- if (active && !active.settled) {
245254
+ async function deliverClaudeMessage(options, deps, launch) {
245255
+ for (;; ) {
245256
+ const existing = sessions.get(options.sessionId);
245257
+ if (!existing)
245258
+ break;
245259
+ if (existing.settled) {
245260
+ await waitForSettledExit(existing, deps, options.signal);
245261
+ continue;
245262
+ }
244891
245263
  try {
244892
- await steerSession(active, options.prompt, options.signal);
244893
- return { mode: "steered", sessionId: options.sessionId };
245264
+ await steerSession(existing, options.prompt, options.signal);
245265
+ return { mode: "steered", session: existing };
244894
245266
  } catch (error5) {
244895
- if (sessions.get(options.sessionId) === active && !active.settled)
245267
+ if (sessions.get(options.sessionId) === existing && !existing.settled)
244896
245268
  throw error5;
244897
245269
  }
244898
245270
  }
244899
- if (options.beforeStart)
244900
- await options.beforeStart();
244901
- const session3 = await startSession({ ...options, resumeSessionId: options.sessionId }, deps);
245271
+ if (!launch)
245272
+ return;
245273
+ const session3 = await launch();
244902
245274
  if (session3.sessionId !== options.sessionId) {
244903
245275
  throw new Error("Claude Code resumed with an unexpected session ID");
244904
245276
  }
245277
+ return { mode: "resumed", session: session3 };
245278
+ }
245279
+ function trackedReceipt(session3) {
244905
245280
  return {
244906
245281
  mode: "resumed",
244907
- sessionId: options.sessionId,
245282
+ sessionId: session3.sessionId,
244908
245283
  completion: session3.completion,
244909
245284
  interrupt: async () => {
244910
245285
  session3.abortController.abort(new Error("Claude Code turn cancelled"));
244911
245286
  }
244912
245287
  };
244913
245288
  }
244914
- var sessions, CONTROL_RESPONSE_TIMEOUT_MS = 30000, TURN_START_TIMEOUT_MS = 60000;
245289
+ async function sendClaudeMessage(options, deps = {}) {
245290
+ options.signal?.throwIfAborted();
245291
+ const steered = await deliverClaudeMessage(options, deps);
245292
+ if (steered)
245293
+ return { mode: "steered", sessionId: options.sessionId };
245294
+ if (options.beforeStart)
245295
+ await options.beforeStart();
245296
+ const delivered = await deliverClaudeMessage(options, deps, () => launchSession({ ...options, resumeSessionId: options.sessionId }, deps));
245297
+ if (!delivered)
245298
+ throw new Error("Claude Code session did not start");
245299
+ if (delivered.mode === "steered" && !options.beforeStart)
245300
+ return { mode: "steered", sessionId: options.sessionId };
245301
+ return trackedReceipt(delivered.session);
245302
+ }
245303
+ var sessions, CONTROL_RESPONSE_TIMEOUT_MS = 30000, TURN_START_TIMEOUT_MS = 60000, BACKGROUND_TASK_WAIT_CAP_MS, SETTLED_EXIT_GRACE_MS = 1e4;
244915
245304
  var init_claude_stream_session = __esm(() => {
244916
245305
  init_subagent_process();
244917
245306
  init_native_cli_env();
244918
245307
  sessions = new Map;
245308
+ BACKGROUND_TASK_WAIT_CAP_MS = 35 * 60000;
245309
+ });
245310
+
245311
+ // src/tools/impl/codex-app-server-payloads.ts
245312
+ function asRecord9(value) {
245313
+ return value && typeof value === "object" ? value : undefined;
245314
+ }
245315
+ function readString3(value, key2) {
245316
+ const record6 = asRecord9(value);
245317
+ return typeof record6?.[key2] === "string" ? record6[key2] : undefined;
245318
+ }
245319
+ function isCapacityError(error5) {
245320
+ const info = asRecord9(error5.codexErrorInfo);
245321
+ if (info && Object.values(info).some((detail) => asRecord9(detail)?.httpStatusCode === 409)) {
245322
+ return true;
245323
+ }
245324
+ return /\b409 Conflict\b/i.test(readString3(error5, "message") ?? "");
245325
+ }
245326
+ function turnFailureMessage(turnError, notifications) {
245327
+ const messages = [turnError, ...notifications].map((error5) => readString3(error5, "message")?.trim()).filter((message) => Boolean(message));
245328
+ return messages.length ? [...new Set(messages)].join("; ") : undefined;
245329
+ }
245330
+ function turnReport(params) {
245331
+ const turn = asRecord9(params.turn);
245332
+ const items3 = Array.isArray(turn?.items) ? turn.items : [];
245333
+ for (let index = items3.length - 1;index >= 0; index--) {
245334
+ const item = asRecord9(items3[index]);
245335
+ if (item?.type === "agentMessage" && typeof item.text === "string") {
245336
+ return item.text;
245337
+ }
245338
+ }
245339
+ return "";
245340
+ }
245341
+ function describeCodexToolItem(item) {
245342
+ const id2 = readString3(item, "id");
245343
+ if (!item || !id2)
245344
+ return;
245345
+ const call2 = (name, args) => ({
245346
+ id: id2,
245347
+ name,
245348
+ args: formatExternalToolCallArgs(args)
245349
+ });
245350
+ switch (item.type) {
245351
+ case "commandExecution":
245352
+ return call2("Bash", { command: item.command });
245353
+ case "fileChange": {
245354
+ const changes = Array.isArray(item.changes) ? item.changes : [];
245355
+ return call2("Edit", {
245356
+ files: changes.map((change) => readString3(change, "path"))
245357
+ });
245358
+ }
245359
+ case "mcpToolCall":
245360
+ return call2(`${readString3(item, "server") ?? "mcp"}/${readString3(item, "tool") ?? "tool"}`, item.arguments);
245361
+ case "dynamicToolCall":
245362
+ return call2(readString3(item, "tool") ?? "tool", item.arguments);
245363
+ case "webSearch": {
245364
+ const query3 = readString3(item, "query");
245365
+ return query3 ? call2("WebSearch", { query: query3 }) : undefined;
245366
+ }
245367
+ default:
245368
+ return;
245369
+ }
245370
+ }
245371
+ function capacityResult(result3) {
245372
+ return {
245373
+ ...result3,
245374
+ error: `${CODEX_CAPACITY_ERROR}. Last error: ${result3.error ?? "unknown"}`
245375
+ };
245376
+ }
245377
+ var CAPACITY_RETRY_DELAYS_MS, CODEX_CAPACITY_ERROR = "Codex is out of capacity for this session; start a new codex session or use claude-code", TOOL_ITEM_TYPES;
245378
+ var init_codex_app_server_payloads = __esm(() => {
245379
+ CAPACITY_RETRY_DELAYS_MS = [1000, 2000];
245380
+ TOOL_ITEM_TYPES = new Set([
245381
+ "commandExecution",
245382
+ "fileChange",
245383
+ "mcpToolCall",
245384
+ "dynamicToolCall",
245385
+ "webSearch"
245386
+ ]);
244919
245387
  });
244920
245388
 
244921
245389
  // src/tools/impl/codex-app-server.ts
244922
245390
  import { createInterface as createInterface9 } from "node:readline";
245391
+ import { setTimeout as sleep11 } from "node:timers/promises";
244923
245392
  async function listCodexModels(cwd2, env6) {
244924
245393
  const controller = new AbortController;
244925
245394
  const running = spawnManagedWorkloadProcess("codex", ["app-server", "--stdio"], {
@@ -244996,29 +245465,6 @@ function spawnTransport(options) {
244996
245465
  })
244997
245466
  };
244998
245467
  }
244999
- function asRecord9(value) {
245000
- return value && typeof value === "object" ? value : undefined;
245001
- }
245002
- function readString3(value, key2) {
245003
- const record6 = asRecord9(value);
245004
- return typeof record6?.[key2] === "string" ? record6[key2] : undefined;
245005
- }
245006
- function turnError(params) {
245007
- const turn = asRecord9(params.turn);
245008
- const error5 = asRecord9(turn?.error);
245009
- return typeof error5?.message === "string" ? error5.message : undefined;
245010
- }
245011
- function turnReport(params) {
245012
- const turn = asRecord9(params.turn);
245013
- const items3 = Array.isArray(turn?.items) ? turn.items : [];
245014
- for (let index = items3.length - 1;index >= 0; index--) {
245015
- const item = asRecord9(items3[index]);
245016
- if (item?.type === "agentMessage" && typeof item.text === "string") {
245017
- return item.text;
245018
- }
245019
- }
245020
- return "";
245021
- }
245022
245468
 
245023
245469
  class CodexAppServerClient {
245024
245470
  transport;
@@ -245070,7 +245516,7 @@ class CodexAppServerClient {
245070
245516
  await this.request("initialize", {
245071
245517
  clientInfo: {
245072
245518
  name: "letta-code",
245073
- version: "0.34.36"
245519
+ version: "0.34.37"
245074
245520
  },
245075
245521
  capabilities: null
245076
245522
  });
@@ -245131,46 +245577,24 @@ function failSession(session3, error5) {
245131
245577
  if (!waiter)
245132
245578
  return;
245133
245579
  waiter.resolve({
245134
- agentId: `codex_${session3.threadId}`,
245135
- runtimeSessionId: session3.threadId,
245136
- model: waiter.model,
245137
- report: waiter.latestAgentMessage ?? "",
245138
- success: false,
245139
- error: error5.message,
245140
- durationMs: Date.now() - waiter.startedAt
245580
+ result: {
245581
+ agentId: `codex_${session3.threadId}`,
245582
+ runtimeSessionId: session3.threadId,
245583
+ model: waiter.model,
245584
+ report: waiter.latestAgentMessage ?? "",
245585
+ success: false,
245586
+ error: error5.message,
245587
+ durationMs: Date.now() - waiter.startedAt
245588
+ },
245589
+ capacityFailure: false,
245590
+ ranTool: waiter.ranTool,
245591
+ steered: waiter.steered
245141
245592
  });
245142
245593
  }
245143
- function describeCodexToolItem(item) {
245144
- const id2 = readString3(item, "id");
245145
- if (!item || !id2)
245146
- return;
245147
- const call2 = (name, args) => ({
245148
- id: id2,
245149
- name,
245150
- args: formatExternalToolCallArgs(args)
245151
- });
245152
- switch (item.type) {
245153
- case "commandExecution":
245154
- return call2("Bash", { command: item.command });
245155
- case "fileChange": {
245156
- const changes = Array.isArray(item.changes) ? item.changes : [];
245157
- return call2("Edit", {
245158
- files: changes.map((change) => readString3(change, "path"))
245159
- });
245160
- }
245161
- case "mcpToolCall":
245162
- return call2(`${readString3(item, "server") ?? "mcp"}/${readString3(item, "tool") ?? "tool"}`, item.arguments);
245163
- case "dynamicToolCall":
245164
- return call2(readString3(item, "tool") ?? "tool", item.arguments);
245165
- case "webSearch": {
245166
- const query3 = readString3(item, "query");
245167
- return query3 ? call2("WebSearch", { query: query3 }) : undefined;
245168
- }
245169
- default:
245170
- return;
245171
- }
245172
- }
245173
245594
  function recordToolItem(waiter, item) {
245595
+ if (typeof item.type === "string" && TOOL_ITEM_TYPES.has(item.type)) {
245596
+ waiter.ranTool = true;
245597
+ }
245174
245598
  if (!waiter.onToolCall)
245175
245599
  return;
245176
245600
  const call2 = describeCodexToolItem(item);
@@ -245181,6 +245605,18 @@ function recordToolItem(waiter, item) {
245181
245605
  waiter.onToolCall(call2);
245182
245606
  } catch {}
245183
245607
  }
245608
+ function recordTextItem(waiter, item) {
245609
+ const id2 = readString3(item, "id");
245610
+ const { reportedText } = waiter;
245611
+ if (!waiter.onText || typeof item.text !== "string" || !item.text.trim() || id2 && reportedText.itemIds.has(id2) || waiter.textFromEarlierAttempts.has(item.text.trim()))
245612
+ return;
245613
+ if (id2)
245614
+ reportedText.itemIds.add(id2);
245615
+ reportedText.texts.add(item.text.trim());
245616
+ try {
245617
+ waiter.onText(item.text);
245618
+ } catch {}
245619
+ }
245184
245620
  function recordItem(session3, params, completed) {
245185
245621
  const turnId = readString3(params, "turnId");
245186
245622
  if (turnId !== session3.activeTurnId || !session3.activeWaiter)
@@ -245191,6 +245627,7 @@ function recordItem(session3, params, completed) {
245191
245627
  recordToolItem(session3.activeWaiter, item);
245192
245628
  if (completed && item.type === "agentMessage" && typeof item.text === "string") {
245193
245629
  session3.activeWaiter.latestAgentMessage = item.text;
245630
+ recordTextItem(session3.activeWaiter, item);
245194
245631
  }
245195
245632
  return true;
245196
245633
  }
@@ -245204,19 +245641,36 @@ function settleTurn(session3, params) {
245204
245641
  session3.activeTurnId = undefined;
245205
245642
  session3.activeWaiter = undefined;
245206
245643
  const status = readString3(turn, "status");
245207
- const failure2 = turnError(params);
245644
+ const completed = status === "completed";
245645
+ const turnError = asRecord9(turn?.error);
245646
+ const failure2 = turnFailureMessage(turnError, waiter.errors);
245208
245647
  waiter.resolve({
245209
- agentId: `codex_${session3.threadId}`,
245210
- runtimeSessionId: session3.threadId,
245211
- model: waiter.model,
245212
- report: turnReport(params) || waiter.latestAgentMessage || "",
245213
- success: status === "completed",
245214
- ...status === "completed" ? {} : { error: failure2 ?? `Codex turn ${status ?? "failed"}` },
245215
- durationMs: Date.now() - waiter.startedAt
245648
+ result: {
245649
+ agentId: `codex_${session3.threadId}`,
245650
+ runtimeSessionId: session3.threadId,
245651
+ model: waiter.model,
245652
+ report: turnReport(params) || waiter.latestAgentMessage || "",
245653
+ success: completed,
245654
+ ...completed ? {} : { error: failure2 ?? `Codex turn ${status ?? "failed"}` },
245655
+ durationMs: Date.now() - waiter.startedAt
245656
+ },
245657
+ capacityFailure: !completed && [turnError, ...waiter.errors].some((error5) => error5 !== undefined && isCapacityError(error5)),
245658
+ ranTool: waiter.ranTool,
245659
+ steered: waiter.steered
245216
245660
  });
245217
245661
  scheduleIdleSessionCleanup(session3);
245218
245662
  return true;
245219
245663
  }
245664
+ function recordError(session3, params) {
245665
+ const turnId = readString3(params, "turnId");
245666
+ if (turnId !== session3.activeTurnId || !session3.activeWaiter)
245667
+ return false;
245668
+ const error5 = asRecord9(params.error);
245669
+ if (error5 && params.willRetry !== true) {
245670
+ session3.activeWaiter.errors.push(error5);
245671
+ }
245672
+ return true;
245673
+ }
245220
245674
  function handleNotification(session3, message) {
245221
245675
  if (!message.params)
245222
245676
  return true;
@@ -245229,6 +245683,9 @@ function handleNotification(session3, message) {
245229
245683
  if (message.method === "turn/completed") {
245230
245684
  return settleTurn(session3, message.params);
245231
245685
  }
245686
+ if (message.method === "error") {
245687
+ return recordError(session3, message.params);
245688
+ }
245232
245689
  return true;
245233
245690
  }
245234
245691
  function replayPendingNotifications(session3) {
@@ -245287,8 +245744,10 @@ async function createSession(options, deps) {
245287
245744
  let session3;
245288
245745
  const pendingNotifications = [];
245289
245746
  const client = new CodexAppServerClient(transport3, (message) => {
245290
- if (!session3 || !handleNotification(session3, message)) {
245747
+ if (!session3)
245291
245748
  pendingNotifications.push(message);
245749
+ else if (!handleNotification(session3, message)) {
245750
+ session3.pendingNotifications.push(message);
245292
245751
  }
245293
245752
  }, (error5) => {
245294
245753
  if (session3)
@@ -245328,7 +245787,8 @@ async function createSession(options, deps) {
245328
245787
  model: options.model,
245329
245788
  startLock: Promise.resolve(),
245330
245789
  pendingNotifications,
245331
- idleTimeoutMs: deps.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS
245790
+ idleTimeoutMs: deps.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS,
245791
+ sleep: deps.sleep ?? sleep11
245332
245792
  };
245333
245793
  sessions2.set(threadId, session3);
245334
245794
  return session3;
@@ -245346,7 +245806,7 @@ async function withSessionLock(session3, operation) {
245346
245806
  release();
245347
245807
  }
245348
245808
  }
245349
- async function startTurnUnlocked(session3, prompt, signal, onStarted, onToolCall) {
245809
+ async function startTurnAttempt(session3, prompt, startedAt, listeners5) {
245350
245810
  if (session3.activeTurnId) {
245351
245811
  throw new Error("Codex thread already has an active turn");
245352
245812
  }
@@ -245363,34 +245823,90 @@ async function startTurnUnlocked(session3, prompt, signal, onStarted, onToolCall
245363
245823
  const turnId = readString3(turn, "id");
245364
245824
  if (!turnId)
245365
245825
  throw new Error("Codex app-server returned no native turn ID");
245366
- const completion = new Promise((resolve35) => {
245826
+ const outcome = new Promise((resolve35) => {
245367
245827
  session3.activeTurnId = turnId;
245368
245828
  session3.activeWaiter = {
245369
245829
  turnId,
245370
245830
  resolve: resolve35,
245371
- startedAt: Date.now(),
245831
+ startedAt,
245372
245832
  model: session3.model,
245373
- onToolCall,
245374
- seenToolCallIds: new Set
245833
+ onToolCall: listeners5.onToolCall,
245834
+ seenToolCallIds: new Set,
245835
+ onText: listeners5.onText,
245836
+ reportedText: listeners5.reportedText,
245837
+ textFromEarlierAttempts: new Set(listeners5.reportedText.texts),
245838
+ ranTool: false,
245839
+ steered: false,
245840
+ errors: []
245375
245841
  };
245376
245842
  });
245377
- onStarted?.(session3.threadId, turnId);
245843
+ return { turnId, outcome };
245844
+ }
245845
+ async function startTurnUnlocked(session3, prompt, signal, onStarted, { onToolCall, onText } = {}) {
245846
+ const startedAt = Date.now();
245847
+ const listeners5 = {
245848
+ onToolCall,
245849
+ onText,
245850
+ reportedText: { itemIds: new Set, texts: new Set }
245851
+ };
245852
+ const first = await startTurnAttempt(session3, prompt, startedAt, listeners5);
245853
+ let currentTurnId = first.turnId;
245854
+ let interrupted = false;
245855
+ onStarted?.(session3.threadId, first.turnId);
245378
245856
  replayPendingNotifications(session3);
245379
- const abort = () => {
245380
- session3.client.request("turn/interrupt", { threadId: session3.threadId, turnId }).catch(() => {
245381
- return;
245857
+ const interrupt = async () => {
245858
+ interrupted = true;
245859
+ await session3.client.request("turn/interrupt", {
245860
+ threadId: session3.threadId,
245861
+ turnId: currentTurnId
245382
245862
  });
245383
245863
  };
245864
+ const abort = () => void interrupt().catch(() => {
245865
+ return;
245866
+ });
245384
245867
  signal?.addEventListener("abort", abort, { once: true });
245385
245868
  if (signal?.aborted)
245386
245869
  abort();
245870
+ const completion = (async () => {
245871
+ let attempt2 = first;
245872
+ for (let retry3 = 0;; retry3++) {
245873
+ const outcome = await attempt2.outcome;
245874
+ if (!outcome.capacityFailure)
245875
+ return outcome.result;
245876
+ const delay4 = CAPACITY_RETRY_DELAYS_MS[retry3];
245877
+ const canRetry = () => !interrupted && !signal?.aborted && !outcome.ranTool && !outcome.steered;
245878
+ if (delay4 === undefined || !canRetry()) {
245879
+ return capacityResult(outcome.result);
245880
+ }
245881
+ await session3.sleep(delay4);
245882
+ if (!canRetry())
245883
+ return capacityResult(outcome.result);
245884
+ try {
245885
+ attempt2 = await withSessionLock(session3, async () => {
245886
+ const next = await startTurnAttempt(session3, prompt, startedAt, listeners5);
245887
+ currentTurnId = next.turnId;
245888
+ replayPendingNotifications(session3);
245889
+ return next;
245890
+ });
245891
+ } catch {
245892
+ return capacityResult(outcome.result);
245893
+ }
245894
+ if (interrupted || signal?.aborted)
245895
+ abort();
245896
+ }
245897
+ })();
245387
245898
  completion.finally(() => signal?.removeEventListener("abort", abort));
245388
- return { threadId: session3.threadId, turnId, completion };
245899
+ return {
245900
+ threadId: session3.threadId,
245901
+ turnId: first.turnId,
245902
+ completion,
245903
+ interrupt
245904
+ };
245389
245905
  }
245390
245906
  function startTurn(session3, options) {
245391
245907
  return withSessionLock(session3, async () => {
245392
245908
  await options.beforeStart?.(session3.threadId);
245393
- return startTurnUnlocked(session3, options.prompt, options.signal, options.onStarted, options.onToolCall);
245909
+ return startTurnUnlocked(session3, options.prompt, options.signal, options.onStarted, options);
245394
245910
  });
245395
245911
  }
245396
245912
  async function startCodexTurn(options, deps = {}) {
@@ -245428,6 +245944,9 @@ async function sendCodexMessage(options, deps = {}) {
245428
245944
  expectedTurnId: activeTurnId,
245429
245945
  input: textInput(options.prompt)
245430
245946
  });
245947
+ if (session3.activeWaiter?.turnId === activeTurnId) {
245948
+ session3.activeWaiter.steered = true;
245949
+ }
245431
245950
  return {
245432
245951
  mode: "steered",
245433
245952
  threadId: session3.threadId,
@@ -245440,12 +245959,9 @@ async function sendCodexMessage(options, deps = {}) {
245440
245959
  }
245441
245960
  options.signal?.throwIfAborted();
245442
245961
  await options.beforeStart?.(session3.threadId);
245443
- const handle2 = await startTurnUnlocked(session3, options.prompt, undefined, options.onStarted, options.onToolCall);
245962
+ const handle2 = await startTurnUnlocked(session3, options.prompt, undefined, options.onStarted, options);
245444
245963
  if (options.signal?.aborted) {
245445
- await session3.client.request("turn/interrupt", {
245446
- threadId: handle2.threadId,
245447
- turnId: handle2.turnId
245448
- });
245964
+ await handle2.interrupt();
245449
245965
  options.signal.throwIfAborted();
245450
245966
  }
245451
245967
  return {
@@ -245453,12 +245969,7 @@ async function sendCodexMessage(options, deps = {}) {
245453
245969
  threadId: handle2.threadId,
245454
245970
  turnId: handle2.turnId,
245455
245971
  completion: handle2.completion,
245456
- interrupt: async () => {
245457
- await session3.client.request("turn/interrupt", {
245458
- threadId: handle2.threadId,
245459
- turnId: handle2.turnId
245460
- });
245461
- }
245972
+ interrupt: handle2.interrupt
245462
245973
  };
245463
245974
  });
245464
245975
  } catch (error5) {
@@ -245487,6 +245998,7 @@ var init_codex_app_server = __esm(() => {
245487
245998
  init_subagent_process();
245488
245999
  init_native_cli_env();
245489
246000
  init_package_manager_spawn();
246001
+ init_codex_app_server_payloads();
245490
246002
  sessions2 = new Map;
245491
246003
  sessionCreations = new Map;
245492
246004
  DEFAULT_IDLE_TIMEOUT_MS = 5 * 60000;
@@ -246069,7 +246581,7 @@ var init_conversation_bootstrap = __esm(() => {
246069
246581
 
246070
246582
  // src/cli/helpers/session-context.ts
246071
246583
  import { platform as platform7 } from "node:os";
246072
- import { basename as basename21 } from "node:path";
246584
+ import { basename as basename22 } from "node:path";
246073
246585
  function getLocalTime() {
246074
246586
  const now2 = new Date;
246075
246587
  return now2.toLocaleString(undefined, {
@@ -246113,7 +246625,7 @@ function getGitInfo(cwd2) {
246113
246625
  };
246114
246626
  }
246115
246627
  function buildUnixShellLine(shellContext) {
246116
- const shellName = basename21(shellContext.displayName) || shellContext.displayName;
246628
+ const shellName = basename22(shellContext.displayName) || shellContext.displayName;
246117
246629
  return `- **Shell**: ${shellName}
246118
246630
  `;
246119
246631
  }
@@ -246700,7 +247212,7 @@ var init_engine3 = __esm(() => {
246700
247212
 
246701
247213
  // src/tools/impl/native-session-capture.ts
246702
247214
  import { createHash as createHash10, randomUUID as randomUUID38 } from "node:crypto";
246703
- import { readdirSync as readdirSync16, rmSync as rmSync15 } from "node:fs";
247215
+ import { readdirSync as readdirSync17, rmSync as rmSync16 } from "node:fs";
246704
247216
  import {
246705
247217
  mkdtemp as mkdtemp4,
246706
247218
  open as open4,
@@ -246754,7 +247266,7 @@ async function snapshotStableNativeSession(input) {
246754
247266
  throw new NativeSessionSourceGrowthError;
246755
247267
  }
246756
247268
  function cleanupSpoolDirectorySync(directory) {
246757
- rmSync15(directory, { recursive: true, force: true });
247269
+ rmSync16(directory, { recursive: true, force: true });
246758
247270
  spoolDirectories.delete(directory);
246759
247271
  }
246760
247272
  async function cleanupSpoolDirectory(directory) {
@@ -246771,7 +247283,7 @@ function scavengeStaleSpoolDirectories() {
246771
247283
  staleSpoolsScavenged = true;
246772
247284
  let entries;
246773
247285
  try {
246774
- entries = readdirSync16(tmpdir13(), { withFileTypes: true });
247286
+ entries = readdirSync17(tmpdir13(), { withFileTypes: true });
246775
247287
  } catch {
246776
247288
  return;
246777
247289
  }
@@ -247207,9 +247719,20 @@ function captureNativeSession(source, sessionId, scope, env6 = process.env, requ
247207
247719
  });
247208
247720
  return sealing.then(() => startDrain(state2, source, sessionId));
247209
247721
  }
247722
+ function getNativeSessionOwner(source, sessionId) {
247723
+ return owners.get(key3(source, sessionId));
247724
+ }
247210
247725
  function rememberNativeSession(source, sessionId, scope, cloudUrl = getServerUrl()) {
247211
247726
  scavengeStaleSpoolDirectories();
247212
247727
  const id2 = key3(source, sessionId);
247728
+ if (!owners.has(id2)) {
247729
+ owners.set(id2, { ...scope });
247730
+ if (owners.size > MAX_NATIVE_SESSION_OWNERS) {
247731
+ const oldest = owners.keys().next().value;
247732
+ if (oldest !== undefined)
247733
+ owners.delete(oldest);
247734
+ }
247735
+ }
247213
247736
  if (!states2.has(id2) && UUID2.test(sessionId) && isCloudServerUrl(cloudUrl))
247214
247737
  states2.set(id2, {
247215
247738
  scope: { ...scope },
@@ -247227,7 +247750,7 @@ function reportNativeSessionCaptureFailure(source, sessionId, error5) {
247227
247750
  const reason = error5 instanceof ApiRequestError ? `HTTP ${error5.status}` : error5 instanceof Error ? error5.name : "unknown error";
247228
247751
  debugWarn("native-session", `${source} ${sessionId}: upload failed (${reason})`);
247229
247752
  }
247230
- var NativeChunkAcknowledgmentError, NativeSessionSourceGrowthError, states2, admissions, spoolDirectories, captureProcessInstanceId, activeInstanceRegistryKey, activeCaptureInstances, spoolDirectoryName, staleSpoolsScavenged = false, sealHookForTests, prefixVerificationHookForTests, drainHookForTests, NATIVE_SESSION_CAPTURE_CHUNK_BYTES, INITIAL_DRAIN_RETRY_MS = 250, MAX_DRAIN_RETRY_MS = 30000, SEAL_RETRY_DELAYS_MS, UUID2;
247753
+ var NativeChunkAcknowledgmentError, NativeSessionSourceGrowthError, states2, admissions, spoolDirectories, captureProcessInstanceId, activeInstanceRegistryKey, activeCaptureInstances, spoolDirectoryName, staleSpoolsScavenged = false, sealHookForTests, prefixVerificationHookForTests, drainHookForTests, NATIVE_SESSION_CAPTURE_CHUNK_BYTES, INITIAL_DRAIN_RETRY_MS = 250, MAX_DRAIN_RETRY_MS = 30000, SEAL_RETRY_DELAYS_MS, UUID2, MAX_NATIVE_SESSION_OWNERS = 1024, owners;
247231
247754
  var init_native_session_capture = __esm(() => {
247232
247755
  init_request();
247233
247756
  init_server_url();
@@ -247265,6 +247788,7 @@ var init_native_session_capture = __esm(() => {
247265
247788
  cleanupSpoolDirectorySync(directory);
247266
247789
  }
247267
247790
  });
247791
+ owners = new Map;
247268
247792
  });
247269
247793
 
247270
247794
  // src/tools/impl/opencode-server.ts
@@ -247920,20 +248444,16 @@ async function resolveExternalCodingAgentSecretEnv(parentAgentId, lookupParent)
247920
248444
  } catch {}
247921
248445
  return { ...inherited, ...loadSecrets2(parentAgentId) };
247922
248446
  }
247923
- async function runExternalCodingAgent(options, deps = {}) {
248447
+ async function buildExternalWorkerLaunchEnv(options, deps = {}) {
247924
248448
  const parentMemoryNote = buildParentMemoryNote(options.parentAgentId);
247925
- options = {
247926
- ...options,
247927
- mcpReminder: [
247928
- parentMemoryNote ? `${SYSTEM_REMINDER_OPEN}
248449
+ const mcpReminder = [
248450
+ parentMemoryNote ? `${SYSTEM_REMINDER_OPEN}
247929
248451
  ${parentMemoryNote}
247930
248452
  ${SYSTEM_REMINDER_CLOSE}` : undefined,
247931
- options.mcpReminder
247932
- ].filter(Boolean).join(`
248453
+ options.mcpReminder
248454
+ ].filter(Boolean).join(`
247933
248455
 
247934
- `) || undefined
247935
- };
247936
- const startedAt = Date.now();
248456
+ `) || undefined;
247937
248457
  const secretEnv = await (deps.resolveSecretEnv ?? resolveExternalCodingAgentSecretEnv)(options.parentAgentId);
247938
248458
  const env6 = withNativeCliPath({
247939
248459
  ...deps.env ?? process.env,
@@ -247949,6 +248469,27 @@ ${SYSTEM_REMINDER_CLOSE}` : undefined,
247949
248469
  } else if (options.actingUserId === null || getRuntimeContext()?.suppressActingUserFallback) {
247950
248470
  delete env6[ACTING_USER_ID_ENV];
247951
248471
  }
248472
+ return { env: env6, secretEnv, mcpReminder };
248473
+ }
248474
+ async function buildExternalWorkerResumeEnv(options, deps = {}) {
248475
+ const mcpReminder = await (deps.resolveMcpReminder ?? ((parentAgentId) => resolveExternalCodingAgentMcpReminder(parentAgentId, undefined)))(options.parentAgentId).catch(() => {
248476
+ return;
248477
+ });
248478
+ return buildExternalWorkerLaunchEnv({ ...options, mcpReminder }, deps);
248479
+ }
248480
+ function scrubExternalWorkerResult(result3, secretEnv) {
248481
+ return {
248482
+ ...result3,
248483
+ report: scrubSecretsFromString(result3.report, secretEnv),
248484
+ ...result3.error !== undefined && {
248485
+ error: scrubSecretsFromString(result3.error, secretEnv)
248486
+ }
248487
+ };
248488
+ }
248489
+ async function runExternalCodingAgent(options, deps = {}) {
248490
+ const startedAt = Date.now();
248491
+ const { env: env6, secretEnv, mcpReminder } = await buildExternalWorkerLaunchEnv(options, deps);
248492
+ options = { ...options, mcpReminder };
247952
248493
  const cwd2 = options.cwd ?? getCurrentWorkingDirectory();
247953
248494
  const captureActingUserId = options.actingUserId !== undefined ? options.actingUserId : getRuntimeActingUserAttribution();
247954
248495
  const scope = options.parentConversationId ? {
@@ -247965,13 +248506,7 @@ ${SYSTEM_REMINDER_CLOSE}` : undefined,
247965
248506
  return captureReservation;
247966
248507
  };
247967
248508
  const capture = async (rawResult) => {
247968
- const result3 = {
247969
- ...rawResult,
247970
- report: scrubSecretsFromString(rawResult.report, secretEnv),
247971
- ...rawResult.error !== undefined && {
247972
- error: scrubSecretsFromString(rawResult.error, secretEnv)
247973
- }
247974
- };
248509
+ const result3 = scrubExternalWorkerResult(rawResult, secretEnv);
247975
248510
  const sessionId = result3.runtimeSessionId ?? captureSessionId;
247976
248511
  if (scope && sessionId) {
247977
248512
  try {
@@ -248029,6 +248564,7 @@ ${SYSTEM_REMINDER_CLOSE}` : undefined,
248029
248564
  signal: options.signal,
248030
248565
  resumeThreadId: options.resumeSessionId,
248031
248566
  onToolCall: options.onToolCall,
248567
+ onText: options.onText,
248032
248568
  beforeStart: async (threadId) => {
248033
248569
  if (scope && !captureReservation) {
248034
248570
  if (!options.resumeSessionId) {
@@ -248071,7 +248607,8 @@ ${SYSTEM_REMINDER_CLOSE}` : undefined,
248071
248607
  signal: options.signal,
248072
248608
  resumeSessionId: options.resumeSessionId,
248073
248609
  sessionId,
248074
- onToolCall: options.onToolCall
248610
+ onToolCall: options.onToolCall,
248611
+ onText: options.onText
248075
248612
  }, { env: env6 }));
248076
248613
  }
248077
248614
  const result3 = await (deps.runProcess ?? runProcess)(buildExternalCodingAgentCommand({ ...options, cwd: cwd2 }), { cwd: cwd2, env: env6, signal: options.signal });
@@ -248874,14 +249411,59 @@ function waitForSocketOpen(socket) {
248874
249411
  return new Promise((resolve35, reject2) => {
248875
249412
  let detachOpen = () => {};
248876
249413
  let detachError = () => {};
249414
+ let detachResponse = () => {};
249415
+ let detachBody = () => {};
248877
249416
  const cleanup = () => {
248878
249417
  detachOpen();
248879
249418
  detachError();
249419
+ detachResponse();
249420
+ detachBody();
248880
249421
  };
248881
249422
  detachOpen = onceSocketEvent(socket, "open", () => {
248882
249423
  cleanup();
248883
249424
  resolve35();
248884
249425
  });
249426
+ if (socket.on) {
249427
+ const onResponse = (_request, response) => {
249428
+ if (!response)
249429
+ return;
249430
+ const request2 = _request;
249431
+ let body3 = Buffer.alloc(0);
249432
+ let finished2 = false;
249433
+ const finish2 = () => {
249434
+ if (finished2)
249435
+ return;
249436
+ detachBody();
249437
+ const detail = body3.toString("utf8").trim();
249438
+ reject2(new Error(`App-server WebSocket failed to open: HTTP ${response.statusCode}${detail ? `: ${detail}` : ""}`));
249439
+ detachOpen();
249440
+ detachResponse();
249441
+ request2.once("close", cleanup);
249442
+ request2.abort();
249443
+ };
249444
+ const onData = (chunk2) => {
249445
+ const bytes = Buffer.isBuffer(chunk2) ? chunk2 : Buffer.from(chunk2);
249446
+ body3 = Buffer.concat([body3, bytes.subarray(0, 2048 - body3.length)]);
249447
+ if (body3.length >= 2048)
249448
+ finish2();
249449
+ };
249450
+ const timeout = setTimeout(finish2, 1000);
249451
+ detachBody = () => {
249452
+ finished2 = true;
249453
+ clearTimeout(timeout);
249454
+ response.off("data", onData);
249455
+ response.off("end", finish2);
249456
+ response.off("error", finish2);
249457
+ response.off("close", finish2);
249458
+ };
249459
+ response.on("data", onData);
249460
+ response.on("end", finish2);
249461
+ response.on("error", finish2);
249462
+ response.on("close", finish2);
249463
+ };
249464
+ socket.on("unexpected-response", onResponse);
249465
+ detachResponse = () => socket.off?.("unexpected-response", onResponse);
249466
+ }
248885
249467
  detachError = onceSocketEvent(socket, "error", (event) => {
248886
249468
  cleanup();
248887
249469
  reject2(new Error(`App-server WebSocket failed to open: ${String(event)}`));
@@ -250116,7 +250698,7 @@ var init_subagent_launcher = __esm(async () => {
250116
250698
  });
250117
250699
 
250118
250700
  // src/agent/subagents/manager.ts
250119
- import { rmSync as rmSync16 } from "node:fs";
250701
+ import { rmSync as rmSync17 } from "node:fs";
250120
250702
  import { platform as platform8 } from "node:os";
250121
250703
  function isProviderNotSupportedError(errorOutput) {
250122
250704
  return errorOutput.includes("Provider") && errorOutput.includes("is not supported") && errorOutput.includes("supported providers:");
@@ -250333,7 +250915,7 @@ async function executeSubagent(type3, config2, model, userPrompt, subagentId, is
250333
250915
  const { exitCode, exitSignal } = await runningProcess.completion;
250334
250916
  if (effectiveLaunchProfile === "memory-subagent" && !parentProcessEnv.LETTA_SCRATCHPAD?.trim() && childEnv.LETTA_SCRATCHPAD) {
250335
250917
  try {
250336
- rmSync16(childEnv.LETTA_SCRATCHPAD, { recursive: true, force: true });
250918
+ rmSync17(childEnv.LETTA_SCRATCHPAD, { recursive: true, force: true });
250337
250919
  } catch (error5) {
250338
250920
  debugWarn("subagent", `Failed to clean up memory-subagent scratchpad: ${getErrorMessage2(error5)}`);
250339
250921
  }
@@ -251029,6 +251611,112 @@ var init_memory_task_lifecycle = __esm(() => {
251029
251611
  init_process_manager();
251030
251612
  });
251031
251613
 
251614
+ // src/tools/impl/task-transcript.ts
251615
+ function buildTaskResultHeader(subagentType, subagentId, result3, status) {
251616
+ return [
251617
+ `subagent_type=${subagentType}`,
251618
+ `subagent_id=${subagentId}`,
251619
+ status ? `subagent_status=${status}` : undefined,
251620
+ result3?.agentId ? `agent_id=${result3.agentId}` : undefined,
251621
+ result3?.conversationId ? `conversation_id=${result3.conversationId}` : undefined,
251622
+ result3?.runtimeSessionId ? `runtime_session_id=${result3.runtimeSessionId}` : undefined
251623
+ ].filter(Boolean).join(" ");
251624
+ }
251625
+ function writeTaskTranscriptStart(outputFile, description, subagentType) {
251626
+ appendToOutputFile(outputFile, `[Task started: ${description}]
251627
+ [subagent_type: ${subagentType}]
251628
+
251629
+ `);
251630
+ }
251631
+ function writeTaskTranscriptResult(outputFile, result3, header, reportAlreadyWritten = false) {
251632
+ if (result3.success) {
251633
+ const report = reportAlreadyWritten ? "" : `${result3.report}
251634
+
251635
+ `;
251636
+ appendToOutputFile(outputFile, `${header}
251637
+
251638
+ ${report}[Task completed]
251639
+ `);
251640
+ return;
251641
+ }
251642
+ appendToOutputFile(outputFile, `${header ? `${header}
251643
+
251644
+ ` : ""}[error] ${result3.error || "Subagent execution failed"}
251645
+
251646
+ [Task failed]
251647
+ `);
251648
+ }
251649
+ function appendProgress(log3, entry, at2) {
251650
+ if (log3.lines >= TASK_PROGRESS_MAX_LINES)
251651
+ return;
251652
+ log3.lines++;
251653
+ const line = log3.lines === TASK_PROGRESS_MAX_LINES ? `[progress log reached ${TASK_PROGRESS_MAX_LINES} lines; further progress omitted]` : `[${at2 ?? log3.now().toISOString()}] ${entry}`;
251654
+ appendToOutputFile(log3.outputFile, `${line}
251655
+ `);
251656
+ }
251657
+ function openTaskProgressLog(subagentId, outputFile, now2 = () => new Date) {
251658
+ progressLogs.set(subagentId, {
251659
+ outputFile,
251660
+ lines: 0,
251661
+ seenToolCallIds: new Set,
251662
+ seenTextIds: new Set,
251663
+ now: now2
251664
+ });
251665
+ }
251666
+ function closeTaskProgressLog(subagentId) {
251667
+ progressLogs.delete(subagentId);
251668
+ }
251669
+ function recordTaskProgressToolCall(subagentId, call2) {
251670
+ const log3 = progressLogs.get(subagentId);
251671
+ if (!log3 || log3.seenToolCallIds.has(call2.id))
251672
+ return;
251673
+ log3.seenToolCallIds.add(call2.id);
251674
+ log3.lastText = undefined;
251675
+ const args = excerptProgressText(call2.args, TASK_PROGRESS_ARGS_CHARS);
251676
+ appendProgress(log3, `tool: ${call2.name}${args ? ` ${args}` : ""}`);
251677
+ }
251678
+ function recordTaskProgressText(subagentId, text2) {
251679
+ const log3 = progressLogs.get(subagentId);
251680
+ if (!log3)
251681
+ return;
251682
+ const line = excerptProgressText(text2, TASK_PROGRESS_TEXT_CHARS);
251683
+ if (!line || line === log3.lastText)
251684
+ return;
251685
+ log3.lastText = line;
251686
+ appendProgress(log3, `text: ${line}`);
251687
+ }
251688
+ function recordTaskProgressRemoteText(subagentId, entry) {
251689
+ const log3 = progressLogs.get(subagentId);
251690
+ if (!log3 || log3.seenTextIds.has(entry.id))
251691
+ return;
251692
+ log3.seenTextIds.add(entry.id);
251693
+ const line = excerptProgressText(entry.text, TASK_PROGRESS_TEXT_CHARS);
251694
+ if (!line)
251695
+ return;
251696
+ log3.lastText = line;
251697
+ const at2 = Number.isNaN(Date.parse(entry.at)) ? undefined : new Date(entry.at).toISOString();
251698
+ appendProgress(log3, `text: ${line}`, at2);
251699
+ }
251700
+ function externalWorkerProgressListeners(subagentId) {
251701
+ return {
251702
+ onToolCall: (call2) => {
251703
+ addToolCall(subagentId, call2.id, call2.name, call2.args);
251704
+ recordTaskProgressToolCall(subagentId, call2);
251705
+ },
251706
+ onText: (text2) => {
251707
+ addProgressText(subagentId, text2);
251708
+ recordTaskProgressText(subagentId, text2);
251709
+ }
251710
+ };
251711
+ }
251712
+ var TASK_PROGRESS_TEXT_CHARS, TASK_PROGRESS_ARGS_CHARS = 200, TASK_PROGRESS_MAX_LINES = 1000, progressLogs;
251713
+ var init_task_transcript = __esm(() => {
251714
+ init_subagent_state();
251715
+ init_process_manager();
251716
+ TASK_PROGRESS_TEXT_CHARS = PROGRESS_TEXT_CHARS;
251717
+ progressLogs = new Map;
251718
+ });
251719
+
251032
251720
  // src/tools/impl/remote-external-coding-agent.ts
251033
251721
  import { randomUUID as randomUUID44 } from "node:crypto";
251034
251722
  import WebSocket6 from "ws";
@@ -251134,6 +251822,9 @@ class RemoteSubagentFollower {
251134
251822
  markLaunched() {
251135
251823
  this.launched = true;
251136
251824
  }
251825
+ latestAgentId() {
251826
+ return this.latest?.agent_id ?? undefined;
251827
+ }
251137
251828
  async waitForAgentId(timeoutMs) {
251138
251829
  const deadline = Date.now() + timeoutMs;
251139
251830
  while (Date.now() < deadline) {
@@ -251160,6 +251851,7 @@ class RemoteSubagentFollower {
251160
251851
  const onAbort = () => this.wake.resolve();
251161
251852
  signal?.addEventListener("abort", onAbort, { once: true });
251162
251853
  let failedReconnects = 0;
251854
+ let disconnectedSince;
251163
251855
  try {
251164
251856
  while (true) {
251165
251857
  signal?.throwIfAborted();
@@ -251173,8 +251865,20 @@ class RemoteSubagentFollower {
251173
251865
  if (latest)
251174
251866
  onProgress(latest);
251175
251867
  if (this.disconnected) {
251176
- await new Promise((resolve36) => setTimeout(resolve36, this.reconnectDelayMs * (failedReconnects + 1)));
251868
+ disconnectedSince ??= Date.now();
251869
+ const offlineSince = disconnectedSince;
251870
+ this.wake = Promise.withResolvers();
251871
+ let timer;
251872
+ await Promise.race([
251873
+ this.wake.promise,
251874
+ new Promise((resolve36) => {
251875
+ timer = setTimeout(resolve36, Math.min(this.reconnectDelayMs * (failedReconnects + 1), MAX_RECONNECT_DELAY_MS));
251876
+ })
251877
+ ]);
251878
+ clearTimeout(timer);
251177
251879
  signal?.throwIfAborted();
251880
+ if (this.closed)
251881
+ throw new Error("Stopped following the subagent");
251178
251882
  try {
251179
251883
  const client = await this.connect();
251180
251884
  this.attach(client);
@@ -251186,8 +251890,10 @@ class RemoteSubagentFollower {
251186
251890
  recover_approvals: false
251187
251891
  });
251188
251892
  failedReconnects = 0;
251893
+ disconnectedSince = undefined;
251189
251894
  } catch (error5) {
251190
- if (++failedReconnects >= 5)
251895
+ failedReconnects++;
251896
+ if (Date.now() - offlineSince >= DEFAULT_PUBLISHED_RESULT_RETENTION_MS)
251191
251897
  throw new Error(`Lost connection: ${errorMessage4(error5)}`);
251192
251898
  }
251193
251899
  continue;
@@ -251266,9 +251972,13 @@ async function launchRemoteExternalCodingAgent(params, deps) {
251266
251972
  };
251267
251973
  }
251268
251974
  follower.markLaunched();
251269
- const nativeAgentId = supportsSteering ? await follower.waitForAgentId(deps.agentIdWaitMs ?? 2000) : null;
251270
- const parsedNativeAgentId = nativeAgentId ? parseExternalCodingAgentId(nativeAgentId) : null;
251271
- const qualifiedAgentId = parsedNativeAgentId && !parsedNativeAgentId.computer ? formatExternalCodingAgentId(parsedNativeAgentId.type, parsedNativeAgentId.sessionId, deviceId) : null;
251975
+ const qualify = (nativeAgentId) => {
251976
+ const parsed = nativeAgentId ? parseExternalCodingAgentId(nativeAgentId) : null;
251977
+ return parsed && !parsed.computer ? formatExternalCodingAgentId(parsed.type, parsed.sessionId, deviceId) : null;
251978
+ };
251979
+ const launchedAgentId = qualify(launched.agent_id);
251980
+ const qualifiedAgentId = supportsSteering ? launchedAgentId ?? qualify(await follower.waitForAgentId(deps.agentIdWaitMs ?? 2000)) : null;
251981
+ const workerAgentId = () => qualify(follower.latestAgentId()) ?? qualifiedAgentId ?? launchedAgentId ?? "";
251272
251982
  const { taskId, outputFile, subagentId } = deps.spawn({
251273
251983
  subagentType: type3,
251274
251984
  config: createExternalCodingAgentConfig(type3),
@@ -251281,13 +251991,30 @@ async function launchRemoteExternalCodingAgent(params, deps) {
251281
251991
  spawnSubagentImpl: async (_type, _prompt, model, subagentId2, signal) => {
251282
251992
  const startedAt = Date.now();
251283
251993
  updateSubagent(subagentId2, { status: "running" });
251994
+ const recordProgress = (snapshot2) => {
251995
+ for (const call2 of snapshot2.tool_calls ?? [])
251996
+ recordTaskProgressToolCall(subagentId2, call2);
251997
+ const texts = Array.isArray(snapshot2.progress_texts) ? snapshot2.progress_texts : [];
251998
+ for (const entry of texts) {
251999
+ if (typeof entry?.id === "string" && typeof entry.text === "string")
252000
+ recordTaskProgressRemoteText(subagentId2, {
252001
+ id: entry.id,
252002
+ at: typeof entry.at === "string" ? entry.at : "",
252003
+ text: entry.text
252004
+ });
252005
+ }
252006
+ };
251284
252007
  try {
251285
- const final = await follower.waitForTerminal(signal, (snapshot2) => updateSubagent(subagentId2, {
251286
- toolCalls: snapshot2.tool_calls,
251287
- totalTokens: snapshot2.total_tokens
251288
- }));
252008
+ const final = await follower.waitForTerminal(signal, (snapshot2) => {
252009
+ updateSubagent(subagentId2, {
252010
+ toolCalls: snapshot2.tool_calls,
252011
+ totalTokens: snapshot2.total_tokens
252012
+ });
252013
+ recordProgress(snapshot2);
252014
+ });
252015
+ recordProgress(final);
251289
252016
  return {
251290
- agentId: qualifiedAgentId ?? parentScope.agentId,
252017
+ agentId: workerAgentId(),
251291
252018
  model: final.model ?? model,
251292
252019
  report: final.result ?? "",
251293
252020
  success: final.status === "completed",
@@ -251298,7 +252025,7 @@ async function launchRemoteExternalCodingAgent(params, deps) {
251298
252025
  } catch (error5) {
251299
252026
  const remoteWorkerStopped = signal?.reason === REMOTE_EXTERNAL_WORKER_STOPPED;
251300
252027
  return {
251301
- agentId: parentScope.agentId,
252028
+ agentId: workerAgentId(),
251302
252029
  model,
251303
252030
  report: "",
251304
252031
  success: false,
@@ -251447,7 +252174,7 @@ async function sendRemoteExternalCodingAgentMessage(params, deps = {}) {
251447
252174
  outputFile: tracked.outputFile
251448
252175
  };
251449
252176
  }
251450
- var REMOTE_EXTERNAL_WORKER_STOPPED, DISPLAY_NAMES, RemoteWorkerLostError;
252177
+ var REMOTE_EXTERNAL_WORKER_STOPPED, DISPLAY_NAMES, RemoteWorkerLostError, MAX_RECONNECT_DELAY_MS = 30000;
251451
252178
  var init_remote_external_coding_agent = __esm(() => {
251452
252179
  init_subagent_state();
251453
252180
  init_app_server_client();
@@ -251457,6 +252184,7 @@ var init_remote_external_coding_agent = __esm(() => {
251457
252184
  init_headless_environment_response();
251458
252185
  init_headless_listener_launch();
251459
252186
  init_external_coding_agent();
252187
+ init_task_transcript();
251460
252188
  REMOTE_EXTERNAL_WORKER_STOPPED = Symbol("remote external worker stopped");
251461
252189
  DISPLAY_NAMES = {
251462
252190
  "claude-code": "Claude Code",
@@ -251695,45 +252423,6 @@ var init_task_abort_hook = __esm(() => {
251695
252423
  init_process_manager();
251696
252424
  });
251697
252425
 
251698
- // src/tools/impl/task-transcript.ts
251699
- function buildTaskResultHeader(subagentType, subagentId, result3, status) {
251700
- return [
251701
- `subagent_type=${subagentType}`,
251702
- `subagent_id=${subagentId}`,
251703
- status ? `subagent_status=${status}` : undefined,
251704
- result3?.agentId ? `agent_id=${result3.agentId}` : undefined,
251705
- result3?.conversationId ? `conversation_id=${result3.conversationId}` : undefined,
251706
- result3?.runtimeSessionId ? `runtime_session_id=${result3.runtimeSessionId}` : undefined
251707
- ].filter(Boolean).join(" ");
251708
- }
251709
- function writeTaskTranscriptStart(outputFile, description, subagentType) {
251710
- appendToOutputFile(outputFile, `[Task started: ${description}]
251711
- [subagent_type: ${subagentType}]
251712
-
251713
- `);
251714
- }
251715
- function writeTaskTranscriptResult(outputFile, result3, header, reportAlreadyWritten = false) {
251716
- if (result3.success) {
251717
- const report = reportAlreadyWritten ? "" : `${result3.report}
251718
-
251719
- `;
251720
- appendToOutputFile(outputFile, `${header}
251721
-
251722
- ${report}[Task completed]
251723
- `);
251724
- return;
251725
- }
251726
- appendToOutputFile(outputFile, `${header ? `${header}
251727
-
251728
- ` : ""}[error] ${result3.error || "Subagent execution failed"}
251729
-
251730
- [Task failed]
251731
- `);
251732
- }
251733
- var init_task_transcript = __esm(() => {
251734
- init_process_manager();
251735
- });
251736
-
251737
252426
  // src/tools/impl/task.ts
251738
252427
  var exports_task = {};
251739
252428
  __export(exports_task, {
@@ -251819,6 +252508,7 @@ function spawnBackgroundSubagentTask(args) {
251819
252508
  backgroundTasks.set(taskId, bgTask);
251820
252509
  registerSubagentAbortHook(subagentId, buildBackgroundTaskAbortHook(taskId, abortController));
251821
252510
  writeTaskTranscriptStart(outputFile, description, subagentType);
252511
+ openTaskProgressLog(subagentId, outputFile);
251822
252512
  const parentAgentIdForSpawn = resolvedParentScope?.agentId;
251823
252513
  const workerMemoryDir = subagentType === "memory" && resolvedParentScope ? memoryScope?.primaryRoot ?? getScopedMemoryFilesystemRoot(resolvedParentScope.agentId) : undefined;
251824
252514
  const effectiveMemoryScope = memoryScope ?? (workerMemoryDir ? { primaryRoot: workerMemoryDir, writableRoots: [workerMemoryDir] } : undefined);
@@ -251841,6 +252531,7 @@ function spawnBackgroundSubagentTask(args) {
251841
252531
  const unsubscribe = memoryTask?.unsubscribe ?? (() => {});
251842
252532
  const subagentExecution = memoryTask?.execution ?? (subagentType === "memory" ? Promise.reject(new Error("Memory tasks require a parent conversation scope")) : execute());
251843
252533
  const taskLifecycle = subagentExecution.then(async (result3) => {
252534
+ closeTaskProgressLog(subagentId);
251844
252535
  await copyGitHubPullRequestTagsFn(result3.conversationId, resolvedParentScope?.conversationId);
251845
252536
  bgTask.status = result3.success ? "completed" : "failed";
251846
252537
  if (result3.error) {
@@ -251854,6 +252545,7 @@ function spawnBackgroundSubagentTask(args) {
251854
252545
  success: result3.success,
251855
252546
  error: result3.error,
251856
252547
  totalTokens: result3.totalTokens,
252548
+ ...publishResult ? { published: true } : {},
251857
252549
  ...publishResult && result3.success ? {
251858
252550
  result: truncateByChars(result3.report || "", LIMITS.TASK_OUTPUT_CHARS, "Task", { workingDirectory: getCurrentWorkingDirectory() }).content
251859
252551
  } : {}
@@ -251904,11 +252596,13 @@ Error: ${result3.error || "Subagent execution failed"}`;
251904
252596
  text: notificationXml,
251905
252597
  agentId: resolvedParentScope?.agentId,
251906
252598
  conversationId: resolvedParentScope?.conversationId,
251907
- actingUserId: bgTask.actingUserId
252599
+ actingUserId: bgTask.actingUserId,
252600
+ clientMessageIds: resolvedParentScope?.clientMessageIds
251908
252601
  });
251909
252602
  }
251910
252603
  runSubagentStopHooksFn(subagentType, subagentId, result3.success, result3.error, result3.agentId, result3.conversationId).catch(() => {});
251911
252604
  }).catch(async (error5) => {
252605
+ closeTaskProgressLog(subagentId);
251912
252606
  const errorMessage5 = error5 instanceof Error ? error5.message : String(error5);
251913
252607
  bgTask.status = "failed";
251914
252608
  bgTask.error = errorMessage5;
@@ -251918,7 +252612,11 @@ Error: ${result3.error || "Subagent execution failed"}`;
251918
252612
  `);
251919
252613
  scheduleBackgroundTaskCleanup(taskId);
251920
252614
  clearSubagentAbortHook(subagentId);
251921
- completeSubagentFn(subagentId, { success: false, error: errorMessage5 });
252615
+ completeSubagentFn(subagentId, {
252616
+ success: false,
252617
+ error: errorMessage5,
252618
+ ...publishResult ? { published: true } : {}
252619
+ });
251922
252620
  try {
251923
252621
  await onComplete?.({
251924
252622
  success: false,
@@ -251959,7 +252657,8 @@ Error: ${errorMessage5}`,
251959
252657
  text: notificationXml,
251960
252658
  agentId: resolvedParentScope?.agentId,
251961
252659
  conversationId: resolvedParentScope?.conversationId,
251962
- actingUserId: bgTask.actingUserId
252660
+ actingUserId: bgTask.actingUserId,
252661
+ clientMessageIds: resolvedParentScope?.clientMessageIds
251963
252662
  });
251964
252663
  }
251965
252664
  runSubagentStopHooksFn(subagentType, subagentId, false, errorMessage5, existingAgentId, existingConversationId).catch(() => {});
@@ -252103,7 +252802,7 @@ async function launchSubagent(args) {
252103
252802
  parentScope: resolvedParentScope,
252104
252803
  ...callerNotification,
252105
252804
  deps: {
252106
- spawnSubagentImpl: async (_type, prompt2, model2, _subagentId, childSignal) => runExternalCodingAgent({
252805
+ spawnSubagentImpl: async (_type, prompt2, model2, workerSubagentId, childSignal) => runExternalCodingAgent({
252107
252806
  type: externalCodingAgentType,
252108
252807
  prompt: prompt2,
252109
252808
  model: model2,
@@ -252114,7 +252813,7 @@ async function launchSubagent(args) {
252114
252813
  mcpReminder,
252115
252814
  signal: childSignal,
252116
252815
  onStarted: (agentId2) => updateSubagent(subagentId2, { agentId: agentId2, status: "running" }),
252117
- onToolCall: (c) => addToolCall(subagentId2, c.id, c.name, c.args)
252816
+ ...externalWorkerProgressListeners(workerSubagentId)
252118
252817
  })
252119
252818
  }
252120
252819
  });
@@ -252338,10 +253037,10 @@ function trackExternalFollowupCompletion(args) {
252338
253037
  });
252339
253038
  }
252340
253039
  var init_external_coding_agent_task = __esm(async () => {
252341
- init_subagent_state();
252342
253040
  init_runtime_context();
252343
253041
  init_external_coding_agent();
252344
253042
  init_native_session_capture();
253043
+ init_task_transcript();
252345
253044
  await init_task();
252346
253045
  });
252347
253046
 
@@ -252478,6 +253177,10 @@ async function send_agent_message(args, deps = {}) {
252478
253177
  throw error5;
252479
253178
  }
252480
253179
  }
253180
+ const worker = await buildExternalWorkerResumeEnv({
253181
+ parentAgentId: parentScope.agentId,
253182
+ actingUserId: getRuntimeActingUserAttribution()
253183
+ }, deps.workerEnv);
252481
253184
  if (externalTarget.type === "codex") {
252482
253185
  let captureReservation2;
252483
253186
  let receipt3;
@@ -252487,6 +253190,7 @@ async function send_agent_message(args, deps = {}) {
252487
253190
  prompt: args.message,
252488
253191
  parentAgentId: parentScope.agentId,
252489
253192
  cwd: getCurrentWorkingDirectory(),
253193
+ mcpReminder: worker.mcpReminder,
252490
253194
  signal: args.signal,
252491
253195
  beforeStart: async () => {
252492
253196
  captureReservation2 = await reserveNativeSessionCapture("codex", externalTarget.sessionId, {
@@ -252494,7 +253198,7 @@ async function send_agent_message(args, deps = {}) {
252494
253198
  actingUserId: getRuntimeActingUserAttribution()
252495
253199
  });
252496
253200
  }
252497
- });
253201
+ }, { env: worker.env });
252498
253202
  } catch (error5) {
252499
253203
  await finishFailedNativeStartCapture(captureReservation2, "codex", externalTarget.sessionId);
252500
253204
  throw error5;
@@ -252513,6 +253217,7 @@ async function send_agent_message(args, deps = {}) {
252513
253217
  if (!receipt3.completion || !receipt3.interrupt) {
252514
253218
  throw new Error("Codex turn/start returned an incomplete background-task receipt");
252515
253219
  }
253220
+ const completion2 = receipt3.completion.then((result3) => scrubExternalWorkerResult(result3, worker.secretEnv));
252516
253221
  let taskReceipt2;
252517
253222
  try {
252518
253223
  taskReceipt2 = (deps.trackExternalFollowup ?? trackExternalFollowupCompletion)({
@@ -252523,7 +253228,7 @@ async function send_agent_message(args, deps = {}) {
252523
253228
  ...parentScope,
252524
253229
  actingUserId: getRuntimeActingUserAttribution()
252525
253230
  },
252526
- completion: receipt3.completion,
253231
+ completion: completion2,
252527
253232
  interrupt: receipt3.interrupt,
252528
253233
  captureReservation: captureReservation2
252529
253234
  });
@@ -252531,7 +253236,7 @@ async function send_agent_message(args, deps = {}) {
252531
253236
  await receipt3.interrupt().catch(() => {
252532
253237
  return;
252533
253238
  });
252534
- finishUntrackedNativeCapture(receipt3.completion, captureReservation2, "codex", externalTarget.sessionId);
253239
+ finishUntrackedNativeCapture(completion2, captureReservation2, "codex", externalTarget.sessionId);
252535
253240
  throw error5;
252536
253241
  }
252537
253242
  return {
@@ -252554,6 +253259,7 @@ async function send_agent_message(args, deps = {}) {
252554
253259
  prompt: args.message,
252555
253260
  parentAgentId: parentScope.agentId,
252556
253261
  cwd: getCurrentWorkingDirectory(),
253262
+ mcpReminder: worker.mcpReminder,
252557
253263
  signal: args.signal,
252558
253264
  beforeStart: async () => {
252559
253265
  captureReservation = await reserveNativeSessionCapture("claude_code", externalTarget.sessionId, {
@@ -252561,7 +253267,7 @@ async function send_agent_message(args, deps = {}) {
252561
253267
  actingUserId: getRuntimeActingUserAttribution()
252562
253268
  });
252563
253269
  }
252564
- });
253270
+ }, { env: worker.env });
252565
253271
  } catch (error5) {
252566
253272
  await finishFailedNativeStartCapture(captureReservation, "claude_code", externalTarget.sessionId);
252567
253273
  throw error5;
@@ -252579,6 +253285,7 @@ async function send_agent_message(args, deps = {}) {
252579
253285
  if (!receipt2.completion || !receipt2.interrupt) {
252580
253286
  throw new Error("Claude resume returned an incomplete background-task receipt");
252581
253287
  }
253288
+ const completion = receipt2.completion.then((result3) => scrubExternalWorkerResult(result3, worker.secretEnv));
252582
253289
  let taskReceipt;
252583
253290
  try {
252584
253291
  taskReceipt = (deps.trackExternalFollowup ?? trackExternalFollowupCompletion)({
@@ -252589,7 +253296,7 @@ async function send_agent_message(args, deps = {}) {
252589
253296
  ...parentScope,
252590
253297
  actingUserId: getRuntimeActingUserAttribution()
252591
253298
  },
252592
- completion: receipt2.completion,
253299
+ completion,
252593
253300
  interrupt: receipt2.interrupt,
252594
253301
  captureReservation
252595
253302
  });
@@ -252597,7 +253304,7 @@ async function send_agent_message(args, deps = {}) {
252597
253304
  await receipt2.interrupt().catch(() => {
252598
253305
  return;
252599
253306
  });
252600
- finishUntrackedNativeCapture(receipt2.completion, captureReservation, "claude_code", externalTarget.sessionId);
253307
+ finishUntrackedNativeCapture(completion, captureReservation, "claude_code", externalTarget.sessionId);
252601
253308
  throw error5;
252602
253309
  }
252603
253310
  return {
@@ -252801,7 +253508,7 @@ __export(exports_skill, {
252801
253508
  loadRenderedSkillContent: () => loadRenderedSkillContent,
252802
253509
  getResolvedSkillsDir: () => getResolvedSkillsDir
252803
253510
  });
252804
- import { existsSync as existsSync47, readdirSync as readdirSync17 } from "node:fs";
253511
+ import { existsSync as existsSync47, readdirSync as readdirSync18 } from "node:fs";
252805
253512
  import { readFile as readFile19 } from "node:fs/promises";
252806
253513
  import { dirname as dirname30, join as join70 } from "node:path";
252807
253514
  async function readSkillFromRoot(skillsRoot, skillId) {
@@ -252840,7 +253547,7 @@ function listSkillResources(skillMdPath) {
252840
253547
  function walk3(directory, relativeDirectory) {
252841
253548
  let entries2;
252842
253549
  try {
252843
- entries2 = readdirSync17(directory, { withFileTypes: true });
253550
+ entries2 = readdirSync18(directory, { withFileTypes: true });
252844
253551
  } catch {
252845
253552
  return;
252846
253553
  }
@@ -254179,7 +254886,7 @@ var init_github_pull_request_watch = __esm(() => {
254179
254886
  });
254180
254887
 
254181
254888
  // src/tools/impl/watch-pr.ts
254182
- import { rmSync as rmSync17 } from "node:fs";
254889
+ import { rmSync as rmSync18 } from "node:fs";
254183
254890
  import { setTimeout as delay5 } from "node:timers/promises";
254184
254891
  function errorText(error5) {
254185
254892
  const message2 = error5 instanceof Error ? error5.message : String(error5);
@@ -254212,7 +254919,7 @@ async function watch_pr(args, deps = {}) {
254212
254919
  if (!output.append(`[initial snapshot]
254213
254920
  ${describeGitHubPullRequestSnapshot(initial2)}
254214
254921
  `)) {
254215
- rmSync17(outputFile, { force: true });
254922
+ rmSync18(outputFile, { force: true });
254216
254923
  throw new Error(`WatchPR could not write its output file: ${outputFile}`);
254217
254924
  }
254218
254925
  const runtimeContext = getRuntimeContext();
@@ -255345,7 +256052,8 @@ ${result3}
255345
256052
  }),
255346
256053
  agentId: scope?.agentId,
255347
256054
  conversationId: scope?.conversationId,
255348
- actingUserId: scope?.actingUserId
256055
+ actingUserId: scope?.actingUserId,
256056
+ clientMessageIds: scope?.clientMessageIds
255349
256057
  });
255350
256058
  };
255351
256059
  executeWorkflow(handle2.spawner, {
@@ -255866,12 +256574,12 @@ var init_Monitor2 = __esm(() => {
255866
256574
  type: "number",
255867
256575
  minimum: 1000,
255868
256576
  default: 300000,
255869
- description: "Kill the monitor after this deadline. Default 300000ms. Maximum is LETTA_MONITOR_MAX_TIMEOUT_MS (default 3600000ms, clamped to 1 hour through 7 days). Ignored when persistent is true."
256577
+ description: "Kill the monitor after this deadline. Default 300000ms. Maximum {{MONITOR_MAX_TIMEOUT}}. Ignored when persistent is true."
255870
256578
  },
255871
256579
  persistent: {
255872
256580
  type: "boolean",
255873
256581
  default: false,
255874
- description: "Run until TaskStop or session end. In managed Cloud sandboxes, the configured monitor cap still applies (default 1 hour); elsewhere there is no timeout. Call Monitor again to re-arm it. For much longer waits in Cloud, use Wake/cron."
256582
+ description: "Run until TaskStop or session end. In managed Cloud sandboxes, it still stops after {{MONITOR_MAX_TIMEOUT}} (this sandbox's monitor cap); elsewhere there is no timeout. Call Monitor again to re-arm it. For much longer waits in Cloud, use Wake/cron."
255875
256583
  },
255876
256584
  backup_after_seconds: {
255877
256585
  type: "integer",
@@ -256322,7 +257030,7 @@ var init_Wake2 = __esm(() => {
256322
257030
  prompt: {
256323
257031
  type: "string",
256324
257032
  maxLength: 4000,
256325
- description: "Instruction your future turn should act on. Required for create."
257033
+ description: "Note to your future self: what you are waiting on, what you planned and why, and what to check before acting. Required for create."
256326
257034
  },
256327
257035
  after_seconds: {
256328
257036
  type: "integer",
@@ -256544,6 +257252,7 @@ var init_tool_definitions = __esm(async () => {
256544
257252
  init_grep();
256545
257253
  init_ls();
256546
257254
  init_memory5();
257255
+ init_monitor_timeout();
256547
257256
  init_skill();
256548
257257
  init_task_create();
256549
257258
  init_task_get();
@@ -256652,13 +257361,13 @@ ${WINDOWS_UNIFIED_EXEC_GUIDANCE}`;
256652
257361
  impl: task_stop
256653
257362
  }),
256654
257363
  Monitor: defineTool({
256655
- schema: Monitor_default2,
256656
- description: Monitor_default.trim(),
257364
+ schema: JSON.parse(applyMonitorMaxTimeout(JSON.stringify(Monitor_default2))),
257365
+ description: applyMonitorMaxTimeout(Monitor_default.trim()),
256657
257366
  impl: monitor
256658
257367
  }),
256659
257368
  WatchPR: defineTool({
256660
257369
  schema: WatchPR_default2,
256661
- description: WatchPR_default.trim(),
257370
+ description: applyMonitorMaxTimeout(WatchPR_default.trim()),
256662
257371
  impl: watch_pr
256663
257372
  }),
256664
257373
  Read: defineTool({
@@ -257051,9 +257760,9 @@ import { createHash as createHash12, randomUUID as randomUUID46 } from "node:cry
257051
257760
  import {
257052
257761
  existsSync as existsSync49,
257053
257762
  mkdirSync as mkdirSync36,
257054
- readdirSync as readdirSync18,
257763
+ readdirSync as readdirSync19,
257055
257764
  readFileSync as readFileSync40,
257056
- rmSync as rmSync18,
257765
+ rmSync as rmSync19,
257057
257766
  statSync as statSync20,
257058
257767
  writeFileSync as writeFileSync31
257059
257768
  } from "node:fs";
@@ -257096,7 +257805,7 @@ function createRecoveryLineageSidecarAccess(params) {
257096
257805
  renameSyncWithRetry(temporary, destination);
257097
257806
  params.syncDirectory(params.directory);
257098
257807
  } finally {
257099
- rmSync18(temporary, { force: true });
257808
+ rmSync19(temporary, { force: true });
257100
257809
  }
257101
257810
  };
257102
257811
  const retire = (current, existing) => {
@@ -257314,7 +258023,7 @@ function createRecoveryLineageSidecarAccess(params) {
257314
258023
  };
257315
258024
  };
257316
258025
  const remove2 = (sidecar) => {
257317
- rmSync18(path33(sidecar.agentId, sidecar.conversationId, sidecar.lineageId), {
258026
+ rmSync19(path33(sidecar.agentId, sidecar.conversationId, sidecar.lineageId), {
257318
258027
  force: true
257319
258028
  });
257320
258029
  params.syncDirectory(params.directory);
@@ -257346,12 +258055,12 @@ function createRecoveryLineageSidecarAccess(params) {
257346
258055
  if (!mainFile || existsSync49(join74(params.directory, mainFile)))
257347
258056
  return;
257348
258057
  try {
257349
- rmSync18(join74(params.directory, file), { force: true });
258058
+ rmSync19(join74(params.directory, file), { force: true });
257350
258059
  params.syncDirectory(params.directory);
257351
258060
  } catch {}
257352
258061
  };
257353
258062
  try {
257354
- const files = readdirSync18(params.directory);
258063
+ const files = readdirSync19(params.directory);
257355
258064
  for (const file of files) {
257356
258065
  const temporaryMatch = file.match(temporarySidecarName) ?? file.match(legacyTemporarySidecarName);
257357
258066
  if (!temporaryMatch)
@@ -257379,7 +258088,7 @@ function createRecoveryLineageSidecarAccess(params) {
257379
258088
  try {
257380
258089
  const currentAgeMs = Date.now() - statSync20(join74(params.directory, file)).mtimeMs;
257381
258090
  if (!ownerIsCurrentWriter && (!ownerIsAlive && currentAgeMs >= staleTemporaryAgeMs || currentAgeMs >= maximumTemporaryAgeMs)) {
257382
- rmSync18(join74(params.directory, file), { force: true });
258091
+ rmSync19(join74(params.directory, file), { force: true });
257383
258092
  params.syncDirectory(params.directory);
257384
258093
  }
257385
258094
  } finally {
@@ -257437,7 +258146,7 @@ import {
257437
258146
  existsSync as existsSync50,
257438
258147
  mkdirSync as mkdirSync37,
257439
258148
  readFileSync as readFileSync41,
257440
- rmSync as rmSync19,
258149
+ rmSync as rmSync20,
257441
258150
  unlinkSync as unlinkSync12,
257442
258151
  writeFileSync as writeFileSync32
257443
258152
  } from "node:fs";
@@ -257449,7 +258158,7 @@ function createInterruptedTurnStore(directory = defaultInterruptedTurnDirectory(
257449
258158
  try {
257450
258159
  writeInterruptedTurnRecordFile(temporary, destination, directory, record6, sync);
257451
258160
  } finally {
257452
- rmSync19(temporary, { force: true });
258161
+ rmSync20(temporary, { force: true });
257453
258162
  }
257454
258163
  }
257455
258164
  function path33(agentId, conversationId) {
@@ -260480,9 +261189,9 @@ import {
260480
261189
  fsyncSync as fsyncSync6,
260481
261190
  mkdirSync as mkdirSync39,
260482
261191
  openSync as openSync10,
260483
- readdirSync as readdirSync19,
261192
+ readdirSync as readdirSync20,
260484
261193
  readFileSync as readFileSync43,
260485
- rmSync as rmSync20,
261194
+ rmSync as rmSync21,
260486
261195
  writeFileSync as writeFileSync34
260487
261196
  } from "node:fs";
260488
261197
  import { join as join77 } from "node:path";
@@ -260579,11 +261288,11 @@ function createTurnFinishedStore(directory = defaultTurnFinishedDirectory(), opt
260579
261288
  renameSyncWithRetry(temporary, destination);
260580
261289
  fsyncDirectory2(directory);
260581
261290
  } finally {
260582
- rmSync20(temporary, { force: true });
261291
+ rmSync21(temporary, { force: true });
260583
261292
  }
260584
261293
  };
260585
261294
  const removeRecordFile = (recordPath) => {
260586
- rmSync20(recordPath, { force: true });
261295
+ rmSync21(recordPath, { force: true });
260587
261296
  fsyncDirectory2(directory);
260588
261297
  };
260589
261298
  const withRecordLock = (agentId, conversationId, operation) => {
@@ -260622,7 +261331,7 @@ function createTurnFinishedStore(directory = defaultTurnFinishedDirectory(), opt
260622
261331
  const sweepExpiredRecords = () => {
260623
261332
  let entries2;
260624
261333
  try {
260625
- entries2 = readdirSync19(directory, { withFileTypes: true });
261334
+ entries2 = readdirSync20(directory, { withFileTypes: true });
260626
261335
  } catch (error5) {
260627
261336
  if (error5.code === "ENOENT")
260628
261337
  return;
@@ -261698,6 +262407,11 @@ function getDequeuedClientMessageIds(runtime, batch) {
261698
262407
  for (const clientMessageId of inboundClientMessageIds.length > 0 ? inboundClientMessageIds : item.clientMessageId ? [item.clientMessageId] : []) {
261699
262408
  clientMessageIds.add(clientMessageId);
261700
262409
  }
262410
+ if (item.kind === "task_notification") {
262411
+ for (const clientMessageId of item.clientMessageIds ?? []) {
262412
+ clientMessageIds.add(clientMessageId);
262413
+ }
262414
+ }
261701
262415
  }
261702
262416
  return [...clientMessageIds];
261703
262417
  }
@@ -263310,8 +264024,8 @@ Add options:
263310
264024
  conversation per fire; "self" for the current
263311
264025
  conversation; "default" for the agent default)
263312
264026
  --computer <id> (managed Cloud sandbox only) Run on a connected
263313
- external computer (deviceId from \`letta computers
263314
- list\`). If that computer is offline at fire
264027
+ external computer (deviceId, id, or name from
264028
+ \`letta computers list\`). If it is offline at fire
263315
264029
  time, that run fails (no Cloud sandbox fallback);
263316
264030
  omit --computer to run in the Cloud sandbox.
263317
264031
 
@@ -266135,7 +266849,7 @@ import {
266135
266849
  appendFileSync as appendFileSync8,
266136
266850
  existsSync as existsSync52,
266137
266851
  mkdirSync as mkdirSync40,
266138
- readdirSync as readdirSync20,
266852
+ readdirSync as readdirSync21,
266139
266853
  unlinkSync as unlinkSync14
266140
266854
  } from "node:fs";
266141
266855
  import { join as join78 } from "node:path";
@@ -266154,7 +266868,7 @@ function pruneOldLogs(dir, maxFiles) {
266154
266868
  try {
266155
266869
  if (!existsSync52(dir))
266156
266870
  return;
266157
- const files = readdirSync20(dir).filter((f4) => f4.endsWith(".log")).sort();
266871
+ const files = readdirSync21(dir).filter((f4) => f4.endsWith(".log")).sort();
266158
266872
  if (files.length >= maxFiles) {
266159
266873
  const toDelete = files.slice(0, files.length - maxFiles + 1);
266160
266874
  for (const file of toDelete) {
@@ -266510,7 +267224,7 @@ async function registerWithCloud(opts, fetchImpl = fetch) {
266510
267224
  async function registerWithCloudRetry(opts, callbacks) {
266511
267225
  const startTime = Date.now();
266512
267226
  const maxDurationMs = callbacks?.maxDurationMs ?? REGISTER_MAX_DURATION_MS;
266513
- const sleep11 = callbacks?.sleep ?? ((delayMs) => new Promise((resolve38) => setTimeout(resolve38, delayMs)));
267227
+ const sleep12 = callbacks?.sleep ?? ((delayMs) => new Promise((resolve38) => setTimeout(resolve38, delayMs)));
266514
267228
  let attempt2 = 0;
266515
267229
  for (;; ) {
266516
267230
  try {
@@ -266529,7 +267243,7 @@ async function registerWithCloudRetry(opts, callbacks) {
266529
267243
  if (error5 instanceof Error) {
266530
267244
  callbacks?.onRetry?.(attempt2, retryDelay, error5);
266531
267245
  }
266532
- await sleep11(retryDelay);
267246
+ await sleep12(retryDelay);
266533
267247
  }
266534
267248
  }
266535
267249
  }
@@ -269148,14 +269862,14 @@ __export(exports_memory_scanner, {
269148
269862
  readFileContent: () => readFileContent,
269149
269863
  getFileNodes: () => getFileNodes
269150
269864
  });
269151
- import { readdirSync as readdirSync21, readFileSync as readFileSync44, statSync as statSync22 } from "node:fs";
269865
+ import { readdirSync as readdirSync22, readFileSync as readFileSync44, statSync as statSync22 } from "node:fs";
269152
269866
  import { join as join79, relative as relative7 } from "node:path";
269153
269867
  function scanMemoryFilesystem(memoryRoot) {
269154
269868
  const nodes = [];
269155
269869
  const scanDir = (dir, depth, parentIsLast) => {
269156
269870
  let entries2;
269157
269871
  try {
269158
- entries2 = readdirSync21(dir);
269872
+ entries2 = readdirSync22(dir);
269159
269873
  } catch {
269160
269874
  return;
269161
269875
  }
@@ -270453,6 +271167,7 @@ async function prepareToolExecutionContextForScope(params) {
270453
271167
  actingUserId,
270454
271168
  suppressActingUserFallback,
270455
271169
  mcpOriginatorSuperRunId,
271170
+ resolveClientMessageIds,
270456
271171
  overrideModel,
270457
271172
  overrideProviderType,
270458
271173
  cachedEffectiveModel,
@@ -270522,6 +271237,7 @@ async function prepareToolExecutionContextForScope(params) {
270522
271237
  ...actingUserId ? { actingUserId } : {},
270523
271238
  ...suppressActingUserFallback ? { suppressActingUserFallback: true } : {},
270524
271239
  mcpOriginatorSuperRunId: mcpOriginatorSuperRunId ?? null,
271240
+ resolveClientMessageIds,
270525
271241
  workingDirectory,
270526
271242
  ...skillsDirectory !== undefined ? { skillsDirectory } : {},
270527
271243
  ...skillSources !== undefined ? { skillSources } : {},
@@ -378816,10 +379532,10 @@ ${lanes.join(`
378816
379532
  }
378817
379533
  function getDefaultLibFilePriority(a2) {
378818
379534
  if (containsPath(defaultLibraryPath, a2.fileName, false)) {
378819
- const basename22 = getBaseFileName(a2.fileName);
378820
- if (basename22 === "lib.d.ts" || basename22 === "lib.es6.d.ts")
379535
+ const basename23 = getBaseFileName(a2.fileName);
379536
+ if (basename23 === "lib.d.ts" || basename23 === "lib.es6.d.ts")
378821
379537
  return 0;
378822
- const name = removeSuffix(removePrefix(basename22, "lib."), ".d.ts");
379538
+ const name = removeSuffix(removePrefix(basename23, "lib."), ".d.ts");
378823
379539
  const index = libs.indexOf(name);
378824
379540
  if (index !== -1)
378825
379541
  return index + 1;
@@ -431382,8 +432098,8 @@ ${options.prefix}` : `
431382
432098
  }
431383
432099
  };
431384
432100
  for (const file of files) {
431385
- const basename22 = getBaseFileName(file);
431386
- if (basename22 === "package.json" || basename22 === "bower.json") {
432101
+ const basename23 = getBaseFileName(file);
432102
+ if (basename23 === "package.json" || basename23 === "bower.json") {
431387
432103
  createProjectWatcher(file, "FileWatcher");
431388
432104
  continue;
431389
432105
  }
@@ -434260,8 +434976,8 @@ All files are: ${JSON.stringify(names2)}`, "Err");
434260
434976
  const fileOrDirectoryPath = removeIgnoredPath(this.toPath(fileOrDirectory));
434261
434977
  if (!fileOrDirectoryPath)
434262
434978
  return;
434263
- const basename22 = getBaseFileName(fileOrDirectoryPath);
434264
- if (((_a10 = result3.affectedModuleSpecifierCacheProjects) == null ? undefined : _a10.size) && (basename22 === "package.json" || basename22 === "node_modules")) {
434979
+ const basename23 = getBaseFileName(fileOrDirectoryPath);
434980
+ if (((_a10 = result3.affectedModuleSpecifierCacheProjects) == null ? undefined : _a10.size) && (basename23 === "package.json" || basename23 === "node_modules")) {
434265
434981
  result3.affectedModuleSpecifierCacheProjects.forEach((project) => {
434266
434982
  var _a22;
434267
434983
  (_a22 = project.getModuleSpecifierCache()) == null || _a22.clear();
@@ -439870,7 +440586,7 @@ import {
439870
440586
  existsSync as existsSync55,
439871
440587
  mkdirSync as mkdirSync43,
439872
440588
  readFileSync as readFileSync47,
439873
- rmSync as rmSync21,
440589
+ rmSync as rmSync22,
439874
440590
  writeFileSync as writeFileSync37
439875
440591
  } from "node:fs";
439876
440592
  import path37 from "node:path";
@@ -440473,7 +441189,7 @@ function removeManagedModPackage(params) {
440473
441189
  assertSafePackageRemovalRoot(match3.metadata);
440474
441190
  registry4.packagesValue.splice(match3.index, 1);
440475
441191
  writePackageRegistry(registry4.registryPath, registry4.registry);
440476
- rmSync21(match3.metadata.packageRoot, { force: true, recursive: true });
441192
+ rmSync22(match3.metadata.packageRoot, { force: true, recursive: true });
440477
441193
  return {
440478
441194
  package: mutationItem(match3.metadata, match3.index, match3.metadata.enabled),
440479
441195
  registryPath: registry4.registryPath,
@@ -440494,12 +441210,12 @@ var init_package_registry = __esm(() => {
440494
441210
  });
440495
441211
 
440496
441212
  // src/mods/mod-sources.ts
440497
- import { existsSync as existsSync56, readdirSync as readdirSync22 } from "node:fs";
441213
+ import { existsSync as existsSync56, readdirSync as readdirSync23 } from "node:fs";
440498
441214
  import path38 from "node:path";
440499
441215
  function listModFiles(directory) {
440500
441216
  if (!existsSync56(directory))
440501
441217
  return [];
440502
- return readdirSync22(directory, { withFileTypes: true }).filter((entry) => {
441218
+ return readdirSync23(directory, { withFileTypes: true }).filter((entry) => {
440503
441219
  if (!entry.isFile())
440504
441220
  return false;
440505
441221
  if (entry.name.startsWith("."))
@@ -440694,7 +441410,7 @@ import { createHash as createHash16 } from "node:crypto";
440694
441410
  import {
440695
441411
  existsSync as existsSync57,
440696
441412
  mkdirSync as mkdirSync45,
440697
- readdirSync as readdirSync23,
441413
+ readdirSync as readdirSync24,
440698
441414
  readFileSync as readFileSync48,
440699
441415
  statSync as statSync23,
440700
441416
  unlinkSync as unlinkSync16,
@@ -440886,7 +441602,7 @@ function createImportableModPath(modPath, cacheDirectory, source) {
440886
441602
  writeFileSync38(importPath, importableSource, "utf8");
440887
441603
  }
440888
441604
  try {
440889
- for (const entry of readdirSync23(importCacheDirectory)) {
441605
+ for (const entry of readdirSync24(importCacheDirectory)) {
440890
441606
  if (entry.startsWith(`.letta-mod-${baseName}-`) && entry !== path40.basename(importPath)) {
440891
441607
  unlinkSync16(path40.join(importCacheDirectory, entry));
440892
441608
  }
@@ -444338,11 +445054,11 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
444338
445054
  existsSync: existsSync58,
444339
445055
  lstatSync: lstatSync4,
444340
445056
  mkdirSync: mkdirSync46,
444341
- rmdirSync: rmdirSync2,
445057
+ rmdirSync: rmdirSync3,
444342
445058
  symlinkSync: symlinkSync2,
444343
445059
  unlinkSync: unlinkSync17
444344
445060
  } = await import("node:fs");
444345
- const { basename: basename22, join: join82 } = await import("node:path");
445061
+ const { basename: basename23, join: join82 } = await import("node:path");
444346
445062
  const globalSkillsDir = getGlobalSkillsDir();
444347
445063
  if (parsed.type === "skill_enable") {
444348
445064
  try {
@@ -444365,14 +445081,14 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
444365
445081
  }, "listener_skill_send_failed", "listener_skill_command");
444366
445082
  return true;
444367
445083
  }
444368
- const linkName = basename22(parsed.skill_path);
445084
+ const linkName = basename23(parsed.skill_path);
444369
445085
  const linkPath = join82(globalSkillsDir, linkName);
444370
445086
  mkdirSync46(globalSkillsDir, { recursive: true });
444371
445087
  if (existsSync58(linkPath)) {
444372
445088
  const stat12 = lstatSync4(linkPath);
444373
445089
  if (stat12.isSymbolicLink()) {
444374
445090
  if (process.platform === "win32") {
444375
- rmdirSync2(linkPath);
445091
+ rmdirSync3(linkPath);
444376
445092
  } else {
444377
445093
  unlinkSync17(linkPath);
444378
445094
  }
@@ -444430,7 +445146,7 @@ async function handleSkillCommand(parsed, socket, safeSocketSend) {
444430
445146
  return true;
444431
445147
  }
444432
445148
  if (process.platform === "win32") {
444433
- rmdirSync2(linkPath);
445149
+ rmdirSync3(linkPath);
444434
445150
  } else {
444435
445151
  unlinkSync17(linkPath);
444436
445152
  }
@@ -447428,7 +448144,7 @@ var init_tui_perf = __esm(() => {
447428
448144
  import {
447429
448145
  existsSync as existsSync59,
447430
448146
  mkdirSync as mkdirSync47,
447431
- readdirSync as readdirSync24,
448147
+ readdirSync as readdirSync25,
447432
448148
  unlinkSync as unlinkSync17,
447433
448149
  writeFileSync as writeFileSync39
447434
448150
  } from "node:fs";
@@ -447553,7 +448269,7 @@ class ChunkLog {
447553
448269
  try {
447554
448270
  if (!existsSync59(this.agentDir))
447555
448271
  return;
447556
- const files = readdirSync24(this.agentDir).filter((f4) => f4.endsWith(".jsonl")).sort();
448272
+ const files = readdirSync25(this.agentDir).filter((f4) => f4.endsWith(".jsonl")).sort();
447557
448273
  if (files.length >= MAX_SESSION_FILES2) {
447558
448274
  const toDelete = files.slice(0, files.length - MAX_SESSION_FILES2 + 1);
447559
448275
  for (const file of toDelete) {
@@ -451483,7 +452199,7 @@ __export(exports_diff, {
451483
452199
  ADV_DIFF_IGNORE_WHITESPACE: () => ADV_DIFF_IGNORE_WHITESPACE,
451484
452200
  ADV_DIFF_CONTEXT_LINES: () => ADV_DIFF_CONTEXT_LINES
451485
452201
  });
451486
- import { basename as basename22 } from "node:path";
452202
+ import { basename as basename23 } from "node:path";
451487
452203
  function readFileOrNull(p2) {
451488
452204
  try {
451489
452205
  return __require("node:fs").readFileSync(p2, "utf-8");
@@ -451507,7 +452223,7 @@ function applyAllOccurrences(content, oldStr, newStr) {
451507
452223
  return { ok: true, out: content.split(oldStr).join(newStr) };
451508
452224
  }
451509
452225
  function computeAdvancedDiff(input, opts) {
451510
- const fileName = basename22(input.filePath || "");
452226
+ const fileName = basename23(input.filePath || "");
451511
452227
  const fileContent = opts?.oldStrOverride !== undefined ? opts.oldStrOverride : readFileOrNull(input.filePath);
451512
452228
  if (fileContent === null && input.kind !== "write") {
451513
452229
  return { mode: "fallback", reason: "File not readable" };
@@ -451539,7 +452255,7 @@ function computeAdvancedDiff(input, opts) {
451539
452255
  return { mode: "advanced", fileName, oldStr, newStr, hunks };
451540
452256
  }
451541
452257
  function parsePatchToAdvancedDiff(patchLines, filePath) {
451542
- const fileName = basename22(filePath);
452258
+ const fileName = basename23(filePath);
451543
452259
  const hunks = [];
451544
452260
  let currentHunk = null;
451545
452261
  let oldLine = 1;
@@ -451817,8 +452533,8 @@ function isFormatterSegment(tokens) {
451817
452533
  }
451818
452534
  }
451819
452535
  function isShellExecutor2(token2) {
451820
- const basename23 = token2.split("/").pop() ?? token2;
451821
- return ["bash", "sh", "zsh", "dash", "ksh"].includes(basename23.toLowerCase());
452536
+ const basename24 = token2.split("/").pop() ?? token2;
452537
+ return ["bash", "sh", "zsh", "dash", "ksh"].includes(basename24.toLowerCase());
451822
452538
  }
451823
452539
  function normalizeRawCommand(command) {
451824
452540
  if (Array.isArray(command)) {
@@ -452605,7 +453321,7 @@ var init_format_args_display = __esm(() => {
452605
453321
  });
452606
453322
 
452607
453323
  // src/helpers/diff-preview.ts
452608
- import path42, { basename as basename23 } from "node:path";
453324
+ import path42, { basename as basename24 } from "node:path";
452609
453325
  function parseHunkLinePrefix(raw2) {
452610
453326
  if (raw2.length === 0) {
452611
453327
  return { type: "context", content: "" };
@@ -452711,7 +453427,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
452711
453427
  filePath: resolvedFilePath,
452712
453428
  content: toolArgs.content || ""
452713
453429
  });
452714
- previews.push(toDiffPreview(result3, basename23(filePath)));
453430
+ previews.push(toDiffPreview(result3, basename24(filePath)));
452715
453431
  }
452716
453432
  } else if (isFileEditTool3(toolName2)) {
452717
453433
  const filePath = toolArgs.file_path;
@@ -452724,7 +453440,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
452724
453440
  newString: toolArgs.new_string || "",
452725
453441
  replaceAll: toolArgs.replace_all
452726
453442
  });
452727
- previews.push(toDiffPreview(result3, basename23(filePath)));
453443
+ previews.push(toDiffPreview(result3, basename24(filePath)));
452728
453444
  }
452729
453445
  } else if (isPatchTool2(toolName2) && toolArgs.input) {
452730
453446
  const operations2 = parsePatchOperations2(toolArgs.input);
@@ -452732,7 +453448,7 @@ async function computeDiffPreviews(toolName2, toolArgs, workingDirectory = getCu
452732
453448
  if (op.kind === "add" || op.kind === "update") {
452733
453449
  const result3 = parsePatchToAdvancedDiff2(op.patchLines, op.path);
452734
453450
  if (result3) {
452735
- previews.push(toDiffPreview(result3, basename23(op.path)));
453451
+ previews.push(toDiffPreview(result3, basename24(op.path)));
452736
453452
  }
452737
453453
  }
452738
453454
  }
@@ -456390,7 +457106,7 @@ var init_deepagents = __esm(() => {
456390
457106
  });
456391
457107
 
456392
457108
  // node_modules/@letta-ai/trajectory/dist/adapters/listing-shared.js
456393
- import { readdirSync as readdirSync25, statSync as statSync24 } from "node:fs";
457109
+ import { readdirSync as readdirSync26, statSync as statSync24 } from "node:fs";
456394
457110
  import { join as join86 } from "node:path";
456395
457111
  function sortListings(items3) {
456396
457112
  return items3.sort((left, right) => {
@@ -456403,7 +457119,7 @@ function sortListings(items3) {
456403
457119
  }
456404
457120
  function safeReadDir(path43) {
456405
457121
  try {
456406
- return readdirSync25(path43, { withFileTypes: true }).map((entry) => ({
457122
+ return readdirSync26(path43, { withFileTypes: true }).map((entry) => ({
456407
457123
  name: entry.name,
456408
457124
  isDirectory: entry.isDirectory(),
456409
457125
  isFile: entry.isFile()
@@ -456521,7 +457237,7 @@ var init_listing_shared = __esm(() => {
456521
457237
 
456522
457238
  // node_modules/@letta-ai/trajectory/dist/adapters/claude-code/list.js
456523
457239
  import { homedir as homedir23 } from "node:os";
456524
- import { basename as basename24, join as join87 } from "node:path";
457240
+ import { basename as basename25, join as join87 } from "node:path";
456525
457241
  async function listClaudeCodeTrajectories(root2) {
456526
457242
  const base2 = root2 ?? join87(homedir23(), ".claude", "projects");
456527
457243
  const items3 = [];
@@ -456533,7 +457249,7 @@ async function listClaudeCodeTrajectories(root2) {
456533
457249
  if (!entry.isFile || !entry.name.endsWith(".jsonl"))
456534
457250
  continue;
456535
457251
  const path43 = join87(projectPath, entry.name);
456536
- const listing = listingFromFile(basename24(entry.name, ".jsonl"), path43);
457252
+ const listing = listingFromFile(basename25(entry.name, ".jsonl"), path43);
456537
457253
  if (listing)
456538
457254
  items3.push(listing);
456539
457255
  }
@@ -456546,12 +457262,12 @@ var init_list = __esm(() => {
456546
457262
 
456547
457263
  // node_modules/@letta-ai/trajectory/dist/adapters/codex/list.js
456548
457264
  import { homedir as homedir24 } from "node:os";
456549
- import { basename as basename25, join as join88 } from "node:path";
457265
+ import { basename as basename26, join as join88 } from "node:path";
456550
457266
  async function listCodexTrajectories(root2) {
456551
457267
  const base2 = root2 ?? join88(homedir24(), ".codex", "sessions");
456552
457268
  const items3 = [];
456553
457269
  for (const path43 of collectFiles(base2, ".jsonl", 4)) {
456554
- const listing = listingFromFile(basename25(path43, ".jsonl"), path43);
457270
+ const listing = listingFromFile(basename26(path43, ".jsonl"), path43);
456555
457271
  if (listing)
456556
457272
  items3.push(listing);
456557
457273
  }
@@ -456658,7 +457374,7 @@ var init_list5 = __esm(() => {
456658
457374
  // node_modules/@letta-ai/trajectory/dist/adapters/openclaw/list.js
456659
457375
  import { existsSync as existsSync62 } from "node:fs";
456660
457376
  import { homedir as homedir28 } from "node:os";
456661
- import { basename as basename26, join as join92 } from "node:path";
457377
+ import { basename as basename27, join as join92 } from "node:path";
456662
457378
  async function listOpenClawTrajectories(root2) {
456663
457379
  const base2 = root2 ?? defaultStateDir();
456664
457380
  const items3 = [];
@@ -456671,7 +457387,7 @@ async function listOpenClawTrajectories(root2) {
456671
457387
  if (!entry.isFile || !entry.name.endsWith(".jsonl"))
456672
457388
  continue;
456673
457389
  const path43 = join92(sessionsPath, entry.name);
456674
- const listing = listingFromFile(basename26(entry.name, ".jsonl"), path43);
457390
+ const listing = listingFromFile(basename27(entry.name, ".jsonl"), path43);
456675
457391
  if (listing)
456676
457392
  items3.push(listing);
456677
457393
  }
@@ -460062,7 +460778,8 @@ async function prepareListenerTurn(params) {
460062
460778
  permissionModeState,
460063
460779
  turnLease,
460064
460780
  onStatusChange,
460065
- connectionId
460781
+ connectionId,
460782
+ resolveClientMessageIds
460066
460783
  } = params;
460067
460784
  const isInterrupted = () => turnLease.signal.aborted || !runtime.turnLifecycle.isCurrent(turnLease);
460068
460785
  let listenAgentMetadata = await ensureListenerWarmStateForTurn(runtime.listener, { agentId, conversationId });
@@ -460229,6 +460946,7 @@ async function prepareListenerTurn(params) {
460229
460946
  actingUserId: msg.actingUserId,
460230
460947
  suppressActingUserFallback: msg.suppressActingUserFallback,
460231
460948
  mcpOriginatorSuperRunId: getEffectiveMcpOriginatorId(msg),
460949
+ resolveClientMessageIds,
460232
460950
  clientToolset: msg.clientToolset,
460233
460951
  clientToolAllowlist: msg.clientToolAllowlist,
460234
460952
  ...msg.excludeInteractiveTools ? { exclude: [...INTERACTIVE_USER_INPUT_TOOL_NAMES] } : {},
@@ -460528,7 +461246,8 @@ async function handleIncomingMessageInner(msg, socket, runtime, onStatusChange,
460528
461246
  permissionModeState: turnPermissionModeState,
460529
461247
  turnLease,
460530
461248
  onStatusChange,
460531
- connectionId
461249
+ connectionId,
461250
+ resolveClientMessageIds: () => turnCorrelation.clientMessageIds
460532
461251
  });
460533
461252
  if (setup.kind === "interrupted") {
460534
461253
  finishTurn({
@@ -462802,7 +463521,7 @@ __export(exports_custom, {
462802
463521
  });
462803
463522
  import { existsSync as existsSync64 } from "node:fs";
462804
463523
  import { readdir as readdir11, readFile as readFile27 } from "node:fs/promises";
462805
- import { basename as basename28, dirname as dirname37, join as join96 } from "node:path";
463524
+ import { basename as basename29, dirname as dirname37, join as join96 } from "node:path";
462806
463525
  function getGlobalCommandsDir() {
462807
463526
  return join96(resolveGlobalConfigDir(), "commands");
462808
463527
  }
@@ -462865,7 +463584,7 @@ async function findCommandFiles(currentPath, rootPath, commands, source) {
462865
463584
  async function parseCommandFile(filePath, rootPath, source) {
462866
463585
  const content = await readFile27(filePath, "utf-8");
462867
463586
  const { frontmatter, body: body3 } = parseFrontmatter(content);
462868
- const id2 = basename28(filePath, ".md");
463587
+ const id2 = basename29(filePath, ".md");
462869
463588
  const relativePath = dirname37(filePath).slice(rootPath.length);
462870
463589
  const namespace = relativePath.replace(/^[/\\]/, "") || undefined;
462871
463590
  let description = getStringField(frontmatter, "description");
@@ -465028,7 +465747,7 @@ function dispatchInboundMessageWhenReady(params) {
465028
465747
  } = params;
465029
465748
  const identity2 = ordinaryInputIdentity(getInboundClientMessageId(incoming));
465030
465749
  let inputAcknowledged = false;
465031
- const acknowledgeInput = (result3) => {
465750
+ const acknowledgeInput2 = (result3) => {
465032
465751
  if (inputAcknowledged)
465033
465752
  return;
465034
465753
  inputAcknowledged = true;
@@ -465051,12 +465770,12 @@ function dispatchInboundMessageWhenReady(params) {
465051
465770
  runtime.pendingInboundDispatches += 1;
465052
465771
  runtime.messageQueue = runtime.messageQueue.then(async () => {
465053
465772
  if (listener !== getActiveRuntime() || listener.intentionallyClosed) {
465054
- acknowledgeInput({ accepted: false });
465773
+ acknowledgeInput2({ accepted: false });
465055
465774
  return;
465056
465775
  }
465057
465776
  const admission = reserveInputDisposition(runtime, identity2);
465058
465777
  if (admission.kind === "duplicate") {
465059
- acknowledgeInput({
465778
+ acknowledgeInput2({
465060
465779
  accepted: true,
465061
465780
  disposition: admission.disposition,
465062
465781
  duplicate: true,
@@ -465065,7 +465784,7 @@ function dispatchInboundMessageWhenReady(params) {
465065
465784
  return;
465066
465785
  }
465067
465786
  if (admission.kind === "full") {
465068
- acknowledgeInput({ accepted: false });
465787
+ acknowledgeInput2({ accepted: false });
465069
465788
  return;
465070
465789
  }
465071
465790
  const reservation = admission.kind === "reserved" ? admission.reservation : undefined;
@@ -465077,7 +465796,7 @@ function dispatchInboundMessageWhenReady(params) {
465077
465796
  try {
465078
465797
  if (isRuntimeTeleportPending(listener, runtime.agentId, runtime.conversationId)) {
465079
465798
  rollbackInputDisposition(runtime, reservation);
465080
- acknowledgeInput({ accepted: false });
465799
+ acknowledgeInput2({ accepted: false });
465081
465800
  return;
465082
465801
  }
465083
465802
  if (shouldQueueInboundMessage(incoming)) {
@@ -465088,7 +465807,7 @@ function dispatchInboundMessageWhenReady(params) {
465088
465807
  } catch (error5) {
465089
465808
  if (committed && !forgetQueuedInput(runtime, identity2)) {
465090
465809
  recoverRetainedQueuedInput();
465091
- acknowledgeInput({ accepted: true, disposition: "queued" });
465810
+ acknowledgeInput2({ accepted: true, disposition: "queued" });
465092
465811
  return;
465093
465812
  }
465094
465813
  throw error5;
@@ -465098,14 +465817,14 @@ function dispatchInboundMessageWhenReady(params) {
465098
465817
  if (committed) {
465099
465818
  if (!forgetQueuedInput(runtime, identity2)) {
465100
465819
  recoverRetainedQueuedInput();
465101
- acknowledgeInput({ accepted: true, disposition: "queued" });
465820
+ acknowledgeInput2({ accepted: true, disposition: "queued" });
465102
465821
  return;
465103
465822
  }
465104
465823
  } else {
465105
465824
  rollbackInputDisposition(runtime, reservation);
465106
465825
  }
465107
465826
  }
465108
- acknowledgeInput({
465827
+ acknowledgeInput2({
465109
465828
  accepted: durablyAccepted,
465110
465829
  ...durablyAccepted ? { disposition: "queued" } : {}
465111
465830
  });
@@ -465120,10 +465839,10 @@ function dispatchInboundMessageWhenReady(params) {
465120
465839
  actingUserId
465121
465840
  })) {
465122
465841
  rollbackInputDisposition(runtime, reservation);
465123
- acknowledgeInput({ accepted: false });
465842
+ acknowledgeInput2({ accepted: false });
465124
465843
  return;
465125
465844
  }
465126
- acknowledgeInput({ accepted: true, disposition: "started" });
465845
+ acknowledgeInput2({ accepted: true, disposition: "started" });
465127
465846
  await processIncomingMessage(attributedIncoming, getOrCreateProcessTransport(listener), runtime, options.onStatusChange, options.connectionId);
465128
465847
  emitListenerStatus(listener, options.onStatusChange, options.connectionId);
465129
465848
  if (runtime.queueRuntime.length > 0 || runtime.queuePumpScheduled || runtime.queuePumpActive) {
@@ -465135,7 +465854,7 @@ function dispatchInboundMessageWhenReady(params) {
465135
465854
  }
465136
465855
  }).catch((error5) => {
465137
465856
  try {
465138
- acknowledgeInput({ accepted: false });
465857
+ acknowledgeInput2({ accepted: false });
465139
465858
  } catch (acknowledgementError) {
465140
465859
  trackListenerError5("listener_input_acknowledgement_failed", acknowledgementError, "listener_message_queue");
465141
465860
  }
@@ -465432,27 +466151,27 @@ function admitTeleportContinueInput(params) {
465432
466151
  agentId,
465433
466152
  conversationId,
465434
466153
  payload,
465435
- acknowledgeInput
466154
+ acknowledgeInput: acknowledgeInput2
465436
466155
  } = params;
465437
466156
  const teleportId = payload.teleport_id;
465438
466157
  if (isInboundTeleportExpected(scopedRuntime) && scopedRuntime.expectedTeleportId !== teleportId) {
465439
- acknowledgeInput(false, "Teleport continuation does not match the expected handoff");
466158
+ acknowledgeInput2(false, "Teleport continuation does not match the expected handoff");
465440
466159
  return;
465441
466160
  }
465442
466161
  const admission = reserveInputDisposition(scopedRuntime, teleportInputIdentity(teleportId));
465443
466162
  if (admission.kind === "duplicate") {
465444
- acknowledgeInput(true, undefined, admission.disposition, "refresh", () => hasLiveAcceptedInputOwnerWithOriginatorRetirement(scopedRuntime, teleportInputIdentity(teleportId)));
466163
+ acknowledgeInput2(true, undefined, admission.disposition, "refresh", () => hasLiveAcceptedInputOwnerWithOriginatorRetirement(scopedRuntime, teleportInputIdentity(teleportId)));
465445
466164
  return;
465446
466165
  }
465447
466166
  if (admission.kind === "full") {
465448
- acknowledgeInput(false, "Stable input ledger is at capacity");
466167
+ acknowledgeInput2(false, "Stable input ledger is at capacity");
465449
466168
  return;
465450
466169
  }
465451
466170
  const reservation = admission.kind === "reserved" ? admission.reservation : undefined;
465452
466171
  try {
465453
466172
  if (scopedRuntime.isProcessing) {
465454
466173
  rollbackInputDisposition(scopedRuntime, reservation);
465455
- acknowledgeInput(false, "Destination runtime is already processing");
466174
+ acknowledgeInput2(false, "Destination runtime is already processing");
465456
466175
  return;
465457
466176
  }
465458
466177
  clearPriorReadyTeleports({
@@ -465479,11 +466198,11 @@ function admitTeleportContinueInput(params) {
465479
466198
  incoming: continuationInput
465480
466199
  })) {
465481
466200
  rollbackInputDisposition(scopedRuntime, reservation);
465482
- acknowledgeInput(false, "Stable input disposition could not be persisted");
466201
+ acknowledgeInput2(false, "Stable input disposition could not be persisted");
465483
466202
  return;
465484
466203
  }
465485
466204
  clearExpectedInboundTeleport(scopedRuntime);
465486
- acknowledgeInput(true, undefined, "started", "refresh");
466205
+ acknowledgeInput2(true, undefined, "started", "refresh");
465487
466206
  params.runDetachedListenerTask("teleport_continue", async () => {
465488
466207
  await params.processIncomingMessage(continuationInput, getOrCreateProcessTransport(listener), scopedRuntime, params.onStatusChange, connectionId);
465489
466208
  });
@@ -465520,11 +466239,11 @@ async function routeInputFrame(deps) {
465520
466239
  processIncomingMessage
465521
466240
  } = deps;
465522
466241
  let ackExtras;
465523
- const acknowledgeInput = (...args) => acknowledgeInputFrame(safeSocketSend, socket, parsed, args[0], args[1], args[2], args[3], args[4], ackExtras);
466242
+ const acknowledgeInput2 = (...args) => acknowledgeInputFrame(safeSocketSend, socket, parsed, args[0], args[1], args[2], args[3], args[4], ackExtras);
465524
466243
  const ackTransport = { safeSocketSend, socket, frame: parsed };
465525
466244
  if (runtime !== getActiveRuntime() || runtime.intentionallyClosed) {
465526
466245
  logV2Command(opts, "Dropping input: runtime mismatch or closed");
465527
- acknowledgeInput(false, "Runtime is no longer active");
466246
+ acknowledgeInput2(false, "Runtime is no longer active");
465528
466247
  return;
465529
466248
  }
465530
466249
  const gateInputOriginatorAdmission = () => {
@@ -465538,7 +466257,7 @@ async function routeInputFrame(deps) {
465538
466257
  abortReason: MCP_ORIGINATOR_DENIED_PERMANENT_ABORT_REASON
465539
466258
  };
465540
466259
  console.error("[message-router] originator admission is permanently denied; rejecting the input without committing work");
465541
- acknowledgeInput(false, "Originator authority for this input was permanently rejected");
466260
+ acknowledgeInput2(false, "Originator authority for this input was permanently rejected");
465542
466261
  return false;
465543
466262
  }
465544
466263
  ackExtras = { preGated: gate.delivery ?? null };
@@ -465547,7 +466266,7 @@ async function routeInputFrame(deps) {
465547
466266
  if (parsed.payload.kind === "teleport_continue") {
465548
466267
  const teleportAgentId = parsed.runtime.agent_id;
465549
466268
  if (!teleportAgentId) {
465550
- acknowledgeInput(false, "Teleport requires an agent-backed runtime");
466269
+ acknowledgeInput2(false, "Teleport requires an agent-backed runtime");
465551
466270
  return;
465552
466271
  }
465553
466272
  if (!gateInputOriginatorAdmission()) {
@@ -465562,7 +466281,7 @@ async function routeInputFrame(deps) {
465562
466281
  payload: parsed.payload,
465563
466282
  originatorSuperRunId: parsed.super_run_id,
465564
466283
  onStatusChange: opts.onStatusChange,
465565
- acknowledgeInput,
466284
+ acknowledgeInput: acknowledgeInput2,
465566
466285
  runDetachedListenerTask: runDetachedListenerTask2,
465567
466286
  processIncomingMessage
465568
466287
  });
@@ -465580,7 +466299,7 @@ async function routeInputFrame(deps) {
465580
466299
  },
465581
466300
  processQueuedTurn
465582
466301
  });
465583
- acknowledgeInput(handled, handled ? undefined : "Approval request is no longer pending");
466302
+ acknowledgeInput2(handled, handled ? undefined : "Approval request is no longer pending");
465584
466303
  return;
465585
466304
  }
465586
466305
  const inputPayload = parsed.payload;
@@ -465592,12 +466311,12 @@ async function routeInputFrame(deps) {
465592
466311
  agentId: parsed.runtime.agent_id,
465593
466312
  conversationId: parsed.runtime.conversation_id
465594
466313
  });
465595
- acknowledgeInput(false, "Unsupported input payload kind");
466314
+ acknowledgeInput2(false, "Unsupported input payload kind");
465596
466315
  return;
465597
466316
  }
465598
466317
  const error5 = validateResponseFormat(inputPayload.response_format);
465599
466318
  if (error5) {
465600
- acknowledgeInput(false, error5);
466319
+ acknowledgeInput2(false, error5);
465601
466320
  return;
465602
466321
  }
465603
466322
  const incoming = createIncomingMessage(parsed.runtime, inputPayload, connectionId, parsed);
@@ -465610,7 +466329,7 @@ async function routeInputFrame(deps) {
465610
466329
  agentId: parsed.runtime.agent_id,
465611
466330
  conversationId: parsed.runtime.conversation_id
465612
466331
  });
465613
- acknowledgeInput(false, "Approval payloads require approval_response");
466332
+ acknowledgeInput2(false, "Approval payloads require approval_response");
465614
466333
  return;
465615
466334
  }
465616
466335
  const scopedRuntime = getOrCreateScopedRuntime2(runtime, incoming.agentId, incoming.conversationId);
@@ -465625,7 +466344,7 @@ async function routeInputFrame(deps) {
465625
466344
  processIncomingMessage,
465626
466345
  actingUserId: parsed.runtime.acting_user_id,
465627
466346
  trackListenerError: trackListenerError5,
465628
- onInputAccepted: (result3) => acknowledgeInput(result3.accepted, result3.accepted ? undefined : "Input was rejected by the queue", result3.disposition, result3.duplicate ? "refresh" : undefined, result3.mayRecreateOwner)
466347
+ onInputAccepted: (result3) => acknowledgeInput2(result3.accepted, result3.accepted ? undefined : "Input was rejected by the queue", result3.disposition, result3.duplicate ? "refresh" : undefined, result3.mayRecreateOwner)
465629
466348
  });
465630
466349
  };
465631
466350
  if (shouldQueueInboundMessage(incoming)) {
@@ -465635,7 +466354,7 @@ async function routeInputFrame(deps) {
465635
466354
  return;
465636
466355
  }
465637
466356
  if (isRuntimeTeleportPending(runtime, scopedRuntime.agentId, scopedRuntime.conversationId)) {
465638
- acknowledgeInput(false, "Conversation is switching computers");
466357
+ acknowledgeInput2(false, "Conversation is switching computers");
465639
466358
  return;
465640
466359
  }
465641
466360
  if (!gateInputOriginatorAdmission()) {
@@ -465647,7 +466366,7 @@ async function routeInputFrame(deps) {
465647
466366
  return;
465648
466367
  }
465649
466368
  if (admission.kind === "full") {
465650
- acknowledgeInput(false, "Stable input ledger is at capacity");
466369
+ acknowledgeInput2(false, "Stable input ledger is at capacity");
465651
466370
  return;
465652
466371
  }
465653
466372
  const reservation = admission.kind === "reserved" ? admission.reservation : undefined;
@@ -465673,7 +466392,7 @@ async function routeInputFrame(deps) {
465673
466392
  } else {
465674
466393
  rollbackInputDisposition(scopedRuntime, reservation);
465675
466394
  }
465676
- acknowledgeInput(durablyAccepted, durablyAccepted ? undefined : "Input was rejected by the queue or durable ledger", durablyAccepted ? "queued" : undefined);
466395
+ acknowledgeInput2(durablyAccepted, durablyAccepted ? undefined : "Input was rejected by the queue or durable ledger", durablyAccepted ? "queued" : undefined);
465677
466396
  } catch (error6) {
465678
466397
  rollbackInputDisposition(scopedRuntime, reservation);
465679
466398
  throw error6;
@@ -466079,6 +466798,15 @@ function findOwnedTask(runtime, agentId) {
466079
466798
  return;
466080
466799
  return [...backgroundTasks.entries()].find(([, task2]) => task2.subagentId === subagent.id);
466081
466800
  }
466801
+ function ownsNativeSession(runtime, agentId) {
466802
+ const target2 = parseExternalCodingAgentId(agentId);
466803
+ if (!target2 || target2.computer)
466804
+ return false;
466805
+ if (target2.type !== "claude-code" && target2.type !== "codex")
466806
+ return false;
466807
+ const owner = getNativeSessionOwner(target2.type === "claude-code" ? "claude_code" : "codex", target2.sessionId);
466808
+ return owner?.agentId === runtime.agentId && owner.conversationId === runtime.conversationId;
466809
+ }
466082
466810
  function runtimeContext(parent, command) {
466083
466811
  return {
466084
466812
  agentId: parent.agentId,
@@ -466110,7 +466838,7 @@ async function handleSubagentMessageCommand(command, parent, deps = {}) {
466110
466838
  try {
466111
466839
  if (parent.agentId !== command.runtime.agent_id || parent.conversationId !== command.runtime.conversation_id)
466112
466840
  throw new Error("Parent runtime does not match the message request");
466113
- if (!findOwnedTask(parent, command.agent_id))
466841
+ if (!findOwnedTask(parent, command.agent_id) && !ownsNativeSession(parent, command.agent_id))
466114
466842
  throw new Error("Subagent does not belong to this conversation");
466115
466843
  const target2 = parseExternalCodingAgentId(command.agent_id);
466116
466844
  if (!target2 || target2.computer || !isExternalCodingAgentType(target2.type))
@@ -466123,40 +466851,52 @@ async function handleSubagentMessageCommand(command, parent, deps = {}) {
466123
466851
  let captureReservation;
466124
466852
  const source = target2.type === "claude-code" ? "claude_code" : "codex";
466125
466853
  const secrets2 = target2.type === "cursor" ? await resolveExternalCodingAgentSecretEnv(parent.agentId) : {};
466126
- const receipt = await runOutsideRuntimeContext(() => runWithRuntimeContext(runtimeContext(parent, command), () => target2.type === "cursor" ? sendCursorMessage({
466127
- sessionId,
466128
- prompt: command.message,
466129
- parentAgentId: command.runtime.agent_id,
466130
- cwd: getCurrentWorkingDirectory()
466131
- }, { ...process.env, ...secrets2 }, secrets2) : target2.type === "claude-code" ? (deps.sendClaude ?? sendClaudeMessage)({
466132
- sessionId: target2.sessionId,
466133
- prompt: command.message,
466134
- parentAgentId: command.runtime.agent_id,
466135
- cwd: getCurrentWorkingDirectory(),
466136
- beforeStart: async () => {
466137
- captureReservation = await (deps.reserveCapture ?? reserveNativeSessionCapture)(source, sessionId, {
466138
- agentId: command.runtime.agent_id,
466139
- conversationId: command.runtime.conversation_id,
466854
+ let worker;
466855
+ const receipt = await runOutsideRuntimeContext(() => runWithRuntimeContext(runtimeContext(parent, command), async () => {
466856
+ if (target2.type !== "cursor")
466857
+ worker = await buildExternalWorkerResumeEnv({
466858
+ parentAgentId: command.runtime.agent_id,
466140
466859
  actingUserId: command.runtime.acting_user_id
466141
- });
466142
- }
466143
- }) : (deps.sendCodex ?? sendCodexMessage)({
466144
- threadId: target2.sessionId,
466145
- prompt: command.message,
466146
- parentAgentId: command.runtime.agent_id,
466147
- cwd: getCurrentWorkingDirectory(),
466148
- beforeStart: async () => {
466149
- captureReservation = await (deps.reserveCapture ?? reserveNativeSessionCapture)(source, sessionId, {
466150
- agentId: command.runtime.agent_id,
466151
- conversationId: command.runtime.conversation_id,
466152
- actingUserId: command.runtime.acting_user_id
466153
- });
466154
- }
466155
- })));
466860
+ }, deps.workerEnv);
466861
+ return target2.type === "cursor" ? sendCursorMessage({
466862
+ sessionId,
466863
+ prompt: command.message,
466864
+ parentAgentId: command.runtime.agent_id,
466865
+ cwd: getCurrentWorkingDirectory()
466866
+ }, { ...process.env, ...secrets2 }, secrets2) : target2.type === "claude-code" ? (deps.sendClaude ?? sendClaudeMessage)({
466867
+ sessionId: target2.sessionId,
466868
+ prompt: command.message,
466869
+ parentAgentId: command.runtime.agent_id,
466870
+ cwd: getCurrentWorkingDirectory(),
466871
+ mcpReminder: worker?.mcpReminder,
466872
+ beforeStart: async () => {
466873
+ captureReservation = await (deps.reserveCapture ?? reserveNativeSessionCapture)(source, sessionId, {
466874
+ agentId: command.runtime.agent_id,
466875
+ conversationId: command.runtime.conversation_id,
466876
+ actingUserId: command.runtime.acting_user_id
466877
+ });
466878
+ }
466879
+ }, { env: worker?.env }) : (deps.sendCodex ?? sendCodexMessage)({
466880
+ threadId: target2.sessionId,
466881
+ prompt: command.message,
466882
+ parentAgentId: command.runtime.agent_id,
466883
+ cwd: getCurrentWorkingDirectory(),
466884
+ mcpReminder: worker?.mcpReminder,
466885
+ beforeStart: async () => {
466886
+ captureReservation = await (deps.reserveCapture ?? reserveNativeSessionCapture)(source, sessionId, {
466887
+ agentId: command.runtime.agent_id,
466888
+ conversationId: command.runtime.conversation_id,
466889
+ actingUserId: command.runtime.acting_user_id
466890
+ });
466891
+ }
466892
+ }, { env: worker?.env });
466893
+ }));
466156
466894
  if (receipt.mode === "steered")
466157
466895
  return { ...base2, success: true, delivery: "steered" };
466158
466896
  if (!receipt.completion || !receipt.interrupt)
466159
466897
  throw new Error("External coding agent returned an incomplete receipt");
466898
+ const secretEnv = worker?.secretEnv;
466899
+ const completion = secretEnv ? receipt.completion.then((result4) => scrubExternalWorkerResult(result4, secretEnv)) : receipt.completion;
466160
466900
  try {
466161
466901
  (deps.track ?? trackExternalFollowupCompletion)({
466162
466902
  type: target2.type,
@@ -466167,7 +466907,7 @@ async function handleSubagentMessageCommand(command, parent, deps = {}) {
466167
466907
  conversationId: parent.conversationId,
466168
466908
  actingUserId: command.runtime.acting_user_id
466169
466909
  },
466170
- completion: receipt.completion,
466910
+ completion,
466171
466911
  interrupt: receipt.interrupt,
466172
466912
  captureReservation,
466173
466913
  toolCallId: command.tool_call_id,
@@ -466179,7 +466919,7 @@ async function handleSubagentMessageCommand(command, parent, deps = {}) {
466179
466919
  await receipt.interrupt().catch(() => {
466180
466920
  return;
466181
466921
  });
466182
- finishUntrackedNativeCapture2(receipt.completion, captureReservation, source, sessionId);
466922
+ finishUntrackedNativeCapture2(completion, captureReservation, source, sessionId);
466183
466923
  throw error5;
466184
466924
  }
466185
466925
  return { ...base2, success: true, delivery: "resumed" };
@@ -466212,8 +466952,11 @@ async function handleSubagentStopCommand(command, parent) {
466212
466952
  if (parent.agentId !== command.runtime.agent_id || parent.conversationId !== command.runtime.conversation_id)
466213
466953
  return { ...base2, error: "Parent runtime does not match the stop request" };
466214
466954
  const owned = findOwnedTask(parent, command.agent_id);
466215
- if (!owned)
466955
+ if (!owned) {
466956
+ if (ownsNativeSession(parent, command.agent_id))
466957
+ return { ...base2, success: true };
466216
466958
  return { ...base2, error: "Subagent does not belong to this conversation" };
466959
+ }
466217
466960
  const [, task2] = owned;
466218
466961
  if (task2.status !== "running")
466219
466962
  return { ...base2, success: true };
@@ -466846,16 +467589,24 @@ var init_message_router = __esm(async () => {
466846
467589
  function installProcessEventRouting(params) {
466847
467590
  const { runtime, processTransport, opts, processQueuedTurn } = params;
466848
467591
  runtime._unsubscribeSubagentState?.();
467592
+ const emitSubagentState = (scope, options) => {
467593
+ const transport3 = runtime.transport ?? runtime.socket;
467594
+ if (!transport3 || !isListenerTransportOpen(transport3)) {
467595
+ clearSubagentSnapshotCache(runtime);
467596
+ return;
467597
+ }
467598
+ emitSubagentStateUpdate(transport3, runtime, scope, TO_SUBSCRIBERS, options);
467599
+ };
466849
467600
  runtime._unsubscribeSubagentState = subscribe2(() => {
466850
467601
  if (runtime.conversationRuntimes.size === 0) {
466851
- emitSubagentStateIfOpen(runtime);
467602
+ emitSubagentState();
466852
467603
  return;
466853
467604
  }
466854
467605
  for (const conversationRuntime of runtime.conversationRuntimes.values()) {
466855
- emitSubagentStateIfOpen(runtime, {
467606
+ emitSubagentState({
466856
467607
  agent_id: conversationRuntime.agentId,
466857
467608
  conversation_id: conversationRuntime.conversationId
466858
- });
467609
+ }, { onlyIfChanged: true });
466859
467610
  }
466860
467611
  });
466861
467612
  runtime._unsubscribeSubagentStreamEvents?.();
@@ -466911,11 +467662,32 @@ function installProcessEventRouting(params) {
466911
467662
  text: queuedMessage.text,
466912
467663
  content: queuedMessage.content,
466913
467664
  actingUserId: queuedMessage.actingUserId,
467665
+ clientMessageIds: queuedMessage.clientMessageIds,
466914
467666
  agentId: queuedMessage.agentId ?? targetRuntime.agentId ?? undefined,
466915
467667
  conversationId: queuedMessage.conversationId ?? targetRuntime.conversationId
466916
467668
  });
466917
467669
  scheduleQueuePump(targetRuntime, processTransport, opts, processQueuedTurn);
466918
467670
  });
467671
+ runtime._stopDiskSpaceWatch?.();
467672
+ runtime._stopDiskSpaceWatch = watchSandboxDiskSpace(getCurrentWorkingDirectory, (text3) => deliverSandboxDiskAlert(runtime, text3));
467673
+ }
467674
+ function deliverSandboxDiskAlert(runtime, text3) {
467675
+ const target2 = getMostRecentlyActiveConversation(runtime);
467676
+ deliverDiskSpaceReminder(text3, target2?.agentId ? { agentId: target2.agentId, conversationId: target2.conversationId } : undefined);
467677
+ }
467678
+ function getMostRecentlyActiveConversation(runtime) {
467679
+ let latest = null;
467680
+ let latestAt = -1;
467681
+ for (const conversationRuntime of runtime.conversationRuntimes.values()) {
467682
+ if (!conversationRuntime.agentId)
467683
+ continue;
467684
+ const activeAt = conversationRuntime.isProcessing ? Number.POSITIVE_INFINITY : conversationRuntime.contextTracker.contextTokensHistory.at(-1)?.timestamp ?? 0;
467685
+ if (activeAt > latestAt) {
467686
+ latest = conversationRuntime;
467687
+ latestAt = activeAt;
467688
+ }
467689
+ }
467690
+ return latest;
466919
467691
  }
466920
467692
  function clearProcessServices(runtime) {
466921
467693
  runtime._unsubscribeSubagentState?.();
@@ -466924,6 +467696,8 @@ function clearProcessServices(runtime) {
466924
467696
  runtime._unsubscribeSubagentStreamEvents = undefined;
466925
467697
  runtime._unsubscribeBackgroundProcessState?.();
466926
467698
  runtime._unsubscribeBackgroundProcessState = undefined;
467699
+ runtime._stopDiskSpaceWatch?.();
467700
+ runtime._stopDiskSpaceWatch = undefined;
466927
467701
  setMessageQueueAdder(null);
466928
467702
  stopScheduler();
466929
467703
  clearRuntimeTimers(runtime);
@@ -466955,8 +467729,11 @@ async function waitForProcessServicesSlot(runtime, connectionId) {
466955
467729
  }
466956
467730
  var init_process_services = __esm(async () => {
466957
467731
  init_subagent_state();
467732
+ init_disk_space();
467733
+ init_runtime_context();
466958
467734
  init_process_manager();
466959
467735
  init_message_queue_bridge();
467736
+ init_subagent_state_cache();
466960
467737
  init_transport2();
466961
467738
  await __promiseAll([
466962
467739
  init_scheduler(),
@@ -472289,7 +473066,7 @@ import {
472289
473066
  copyFileSync as copyFileSync3,
472290
473067
  existsSync as existsSync65,
472291
473068
  mkdirSync as mkdirSync48,
472292
- readdirSync as readdirSync26,
473069
+ readdirSync as readdirSync27,
472293
473070
  readFileSync as readFileSync49,
472294
473071
  writeFileSync as writeFileSync40
472295
473072
  } from "node:fs";
@@ -472585,7 +473362,7 @@ function migrateLocalBackendTranscripts(input) {
472585
473362
  };
472586
473363
  if (!existsSync65(conversationsDir))
472587
473364
  return result3;
472588
- for (const name of readdirSync26(conversationsDir)) {
473365
+ for (const name of readdirSync27(conversationsDir)) {
472589
473366
  const conversationDir = join97(conversationsDir, name);
472590
473367
  const messagesPath = join97(conversationDir, "messages.jsonl");
472591
473368
  const manifestPath = join97(conversationDir, "manifest.json");
@@ -472827,7 +473604,7 @@ var init_memory_tokens = __esm(() => {
472827
473604
  });
472828
473605
 
472829
473606
  // src/cli/subcommands/memory.ts
472830
- import { cpSync, existsSync as existsSync66, mkdirSync as mkdirSync49, rmSync as rmSync22, statSync as statSync25 } from "node:fs";
473607
+ import { cpSync, existsSync as existsSync66, mkdirSync as mkdirSync49, rmSync as rmSync23, statSync as statSync25 } from "node:fs";
472831
473608
  import { readdir as readdir12 } from "node:fs/promises";
472832
473609
  import { dirname as dirname38, join as join98 } from "node:path";
472833
473610
  import { parseArgs as parseArgs11 } from "node:util";
@@ -473035,7 +473812,7 @@ async function runMemorySubcommand(argv, deps = {}) {
473035
473812
  return 1;
473036
473813
  }
473037
473814
  const root2 = getMemoryRoot(agentId);
473038
- rmSync22(root2, { recursive: true, force: true });
473815
+ rmSync23(root2, { recursive: true, force: true });
473039
473816
  cpSync(backupPath, root2, { recursive: true });
473040
473817
  console.log(JSON.stringify({ restoredFrom: backupPath }, null, 2));
473041
473818
  return 0;
@@ -473100,7 +473877,7 @@ var init_memory7 = __esm(() => {
473100
473877
  });
473101
473878
 
473102
473879
  // src/backend/local/transcript-search.ts
473103
- import { existsSync as existsSync67, readdirSync as readdirSync27, readFileSync as readFileSync50, statSync as statSync26 } from "node:fs";
473880
+ import { existsSync as existsSync67, readdirSync as readdirSync28, readFileSync as readFileSync50, statSync as statSync26 } from "node:fs";
473104
473881
  import { join as join99 } from "node:path";
473105
473882
  function readJsonFile3(path47) {
473106
473883
  if (!existsSync67(path47))
@@ -473439,7 +474216,7 @@ function conversationDirectories(storageDir) {
473439
474216
  if (!existsSync67(conversationsDir))
473440
474217
  return [];
473441
474218
  try {
473442
- return readdirSync27(conversationsDir).map((entry) => join99(conversationsDir, entry)).filter((entryPath) => statSync26(entryPath).isDirectory());
474219
+ return readdirSync28(conversationsDir).map((entry) => join99(conversationsDir, entry)).filter((entryPath) => statSync26(entryPath).isDirectory());
473443
474220
  } catch {
473444
474221
  return [];
473445
474222
  }
@@ -474503,10 +475280,10 @@ import {
474503
475280
  lstatSync as lstatSync4,
474504
475281
  mkdirSync as mkdirSync50,
474505
475282
  mkdtempSync as mkdtempSync5,
474506
- readdirSync as readdirSync28,
475283
+ readdirSync as readdirSync29,
474507
475284
  readFileSync as readFileSync51,
474508
475285
  renameSync as renameSync12,
474509
- rmSync as rmSync23,
475286
+ rmSync as rmSync24,
474510
475287
  writeFileSync as writeFileSync41
474511
475288
  } from "node:fs";
474512
475289
  import { tmpdir as tmpdir14 } from "node:os";
@@ -474644,7 +475421,7 @@ function validatePackageSource(packageDirectory) {
474644
475421
  }
474645
475422
  function copyPackageDirectory(sourceRoot, targetRoot) {
474646
475423
  mkdirSync50(targetRoot, { recursive: true });
474647
- for (const entry of readdirSync28(sourceRoot, { withFileTypes: true })) {
475424
+ for (const entry of readdirSync29(sourceRoot, { withFileTypes: true })) {
474648
475425
  if (SKIPPED_PACKAGE_COPY_NAMES.has(entry.name))
474649
475426
  continue;
474650
475427
  const sourcePath = path47.join(sourceRoot, entry.name);
@@ -474676,7 +475453,7 @@ function shouldSkipDependencyPath(relativeParts, installedPackageName) {
474676
475453
  function copyDependencyDirectoryFiltered(params) {
474677
475454
  let copied = false;
474678
475455
  const relativeParts = params.relativeParts ?? [];
474679
- for (const entry of readdirSync28(params.sourceRoot, { withFileTypes: true })) {
475456
+ for (const entry of readdirSync29(params.sourceRoot, { withFileTypes: true })) {
474680
475457
  const nextRelativeParts = [...relativeParts, entry.name];
474681
475458
  if (shouldSkipDependencyPath(nextRelativeParts, params.installedPackageName)) {
474682
475459
  continue;
@@ -474727,7 +475504,7 @@ function copyPackageInternalNodeModules(params) {
474727
475504
  }
474728
475505
  function restoreRegistry(registryPath, previousContents) {
474729
475506
  if (previousContents === null) {
474730
- rmSync23(registryPath, { force: true });
475507
+ rmSync24(registryPath, { force: true });
474731
475508
  return;
474732
475509
  }
474733
475510
  mkdirSync50(path47.dirname(registryPath), { recursive: true });
@@ -474736,17 +475513,17 @@ function restoreRegistry(registryPath, previousContents) {
474736
475513
  function removeIfExists(targetPath) {
474737
475514
  if (!targetPath)
474738
475515
  return;
474739
- rmSync23(targetPath, { force: true, recursive: true });
475516
+ rmSync24(targetPath, { force: true, recursive: true });
474740
475517
  }
474741
475518
  function restoreDestination(params) {
474742
- rmSync23(params.destinationRoot, { force: true, recursive: true });
475519
+ rmSync24(params.destinationRoot, { force: true, recursive: true });
474743
475520
  if (params.backupRoot && existsSync68(params.backupRoot)) {
474744
475521
  renameSync12(params.backupRoot, params.destinationRoot);
474745
475522
  }
474746
475523
  }
474747
475524
  function restoreDestinationIfNeeded(params) {
474748
475525
  if (!params.backupRoot || !existsSync68(params.backupRoot)) {
474749
- rmSync23(params.destinationRoot, { force: true, recursive: true });
475526
+ rmSync24(params.destinationRoot, { force: true, recursive: true });
474750
475527
  return;
474751
475528
  }
474752
475529
  restoreDestination(params);
@@ -474788,7 +475565,7 @@ function installPreparedManagedModPackage(params) {
474788
475565
  }
474789
475566
  if (existsSync68(destinationRoot)) {
474790
475567
  backupRoot = makeSiblingTempDirectory(destinationRoot, "backup");
474791
- rmSync23(backupRoot, { force: true, recursive: true });
475568
+ rmSync24(backupRoot, { force: true, recursive: true });
474792
475569
  renameSync12(destinationRoot, backupRoot);
474793
475570
  destinationNeedsRollback = true;
474794
475571
  }
@@ -475091,7 +475868,7 @@ function inferCompatibilityModEntries(packageDirectory) {
475091
475868
  throw new Error(`Package mods directory must not be a symlink: mods`);
475092
475869
  }
475093
475870
  if (stats.isDirectory()) {
475094
- const entries2 = readdirSync28(modsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && isModFileExtension(path47.extname(entry.name))).map((entry) => `mods/${entry.name}`).sort();
475871
+ const entries2 = readdirSync29(modsDirectory, { withFileTypes: true }).filter((entry) => entry.isFile() && isModFileExtension(path47.extname(entry.name))).map((entry) => `mods/${entry.name}`).sort();
475095
475872
  if (entries2.length > 0)
475096
475873
  return entries2;
475097
475874
  }
@@ -475239,7 +476016,7 @@ async function installNpmManagedModPackage(params) {
475239
476016
  packageDirectory
475240
476017
  });
475241
476018
  } finally {
475242
- rmSync23(tempRoot, { force: true, recursive: true });
476019
+ rmSync24(tempRoot, { force: true, recursive: true });
475243
476020
  }
475244
476021
  }
475245
476022
  async function installGitManagedModPackage(params) {
@@ -475271,7 +476048,7 @@ async function installGitManagedModPackage(params) {
475271
476048
  packageInfo
475272
476049
  });
475273
476050
  } finally {
475274
- rmSync23(tempRoot, { force: true, recursive: true });
476051
+ rmSync24(tempRoot, { force: true, recursive: true });
475275
476052
  }
475276
476053
  }
475277
476054
  async function updateNpmManagedModPackage(params) {
@@ -475302,7 +476079,7 @@ async function updateNpmManagedModPackage(params) {
475302
476079
  previousVersion: existing.version
475303
476080
  };
475304
476081
  } finally {
475305
- rmSync23(tempRoot, { force: true, recursive: true });
476082
+ rmSync24(tempRoot, { force: true, recursive: true });
475306
476083
  }
475307
476084
  }
475308
476085
  async function updateGitManagedModPackage(params) {
@@ -475344,7 +476121,7 @@ async function updateGitManagedModPackage(params) {
475344
476121
  previousVersion: existing.version
475345
476122
  };
475346
476123
  } finally {
475347
- rmSync23(tempRoot, { force: true, recursive: true });
476124
+ rmSync24(tempRoot, { force: true, recursive: true });
475348
476125
  }
475349
476126
  }
475350
476127
  var SKIPPED_PACKAGE_COPY_NAMES, spawnNpmInstallProcessOverride = null, spawnGitInstallProcess, platformOverride2 = null;
@@ -475363,7 +476140,7 @@ import {
475363
476140
  existsSync as existsSync69,
475364
476141
  lstatSync as lstatSync5,
475365
476142
  mkdirSync as mkdirSync51,
475366
- rmSync as rmSync24,
476143
+ rmSync as rmSync25,
475367
476144
  writeFileSync as writeFileSync42
475368
476145
  } from "node:fs";
475369
476146
  import path48 from "node:path";
@@ -475472,7 +476249,7 @@ function scaffoldLocalModPackage(options) {
475472
476249
  writeFileSync42(readmePath, createReadme(packageName));
475473
476250
  writeFileSync42(modGuidePath, createModGuide(packageName, manifestEntry));
475474
476251
  } catch (error5) {
475475
- rmSync24(outputDirectory, { force: true, recursive: true });
476252
+ rmSync25(outputDirectory, { force: true, recursive: true });
475476
476253
  throw error5;
475477
476254
  }
475478
476255
  return {
@@ -476009,7 +476786,7 @@ var init_sandbox_files = __esm(() => {
476009
476786
 
476010
476787
  // src/cli/subcommands/sandbox.ts
476011
476788
  import { readFile as readFile29, stat as stat15, writeFile as writeFile19 } from "node:fs/promises";
476012
- import { basename as basename29, resolve as resolve40 } from "node:path";
476789
+ import { basename as basename30, resolve as resolve40 } from "node:path";
476013
476790
  import { parseArgs as parseArgs16 } from "node:util";
476014
476791
  function printUsage13() {
476015
476792
  console.log(`
@@ -476160,13 +476937,13 @@ async function runSandboxSubcommand(argv, deps = {}) {
476160
476937
  throw new Error(`${localPath2} is not a file`);
476161
476938
  const data2 = await (deps.readLocalFile ?? readFile29)(localPath2);
476162
476939
  const sandbox2 = await ensureSandbox();
476163
- const result3 = await (deps.uploadFile ?? uploadFileToSandbox)(sandbox2.sandboxId, { blob: new Blob([data2]), name: basename29(localPath2) });
476940
+ const result3 = await (deps.uploadFile ?? uploadFileToSandbox)(sandbox2.sandboxId, { blob: new Blob([data2]), name: basename30(localPath2) });
476164
476941
  console.log(JSON.stringify({ ...result3, ...targetOutput }, null, 2));
476165
476942
  return 0;
476166
476943
  }
476167
476944
  const sandbox = await ensureSandbox();
476168
476945
  const data = await (deps.downloadFile ?? downloadFileFromSandbox)(sandbox.sandboxId, path49);
476169
- const localPath = resolve40(parsed.values.to ?? basename29(path49));
476946
+ const localPath = resolve40(parsed.values.to ?? basename30(path49));
476170
476947
  await (deps.writeLocalFile ?? writeFile19)(localPath, data);
476171
476948
  console.log(JSON.stringify({
476172
476949
  path: localPath,
@@ -478859,13 +479636,13 @@ import {
478859
479636
  existsSync as existsSync71,
478860
479637
  mkdtempSync as mkdtempSync6,
478861
479638
  readFileSync as readFileSync52,
478862
- rmSync as rmSync25,
479639
+ rmSync as rmSync26,
478863
479640
  statSync as statSync27,
478864
479641
  writeFileSync as writeFileSync43
478865
479642
  } from "node:fs";
478866
479643
  import { mkdir as mkdir16, readdir as readdir13 } from "node:fs/promises";
478867
479644
  import { tmpdir as tmpdir15 } from "node:os";
478868
- import { basename as basename30, dirname as dirname40, join as join102, normalize as normalize5, resolve as resolve41, sep as sep8 } from "node:path";
479645
+ import { basename as basename31, dirname as dirname40, join as join102, normalize as normalize5, resolve as resolve41, sep as sep8 } from "node:path";
478869
479646
  import { parseArgs as parseArgs20, TextDecoder as TextDecoder2, TextEncoder as TextEncoder2 } from "node:util";
478870
479647
  function printUsage17() {
478871
479648
  console.log(`
@@ -479039,7 +479816,7 @@ function parseDirectSkillFileUrlSpecifier(input) {
479039
479816
  if (url2.protocol !== "https:" && !(url2.protocol === "http:" && isLocalhostHostname(url2.hostname))) {
479040
479817
  return null;
479041
479818
  }
479042
- if (basename30(url2.pathname).toLowerCase() !== "skill.md")
479819
+ if (basename31(url2.pathname).toLowerCase() !== "skill.md")
479043
479820
  return null;
479044
479821
  return { url: url2.toString() };
479045
479822
  }
@@ -479205,7 +479982,7 @@ async function downloadDirectSkillFileSource(location, options = {}) {
479205
479982
  writeFileSync43(join102(sourceDir, "SKILL.md"), skillText, "utf8");
479206
479983
  return { tmpDir, sourceDir };
479207
479984
  } catch (error5) {
479208
- rmSync25(tmpDir, { recursive: true, force: true });
479985
+ rmSync26(tmpDir, { recursive: true, force: true });
479209
479986
  throw error5;
479210
479987
  }
479211
479988
  }
@@ -479287,7 +480064,7 @@ function getSkillName(sourceDir) {
479287
480064
  const skillMd = readFileSync52(join102(sourceDir, "SKILL.md"), "utf8");
479288
480065
  const { frontmatter } = parseFrontmatter(skillMd);
479289
480066
  const frontmatterName = frontmatter.name;
479290
- const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename30(sourceDir);
480067
+ const name = typeof frontmatterName === "string" && frontmatterName.trim() ? frontmatterName : basename31(sourceDir);
479291
480068
  return sanitizeSkillName(name);
479292
480069
  }
479293
480070
  async function installSkillDirectory(params) {
@@ -479308,12 +480085,12 @@ async function installSkillDirectory(params) {
479308
480085
  if (!params.force) {
479309
480086
  throw new Error(`Skill "${name}" already exists at ${targetPath}. Re-run with --force to replace it.`);
479310
480087
  }
479311
- rmSync25(targetPath, { recursive: true, force: true });
480088
+ rmSync26(targetPath, { recursive: true, force: true });
479312
480089
  }
479313
480090
  await mkdir16(skillsDir, { recursive: true });
479314
480091
  cpSync2(sourceDir, targetPath, {
479315
480092
  recursive: true,
479316
- filter: (source) => basename30(source) !== ".git"
480093
+ filter: (source) => basename31(source) !== ".git"
479317
480094
  });
479318
480095
  return { name, path: normalize5(targetPath) };
479319
480096
  }
@@ -479359,7 +480136,7 @@ async function deleteSkillDirectory(params) {
479359
480136
  if (!statSync27(targetPath).isDirectory()) {
479360
480137
  throw new Error(`Skill path is not a directory: ${targetPath}`);
479361
480138
  }
479362
- rmSync25(targetPath, { recursive: true, force: true });
480139
+ rmSync26(targetPath, { recursive: true, force: true });
479363
480140
  return { name, path: normalize5(targetPath) };
479364
480141
  }
479365
480142
  async function loadSkillMemorySyncFn() {
@@ -479423,7 +480200,7 @@ async function installSkill(specifier, agentId, force) {
479423
480200
  };
479424
480201
  } finally {
479425
480202
  if (tmpDir)
479426
- rmSync25(tmpDir, { recursive: true, force: true });
480203
+ rmSync26(tmpDir, { recursive: true, force: true });
479427
480204
  }
479428
480205
  }
479429
480206
  async function getAgentMemoryDir(agentId) {
@@ -480033,7 +480810,7 @@ import {
480033
480810
  stat as stat17,
480034
480811
  writeFile as writeFile20
480035
480812
  } from "node:fs/promises";
480036
- import { basename as basename31, join as join104 } from "node:path";
480813
+ import { basename as basename32, join as join104 } from "node:path";
480037
480814
  function fileTimestamp(startedAt) {
480038
480815
  if (!startedAt)
480039
480816
  return "unknown-date";
@@ -480201,10 +480978,10 @@ async function runTrajectoryExport(options) {
480201
480978
  if (!supported.includes(explicit.source)) {
480202
480979
  throw new Error(`Unknown source "${explicit.source}" in --transcript. The installed trajectory package supports: ${supported.join(", ")}.`);
480203
480980
  }
480204
- await exportTranscript(explicit.source, basename31(explicit.path).replace(/\.[^.]+$/, ""), explicit.path, () => readFile31(explicit.path, "utf-8"));
480981
+ await exportTranscript(explicit.source, basename32(explicit.path).replace(/\.[^.]+$/, ""), explicit.path, () => readFile31(explicit.path, "utf-8"));
480205
480982
  }
480206
480983
  for (const checkpoint of options.deepagents ?? []) {
480207
- await exportCheckpoint(checkpoint, `${basename31(checkpoint.path)}-${checkpoint.threadId}`);
480984
+ await exportCheckpoint(checkpoint, `${basename32(checkpoint.path)}-${checkpoint.threadId}`);
480208
480985
  }
480209
480986
  manifest2.sessions.sort((a2, b3) => (a2.startedAt ?? "").localeCompare(b3.startedAt ?? ""));
480210
480987
  await writeFile20(join104(options.outDir, MANIFEST_NAME), JSON.stringify(manifest2, null, 2), "utf-8");
@@ -483652,7 +484429,7 @@ var init_message_channel_gateway_tool = __esm(() => {
483652
484429
  });
483653
484430
 
483654
484431
  // src/channels/custom/scaffolding.ts
483655
- import { existsSync as existsSync72, mkdirSync as mkdirSync52, rmSync as rmSync26, writeFileSync as writeFileSync44 } from "node:fs";
484432
+ import { existsSync as existsSync72, mkdirSync as mkdirSync52, rmSync as rmSync27, writeFileSync as writeFileSync44 } from "node:fs";
483656
484433
  function removeUserPlugin(channelId) {
483657
484434
  if (FIRST_PARTY_SET.has(channelId)) {
483658
484435
  return;
@@ -483665,7 +484442,7 @@ function removeUserPlugin(channelId) {
483665
484442
  return;
483666
484443
  }
483667
484444
  try {
483668
- rmSync26(channelDir, { recursive: true, force: true });
484445
+ rmSync27(channelDir, { recursive: true, force: true });
483669
484446
  } catch (err) {
483670
484447
  console.error(`[channels] Failed to remove plugin folder ${channelDir}:`, err);
483671
484448
  }
@@ -490432,7 +491209,7 @@ var BYTES_PER_TOKEN = 4;
490432
491209
 
490433
491210
  // src/cli/helpers/window-title-config.ts
490434
491211
  import { homedir as homedir32 } from "node:os";
490435
- import { basename as basename32, resolve as resolve42 } from "node:path";
491212
+ import { basename as basename33, resolve as resolve42 } from "node:path";
490436
491213
  function isWindowTitleField(value) {
490437
491214
  return WINDOW_TITLE_FIELDS.includes(value);
490438
491215
  }
@@ -490591,7 +491368,7 @@ function terminalTitleProjectName(data) {
490591
491368
  if (!directory)
490592
491369
  return null;
490593
491370
  const resolved2 = resolve42(directory);
490594
- const name = basename32(resolved2) || formatDirectoryDisplay(resolved2) || resolved2;
491371
+ const name = basename33(resolved2) || formatDirectoryDisplay(resolved2) || resolved2;
490595
491372
  return truncateTerminalTitlePart(name, 24);
490596
491373
  }
490597
491374
  function titleDirectory(data) {
@@ -504149,7 +504926,7 @@ import {
504149
504926
  mkdirSync as mkdirSync55,
504150
504927
  mkdtempSync as mkdtempSync7,
504151
504928
  readFileSync as readFileSync55,
504152
- rmSync as rmSync27,
504929
+ rmSync as rmSync28,
504153
504930
  writeFileSync as writeFileSync47
504154
504931
  } from "node:fs";
504155
504932
  import { tmpdir as tmpdir16 } from "node:os";
@@ -504519,7 +505296,7 @@ async function installGithubApp(options) {
504519
505296
  agentUrl: resolvedAgentId ? buildAgentReference(resolvedAgentId) : null
504520
505297
  };
504521
505298
  } finally {
504522
- rmSync27(tempDir, { recursive: true, force: true });
505299
+ rmSync28(tempDir, { recursive: true, force: true });
504523
505300
  }
504524
505301
  }
504525
505302
  var DEFAULT_WORKFLOW_PATH = ".github/workflows/letta.yml", ALTERNATE_WORKFLOW_PATH = ".github/workflows/letta-code.yml";
@@ -522801,7 +523578,7 @@ var init_system_reminders2 = __esm(() => {
522801
523578
 
522802
523579
  // src/cli/app/use-conversation-loop.ts
522803
523580
  import { randomUUID as randomUUID68 } from "node:crypto";
522804
- function sleep11(ms) {
523581
+ function sleep12(ms) {
522805
523582
  return new Promise((resolve44) => setTimeout(resolve44, ms));
522806
523583
  }
522807
523584
  function makeExecutionPhaseHook(setExecutionPhase) {
@@ -522932,7 +523709,7 @@ function useConversationLoop(ctx) {
522932
523709
  const currentSettings = await settingsManager.getSettingsWithSecureTokens();
522933
523710
  const hasCloudAuth = Boolean(process.env.LETTA_API_KEY || currentSettings.refreshToken || currentSettings.env?.LETTA_API_KEY);
522934
523711
  setThinkingMessage(getRandomThinkingVerb());
522935
- await sleep11(250);
523712
+ await sleep12(250);
522936
523713
  const lineId = uid("assistant");
522937
523714
  buffersRef.current.byId.set(lineId, {
522938
523715
  kind: "assistant",
@@ -522957,7 +523734,7 @@ function useConversationLoop(ctx) {
522957
523734
  });
522958
523735
  buffersRef.current.tokenCount += Buffer.byteLength(chunk2, "utf8");
522959
523736
  refreshDerived();
522960
- await sleep11(chunk2 === `
523737
+ await sleep12(chunk2 === `
522961
523738
  ` ? 70 : 120);
522962
523739
  }
522963
523740
  const finalLine = buffersRef.current.byId.get(lineId);
@@ -529671,7 +530448,7 @@ __export(exports_worktree_diff_list, {
529671
530448
  listWorktreeDiffOptions: () => listWorktreeDiffOptions
529672
530449
  });
529673
530450
  import { execFile as execFileCb8 } from "node:child_process";
529674
- import { basename as basename33 } from "node:path";
530451
+ import { basename as basename34 } from "node:path";
529675
530452
  import { promisify as promisify23 } from "node:util";
529676
530453
  async function runGit9(cwd2, args) {
529677
530454
  try {
@@ -529720,7 +530497,7 @@ function parseWorktreeList(output, currentPath) {
529720
530497
  if (current?.path) {
529721
530498
  worktrees.push({
529722
530499
  path: current.path,
529723
- name: basename33(current.path),
530500
+ name: basename34(current.path),
529724
530501
  branch: current.branch ?? "detached",
529725
530502
  head: current.head ?? "",
529726
530503
  isCurrent: current.path === currentPath,
@@ -529746,7 +530523,7 @@ function parseWorktreeList(output, currentPath) {
529746
530523
  if (current?.path) {
529747
530524
  worktrees.push({
529748
530525
  path: current.path,
529749
- name: basename33(current.path),
530526
+ name: basename34(current.path),
529750
530527
  branch: current.branch ?? "detached",
529751
530528
  head: current.head ?? "",
529752
530529
  isCurrent: current.path === currentPath,
@@ -539736,4 +540513,4 @@ function registerBunOAuthFlows() {
539736
540513
  registerBunOAuthFlows();
539737
540514
  await init_src5().then(() => exports_src2);
539738
540515
 
539739
- //# debugId=69C4BA5DCB08F6E364756E2164756E21
540516
+ //# debugId=23162BCF185F91F064756E2164756E21