@mastra/docker 0.9.2-alpha.1 → 0.9.3-alpha.1

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/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { isDeepStrictEqual, promisify } from "util";
3
3
  import { MastraSandbox, ProcessHandle, SandboxAbortError, SandboxError, SandboxNotReadyError, SandboxProcessManager, validateSandboxFileMode } from "@mastra/core/workspace";
4
4
  import Docker from "dockerode";
5
5
  import { pack } from "tar-stream";
6
+ import { StringDecoder } from "string_decoder";
6
7
  import posixPath from "path/posix";
7
8
  import { Server, ServerCredentials } from "@grpc/grpc-js";
8
9
  import { createHash } from "crypto";
@@ -89,6 +90,8 @@ ret=$?
89
90
  rm -f "$1" 2>/dev/null
90
91
  exit $ret
91
92
  `;
93
+ /** KILL_SCRIPT exit code when no PGID file was readable or it was empty. */
94
+ const NO_PGID_EXIT_CODE = 3;
92
95
  /**
93
96
  * Kill script: read the recorded PGID and SIGKILL the whole process group.
94
97
  * A negative PID targets the kernel-owned process group, so descendants that
@@ -104,11 +107,12 @@ i=0
104
107
  while [ ! -r "$f" ] && [ "$i" -lt 40 ]; do sleep 0.05; i=$((i + 1)); done
105
108
  # If the PGID was never recorded (file absent/unreadable after the wait, or
106
109
  # empty), we have no group to signal or verify — report failure rather than
107
- # falsely claiming the tree was terminated.
108
- [ -r "$f" ] || exit 1
110
+ # falsely claiming the tree was terminated. Exit code 3 marks this case so
111
+ # kill() can tell it apart from a failed termination (exit 1).
112
+ [ -r "$f" ] || exit 3
109
113
  pgid=$(cat "$f" 2>/dev/null)
110
114
  rm -f "$f" 2>/dev/null
111
- [ -n "$pgid" ] || exit 1
115
+ [ -n "$pgid" ] || exit 3
112
116
  kill -STOP -"$pgid" 2>/dev/null
113
117
  kill -KILL -"$pgid" 2>/dev/null
114
118
  # Fallback for images without setsid: the leader is not a group leader, so also
@@ -285,7 +289,13 @@ var DockerProcessHandle = class extends ProcessHandle {
285
289
  await new Promise((resolve) => setTimeout(resolve, 10));
286
290
  killInfo = await killExec.inspect();
287
291
  }
288
- if (killInfo.ExitCode !== 0) throw new Error(`kill helper exited with code ${killInfo.ExitCode}`);
292
+ if (killInfo.ExitCode !== 0) {
293
+ if (killInfo.ExitCode === NO_PGID_EXIT_CODE) {
294
+ const selfInfo = await this._exec.inspect().catch(() => void 0);
295
+ if (selfInfo && !selfInfo.Running) return false;
296
+ }
297
+ throw new Error(`kill helper exited with code ${killInfo.ExitCode}`);
298
+ }
289
299
  this._killed = true;
290
300
  this._destroyStream();
291
301
  return true;
@@ -374,6 +384,8 @@ var DockerProcessManager = class extends SandboxProcessManager {
374
384
  handle._setExecStream(stream);
375
385
  const waitPromise = new Promise((resolve) => {
376
386
  const buffer = [];
387
+ const stdoutDecoder = new StringDecoder("utf8");
388
+ const stderrDecoder = new StringDecoder("utf8");
377
389
  stream.on("data", (chunk) => {
378
390
  buffer.push(chunk);
379
391
  let combined = Buffer.concat(buffer);
@@ -385,17 +397,32 @@ var DockerProcessManager = class extends SandboxProcessManager {
385
397
  buffer.push(combined);
386
398
  break;
387
399
  }
388
- const payload = combined.subarray(8, 8 + size).toString("utf-8");
389
- if (type === 1) handle.emitStdout(payload);
390
- else if (type === 2) handle.emitStderr(payload);
400
+ const payload = combined.subarray(8, 8 + size);
401
+ if (type === 1) {
402
+ const text = stdoutDecoder.write(payload);
403
+ if (text) handle.emitStdout(text);
404
+ } else if (type === 2) {
405
+ const text = stderrDecoder.write(payload);
406
+ if (text) handle.emitStderr(text);
407
+ }
391
408
  combined = combined.subarray(8 + size);
392
409
  }
393
410
  if (combined.length > 0 && buffer.length === 0) buffer.push(combined);
394
411
  });
412
+ let decodersFlushed = false;
413
+ const flushDecoders = () => {
414
+ if (decodersFlushed) return;
415
+ decodersFlushed = true;
416
+ const stdoutRest = stdoutDecoder.end();
417
+ if (stdoutRest) handle.emitStdout(stdoutRest);
418
+ const stderrRest = stderrDecoder.end();
419
+ if (stderrRest) handle.emitStderr(stderrRest);
420
+ };
395
421
  let settled = false;
396
422
  const settle = (exitCode, metadata = {}) => {
397
423
  if (settled) return;
398
424
  settled = true;
425
+ flushDecoders();
399
426
  handle._setExitCode(exitCode);
400
427
  resolve({
401
428
  success: exitCode === 0,
@@ -453,6 +480,7 @@ var DockerProcessManager = class extends SandboxProcessManager {
453
480
  settleTerminated();
454
481
  return;
455
482
  }
483
+ flushDecoders();
456
484
  settle(1, { stderr: handle.stderr || "Stream error" });
457
485
  });
458
486
  });