@myagentroam/node 0.12.0 → 0.12.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/code-navigation/index.js +2 -0
- package/dist/code-navigation/languages/c-family.js +9 -0
- package/dist/code-navigation/languages/c-preprocessor.js +30 -0
- package/dist/code-navigation/languages/c.js +8 -0
- package/dist/code-navigation/languages/cpp.js +10 -0
- package/dist/code-navigation/languages/csharp.js +18 -0
- package/dist/code-navigation/languages/css.js +7 -0
- package/dist/code-navigation/languages/ecmascript.js +44 -0
- package/dist/code-navigation/languages/file-target.js +9 -0
- package/dist/code-navigation/languages/go.js +32 -0
- package/dist/code-navigation/languages/html.js +7 -0
- package/dist/code-navigation/languages/jvm.js +17 -0
- package/dist/code-navigation/languages/less.js +7 -0
- package/dist/code-navigation/languages/markdown.js +113 -0
- package/dist/code-navigation/languages/markup-reference.js +27 -0
- package/dist/code-navigation/languages/objective-c.js +11 -0
- package/dist/code-navigation/languages/objective-cpp.js +10 -0
- package/dist/code-navigation/languages/python.js +17 -0
- package/dist/code-navigation/languages/rust.js +18 -0
- package/dist/code-navigation/languages/sass.js +7 -0
- package/dist/code-navigation/languages/scss.js +7 -0
- package/dist/code-navigation/languages/stylesheet-reference.js +37 -0
- package/dist/code-navigation/languages/vue.js +75 -0
- package/dist/code-navigation/registry.js +72 -0
- package/dist/code-navigation/source-ranges.js +17 -0
- package/dist/code-navigation/symbol-maps.js +257 -0
- package/dist/code-navigation/symbol-matcher.js +48 -0
- package/dist/code-navigation/symbol-navigation.js +1 -0
- package/dist/code-navigation/types.js +1 -0
- package/dist/ctags-binary.js +3 -3
- package/dist/marctl/bin/marctl.mjs +6 -0
- package/dist/marctl/bin/marnodes.mjs +6 -0
- package/dist/marctl/bin/marscp.mjs +6 -0
- package/dist/marctl/bin/marssh.mjs +6 -0
- package/dist/marctl/package.json +1 -0
- package/dist/marctl/src/cli.mjs +271 -0
- package/dist/marctl/src/client.mjs +291 -0
- package/dist/marctl/src/config.mjs +46 -0
- package/dist/marctl/src/direct-control.mjs +225 -0
- package/dist/marctl/src/direct-errors.mjs +48 -0
- package/dist/marctl/src/direct-process.mjs +374 -0
- package/dist/marctl/src/direct-transport.mjs +235 -0
- package/dist/marctl/src/direct.mjs +421 -0
- package/dist/marctl/src/errors.mjs +11 -0
- package/dist/marctl/src/i18n/en-US.mjs +285 -0
- package/dist/marctl/src/i18n/index.mjs +20 -0
- package/dist/marctl/src/i18n/zh-CN.mjs +269 -0
- package/dist/marctl/src/scp-channel.mjs +99 -0
- package/dist/marctl/src/scp-copy.mjs +46 -0
- package/dist/marctl/src/scp-endpoint.mjs +29 -0
- package/dist/marctl/src/scp-protocol.mjs +2 -0
- package/dist/marctl/src/scp-worker.cjs +266 -0
- package/dist/marctl/src/scp-workers.mjs +179 -0
- package/dist/marctl/src/scp.mjs +64 -0
- package/dist/marctl/src/session-args.mjs +233 -0
- package/dist/marctl/src/session-input.mjs +43 -0
- package/dist/marctl/src/session-prepare.mjs +87 -0
- package/dist/marctl/src/session-target.mjs +26 -0
- package/dist/marctl/src/session-wait.mjs +232 -0
- package/dist/marctl/src/sessions.mjs +93 -0
- package/dist/marctl/src/terminal-frame.mjs +48 -0
- package/dist/marctl/src/terminal-interaction.mjs +177 -0
- package/dist/marctl/src/terminal-race.mjs +117 -0
- package/dist/marctl/src/terminal-relay-sender.mjs +129 -0
- package/dist/marctl/src/terminal-relay.mjs +305 -0
- package/dist/marctl/src/terminal.mjs +152 -0
- package/dist/marctl.js +1 -1
- package/dist/marnodes.js +1 -1
- package/dist/marscp.js +1 -1
- package/dist/marssh.js +1 -1
- package/dist/ripgrep-binary.js +3 -3
- package/dist/runner/mar-agent/agent-operation-presentation.js +22 -10
- package/dist/service/code-navigation/file-reference-parser.js +1 -1
- package/dist/service/node-terminal-channel.js +1 -1
- package/dist/session/session-catalog-service.js +4 -1
- package/dist/workspace/workspace-code-navigation-service.js +2 -2
- package/package.json +11 -9
- package/vendor/ctags/NOTICE +0 -22
- package/vendor/ctags/darwin-arm64/ctags +0 -0
- package/vendor/ctags/darwin-x64/ctags +0 -0
- package/vendor/ctags/licenses/COPYING +0 -340
- package/vendor/ctags/licenses/COPYING.MinGW-w64-runtime.txt +0 -240
- package/vendor/ctags/licenses/LICENSE.janssen +0 -19
- package/vendor/ctags/licenses/LICENSE.libyaml +0 -19
- package/vendor/ctags/licenses/official-snapshot/darwin-arm64/COPYING +0 -340
- package/vendor/ctags/licenses/official-snapshot/darwin-arm64/RECEIPT.yml +0 -27
- package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libiconv.yml +0 -24
- package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libjansson.yml +0 -19
- package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libxml2.yml +0 -20
- package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libyaml.yml +0 -7
- package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libz.yml +0 -13
- package/vendor/ctags/licenses/official-snapshot/darwin-x64/COPYING +0 -340
- package/vendor/ctags/licenses/official-snapshot/darwin-x64/RECEIPT.yml +0 -27
- package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libiconv.yml +0 -24
- package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libjansson.yml +0 -19
- package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libxml2.yml +0 -20
- package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libyaml.yml +0 -7
- package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libz.yml +0 -13
- package/vendor/ctags/licenses/official-snapshot/linux-arm64/COPYING +0 -340
- package/vendor/ctags/licenses/official-snapshot/linux-arm64/RECEIPT.yml +0 -27
- package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libiconv.yml +0 -24
- package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libjansson.yml +0 -19
- package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libxml2.yml +0 -20
- package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libyaml.yml +0 -7
- package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libz.yml +0 -13
- package/vendor/ctags/licenses/official-snapshot/linux-x64/COPYING +0 -340
- package/vendor/ctags/licenses/official-snapshot/linux-x64/RECEIPT.yml +0 -27
- package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libiconv.yml +0 -24
- package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libjansson.yml +0 -19
- package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libxml2.yml +0 -20
- package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libyaml.yml +0 -7
- package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libz.yml +0 -13
- package/vendor/ctags/licenses/win32-x64/COPYING +0 -340
- package/vendor/ctags/licenses/win32-x64/COPYING.MinGW-w64-runtime.txt +0 -240
- package/vendor/ctags/licenses/win32-x64/Copyright.libxml2 +0 -23
- package/vendor/ctags/licenses/win32-x64/LICENCE.pcre2 +0 -94
- package/vendor/ctags/licenses/win32-x64/LICENSE.janssen +0 -19
- package/vendor/ctags/licenses/win32-x64/LICENSE.libyaml +0 -19
- package/vendor/ctags/linux-arm64/ctags +0 -0
- package/vendor/ctags/linux-x64/ctags +0 -0
- package/vendor/ctags/manifest.json +0 -42
- package/vendor/ctags/source/universal-ctags-ab95af198f8eaeb6d50dc96e3adf52e769d3e5f0.tar.gz +0 -0
- package/vendor/ctags/win32-x64/ctags.exe +0 -0
- package/vendor/ripgrep/LICENSE-MIT +0 -21
- package/vendor/ripgrep/UNLICENSE +0 -24
- package/vendor/ripgrep/darwin-arm64/rg +0 -0
- package/vendor/ripgrep/darwin-x64/rg +0 -0
- package/vendor/ripgrep/linux-arm64/rg +0 -0
- package/vendor/ripgrep/linux-x64/rg +0 -0
- package/vendor/ripgrep/manifest.json +0 -42
- package/vendor/ripgrep/win32-arm64/rg.exe +0 -0
- package/vendor/ripgrep/win32-x64/rg.exe +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { MarctlError } from './errors.mjs';
|
|
3
|
+
import { TerminalRelaySender } from './terminal-relay-sender.mjs';
|
|
4
|
+
import { parseFrame } from './terminal-frame.mjs';
|
|
5
|
+
import { DirectFallbackError } from './direct-errors.mjs';
|
|
6
|
+
|
|
7
|
+
export async function openRelayTransport({
|
|
8
|
+
client,
|
|
9
|
+
WebSocketClass,
|
|
10
|
+
nodeId,
|
|
11
|
+
terminalId,
|
|
12
|
+
translate,
|
|
13
|
+
connectionTimeoutMs,
|
|
14
|
+
signal
|
|
15
|
+
}) {
|
|
16
|
+
const ticket = await client.createAttachTicket({ nodeId, terminalId });
|
|
17
|
+
if (signal?.aborted) throw new DirectFallbackError('DIRECT_RACE_CANCELLED');
|
|
18
|
+
const socket = client.openTerminalWebSocket(WebSocketClass, { terminalId, ticket });
|
|
19
|
+
const transport = new BufferedRelayTransport({
|
|
20
|
+
socket,
|
|
21
|
+
terminalId,
|
|
22
|
+
translate,
|
|
23
|
+
connectionTimeoutMs
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
await waitForAttachment(transport, signal);
|
|
27
|
+
return transport;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
transport.close();
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function prepareRelayTransport({
|
|
35
|
+
client,
|
|
36
|
+
WebSocketClass,
|
|
37
|
+
nodeId,
|
|
38
|
+
terminalId,
|
|
39
|
+
translate,
|
|
40
|
+
connectionTimeoutMs,
|
|
41
|
+
signal,
|
|
42
|
+
onPrepared
|
|
43
|
+
}) {
|
|
44
|
+
const ticket = await client.createAttachTicket({ nodeId, terminalId });
|
|
45
|
+
if (onPrepared) await onPrepared();
|
|
46
|
+
if (signal?.aborted) throw new MarctlError(translate('errors.terminalAttachConnection'));
|
|
47
|
+
const socket = client.openTerminalWebSocket(WebSocketClass, {
|
|
48
|
+
terminalId,
|
|
49
|
+
ticket,
|
|
50
|
+
deferred: true
|
|
51
|
+
});
|
|
52
|
+
// Keep an error listener after readiness until the socket is discarded.
|
|
53
|
+
socket.on('error', () => {});
|
|
54
|
+
let activated = false;
|
|
55
|
+
const ready = new Promise((resolve, reject) => {
|
|
56
|
+
const timer = setTimeout(() => fail(), connectionTimeoutMs);
|
|
57
|
+
const cleanup = () => {
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
socket.removeListener?.('message', onMessage);
|
|
60
|
+
socket.removeListener?.('error', fail);
|
|
61
|
+
socket.removeListener?.('close', fail);
|
|
62
|
+
signal?.removeEventListener('abort', fail);
|
|
63
|
+
};
|
|
64
|
+
const fail = () => {
|
|
65
|
+
cleanup();
|
|
66
|
+
try {
|
|
67
|
+
socket.close();
|
|
68
|
+
} catch {
|
|
69
|
+
/* Connection not yet established. */
|
|
70
|
+
}
|
|
71
|
+
reject(new MarctlError(translate('errors.terminalAttachConnection')));
|
|
72
|
+
};
|
|
73
|
+
const onMessage = (raw) => {
|
|
74
|
+
let frame;
|
|
75
|
+
try {
|
|
76
|
+
frame = JSON.parse(String(raw));
|
|
77
|
+
} catch {
|
|
78
|
+
return fail();
|
|
79
|
+
}
|
|
80
|
+
if (frame?.type !== 'ready' || frame.terminalId !== terminalId) return fail();
|
|
81
|
+
cleanup();
|
|
82
|
+
resolve();
|
|
83
|
+
};
|
|
84
|
+
socket.on('message', onMessage);
|
|
85
|
+
socket.on('error', fail);
|
|
86
|
+
socket.on('close', fail);
|
|
87
|
+
signal?.addEventListener('abort', fail, { once: true });
|
|
88
|
+
if (signal?.aborted) fail();
|
|
89
|
+
});
|
|
90
|
+
await ready;
|
|
91
|
+
return {
|
|
92
|
+
async activate(signal) {
|
|
93
|
+
if (signal?.aborted) {
|
|
94
|
+
socket.close();
|
|
95
|
+
throw new DirectFallbackError('DIRECT_RACE_CANCELLED');
|
|
96
|
+
}
|
|
97
|
+
if (activated || socket.readyState !== 1)
|
|
98
|
+
throw new MarctlError(translate('errors.terminalAttachConnection'));
|
|
99
|
+
activated = true;
|
|
100
|
+
const transport = new BufferedRelayTransport({
|
|
101
|
+
socket,
|
|
102
|
+
terminalId,
|
|
103
|
+
translate,
|
|
104
|
+
connectionTimeoutMs
|
|
105
|
+
});
|
|
106
|
+
try {
|
|
107
|
+
socket.send(JSON.stringify({ type: 'activate', terminalId }));
|
|
108
|
+
await waitForAttachment(transport, signal);
|
|
109
|
+
return transport;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
transport.close();
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
close() {
|
|
116
|
+
socket.close();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function waitForAttachment(transport, signal) {
|
|
122
|
+
if (!signal) return transport.waitForAttachment();
|
|
123
|
+
if (signal.aborted) throw new DirectFallbackError('DIRECT_RACE_CANCELLED');
|
|
124
|
+
let cancel;
|
|
125
|
+
const cancelled = new Promise((_, reject) => {
|
|
126
|
+
cancel = () => {
|
|
127
|
+
transport.close();
|
|
128
|
+
reject(new DirectFallbackError('DIRECT_RACE_CANCELLED'));
|
|
129
|
+
};
|
|
130
|
+
signal.addEventListener('abort', cancel, { once: true });
|
|
131
|
+
});
|
|
132
|
+
try {
|
|
133
|
+
return await Promise.race([transport.waitForAttachment(), cancelled]);
|
|
134
|
+
} finally {
|
|
135
|
+
signal.removeEventListener('abort', cancel);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
class BufferedRelayTransport extends EventEmitter {
|
|
140
|
+
#socket;
|
|
141
|
+
#sender;
|
|
142
|
+
#terminalId;
|
|
143
|
+
#translate;
|
|
144
|
+
#attached = false;
|
|
145
|
+
#active = false;
|
|
146
|
+
#pendingEvents = [];
|
|
147
|
+
#attachmentResolve;
|
|
148
|
+
#attachmentReject;
|
|
149
|
+
#openTimer;
|
|
150
|
+
#attachTimer;
|
|
151
|
+
#closed = false;
|
|
152
|
+
#onOpen;
|
|
153
|
+
#onMessage;
|
|
154
|
+
#onError;
|
|
155
|
+
#onClose;
|
|
156
|
+
|
|
157
|
+
constructor({ socket, terminalId, translate, connectionTimeoutMs }) {
|
|
158
|
+
super();
|
|
159
|
+
this.#socket = socket;
|
|
160
|
+
this.#sender = new TerminalRelaySender(socket);
|
|
161
|
+
this.#terminalId = terminalId;
|
|
162
|
+
this.#translate = translate;
|
|
163
|
+
this.#onOpen = () => {
|
|
164
|
+
clearTimeout(this.#openTimer);
|
|
165
|
+
this.#armAttachTimer(connectionTimeoutMs);
|
|
166
|
+
};
|
|
167
|
+
this.#onMessage = (raw, isBinary) => {
|
|
168
|
+
try {
|
|
169
|
+
const frame = parseFrame(raw, isBinary, this.#terminalId, this.#translate);
|
|
170
|
+
if (!this.#attached) {
|
|
171
|
+
if (frame.type === 'attach') {
|
|
172
|
+
this.#attached = true;
|
|
173
|
+
clearTimeout(this.#attachTimer);
|
|
174
|
+
this.#attachmentResolve?.();
|
|
175
|
+
this.#attachmentResolve = undefined;
|
|
176
|
+
this.#attachmentReject = undefined;
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (frame.type === 'error')
|
|
180
|
+
throw new MarctlError(this.#translate('errors.terminalRemoteError'));
|
|
181
|
+
this.#queueOrEmit('message', raw, isBinary);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
this.#queueOrEmit('message', raw, isBinary);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
this.#fail(
|
|
187
|
+
error instanceof MarctlError
|
|
188
|
+
? error
|
|
189
|
+
: new MarctlError(this.#translate('errors.terminalFrameInvalid'))
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
this.#onError = () => {
|
|
194
|
+
const error = new MarctlError(
|
|
195
|
+
this.#translate(
|
|
196
|
+
this.#attached ? 'errors.terminalConnectionFailed' : 'errors.terminalAttachConnection'
|
|
197
|
+
)
|
|
198
|
+
);
|
|
199
|
+
if (this.#attached) this.#queueOrEmit('error', error);
|
|
200
|
+
else this.#fail(error);
|
|
201
|
+
};
|
|
202
|
+
this.#onClose = () => {
|
|
203
|
+
this.#sender.close();
|
|
204
|
+
const error = new MarctlError(
|
|
205
|
+
this.#translate(
|
|
206
|
+
this.#attached ? 'errors.terminalConnectionLost' : 'errors.terminalAttachLost'
|
|
207
|
+
)
|
|
208
|
+
);
|
|
209
|
+
if (this.#attached) this.#queueOrEmit('close');
|
|
210
|
+
else this.#fail(error);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
socket.on?.('open', this.#onOpen);
|
|
214
|
+
socket.on?.('message', this.#onMessage);
|
|
215
|
+
socket.on?.('error', this.#onError);
|
|
216
|
+
socket.on?.('close', this.#onClose);
|
|
217
|
+
if (socket.readyState === 1) this.#onOpen();
|
|
218
|
+
else
|
|
219
|
+
this.#openTimer = setTimeout(
|
|
220
|
+
() => this.#fail(new MarctlError(this.#translate('errors.terminalConnectionOpen'))),
|
|
221
|
+
connectionTimeoutMs
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
waitForAttachment() {
|
|
226
|
+
return new Promise((resolve, reject) => {
|
|
227
|
+
if (this.#closed) {
|
|
228
|
+
reject(new MarctlError(this.#translate('errors.terminalAttachLost')));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
this.#attachmentResolve = resolve;
|
|
232
|
+
this.#attachmentReject = reject;
|
|
233
|
+
if (this.#attached) {
|
|
234
|
+
this.#attachmentResolve = undefined;
|
|
235
|
+
this.#attachmentReject = undefined;
|
|
236
|
+
resolve();
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
activate() {
|
|
242
|
+
if (this.#active) return;
|
|
243
|
+
this.#active = true;
|
|
244
|
+
const pendingEvents = this.#pendingEvents;
|
|
245
|
+
this.#pendingEvents = [];
|
|
246
|
+
for (const { type, args } of pendingEvents) this.emit(type, ...args);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
get readyState() {
|
|
250
|
+
return this.#socket.readyState;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
send(value) {
|
|
254
|
+
if (this.#closed) throw new Error('TERMINAL_CONNECTION_LOST');
|
|
255
|
+
if (JSON.parse(value).type === 'input') return this.#sender.send(value);
|
|
256
|
+
this.#socket.send(value);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
close() {
|
|
260
|
+
if (this.#closed) return;
|
|
261
|
+
this.#closed = true;
|
|
262
|
+
this.#attachmentReject?.(new MarctlError(this.#translate('errors.terminalAttachLost')));
|
|
263
|
+
this.#attachmentReject = undefined;
|
|
264
|
+
this.#attachmentResolve = undefined;
|
|
265
|
+
this.#sender.close();
|
|
266
|
+
clearTimeout(this.#openTimer);
|
|
267
|
+
clearTimeout(this.#attachTimer);
|
|
268
|
+
this.#socket.removeListener?.('open', this.#onOpen);
|
|
269
|
+
this.#socket.removeListener?.('message', this.#onMessage);
|
|
270
|
+
this.#socket.removeListener?.('error', this.#onError);
|
|
271
|
+
this.#socket.removeListener?.('close', this.#onClose);
|
|
272
|
+
try {
|
|
273
|
+
this.#socket.close();
|
|
274
|
+
} catch {
|
|
275
|
+
// The connection is already unavailable.
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
#armAttachTimer(connectionTimeoutMs) {
|
|
280
|
+
if (this.#attached) return;
|
|
281
|
+
this.#attachTimer = setTimeout(
|
|
282
|
+
() => this.#fail(new MarctlError(this.#translate('errors.terminalAttachTimeout'))),
|
|
283
|
+
connectionTimeoutMs
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#fail(error) {
|
|
288
|
+
if (this.#closed) return;
|
|
289
|
+
clearTimeout(this.#openTimer);
|
|
290
|
+
clearTimeout(this.#attachTimer);
|
|
291
|
+
this.#attachmentResolve = undefined;
|
|
292
|
+
const reject = this.#attachmentReject;
|
|
293
|
+
this.#attachmentReject = undefined;
|
|
294
|
+
if (!this.#attached) reject?.(error);
|
|
295
|
+
else this.#queueOrEmit('error', error);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
#queueOrEmit(type, ...args) {
|
|
299
|
+
if (this.#active) {
|
|
300
|
+
if (type !== 'error' || this.listenerCount('error') > 0) this.emit(type, ...args);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
this.#pendingEvents.push({ type, args });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { MarctlError } from './errors.mjs';
|
|
2
|
+
import { DirectRejectedError } from './direct-errors.mjs';
|
|
3
|
+
import { createTranslator } from './i18n/index.mjs';
|
|
4
|
+
import { raceTerminalConnections } from './terminal-race.mjs';
|
|
5
|
+
import { openRelayTransport } from './terminal-relay.mjs';
|
|
6
|
+
import { getDimensions, runAttachedTerminal } from './terminal-interaction.mjs';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_CONNECTION_TIMEOUT_MS = 15000;
|
|
9
|
+
|
|
10
|
+
export async function runTerminalSession({
|
|
11
|
+
client,
|
|
12
|
+
WebSocketClass,
|
|
13
|
+
nodeId,
|
|
14
|
+
command,
|
|
15
|
+
binary = false,
|
|
16
|
+
attached,
|
|
17
|
+
stdin = process.stdin,
|
|
18
|
+
stdout = process.stdout,
|
|
19
|
+
signal,
|
|
20
|
+
translate = createTranslator(),
|
|
21
|
+
connectionTimeoutMs = DEFAULT_CONNECTION_TIMEOUT_MS,
|
|
22
|
+
openDirectTerminal: openDirectTerminalImpl,
|
|
23
|
+
raceConnections = false
|
|
24
|
+
}) {
|
|
25
|
+
const dimensions = getDimensions(stdout);
|
|
26
|
+
let terminalId;
|
|
27
|
+
let transport;
|
|
28
|
+
let result;
|
|
29
|
+
let primaryError;
|
|
30
|
+
let manifest;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
if (signal?.aborted) return signal.reason === 'SIGTERM' ? 143 : 130;
|
|
34
|
+
if (binary) {
|
|
35
|
+
if (command === undefined)
|
|
36
|
+
throw new MarctlError(translate('errors.terminalBinaryUnavailable'));
|
|
37
|
+
manifest = await client.getTerminalManifest(nodeId);
|
|
38
|
+
if (signal?.aborted) return signal.reason === 'SIGTERM' ? 143 : 130;
|
|
39
|
+
if (manifest?.binaryTerminal !== true)
|
|
40
|
+
throw new MarctlError(translate('errors.terminalBinaryUnavailable'));
|
|
41
|
+
}
|
|
42
|
+
const created = await client.createTerminal({
|
|
43
|
+
nodeId,
|
|
44
|
+
...dimensions,
|
|
45
|
+
...(command === undefined ? {} : { command }),
|
|
46
|
+
...(binary ? { binary: true } : {})
|
|
47
|
+
});
|
|
48
|
+
terminalId = binary ? created?.terminalId : created;
|
|
49
|
+
if (binary && created?.binary !== true)
|
|
50
|
+
throw new MarctlError(translate('errors.terminalBinaryUnavailable'));
|
|
51
|
+
if (signal?.aborted) return signal.reason === 'SIGTERM' ? 143 : 130;
|
|
52
|
+
try {
|
|
53
|
+
const openDirectTerminal =
|
|
54
|
+
openDirectTerminalImpl ?? (await import('./direct.mjs')).openDirectTerminal;
|
|
55
|
+
if (raceConnections && manifest === undefined)
|
|
56
|
+
manifest = await client.getTerminalManifest(nodeId).catch(() => undefined);
|
|
57
|
+
const directOptions = {
|
|
58
|
+
client,
|
|
59
|
+
WebSocketClass,
|
|
60
|
+
nodeId,
|
|
61
|
+
terminalId,
|
|
62
|
+
manifest,
|
|
63
|
+
afterSequence: 0,
|
|
64
|
+
timeoutMs: connectionTimeoutMs,
|
|
65
|
+
signal
|
|
66
|
+
};
|
|
67
|
+
const canRace = raceConnections && manifest?.deferredRelay === true;
|
|
68
|
+
transport = canRace
|
|
69
|
+
? await raceTerminalConnections({
|
|
70
|
+
openDirectTerminal,
|
|
71
|
+
directOptions,
|
|
72
|
+
client,
|
|
73
|
+
WebSocketClass,
|
|
74
|
+
nodeId,
|
|
75
|
+
terminalId,
|
|
76
|
+
translate,
|
|
77
|
+
connectionTimeoutMs,
|
|
78
|
+
signal
|
|
79
|
+
})
|
|
80
|
+
: await openDirectTerminal(directOptions);
|
|
81
|
+
if (signal?.aborted) return signal.reason === 'SIGTERM' ? 143 : 130;
|
|
82
|
+
result =
|
|
83
|
+
attached === undefined
|
|
84
|
+
? await runAttachedTerminal({
|
|
85
|
+
transport,
|
|
86
|
+
terminalId,
|
|
87
|
+
commandMode: command !== undefined,
|
|
88
|
+
stdin,
|
|
89
|
+
stdout,
|
|
90
|
+
signal,
|
|
91
|
+
translate
|
|
92
|
+
})
|
|
93
|
+
: await attached({ transport, terminalId, translate });
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (signal?.aborted) {
|
|
96
|
+
result = signal.reason === 'SIGTERM' ? 143 : 130;
|
|
97
|
+
} else {
|
|
98
|
+
if (error?.name === 'DirectUnsafeError')
|
|
99
|
+
throw new MarctlError(translate('errors.terminalDirectUnsafeFallback'));
|
|
100
|
+
if (error?.name !== 'DirectFallbackError') throw error;
|
|
101
|
+
transport = await openRelayTransport({
|
|
102
|
+
client,
|
|
103
|
+
WebSocketClass,
|
|
104
|
+
nodeId,
|
|
105
|
+
terminalId,
|
|
106
|
+
translate,
|
|
107
|
+
connectionTimeoutMs,
|
|
108
|
+
signal
|
|
109
|
+
});
|
|
110
|
+
if (signal?.aborted) return signal.reason === 'SIGTERM' ? 143 : 130;
|
|
111
|
+
result =
|
|
112
|
+
attached === undefined
|
|
113
|
+
? await runAttachedTerminal({
|
|
114
|
+
transport,
|
|
115
|
+
terminalId,
|
|
116
|
+
commandMode: command !== undefined,
|
|
117
|
+
stdin,
|
|
118
|
+
stdout,
|
|
119
|
+
signal,
|
|
120
|
+
translate
|
|
121
|
+
})
|
|
122
|
+
: await attached({ transport, terminalId, translate });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (signal?.aborted) result = signal.reason === 'SIGTERM' ? 143 : 130;
|
|
127
|
+
else primaryError = toMarctlError(error, translate);
|
|
128
|
+
} finally {
|
|
129
|
+
transport?.close?.();
|
|
130
|
+
if (terminalId !== undefined) {
|
|
131
|
+
try {
|
|
132
|
+
await client.deleteTerminal({ nodeId, terminalId });
|
|
133
|
+
} catch {
|
|
134
|
+
if (primaryError === undefined && result === undefined)
|
|
135
|
+
primaryError = new MarctlError(translate('errors.terminalCloseFailed'));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (primaryError !== undefined) throw primaryError;
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function toMarctlError(error, translate) {
|
|
145
|
+
if (error instanceof DirectRejectedError)
|
|
146
|
+
return new MarctlError(`${translate('errors.terminalSessionFailed')} [${error.code}]`, {
|
|
147
|
+
code: error.code
|
|
148
|
+
});
|
|
149
|
+
return error instanceof MarctlError
|
|
150
|
+
? error
|
|
151
|
+
: new MarctlError(translate('errors.terminalSessionFailed'));
|
|
152
|
+
}
|
package/dist/marctl.js
CHANGED
package/dist/marnodes.js
CHANGED
package/dist/marscp.js
CHANGED
package/dist/marssh.js
CHANGED
package/dist/ripgrep-binary.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dirname, resolve } from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
3
|
export const BUNDLED_RIPGREP_VERSION = '15.1.0';
|
|
4
4
|
const TARGETS = {
|
|
5
5
|
'linux-x64': ['linux-x64', 'rg'],
|
|
@@ -11,8 +11,8 @@ const TARGETS = {
|
|
|
11
11
|
};
|
|
12
12
|
export function bundledRipgrepDirectory(packageRoot) {
|
|
13
13
|
return packageRoot === undefined
|
|
14
|
-
? resolve(dirname(
|
|
15
|
-
: resolve(packageRoot, '
|
|
14
|
+
? resolve(dirname(createRequire(import.meta.url).resolve('@myagentroam/binaries/package.json')), 'vendor/ripgrep')
|
|
15
|
+
: resolve(packageRoot, 'packages/binaries/vendor/ripgrep');
|
|
16
16
|
}
|
|
17
17
|
export function bundledRipgrepPath(platform = process.platform, architecture = process.arch, packageRoot) {
|
|
18
18
|
const target = TARGETS[`${platform}-${architecture}`];
|
|
@@ -39,22 +39,34 @@ export function agentOperationPresentation(toolName, input, data) {
|
|
|
39
39
|
if (!action)
|
|
40
40
|
return undefined;
|
|
41
41
|
const parsed = agentOperationPresentationSchema.safeParse(isPlainRecord(data) ? data.agentOperation : undefined);
|
|
42
|
-
if (parsed.success && parsed.data.action === action)
|
|
43
|
-
return parsed.data;
|
|
44
42
|
const value = isPlainRecord(input) ? input : {};
|
|
45
43
|
const ids = typeof value.agentId === 'string'
|
|
46
44
|
? [value.agentId]
|
|
47
45
|
: Array.isArray(value.agentIds)
|
|
48
46
|
? value.agentIds
|
|
49
47
|
: [];
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
const operation = parsed.success && parsed.data.action === action
|
|
49
|
+
? parsed.data
|
|
50
|
+
: {
|
|
51
|
+
action,
|
|
52
|
+
targets: ids
|
|
53
|
+
.filter((id) => typeof id === 'string' && id.length > 0 && id.length <= 128)
|
|
54
|
+
.slice(0, 8)
|
|
55
|
+
.map((agentId) => ({ agentId })),
|
|
56
|
+
...(text(value.scope, 32) ? { scope: text(value.scope, 32) } : {})
|
|
57
|
+
};
|
|
58
|
+
const goal = isPlainRecord(value.goal) ? value.goal : undefined;
|
|
59
|
+
const objective = action === 'SEND' && !operation.detail?.message && !text(value.content) && goal?.clear !== true
|
|
60
|
+
? text(goal?.objective, 2000)
|
|
61
|
+
: undefined;
|
|
62
|
+
if (objective)
|
|
63
|
+
operation.detail = {
|
|
64
|
+
...operation.detail,
|
|
65
|
+
message: objective,
|
|
66
|
+
messageIsGoal: true,
|
|
67
|
+
...(objective !== goal?.objective ? { messageTruncated: true } : {})
|
|
68
|
+
};
|
|
69
|
+
return operation;
|
|
58
70
|
}
|
|
59
71
|
/** Whitelist public receipts; never serialize configuration, credentials or full history. */
|
|
60
72
|
export function agentOperationEvent(action, input, result) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fileSpecifierParser } from '
|
|
1
|
+
import { fileSpecifierParser } from '../../code-navigation/index.js';
|
|
2
2
|
const MAX_REFERENCE_REPARSE_POSITIONS = 8;
|
|
3
3
|
export function reparseFileReference(path, requested) {
|
|
4
4
|
const parser = fileSpecifierParser(path, requested.sourceContext.text);
|
|
@@ -3,7 +3,7 @@ import { terminalDataFrameSchema } from '@myagentroam/protocol';
|
|
|
3
3
|
import { nodeTerminalConnectEndpoint } from '../connection/endpoints.js';
|
|
4
4
|
import { isPlainRecord } from '../util/records.js';
|
|
5
5
|
import { TerminalRelayState } from './terminal-relay-state.js';
|
|
6
|
-
import { TerminalRelaySender } from '
|
|
6
|
+
import { TerminalRelaySender } from '../marctl/src/terminal-relay-sender.mjs';
|
|
7
7
|
export class NodeTerminalChannel {
|
|
8
8
|
options;
|
|
9
9
|
socket;
|
|
@@ -187,13 +187,16 @@ export class SessionCatalogService {
|
|
|
187
187
|
for (const record of candidates) {
|
|
188
188
|
if (selected.size >= query.limit)
|
|
189
189
|
break;
|
|
190
|
+
const remaining = query.limit - selected.size;
|
|
190
191
|
const path = [];
|
|
191
192
|
let current = record;
|
|
192
193
|
while (current !== undefined && !selected.has(current.id)) {
|
|
193
194
|
path.push(current);
|
|
195
|
+
if (path.length > remaining)
|
|
196
|
+
break;
|
|
194
197
|
current = byId.get(current.metadata.parentSessionId ?? '');
|
|
195
198
|
}
|
|
196
|
-
if (path.length >
|
|
199
|
+
if (path.length > remaining)
|
|
197
200
|
continue;
|
|
198
201
|
for (const ancestor of path.reverse())
|
|
199
202
|
selected.set(ancestor.id, ancestor);
|
|
@@ -3,8 +3,8 @@ import { constants } from 'node:fs';
|
|
|
3
3
|
import { access, open, realpath, rename, rm, stat, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { relative, resolve, sep } from 'node:path';
|
|
6
|
-
import { isNavigationSymbol } from '
|
|
7
|
-
import { supportsSymbolNavigationPath } from '
|
|
6
|
+
import { isNavigationSymbol } from '../code-navigation/index.js';
|
|
7
|
+
import { supportsSymbolNavigationPath } from '../code-navigation/symbol-navigation.js';
|
|
8
8
|
import { workspaceFileReferenceSchema } from '@myagentroam/protocol';
|
|
9
9
|
import { bundledCtagsPath, BUNDLED_CTAGS_VERSION, repairBundledCtagsExecutable } from '../ctags-binary.js';
|
|
10
10
|
import { nodeLog } from '../operational.js';
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist/**/*.js",
|
|
9
|
+
"dist/marctl/**/*.mjs",
|
|
10
|
+
"dist/marctl/**/*.cjs",
|
|
11
|
+
"dist/marctl/package.json",
|
|
9
12
|
"scripts/install-web-browser.mjs",
|
|
10
|
-
"vendor/ripgrep/**/*",
|
|
11
|
-
"vendor/ctags/**/*",
|
|
12
13
|
"dist/config.d.ts",
|
|
13
14
|
"LICENSE",
|
|
14
15
|
"NOTICE"
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
"dependencies": {
|
|
30
31
|
"@anthropic-ai/claude-agent-sdk": "0.3.233",
|
|
31
32
|
"@modelcontextprotocol/sdk": "1.32.0",
|
|
33
|
+
"@myagentroam/binaries": "0.10.1",
|
|
32
34
|
"@opencode-ai/sdk": "1.18.20",
|
|
33
35
|
"minimatch": "^10.2.6",
|
|
34
36
|
"node-datachannel": "0.33.4",
|
|
@@ -40,14 +42,14 @@
|
|
|
40
42
|
"turndown-plugin-gfm": "^1.0.2",
|
|
41
43
|
"ws": "^8.21.3",
|
|
42
44
|
"zod": "4.4.3",
|
|
43
|
-
"@myagentroam/
|
|
44
|
-
"@myagentroam/
|
|
45
|
-
"@myagentroam/code-navigation": "0.11.1",
|
|
46
|
-
"@myagentroam/protocol": "0.12.0"
|
|
45
|
+
"@myagentroam/protocol": "0.12.1",
|
|
46
|
+
"@myagentroam/agent": "0.12.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/turndown": "^5.0.6",
|
|
50
|
-
"@types/ws": "^8.18.1"
|
|
50
|
+
"@types/ws": "^8.18.1",
|
|
51
|
+
"@myagentroam/code-navigation": "0.11.1",
|
|
52
|
+
"@myagentroam/marctl": "0.12.1"
|
|
51
53
|
},
|
|
52
54
|
"exports": {
|
|
53
55
|
"./config": {
|
|
@@ -59,7 +61,7 @@
|
|
|
59
61
|
},
|
|
60
62
|
"scripts": {
|
|
61
63
|
"postinstall": "node scripts/install-web-browser.mjs",
|
|
62
|
-
"build": "node ../scripts/clean-build-output.mjs dist && tsc -p tsconfig.json",
|
|
64
|
+
"build": "node ../scripts/clean-build-output.mjs dist && tsc -p tsconfig.json && node ../scripts/stage-node-internals.mjs",
|
|
63
65
|
"stage:computer-use-runtime": "node ../scripts/stage-computer-use-runtime.mjs",
|
|
64
66
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
|
|
65
67
|
"dev": "tsx watch src/main.ts",
|
package/vendor/ctags/NOTICE
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
This directory distributes Universal Ctags binaries as a separate executable
|
|
2
|
-
work. All bundled binaries are official upstream artifacts built from commit
|
|
3
|
-
ab95af198f8eaeb6d50dc96e3adf52e769d3e5f0.
|
|
4
|
-
|
|
5
|
-
Universal Ctags is licensed under GPL-2.0-or-later. Its complete corresponding
|
|
6
|
-
source is included at:
|
|
7
|
-
|
|
8
|
-
source/universal-ctags-ab95af198f8eaeb6d50dc96e3adf52e769d3e5f0.tar.gz
|
|
9
|
-
|
|
10
|
-
The official source URL, per-platform release URLs, archive SHA-256 values and
|
|
11
|
-
executable SHA-256 values are recorded in manifest.json.
|
|
12
|
-
|
|
13
|
-
Linux x64/ARM64 and macOS x64/ARM64 come from the official
|
|
14
|
-
universal-ctags/ctags-nightly-build 2026.09.16 release. Their upstream package
|
|
15
|
-
metadata and dependency notices are preserved under
|
|
16
|
-
licenses/official-snapshot/<target>/.
|
|
17
|
-
|
|
18
|
-
Windows x64 comes from the official universal-ctags/ctags-win32
|
|
19
|
-
2026-09-16/p6.2.20260913.0-2-gab95af1 release. Its distributed license texts
|
|
20
|
-
are preserved under licenses/win32-x64/.
|
|
21
|
-
|
|
22
|
-
No bundled Ctags executable is built by this project.
|
|
Binary file
|
|
Binary file
|