@tbrandenburg/node-red-agents 0.1.3 → 0.1.5

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.
@@ -1,4 +1,4 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
3
  // Framework-agnostic bounded-concurrency FIFO scheduler. Deliberately has no
4
4
  // Node-RED dependency (same reasoning as lib/execution/lifecycle.js) so it's
@@ -9,89 +9,90 @@
9
9
  // model already gives independent executions for free (see AGENTS fan-out
10
10
  // spec); this class only adds the bound + the waiting line on top of that.
11
11
  class ExecutionScheduler {
12
- constructor({ concurrency, onStart, onQueued, onSettled } = {}) {
13
- this.concurrency = Number.isFinite(concurrency) && concurrency > 0 ? Math.floor(concurrency) : 1;
14
- this.onStart = onStart; // (item) => Promise -- required
15
- this.onQueued = onQueued; // (item) => void -- optional
16
- // Called after this item is removed from `active` AND after any
17
- // queued item that became eligible to start has already been
18
- // started -- i.e. the scheduler's own bookkeeping is fully
19
- // settled, so a status render triggered from here is never stale.
20
- this.onSettled = onSettled; // (item) => void -- optional
21
- this.queue = [];
22
- this.active = new Map();
23
- }
12
+ constructor({ concurrency, onStart, onQueued, onSettled } = {}) {
13
+ this.concurrency =
14
+ Number.isFinite(concurrency) && concurrency > 0 ? Math.floor(concurrency) : 1;
15
+ this.onStart = onStart; // (item) => Promise -- required
16
+ this.onQueued = onQueued; // (item) => void -- optional
17
+ // Called after this item is removed from `active` AND after any
18
+ // queued item that became eligible to start has already been
19
+ // started -- i.e. the scheduler's own bookkeeping is fully
20
+ // settled, so a status render triggered from here is never stale.
21
+ this.onSettled = onSettled; // (item) => void -- optional
22
+ this.queue = [];
23
+ this.active = new Map();
24
+ }
24
25
 
25
- get activeCount() {
26
- return this.active.size;
27
- }
26
+ get activeCount() {
27
+ return this.active.size;
28
+ }
28
29
 
29
- get queuedCount() {
30
- return this.queue.length;
31
- }
30
+ get queuedCount() {
31
+ return this.queue.length;
32
+ }
32
33
 
33
- activeIds() {
34
- return Array.from(this.active.keys());
35
- }
34
+ activeIds() {
35
+ return Array.from(this.active.keys());
36
+ }
36
37
 
37
- // item must have a unique `executionId` property; anything else on it
38
- // is opaque to the scheduler (agent.js stores msg/send/done/resolved).
39
- submit(item) {
40
- if (this.active.size < this.concurrency) {
41
- this._start(item);
42
- } else {
43
- this.queue.push(item);
44
- if (this.onQueued) this.onQueued(item);
45
- }
38
+ // item must have a unique `executionId` property; anything else on it
39
+ // is opaque to the scheduler (agent.js stores msg/send/done/resolved).
40
+ submit(item) {
41
+ if (this.active.size < this.concurrency) {
42
+ this._start(item);
43
+ } else {
44
+ this.queue.push(item);
45
+ if (this.onQueued) this.onQueued(item);
46
46
  }
47
+ }
47
48
 
48
- _start(item) {
49
- this.active.set(item.executionId, item);
50
- Promise.resolve(this.onStart(item)).finally(() => {
51
- this.active.delete(item.executionId);
52
- this._advance();
53
- if (this.onSettled) this.onSettled(item);
54
- });
55
- }
49
+ _start(item) {
50
+ this.active.set(item.executionId, item);
51
+ Promise.resolve(this.onStart(item)).finally(() => {
52
+ this.active.delete(item.executionId);
53
+ this._advance();
54
+ if (this.onSettled) this.onSettled(item);
55
+ });
56
+ }
56
57
 
57
- _advance() {
58
- while (this.active.size < this.concurrency && this.queue.length > 0) {
59
- this._start(this.queue.shift());
60
- }
58
+ _advance() {
59
+ while (this.active.size < this.concurrency && this.queue.length > 0) {
60
+ this._start(this.queue.shift());
61
61
  }
62
+ }
62
63
 
63
- // Removes every still-queued item (FIFO order) without ever starting
64
- // them, calling onCancel for each. Used on node close/redeploy so
65
- // queued-but-not-yet-started messages get a clean done() instead of
66
- // hanging forever. Does not touch active executions -- that's the
67
- // caller's responsibility (terminate() belongs to the runtime layer).
68
- drainQueue(onCancel) {
69
- const remaining = this.queue.splice(0, this.queue.length);
70
- if (onCancel) remaining.forEach((item) => onCancel(item));
71
- return remaining;
72
- }
64
+ // Removes every still-queued item (FIFO order) without ever starting
65
+ // them, calling onCancel for each. Used on node close/redeploy so
66
+ // queued-but-not-yet-started messages get a clean done() instead of
67
+ // hanging forever. Does not touch active executions -- that's the
68
+ // caller's responsibility (terminate() belongs to the runtime layer).
69
+ drainQueue(onCancel) {
70
+ const remaining = this.queue.splice(0, this.queue.length);
71
+ if (onCancel) remaining.forEach((item) => onCancel(item));
72
+ return remaining;
73
+ }
73
74
 
74
- // On-demand single-item cancellation (the `terminate` operation), as
75
- // opposed to drainQueue's "everything, node is closing" semantics.
76
- // Returns:
77
- // { status: 'active', item } -- still running; caller must kill the
78
- // actual process/runtime itself, this
79
- // scheduler has no handle on that.
80
- // { status: 'queued', item } -- removed from the queue before it ever
81
- // started; caller must still settle the
82
- // item's own done()/send() itself, same
83
- // as drainQueue's onCancel.
84
- // null -- unknown executionId (already finished,
85
- // or never existed).
86
- cancel(executionId) {
87
- if (this.active.has(executionId)) {
88
- return { status: 'active', item: this.active.get(executionId) };
89
- }
90
- const idx = this.queue.findIndex((item) => item.executionId === executionId);
91
- if (idx === -1) return null;
92
- const [item] = this.queue.splice(idx, 1);
93
- return { status: 'queued', item };
75
+ // On-demand single-item cancellation (the `terminate` operation), as
76
+ // opposed to drainQueue's "everything, node is closing" semantics.
77
+ // Returns:
78
+ // { status: 'active', item } -- still running; caller must kill the
79
+ // actual process/runtime itself, this
80
+ // scheduler has no handle on that.
81
+ // { status: 'queued', item } -- removed from the queue before it ever
82
+ // started; caller must still settle the
83
+ // item's own done()/send() itself, same
84
+ // as drainQueue's onCancel.
85
+ // null -- unknown executionId (already finished,
86
+ // or never existed).
87
+ cancel(executionId) {
88
+ if (this.active.has(executionId)) {
89
+ return { status: "active", item: this.active.get(executionId) };
94
90
  }
91
+ const idx = this.queue.findIndex((item) => item.executionId === executionId);
92
+ if (idx === -1) return null;
93
+ const [item] = this.queue.splice(idx, 1);
94
+ return { status: "queued", item };
95
+ }
95
96
  }
96
97
 
97
98
  module.exports = { ExecutionScheduler };
@@ -1,4 +1,4 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
3
  // Pure function computing the node.status() shape from current scheduler
4
4
  // counts plus the last terminal outcome. Kept separate from agent.js so the
@@ -8,17 +8,17 @@
8
8
  // lastTerminal: undefined (never run) | 'completed' | 'failed' | 'timeout'
9
9
  // lastText: optional override for the failed-state text (e.g. 'bad config')
10
10
  function computeNodeStatus({ active, queued, lastTerminal, lastText }) {
11
- if (active > 0 || queued > 0) {
12
- let text = `${active} running`;
13
- if (queued > 0) text += ` \u00b7 ${queued} queued`;
14
- return { fill: 'blue', shape: 'dot', text };
15
- }
11
+ if (active > 0 || queued > 0) {
12
+ let text = `${active} running`;
13
+ if (queued > 0) text += ` \u00b7 ${queued} queued`;
14
+ return { fill: "blue", shape: "dot", text };
15
+ }
16
16
 
17
- if (lastTerminal === 'completed') return { fill: 'green', shape: 'dot', text: 'completed' };
18
- if (lastTerminal === 'failed') return { fill: 'red', shape: 'ring', text: lastText || 'failed' };
19
- if (lastTerminal === 'timeout') return { fill: 'yellow', shape: 'ring', text: 'timeout' };
17
+ if (lastTerminal === "completed") return { fill: "green", shape: "dot", text: "completed" };
18
+ if (lastTerminal === "failed") return { fill: "red", shape: "ring", text: lastText || "failed" };
19
+ if (lastTerminal === "timeout") return { fill: "yellow", shape: "ring", text: "timeout" };
20
20
 
21
- return {}; // idle, never run -- no status
21
+ return {}; // idle, never run -- no status
22
22
  }
23
23
 
24
24
  module.exports = { computeNodeStatus };
@@ -1,4 +1,4 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
3
  // Generic mcpServers[] (see AGENTS node schema) -> OpenCode's keyed `mcp`
4
4
  // config object, as verified against opencode's real config schema:
@@ -7,25 +7,25 @@
7
7
  //
8
8
  // Each agent adapter owns its own translation; this module is OpenCode's.
9
9
  function toOpenCodeMcp(mcpServers) {
10
- const out = {};
11
- if (!Array.isArray(mcpServers)) return out;
10
+ const out = {};
11
+ if (!Array.isArray(mcpServers)) return out;
12
12
 
13
- for (const server of mcpServers) {
14
- if (!server || typeof server.name !== 'string' || !server.name.trim()) continue;
13
+ for (const server of mcpServers) {
14
+ if (!server || typeof server.name !== "string" || !server.name.trim()) continue;
15
15
 
16
- if (server.type === 'remote') {
17
- if (typeof server.url !== 'string' || !server.url.trim()) continue;
18
- out[server.name] = { type: 'remote', url: server.url, enabled: true };
19
- } else if (server.type === 'local') {
20
- if (typeof server.command !== 'string' || !server.command.trim()) continue;
21
- const args = Array.isArray(server.args) ? server.args : [];
22
- out[server.name] = { type: 'local', command: [server.command, ...args], enabled: true };
23
- }
24
- // Unknown types are silently skipped -- validate() at the adapter
25
- // level is responsible for surfacing a clear error before execution.
16
+ if (server.type === "remote") {
17
+ if (typeof server.url !== "string" || !server.url.trim()) continue;
18
+ out[server.name] = { type: "remote", url: server.url, enabled: true };
19
+ } else if (server.type === "local") {
20
+ if (typeof server.command !== "string" || !server.command.trim()) continue;
21
+ const args = Array.isArray(server.args) ? server.args : [];
22
+ out[server.name] = { type: "local", command: [server.command, ...args], enabled: true };
26
23
  }
24
+ // Unknown types are silently skipped -- validate() at the adapter
25
+ // level is responsible for surfacing a clear error before execution.
26
+ }
27
27
 
28
- return out;
28
+ return out;
29
29
  }
30
30
 
31
31
  module.exports = { toOpenCodeMcp };
@@ -1,21 +1,21 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
3
  // Generic interface every runtime (Direct, SRT, and later Daytona/OpenShell)
4
4
  // must implement. Agent adapters never depend on a runtime directly, and
5
5
  // runtimes never depend on an agent adapter -- they only see the normalized
6
6
  // executionRequest built by lib/execution/lifecycle.js.
7
7
  class RuntimeProvider {
8
- // executionRequest: { id, command, args, cwd, env, timeoutMs }
9
- // handlers: { onLine(line: string), onExit(...) } -- onExit is not
10
- // called directly by implementations; execute() resolves instead with
11
- // { exitCode, signal, stderr, timedOut }.
12
- async execute(_executionRequest, _handlers) {
13
- throw new Error('RuntimeProvider.execute() not implemented');
14
- }
8
+ // executionRequest: { id, command, args, cwd, env, timeoutMs }
9
+ // handlers: { onLine(line: string), onExit(...) } -- onExit is not
10
+ // called directly by implementations; execute() resolves instead with
11
+ // { exitCode, signal, stderr, timedOut }.
12
+ async execute(_executionRequest, _handlers) {
13
+ throw new Error("RuntimeProvider.execute() not implemented");
14
+ }
15
15
 
16
- async terminate(_executionId) {}
16
+ async terminate(_executionId) {}
17
17
 
18
- async cleanup(_executionId) {}
18
+ async cleanup(_executionId) {}
19
19
  }
20
20
 
21
21
  module.exports = { RuntimeProvider };
@@ -1,28 +1,28 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
- const { RuntimeProvider } = require('./base');
4
- const { runProcess, terminate } = require('./process-exec');
3
+ const { RuntimeProvider } = require("./base");
4
+ const { runProcess, terminate } = require("./process-exec");
5
5
 
6
6
  // The portability baseline: runs the agent CLI directly as a child process
7
7
  // wherever it's on PATH (laptop, GitHub runner, Kubernetes container, ...).
8
8
  class DirectRuntime extends RuntimeProvider {
9
- async execute(executionRequest, handlers) {
10
- return runProcess(
11
- {
12
- id: executionRequest.id,
13
- cmd: executionRequest.command,
14
- args: executionRequest.args,
15
- cwd: executionRequest.cwd,
16
- env: executionRequest.env,
17
- timeoutMs: executionRequest.timeoutMs
18
- },
19
- handlers
20
- );
21
- }
9
+ async execute(executionRequest, handlers) {
10
+ return runProcess(
11
+ {
12
+ id: executionRequest.id,
13
+ cmd: executionRequest.command,
14
+ args: executionRequest.args,
15
+ cwd: executionRequest.cwd,
16
+ env: executionRequest.env,
17
+ timeoutMs: executionRequest.timeoutMs,
18
+ },
19
+ handlers,
20
+ );
21
+ }
22
22
 
23
- async terminate(executionId) {
24
- terminate(executionId);
25
- }
23
+ async terminate(executionId) {
24
+ terminate(executionId);
25
+ }
26
26
  }
27
27
 
28
28
  module.exports = { DirectRuntime };
@@ -1,10 +1,10 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
3
  // Shared spawn/timeout/kill logic used by both the Direct and SRT runtimes.
4
4
  // Direct and SRT differ only in *which* command+args get spawned (see
5
5
  // direct.js / srt.js) -- everything about process lifecycle, JSONL line
6
6
  // buffering, and timeout handling lives here exactly once.
7
- const { spawn } = require('child_process');
7
+ const { spawn } = require("child_process");
8
8
 
9
9
  const GRACE_PERIOD_MS = 2000;
10
10
 
@@ -12,94 +12,94 @@ const GRACE_PERIOD_MS = 2000;
12
12
  const registry = new Map();
13
13
 
14
14
  function killProcessGroup(child, signal) {
15
- if (!child || child.exitCode !== null || child.signalCode !== null) return;
15
+ if (!child || child.exitCode !== null || child.signalCode !== null) return;
16
+ try {
17
+ // `detached: true` (see runProcess) gives the child its own process
18
+ // group with pgid === child.pid, so `-pid` reaches the whole tree
19
+ // (e.g. srt's bwrap wrapper + the agent CLI it spawns), leaving no
20
+ // orphans -- verified manually against a real `srt`-wrapped process.
21
+ process.kill(-child.pid, signal);
22
+ } catch (err) {
16
23
  try {
17
- // `detached: true` (see runProcess) gives the child its own process
18
- // group with pgid === child.pid, so `-pid` reaches the whole tree
19
- // (e.g. srt's bwrap wrapper + the agent CLI it spawns), leaving no
20
- // orphans -- verified manually against a real `srt`-wrapped process.
21
- process.kill(-child.pid, signal);
22
- } catch (err) {
23
- try {
24
- child.kill(signal);
25
- } catch (_err) {
26
- // Process likely already exited between the check above and here.
27
- }
24
+ child.kill(signal);
25
+ } catch (_err) {
26
+ // Process likely already exited between the check above and here.
28
27
  }
28
+ }
29
29
  }
30
30
 
31
31
  function runProcess(executionRequest, handlers = {}) {
32
- const { id, cmd, args, cwd, env, timeoutMs } = executionRequest;
32
+ const { id, cmd, args, cwd, env, timeoutMs } = executionRequest;
33
33
 
34
- return new Promise((resolve, reject) => {
35
- let child;
36
- try {
37
- child = spawn(cmd, args, {
38
- cwd: cwd || undefined,
39
- env: env || process.env,
40
- detached: true,
41
- // Agent CLIs (opencode, srt-wrapped or not) wait on stdin if
42
- // it's left open as a pipe; close it so they behave like a
43
- // normal non-interactive invocation (see AGENTS.md).
44
- stdio: ['ignore', 'pipe', 'pipe']
45
- });
46
- } catch (err) {
47
- reject(err);
48
- return;
49
- }
34
+ return new Promise((resolve, reject) => {
35
+ let child;
36
+ try {
37
+ child = spawn(cmd, args, {
38
+ cwd: cwd || undefined,
39
+ env: env || process.env,
40
+ detached: true,
41
+ // Agent CLIs (opencode, srt-wrapped or not) wait on stdin if
42
+ // it's left open as a pipe; close it so they behave like a
43
+ // normal non-interactive invocation (see AGENTS.md).
44
+ stdio: ["ignore", "pipe", "pipe"],
45
+ });
46
+ } catch (err) {
47
+ reject(err);
48
+ return;
49
+ }
50
50
 
51
- const state = { child, timeoutTimer: null, killTimer: null, timedOut: false };
52
- registry.set(id, state);
51
+ const state = { child, timeoutTimer: null, killTimer: null, timedOut: false };
52
+ registry.set(id, state);
53
53
 
54
- let lineBuffer = '';
55
- let stderr = '';
54
+ let lineBuffer = "";
55
+ let stderr = "";
56
56
 
57
- child.stdout.on('data', (chunk) => {
58
- lineBuffer += chunk.toString();
59
- let idx;
60
- while ((idx = lineBuffer.indexOf('\n')) >= 0) {
61
- const line = lineBuffer.slice(0, idx);
62
- lineBuffer = lineBuffer.slice(idx + 1);
63
- if (handlers.onLine) handlers.onLine(line);
64
- }
65
- });
66
- child.stderr.on('data', (chunk) => {
67
- stderr += chunk.toString();
68
- });
57
+ child.stdout.on("data", (chunk) => {
58
+ lineBuffer += chunk.toString();
59
+ let idx;
60
+ while ((idx = lineBuffer.indexOf("\n")) >= 0) {
61
+ const line = lineBuffer.slice(0, idx);
62
+ lineBuffer = lineBuffer.slice(idx + 1);
63
+ if (handlers.onLine) handlers.onLine(line);
64
+ }
65
+ });
66
+ child.stderr.on("data", (chunk) => {
67
+ stderr += chunk.toString();
68
+ });
69
69
 
70
- if (timeoutMs && timeoutMs > 0) {
71
- state.timeoutTimer = setTimeout(() => {
72
- state.timedOut = true;
73
- killProcessGroup(child, 'SIGTERM');
74
- state.killTimer = setTimeout(() => killProcessGroup(child, 'SIGKILL'), GRACE_PERIOD_MS);
75
- }, timeoutMs);
76
- }
70
+ if (timeoutMs && timeoutMs > 0) {
71
+ state.timeoutTimer = setTimeout(() => {
72
+ state.timedOut = true;
73
+ killProcessGroup(child, "SIGTERM");
74
+ state.killTimer = setTimeout(() => killProcessGroup(child, "SIGKILL"), GRACE_PERIOD_MS);
75
+ }, timeoutMs);
76
+ }
77
77
 
78
- child.on('error', (err) => {
79
- cleanupTimers(state);
80
- registry.delete(id);
81
- reject(err);
82
- });
78
+ child.on("error", (err) => {
79
+ cleanupTimers(state);
80
+ registry.delete(id);
81
+ reject(err);
82
+ });
83
83
 
84
- child.on('close', (code, signal) => {
85
- if (lineBuffer.length && handlers.onLine) handlers.onLine(lineBuffer);
86
- cleanupTimers(state);
87
- registry.delete(id);
88
- resolve({ exitCode: code, signal, stderr, timedOut: state.timedOut, pid: child.pid });
89
- });
84
+ child.on("close", (code, signal) => {
85
+ if (lineBuffer.length && handlers.onLine) handlers.onLine(lineBuffer);
86
+ cleanupTimers(state);
87
+ registry.delete(id);
88
+ resolve({ exitCode: code, signal, stderr, timedOut: state.timedOut, pid: child.pid });
90
89
  });
90
+ });
91
91
  }
92
92
 
93
93
  function cleanupTimers(state) {
94
- if (state.timeoutTimer) clearTimeout(state.timeoutTimer);
95
- if (state.killTimer) clearTimeout(state.killTimer);
94
+ if (state.timeoutTimer) clearTimeout(state.timeoutTimer);
95
+ if (state.killTimer) clearTimeout(state.killTimer);
96
96
  }
97
97
 
98
98
  function terminate(id) {
99
- const state = registry.get(id);
100
- if (!state) return;
101
- killProcessGroup(state.child, 'SIGTERM');
102
- state.killTimer = setTimeout(() => killProcessGroup(state.child, 'SIGKILL'), GRACE_PERIOD_MS);
99
+ const state = registry.get(id);
100
+ if (!state) return;
101
+ killProcessGroup(state.child, "SIGTERM");
102
+ state.killTimer = setTimeout(() => killProcessGroup(state.child, "SIGKILL"), GRACE_PERIOD_MS);
103
103
  }
104
104
 
105
105
  module.exports = { runProcess, terminate, killProcessGroup, GRACE_PERIOD_MS };
@@ -1,9 +1,9 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
- const { RuntimeProvider } = require('./base');
4
- const { runProcess, terminate } = require('./process-exec');
3
+ const { RuntimeProvider } = require("./base");
4
+ const { runProcess, terminate } = require("./process-exec");
5
5
 
6
- const DEFAULT_BINARY = 'srt';
6
+ const DEFAULT_BINARY = "srt";
7
7
 
8
8
  // Wraps execution in Anthropic's `srt` (sandbox-runtime) CLI, which is
9
9
  // already installed on this host as a plain binary. Verified empirically
@@ -19,45 +19,45 @@ const DEFAULT_BINARY = 'srt';
19
19
  // top of the exact same process-exec.js used by Direct: no new npm
20
20
  // dependency, no shell-quoting step, no separate process lifecycle code.
21
21
  class SrtRuntime extends RuntimeProvider {
22
- constructor(options = {}) {
23
- super();
24
- this.binary = options.binary || DEFAULT_BINARY;
25
- // Left undefined by default so `srt` falls back to its own default
26
- // (~/.srt-settings.json) -- SRT policy is deliberately kept out of
27
- // the Agent node's core schema (spec: "SRT-specific configuration
28
- // should be hidden... implemented by the runtime adapter").
29
- this.settingsPath = options.settingsPath || undefined;
30
- this.extraArgs = Array.isArray(options.extraArgs) ? options.extraArgs : [];
31
- }
22
+ constructor(options = {}) {
23
+ super();
24
+ this.binary = options.binary || DEFAULT_BINARY;
25
+ // Left undefined by default so `srt` falls back to its own default
26
+ // (~/.srt-settings.json) -- SRT policy is deliberately kept out of
27
+ // the Agent node's core schema (spec: "SRT-specific configuration
28
+ // should be hidden... implemented by the runtime adapter").
29
+ this.settingsPath = options.settingsPath || undefined;
30
+ this.extraArgs = Array.isArray(options.extraArgs) ? options.extraArgs : [];
31
+ }
32
32
 
33
- buildCommand(executionRequest) {
34
- const flags = [];
35
- if (this.settingsPath) flags.push('-s', this.settingsPath);
36
- flags.push(...this.extraArgs);
37
- return {
38
- cmd: this.binary,
39
- args: [...flags, executionRequest.command, ...executionRequest.args]
40
- };
41
- }
33
+ buildCommand(executionRequest) {
34
+ const flags = [];
35
+ if (this.settingsPath) flags.push("-s", this.settingsPath);
36
+ flags.push(...this.extraArgs);
37
+ return {
38
+ cmd: this.binary,
39
+ args: [...flags, executionRequest.command, ...executionRequest.args],
40
+ };
41
+ }
42
42
 
43
- async execute(executionRequest, handlers) {
44
- const { cmd, args } = this.buildCommand(executionRequest);
45
- return runProcess(
46
- {
47
- id: executionRequest.id,
48
- cmd,
49
- args,
50
- cwd: executionRequest.cwd,
51
- env: executionRequest.env,
52
- timeoutMs: executionRequest.timeoutMs
53
- },
54
- handlers
55
- );
56
- }
43
+ async execute(executionRequest, handlers) {
44
+ const { cmd, args } = this.buildCommand(executionRequest);
45
+ return runProcess(
46
+ {
47
+ id: executionRequest.id,
48
+ cmd,
49
+ args,
50
+ cwd: executionRequest.cwd,
51
+ env: executionRequest.env,
52
+ timeoutMs: executionRequest.timeoutMs,
53
+ },
54
+ handlers,
55
+ );
56
+ }
57
57
 
58
- async terminate(executionId) {
59
- terminate(executionId);
60
- }
58
+ async terminate(executionId) {
59
+ terminate(executionId);
60
+ }
61
61
  }
62
62
 
63
63
  module.exports = { SrtRuntime };