@myagentroam/node 0.11.74 → 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/runner/mar-agent/hosted-conversation-runtime.js +3 -2
- package/dist/runner/mar-agent/runtime-extensions.js +33 -0
- package/dist/runner/mar-agent/session-runtime.js +5 -4
- package/dist/service/code-navigation/file-reference-parser.js +1 -1
- package/dist/service/node-terminal-channel.js +1 -1
- package/dist/session/native-session-projection-service.js +1 -2
- package/dist/session/session-catalog-service.js +74 -25
- 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) {
|
|
@@ -9,7 +9,8 @@ import { MarAgentRuntimeModelFactory, sdkModelConfigurations, closeImageCredenti
|
|
|
9
9
|
import { createImageGenerationExtensions } from './image-generation-extensions.js';
|
|
10
10
|
import { createWebToolsExtensions } from './web-tools-extensions.js';
|
|
11
11
|
import { combineExecutionExtensions } from './execution-extensions.js';
|
|
12
|
-
import { compactRuntimeConfigurations,
|
|
12
|
+
import { compactRuntimeConfigurations, updateMarAgentCompactState } from './compact-extensions.js';
|
|
13
|
+
import { marAgentRuntimeExtensionSource } from './runtime-extensions.js';
|
|
13
14
|
import { webSessionScope } from '../../service/web-fetch-contracts.js';
|
|
14
15
|
/**
|
|
15
16
|
* Opens one short-lived MAR Agent Host per hosted Run so template mounts cannot leak across Run
|
|
@@ -391,7 +392,7 @@ export class MarAgentHostedConversationRuntime {
|
|
|
391
392
|
mode: 'node',
|
|
392
393
|
host,
|
|
393
394
|
models: sdkModelConfigurations(models.filter((model) => input.models.some((candidate) => candidate.id === model.id))),
|
|
394
|
-
extensions:
|
|
395
|
+
extensions: marAgentRuntimeExtensionSource(compactState),
|
|
395
396
|
defaultModelId: 'defaultModelId' in input ? input.defaultModelId : input.modelId,
|
|
396
397
|
workspaceMapping: {
|
|
397
398
|
logicalPath: '/workspace',
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { marAgentCompactExtensionSource } from './compact-extensions.js';
|
|
2
|
+
export function marAgentRuntimeExtensionSource(state) {
|
|
3
|
+
const compactSource = marAgentCompactExtensionSource(state);
|
|
4
|
+
return {
|
|
5
|
+
async resolve(request) {
|
|
6
|
+
const snapshot = await compactSource.resolve(request);
|
|
7
|
+
return {
|
|
8
|
+
...snapshot,
|
|
9
|
+
extensions: [
|
|
10
|
+
...snapshot.extensions,
|
|
11
|
+
{
|
|
12
|
+
id: 'mar.node.file-links',
|
|
13
|
+
apiVersion: '1.0',
|
|
14
|
+
attachSession(context) {
|
|
15
|
+
context.hooks.intercept('prompt.sections', (input, _call, next) => next({
|
|
16
|
+
...input,
|
|
17
|
+
sections: [
|
|
18
|
+
...input.sections,
|
|
19
|
+
{
|
|
20
|
+
id: 'mar.node.file-links',
|
|
21
|
+
text: input.facts?.mode === 'compact'
|
|
22
|
+
? null
|
|
23
|
+
: 'When mentioning key files changed in this task, prefer Markdown links to their absolute paths for easy preview.'
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -9,7 +9,8 @@ import { nodeExecutionEnvironment } from '../../node-execution-environment.js';
|
|
|
9
9
|
import { nodeLog } from '../../operational.js';
|
|
10
10
|
import { BUNDLED_RIPGREP_VERSION, bundledRipgrepPath, prependBundledRipgrepToPath } from '../../ripgrep-binary.js';
|
|
11
11
|
import { canonicalJson } from '../../util/canonical-json.js';
|
|
12
|
-
import { compactRuntimeConfigurations,
|
|
12
|
+
import { compactRuntimeConfigurations, updateMarAgentCompactState } from './compact-extensions.js';
|
|
13
|
+
import { marAgentRuntimeExtensionSource } from './runtime-extensions.js';
|
|
13
14
|
import { MarAgentConversationNormalizer } from './conversation-normalizer.js';
|
|
14
15
|
import { sdkModelConfigurations } from './runtime-model-factory.js';
|
|
15
16
|
export const HOST_CONFIGURATION_CATEGORIES = [
|
|
@@ -72,7 +73,7 @@ export async function createSessionRuntime(input, sessionKey, fingerprint, hostC
|
|
|
72
73
|
});
|
|
73
74
|
const compactState = { revision: 0 };
|
|
74
75
|
updateMarAgentCompactState(compactState, input.compact, models, input.models.map((model) => model.id));
|
|
75
|
-
const
|
|
76
|
+
const runtimeSource = marAgentRuntimeExtensionSource(compactState);
|
|
76
77
|
const networkProvider = networkContext;
|
|
77
78
|
agent = await dependencies.createAgent({
|
|
78
79
|
mode: 'node',
|
|
@@ -80,10 +81,10 @@ export async function createSessionRuntime(input, sessionKey, fingerprint, hostC
|
|
|
80
81
|
models: sdkModelConfigurations(models.filter((model) => input.models.some((candidate) => candidate.id === model.id))),
|
|
81
82
|
defaultModelId: input.model.id,
|
|
82
83
|
extensions: networkProvider === undefined
|
|
83
|
-
?
|
|
84
|
+
? runtimeSource
|
|
84
85
|
: {
|
|
85
86
|
async resolve(request) {
|
|
86
|
-
const snapshot = await
|
|
87
|
+
const snapshot = await runtimeSource.resolve(request);
|
|
87
88
|
return {
|
|
88
89
|
...snapshot,
|
|
89
90
|
extensions: [
|
|
@@ -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;
|
|
@@ -361,8 +361,7 @@ export class NativeSessionProjectionService {
|
|
|
361
361
|
projectionForNative(native) {
|
|
362
362
|
return this.resolveNativeProjection(native, this.options.runtime, false);
|
|
363
363
|
}
|
|
364
|
-
projectionsForNative(native) {
|
|
365
|
-
const lookup = this.options.runtime.createSessionLookup();
|
|
364
|
+
projectionsForNative(native, lookup = this.options.runtime.createSessionLookup()) {
|
|
366
365
|
return new Map(native.map((session) => [session, this.resolveNativeProjection(session, lookup, false)]));
|
|
367
366
|
}
|
|
368
367
|
managedForNative(native) {
|