@myagentroam/node 0.9.131 → 0.9.132
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/connector.js +2 -1
- package/dist/marmgr.js +5 -0
- package/dist/marnodes.js +4 -0
- package/dist/marscp.js +4 -0
- package/dist/marssh.js +4 -0
- package/dist/runner/abstract-runner.js +17 -4
- package/dist/runner/claude/managed-run-controller.js +1 -1
- package/dist/runner/codex/managed-run-controller.js +1 -1
- package/dist/runner/mar-agent/managed-run-controller.js +1 -1
- package/dist/runner/opencode/managed-run-controller.js +4 -1
- package/dist/service/terminal-service.js +6 -3
- package/dist/terminal.js +85 -7
- package/package.json +9 -4
package/dist/connector.js
CHANGED
|
@@ -1480,7 +1480,8 @@ export class NodeConnector {
|
|
|
1480
1480
|
this.operationRouter.register('node.upgrade.request', (data) => this.upgradeCoordinator.request(data));
|
|
1481
1481
|
this.operationRouter.register('node.upgrade.cancel', () => this.upgradeCoordinator.cancel());
|
|
1482
1482
|
this.operationRouter.register('node.workbench.capabilities', async () => ({
|
|
1483
|
-
manifest: await this.workbenchManifestService.read()
|
|
1483
|
+
manifest: await this.workbenchManifestService.read(),
|
|
1484
|
+
binaryTerminal: true
|
|
1484
1485
|
}));
|
|
1485
1486
|
}
|
|
1486
1487
|
async initializeConversationHosting() {
|
package/dist/marmgr.js
ADDED
package/dist/marnodes.js
ADDED
package/dist/marscp.js
ADDED
package/dist/marssh.js
ADDED
|
@@ -166,6 +166,15 @@ export class AbstractRunner {
|
|
|
166
166
|
function resolvedMcpServers(raw, secrets) {
|
|
167
167
|
if (!Array.isArray(raw))
|
|
168
168
|
return [];
|
|
169
|
+
const marmgrEnvironment = {
|
|
170
|
+
...(secrets['MAR_MGR_SERVER_URL'] === undefined
|
|
171
|
+
? {}
|
|
172
|
+
: { MAR_MGR_SERVER_URL: secrets['MAR_MGR_SERVER_URL'] }),
|
|
173
|
+
...(secrets['MAR_MGR_USER_TOKEN'] === undefined
|
|
174
|
+
? {}
|
|
175
|
+
: { MAR_MGR_USER_TOKEN: secrets['MAR_MGR_USER_TOKEN'] }),
|
|
176
|
+
MAR_MGR_CONTEXT_REQUIRED: '1'
|
|
177
|
+
};
|
|
169
178
|
const result = [];
|
|
170
179
|
for (const value of raw) {
|
|
171
180
|
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
@@ -191,17 +200,20 @@ function resolvedMcpServers(raw, secrets) {
|
|
|
191
200
|
environment: record['__marGoal'] === true
|
|
192
201
|
? {
|
|
193
202
|
MAR_GOAL_MCP_ENDPOINT: record['endpoint'],
|
|
194
|
-
MAR_GOAL_MCP_TOKEN: secrets[record['secretName']]
|
|
203
|
+
MAR_GOAL_MCP_TOKEN: secrets[record['secretName']],
|
|
204
|
+
...marmgrEnvironment
|
|
195
205
|
}
|
|
196
206
|
: record['__marScheduled'] === true
|
|
197
207
|
? {
|
|
198
208
|
MAR_SCHEDULE_MCP_ENDPOINT: record['endpoint'],
|
|
199
209
|
MAR_SCHEDULE_MCP_TOKEN: secrets[record['secretName']],
|
|
200
|
-
MAR_SCHEDULE_MCP_READ_ONLY: record['readOnly'] === true ? '1' : '0'
|
|
210
|
+
MAR_SCHEDULE_MCP_READ_ONLY: record['readOnly'] === true ? '1' : '0',
|
|
211
|
+
...marmgrEnvironment
|
|
201
212
|
}
|
|
202
213
|
: {
|
|
203
214
|
MAR_MAIL_MCP_ENDPOINT: record['endpoint'],
|
|
204
|
-
MAR_MAIL_MCP_TOKEN: secrets[record['secretName']]
|
|
215
|
+
MAR_MAIL_MCP_TOKEN: secrets[record['secretName']],
|
|
216
|
+
...marmgrEnvironment
|
|
205
217
|
}
|
|
206
218
|
});
|
|
207
219
|
continue;
|
|
@@ -241,7 +253,8 @@ function resolvedMcpServers(raw, secrets) {
|
|
|
241
253
|
],
|
|
242
254
|
environment: {
|
|
243
255
|
...runtimeEnvironment,
|
|
244
|
-
...configuredEnvironment
|
|
256
|
+
...configuredEnvironment,
|
|
257
|
+
...marmgrEnvironment
|
|
245
258
|
}
|
|
246
259
|
});
|
|
247
260
|
}
|
|
@@ -170,7 +170,7 @@ export class ClaudeManagedRunController {
|
|
|
170
170
|
...(typeof payload.model === 'string' ? { model: payload.model } : {}),
|
|
171
171
|
...(typeof payload.effort === 'string' ? { effort: payload.effort } : {}),
|
|
172
172
|
...(typeof payload.access === 'string' ? { access: payload.access } : {}),
|
|
173
|
-
environment: secretEnvironment,
|
|
173
|
+
environment: { ...secretEnvironment, MAR_MGR_CONTEXT_REQUIRED: '1' },
|
|
174
174
|
...(typeof payload.personalInstructions === 'string'
|
|
175
175
|
? { personalInstructions: payload.personalInstructions }
|
|
176
176
|
: {}),
|
|
@@ -385,7 +385,7 @@ export class CodexManagedRunController {
|
|
|
385
385
|
return;
|
|
386
386
|
}
|
|
387
387
|
try {
|
|
388
|
-
this.runner.prepareEnvironment(secretEnvironment, runId);
|
|
388
|
+
this.runner.prepareEnvironment({ ...secretEnvironment, MAR_MGR_CONTEXT_REQUIRED: '1' }, runId);
|
|
389
389
|
}
|
|
390
390
|
catch (error) {
|
|
391
391
|
this.host.emit(runId, 'run.rejected', { code: safeErrorCode(error, 'SECRET_ENVIRONMENT_INVALID') }, 'FAILED');
|
|
@@ -686,7 +686,7 @@ export function allowsUntrustedWebFetchTls(environment) {
|
|
|
686
686
|
return environment['MAR_AGENT_WEB_FETCH_ALLOW_UNTRUSTED_TLS'] !== '0';
|
|
687
687
|
}
|
|
688
688
|
async function resolveMarAgentHostRuntimeConfiguration(secretEnvironment = {}) {
|
|
689
|
-
const environment = { ...process.env, ...secretEnvironment };
|
|
689
|
+
const environment = { ...process.env, ...secretEnvironment, MAR_MGR_CONTEXT_REQUIRED: '1' };
|
|
690
690
|
const ripgrep = await availableBundledRipgrep();
|
|
691
691
|
return {
|
|
692
692
|
environment: ripgrep === undefined ? environment : prependBundledRipgrepToPath(environment, ripgrep),
|
|
@@ -108,7 +108,10 @@ export class OpenCodeManagedRunController {
|
|
|
108
108
|
let mcp;
|
|
109
109
|
let attachments;
|
|
110
110
|
try {
|
|
111
|
-
environment =
|
|
111
|
+
environment = {
|
|
112
|
+
...parseSecretEnvironment(payload.secretEnvironment),
|
|
113
|
+
MAR_MGR_CONTEXT_REQUIRED: '1'
|
|
114
|
+
};
|
|
112
115
|
mcpSecretEnvironment = parseSecretEnvironment(payload.mcpSecretEnvironment);
|
|
113
116
|
mcp = this.runner.mcpConfiguration(payload.mcpInstallations, {
|
|
114
117
|
...environment,
|
|
@@ -38,8 +38,11 @@ export class TerminalService {
|
|
|
38
38
|
if (commandMode &&
|
|
39
39
|
(input.workspaceId !== undefined ||
|
|
40
40
|
typeof input.command !== 'string' ||
|
|
41
|
-
input.command.trim().length === 0
|
|
41
|
+
input.command.trim().length === 0 ||
|
|
42
|
+
(input.binary !== undefined && typeof input.binary !== 'boolean')))
|
|
42
43
|
throw new Error('TERMINAL_COMMAND_INVALID');
|
|
44
|
+
if (!commandMode && input.binary !== undefined)
|
|
45
|
+
throw new Error('TERMINAL_OPEN_INVALID');
|
|
43
46
|
const secretEnvironment = parseSecretEnvironment(input.secretEnvironment);
|
|
44
47
|
if ((commandMode || secretEnvironment.MAR_GIT_TOKEN !== undefined) &&
|
|
45
48
|
(!Number.isSafeInteger(input.__requestUserId) || Number(input.__requestUserId) <= 0))
|
|
@@ -58,11 +61,11 @@ export class TerminalService {
|
|
|
58
61
|
const options = {
|
|
59
62
|
...input,
|
|
60
63
|
workspaceId: typeof input.workspaceId === 'string' ? input.workspaceId : null,
|
|
61
|
-
environment: secretEnvironment,
|
|
64
|
+
environment: { ...secretEnvironment, MAR_MGR_CONTEXT_REQUIRED: '1' },
|
|
62
65
|
...(cwd === undefined ? {} : { cwd })
|
|
63
66
|
};
|
|
64
67
|
const terminal = commandMode
|
|
65
|
-
? this.terminalManager.openCommand(options, input.command)
|
|
68
|
+
? this.terminalManager.openCommand(options, input.command, input.binary === true)
|
|
66
69
|
: this.terminalManager.open(options);
|
|
67
70
|
if (commandMode || secretEnvironment.MAR_GIT_TOKEN !== undefined)
|
|
68
71
|
this.terminalOwners.set(terminal.id, {
|
package/dist/terminal.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { spawn as spawnProcess } from 'node:child_process';
|
|
2
3
|
import { existsSync } from 'node:fs';
|
|
3
4
|
import { homedir } from 'node:os';
|
|
4
5
|
import { join } from 'node:path';
|
|
@@ -26,6 +27,7 @@ export class TerminalManager {
|
|
|
26
27
|
idleTimeoutMs;
|
|
27
28
|
now;
|
|
28
29
|
ptyFactory;
|
|
30
|
+
pipeFactory;
|
|
29
31
|
terminate;
|
|
30
32
|
terminals = new Map();
|
|
31
33
|
attachments = new Map();
|
|
@@ -61,6 +63,7 @@ export class TerminalManager {
|
|
|
61
63
|
}
|
|
62
64
|
this.now = options.now ?? Date.now;
|
|
63
65
|
this.ptyFactory = options.ptyFactory ?? nodePtyFactory;
|
|
66
|
+
this.pipeFactory = options.pipeFactory ?? nodePipeFactory;
|
|
64
67
|
this.terminate =
|
|
65
68
|
options.terminate ?? ((child, platform) => terminateProcessTree(child, platform));
|
|
66
69
|
this.idleTimer = setInterval(() => void this.closeExpired(), Math.min(this.idleTimeoutMs, 60_000));
|
|
@@ -81,13 +84,13 @@ export class TerminalManager {
|
|
|
81
84
|
return this.openInternal(input);
|
|
82
85
|
}
|
|
83
86
|
/** A command starts only after a relay or direct Terminal attachment is active. */
|
|
84
|
-
openCommand(input, command) {
|
|
87
|
+
openCommand(input, command, binary = false) {
|
|
85
88
|
if (typeof command !== 'string' ||
|
|
86
89
|
command.trim().length === 0 ||
|
|
87
90
|
Buffer.byteLength(command, 'utf8') > TERMINAL_COMMAND_MAX_BYTES ||
|
|
88
91
|
command.includes('\0'))
|
|
89
92
|
throw new Error('TERMINAL_COMMAND_INVALID');
|
|
90
|
-
return this.openInternal(input, command);
|
|
93
|
+
return this.openInternal(input, command, binary);
|
|
91
94
|
}
|
|
92
95
|
startCommand(terminalId) {
|
|
93
96
|
const terminal = this.requireTerminal(terminalId);
|
|
@@ -96,17 +99,25 @@ export class TerminalManager {
|
|
|
96
99
|
return;
|
|
97
100
|
delete terminal.deferredCommand;
|
|
98
101
|
try {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
if (terminal.binary) {
|
|
103
|
+
const pipe = this.pipeFactory(deferred.shell, deferred.args, deferred.options);
|
|
104
|
+
terminal.pipe = pipe;
|
|
105
|
+
pipe.onData((data) => this.recordBinaryOutput(terminal, data));
|
|
106
|
+
pipe.onExit((exitCode) => this.exited(terminal, exitCode));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const pty = this.ptyFactory(deferred.shell, deferred.args, deferred.options);
|
|
110
|
+
terminal.pty = pty;
|
|
111
|
+
pty.onData((data) => this.recordOutput(terminal, data));
|
|
112
|
+
pty.onExit((event) => this.exited(terminal, event.exitCode));
|
|
113
|
+
}
|
|
103
114
|
}
|
|
104
115
|
catch {
|
|
105
116
|
this.emit({ type: 'error', terminalId, code: 'TERMINAL_COMMAND_START_FAILED' });
|
|
106
117
|
this.exited(terminal, 127);
|
|
107
118
|
}
|
|
108
119
|
}
|
|
109
|
-
openInternal(input = {}, command) {
|
|
120
|
+
openInternal(input = {}, command, binary = false) {
|
|
110
121
|
const profileId = input.profileId ?? this.profiles.find((profile) => profile.isDefault)?.id;
|
|
111
122
|
if (typeof profileId !== 'string')
|
|
112
123
|
throw new Error('TERMINAL_PROFILE_INVALID');
|
|
@@ -143,6 +154,8 @@ export class TerminalManager {
|
|
|
143
154
|
workspaceId: input.workspaceId ?? null,
|
|
144
155
|
profile,
|
|
145
156
|
pty,
|
|
157
|
+
pipe: undefined,
|
|
158
|
+
binary,
|
|
146
159
|
...(commandArgs === undefined
|
|
147
160
|
? {}
|
|
148
161
|
: { deferredCommand: { shell: profile.shell, args: commandArgs, options } }),
|
|
@@ -252,12 +265,23 @@ export class TerminalManager {
|
|
|
252
265
|
terminal.updatedAt = this.now();
|
|
253
266
|
terminal.lastUsedAt = terminal.updatedAt;
|
|
254
267
|
if (parsed.data.type === 'input') {
|
|
268
|
+
if (terminal.binary) {
|
|
269
|
+
if (terminal.pipe === undefined)
|
|
270
|
+
throw new Error('TERMINAL_COMMAND_NOT_STARTED');
|
|
271
|
+
const bytes = Buffer.from(parsed.data.data, 'base64');
|
|
272
|
+
if (bytes.length > 32 * 1024 || bytes.toString('base64') !== parsed.data.data)
|
|
273
|
+
throw new Error('TERMINAL_FRAME_INVALID');
|
|
274
|
+
terminal.pipe.write(bytes);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
255
277
|
if (terminal.pty === undefined)
|
|
256
278
|
throw new Error('TERMINAL_COMMAND_NOT_STARTED');
|
|
257
279
|
terminal.pty.write(parsed.data.data);
|
|
258
280
|
return;
|
|
259
281
|
}
|
|
260
282
|
if (parsed.data.type === 'resize') {
|
|
283
|
+
if (terminal.binary)
|
|
284
|
+
throw new Error('TERMINAL_FRAME_INVALID');
|
|
261
285
|
if (terminal.pty === undefined)
|
|
262
286
|
throw new Error('TERMINAL_COMMAND_NOT_STARTED');
|
|
263
287
|
terminal.pty.resize(parsed.data.cols, parsed.data.rows);
|
|
@@ -279,6 +303,8 @@ export class TerminalManager {
|
|
|
279
303
|
try {
|
|
280
304
|
if (terminal.pty !== undefined)
|
|
281
305
|
await this.terminate(terminal.pty, this.platform);
|
|
306
|
+
if (terminal.pipe !== undefined)
|
|
307
|
+
await this.terminate(terminal.pipe, this.platform);
|
|
282
308
|
}
|
|
283
309
|
finally {
|
|
284
310
|
this.emit({ type: 'exit', terminalId: terminal.id, exitCode: terminal.exitCode });
|
|
@@ -331,6 +357,31 @@ export class TerminalManager {
|
|
|
331
357
|
});
|
|
332
358
|
}
|
|
333
359
|
}
|
|
360
|
+
recordBinaryOutput(terminal, data) {
|
|
361
|
+
if (terminal.state !== 'RUNNING')
|
|
362
|
+
return;
|
|
363
|
+
for (let offset = 0; offset < data.length; offset += 32 * 1024) {
|
|
364
|
+
const part = data.subarray(offset, offset + 32 * 1024);
|
|
365
|
+
const frame = {
|
|
366
|
+
sequence: ++terminal.sequence,
|
|
367
|
+
data: part.toString('base64'),
|
|
368
|
+
bytes: part.length
|
|
369
|
+
};
|
|
370
|
+
terminal.replay.push(frame);
|
|
371
|
+
terminal.replayBytes += frame.bytes;
|
|
372
|
+
while (terminal.replayBytes > this.maxReplayBytes && terminal.replay.length > 0) {
|
|
373
|
+
const removed = terminal.replay.shift();
|
|
374
|
+
if (removed !== undefined)
|
|
375
|
+
terminal.replayBytes -= removed.bytes;
|
|
376
|
+
}
|
|
377
|
+
this.emit({
|
|
378
|
+
type: 'output',
|
|
379
|
+
terminalId: terminal.id,
|
|
380
|
+
sequence: frame.sequence,
|
|
381
|
+
data: frame.data
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
334
385
|
exited(terminal, exitCode) {
|
|
335
386
|
if (terminal.state !== 'RUNNING')
|
|
336
387
|
return;
|
|
@@ -433,6 +484,33 @@ function nodePtyFactory(shell, args, options) {
|
|
|
433
484
|
});
|
|
434
485
|
return pty;
|
|
435
486
|
}
|
|
487
|
+
function nodePipeFactory(shell, args, options) {
|
|
488
|
+
const child = spawnProcess(shell, [...args], {
|
|
489
|
+
cwd: options.cwd,
|
|
490
|
+
env: options.env,
|
|
491
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
492
|
+
detached: process.platform !== 'win32',
|
|
493
|
+
windowsHide: true
|
|
494
|
+
});
|
|
495
|
+
child.stdin.on('error', () => undefined);
|
|
496
|
+
child.stderr.resume();
|
|
497
|
+
return {
|
|
498
|
+
pid: child.pid,
|
|
499
|
+
kill: (signal) => child.kill(signal),
|
|
500
|
+
write: (bytes) => {
|
|
501
|
+
if (child.stdin.destroyed)
|
|
502
|
+
throw new Error('TERMINAL_PIPE_CLOSED');
|
|
503
|
+
child.stdin.write(bytes);
|
|
504
|
+
},
|
|
505
|
+
onData: (listener) => {
|
|
506
|
+
child.stdout.on('data', listener);
|
|
507
|
+
},
|
|
508
|
+
onExit: (listener) => {
|
|
509
|
+
child.on('error', () => listener(127));
|
|
510
|
+
child.on('close', (exitCode) => listener(exitCode ?? 1));
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
}
|
|
436
514
|
export function defaultTerminalProfiles(platform, findWindowsExecutable = resolveWindowsExecutable) {
|
|
437
515
|
if (platform === 'win32') {
|
|
438
516
|
const pwsh = findWindowsExecutable('pwsh.exe');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.132",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
"NOTICE"
|
|
13
13
|
],
|
|
14
14
|
"bin": {
|
|
15
|
-
"mar-node": "./dist/main.js"
|
|
15
|
+
"mar-node": "./dist/main.js",
|
|
16
|
+
"marmgr": "./dist/marmgr.js",
|
|
17
|
+
"marnodes": "./dist/marnodes.js",
|
|
18
|
+
"marssh": "./dist/marssh.js",
|
|
19
|
+
"marscp": "./dist/marscp.js"
|
|
16
20
|
},
|
|
17
21
|
"engines": {
|
|
18
22
|
"node": ">=22.13"
|
|
@@ -30,8 +34,9 @@
|
|
|
30
34
|
"npm": "11.12.1",
|
|
31
35
|
"ws": "^8.21.3",
|
|
32
36
|
"zod": "4.4.3",
|
|
33
|
-
"@myagentroam/
|
|
34
|
-
"@myagentroam/
|
|
37
|
+
"@myagentroam/marmgr": "0.9.115",
|
|
38
|
+
"@myagentroam/agent": "0.9.132",
|
|
39
|
+
"@myagentroam/protocol": "0.9.132",
|
|
35
40
|
"@myagentroam/code-navigation": "0.9.129"
|
|
36
41
|
},
|
|
37
42
|
"devDependencies": {
|