@deepagents/context 6.1.0 → 6.1.2

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/README.md CHANGED
@@ -317,8 +317,9 @@ points.
317
317
  For `target: 'tool-output'`, use `toolOutput(...)` or inspect
318
318
  `ctx.toolOutcome`. The outcome is available after a tool reaches
319
319
  `output-available`, `output-error`, or `output-denied`, but before the next model
320
- generation. Assistant-history predicates such as `toolCalled(...)` only
321
- describe already persisted calls.
320
+ generation. Assistant-history predicates such as `toolCalled(...)` describe
321
+ tool parts visible in the current assistant segment; use `toolOutput(...)` when
322
+ you need the raw outcome currently being evaluated.
322
323
 
323
324
  ```ts
324
325
  import {
package/dist/index.js CHANGED
@@ -840,6 +840,7 @@ import { getErrorMessage } from "@ai-sdk/provider";
840
840
  import {
841
841
  convertToModelMessages as convertToModelMessages2,
842
842
  generateId as generateId5,
843
+ isStaticToolUIPart as isStaticToolUIPart2,
843
844
  validateUIMessages
844
845
  } from "ai";
845
846
 
@@ -3959,6 +3960,58 @@ function toolOutcomesFromStep(content) {
3959
3960
  }
3960
3961
  return outcomes;
3961
3962
  }
3963
+ function terminalToolPartsFromStep(content) {
3964
+ return content.flatMap((part) => {
3965
+ if (part.type === "tool-result" && part.dynamic !== true) {
3966
+ return [
3967
+ {
3968
+ type: `tool-${part.toolName}`,
3969
+ toolCallId: part.toolCallId,
3970
+ state: "output-available",
3971
+ input: part.input,
3972
+ output: part.output === void 0 ? null : part.output
3973
+ }
3974
+ ];
3975
+ }
3976
+ if (part.type === "tool-error" && part.dynamic !== true) {
3977
+ return [
3978
+ {
3979
+ type: `tool-${part.toolName}`,
3980
+ toolCallId: part.toolCallId,
3981
+ state: "output-error",
3982
+ input: part.input,
3983
+ errorText: getErrorMessage(part.error)
3984
+ }
3985
+ ];
3986
+ }
3987
+ if (part.type === "tool-approval-response" && part.approved === false && part.toolCall.dynamic !== true) {
3988
+ return [
3989
+ {
3990
+ type: `tool-${part.toolCall.toolName}`,
3991
+ toolCallId: part.toolCall.toolCallId,
3992
+ state: "output-denied",
3993
+ input: part.toolCall.input,
3994
+ approval: {
3995
+ id: part.approvalId,
3996
+ approved: false,
3997
+ ...part.reason === void 0 ? {} : { reason: part.reason }
3998
+ }
3999
+ }
4000
+ ];
4001
+ }
4002
+ return [];
4003
+ });
4004
+ }
4005
+ function mergeTerminalToolParts(message2, liveParts) {
4006
+ const remaining = new Map(liveParts);
4007
+ const parts = message2.parts.map((part) => {
4008
+ if (!isStaticToolUIPart2(part)) return part;
4009
+ remaining.delete(part.toolCallId);
4010
+ return part;
4011
+ });
4012
+ parts.push(...remaining.values());
4013
+ return { ...message2, parts };
4014
+ }
3962
4015
  var ContextEngine = class _ContextEngine {
3963
4016
  /** Non-message fragments (role, hints, etc.) - not persisted in graph */
3964
4017
  #fragments = [];
@@ -4371,12 +4424,24 @@ var ContextEngine = class _ContextEngine {
4371
4424
  const enableSteer = options.steer ?? true;
4372
4425
  const session = {
4373
4426
  firedOnceIds: /* @__PURE__ */ new Set(),
4374
- currentSegStart: 0
4427
+ terminalToolParts: /* @__PURE__ */ new Map(),
4428
+ segments: [],
4429
+ initialStepStarts: null,
4430
+ stepOffset: 0,
4431
+ lastStepNumber: null
4375
4432
  };
4376
4433
  this.#currentReminderSession = session;
4377
4434
  return async ({ steps, stepNumber, messages }) => {
4435
+ if (stepNumber === 0 && session.lastStepNumber !== null) {
4436
+ session.stepOffset += session.lastStepNumber + 1;
4437
+ }
4438
+ session.lastStepNumber = stepNumber;
4439
+ const completedSteps = session.stepOffset + stepNumber;
4378
4440
  const priorStep = stepNumber >= 1 ? steps[stepNumber - 1] : void 0;
4379
4441
  const hasSafeBoundary = (priorStep?.content?.length ?? 0) > 0;
4442
+ for (const part of terminalToolPartsFromStep(priorStep?.content ?? [])) {
4443
+ session.terminalToolParts.set(part.toolCallId, part);
4444
+ }
4380
4445
  const canFire = enableSteer && hasSafeBoundary;
4381
4446
  const steerConfigs = canFire ? this.#remindersFor("steer") : [];
4382
4447
  const outcomes = toolOutcomesFromStep(steps.at(-1)?.content ?? []);
@@ -4435,18 +4500,24 @@ var ContextEngine = class _ContextEngine {
4435
4500
  "createPrepareStep: expected an assistant message at chain head."
4436
4501
  );
4437
4502
  }
4438
- const currentSegmentId = session.currentSegId ?? head.id;
4503
+ const currentSegmentId = head.id;
4439
4504
  const currentSegment = await this.#store.getMessage(currentSegmentId);
4440
4505
  if (!currentSegment || currentSegment.name !== "assistant") {
4441
4506
  throw new Error(
4442
4507
  "createPrepareStep: expected the open assistant segment to be persisted."
4443
4508
  );
4444
4509
  }
4445
- const currentMessage = requireUIMessage(
4510
+ requireUIMessage(
4446
4511
  currentSegment.data,
4447
4512
  `Stored assistant message "${currentSegment.id}"`
4448
4513
  );
4449
4514
  const nextSegmentId = generateId5();
4515
+ if (session.segments.length === 0) {
4516
+ session.segments.push({
4517
+ id: currentSegmentId,
4518
+ startStep: 0
4519
+ });
4520
+ }
4450
4521
  for (const input of inputs) this.set(user(input));
4451
4522
  this.set(
4452
4523
  assistant({
@@ -4456,8 +4527,11 @@ var ContextEngine = class _ContextEngine {
4456
4527
  })
4457
4528
  );
4458
4529
  await this.save({ branch: false });
4459
- session.currentSegId = nextSegmentId;
4460
- session.currentSegStart += currentMessage.parts.length;
4530
+ session.segments.push({
4531
+ id: nextSegmentId,
4532
+ startStep: completedSteps
4533
+ });
4534
+ session.terminalToolParts.clear();
4461
4535
  return {
4462
4536
  messages: [...messages, ...inputModel]
4463
4537
  };
@@ -4482,14 +4556,81 @@ var ContextEngine = class _ContextEngine {
4482
4556
  );
4483
4557
  }
4484
4558
  const session = this.#currentReminderSession;
4485
- this.set(
4486
- assistant({
4487
- ...message2,
4488
- id: session?.currentSegId ?? head.id,
4489
- parts: message2.parts.slice(session?.currentSegStart ?? 0)
4490
- })
4491
- );
4492
- await this.save({ branch: false });
4559
+ let id = head.id;
4560
+ let parts = message2.parts;
4561
+ if (session) {
4562
+ if (session.initialStepStarts === null) {
4563
+ const initialId = session.segments[0]?.id ?? head.id;
4564
+ const initial = await this.#store.getMessage(initialId);
4565
+ if (!initial || initial.name !== "assistant") {
4566
+ throw new Error(
4567
+ `writeAssistantSegment: initial segment "${initialId}" was not found`
4568
+ );
4569
+ }
4570
+ session.initialStepStarts = requireUIMessage(
4571
+ initial.data,
4572
+ `Stored assistant message "${initial.id}"`
4573
+ ).parts.filter((part) => part.type === "step-start").length;
4574
+ }
4575
+ const streamStepStarts = message2.parts.flatMap(
4576
+ (part, index) => part.type === "step-start" ? [index] : []
4577
+ );
4578
+ const completedSteps = streamStepStarts.length - session.initialStepStarts;
4579
+ if (completedSteps < 0) {
4580
+ throw new Error(
4581
+ "writeAssistantSegment: response lost an existing step boundary"
4582
+ );
4583
+ }
4584
+ const segmentIndex = session.segments.findLastIndex(
4585
+ (candidate) => candidate.startStep < completedSteps
4586
+ );
4587
+ if (segmentIndex >= 0) {
4588
+ const segment = session.segments[segmentIndex];
4589
+ id = segment.id;
4590
+ if (segmentIndex > 0) {
4591
+ const start = streamStepStarts[session.initialStepStarts + segment.startStep];
4592
+ if (start === void 0) {
4593
+ throw new Error(
4594
+ `writeAssistantSegment: response is missing step ${segment.startStep + 1}`
4595
+ );
4596
+ }
4597
+ parts = message2.parts.slice(start);
4598
+ }
4599
+ } else {
4600
+ const lastSegment = session.segments.at(-1);
4601
+ if (lastSegment) {
4602
+ id = lastSegment.id;
4603
+ parts = [];
4604
+ }
4605
+ }
4606
+ }
4607
+ const fragment2 = assistant({
4608
+ ...message2,
4609
+ id,
4610
+ parts
4611
+ });
4612
+ if (!session) {
4613
+ this.set(fragment2);
4614
+ await this.save({ branch: false });
4615
+ return;
4616
+ }
4617
+ const stored = await this.#store.getMessage(id);
4618
+ if (!stored) {
4619
+ throw new Error(
4620
+ `writeAssistantSegment: reserved segment "${id}" was not found`
4621
+ );
4622
+ }
4623
+ if (!fragment2.codec) {
4624
+ throw new Error("writeAssistantSegment: assistant codec is missing");
4625
+ }
4626
+ await this.#store.addMessages([
4627
+ {
4628
+ ...stored,
4629
+ name: fragment2.name,
4630
+ type: fragment2.type,
4631
+ data: fragment2.codec.encode()
4632
+ }
4633
+ ]);
4493
4634
  }
4494
4635
  #remindersFor(target) {
4495
4636
  return this.#fragments.filter(isConditionalReminder).map((fragment2) => fragment2.metadata.reminder).filter((config) => config.target === target);
@@ -4590,8 +4731,16 @@ var ContextEngine = class _ContextEngine {
4590
4731
  "steer reminders require a user message earlier in the turn"
4591
4732
  );
4592
4733
  }
4734
+ const lastAssistantMessage = chain.lastAssistantMessage;
4735
+ if (!lastAssistantMessage) {
4736
+ throw new Error("steer reminders require a completed assistant step");
4737
+ }
4593
4738
  return {
4594
4739
  ...this.#buildWhenCtx(chain, currentMessage),
4740
+ lastAssistantMessage: mergeTerminalToolParts(
4741
+ lastAssistantMessage,
4742
+ session.terminalToolParts
4743
+ ),
4595
4744
  sandbox,
4596
4745
  firedOnceIds: /* @__PURE__ */ new Set([...chain.firedOnceIds, ...session.firedOnceIds])
4597
4746
  };
@@ -6557,7 +6706,7 @@ function startKernelProcess(os, command, options) {
6557
6706
  const stderr = new PassThrough();
6558
6707
  const onStdout = (chunk) => stdout.write(chunk);
6559
6708
  const onStderr = (chunk) => stderr.write(chunk);
6560
- const { pid } = os.spawn("sh", ["-c", command], {
6709
+ const { pid } = os.spawn("bash", ["-lc", command], {
6561
6710
  ...options,
6562
6711
  onStdout,
6563
6712
  onStderr
@@ -6610,6 +6759,25 @@ async function createAgentOsSandbox(options = {}) {
6610
6759
  const err = error instanceof Error ? error : new Error(String(error));
6611
6760
  throw new AgentOsCreationError(err.message, err);
6612
6761
  }
6762
+ try {
6763
+ const probe = startKernelProcess(os, ":", {});
6764
+ const [, stderr, exitCode] = await Promise.all([
6765
+ readAll(probe.stdout),
6766
+ readAll(probe.stderr),
6767
+ probe.exit
6768
+ ]);
6769
+ if (exitCode !== 0) {
6770
+ throw new Error(stderr.trim() || `exit code ${exitCode}`);
6771
+ }
6772
+ } catch (error) {
6773
+ await os.dispose().catch(() => {
6774
+ });
6775
+ const err = error instanceof Error ? error : new Error(String(error));
6776
+ throw new AgentOsCreationError(
6777
+ `Bash is required to execute sandbox commands but could not be started: ${err.message}`,
6778
+ err
6779
+ );
6780
+ }
6613
6781
  const sandbox = {
6614
6782
  async executeCommand(command, { signal } = {}) {
6615
6783
  if (signal?.aborted) {
@@ -7143,6 +7311,7 @@ var ContainerSandboxStrategy = class {
7143
7311
  await this.engine.ensureWorkdir(this.context.containerId, this.workdir);
7144
7312
  await this.configure();
7145
7313
  }
7314
+ await this.assertBashAvailable();
7146
7315
  } catch (error) {
7147
7316
  if (acquired && !acquired.attached) {
7148
7317
  await this.stopContainer(acquired.containerId);
@@ -7441,6 +7610,15 @@ var ContainerSandboxStrategy = class {
7441
7610
  };
7442
7611
  }
7443
7612
  }
7613
+ async assertBashAvailable() {
7614
+ const result = await this.exec(":");
7615
+ if (result.exitCode === 0) return;
7616
+ const detail = result.stderr.trim() || result.stdout.trim();
7617
+ throw this.engine.errors.generic(
7618
+ `Bash is required to execute sandbox commands but could not be started${detail ? `: ${detail}` : "."}`,
7619
+ this.context.containerId
7620
+ );
7621
+ }
7444
7622
  spawnProcess(command, options) {
7445
7623
  const child = childSpawn(
7446
7624
  this.engine.cli,
@@ -7632,7 +7810,7 @@ var appleEngine = {
7632
7810
  flags.push("--env", `${key}=${value}`);
7633
7811
  }
7634
7812
  }
7635
- return ["exec", ...flags, containerId, "sh", "-c", command];
7813
+ return ["exec", ...flags, containerId, "bash", "-lc", command];
7636
7814
  },
7637
7815
  inspectArgs(containerId) {
7638
7816
  return ["inspect", containerId];
@@ -7661,9 +7839,15 @@ var appleEngine = {
7661
7839
  return /already exists/i.test(message2);
7662
7840
  },
7663
7841
  async ensureWorkdir(containerId, workdir) {
7664
- await spawn3(CLI, ["exec", containerId, "sh", "-c", `mkdir -p ${workdir}`]);
7842
+ await spawn3(CLI, [
7843
+ "exec",
7844
+ containerId,
7845
+ "bash",
7846
+ "-lc",
7847
+ `mkdir -p ${shellQuote(workdir)}`
7848
+ ]);
7665
7849
  },
7666
- defaultImage: "docker.io/library/alpine:latest",
7850
+ defaultImage: "docker.io/library/bash:5.3-alpine3.24",
7667
7851
  createInstallerContext: createAppleInstallerContext,
7668
7852
  async imageExists(tag) {
7669
7853
  try {
@@ -8313,6 +8497,7 @@ async function createDaytonaSandbox(client, options = {}) {
8313
8497
  } catch (error) {
8314
8498
  throw normalizeDaytonaError(error, sdk);
8315
8499
  }
8500
+ await assertDaytonaBash(sandbox, options.commandTimeout);
8316
8501
  const backend = createDaytonaSandboxMethods({
8317
8502
  sandbox,
8318
8503
  commandTimeout: options.commandTimeout
@@ -8328,6 +8513,24 @@ async function createDaytonaSandbox(client, options = {}) {
8328
8513
  }
8329
8514
  return backend;
8330
8515
  }
8516
+ async function assertDaytonaBash(sandbox, commandTimeout) {
8517
+ try {
8518
+ const result = await sandbox.process.executeCommand(
8519
+ "bash -lc ':'",
8520
+ void 0,
8521
+ void 0,
8522
+ commandTimeout
8523
+ );
8524
+ if (result.exitCode === void 0 || result.exitCode === 0) return;
8525
+ throw new Error(result.result || `exit code ${result.exitCode}`);
8526
+ } catch (error) {
8527
+ const err = toError(error);
8528
+ throw new DaytonaCreationError(
8529
+ `Bash is required to execute sandbox commands but could not be started: ${err.message}`,
8530
+ err
8531
+ );
8532
+ }
8533
+ }
8331
8534
  var UNRECOVERABLE_SANDBOX_STATES = /* @__PURE__ */ new Set([
8332
8535
  "error",
8333
8536
  "build_failed",
@@ -8464,7 +8667,7 @@ function createDaytonaSandboxMethods(args) {
8464
8667
  return abortedCommandResult();
8465
8668
  }
8466
8669
  const response = await sandbox.process.executeCommand(
8467
- command,
8670
+ `bash -lc ${shellQuote(command)}`,
8468
8671
  void 0,
8469
8672
  void 0,
8470
8673
  commandTimeout
@@ -8706,13 +8909,13 @@ function buildSessionCommand(command, options) {
8706
8909
  const env = options.env ?? {};
8707
8910
  const entries = Object.entries(env);
8708
8911
  if (entries.length === 0) {
8709
- return `sh -lc ${shellQuote(`${cwdPrefix}${command}`)}`;
8912
+ return `bash -lc ${shellQuote(`${cwdPrefix}${command}`)}`;
8710
8913
  }
8711
8914
  for (const [key] of entries) {
8712
8915
  validateEnvKey(key);
8713
8916
  }
8714
8917
  const exports = entries.map(([key, value]) => `export ${key}=${shellQuote(value)}`).join("; ");
8715
- return `sh -lc ${shellQuote(`${exports}; ${cwdPrefix}${command}`)}`;
8918
+ return `bash -lc ${shellQuote(`${exports}; ${cwdPrefix}${command}`)}`;
8716
8919
  }
8717
8920
  function validateEnvKey(key) {
8718
8921
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
@@ -8952,7 +9155,7 @@ var dockerEngine = {
8952
9155
  flags.push("-e", `${key}=${value}`);
8953
9156
  }
8954
9157
  }
8955
- return ["exec", ...flags, containerId, "sh", "-c", command];
9158
+ return ["exec", ...flags, containerId, "bash", "-lc", command];
8956
9159
  },
8957
9160
  inspectArgs(containerId) {
8958
9161
  return [
@@ -8995,7 +9198,7 @@ var dockerEngine = {
8995
9198
  },
8996
9199
  async ensureWorkdir() {
8997
9200
  },
8998
- defaultImage: "alpine:latest",
9201
+ defaultImage: "bash:5.3-alpine3.24",
8999
9202
  createInstallerContext,
9000
9203
  async imageExists(tag) {
9001
9204
  try {
@@ -9105,8 +9308,8 @@ var ComposeStrategy = class extends ContainerSandboxStrategy {
9105
9308
  "exec",
9106
9309
  "-T",
9107
9310
  this.service,
9108
- "sh",
9109
- "-c",
9311
+ "bash",
9312
+ "-lc",
9110
9313
  command
9111
9314
  ],
9112
9315
  { signal: options?.signal }
@@ -9132,8 +9335,8 @@ var ComposeStrategy = class extends ContainerSandboxStrategy {
9132
9335
  "-T",
9133
9336
  ...buildDockerExecFlags(options),
9134
9337
  this.service,
9135
- "sh",
9136
- "-c",
9338
+ "bash",
9339
+ "-lc",
9137
9340
  command
9138
9341
  ]);
9139
9342
  return toSandboxProcess(child, options?.signal);
@@ -9191,10 +9394,10 @@ import spawn6 from "nano-spawn";
9191
9394
  import { posix as posix2 } from "node:path";
9192
9395
  var STRACE_FLAGS = "-f -y -qq -e trace=%file,write,pwrite64,writev";
9193
9396
  function buildStraceCommand(command, traceFile, traceDir) {
9194
- return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} -- sh -c ${shellQuote(command)}`;
9397
+ return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} -- bash -lc ${shellQuote(command)}`;
9195
9398
  }
9196
9399
  function buildTracedCommand(command, traceFile, traceDir, sentinel) {
9197
- return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} -- sh -c ${shellQuote(command)}; __dat_rc=$?; printf '\\n%s\\n' ${shellQuote(sentinel)}; base64 ${shellQuote(traceFile)} 2>/dev/null; rm -f ${shellQuote(traceFile)} 2>/dev/null; exit $__dat_rc`;
9400
+ return `mkdir -p ${shellQuote(traceDir)} 2>/dev/null; strace ${STRACE_FLAGS} -o ${shellQuote(traceFile)} -- bash -lc ${shellQuote(command)}; __dat_rc=$?; printf '\\n%s\\n' ${shellQuote(sentinel)}; base64 ${shellQuote(traceFile)} 2>/dev/null; rm -f ${shellQuote(traceFile)} 2>/dev/null; exit $__dat_rc`;
9198
9401
  }
9199
9402
  function splitTracedOutput(stdout, sentinel) {
9200
9403
  const marker = `
@@ -9817,7 +10020,7 @@ function formatVersion(version) {
9817
10020
  // packages/context/src/lib/sandbox/microsandbox-sandbox.ts
9818
10021
  import { randomUUID as randomUUID3 } from "node:crypto";
9819
10022
  var MICROSANDBOX_DEFAULT_DESTINATION = "/workspace";
9820
- var MICROSANDBOX_DEFAULT_IMAGE = "alpine";
10023
+ var MICROSANDBOX_DEFAULT_IMAGE = "bash:5.3-alpine3.24";
9821
10024
  var MICROSANDBOX_MAX_NAME_BYTES = 128;
9822
10025
  var COMMAND_TIMEOUT_EXIT_CODE = 124;
9823
10026
  var MicrosandboxSandboxError = class extends Error {
@@ -9857,8 +10060,17 @@ async function createMicrosandboxSandbox(options = {}) {
9857
10060
  let vm;
9858
10061
  try {
9859
10062
  vm = await acquireSandbox(sdk, { ...options, name, ephemeral, workdir });
10063
+ } catch (error) {
10064
+ throw normalizeMicrosandboxError(error, sdk);
10065
+ }
10066
+ try {
9860
10067
  await vm.fs().mkdir(workdir);
10068
+ await assertMicrosandboxBash(vm);
9861
10069
  } catch (error) {
10070
+ await vm.stop().catch(() => {
10071
+ });
10072
+ if (ephemeral) await sdk.Sandbox.remove(name).catch(() => {
10073
+ });
9862
10074
  throw normalizeMicrosandboxError(error, sdk);
9863
10075
  }
9864
10076
  const backend = createMicrosandboxMethods({
@@ -9932,10 +10144,24 @@ function buildSandbox(sdk, options) {
9932
10144
  if (options.memory !== void 0) builder = builder.memory(options.memory);
9933
10145
  if (options.env) builder = builder.envs(options.env);
9934
10146
  if (options.configure) builder = options.configure(builder);
9935
- return builder.create();
10147
+ return builder.shell("bash").create();
10148
+ }
10149
+ async function assertMicrosandboxBash(vm) {
10150
+ try {
10151
+ const result = await vm.exec("bash", ["-lc", ":"]);
10152
+ if (result.code === 0) return;
10153
+ throw new Error(result.stderr() || `exit code ${result.code}`);
10154
+ } catch (error) {
10155
+ const err = toError2(error);
10156
+ throw new MicrosandboxCreationError(
10157
+ `Bash is required to execute sandbox commands but could not be started: ${err.message}`,
10158
+ err
10159
+ );
10160
+ }
9936
10161
  }
9937
10162
  function normalizeMicrosandboxError(error, sdk) {
9938
10163
  const err = toError2(error);
10164
+ if (err instanceof MicrosandboxSandboxError) return err;
9939
10165
  if (err instanceof sdk.LibkrunfwNotFoundError) {
9940
10166
  return new MicrosandboxNotAvailableError(err);
9941
10167
  }
@@ -10050,7 +10276,7 @@ async function pumpExecStream(args) {
10050
10276
  }
10051
10277
  signal?.addEventListener("abort", abort, { once: true });
10052
10278
  try {
10053
- handle = await vm.execStreamWith("sh", (builder) => {
10279
+ handle = await vm.execStreamWith("bash", (builder) => {
10054
10280
  builder.args(["-lc", command]).stdinNull();
10055
10281
  if (options.cwd) builder.cwd(options.cwd);
10056
10282
  if (options.env) builder.envs(options.env);