@myagentroam/node 0.11.41 → 0.11.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connector.js +9 -2
- package/dist/hosting/hosted-conversation-node-service.js +1 -2
- package/dist/marctl-guidance.js +3 -1
- package/dist/runner/abstract-runner.js +2 -2
- package/dist/runner/claude/managed-run-controller.js +1 -1
- package/dist/runner/claude/native-transcript.js +1 -1
- package/dist/runner/claude/tool-normalizer.js +21 -12
- package/dist/runner/codex/conversation-parser.js +17 -9
- package/dist/runner/codex/managed-run-controller.js +1 -1
- package/dist/runner/codex/tool-normalizer.js +17 -9
- package/dist/runner/execution-presentation.js +0 -3
- package/dist/runner/mar-agent/agent-network-extension.js +2 -2
- package/dist/runner/mar-agent/conversation-normalizer.js +259 -43
- package/dist/runner/mar-agent/managed-run-controller.js +2 -1
- package/dist/runner/mar-agent/runtime-model-factory.js +2 -4
- package/dist/runner/mar-agent-runner.js +32 -8
- package/dist/runner/normalization.js +8 -0
- package/dist/runner/opencode/tool-normalizer.js +8 -4
- package/dist/runner/personal-instructions.js +7 -0
- package/dist/runtime-state.js +0 -1
- package/dist/service/agent-network-bindings.js +6 -3
- package/dist/service/agent-network-invoke.js +5 -2
- package/dist/service/agent-network-observations.js +15 -13
- package/dist/service/agent-network-service.js +39 -15
- package/dist/service/goal-continuation-coordinator.js +5 -0
- package/dist/service/runner-service.js +7 -3
- package/dist/session/runtime/conversation-projection.js +3 -1
- package/dist/session/session-lifecycle-service.js +7 -4
- package/dist/session/session-message-service.js +4 -2
- package/package.json +5 -5
|
@@ -7,7 +7,41 @@ export function normalizeMarAgentUsage(usage) {
|
|
|
7
7
|
import { boundedConversationItemId, compactRunnerText, compactRunnerValue } from '../normalization.js';
|
|
8
8
|
import { runnerErrorProjection } from '../runner-error.js';
|
|
9
9
|
import { toolPresentationSchema } from '@myagentroam/protocol';
|
|
10
|
-
import { boundExecutionPresentation
|
|
10
|
+
import { boundExecutionPresentation } from '../execution-presentation.js';
|
|
11
|
+
import { publicOutputSnapshot } from '../normalization.js';
|
|
12
|
+
function boundCodeOutputSnapshots(sources) {
|
|
13
|
+
for (const channel of ['outputPreview', 'stdout', 'stderr']) {
|
|
14
|
+
const text = (entry) => channel === 'outputPreview' ? entry.outputPreview : entry.displayOutput[channel];
|
|
15
|
+
let excess = [...sources.values()].reduce((length, entry) => length + text(entry).length, 0) - 10_000;
|
|
16
|
+
for (const [id, entry] of sources) {
|
|
17
|
+
if (excess <= 0)
|
|
18
|
+
break;
|
|
19
|
+
const before = text(entry);
|
|
20
|
+
if (!before)
|
|
21
|
+
continue;
|
|
22
|
+
let removed = Math.min(excess, before.length);
|
|
23
|
+
if (/^[\uDC00-\uDFFF]/u.test(before.slice(removed)))
|
|
24
|
+
removed++;
|
|
25
|
+
const tail = before.slice(removed);
|
|
26
|
+
if (channel === 'outputPreview') {
|
|
27
|
+
sources.set(id, { ...entry, outputPreview: tail, truncated: true });
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const dropped = channel === 'stdout' ? 'stdoutDroppedBytes' : 'stderrDroppedBytes';
|
|
31
|
+
sources.set(id, {
|
|
32
|
+
...entry,
|
|
33
|
+
truncated: true,
|
|
34
|
+
displayOutput: {
|
|
35
|
+
...entry.displayOutput,
|
|
36
|
+
[channel]: tail,
|
|
37
|
+
[dropped]: entry.displayOutput[dropped] + Buffer.byteLength(before.slice(0, removed))
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
excess -= removed;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
11
45
|
export class MarAgentConversationNormalizer {
|
|
12
46
|
input(entry) {
|
|
13
47
|
return {
|
|
@@ -32,6 +66,7 @@ export class MarAgentConversationNormalizer {
|
|
|
32
66
|
#codeModeSourceCallIds = new Set();
|
|
33
67
|
#codeModeOutputCalls = new Map();
|
|
34
68
|
#codeModeOutputSnapshots = new Map();
|
|
69
|
+
#codeModeOutputArchive = new Map();
|
|
35
70
|
#runningCodeModeCells = new Map();
|
|
36
71
|
#codeModeCellWaiters = new Map();
|
|
37
72
|
messageItemId(nativeItemId) {
|
|
@@ -234,6 +269,8 @@ export class MarAgentConversationNormalizer {
|
|
|
234
269
|
}
|
|
235
270
|
#toolOutput(event) {
|
|
236
271
|
const { callId, toolName, executionId, turnId, parentCallId, output } = event;
|
|
272
|
+
if (output.mode === 'delta')
|
|
273
|
+
return this.#toolOutputDelta(event);
|
|
237
274
|
const inputOutput = [output.stdout, output.stderr].filter(Boolean).join('\n');
|
|
238
275
|
const displayOutput = execDisplayOutput(output.displayOutput) ?? {
|
|
239
276
|
stdout: output.stdout,
|
|
@@ -248,9 +285,10 @@ export class MarAgentConversationNormalizer {
|
|
|
248
285
|
const snapshot = {
|
|
249
286
|
outputPreview: bounded.text,
|
|
250
287
|
truncated: bounded.truncated || inputOutput.length > 10_000,
|
|
251
|
-
displayOutput
|
|
288
|
+
displayOutput,
|
|
289
|
+
processId: output.processId
|
|
252
290
|
};
|
|
253
|
-
if (parentCallId !== undefined)
|
|
291
|
+
if (parentCallId !== undefined && (toolName === 'exec' || toolName === 'exec_wait'))
|
|
254
292
|
return this.#codeModeToolOutput(callId, parentCallId, toolName, executionId, turnId, output.processId, snapshot);
|
|
255
293
|
const state = this.#tools.get(callId);
|
|
256
294
|
if (state === undefined ||
|
|
@@ -263,10 +301,15 @@ export class MarAgentConversationNormalizer {
|
|
|
263
301
|
if (typeof input?.processId === 'string' && input.processId !== output.processId)
|
|
264
302
|
return [];
|
|
265
303
|
if (state.commandOrigin === undefined) {
|
|
266
|
-
if (toolName !== 'exec_wait')
|
|
304
|
+
if (toolName !== 'exec_wait' && toolName !== 'code_exec_wait')
|
|
267
305
|
return [];
|
|
268
306
|
return [
|
|
269
|
-
genericToolItem(state.itemId, toolName, 'IN_PROGRESS', state.input, snapshot.outputPreview, null, snapshot.truncated, {
|
|
307
|
+
genericToolItem(state.itemId, toolName, 'IN_PROGRESS', state.input, snapshot.outputPreview, null, snapshot.truncated, {
|
|
308
|
+
processId: output.processId,
|
|
309
|
+
displayOutput: snapshot.displayOutput,
|
|
310
|
+
outputHeadTruncated: snapshot.displayOutput.stdoutDroppedBytes > 0 ||
|
|
311
|
+
snapshot.displayOutput.stderrDroppedBytes > 0
|
|
312
|
+
})
|
|
270
313
|
];
|
|
271
314
|
}
|
|
272
315
|
const command = this.#commands.get(state.commandOrigin);
|
|
@@ -279,6 +322,93 @@ export class MarAgentConversationNormalizer {
|
|
|
279
322
|
command.truncated = snapshot.truncated;
|
|
280
323
|
return [commandItem(command, 'IN_PROGRESS')];
|
|
281
324
|
}
|
|
325
|
+
#toolOutputDelta(event) {
|
|
326
|
+
const { callId, toolName, executionId, turnId, parentCallId, output } = event;
|
|
327
|
+
let target = this.#tools.get(callId);
|
|
328
|
+
if (parentCallId !== undefined) {
|
|
329
|
+
const child = this.#codeModeOutputCalls.get(callId);
|
|
330
|
+
const parent = this.#tools.get(parentCallId);
|
|
331
|
+
if (!child ||
|
|
332
|
+
child.parentCallId !== parentCallId ||
|
|
333
|
+
child.toolName !== toolName ||
|
|
334
|
+
child.executionId !== executionId ||
|
|
335
|
+
(child.turnId && turnId && child.turnId !== turnId) ||
|
|
336
|
+
!parent ||
|
|
337
|
+
parent.executionId !== executionId ||
|
|
338
|
+
(parent.turnId && turnId && parent.turnId !== turnId))
|
|
339
|
+
return [];
|
|
340
|
+
const input = record(child.input);
|
|
341
|
+
if (typeof input?.processId === 'string' && input.processId !== output.processId)
|
|
342
|
+
return [];
|
|
343
|
+
const display = execDisplayOutput(output.displayOutput);
|
|
344
|
+
if (display) {
|
|
345
|
+
const snapshots = this.#codeModeOutputSnapshots.get(parentCallId) ?? new Map();
|
|
346
|
+
const text = [display.stdout, display.stderr].filter(Boolean).join('\n');
|
|
347
|
+
const bounded = publicOutputSnapshot(text, display.stdoutDroppedBytes > 0 || display.stderrDroppedBytes > 0);
|
|
348
|
+
snapshots.set(callId, {
|
|
349
|
+
outputPreview: bounded.text,
|
|
350
|
+
truncated: bounded.truncated,
|
|
351
|
+
displayOutput: display,
|
|
352
|
+
processId: output.processId
|
|
353
|
+
});
|
|
354
|
+
this.#codeModeOutputSnapshots.set(parentCallId, snapshots);
|
|
355
|
+
}
|
|
356
|
+
target = parent.active
|
|
357
|
+
? parent
|
|
358
|
+
: this.#runningCodeModeCells.get(parentCallId)?.executionId === executionId
|
|
359
|
+
? this.#activeCodeModeWaiter(this.#runningCodeModeCells.get(parentCallId))
|
|
360
|
+
: undefined;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
if (!target ||
|
|
364
|
+
!target.active ||
|
|
365
|
+
target.toolName !== toolName ||
|
|
366
|
+
target.executionId !== executionId ||
|
|
367
|
+
(target.turnId && turnId && target.turnId !== turnId))
|
|
368
|
+
return [];
|
|
369
|
+
const input = record(target.input);
|
|
370
|
+
if (typeof input?.processId === 'string' && input.processId !== output.processId)
|
|
371
|
+
return [];
|
|
372
|
+
}
|
|
373
|
+
if (!target)
|
|
374
|
+
return [];
|
|
375
|
+
const command = target.commandOrigin === undefined ? undefined : this.#commands.get(target.commandOrigin);
|
|
376
|
+
const item = command
|
|
377
|
+
? commandItem(command, 'IN_PROGRESS')
|
|
378
|
+
: genericToolItem(target.itemId, target.toolName, 'IN_PROGRESS', target.input, null, null);
|
|
379
|
+
const original = record(record(item.payload.toolPresentation)?.execution);
|
|
380
|
+
const blocks = [
|
|
381
|
+
...(output.stdout ? [{ channel: 'STDOUT', text: output.stdout }] : []),
|
|
382
|
+
...(output.stderr ? [{ channel: 'STDERR', text: output.stderr }] : [])
|
|
383
|
+
];
|
|
384
|
+
const text = [output.stdout, output.stderr].filter(Boolean).join('\n');
|
|
385
|
+
const boundedText = publicOutputSnapshot(text, output.truncated);
|
|
386
|
+
const bounded = boundExecutionPresentation({
|
|
387
|
+
kind: parentCallId !== undefined
|
|
388
|
+
? target.toolName === 'code_exec'
|
|
389
|
+
? 'CODE'
|
|
390
|
+
: 'CONTROL'
|
|
391
|
+
: toolName === 'exec'
|
|
392
|
+
? 'SHELL'
|
|
393
|
+
: 'CONTROL',
|
|
394
|
+
...(typeof original?.toolName === 'string' ? { toolName: original.toolName } : {}),
|
|
395
|
+
output: blocks,
|
|
396
|
+
...(output.truncated ? { truncation: { output: 'HEAD' } } : {})
|
|
397
|
+
});
|
|
398
|
+
return [
|
|
399
|
+
{
|
|
400
|
+
...item,
|
|
401
|
+
append: 'output',
|
|
402
|
+
merge: true,
|
|
403
|
+
payload: {
|
|
404
|
+
...item.payload,
|
|
405
|
+
outputPreview: boundedText.text,
|
|
406
|
+
output: boundedText,
|
|
407
|
+
toolPresentation: bounded.presentation
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
];
|
|
411
|
+
}
|
|
282
412
|
#codeModeToolOutput(callId, parentCallId, toolName, executionId, turnId, processId, snapshot) {
|
|
283
413
|
const parent = this.#tools.get(parentCallId);
|
|
284
414
|
const child = this.#codeModeOutputCalls.get(callId);
|
|
@@ -305,13 +435,30 @@ export class MarAgentConversationNormalizer {
|
|
|
305
435
|
const snapshots = this.#codeModeOutputSnapshots.get(parentCallId) ?? new Map();
|
|
306
436
|
snapshots.set(callId, snapshot);
|
|
307
437
|
this.#codeModeOutputSnapshots.set(parentCallId, snapshots);
|
|
308
|
-
const
|
|
438
|
+
const sources = new Map(this.#codeModeOutputArchive.get(parentCallId));
|
|
439
|
+
for (const active of snapshots.values())
|
|
440
|
+
sources.set(active.processId, active);
|
|
441
|
+
const entries = [...sources.values()];
|
|
442
|
+
const combined = entries
|
|
309
443
|
.map((entry) => entry.outputPreview)
|
|
310
444
|
.filter(Boolean)
|
|
311
|
-
.join('
|
|
312
|
-
const bounded = publicOutputSnapshot(combined,
|
|
445
|
+
.join('');
|
|
446
|
+
const bounded = publicOutputSnapshot(combined, entries.some((entry) => entry.truncated));
|
|
313
447
|
return [
|
|
314
|
-
genericToolItem(target.itemId, target.toolName, 'IN_PROGRESS', target.input, bounded.text, null, bounded.truncated
|
|
448
|
+
genericToolItem(target.itemId, target.toolName, 'IN_PROGRESS', target.input, bounded.text, null, bounded.truncated, {
|
|
449
|
+
outputHeadTruncated: entries.some((entry) => entry.displayOutput.stdoutDroppedBytes > 0 ||
|
|
450
|
+
entry.displayOutput.stderrDroppedBytes > 0),
|
|
451
|
+
displayOutput: {
|
|
452
|
+
stdout: entries
|
|
453
|
+
.map((entry) => entry.displayOutput.stdout)
|
|
454
|
+
.filter(Boolean)
|
|
455
|
+
.join(''),
|
|
456
|
+
stderr: entries
|
|
457
|
+
.map((entry) => entry.displayOutput.stderr)
|
|
458
|
+
.filter(Boolean)
|
|
459
|
+
.join('')
|
|
460
|
+
}
|
|
461
|
+
})
|
|
315
462
|
];
|
|
316
463
|
}
|
|
317
464
|
#trackCodeModeOutputCall(event) {
|
|
@@ -343,7 +490,16 @@ export class MarAgentConversationNormalizer {
|
|
|
343
490
|
const call = this.#codeModeOutputCalls.get(callId);
|
|
344
491
|
if (call?.parentCallId === parentCallId) {
|
|
345
492
|
this.#codeModeOutputCalls.delete(callId);
|
|
346
|
-
this.#codeModeOutputSnapshots.get(parentCallId)
|
|
493
|
+
const snapshots = this.#codeModeOutputSnapshots.get(parentCallId);
|
|
494
|
+
const completed = snapshots?.get(callId);
|
|
495
|
+
snapshots?.delete(callId);
|
|
496
|
+
if (completed) {
|
|
497
|
+
const archive = this.#codeModeOutputArchive.get(parentCallId) ??
|
|
498
|
+
new Map();
|
|
499
|
+
archive.set(completed.processId, completed);
|
|
500
|
+
boundCodeOutputSnapshots(archive);
|
|
501
|
+
this.#codeModeOutputArchive.set(parentCallId, archive);
|
|
502
|
+
}
|
|
347
503
|
}
|
|
348
504
|
}
|
|
349
505
|
#trackCodeModeWait(event) {
|
|
@@ -415,6 +571,7 @@ export class MarAgentConversationNormalizer {
|
|
|
415
571
|
}
|
|
416
572
|
#clearCodeModeOutputSnapshots(parentCallId) {
|
|
417
573
|
this.#codeModeOutputSnapshots.delete(parentCallId);
|
|
574
|
+
this.#codeModeOutputArchive.delete(parentCallId);
|
|
418
575
|
for (const [callId, state] of this.#codeModeOutputCalls)
|
|
419
576
|
if (state.parentCallId === parentCallId)
|
|
420
577
|
this.#codeModeOutputCalls.delete(callId);
|
|
@@ -822,28 +979,43 @@ function validCompactAnchor(value) {
|
|
|
822
979
|
return value !== undefined && value.length > 0 && value.length <= 128 ? value : undefined;
|
|
823
980
|
}
|
|
824
981
|
function codeObservationOutput(data, summary) {
|
|
982
|
+
const blocks = [];
|
|
983
|
+
const add = (channel, text) => {
|
|
984
|
+
if (typeof text !== 'string' || text.length === 0)
|
|
985
|
+
return;
|
|
986
|
+
const existing = blocks.find((block) => block.channel === channel);
|
|
987
|
+
if (existing)
|
|
988
|
+
existing.text += `\n${text}`;
|
|
989
|
+
else
|
|
990
|
+
blocks.push({ channel, text });
|
|
991
|
+
};
|
|
992
|
+
const streams = (value) => {
|
|
993
|
+
const display = record(value?.displayOutput) ?? value;
|
|
994
|
+
if (typeof display?.stdout !== 'string' && typeof display?.stderr !== 'string')
|
|
995
|
+
return false;
|
|
996
|
+
add('STDOUT', display?.stdout);
|
|
997
|
+
add('STDERR', display?.stderr);
|
|
998
|
+
return true;
|
|
999
|
+
};
|
|
1000
|
+
if (streams(data))
|
|
1001
|
+
return blocks;
|
|
825
1002
|
if (Array.isArray(data?.observations)) {
|
|
826
|
-
|
|
827
|
-
.flatMap((entry) => {
|
|
1003
|
+
for (const entry of data.observations) {
|
|
828
1004
|
const observation = record(entry);
|
|
829
|
-
if (observation?.type === 'value'
|
|
830
|
-
|
|
1005
|
+
if (observation?.type === 'value')
|
|
1006
|
+
add('TEXT', observation.value);
|
|
831
1007
|
const result = record(observation?.result);
|
|
832
1008
|
const source = record(observation?.source);
|
|
833
|
-
if (observation?.type
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
? [result.content]
|
|
842
|
-
: [];
|
|
843
|
-
})
|
|
844
|
-
.join('\n');
|
|
1009
|
+
if (observation?.type !== 'tool_result')
|
|
1010
|
+
continue;
|
|
1011
|
+
if ((source?.toolName === 'exec' || source?.toolName === 'exec_wait') &&
|
|
1012
|
+
streams(record(result?.data)))
|
|
1013
|
+
continue;
|
|
1014
|
+
add('TEXT', result?.content);
|
|
1015
|
+
}
|
|
1016
|
+
return blocks.length ? blocks : [{ channel: 'TEXT', text: '' }];
|
|
845
1017
|
}
|
|
846
|
-
return summary
|
|
1018
|
+
return summary === null ? undefined : [{ channel: 'TEXT', text: summary }];
|
|
847
1019
|
}
|
|
848
1020
|
function codeExecutionError(data) {
|
|
849
1021
|
const error = record(data?.error);
|
|
@@ -876,7 +1048,14 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
|
|
|
876
1048
|
preview.length > 10_000
|
|
877
1049
|
}, status, 'Code execution', {
|
|
878
1050
|
kind: 'CODE',
|
|
879
|
-
...(source.length > 10_000
|
|
1051
|
+
...(source.length > 10_000 || resultData?.outputHeadTruncated === true
|
|
1052
|
+
? {
|
|
1053
|
+
truncation: {
|
|
1054
|
+
...(source.length > 10_000 ? { input: true } : {}),
|
|
1055
|
+
...(resultData?.outputHeadTruncated === true ? { output: 'HEAD' } : {})
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
: {}),
|
|
880
1059
|
...(errorCode === null
|
|
881
1060
|
? resultError === undefined
|
|
882
1061
|
? {}
|
|
@@ -887,8 +1066,8 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
|
|
|
887
1066
|
message: compactRunnerText(outputSummary ?? '', 1000)
|
|
888
1067
|
}
|
|
889
1068
|
}),
|
|
890
|
-
...(codeOutput === undefined ? {} : { output:
|
|
891
|
-
});
|
|
1069
|
+
...(codeOutput === undefined ? {} : { output: codeOutput })
|
|
1070
|
+
}, toolName);
|
|
892
1071
|
}
|
|
893
1072
|
if (toolName === 'code_exec_wait' || toolName === 'exec_wait') {
|
|
894
1073
|
const inputRecord = record(input);
|
|
@@ -920,7 +1099,7 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
|
|
|
920
1099
|
.join('\n');
|
|
921
1100
|
return commandItem({
|
|
922
1101
|
itemId: id,
|
|
923
|
-
command:
|
|
1102
|
+
command: '',
|
|
924
1103
|
cwd: null,
|
|
925
1104
|
outputPreview: status === 'IN_PROGRESS' && outputSummary !== null
|
|
926
1105
|
? outputSummary
|
|
@@ -938,6 +1117,14 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
|
|
|
938
1117
|
resultSummary.length > 10_000
|
|
939
1118
|
}, status, toolName === 'code_exec_wait' ? 'Code execution wait' : 'Command wait', {
|
|
940
1119
|
kind: 'CONTROL',
|
|
1120
|
+
toolName,
|
|
1121
|
+
action: compactRunnerText(action, 128),
|
|
1122
|
+
...(typeof inputRecord?.processId === 'string' || typeof inputRecord?.cellId === 'string'
|
|
1123
|
+
? {
|
|
1124
|
+
targetId: compactRunnerText(String(inputRecord.processId ?? inputRecord.cellId), 256)
|
|
1125
|
+
}
|
|
1126
|
+
: {}),
|
|
1127
|
+
...executionSource(resultData?.executionSource),
|
|
941
1128
|
...(display === undefined
|
|
942
1129
|
? {}
|
|
943
1130
|
: {
|
|
@@ -947,10 +1134,9 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
|
|
|
947
1134
|
]
|
|
948
1135
|
}),
|
|
949
1136
|
...(display === undefined && legacyBlocks.length > 0 ? { output: legacyBlocks } : {}),
|
|
950
|
-
...(codeOutput === undefined
|
|
951
|
-
? {}
|
|
952
|
-
: { output: [{ channel: 'TEXT', text: codeOutput }] }),
|
|
1137
|
+
...(codeOutput === undefined ? {} : { output: codeOutput }),
|
|
953
1138
|
...((typeof inputRecord?.data === 'string' && inputRecord.data.length > 10_000) ||
|
|
1139
|
+
resultData?.outputHeadTruncated === true ||
|
|
954
1140
|
(display !== undefined && (display.stdoutDroppedBytes || display.stderrDroppedBytes)) ||
|
|
955
1141
|
(display === undefined && legacyBlocks.length > 0 && truncated)
|
|
956
1142
|
? {
|
|
@@ -958,8 +1144,9 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
|
|
|
958
1144
|
...(typeof inputRecord?.data === 'string' && inputRecord.data.length > 10_000
|
|
959
1145
|
? { input: true }
|
|
960
1146
|
: {}),
|
|
961
|
-
...(
|
|
962
|
-
(display
|
|
1147
|
+
...(resultData?.outputHeadTruncated === true ||
|
|
1148
|
+
(display !== undefined &&
|
|
1149
|
+
(display.stdoutDroppedBytes || display.stderrDroppedBytes))
|
|
963
1150
|
? { output: 'HEAD' }
|
|
964
1151
|
: display === undefined && legacyBlocks.length > 0 && truncated
|
|
965
1152
|
? { output: 'SOURCE' }
|
|
@@ -993,6 +1180,7 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
|
|
|
993
1180
|
title: compactRunnerText(toolName, 500) || 'unknown',
|
|
994
1181
|
inputSummary: inputSummary.text || null,
|
|
995
1182
|
outputSummary: outputSummary === null ? null : compactRunnerText(outputSummary, 10_000),
|
|
1183
|
+
...(outputSummary === null ? {} : { output: publicOutputSnapshot(outputSummary, truncated) }),
|
|
996
1184
|
progressLabel: status === 'IN_PROGRESS' ? 'Running' : null,
|
|
997
1185
|
errorCode: errorCode === null ? null : compactRunnerText(errorCode, 80),
|
|
998
1186
|
truncated: truncated || inputSummary.truncated || (outputSummary?.length ?? 0) > 10_000,
|
|
@@ -1064,7 +1252,24 @@ function execDisplayOutput(value) {
|
|
|
1064
1252
|
stderrDroppedBytes: data.stderrDroppedBytes
|
|
1065
1253
|
};
|
|
1066
1254
|
}
|
|
1067
|
-
function
|
|
1255
|
+
function executionSource(value) {
|
|
1256
|
+
const source = record(value);
|
|
1257
|
+
if (!source ||
|
|
1258
|
+
(source.kind !== 'SHELL' && source.kind !== 'CODE') ||
|
|
1259
|
+
typeof source.text !== 'string')
|
|
1260
|
+
return {};
|
|
1261
|
+
return {
|
|
1262
|
+
source: {
|
|
1263
|
+
kind: source.kind,
|
|
1264
|
+
text: compactRunnerText(source.text, 10_000),
|
|
1265
|
+
...(typeof source.cwd === 'string' ? { cwd: compactRunnerText(source.cwd, 10_000) } : {}),
|
|
1266
|
+
truncated: source.truncated === true ||
|
|
1267
|
+
source.text.length > 10_000 ||
|
|
1268
|
+
(typeof source.cwd === 'string' && source.cwd.length > 10_000)
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
function commandItem(command, status, title, execution, toolName = 'exec') {
|
|
1068
1273
|
const display = command.displayOutput;
|
|
1069
1274
|
const detail = execution ?? {
|
|
1070
1275
|
kind: 'SHELL',
|
|
@@ -1089,7 +1294,7 @@ function commandItem(command, status, title, execution) {
|
|
|
1089
1294
|
]
|
|
1090
1295
|
})
|
|
1091
1296
|
};
|
|
1092
|
-
const bounded = boundExecutionPresentation(detail);
|
|
1297
|
+
const bounded = boundExecutionPresentation({ toolName, ...detail });
|
|
1093
1298
|
return {
|
|
1094
1299
|
itemId: command.itemId,
|
|
1095
1300
|
kind: 'command_execution',
|
|
@@ -1099,7 +1304,13 @@ function commandItem(command, status, title, execution) {
|
|
|
1099
1304
|
command: command.command,
|
|
1100
1305
|
cwd: command.cwd,
|
|
1101
1306
|
outputPreview: command.outputPreview,
|
|
1102
|
-
|
|
1307
|
+
output: {
|
|
1308
|
+
text: publicOutputSnapshot(bounded.presentation.execution.output
|
|
1309
|
+
?.map((block) => block.text)
|
|
1310
|
+
.filter(Boolean)
|
|
1311
|
+
.join('\n') ?? command.outputPreview).text,
|
|
1312
|
+
truncated: command.truncated || bounded.truncated
|
|
1313
|
+
},
|
|
1103
1314
|
exitCode: command.exitCode,
|
|
1104
1315
|
durationMs: null,
|
|
1105
1316
|
truncated: command.truncated ||
|
|
@@ -1130,7 +1341,6 @@ function patchChanges(value, extensions) {
|
|
|
1130
1341
|
additions: entry.additions,
|
|
1131
1342
|
deletions: entry.deletions,
|
|
1132
1343
|
changeId: entry.changeId,
|
|
1133
|
-
diffAvailable: entry.diff.status === 'available',
|
|
1134
1344
|
diff: entry.diff.status === 'available'
|
|
1135
1345
|
? { ...entry.diff, source: 'TOOL_CHANGE' }
|
|
1136
1346
|
: {
|
|
@@ -1164,7 +1374,7 @@ function patchChanges(value, extensions) {
|
|
|
1164
1374
|
});
|
|
1165
1375
|
}
|
|
1166
1376
|
function change(path, operation, additions, deletions) {
|
|
1167
|
-
return { path, change: operation, additions, deletions
|
|
1377
|
+
return { path, change: operation, additions, deletions };
|
|
1168
1378
|
}
|
|
1169
1379
|
function execResult(value, summary, eventTruncated = false) {
|
|
1170
1380
|
const data = record(value);
|
|
@@ -1248,9 +1458,15 @@ function marAgentSubagentProjection(toolName, input, output, knownTitle, knownDe
|
|
|
1248
1458
|
...(title.length === 0 ? {} : { title }),
|
|
1249
1459
|
...subagentPayload(details),
|
|
1250
1460
|
...(typeof details.latestMessage?.text === 'string'
|
|
1251
|
-
? {
|
|
1461
|
+
? {
|
|
1462
|
+
outputSummary: boundedToolSummary(details.latestMessage.text),
|
|
1463
|
+
output: publicOutputSnapshot(details.latestMessage.text, details.latestMessage.truncated === true)
|
|
1464
|
+
}
|
|
1252
1465
|
: typeof outputData?.errorMessage === 'string'
|
|
1253
|
-
? {
|
|
1466
|
+
? {
|
|
1467
|
+
outputSummary: compactRunnerText(outputData.errorMessage, 10_000),
|
|
1468
|
+
output: publicOutputSnapshot(outputData.errorMessage)
|
|
1469
|
+
}
|
|
1254
1470
|
: {}),
|
|
1255
1471
|
...(typeof outputData?.errorCode === 'string'
|
|
1256
1472
|
? { errorCode: compactRunnerText(outputData.errorCode, 80) }
|
|
@@ -737,7 +737,8 @@ export class MarAgentManagedRunController {
|
|
|
737
737
|
status: item.status,
|
|
738
738
|
payload: attachments.length === 0 ? item.payload : { ...item.payload, attachments },
|
|
739
739
|
...(item.permissionStop === undefined ? {} : { permissionStop: item.permissionStop }),
|
|
740
|
-
...(item.merge === undefined ? {} : { merge: item.merge })
|
|
740
|
+
...(item.merge === undefined ? {} : { merge: item.merge }),
|
|
741
|
+
...(item.append === undefined ? {} : { append: item.append })
|
|
741
742
|
});
|
|
742
743
|
}
|
|
743
744
|
}
|
|
@@ -87,10 +87,8 @@ export class MarAgentRuntimeModelFactory {
|
|
|
87
87
|
: { responsesConfigurationUpdates: configuration.responsesConfigurationUpdates }),
|
|
88
88
|
enabled: configuration.enabled
|
|
89
89
|
};
|
|
90
|
-
const {
|
|
91
|
-
if (
|
|
92
|
-
return { ...model, apiKey: new SecretValue(apiKey) };
|
|
93
|
-
if (credential?.type === 'INLINE_API_KEY')
|
|
90
|
+
const { credential } = configuration;
|
|
91
|
+
if (credential.type === 'INLINE_API_KEY')
|
|
94
92
|
return {
|
|
95
93
|
...model,
|
|
96
94
|
apiKey: new SecretValue(credential.value)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { marAgentNodeModelSummarySchema, parseComposerTags, resolveMarAgentDefaultReasoningEffort, serializeComposerTag } from '@myagentroam/protocol';
|
|
1
|
+
import { marAgentNodeModelSummarySchema, marAgentRuntimeModelConfigurationSchema, parseComposerTags, resolveMarAgentDefaultReasoningEffort, serializeComposerTag } from '@myagentroam/protocol';
|
|
2
2
|
import { nodeLog } from '../operational.js';
|
|
3
3
|
import { runnerErrorProjection } from './runner-error.js';
|
|
4
4
|
import { AgentError, openAgentSessionCatalog } from '@myagentroam/agent';
|
|
@@ -7,7 +7,7 @@ import { resolve } from 'node:path';
|
|
|
7
7
|
import { AbstractRunner } from './abstract-runner.js';
|
|
8
8
|
import { marAgentGeneratedImageSources, marAgentGeneratedImagesDirectory } from './mar-agent/generated-images.js';
|
|
9
9
|
import { projectMarAgentHistory } from './mar-agent/history-projection.js';
|
|
10
|
-
import { captureMarAgentExecutionInput } from './mar-agent/execution-input.js';
|
|
10
|
+
import { captureMarAgentExecutionInput, marAgentEnvelopeInput } from './mar-agent/execution-input.js';
|
|
11
11
|
export class MarAgentRunner extends AbstractRunner {
|
|
12
12
|
homeDirectory;
|
|
13
13
|
name = 'mar-agent';
|
|
@@ -31,6 +31,7 @@ export class MarAgentRunner extends AbstractRunner {
|
|
|
31
31
|
return { runner: this.name, runnerInput: captureMarAgentExecutionInput(input) };
|
|
32
32
|
}
|
|
33
33
|
discoveryScope = 'ALL_WORKSPACES';
|
|
34
|
+
// Display and usage hints only; request admission/defaults use captured resources.
|
|
34
35
|
#models = [];
|
|
35
36
|
#releaseSessionResources;
|
|
36
37
|
#generatedImageRegistrar;
|
|
@@ -45,6 +46,7 @@ export class MarAgentRunner extends AbstractRunner {
|
|
|
45
46
|
return parsed.success ? [parsed.data] : [];
|
|
46
47
|
})
|
|
47
48
|
: [];
|
|
49
|
+
return this.profileForValidation();
|
|
48
50
|
}
|
|
49
51
|
setSessionResourceReleaser(release) {
|
|
50
52
|
this.#releaseSessionResources = release;
|
|
@@ -114,8 +116,9 @@ export class MarAgentRunner extends AbstractRunner {
|
|
|
114
116
|
available(capabilities) {
|
|
115
117
|
return capabilities.marAgent?.available === true;
|
|
116
118
|
}
|
|
117
|
-
profileForValidation(
|
|
118
|
-
|
|
119
|
+
profileForValidation(catalog = this
|
|
120
|
+
.#models) {
|
|
121
|
+
const models = catalog.filter((model) => model.enabled && model.conversationModel !== false);
|
|
119
122
|
return {
|
|
120
123
|
runner: 'mar-agent',
|
|
121
124
|
models: models.map((model, index) => ({
|
|
@@ -202,10 +205,29 @@ export class MarAgentRunner extends AbstractRunner {
|
|
|
202
205
|
.map((model) => model.id));
|
|
203
206
|
return this.profileForValidation().models.filter((model) => eligible.has(model.id));
|
|
204
207
|
}
|
|
205
|
-
assertChildModel(modelId) {
|
|
206
|
-
if (!this.
|
|
208
|
+
assertChildModel(modelId, context) {
|
|
209
|
+
if (!this.executionModels(context).some((model) => model.id === modelId && model.enabled && model.conversationModel && model.subagentModel))
|
|
207
210
|
throw new Error('MAR_AGENT_SUBAGENT_MODEL_UNAVAILABLE');
|
|
208
211
|
}
|
|
212
|
+
executionModels(context, purpose = 'admission') {
|
|
213
|
+
if (context.runner !== this.name)
|
|
214
|
+
return [];
|
|
215
|
+
const input = marAgentEnvelopeInput({ runnerInput: context.runnerInput });
|
|
216
|
+
const candidates = purpose === 'defaults' && Array.isArray(input?.models) && input.models.length > 0
|
|
217
|
+
? input.models
|
|
218
|
+
: input?.model !== undefined
|
|
219
|
+
? [input.model]
|
|
220
|
+
: Array.isArray(input?.models)
|
|
221
|
+
? input.models
|
|
222
|
+
: [];
|
|
223
|
+
return candidates.flatMap((value) => {
|
|
224
|
+
const runtime = marAgentRuntimeModelConfigurationSchema.safeParse(value);
|
|
225
|
+
if (runtime.success)
|
|
226
|
+
return [runtime.data];
|
|
227
|
+
const summary = marAgentNodeModelSummarySchema.safeParse(value);
|
|
228
|
+
return summary.success ? [summary.data] : [];
|
|
229
|
+
});
|
|
230
|
+
}
|
|
209
231
|
supportsConfiguration(configuration) {
|
|
210
232
|
if (configuration.runner !== this.name)
|
|
211
233
|
return false;
|
|
@@ -217,8 +239,10 @@ export class MarAgentRunner extends AbstractRunner {
|
|
|
217
239
|
: model.supportedEfforts.includes(configuration.effort)) &&
|
|
218
240
|
profile.accessOptions.some((candidate) => candidate.id === configuration.access));
|
|
219
241
|
}
|
|
220
|
-
defaultConfiguration() {
|
|
221
|
-
const profile = this.profileForValidation(
|
|
242
|
+
defaultConfiguration(_workspace, _environment, executionContext) {
|
|
243
|
+
const profile = this.profileForValidation(executionContext === undefined
|
|
244
|
+
? this.#models
|
|
245
|
+
: this.executionModels(executionContext, 'defaults'));
|
|
222
246
|
const model = profile.models[0];
|
|
223
247
|
return {
|
|
224
248
|
runner: 'mar-agent',
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
export function compactRunnerText(value, limit) {
|
|
2
2
|
return value.length <= limit ? value : `${value.slice(0, Math.max(0, limit - 1))}…`;
|
|
3
3
|
}
|
|
4
|
+
export function publicOutputSnapshot(value, truncated = false) {
|
|
5
|
+
const text = typeof value === 'string' ? value : compactRunnerValue(value, Number.MAX_SAFE_INTEGER).text;
|
|
6
|
+
let bounded = text.slice(-10_000);
|
|
7
|
+
const first = bounded.charCodeAt(0);
|
|
8
|
+
if (text.length > 10_000 && first >= 0xdc00 && first <= 0xdfff)
|
|
9
|
+
bounded = bounded.slice(1);
|
|
10
|
+
return { text: bounded, truncated: truncated || text.length > 10_000 };
|
|
11
|
+
}
|
|
4
12
|
export function compactRunnerValue(value, limit) {
|
|
5
13
|
if (value === undefined || value === null)
|
|
6
14
|
return { text: '', truncated: false };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { compactRunnerText, compactRunnerValue } from '../normalization.js';
|
|
2
|
-
import {
|
|
1
|
+
import { compactRunnerText, compactRunnerValue, publicOutputSnapshot } from '../normalization.js';
|
|
2
|
+
import { shellExecution } from '../execution-presentation.js';
|
|
3
3
|
export function normalizeOpenCodeTool(toolName, state) {
|
|
4
4
|
const status = state?.status === 'completed'
|
|
5
5
|
? 'COMPLETED'
|
|
@@ -14,6 +14,7 @@ export function normalizeOpenCodeTool(toolName, state) {
|
|
|
14
14
|
return {
|
|
15
15
|
kind: 'command_execution',
|
|
16
16
|
payload: {
|
|
17
|
+
toolName: publicToolName,
|
|
17
18
|
command: compactRunnerText(typeof input?.command === 'string'
|
|
18
19
|
? input.command
|
|
19
20
|
: typeof input?.cmd === 'string'
|
|
@@ -21,7 +22,6 @@ export function normalizeOpenCodeTool(toolName, state) {
|
|
|
21
22
|
: publicToolName, 10_000),
|
|
22
23
|
cwd: typeof input?.cwd === 'string' ? compactRunnerText(input.cwd, 4_096) : null,
|
|
23
24
|
outputPreview: typeof state?.output === 'string' ? compactRunnerText(state.output, 10_000) : '',
|
|
24
|
-
outputRef: null,
|
|
25
25
|
exitCode: typeof state?.exitCode === 'number' ? state.exitCode : null,
|
|
26
26
|
durationMs: null,
|
|
27
27
|
truncated: typeof state?.output === 'string' && state.output.length > 10_000,
|
|
@@ -53,6 +53,7 @@ export function normalizeOpenCodeTool(toolName, state) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
: {}),
|
|
56
|
+
...(typeof state?.output === 'string' ? { output: publicOutputSnapshot(state.output) } : {}),
|
|
56
57
|
...subagent
|
|
57
58
|
}
|
|
58
59
|
};
|
|
@@ -75,7 +76,10 @@ function openCodeSubagentProjection(toolName, input, output) {
|
|
|
75
76
|
...(title.length === 0 ? {} : { title }),
|
|
76
77
|
...(nativeResult === undefined
|
|
77
78
|
? {}
|
|
78
|
-
: {
|
|
79
|
+
: {
|
|
80
|
+
outputSummary: compactRunnerText(nativeResult.result, 10_000) || null,
|
|
81
|
+
output: publicOutputSnapshot(nativeResult.result)
|
|
82
|
+
})
|
|
79
83
|
};
|
|
80
84
|
}
|
|
81
85
|
function openCodeTaskResult(value) {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
const MAX_CONTENT_LENGTH = 20_000;
|
|
2
|
+
const RESOLVED_INSTRUCTIONS = Symbol('resolvedPersonalInstructions');
|
|
3
|
+
/** Carry Node-owned merged instructions across internal Session operations, never JSON input. */
|
|
4
|
+
export function resolvedPersonalInstructions(value) {
|
|
5
|
+
return { [RESOLVED_INSTRUCTIONS]: value };
|
|
6
|
+
}
|
|
2
7
|
export function normalizeSessionPrompt(value) {
|
|
3
8
|
if (value === null)
|
|
4
9
|
return null;
|
|
@@ -15,6 +20,8 @@ export function personalInstructionsForRunner(value, runner) {
|
|
|
15
20
|
return undefined;
|
|
16
21
|
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
17
22
|
throw new Error('PERSONAL_INSTRUCTION_INVALID');
|
|
23
|
+
if (RESOLVED_INSTRUCTIONS in value && typeof value[RESOLVED_INSTRUCTIONS] === 'string')
|
|
24
|
+
return value[RESOLVED_INSTRUCTIONS] || undefined;
|
|
18
25
|
const record = value;
|
|
19
26
|
const instructions = {
|
|
20
27
|
common: content(record['common']),
|