@myagentroam/node 0.11.42 → 0.11.44
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/application/node-lifecycle.js +30 -7
- package/dist/connector.js +14 -3
- package/dist/hosting/hosted-conversation-node-service.js +1 -2
- package/dist/main.js +10 -3
- 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/session-runtime-registry.js +22 -12
- package/dist/runner/mar-agent/session-runtime.js +16 -11
- 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/runtime-state.js +0 -1
- package/dist/service/agent-network-bindings.js +9 -50
- package/dist/service/agent-network-invoke.js +9 -21
- package/dist/service/agent-network-observations.js +15 -13
- package/dist/service/agent-network-service.js +39 -31
- package/dist/service/goal-continuation-coordinator.js +5 -0
- package/dist/service/marctl-caller.js +17 -9
- 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)
|
|
@@ -240,19 +240,24 @@ export class MarAgentSessionRuntimeRegistry {
|
|
|
240
240
|
throw failure.reason;
|
|
241
241
|
}
|
|
242
242
|
async #destroyRuntime(runtime, aliases, reason, runId, changedCategories = []) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
243
|
+
try {
|
|
244
|
+
nodeLog('runner.mar-agent.runtime.releasing', {
|
|
245
|
+
runtimeId: runtime.runtimeId,
|
|
246
|
+
sessionId: runtime.session.id,
|
|
247
|
+
reason,
|
|
248
|
+
...(runId === undefined ? {} : { runId }),
|
|
249
|
+
...(changedCategories.length === 0 ? {} : { changedCategories })
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
// Resource release must not depend on a writable diagnostic sink.
|
|
254
|
+
}
|
|
250
255
|
const results = await Promise.allSettled([
|
|
251
256
|
this.#releaseComputerAliases(new Set([...aliases, runtime.session.id]))
|
|
252
257
|
]);
|
|
253
258
|
results.push(...(await Promise.allSettled([releaseSessionRuntime(runtime)])));
|
|
254
259
|
const failures = results.filter((result) => result.status === 'rejected');
|
|
255
|
-
if (failures.length >
|
|
260
|
+
if (failures.length > 0)
|
|
256
261
|
this.#logCleanupFailure(runtime.session.id);
|
|
257
262
|
if (failures[0]?.status === 'rejected')
|
|
258
263
|
throw failures[0].reason;
|
|
@@ -263,9 +268,14 @@ export class MarAgentSessionRuntimeRegistry {
|
|
|
263
268
|
this.#entries.delete(alias);
|
|
264
269
|
}
|
|
265
270
|
#logCleanupFailure(sessionId) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
271
|
+
try {
|
|
272
|
+
nodeLog('runner.mar-agent.runtime.cleanup_failed', {
|
|
273
|
+
sessionId,
|
|
274
|
+
code: 'MAR_AGENT_RUNTIME_CLEANUP_FAILED'
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// Keep the original cleanup error when the diagnostic sink is unavailable.
|
|
279
|
+
}
|
|
270
280
|
}
|
|
271
281
|
}
|
|
@@ -185,25 +185,30 @@ export async function reconfigureSessionRuntime(existing, input, modelFactory) {
|
|
|
185
185
|
}
|
|
186
186
|
export async function releaseSessionRuntime(runtime) {
|
|
187
187
|
const failures = [];
|
|
188
|
-
for (const cleanup of [
|
|
189
|
-
() => runtime.agent.dispose(),
|
|
190
|
-
() => runtime.releaseNetworkContext?.(),
|
|
191
|
-
() => runtime.mcpLease.release(),
|
|
192
|
-
() => runtime.releaseEnvironment?.()
|
|
188
|
+
for (const [resource, cleanup] of [
|
|
189
|
+
['agent', () => runtime.agent.dispose()],
|
|
190
|
+
['network', () => runtime.releaseNetworkContext?.()],
|
|
191
|
+
['mcp', () => runtime.mcpLease.release()],
|
|
192
|
+
['environment', () => runtime.releaseEnvironment?.()]
|
|
193
193
|
]) {
|
|
194
194
|
try {
|
|
195
195
|
await cleanup();
|
|
196
196
|
}
|
|
197
197
|
catch (error) {
|
|
198
198
|
failures.push(error);
|
|
199
|
+
try {
|
|
200
|
+
nodeLog('runner.mar-agent.runtime.cleanup_failed', {
|
|
201
|
+
sessionId: runtime.session.id,
|
|
202
|
+
code: 'MAR_AGENT_RUNTIME_CLEANUP_FAILED',
|
|
203
|
+
stage: 'resource_release',
|
|
204
|
+
resource
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// Keep releasing resources even when the diagnostic sink is unavailable.
|
|
209
|
+
}
|
|
199
210
|
}
|
|
200
211
|
}
|
|
201
|
-
if (failures.length > 1)
|
|
202
|
-
nodeLog('runner.mar-agent.runtime.cleanup_failed', {
|
|
203
|
-
sessionId: runtime.session.id,
|
|
204
|
-
code: 'MAR_AGENT_RUNTIME_CLEANUP_FAILED',
|
|
205
|
-
stage: 'resource_release'
|
|
206
|
-
});
|
|
207
212
|
if (failures.length > 0)
|
|
208
213
|
throw failures[0];
|
|
209
214
|
}
|