@letta-ai/letta-code 0.30.12 → 0.30.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/letta.js CHANGED
@@ -5488,7 +5488,7 @@ var package_default;
5488
5488
  var init_package = __esm(() => {
5489
5489
  package_default = {
5490
5490
  name: "@letta-ai/letta-code",
5491
- version: "0.30.12",
5491
+ version: "0.30.13",
5492
5492
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
5493
5493
  type: "module",
5494
5494
  packageManager: "bun@1.3.0",
@@ -144036,7 +144036,7 @@ var general_purpose_default = `---
144036
144036
  name: general-purpose
144037
144037
  description: Full-capability agent for research, planning, and implementation
144038
144038
  tools: Bash, TaskOutput, Edit, KillBash, LS, MultiEdit, Read, TodoWrite, Write
144039
- model: auto
144039
+ model: inherit
144040
144040
  ---
144041
144041
 
144042
144042
  You are a general-purpose coding agent that can research, plan, and implement.
@@ -149056,6 +149056,7 @@ var init_truncation = __esm(() => {
149056
149056
  LIMITS = {
149057
149057
  BASH_OUTPUT_CHARS: 30000,
149058
149058
  TASK_OUTPUT_CHARS: 30000,
149059
+ BASH_NOTIFICATION_CHARS: 1e4,
149059
149060
  READ_MAX_LINES: 2000,
149060
149061
  READ_MAX_CHARS_PER_LINE: 2000,
149061
149062
  READ_OUTPUT_CHARS: 30000,
@@ -151006,6 +151007,131 @@ async function ask_user_question(args) {
151006
151007
  }
151007
151008
  var init_ask_user_question = () => {};
151008
151009
 
151010
+ // src/utils/message-queue-bridge.ts
151011
+ function setMessageQueueAdder(fn) {
151012
+ queueAdder = fn;
151013
+ if (queueAdder && pendingMessages.length > 0) {
151014
+ for (const message of pendingMessages) {
151015
+ queueAdder(message);
151016
+ }
151017
+ pendingMessages.length = 0;
151018
+ }
151019
+ }
151020
+ function addToMessageQueue(message) {
151021
+ if (queueAdder) {
151022
+ queueAdder(message);
151023
+ return;
151024
+ }
151025
+ if (pendingMessages.length >= MAX_PENDING_MESSAGES) {
151026
+ pendingMessages.shift();
151027
+ }
151028
+ pendingMessages.push(message);
151029
+ }
151030
+ var queueAdder = null, pendingMessages, MAX_PENDING_MESSAGES = 10;
151031
+ var init_message_queue_bridge = __esm(() => {
151032
+ pendingMessages = [];
151033
+ });
151034
+
151035
+ // src/utils/task-notifications.ts
151036
+ function escapeXml(str2) {
151037
+ return str2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
151038
+ }
151039
+ function unescapeXml(str2) {
151040
+ return str2.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
151041
+ }
151042
+ function resolveNotificationScope(parentScope) {
151043
+ if (parentScope?.agentId) {
151044
+ return {
151045
+ agentId: parentScope.agentId,
151046
+ conversationId: parentScope.conversationId || "default"
151047
+ };
151048
+ }
151049
+ try {
151050
+ return {
151051
+ agentId: getCurrentAgentId(),
151052
+ conversationId: getConversationId() ?? "default"
151053
+ };
151054
+ } catch {
151055
+ return;
151056
+ }
151057
+ }
151058
+ function formatTaskNotification(notification) {
151059
+ const escapedSummary = escapeXml(notification.summary);
151060
+ const escapedResult = escapeXml(notification.result);
151061
+ const usageLines = [];
151062
+ if (notification.usage?.totalTokens !== undefined) {
151063
+ usageLines.push(`total_tokens: ${notification.usage.totalTokens}`);
151064
+ }
151065
+ if (notification.usage?.toolUses !== undefined) {
151066
+ usageLines.push(`tool_uses: ${notification.usage.toolUses}`);
151067
+ }
151068
+ if (notification.usage?.durationMs !== undefined) {
151069
+ usageLines.push(`duration_ms: ${notification.usage.durationMs}`);
151070
+ }
151071
+ const usageBlock = usageLines.length ? `
151072
+ <usage>${usageLines.join(`
151073
+ `)}</usage>` : "";
151074
+ return `<task-notification>
151075
+ <task-id>${notification.taskId}</task-id>
151076
+ <status>${notification.status}</status>
151077
+ <summary>${escapedSummary}</summary>
151078
+ <result>${escapedResult}</result>${usageBlock}
151079
+ </task-notification>
151080
+ Full transcript available at: ${notification.outputFile}`;
151081
+ }
151082
+ function extractTaskNotificationsForDisplay(message) {
151083
+ if (!message.includes("<task-notification>")) {
151084
+ return { notifications: [], cleanedText: message };
151085
+ }
151086
+ const notificationRegex = /<task-notification>[\s\S]*?(?:<\/task-notification>|$)(?:\s*Full transcript available at:[^\n]*\n?)?/g;
151087
+ const notifications = [];
151088
+ let match2 = notificationRegex.exec(message);
151089
+ while (match2 !== null) {
151090
+ const xml = match2[0];
151091
+ const summaryMatch = xml.match(/<summary>([\s\S]*?)<\/summary>/);
151092
+ const statusMatch = xml.match(/<status>([\s\S]*?)<\/status>/);
151093
+ const resultMatch = xml.match(/<result>([\s\S]*?)<\/result>/);
151094
+ const result = resultMatch?.[1]?.trim() || "";
151095
+ const isAgentOnlyReminder = result.includes(SYSTEM_REMINDER_OPEN);
151096
+ if (isAgentOnlyReminder) {
151097
+ match2 = notificationRegex.exec(message);
151098
+ continue;
151099
+ }
151100
+ const status = statusMatch?.[1]?.trim();
151101
+ let summary = summaryMatch?.[1]?.trim() || "";
151102
+ summary = unescapeXml(summary);
151103
+ const display = summary || `Agent task ${status || "completed"}`;
151104
+ notifications.push(display);
151105
+ match2 = notificationRegex.exec(message);
151106
+ }
151107
+ const cleanedText = message.replace(notificationRegex, "").replace(/^\s*Full transcript available at:[^\n]*\n?/gm, "").replace(/\n{3,}/g, `
151108
+
151109
+ `).trim();
151110
+ return { notifications, cleanedText };
151111
+ }
151112
+ function appendTaskNotificationEventsToBuffer(summaries, buffer, generateId, flush) {
151113
+ if (summaries.length === 0)
151114
+ return false;
151115
+ for (const summary of summaries) {
151116
+ const eventId = generateId();
151117
+ buffer.byId.set(eventId, {
151118
+ kind: "event",
151119
+ id: eventId,
151120
+ eventType: "task_notification",
151121
+ eventData: {},
151122
+ phase: "finished",
151123
+ summary
151124
+ });
151125
+ buffer.order.push(eventId);
151126
+ }
151127
+ flush?.();
151128
+ return true;
151129
+ }
151130
+ var init_task_notifications = __esm(() => {
151131
+ init_context();
151132
+ init_constants2();
151133
+ });
151134
+
151009
151135
  // src/permissions/shell-analysis.ts
151010
151136
  function tryConsumeSafeRedirect(input, pos) {
151011
151137
  const isAppend = input.startsWith(">>", pos);
@@ -154260,6 +154386,197 @@ var init_shell_env = __esm(() => {
154260
154386
  init_ripgrep_manager();
154261
154387
  });
154262
154388
 
154389
+ // src/tools/impl/github-pull-request-tracker.ts
154390
+ function executableName(value) {
154391
+ return value.replaceAll("\\", "/").split("/").pop()?.toLowerCase() ?? "";
154392
+ }
154393
+ function findExecutableIndex(tokens) {
154394
+ let index = 0;
154395
+ while (ENV_ASSIGNMENT.test(tokens[index] ?? "")) {
154396
+ index += 1;
154397
+ }
154398
+ if (executableName(tokens[index] ?? "") === "env") {
154399
+ index += 1;
154400
+ while (index < tokens.length) {
154401
+ const token = tokens[index] ?? "";
154402
+ if (ENV_ASSIGNMENT.test(token)) {
154403
+ index += 1;
154404
+ continue;
154405
+ }
154406
+ if (token === "-u" || token === "--unset") {
154407
+ index += 2;
154408
+ continue;
154409
+ }
154410
+ if (token.startsWith("-")) {
154411
+ index += 1;
154412
+ continue;
154413
+ }
154414
+ break;
154415
+ }
154416
+ }
154417
+ while (ENV_ASSIGNMENT.test(tokens[index] ?? "")) {
154418
+ index += 1;
154419
+ }
154420
+ if (tokens[index] === "command" || tokens[index] === "&") {
154421
+ index += 1;
154422
+ }
154423
+ return index;
154424
+ }
154425
+ function skipGhGlobalFlags(tokens, startIndex) {
154426
+ let index = startIndex;
154427
+ while (index < tokens.length) {
154428
+ const token = tokens[index] ?? "";
154429
+ if (GH_GLOBAL_FLAGS_WITH_VALUES.has(token)) {
154430
+ index += 2;
154431
+ continue;
154432
+ }
154433
+ if (token.startsWith("--hostname=") || token.startsWith("--repo=") || token.startsWith("-R") && token.length > 2) {
154434
+ index += 1;
154435
+ continue;
154436
+ }
154437
+ break;
154438
+ }
154439
+ return index;
154440
+ }
154441
+ function tokensCreatePullRequest(tokens) {
154442
+ const executableIndex = findExecutableIndex(tokens);
154443
+ if (executableName(tokens[executableIndex] ?? "") !== "gh") {
154444
+ return false;
154445
+ }
154446
+ const prIndex = skipGhGlobalFlags(tokens, executableIndex + 1);
154447
+ if (tokens[prIndex] !== "pr" || tokens[prIndex + 1] !== "create") {
154448
+ return false;
154449
+ }
154450
+ const createArgs = tokens.slice(prIndex + 2);
154451
+ return !createArgs.some((token) => token === "--dry-run" || token === "--web" || token === "-w");
154452
+ }
154453
+ function isShellExecutable2(value) {
154454
+ const name = executableName(value);
154455
+ return /^(ba|z|a|da)?sh$/.test(name) || name === "cmd" || name === "cmd.exe" || name.includes("powershell") || name.includes("pwsh");
154456
+ }
154457
+ function shellScriptFromCommand(tokens) {
154458
+ const executableIndex = findExecutableIndex(tokens);
154459
+ if (!isShellExecutable2(tokens[executableIndex] ?? "")) {
154460
+ return;
154461
+ }
154462
+ for (let index = executableIndex + 1;index < tokens.length; index += 1) {
154463
+ const flag = (tokens[index] ?? "").toLowerCase();
154464
+ if (flag === "-c" || flag === "-lc" || flag === "/c" || flag === "-command") {
154465
+ return tokens[index + 1];
154466
+ }
154467
+ }
154468
+ return;
154469
+ }
154470
+ function isGitHubPullRequestCreateCommand(command) {
154471
+ if (typeof command !== "string") {
154472
+ if (tokensCreatePullRequest(command)) {
154473
+ return true;
154474
+ }
154475
+ const shellScript = shellScriptFromCommand(command);
154476
+ return shellScript ? isGitHubPullRequestCreateCommand(shellScript) : false;
154477
+ }
154478
+ const segments = splitShellSegmentsAllowCommandSubstitution(command) ?? [
154479
+ command
154480
+ ];
154481
+ return segments.some((segment) => tokensCreatePullRequest(tokenizeShellWords(segment)));
154482
+ }
154483
+ function tagFromOutputLine(line) {
154484
+ const match2 = stripAnsi(line).trim().match(GITHUB_PR_URL);
154485
+ if (!match2) {
154486
+ return;
154487
+ }
154488
+ const [, owner, repo, number7] = match2;
154489
+ if (!owner || !repo || !number7) {
154490
+ return;
154491
+ }
154492
+ return `github:pull-request:${owner.toLowerCase()}:${repo.toLowerCase()}:${number7}`;
154493
+ }
154494
+ function appendOutputTail(outputByStream, text, stream11) {
154495
+ outputByStream[stream11] = `${outputByStream[stream11]}${text}`.slice(-MAX_TRACKED_OUTPUT_CHARS);
154496
+ }
154497
+ async function appendConversationTags(backend, conversationId, tags) {
154498
+ const conversation = await backend.retrieveConversation(conversationId);
154499
+ const currentTags = typeof conversation === "object" && conversation !== null ? Reflect.get(conversation, "tags") : undefined;
154500
+ const existingTags = Array.isArray(currentTags) ? currentTags.filter((tag) => typeof tag === "string") : [];
154501
+ const missingTags = tags.filter((tag) => !existingTags.includes(tag));
154502
+ if (missingTags.length === 0) {
154503
+ return;
154504
+ }
154505
+ await backend.updateConversation(conversationId, {
154506
+ tags: [...new Set([...existingTags, ...missingTags])]
154507
+ });
154508
+ }
154509
+ function queueConversationTagUpdate(backend, conversationId, tags) {
154510
+ const previous = conversationTagUpdateTails.get(conversationId);
154511
+ const update2 = (previous ?? Promise.resolve()).then(() => appendConversationTags(backend, conversationId, tags)).catch((error54) => {
154512
+ debugLog("github-pr-tracking", `Failed to tag conversation ${conversationId}`, error54);
154513
+ });
154514
+ conversationTagUpdateTails.set(conversationId, update2);
154515
+ update2.finally(() => {
154516
+ if (conversationTagUpdateTails.get(conversationId) === update2) {
154517
+ conversationTagUpdateTails.delete(conversationId);
154518
+ }
154519
+ });
154520
+ return update2;
154521
+ }
154522
+ function createGitHubPullRequestOutputTracker(command, options3) {
154523
+ if (!isGitHubPullRequestCreateCommand(command)) {
154524
+ return;
154525
+ }
154526
+ const conversationId = options3?.conversationId ?? getRuntimeContext()?.conversationId;
154527
+ if (!conversationId || conversationId === "default") {
154528
+ return;
154529
+ }
154530
+ const outputByStream = {
154531
+ stdout: "",
154532
+ stderr: ""
154533
+ };
154534
+ let finishPromise;
154535
+ return {
154536
+ append(text, stream11) {
154537
+ if (finishPromise) {
154538
+ return;
154539
+ }
154540
+ appendOutputTail(outputByStream, text, stream11);
154541
+ },
154542
+ finish() {
154543
+ if (finishPromise) {
154544
+ return finishPromise;
154545
+ }
154546
+ const tags = new Set;
154547
+ for (const line of `${outputByStream.stdout}
154548
+ ${outputByStream.stderr}`.split(/\r\n|\n|\r/)) {
154549
+ const tag = tagFromOutputLine(line);
154550
+ if (tag) {
154551
+ tags.add(tag);
154552
+ }
154553
+ }
154554
+ if (tags.size === 0) {
154555
+ finishPromise = Promise.resolve();
154556
+ return finishPromise;
154557
+ }
154558
+ try {
154559
+ finishPromise = queueConversationTagUpdate(options3?.backend ?? getBackend(), conversationId, [...tags]);
154560
+ } catch (error54) {
154561
+ debugLog("github-pr-tracking", `Failed to tag conversation ${conversationId}`, error54);
154562
+ finishPromise = Promise.resolve();
154563
+ }
154564
+ return finishPromise;
154565
+ }
154566
+ };
154567
+ }
154568
+ var ENV_ASSIGNMENT, GITHUB_PR_URL, MAX_TRACKED_OUTPUT_CHARS = 30000, GH_GLOBAL_FLAGS_WITH_VALUES, conversationTagUpdateTails;
154569
+ var init_github_pull_request_tracker = __esm(() => {
154570
+ init_strip_ansi();
154571
+ init_backend2();
154572
+ init_runtime_context();
154573
+ init_debug();
154574
+ ENV_ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=.*/;
154575
+ GITHUB_PR_URL = /^https?:\/\/github\.com\/([^/\s]+)\/([^/\s]+)\/pull\/([1-9]\d*)\/?$/i;
154576
+ GH_GLOBAL_FLAGS_WITH_VALUES = new Set(["--hostname", "--repo", "-R"]);
154577
+ conversationTagUpdateTails = new Map;
154578
+ });
154579
+
154263
154580
  // src/tools/impl/shell-runner.ts
154264
154581
  import { spawn as spawn2 } from "node:child_process";
154265
154582
  function buildSpawnError(err, executable, cwd) {
@@ -154281,145 +154598,293 @@ function buildSpawnError(err, executable, cwd) {
154281
154598
  execError.reason = reason;
154282
154599
  return execError;
154283
154600
  }
154284
- function spawnWithLauncher(launcher, options3) {
154285
- return new Promise((resolve8, reject) => {
154286
- const [executable, ...args] = launcher;
154287
- if (!executable) {
154288
- reject(new ShellExecutionError("Executable is required"));
154289
- return;
154601
+ function buildTimeoutError(stdout, stderr, code2) {
154602
+ return Object.assign(new Error("Command timed out"), {
154603
+ killed: true,
154604
+ signal: "SIGTERM",
154605
+ stdout,
154606
+ stderr,
154607
+ code: code2
154608
+ });
154609
+ }
154610
+ function buildAbortError(stdout, stderr) {
154611
+ return Object.assign(new Error("The operation was aborted"), {
154612
+ name: "AbortError",
154613
+ code: "ABORT_ERR",
154614
+ stdout,
154615
+ stderr
154616
+ });
154617
+ }
154618
+ function buildPtyEnv(env3) {
154619
+ const ptyEnv = {};
154620
+ for (const [key, value] of Object.entries(env3)) {
154621
+ if (value !== undefined) {
154622
+ ptyEnv[key] = value;
154623
+ }
154624
+ }
154625
+ ptyEnv.TERM = ptyEnv.TERM || "xterm-256color";
154626
+ ptyEnv.COLORTERM = ptyEnv.COLORTERM || "truecolor";
154627
+ return ptyEnv;
154628
+ }
154629
+ function killChildProcessTree(childProcess, signal = "SIGTERM") {
154630
+ if (!childProcess.pid) {
154631
+ return;
154632
+ }
154633
+ if (process.platform === "win32") {
154634
+ const taskkill = spawn2("taskkill.exe", ["/pid", String(childProcess.pid), "/t", "/f"], {
154635
+ stdio: "ignore",
154636
+ windowsHide: true
154637
+ });
154638
+ taskkill.once("error", () => {
154639
+ try {
154640
+ childProcess.kill("SIGKILL");
154641
+ } catch {}
154642
+ });
154643
+ taskkill.once("close", (code2) => {
154644
+ if (code2 === 0)
154645
+ return;
154646
+ try {
154647
+ childProcess.kill("SIGKILL");
154648
+ } catch {}
154649
+ });
154650
+ return;
154651
+ }
154652
+ try {
154653
+ process.kill(-childProcess.pid, signal);
154654
+ } catch {
154655
+ try {
154656
+ childProcess.kill(signal);
154657
+ } catch {}
154658
+ }
154659
+ }
154660
+ function spawnPipeProcess(launcher, options3, events) {
154661
+ const [executable, ...args] = launcher;
154662
+ if (!executable) {
154663
+ throw new ShellExecutionError("Executable is required");
154664
+ }
154665
+ const childProcess = spawn2(executable, args, {
154666
+ cwd: options3.cwd,
154667
+ env: options3.env,
154668
+ shell: false,
154669
+ stdio: ["ignore", "pipe", "pipe"],
154670
+ detached: process.platform !== "win32"
154671
+ });
154672
+ childProcess.stdout?.on("data", (chunk) => {
154673
+ events.output(chunk, "stdout");
154674
+ });
154675
+ childProcess.stderr?.on("data", (chunk) => {
154676
+ events.output(chunk, "stderr");
154677
+ });
154678
+ childProcess.on("error", events.error);
154679
+ childProcess.on("close", events.close);
154680
+ return {
154681
+ kill(signal) {
154682
+ killChildProcessTree(childProcess, signal);
154683
+ },
154684
+ write(_input) {}
154685
+ };
154686
+ }
154687
+ function spawnPtyBridgeProcess(launcher, options3, events) {
154688
+ const [executable, ...args] = launcher;
154689
+ if (!executable) {
154690
+ throw new ShellExecutionError("Executable is required");
154691
+ }
154692
+ const childProcess = spawn2("node", [
154693
+ "-e",
154694
+ NODE_PTY_BRIDGE_SCRIPT,
154695
+ JSON.stringify({ executable, args, cwd: options3.cwd })
154696
+ ], {
154697
+ cwd: options3.cwd,
154698
+ env: buildPtyEnv(options3.env),
154699
+ shell: false,
154700
+ stdio: ["pipe", "pipe", "pipe"],
154701
+ detached: process.platform !== "win32"
154702
+ });
154703
+ childProcess.stdout?.on("data", (chunk) => {
154704
+ events.output(chunk, "stdout");
154705
+ });
154706
+ childProcess.stderr?.on("data", (chunk) => {
154707
+ events.output(chunk, "stderr");
154708
+ });
154709
+ childProcess.on("error", events.error);
154710
+ childProcess.on("close", events.close);
154711
+ return {
154712
+ kill(signal) {
154713
+ killChildProcessTree(childProcess, signal);
154714
+ },
154715
+ write(input) {
154716
+ childProcess.stdin?.write(input);
154290
154717
  }
154291
- if (!isUsableDirectory(options3.cwd)) {
154292
- reject(buildSpawnError({ code: "ENOENT" }, executable, options3.cwd));
154718
+ };
154719
+ }
154720
+ function spawnNativePtyProcess(launcher, options3, events) {
154721
+ const [executable, ...args] = launcher;
154722
+ if (!executable) {
154723
+ throw new ShellExecutionError("Executable is required");
154724
+ }
154725
+ const pty = __require("node-pty");
154726
+ const ptyProcess = pty.spawn(executable, args, {
154727
+ name: "xterm-256color",
154728
+ cols: 80,
154729
+ rows: 24,
154730
+ cwd: options3.cwd,
154731
+ env: buildPtyEnv(options3.env)
154732
+ });
154733
+ ptyProcess.onData((data) => events.output(data, "stdout"));
154734
+ ptyProcess.onExit(({ exitCode }) => {
154735
+ events.close(typeof exitCode === "number" ? exitCode : null);
154736
+ });
154737
+ return {
154738
+ kill(signal) {
154739
+ ptyProcess.kill(typeof signal === "string" ? signal : undefined);
154740
+ },
154741
+ write(input) {
154742
+ ptyProcess.write(input);
154743
+ }
154744
+ };
154745
+ }
154746
+ function spawnPtyProcess(launcher, options3, events) {
154747
+ return typeof Bun !== "undefined" ? spawnPtyBridgeProcess(launcher, options3, events) : spawnNativePtyProcess(launcher, options3, events);
154748
+ }
154749
+ function startShellProcess(launcher, options3) {
154750
+ const [executable] = launcher;
154751
+ if (!executable) {
154752
+ throw new ShellExecutionError("Executable is required");
154753
+ }
154754
+ if (!isUsableDirectory(options3.cwd)) {
154755
+ throw buildSpawnError({ code: "ENOENT" }, executable, options3.cwd);
154756
+ }
154757
+ noteExpectedWorktreeForLauncher(launcher, options3.cwd);
154758
+ const pullRequestTracker = createGitHubPullRequestOutputTracker(options3.sourceCommand ?? launcher);
154759
+ const stdoutChunks = [];
154760
+ const stderrChunks = [];
154761
+ let completed = false;
154762
+ let timedOut = false;
154763
+ let forceKillTimer;
154764
+ let timeoutTimer;
154765
+ let resolveCompletion;
154766
+ let rejectCompletion;
154767
+ const completion = new Promise((resolve8, reject) => {
154768
+ resolveCompletion = resolve8;
154769
+ rejectCompletion = reject;
154770
+ });
154771
+ const cleanup = () => {
154772
+ if (timeoutTimer) {
154773
+ clearTimeout(timeoutTimer);
154774
+ timeoutTimer = undefined;
154775
+ }
154776
+ if (forceKillTimer) {
154777
+ clearTimeout(forceKillTimer);
154778
+ forceKillTimer = undefined;
154779
+ }
154780
+ options3.signal?.removeEventListener("abort", abortHandler);
154781
+ };
154782
+ let processHandle;
154783
+ const terminateProcess = () => {
154784
+ if (process.platform === "win32") {
154785
+ processHandle.kill("SIGKILL");
154293
154786
  return;
154294
154787
  }
154295
- noteExpectedWorktreeForLauncher(launcher, options3.cwd);
154296
- const childProcess = spawn2(executable, args, {
154297
- cwd: options3.cwd,
154298
- env: options3.env,
154299
- shell: false,
154300
- stdio: ["ignore", "pipe", "pipe"],
154301
- detached: process.platform !== "win32"
154302
- });
154303
- const killProcessTree = (signal) => {
154304
- if (childProcess.pid) {
154305
- if (process.platform === "win32") {
154306
- const taskkill = spawn2("taskkill.exe", ["/pid", String(childProcess.pid), "/t", "/f"], {
154307
- stdio: "ignore",
154308
- windowsHide: true
154309
- });
154310
- taskkill.once("error", () => {
154311
- try {
154312
- childProcess.kill("SIGKILL");
154313
- } catch {}
154314
- });
154315
- taskkill.once("close", (code2) => {
154316
- if (code2 === 0)
154317
- return;
154318
- try {
154319
- childProcess.kill("SIGKILL");
154320
- } catch {}
154321
- });
154322
- return;
154788
+ processHandle.kill("SIGTERM");
154789
+ if (!forceKillTimer) {
154790
+ forceKillTimer = setTimeout(() => {
154791
+ if (!completed) {
154792
+ processHandle.kill("SIGKILL");
154323
154793
  }
154324
- try {
154325
- process.kill(-childProcess.pid, signal);
154326
- } catch {
154327
- try {
154328
- childProcess.kill(signal);
154329
- } catch {}
154794
+ }, FORCE_KILL_GRACE_MS);
154795
+ }
154796
+ };
154797
+ const abortHandler = () => {
154798
+ terminateProcess();
154799
+ };
154800
+ const events = {
154801
+ output(data, stream11) {
154802
+ const text = Buffer.isBuffer(data) ? data.toString("utf8") : data;
154803
+ pullRequestTracker?.append(text, stream11);
154804
+ if (options3.captureOutput !== false) {
154805
+ if (stream11 === "stdout") {
154806
+ stdoutChunks.push(Buffer.isBuffer(data) ? data : Buffer.from(data));
154807
+ } else {
154808
+ stderrChunks.push(Buffer.isBuffer(data) ? data : Buffer.from(data));
154330
154809
  }
154331
154810
  }
154332
- };
154333
- const stdoutChunks = [];
154334
- const stderrChunks = [];
154335
- let timedOut = false;
154336
- let killTimer = null;
154337
- let completed = false;
154338
- const terminateProcess = () => {
154339
- if (process.platform === "win32") {
154340
- killProcessTree("SIGKILL");
154811
+ options3.onOutput?.(text, stream11);
154812
+ },
154813
+ error(error54) {
154814
+ if (completed)
154341
154815
  return;
154342
- }
154343
- killProcessTree("SIGTERM");
154344
- if (!killTimer) {
154345
- killTimer = setTimeout(() => {
154346
- if (!completed) {
154347
- killProcessTree("SIGKILL");
154348
- }
154349
- }, FORCE_KILL_GRACE_MS);
154350
- }
154351
- };
154352
- const timeoutId = options3.timeoutMs ? setTimeout(() => {
154353
- timedOut = true;
154354
- terminateProcess();
154355
- }, options3.timeoutMs) : null;
154356
- const abortHandler = () => {
154357
- terminateProcess();
154358
- };
154359
- if (options3.signal) {
154360
- options3.signal.addEventListener("abort", abortHandler, { once: true });
154361
- }
154362
- childProcess.stdout?.on("data", (chunk) => {
154363
- stdoutChunks.push(chunk);
154364
- options3.onOutput?.(chunk.toString("utf8"), "stdout");
154365
- });
154366
- childProcess.stderr?.on("data", (chunk) => {
154367
- stderrChunks.push(chunk);
154368
- options3.onOutput?.(chunk.toString("utf8"), "stderr");
154369
- });
154370
- childProcess.on("error", (err) => {
154371
154816
  completed = true;
154372
- if (timeoutId)
154373
- clearTimeout(timeoutId);
154374
- if (killTimer) {
154375
- clearTimeout(killTimer);
154376
- killTimer = null;
154377
- }
154378
- if (options3.signal) {
154379
- options3.signal.removeEventListener("abort", abortHandler);
154380
- }
154381
- reject(buildSpawnError(err, executable, options3.cwd));
154382
- });
154383
- childProcess.on("close", (code2) => {
154817
+ cleanup();
154818
+ pullRequestTracker?.finish();
154819
+ rejectCompletion(buildSpawnError(error54, executable, options3.cwd));
154820
+ },
154821
+ close(code2) {
154822
+ if (completed)
154823
+ return;
154384
154824
  completed = true;
154385
- if (timeoutId)
154386
- clearTimeout(timeoutId);
154387
- if (killTimer) {
154388
- clearTimeout(killTimer);
154389
- killTimer = null;
154390
- }
154391
- if (options3.signal) {
154392
- options3.signal.removeEventListener("abort", abortHandler);
154393
- }
154825
+ cleanup();
154826
+ pullRequestTracker?.finish();
154394
154827
  const stdout = Buffer.concat(stdoutChunks).toString("utf8");
154395
154828
  const stderr = Buffer.concat(stderrChunks).toString("utf8");
154396
154829
  if (timedOut) {
154397
- reject(Object.assign(new Error("Command timed out"), {
154398
- killed: true,
154399
- signal: "SIGTERM",
154400
- stdout,
154401
- stderr,
154402
- code: code2
154403
- }));
154830
+ rejectCompletion(buildTimeoutError(stdout, stderr, code2));
154404
154831
  return;
154405
154832
  }
154406
154833
  if (options3.signal?.aborted) {
154407
- reject(Object.assign(new Error("The operation was aborted"), {
154408
- name: "AbortError",
154409
- code: "ABORT_ERR",
154410
- stdout,
154411
- stderr
154412
- }));
154834
+ rejectCompletion(buildAbortError(stdout, stderr));
154413
154835
  return;
154414
154836
  }
154415
- resolve8({ stdout, stderr, exitCode: code2 });
154416
- });
154417
- });
154837
+ resolveCompletion({ stdout, stderr, exitCode: code2 });
154838
+ }
154839
+ };
154840
+ try {
154841
+ processHandle = options3.tty ? spawnPtyProcess(launcher, options3, events) : spawnPipeProcess(launcher, options3, events);
154842
+ } catch (error54) {
154843
+ completed = true;
154844
+ cleanup();
154845
+ const failure2 = error54 instanceof Error ? error54 : new Error(String(error54));
154846
+ rejectCompletion(failure2);
154847
+ completion.catch(() => {});
154848
+ throw failure2;
154849
+ }
154850
+ if (options3.timeoutMs) {
154851
+ timeoutTimer = setTimeout(() => {
154852
+ if (completed)
154853
+ return;
154854
+ timedOut = true;
154855
+ terminateProcess();
154856
+ }, options3.timeoutMs);
154857
+ }
154858
+ options3.signal?.addEventListener("abort", abortHandler, { once: true });
154859
+ if (options3.signal?.aborted) {
154860
+ abortHandler();
154861
+ }
154862
+ return { process: processHandle, completion };
154863
+ }
154864
+ async function spawnWithLauncher(launcher, options3) {
154865
+ return startShellProcess(launcher, options3).completion;
154418
154866
  }
154419
- var ShellExecutionError, FORCE_KILL_GRACE_MS = 2000;
154867
+ var ShellExecutionError, NODE_PTY_BRIDGE_SCRIPT = `
154868
+ const pty = require("node-pty");
154869
+ const config = JSON.parse(process.argv[1]);
154870
+ const child = pty.spawn(config.executable, config.args, {
154871
+ name: "xterm-256color",
154872
+ cols: 80,
154873
+ rows: 24,
154874
+ cwd: config.cwd,
154875
+ env: process.env,
154876
+ });
154877
+ child.onData((data) => process.stdout.write(data));
154878
+ child.onExit(({ exitCode }) => process.exit(typeof exitCode === "number" ? exitCode : 1));
154879
+ process.stdin.setEncoding("utf8");
154880
+ process.stdin.on("data", (data) => child.write(data));
154881
+ process.on("SIGTERM", () => child.kill("SIGTERM"));
154882
+ process.on("SIGINT", () => child.kill("SIGINT"));
154883
+ `, FORCE_KILL_GRACE_MS = 2000;
154420
154884
  var init_shell_runner = __esm(() => {
154421
154885
  init_usable_directory();
154422
154886
  init_worktree_ownership();
154887
+ init_github_pull_request_tracker();
154423
154888
  ShellExecutionError = class ShellExecutionError extends Error {
154424
154889
  code;
154425
154890
  executable;
@@ -154940,7 +155405,6 @@ __export(exports_bash, {
154940
155405
  spawnCommand: () => spawnCommand,
154941
155406
  bash: () => bash
154942
155407
  });
154943
- import { spawn as spawn3 } from "node:child_process";
154944
155408
  function rebuildCachedLauncher(command, secretEnv) {
154945
155409
  if (!cachedWorkingLauncher)
154946
155410
  return null;
@@ -154975,6 +155439,7 @@ async function spawnCommand(command, options3) {
154975
155439
  cwd: options3.cwd,
154976
155440
  env: sandboxed.env,
154977
155441
  timeoutMs: options3.timeout,
155442
+ sourceCommand: command,
154978
155443
  signal: options3.signal,
154979
155444
  onOutput: options3.onOutput
154980
155445
  });
@@ -154987,6 +155452,7 @@ async function spawnCommand(command, options3) {
154987
155452
  cwd: options3.cwd,
154988
155453
  env: env3,
154989
155454
  timeoutMs: options3.timeout,
155455
+ sourceCommand: command,
154990
155456
  signal: options3.signal,
154991
155457
  onOutput: options3.onOutput
154992
155458
  });
@@ -155014,6 +155480,7 @@ async function spawnCommand(command, options3) {
155014
155480
  cwd: options3.cwd,
155015
155481
  env: env3,
155016
155482
  timeoutMs: options3.timeout,
155483
+ sourceCommand: command,
155017
155484
  signal: options3.signal,
155018
155485
  onOutput: options3.onOutput
155019
155486
  });
@@ -155033,12 +155500,55 @@ async function spawnCommand(command, options3) {
155033
155500
  const reason = lastError?.message || "Shell unavailable";
155034
155501
  throw new Error(suffix ? `${reason} (tried: ${suffix})` : reason);
155035
155502
  }
155503
+ function formatStreamTail(label, retainedLines, totalLines) {
155504
+ if (retainedLines.length === 0) {
155505
+ return;
155506
+ }
155507
+ const tail = retainedLines.slice(-NOTIFICATION_TAIL_LINES);
155508
+ const header = tail.length < totalLines ? `[${label} - last ${tail.length} of ${totalLines} lines]` : `[${label}]`;
155509
+ return `${header}
155510
+ ${tail.join(`
155511
+ `)}`;
155512
+ }
155513
+ function formatBackgroundOutputTail(bgProcess) {
155514
+ const sections = [
155515
+ formatStreamTail("stdout", bgProcess.stdout, bgProcess.totalStdoutLines ?? bgProcess.stdout.length),
155516
+ formatStreamTail("stderr", bgProcess.stderr, bgProcess.totalStderrLines ?? bgProcess.stderr.length)
155517
+ ].filter(Boolean);
155518
+ return sections.length > 0 ? sections.join(`
155519
+
155520
+ `) : "(no output)";
155521
+ }
155522
+ function notifyBackgroundCompletion(params) {
155523
+ const { bashId, description, outputFile, bgProcess, scope, status, detail } = params;
155524
+ if (bgProcess.completionNotificationSuppressed) {
155525
+ return;
155526
+ }
155527
+ const label = description?.trim() || bgProcess.command;
155528
+ const durationMs = bgProcess.startTime ? Math.max(0, Date.now() - bgProcess.startTime.getTime()) : undefined;
155529
+ const { content: result } = truncateByChars([`$ ${bgProcess.command}`, detail, formatBackgroundOutputTail(bgProcess)].filter(Boolean).join(`
155530
+
155531
+ `), LIMITS.BASH_NOTIFICATION_CHARS, "Bash", { useMiddleTruncation: true });
155532
+ addToMessageQueue({
155533
+ kind: "task_notification",
155534
+ text: formatTaskNotification({
155535
+ taskId: bashId,
155536
+ status,
155537
+ summary: `Background command "${label}" ${status}`,
155538
+ result,
155539
+ outputFile,
155540
+ usage: durationMs === undefined ? undefined : { durationMs }
155541
+ }),
155542
+ agentId: scope?.agentId,
155543
+ conversationId: scope?.conversationId
155544
+ });
155545
+ }
155036
155546
  async function bash(args) {
155037
155547
  validateRequiredParams(args, ["command"], "Bash");
155038
155548
  const {
155039
155549
  command,
155040
155550
  timeout = 120000,
155041
- description: _description,
155551
+ description,
155042
155552
  run_in_background = false,
155043
155553
  signal,
155044
155554
  onOutput,
@@ -155096,14 +155606,20 @@ async function bash(args) {
155096
155606
  }
155097
155607
  noteExpectedWorktreeForLauncher(launcher, userCwd);
155098
155608
  const sandboxed = applyShellSandbox(launcher, userCwd, bgEnv);
155099
- const [bgExecutable, ...bgLauncherArgs] = sandboxed.launcher;
155100
- const childProcess = spawn3(bgExecutable ?? executable, bgLauncherArgs, {
155101
- shell: false,
155609
+ let bgProcess;
155610
+ const runningProcess = startShellProcess(sandboxed.launcher, {
155102
155611
  cwd: userCwd,
155103
- env: sandboxed.env
155612
+ env: sandboxed.env,
155613
+ timeoutMs: timeout > 0 ? timeout : 0,
155614
+ sourceCommand: command,
155615
+ captureOutput: false,
155616
+ onOutput(text, stream11) {
155617
+ appendBackgroundProcessOutput(bgProcess, stream11, text);
155618
+ appendToOutputFile(outputFile, stream11 === "stderr" ? `[stderr] ${text}` : text);
155619
+ }
155104
155620
  });
155105
- backgroundProcesses.set(bashId, {
155106
- process: childProcess,
155621
+ bgProcess = {
155622
+ process: runningProcess.process,
155107
155623
  command,
155108
155624
  stdout: [],
155109
155625
  stderr: [],
@@ -155115,51 +155631,46 @@ async function bash(args) {
155115
155631
  totalStdoutLines: 0,
155116
155632
  totalStderrLines: 0,
155117
155633
  runtimeScope: parentScope
155118
- });
155119
- const bgProcess = backgroundProcesses.get(bashId);
155120
- if (!bgProcess) {
155121
- throw new Error("Failed to track background process state");
155122
- }
155123
- childProcess.stdout?.on("data", (data) => {
155124
- const text = data.toString();
155125
- appendBackgroundProcessOutput(bgProcess, "stdout", text);
155126
- appendToOutputFile(outputFile, text);
155127
- });
155128
- childProcess.stderr?.on("data", (data) => {
155129
- const text = data.toString();
155130
- appendBackgroundProcessOutput(bgProcess, "stderr", text);
155131
- appendToOutputFile(outputFile, `[stderr] ${text}`);
155132
- });
155133
- childProcess.on("exit", (code2) => {
155134
- bgProcess.status = code2 === 0 ? "completed" : "failed";
155135
- bgProcess.exitCode = code2;
155634
+ };
155635
+ backgroundProcesses.set(bashId, bgProcess);
155636
+ const notificationScope = resolveNotificationScope(parentScope);
155637
+ runningProcess.completion.then(({ exitCode }) => {
155638
+ bgProcess.status = exitCode === 0 ? "completed" : "failed";
155639
+ bgProcess.exitCode = exitCode;
155136
155640
  appendToOutputFile(outputFile, `
155137
- [exit code: ${code2}]
155641
+ [exit code: ${exitCode}]
155138
155642
  `);
155643
+ notifyBackgroundCompletion({
155644
+ bashId,
155645
+ description,
155646
+ outputFile,
155647
+ bgProcess,
155648
+ scope: notificationScope,
155649
+ status: exitCode === 0 ? "completed" : "failed",
155650
+ detail: exitCode === null ? "Terminated by signal before exiting" : `Exit code: ${exitCode}`
155651
+ });
155139
155652
  scheduleBackgroundProcessCleanup(bashId);
155140
- });
155141
- childProcess.on("error", (err) => {
155653
+ }, (error54) => {
155654
+ const err = error54;
155655
+ const message = err.killed ? `Command timed out after ${timeout}ms` : err.message;
155142
155656
  bgProcess.status = "failed";
155143
- appendBackgroundProcessOutput(bgProcess, "stderr", err.message);
155144
- appendToOutputFile(outputFile, `
155145
- [error] ${err.message}
155657
+ appendBackgroundProcessOutput(bgProcess, "stderr", message);
155658
+ appendToOutputFile(outputFile, err.killed ? `
155659
+ [timeout after ${timeout}ms]
155660
+ ` : `
155661
+ [error] ${message}
155146
155662
  `);
155663
+ notifyBackgroundCompletion({
155664
+ bashId,
155665
+ description,
155666
+ outputFile,
155667
+ bgProcess,
155668
+ scope: notificationScope,
155669
+ status: "failed",
155670
+ detail: err.killed ? message : `Error: ${message}`
155671
+ });
155147
155672
  scheduleBackgroundProcessCleanup(bashId);
155148
155673
  });
155149
- if (timeout && timeout > 0) {
155150
- const timeoutHandle = setTimeout(() => {
155151
- if (bgProcess.status === "running") {
155152
- childProcess.kill("SIGTERM");
155153
- bgProcess.status = "failed";
155154
- appendBackgroundProcessOutput(bgProcess, "stderr", `Command timed out after ${timeout}ms`);
155155
- appendToOutputFile(outputFile, `
155156
- [timeout after ${timeout}ms]
155157
- `);
155158
- scheduleBackgroundProcessCleanup(bashId);
155159
- }
155160
- }, timeout);
155161
- unrefTimer2(timeoutHandle);
155162
- }
155163
155674
  return {
155164
155675
  content: [
155165
155676
  {
@@ -155235,10 +155746,12 @@ ${errorMessage}`;
155235
155746
  };
155236
155747
  }
155237
155748
  }
155238
- var cachedWorkingLauncher = null;
155749
+ var cachedWorkingLauncher = null, NOTIFICATION_TAIL_LINES = 50;
155239
155750
  var init_bash = __esm(() => {
155240
155751
  init_constants2();
155241
155752
  init_runtime_context();
155753
+ init_message_queue_bridge();
155754
+ init_task_notifications();
155242
155755
  init_worktree_ownership();
155243
155756
  init_process_manager();
155244
155757
  init_shell_env();
@@ -157808,7 +158321,7 @@ var init_enter_worktree_messages = __esm(() => {
157808
158321
  });
157809
158322
 
157810
158323
  // src/tools/impl/enter-worktree.ts
157811
- import { spawn as spawn4 } from "node:child_process";
158324
+ import { spawn as spawn3 } from "node:child_process";
157812
158325
  import { randomUUID as randomUUID6 } from "node:crypto";
157813
158326
  import {
157814
158327
  copyFile,
@@ -157860,7 +158373,7 @@ This looks like a Windows path-length issue. Try:
157860
158373
  async function runGit2(args, cwd, options3 = {}) {
157861
158374
  const timeoutMs = options3.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
157862
158375
  return await new Promise((resolve11, reject) => {
157863
- const child = spawn4("git", args, {
158376
+ const child = spawn3("git", args, {
157864
158377
  cwd,
157865
158378
  env: getShellEnv(),
157866
158379
  shell: false,
@@ -158535,6 +159048,7 @@ async function runProcess(context3) {
158535
159048
  cwd: context3.cwd,
158536
159049
  env: context3.env,
158537
159050
  timeoutMs: context3.timeout,
159051
+ sourceCommand: context3.sourceCommand,
158538
159052
  signal: context3.signal,
158539
159053
  onOutput: context3.onOutput
158540
159054
  });
@@ -158585,6 +159099,7 @@ async function shell(args) {
158585
159099
  }
158586
159100
  const context3 = {
158587
159101
  command: sandboxed.launcher,
159102
+ sourceCommand: command,
158588
159103
  cwd,
158589
159104
  env: sandboxed.env,
158590
159105
  timeout,
@@ -158694,7 +159209,6 @@ var init_shell = __esm(() => {
158694
159209
  });
158695
159210
 
158696
159211
  // src/tools/impl/exec-command.ts
158697
- import { spawn as spawn5 } from "node:child_process";
158698
159212
  function createAbortError2() {
158699
159213
  const error54 = new Error("The operation was aborted");
158700
159214
  error54.name = "AbortError";
@@ -158884,17 +159398,6 @@ function buildExecLaunchers(args) {
158884
159398
  powershellEnvAliases: envAliases
158885
159399
  });
158886
159400
  }
158887
- function buildPtyEnv(env3) {
158888
- const ptyEnv = {};
158889
- for (const [key, value] of Object.entries(env3)) {
158890
- if (value !== undefined) {
158891
- ptyEnv[key] = value;
158892
- }
158893
- }
158894
- ptyEnv.TERM = ptyEnv.TERM || "xterm-256color";
158895
- ptyEnv.COLORTERM = ptyEnv.COLORTERM || "truecolor";
158896
- return ptyEnv;
158897
- }
158898
159401
  function createSessionOutputAppender(params) {
158899
159402
  return (text, stream11) => {
158900
159403
  appendSessionOutput(params.session, text, stream11);
@@ -158925,117 +159428,6 @@ function markSessionClosed(session, code2) {
158925
159428
  }
158926
159429
  scheduleExecSessionCleanup(session.id);
158927
159430
  }
158928
- function spawnPipeProcess(params) {
158929
- const [executable, ...args] = params.launcher;
158930
- if (!executable) {
158931
- throw new Error("Executable is required");
158932
- }
158933
- noteExpectedWorktreeForLauncher(params.launcher, params.cwd);
158934
- const childProcess = spawn5(executable, args, {
158935
- cwd: params.cwd,
158936
- env: params.env,
158937
- shell: false,
158938
- stdio: ["ignore", "pipe", "pipe"],
158939
- detached: process.platform !== "win32"
158940
- });
158941
- const appendOutput = createSessionOutputAppender(params);
158942
- childProcess.stdout?.on("data", (chunk) => {
158943
- appendOutput(chunk.toString("utf8"), "stdout");
158944
- });
158945
- childProcess.stderr?.on("data", (chunk) => {
158946
- appendOutput(chunk.toString("utf8"), "stderr");
158947
- });
158948
- childProcess.on("error", (error54) => {
158949
- appendOutput(error54.message, "stderr");
158950
- markSessionFailed(params.session);
158951
- });
158952
- childProcess.on("close", (code2) => {
158953
- markSessionClosed(params.session, code2);
158954
- });
158955
- return {
158956
- kill(signal) {
158957
- if (childProcess.pid && process.platform !== "win32") {
158958
- try {
158959
- process.kill(-childProcess.pid, signal);
158960
- return;
158961
- } catch {}
158962
- }
158963
- childProcess.kill(signal);
158964
- },
158965
- write(input) {
158966
- childProcess.stdin?.write(input);
158967
- }
158968
- };
158969
- }
158970
- function spawnPtyProcess(params) {
158971
- const [executable, ...args] = params.launcher;
158972
- if (!executable) {
158973
- throw new Error("Executable is required");
158974
- }
158975
- noteExpectedWorktreeForLauncher(params.launcher, params.cwd);
158976
- const appendOutput = createSessionOutputAppender(params);
158977
- const ptyEnv = buildPtyEnv(params.env);
158978
- if (typeof Bun !== "undefined") {
158979
- const childProcess = spawn5("node", [
158980
- "-e",
158981
- NODE_PTY_BRIDGE_SCRIPT,
158982
- JSON.stringify({ executable, args, cwd: params.cwd })
158983
- ], {
158984
- cwd: params.cwd,
158985
- env: ptyEnv,
158986
- shell: false,
158987
- stdio: ["pipe", "pipe", "pipe"],
158988
- detached: process.platform !== "win32"
158989
- });
158990
- childProcess.stdout?.on("data", (chunk) => {
158991
- appendOutput(chunk.toString("utf8"), "stdout");
158992
- });
158993
- childProcess.stderr?.on("data", (chunk) => {
158994
- appendOutput(chunk.toString("utf8"), "stderr");
158995
- });
158996
- childProcess.on("error", (error54) => {
158997
- appendOutput(error54.message, "stderr");
158998
- markSessionFailed(params.session);
158999
- });
159000
- childProcess.on("close", (code2) => {
159001
- markSessionClosed(params.session, code2);
159002
- });
159003
- return {
159004
- kill(signal) {
159005
- if (childProcess.pid && process.platform !== "win32") {
159006
- try {
159007
- process.kill(-childProcess.pid, signal);
159008
- return;
159009
- } catch {}
159010
- }
159011
- childProcess.kill(signal);
159012
- },
159013
- write(input) {
159014
- childProcess.stdin?.write(input);
159015
- }
159016
- };
159017
- }
159018
- const pty = __require("node-pty");
159019
- const ptyProcess = pty.spawn(executable, args, {
159020
- name: "xterm-256color",
159021
- cols: 80,
159022
- rows: 24,
159023
- cwd: params.cwd,
159024
- env: ptyEnv
159025
- });
159026
- ptyProcess.onData((data) => appendOutput(data, "stdout"));
159027
- ptyProcess.onExit(({ exitCode }) => {
159028
- markSessionClosed(params.session, typeof exitCode === "number" ? exitCode : null);
159029
- });
159030
- return {
159031
- kill(signal) {
159032
- ptyProcess.kill(typeof signal === "string" ? signal : undefined);
159033
- },
159034
- write(input) {
159035
- ptyProcess.write(input);
159036
- }
159037
- };
159038
- }
159039
159431
  async function waitForSessionOutput(params) {
159040
159432
  const startTime = Date.now();
159041
159433
  const deadline = startTime + params.yieldTimeMs;
@@ -159089,22 +159481,25 @@ async function startExecSession(args) {
159089
159481
  tty: args.tty ?? false
159090
159482
  };
159091
159483
  execSessions.set(id2, session);
159092
- let processLauncher;
159484
+ const appendOutput = createSessionOutputAppender({ session, outputFile });
159485
+ let runningProcess;
159093
159486
  try {
159094
- const spawnProcess = session.tty ? spawnPtyProcess : spawnPipeProcess;
159095
- processLauncher = spawnProcess({
159096
- launcher,
159487
+ runningProcess = startShellProcess(launcher, {
159097
159488
  cwd,
159098
159489
  env: spawnEnv,
159099
- session,
159100
- outputFile
159490
+ timeoutMs: 0,
159491
+ sourceCommand: args.cmd,
159492
+ signal: args.signal,
159493
+ tty: session.tty,
159494
+ captureOutput: false,
159495
+ onOutput: appendOutput
159101
159496
  });
159102
159497
  } catch (error54) {
159103
159498
  execSessions.delete(id2);
159104
159499
  throw error54;
159105
159500
  }
159106
159501
  backgroundProcesses.set(id2, {
159107
- process: processLauncher,
159502
+ process: runningProcess.process,
159108
159503
  command: args.cmd,
159109
159504
  stdout: [],
159110
159505
  stderr: [],
@@ -159120,9 +159515,12 @@ async function startExecSession(args) {
159120
159515
  if (session.status !== "running") {
159121
159516
  scheduleBackgroundProcessCleanup(id2);
159122
159517
  }
159123
- args.signal?.addEventListener("abort", () => {
159124
- processLauncher.kill("SIGTERM");
159125
- }, { once: true });
159518
+ runningProcess.completion.then(({ exitCode }) => markSessionClosed(session, exitCode), (error54) => {
159519
+ if (error54 instanceof ShellExecutionError) {
159520
+ appendOutput(error54.message, "stderr");
159521
+ }
159522
+ markSessionFailed(session);
159523
+ });
159126
159524
  return session;
159127
159525
  }
159128
159526
  async function exec_command(args) {
@@ -159198,23 +159596,7 @@ async function write_stdin(args) {
159198
159596
  output: formattedOutput
159199
159597
  };
159200
159598
  }
159201
- var DEFAULT_EXEC_YIELD_TIME_MS = 1e4, DEFAULT_WRITE_STDIN_YIELD_TIME_MS = 250, MIN_YIELD_TIME_MS = 250, MIN_EMPTY_WRITE_STDIN_YIELD_TIME_MS = 5000, MAX_YIELD_TIME_MS = 30000, MAX_EMPTY_WRITE_STDIN_YIELD_TIME_MS = 300000, DEFAULT_MAX_OUTPUT_TOKENS = 1e4, MAX_INLINE_OUTPUT_CHARS, MAX_SESSION_OUTPUT_CHARS = 1e6, EXEC_SESSION_CLEANUP_MS, NODE_PTY_BRIDGE_SCRIPT = `
159202
- const pty = require("node-pty");
159203
- const config = JSON.parse(process.argv[1]);
159204
- const child = pty.spawn(config.executable, config.args, {
159205
- name: "xterm-256color",
159206
- cols: 80,
159207
- rows: 24,
159208
- cwd: config.cwd,
159209
- env: process.env,
159210
- });
159211
- child.onData((data) => process.stdout.write(data));
159212
- child.onExit(({ exitCode }) => process.exit(typeof exitCode === "number" ? exitCode : 1));
159213
- process.stdin.setEncoding("utf8");
159214
- process.stdin.on("data", (data) => child.write(data));
159215
- process.on("SIGTERM", () => child.kill("SIGTERM"));
159216
- process.on("SIGINT", () => child.kill("SIGINT"));
159217
- `, execSessions;
159599
+ var DEFAULT_EXEC_YIELD_TIME_MS = 1e4, DEFAULT_WRITE_STDIN_YIELD_TIME_MS = 250, MIN_YIELD_TIME_MS = 250, MIN_EMPTY_WRITE_STDIN_YIELD_TIME_MS = 5000, MAX_YIELD_TIME_MS = 30000, MAX_EMPTY_WRITE_STDIN_YIELD_TIME_MS = 300000, DEFAULT_MAX_OUTPUT_TOKENS = 1e4, MAX_INLINE_OUTPUT_CHARS, MAX_SESSION_OUTPUT_CHARS = 1e6, EXEC_SESSION_CLEANUP_MS, execSessions;
159218
159600
  var init_exec_command = __esm(() => {
159219
159601
  init_runtime_context();
159220
159602
  init_worktree_ownership();
@@ -159222,6 +159604,7 @@ var init_exec_command = __esm(() => {
159222
159604
  init_shell();
159223
159605
  init_shell_env();
159224
159606
  init_shell_launchers();
159607
+ init_shell_runner();
159225
159608
  init_shell_sandbox();
159226
159609
  init_truncation();
159227
159610
  MAX_INLINE_OUTPUT_CHARS = LIMITS.BASH_OUTPUT_CHARS;
@@ -159521,6 +159904,7 @@ async function kill_bash(args) {
159521
159904
  if (!proc)
159522
159905
  return { killed: false };
159523
159906
  try {
159907
+ proc.completionNotificationSuppressed = true;
159524
159908
  proc.process.kill("SIGTERM");
159525
159909
  clearBackgroundProcessCleanup(shell_id);
159526
159910
  backgroundProcesses.delete(shell_id);
@@ -162500,7 +162884,7 @@ async function convertHeicToJpegWithSips(buffer) {
162500
162884
  var init_image_resize_sips = () => {};
162501
162885
 
162502
162886
  // src/utils/image-resize.ts
162503
- import { spawn as spawn6 } from "node:child_process";
162887
+ import { spawn as spawn4 } from "node:child_process";
162504
162888
  import { existsSync as existsSync16 } from "node:fs";
162505
162889
  import { fileURLToPath as fileURLToPath4 } from "node:url";
162506
162890
  function resolveImageWorkerPath() {
@@ -162513,7 +162897,7 @@ function resolveImageWorkerPath() {
162513
162897
  function resizeWithSharpWorker(buffer, inputMediaType) {
162514
162898
  return new Promise((resolve18, reject) => {
162515
162899
  const workerPath = resolveImageWorkerPath();
162516
- const child = spawn6(process.execPath, [workerPath, inputMediaType], {
162900
+ const child = spawn4(process.execPath, [workerPath, inputMediaType], {
162517
162901
  shell: false,
162518
162902
  stdio: ["pipe", "pipe", "pipe"],
162519
162903
  windowsHide: true
@@ -163609,7 +163993,7 @@ var require_cross_spawn = __commonJS((exports, module3) => {
163609
163993
  var cp = __require("child_process");
163610
163994
  var parse8 = require_parse3();
163611
163995
  var enoent = require_enoent();
163612
- function spawn7(command, args, options3) {
163996
+ function spawn5(command, args, options3) {
163613
163997
  const parsed = parse8(command, args, options3);
163614
163998
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
163615
163999
  enoent.hookChildProcess(spawned, parsed);
@@ -163621,8 +164005,8 @@ var require_cross_spawn = __commonJS((exports, module3) => {
163621
164005
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
163622
164006
  return result;
163623
164007
  }
163624
- module3.exports = spawn7;
163625
- module3.exports.spawn = spawn7;
164008
+ module3.exports = spawn5;
164009
+ module3.exports.spawn = spawn5;
163626
164010
  module3.exports.sync = spawnSync3;
163627
164011
  module3.exports._parse = parse8;
163628
164012
  module3.exports._enoent = enoent;
@@ -163630,13 +164014,13 @@ var require_cross_spawn = __commonJS((exports, module3) => {
163630
164014
 
163631
164015
  // src/utils/package-manager-spawn.ts
163632
164016
  import {
163633
- spawn as spawn7
164017
+ spawn as spawn5
163634
164018
  } from "node:child_process";
163635
164019
  function isWindowsCommandShim(command) {
163636
164020
  return /\.(?:cmd|bat)$/i.test(command);
163637
164021
  }
163638
164022
  function getPackageManagerProcessFactory({
163639
- nativeSpawn = spawn7,
164023
+ nativeSpawn = spawn5,
163640
164024
  platform: platform2 = process.platform,
163641
164025
  windowsSpawn = import_cross_spawn.default
163642
164026
  } = {}) {
@@ -163737,9 +164121,9 @@ var init_typescript = __esm(() => {
163737
164121
  throw new Error("LSP auto-download is disabled. Please install typescript-language-server manually: npm install -g typescript-language-server typescript");
163738
164122
  }
163739
164123
  console.log("[LSP] Installing typescript-language-server and typescript...");
163740
- const { spawn: spawn8 } = await import("node:child_process");
164124
+ const { spawn: spawn6 } = await import("node:child_process");
163741
164125
  return new Promise((resolve18, reject) => {
163742
- const proc = spawn8("npm", ["install", "-g", "typescript-language-server", "typescript"], {
164126
+ const proc = spawn6("npm", ["install", "-g", "typescript-language-server", "typescript"], {
163743
164127
  stdio: "inherit"
163744
164128
  });
163745
164129
  proc.on("exit", (code2) => {
@@ -163812,7 +164196,7 @@ class LSPManager {
163812
164196
  return existing.client;
163813
164197
  }
163814
164198
  try {
163815
- const { spawn: spawn8 } = await import("node:child_process");
164199
+ const { spawn: spawn6 } = await import("node:child_process");
163816
164200
  const rootUri = process.cwd();
163817
164201
  if (serverDef.autoInstall) {
163818
164202
  const isAvailable = await serverDef.autoInstall.check();
@@ -163826,7 +164210,7 @@ class LSPManager {
163826
164210
  console.error(`[LSP] ${serverDef.id} has no command configured`);
163827
164211
  return null;
163828
164212
  }
163829
- const proc = spawn8(command, serverDef.command.slice(1), {
164213
+ const proc = spawn6(command, serverDef.command.slice(1), {
163830
164214
  cwd: rootUri,
163831
164215
  env: {
163832
164216
  ...process.env,
@@ -172641,6 +173025,9 @@ async function resolveSubagentModel(options3) {
172641
173025
  }
172642
173026
  return "letta/auto-memory";
172643
173027
  }
173028
+ if (isInheritModel(effectiveRecommendedModel) && parentModelHandle) {
173029
+ return parentModelHandle;
173030
+ }
172644
173031
  let recommendedHandle = null;
172645
173032
  if (effectiveRecommendedModel && !isInheritModel(effectiveRecommendedModel)) {
172646
173033
  recommendedHandle = resolveModel(effectiveRecommendedModel);
@@ -172850,7 +173237,7 @@ var init_subagent_stream = __esm(() => {
172850
173237
  });
172851
173238
 
172852
173239
  // src/agent/subagents/manager.ts
172853
- import { spawn as spawn8 } from "node:child_process";
173240
+ import { spawn as spawn6 } from "node:child_process";
172854
173241
  import { platform as platform2 } from "node:os";
172855
173242
  function isProviderNotSupportedError(errorOutput) {
172856
173243
  return errorOutput.includes("Provider") && errorOutput.includes("is not supported") && errorOutput.includes("supported providers:");
@@ -173067,7 +173454,7 @@ async function executeSubagent(type3, config3, model, userPrompt, subagentId, is
173067
173454
  if (sandbox) {
173068
173455
  debugLog("subagent", `memory subagent child sandboxed via ${sandbox.backend}`);
173069
173456
  }
173070
- const proc2 = spawn8(spawnLauncher.command, spawnLauncher.args, {
173457
+ const proc2 = spawn6(spawnLauncher.command, spawnLauncher.args, {
173071
173458
  cwd: subagentWorkingDirectory,
173072
173459
  env: spawnEnv
173073
173460
  });
@@ -173334,114 +173721,6 @@ var init_manager3 = __esm(() => {
173334
173721
  ]);
173335
173722
  });
173336
173723
 
173337
- // src/utils/message-queue-bridge.ts
173338
- function setMessageQueueAdder(fn) {
173339
- queueAdder = fn;
173340
- if (queueAdder && pendingMessages.length > 0) {
173341
- for (const message of pendingMessages) {
173342
- queueAdder(message);
173343
- }
173344
- pendingMessages.length = 0;
173345
- }
173346
- }
173347
- function addToMessageQueue(message) {
173348
- if (queueAdder) {
173349
- queueAdder(message);
173350
- return;
173351
- }
173352
- if (pendingMessages.length >= MAX_PENDING_MESSAGES) {
173353
- pendingMessages.shift();
173354
- }
173355
- pendingMessages.push(message);
173356
- }
173357
- var queueAdder = null, pendingMessages, MAX_PENDING_MESSAGES = 10;
173358
- var init_message_queue_bridge = __esm(() => {
173359
- pendingMessages = [];
173360
- });
173361
-
173362
- // src/utils/task-notifications.ts
173363
- function escapeXml(str2) {
173364
- return str2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
173365
- }
173366
- function unescapeXml(str2) {
173367
- return str2.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
173368
- }
173369
- function formatTaskNotification(notification) {
173370
- const escapedSummary = escapeXml(notification.summary);
173371
- const escapedResult = escapeXml(notification.result);
173372
- const usageLines = [];
173373
- if (notification.usage?.totalTokens !== undefined) {
173374
- usageLines.push(`total_tokens: ${notification.usage.totalTokens}`);
173375
- }
173376
- if (notification.usage?.toolUses !== undefined) {
173377
- usageLines.push(`tool_uses: ${notification.usage.toolUses}`);
173378
- }
173379
- if (notification.usage?.durationMs !== undefined) {
173380
- usageLines.push(`duration_ms: ${notification.usage.durationMs}`);
173381
- }
173382
- const usageBlock = usageLines.length ? `
173383
- <usage>${usageLines.join(`
173384
- `)}</usage>` : "";
173385
- return `<task-notification>
173386
- <task-id>${notification.taskId}</task-id>
173387
- <status>${notification.status}</status>
173388
- <summary>${escapedSummary}</summary>
173389
- <result>${escapedResult}</result>${usageBlock}
173390
- </task-notification>
173391
- Full transcript available at: ${notification.outputFile}`;
173392
- }
173393
- function extractTaskNotificationsForDisplay(message) {
173394
- if (!message.includes("<task-notification>")) {
173395
- return { notifications: [], cleanedText: message };
173396
- }
173397
- const notificationRegex = /<task-notification>[\s\S]*?(?:<\/task-notification>|$)(?:\s*Full transcript available at:[^\n]*\n?)?/g;
173398
- const notifications = [];
173399
- let match3 = notificationRegex.exec(message);
173400
- while (match3 !== null) {
173401
- const xml = match3[0];
173402
- const summaryMatch = xml.match(/<summary>([\s\S]*?)<\/summary>/);
173403
- const statusMatch = xml.match(/<status>([\s\S]*?)<\/status>/);
173404
- const resultMatch = xml.match(/<result>([\s\S]*?)<\/result>/);
173405
- const result = resultMatch?.[1]?.trim() || "";
173406
- const isAgentOnlyReminder = result.includes(SYSTEM_REMINDER_OPEN);
173407
- if (isAgentOnlyReminder) {
173408
- match3 = notificationRegex.exec(message);
173409
- continue;
173410
- }
173411
- const status = statusMatch?.[1]?.trim();
173412
- let summary = summaryMatch?.[1]?.trim() || "";
173413
- summary = unescapeXml(summary);
173414
- const display = summary || `Agent task ${status || "completed"}`;
173415
- notifications.push(display);
173416
- match3 = notificationRegex.exec(message);
173417
- }
173418
- const cleanedText = message.replace(notificationRegex, "").replace(/^\s*Full transcript available at:[^\n]*\n?/gm, "").replace(/\n{3,}/g, `
173419
-
173420
- `).trim();
173421
- return { notifications, cleanedText };
173422
- }
173423
- function appendTaskNotificationEventsToBuffer(summaries, buffer, generateId, flush) {
173424
- if (summaries.length === 0)
173425
- return false;
173426
- for (const summary of summaries) {
173427
- const eventId = generateId();
173428
- buffer.byId.set(eventId, {
173429
- kind: "event",
173430
- id: eventId,
173431
- eventType: "task_notification",
173432
- eventData: {},
173433
- phase: "finished",
173434
- summary
173435
- });
173436
- buffer.order.push(eventId);
173437
- }
173438
- flush?.();
173439
- return true;
173440
- }
173441
- var init_task_notifications = __esm(() => {
173442
- init_constants2();
173443
- });
173444
-
173445
173724
  // src/tools/impl/task.ts
173446
173725
  var exports_task = {};
173447
173726
  __export(exports_task, {
@@ -173491,22 +173770,6 @@ ${result.report}
173491
173770
  [Task failed]
173492
173771
  `);
173493
173772
  }
173494
- function resolveParentScope(parentScope) {
173495
- if (parentScope?.agentId) {
173496
- return {
173497
- agentId: parentScope.agentId,
173498
- conversationId: parentScope.conversationId || "default"
173499
- };
173500
- }
173501
- try {
173502
- return {
173503
- agentId: getCurrentAgentId(),
173504
- conversationId: getConversationId() ?? "default"
173505
- };
173506
- } catch {
173507
- return;
173508
- }
173509
- }
173510
173773
  async function waitForBackgroundSubagentLink(subagentId, timeoutMs = null, signal) {
173511
173774
  const deadline = timeoutMs !== null && timeoutMs > 0 ? Date.now() + timeoutMs : null;
173512
173775
  while (true) {
@@ -173597,7 +173860,7 @@ function spawnBackgroundSubagentTask(args) {
173597
173860
  deps
173598
173861
  } = args;
173599
173862
  const shouldEmitCompletionNotification = emitCompletionNotification ?? !silentCompletion;
173600
- const resolvedParentScope = resolveParentScope(parentScope);
173863
+ const resolvedParentScope = resolveNotificationScope(parentScope);
173601
173864
  const spawnSubagentFn = deps?.spawnSubagentImpl ?? spawnSubagent;
173602
173865
  const addToMessageQueueFn = deps?.addToMessageQueueImpl ?? addToMessageQueue;
173603
173866
  const formatTaskNotificationFn = deps?.formatTaskNotificationImpl ?? formatTaskNotification;
@@ -173804,7 +174067,7 @@ async function task(args) {
173804
174067
  }
173805
174068
  const prompt = inputPrompt;
173806
174069
  const isBackground = args.run_in_background ?? config3.background;
173807
- const resolvedParentScope = resolveParentScope(args.parentScope);
174070
+ const resolvedParentScope = resolveNotificationScope(args.parentScope);
173808
174071
  if (isBackground) {
173809
174072
  const { taskId, outputFile: outputFile2, subagentId: subagentId2 } = spawnBackgroundSubagentTask({
173810
174073
  subagentType: subagent_type,
@@ -232312,7 +232575,7 @@ function parsePositiveIntFlag(options3) {
232312
232575
  }
232313
232576
 
232314
232577
  // src/cli/helpers/file-autocomplete.ts
232315
- import { spawn as spawn9, spawnSync as spawnSync3 } from "node:child_process";
232578
+ import { spawn as spawn7, spawnSync as spawnSync3 } from "node:child_process";
232316
232579
  import {
232317
232580
  chmodSync as chmodSync5,
232318
232581
  createWriteStream as createWriteStream3,
@@ -232458,7 +232721,7 @@ async function walkDirectoryWithFd(baseDir, fdPath, query2, maxResults, signal)
232458
232721
  resolve29([]);
232459
232722
  return;
232460
232723
  }
232461
- const child = spawn9(fdPath, args, {
232724
+ const child = spawn7(fdPath, args, {
232462
232725
  stdio: ["ignore", "pipe", "pipe"]
232463
232726
  });
232464
232727
  let stdout = "";
@@ -250219,7 +250482,7 @@ var init_runtime6 = __esm(() => {
250219
250482
  });
250220
250483
 
250221
250484
  // src/channels/signal/setup-runtime.ts
250222
- import { execFileSync as execFileSync5, spawn as spawn10 } from "node:child_process";
250485
+ import { execFileSync as execFileSync5, spawn as spawn8 } from "node:child_process";
250223
250486
  import { existsSync as existsSync35 } from "node:fs";
250224
250487
  function getSignalDockerRunCommand() {
250225
250488
  return [
@@ -250281,7 +250544,7 @@ function runNativeSignalCli(args) {
250281
250544
  }
250282
250545
  function runNativeSignalCliInteractive(args, onOutput) {
250283
250546
  return new Promise((resolve30) => {
250284
- const child = spawn10("signal-cli", args, {
250547
+ const child = spawn8("signal-cli", args, {
250285
250548
  stdio: ["ignore", "pipe", "pipe"]
250286
250549
  });
250287
250550
  let output = "";
@@ -268958,7 +269221,7 @@ var init_core5 = __esm(() => {
268958
269221
  });
268959
269222
 
268960
269223
  // node_modules/@letta-ai/trajectory/dist/adapters/deepagents/index.js
268961
- import { spawn as spawn11 } from "node:child_process";
269224
+ import { spawn as spawn9 } from "node:child_process";
268962
269225
  import { accessSync as accessSync2, constants as constants5 } from "node:fs";
268963
269226
  import { homedir as homedir27 } from "node:os";
268964
269227
  import { join as join48 } from "node:path";
@@ -268989,7 +269252,7 @@ async function loadDeepAgentsCheckpoint(checkpoint2) {
268989
269252
  const python = checkpoint2.pythonExecutable ?? process.env.PYTHON ?? "python3";
268990
269253
  const helper = resolveHelperPath();
268991
269254
  return await new Promise((resolve31, reject) => {
268992
- const child = spawn11(python, [helper], {
269255
+ const child = spawn9(python, [helper], {
268993
269256
  stdio: ["pipe", "pipe", "pipe"],
268994
269257
  windowsHide: true
268995
269258
  });
@@ -462626,7 +462889,7 @@ var init_mod_commands = __esm(async () => {
462626
462889
  });
462627
462890
 
462628
462891
  // src/websocket/listener/commands.ts
462629
- import { spawn as spawn12 } from "node:child_process";
462892
+ import { spawn as spawn10 } from "node:child_process";
462630
462893
  async function handleExecuteCommand(command, socket, conversationRuntime, opts) {
462631
462894
  const scope = {
462632
462895
  agent_id: conversationRuntime.agentId,
@@ -462833,7 +463096,7 @@ function scheduleRemoteRestart(connectionName, log2) {
462833
463096
  setTimeout(async () => {
462834
463097
  await flushRemoteSettingsWrites();
462835
463098
  log2(`spawning replacement listener: ${process.execPath} ${entrypoint} remote --env-name ${connectionName}`);
462836
- const child = spawn12(process.execPath, [entrypoint, "remote", "--env-name", connectionName], {
463099
+ const child = spawn10(process.execPath, [entrypoint, "remote", "--env-name", connectionName], {
462837
463100
  cwd: process.cwd(),
462838
463101
  detached: true,
462839
463102
  env: process.env,
@@ -464398,7 +464661,8 @@ function dispatchInboundMessageWhenReady(params) {
464398
464661
  emitListenerStatus(listener, options3.onStatusChange, options3.connectionId);
464399
464662
  rememberAcceptedInputDisposition(runtime, clientMessageId, "started");
464400
464663
  acknowledgeInput({ accepted: true, disposition: "started" });
464401
- await processIncomingMessage(incoming, getOrCreateProcessTransport(listener), runtime, options3.onStatusChange, options3.connectionId);
464664
+ const attributedIncoming = actingUserId && incoming.actingUserId !== actingUserId ? { ...incoming, actingUserId } : incoming;
464665
+ await processIncomingMessage(attributedIncoming, getOrCreateProcessTransport(listener), runtime, options3.onStatusChange, options3.connectionId);
464402
464666
  emitListenerStatus(listener, options3.onStatusChange, options3.connectionId);
464403
464667
  if (runtime.queueRuntime.length > 0 || runtime.queuePumpScheduled || runtime.queuePumpActive) {
464404
464668
  scheduleQueuePump(runtime, socket, options3, processQueuedTurn);
@@ -468641,7 +468905,7 @@ __export(exports_gateway_supervisor, {
468641
468905
  startChannelGatewaySupervisor: () => startChannelGatewaySupervisor,
468642
468906
  CHANNEL_GATEWAY_READY_SIGNAL: () => CHANNEL_GATEWAY_READY_SIGNAL
468643
468907
  });
468644
- import { spawn as spawn13 } from "node:child_process";
468908
+ import { spawn as spawn11 } from "node:child_process";
468645
468909
  function resolveLauncher(cwd2) {
468646
468910
  const invocation = resolveLettaInvocation(process.env, process.argv, process.execPath, cwd2);
468647
468911
  if (invocation)
@@ -468686,7 +468950,7 @@ async function startChannelGatewaySupervisor(options3) {
468686
468950
  const launch = () => {
468687
468951
  if (stopping)
468688
468952
  return;
468689
- child = (options3.spawnProcess ?? spawn13)(launcher.command, childArgs, {
468953
+ child = (options3.spawnProcess ?? spawn11)(launcher.command, childArgs, {
468690
468954
  cwd: cwd2,
468691
468955
  env: options3.env ?? process.env,
468692
468956
  stdio: ["pipe", "pipe", "pipe"],
@@ -470981,7 +471245,7 @@ var init_messages10 = __esm(() => {
470981
471245
  });
470982
471246
 
470983
471247
  // src/mods/package-installer.ts
470984
- import { spawn as spawn14 } from "node:child_process";
471248
+ import { spawn as spawn12 } from "node:child_process";
470985
471249
  import {
470986
471250
  copyFileSync as copyFileSync4,
470987
471251
  existsSync as existsSync55,
@@ -471839,7 +472103,7 @@ var init_package_installer = __esm(() => {
471839
472103
  init_package_registry();
471840
472104
  init_package_manager_spawn();
471841
472105
  SKIPPED_PACKAGE_COPY_NAMES = new Set([".git", "node_modules"]);
471842
- spawnGitInstallProcess = spawn14;
472106
+ spawnGitInstallProcess = spawn12;
471843
472107
  });
471844
472108
 
471845
472109
  // src/mods/package-scaffolder.ts
@@ -492975,7 +493239,7 @@ var init_mcp_client = __esm(() => {
492975
493239
  init_streamableHttp();
492976
493240
  DEFAULT_CLIENT_INFO = {
492977
493241
  name: "letta-code",
492978
- version: "0.30.12"
493242
+ version: "0.30.13"
492979
493243
  };
492980
493244
  });
492981
493245
 
@@ -546178,7 +546442,7 @@ The deployment target for this project is CITATION-DOGFOOD-OK.
546178
546442
  });
546179
546443
 
546180
546444
  // src/mods/learning-harness.ts
546181
- import { spawn as spawn16 } from "node:child_process";
546445
+ import { spawn as spawn14 } from "node:child_process";
546182
546446
  import { access as access3, copyFile as copyFile2, mkdir as mkdir20, readFile as readFile32, writeFile as writeFile22 } from "node:fs/promises";
546183
546447
  import path45 from "node:path";
546184
546448
  function slugify2(value) {
@@ -547118,7 +547382,7 @@ async function writeHistoryArtifacts(params) {
547118
547382
  async function defaultCommandRunner(command, args, options3) {
547119
547383
  const startedAt = Date.now();
547120
547384
  return new Promise((resolve39) => {
547121
- const child = spawn16(command, args, {
547385
+ const child = spawn14(command, args, {
547122
547386
  cwd: options3.cwd,
547123
547387
  env: options3.env,
547124
547388
  stdio: ["ignore", "pipe", "pipe"]
@@ -560076,4 +560340,4 @@ function registerBunOAuthFlows() {
560076
560340
  registerBunOAuthFlows();
560077
560341
  await init_src5().then(() => exports_src2);
560078
560342
 
560079
- //# debugId=88D7420381F4049564756E2164756E21
560343
+ //# debugId=A52BE38779C3A2C664756E2164756E21