@myagentroam/node 0.12.0 → 0.12.2
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/hosting/hosted-conversation-node-service.js +1 -1
- 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-guidance.js +1 -1
- 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/native-session-history.js +1 -1
- package/dist/ripgrep-binary.js +3 -3
- package/dist/runner/codex-runner.js +2 -2
- package/dist/runner/mar-agent/agent-operation-presentation.js +22 -10
- package/dist/runner/mar-agent/codex-imagegen-skill.js +15 -23
- package/dist/runner/mar-agent/conversation-normalizer.js +4 -18
- package/dist/runner/mar-agent/image-generation-extensions.js +1 -1
- package/dist/runner/mar-agent/image-generation.js +73 -20
- package/dist/runner/mar-agent/session-runtime-registry.js +5 -3
- 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/dist/workspace/workspace-git-exclude-service.js +1 -1
- 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-guidance.js
CHANGED
|
@@ -28,7 +28,7 @@ export const marctlInstructions = [
|
|
|
28
28
|
'Prefer agents send <id> --steer -m <text> for timely communication or course correction. --queue is best reserved for deferred input explicitly requested by the user or recipient: it is consumed after current work and earlier queued inputs finish, and with an active Goal it is not consumed until that Goal exits. Acceptance is not a guarantee of immediate processing.',
|
|
29
29
|
'An accepted message normally needs no separate acknowledgment. Requests for receipt-only replies and immediate agents view checks solely to confirm receipt are usually unnecessary.',
|
|
30
30
|
'Send can update a Goal alone with --goal <objective> or --clear-goal; omitted Goal leaves it unchanged. Decide an authorized Agent approval with send <id> --approval <approval-id> --decision approve|reject.',
|
|
31
|
-
'List accepts only --scope tree|active, optional --query <title-fragment> and --limit <1..100> (default 10). With a current Session it defaults to the containing collaboration tree, including idle Sessions; without one it defaults to active Workspace Sessions (running or sleeping), and explicit tree is rejected. Active Sessions come first, then recent activity descending. Returns currentAgentId (null without a Session), flat sessions with id, parentSessionId, title and status, and truncated; no cursor or pagination. Reuse known IDs directly.',
|
|
31
|
+
'List accepts only --scope tree|active, optional --query <title-fragment> and --limit <1..100> (default 10). With a current Session it defaults to the containing collaboration tree, including idle Sessions; without one it defaults to active Workspace Sessions (running or sleeping), and explicit tree is rejected. Active Sessions come first, then recent activity descending. Returns scope, currentAgentId (null without a Session), flat sessions with id, parentSessionId, title and status, and truncated; no cursor or pagination. Reuse known IDs directly.',
|
|
32
32
|
'Only direct-child updates are collected automatically. Sending to a non-child never subscribes; an explicit wait observes it only for that call.',
|
|
33
33
|
'Use agents config, rename, prompt and schedule for management. marctl nodes, ssh and scp use authorized Nodes.',
|
|
34
34
|
marctlSafety
|
package/dist/marctl.js
CHANGED
package/dist/marnodes.js
CHANGED
package/dist/marscp.js
CHANGED
package/dist/marssh.js
CHANGED
|
@@ -365,7 +365,7 @@ function deleteTranscriptIndex(key) {
|
|
|
365
365
|
export async function locateNativeSessionPath(runner, workspacePath, externalSessionId) {
|
|
366
366
|
const wanted = canonical(workspacePath);
|
|
367
367
|
const key = indexKey(runner, wanted, externalSessionId);
|
|
368
|
-
|
|
368
|
+
const path = getTranscriptIndex(key);
|
|
369
369
|
if (path !== undefined)
|
|
370
370
|
return path;
|
|
371
371
|
const candidates = await nativeTranscriptAdapter(runner)?.locateCandidates?.(externalSessionId);
|
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}`];
|
|
@@ -394,7 +394,7 @@ export class CodexRunner extends AbstractRunner {
|
|
|
394
394
|
const threads = [];
|
|
395
395
|
const cursors = new Set();
|
|
396
396
|
let cursor;
|
|
397
|
-
|
|
397
|
+
for (;;) {
|
|
398
398
|
const result = await this.client.listThreads({
|
|
399
399
|
limit: 200,
|
|
400
400
|
...(cursor === undefined ? {} : { cursor })
|
|
@@ -415,7 +415,7 @@ export class CodexRunner extends AbstractRunner {
|
|
|
415
415
|
throw new Error('CODEX_THREAD_LIST_INVALID');
|
|
416
416
|
cursors.add(next);
|
|
417
417
|
cursor = next;
|
|
418
|
-
}
|
|
418
|
+
}
|
|
419
419
|
}
|
|
420
420
|
async discoverSessions(context, workspace) {
|
|
421
421
|
const [threads, nativeSessions] = context.cleanup
|
|
@@ -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,36 +1,28 @@
|
|
|
1
1
|
export function codexImagegenSkill() {
|
|
2
2
|
return `## Working with images
|
|
3
3
|
|
|
4
|
-
Use codex_image_gen only
|
|
4
|
+
Use codex_image_gen only for image generation or editing the user requests or explicitly authorizes. Loading this skill is not authorization to add visuals.
|
|
5
5
|
|
|
6
6
|
### Choose the operation
|
|
7
|
-
- Use
|
|
8
|
-
-
|
|
9
|
-
- Inspect
|
|
10
|
-
- Use num_last_images_to_include only when a necessary image has no usable path, and choose the smallest suffix containing all inputs. This is the current Execution's available in-memory images, not a permanent conversation gallery. After a new Execution or Compact, use valid saved paths or ask for missing inputs again.
|
|
11
|
-
- The selectors are mutually exclusive and include at most five images. Omit both only for generation without input images. Do not pretend an unavailable reference was used.
|
|
7
|
+
- Use generated raster artwork for photos, illustrations, textures, and visual variants. Prefer direct source edits for existing SVG, icons, and other code-native assets.
|
|
8
|
+
- Omit both selectors for generation without references. Otherwise use up to five absolute referenced_image_paths, or the smallest num_last_images_to_include containing all needed images, never both. Prefer paths when all inputs have them. Recent images belong to this Execution, not a permanent gallery; after recovery or Compact, use saved paths or ask for missing inputs.
|
|
9
|
+
- Identify each reference's role. Inspect unseen PNG/JPEG/WebP inputs with view_image when available; TEXT-only models must not claim visual inspection. Do not silently omit required references.
|
|
12
10
|
|
|
13
11
|
### Shape the prompt
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- For
|
|
17
|
-
-
|
|
18
|
-
-
|
|
12
|
+
- State the subject, composition, style, and essential constraints; preserve exact requested lettering. For edits, specify what changes and what stays unchanged. Add only details that support the user's goal; clarify only when a missing decision blocks the result.
|
|
13
|
+
- Set transparent_background: true for cutouts, background removal, or transparency; preserve existing transparency during edits unless the user asks to change it. Preserve real alpha, not a drawn checkerboard.
|
|
14
|
+
- For a simple looping animation, set gif: {} or specify frame_count (2–16) and frame_duration_ms (20–2000). Defaults are 9 frames and 200 ms. Describe the motion and loop seam; keep subjects and camera stable unless asked otherwise.
|
|
15
|
+
- To edit a GIF, first inspect its frames and use available tools to make a PNG spritesheet with equal-sized cells in a regular grid. Pass that spritesheet through referenced_image_paths and set gif. Do not pass the GIF itself as an edit input; if preparation is unavailable, explain the limitation.
|
|
16
|
+
- For complex animation or more than 16 frames, use suitable available tools or explain the limit rather than stretching this tool's bounds.
|
|
19
17
|
|
|
20
18
|
### Generate and check
|
|
21
|
-
-
|
|
22
|
-
- In Code Mode, call tools.codex_image_gen. Independent calls
|
|
23
|
-
-
|
|
24
|
-
- Generation may take minutes. Await the tool result; do not blindly repeat a timed-out or interrupted request because the upstream operation may already have run. Report failures rather than claiming an artifact exists.
|
|
25
|
-
- A successful result returns the saved path, not inspected pixels. When view_image is available, use it for visual acceptance: subject, exact text, composition, edit invariants, and unwanted elements. Otherwise explicitly state that visual acceptance was not performed. Make targeted corrections only within the requested scope.
|
|
26
|
-
- For transparent deliverables, verify actual transparency rather than treating a drawn checkerboard as alpha. Preserve the alpha channel when copying or processing the result.
|
|
19
|
+
- One PNG or GIF is saved per call. Model, quality, and size remain service-controlled; do not invent API parameters, output paths, SVG support, or fallback tools.
|
|
20
|
+
- In Code Mode, call tools.codex_image_gen. Independent calls may use Promise.all; dependent edits must await their inputs. Generation can take minutes: await the result and do not blindly replay an interrupted or timed-out request. Report failures rather than claiming an artifact exists.
|
|
21
|
+
- Verify the actual format and requested transparency, then check PNG content (subject, lettering, and edit invariants) with view_image when available. For GIFs, check frames, timing, and the loop with available animation-aware tools; a first-frame preview does not verify animation. If inspection is unavailable, say so. Correct only issues within the requested scope.
|
|
27
22
|
|
|
28
23
|
### Keep and deliver
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- Avoid overwriting existing assets unless replacement was requested. For preview-only work the managed file can remain in place.
|
|
32
|
-
- If the user asks to reuse an existing image, inspect or copy it rather than generating a replacement. If it is missing, state that fact; generate again only when authorized.
|
|
33
|
-
- Report the actual final path and any material unmet constraints. Do not dump a long generation prompt unless the user requests it.
|
|
24
|
+
- Trust the returned path and keep the managed original. Copy assets into the authorized project destination when needed; do not leave project dependencies in private Session storage. Do not overwrite existing assets unless replacement was requested.
|
|
25
|
+
- Reuse existing images when requested rather than regenerating them. Report the final path and material unmet constraints, not a long prompt dump.
|
|
34
26
|
|
|
35
|
-
This Host-provided skill has no bundled
|
|
27
|
+
This Host-provided skill has no bundled CLI fallback or separate API-key setup. Do not switch credentials, endpoints, or models. Follow the tool schema and Host file boundaries.`;
|
|
36
28
|
}
|