@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.
Files changed (136) hide show
  1. package/dist/code-navigation/index.js +2 -0
  2. package/dist/code-navigation/languages/c-family.js +9 -0
  3. package/dist/code-navigation/languages/c-preprocessor.js +30 -0
  4. package/dist/code-navigation/languages/c.js +8 -0
  5. package/dist/code-navigation/languages/cpp.js +10 -0
  6. package/dist/code-navigation/languages/csharp.js +18 -0
  7. package/dist/code-navigation/languages/css.js +7 -0
  8. package/dist/code-navigation/languages/ecmascript.js +44 -0
  9. package/dist/code-navigation/languages/file-target.js +9 -0
  10. package/dist/code-navigation/languages/go.js +32 -0
  11. package/dist/code-navigation/languages/html.js +7 -0
  12. package/dist/code-navigation/languages/jvm.js +17 -0
  13. package/dist/code-navigation/languages/less.js +7 -0
  14. package/dist/code-navigation/languages/markdown.js +113 -0
  15. package/dist/code-navigation/languages/markup-reference.js +27 -0
  16. package/dist/code-navigation/languages/objective-c.js +11 -0
  17. package/dist/code-navigation/languages/objective-cpp.js +10 -0
  18. package/dist/code-navigation/languages/python.js +17 -0
  19. package/dist/code-navigation/languages/rust.js +18 -0
  20. package/dist/code-navigation/languages/sass.js +7 -0
  21. package/dist/code-navigation/languages/scss.js +7 -0
  22. package/dist/code-navigation/languages/stylesheet-reference.js +37 -0
  23. package/dist/code-navigation/languages/vue.js +75 -0
  24. package/dist/code-navigation/registry.js +72 -0
  25. package/dist/code-navigation/source-ranges.js +17 -0
  26. package/dist/code-navigation/symbol-maps.js +257 -0
  27. package/dist/code-navigation/symbol-matcher.js +48 -0
  28. package/dist/code-navigation/symbol-navigation.js +1 -0
  29. package/dist/code-navigation/types.js +1 -0
  30. package/dist/ctags-binary.js +3 -3
  31. package/dist/marctl/bin/marctl.mjs +6 -0
  32. package/dist/marctl/bin/marnodes.mjs +6 -0
  33. package/dist/marctl/bin/marscp.mjs +6 -0
  34. package/dist/marctl/bin/marssh.mjs +6 -0
  35. package/dist/marctl/package.json +1 -0
  36. package/dist/marctl/src/cli.mjs +271 -0
  37. package/dist/marctl/src/client.mjs +291 -0
  38. package/dist/marctl/src/config.mjs +46 -0
  39. package/dist/marctl/src/direct-control.mjs +225 -0
  40. package/dist/marctl/src/direct-errors.mjs +48 -0
  41. package/dist/marctl/src/direct-process.mjs +374 -0
  42. package/dist/marctl/src/direct-transport.mjs +235 -0
  43. package/dist/marctl/src/direct.mjs +421 -0
  44. package/dist/marctl/src/errors.mjs +11 -0
  45. package/dist/marctl/src/i18n/en-US.mjs +285 -0
  46. package/dist/marctl/src/i18n/index.mjs +20 -0
  47. package/dist/marctl/src/i18n/zh-CN.mjs +269 -0
  48. package/dist/marctl/src/scp-channel.mjs +99 -0
  49. package/dist/marctl/src/scp-copy.mjs +46 -0
  50. package/dist/marctl/src/scp-endpoint.mjs +29 -0
  51. package/dist/marctl/src/scp-protocol.mjs +2 -0
  52. package/dist/marctl/src/scp-worker.cjs +266 -0
  53. package/dist/marctl/src/scp-workers.mjs +179 -0
  54. package/dist/marctl/src/scp.mjs +64 -0
  55. package/dist/marctl/src/session-args.mjs +233 -0
  56. package/dist/marctl/src/session-input.mjs +43 -0
  57. package/dist/marctl/src/session-prepare.mjs +87 -0
  58. package/dist/marctl/src/session-target.mjs +26 -0
  59. package/dist/marctl/src/session-wait.mjs +232 -0
  60. package/dist/marctl/src/sessions.mjs +93 -0
  61. package/dist/marctl/src/terminal-frame.mjs +48 -0
  62. package/dist/marctl/src/terminal-interaction.mjs +177 -0
  63. package/dist/marctl/src/terminal-race.mjs +117 -0
  64. package/dist/marctl/src/terminal-relay-sender.mjs +129 -0
  65. package/dist/marctl/src/terminal-relay.mjs +305 -0
  66. package/dist/marctl/src/terminal.mjs +152 -0
  67. package/dist/marctl.js +1 -1
  68. package/dist/marnodes.js +1 -1
  69. package/dist/marscp.js +1 -1
  70. package/dist/marssh.js +1 -1
  71. package/dist/ripgrep-binary.js +3 -3
  72. package/dist/runner/mar-agent/agent-operation-presentation.js +22 -10
  73. package/dist/runner/mar-agent/hosted-conversation-runtime.js +3 -2
  74. package/dist/runner/mar-agent/runtime-extensions.js +33 -0
  75. package/dist/runner/mar-agent/session-runtime.js +5 -4
  76. package/dist/service/code-navigation/file-reference-parser.js +1 -1
  77. package/dist/service/node-terminal-channel.js +1 -1
  78. package/dist/session/native-session-projection-service.js +1 -2
  79. package/dist/session/session-catalog-service.js +74 -25
  80. package/dist/workspace/workspace-code-navigation-service.js +2 -2
  81. package/package.json +11 -9
  82. package/vendor/ctags/NOTICE +0 -22
  83. package/vendor/ctags/darwin-arm64/ctags +0 -0
  84. package/vendor/ctags/darwin-x64/ctags +0 -0
  85. package/vendor/ctags/licenses/COPYING +0 -340
  86. package/vendor/ctags/licenses/COPYING.MinGW-w64-runtime.txt +0 -240
  87. package/vendor/ctags/licenses/LICENSE.janssen +0 -19
  88. package/vendor/ctags/licenses/LICENSE.libyaml +0 -19
  89. package/vendor/ctags/licenses/official-snapshot/darwin-arm64/COPYING +0 -340
  90. package/vendor/ctags/licenses/official-snapshot/darwin-arm64/RECEIPT.yml +0 -27
  91. package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libiconv.yml +0 -24
  92. package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libjansson.yml +0 -19
  93. package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libxml2.yml +0 -20
  94. package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libyaml.yml +0 -7
  95. package/vendor/ctags/licenses/official-snapshot/darwin-arm64/dependencies/libz.yml +0 -13
  96. package/vendor/ctags/licenses/official-snapshot/darwin-x64/COPYING +0 -340
  97. package/vendor/ctags/licenses/official-snapshot/darwin-x64/RECEIPT.yml +0 -27
  98. package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libiconv.yml +0 -24
  99. package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libjansson.yml +0 -19
  100. package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libxml2.yml +0 -20
  101. package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libyaml.yml +0 -7
  102. package/vendor/ctags/licenses/official-snapshot/darwin-x64/dependencies/libz.yml +0 -13
  103. package/vendor/ctags/licenses/official-snapshot/linux-arm64/COPYING +0 -340
  104. package/vendor/ctags/licenses/official-snapshot/linux-arm64/RECEIPT.yml +0 -27
  105. package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libiconv.yml +0 -24
  106. package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libjansson.yml +0 -19
  107. package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libxml2.yml +0 -20
  108. package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libyaml.yml +0 -7
  109. package/vendor/ctags/licenses/official-snapshot/linux-arm64/dependencies/libz.yml +0 -13
  110. package/vendor/ctags/licenses/official-snapshot/linux-x64/COPYING +0 -340
  111. package/vendor/ctags/licenses/official-snapshot/linux-x64/RECEIPT.yml +0 -27
  112. package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libiconv.yml +0 -24
  113. package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libjansson.yml +0 -19
  114. package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libxml2.yml +0 -20
  115. package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libyaml.yml +0 -7
  116. package/vendor/ctags/licenses/official-snapshot/linux-x64/dependencies/libz.yml +0 -13
  117. package/vendor/ctags/licenses/win32-x64/COPYING +0 -340
  118. package/vendor/ctags/licenses/win32-x64/COPYING.MinGW-w64-runtime.txt +0 -240
  119. package/vendor/ctags/licenses/win32-x64/Copyright.libxml2 +0 -23
  120. package/vendor/ctags/licenses/win32-x64/LICENCE.pcre2 +0 -94
  121. package/vendor/ctags/licenses/win32-x64/LICENSE.janssen +0 -19
  122. package/vendor/ctags/licenses/win32-x64/LICENSE.libyaml +0 -19
  123. package/vendor/ctags/linux-arm64/ctags +0 -0
  124. package/vendor/ctags/linux-x64/ctags +0 -0
  125. package/vendor/ctags/manifest.json +0 -42
  126. package/vendor/ctags/source/universal-ctags-ab95af198f8eaeb6d50dc96e3adf52e769d3e5f0.tar.gz +0 -0
  127. package/vendor/ctags/win32-x64/ctags.exe +0 -0
  128. package/vendor/ripgrep/LICENSE-MIT +0 -21
  129. package/vendor/ripgrep/UNLICENSE +0 -24
  130. package/vendor/ripgrep/darwin-arm64/rg +0 -0
  131. package/vendor/ripgrep/darwin-x64/rg +0 -0
  132. package/vendor/ripgrep/linux-arm64/rg +0 -0
  133. package/vendor/ripgrep/linux-x64/rg +0 -0
  134. package/vendor/ripgrep/manifest.json +0 -42
  135. package/vendor/ripgrep/win32-arm64/rg.exe +0 -0
  136. 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
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  // Keep the CLI implementation in its own package; the Node install exposes the same entrypoint.
3
- const entrypoint = '@myagentroam/marctl/bin/marctl.mjs';
3
+ const entrypoint = './marctl/bin/marctl.mjs';
4
4
  await import(entrypoint);
5
5
  export {};
package/dist/marnodes.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- const entrypoint = '@myagentroam/marctl/bin/marnodes.mjs';
2
+ const entrypoint = './marctl/bin/marnodes.mjs';
3
3
  await import(entrypoint);
4
4
  export {};
package/dist/marscp.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- const entrypoint = '@myagentroam/marctl/bin/marscp.mjs';
2
+ const entrypoint = './marctl/bin/marscp.mjs';
3
3
  await import(entrypoint);
4
4
  export {};
package/dist/marssh.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- const entrypoint = '@myagentroam/marctl/bin/marssh.mjs';
2
+ const entrypoint = './marctl/bin/marssh.mjs';
3
3
  await import(entrypoint);
4
4
  export {};
@@ -1,5 +1,5 @@
1
1
  import { dirname, resolve } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
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(fileURLToPath(import.meta.url)), '..', 'vendor/ripgrep')
15
- : resolve(packageRoot, 'mar-node/vendor/ripgrep');
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
- return {
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
- };
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, marAgentCompactExtensionSource, updateMarAgentCompactState } from './compact-extensions.js';
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: marAgentCompactExtensionSource(compactState),
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, marAgentCompactExtensionSource, updateMarAgentCompactState } from './compact-extensions.js';
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 compactSource = marAgentCompactExtensionSource(compactState);
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
- ? compactSource
84
+ ? runtimeSource
84
85
  : {
85
86
  async resolve(request) {
86
- const snapshot = await compactSource.resolve(request);
87
+ const snapshot = await runtimeSource.resolve(request);
87
88
  return {
88
89
  ...snapshot,
89
90
  extensions: [
@@ -1,4 +1,4 @@
1
- import { fileSpecifierParser } from '@myagentroam/code-navigation';
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 '@myagentroam/marctl/src/terminal-relay-sender.mjs';
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) {