@myagentroam/node 0.11.43 → 0.11.45

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.
@@ -7,8 +7,9 @@ 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 } from '../execution-presentation.js';
11
- import { publicOutputSnapshot } from '../normalization.js';
10
+ import { publicOutputSnapshot, publicToolOutput } from '../normalization.js';
11
+ import { boundToolOutput } from '@myagentroam/protocol';
12
+ import { agentOperationAction, agentOperationPresentation } from './agent-operation-presentation.js';
12
13
  function boundCodeOutputSnapshots(sources) {
13
14
  for (const channel of ['outputPreview', 'stdout', 'stderr']) {
14
15
  const text = (entry) => channel === 'outputPreview' ? entry.outputPreview : entry.displayOutput[channel];
@@ -147,15 +148,18 @@ export class MarAgentConversationNormalizer {
147
148
  this.#finishCodeModeOutputCall(event.callId, event.parentCallId);
148
149
  return [];
149
150
  }
150
- // Read/web calls and generated artifacts stay visible independently of cell observations.
151
+ // Public Agent calls, read/web calls and artifacts do not depend on model observations.
151
152
  if (event.parentCallId !== undefined &&
152
153
  event.toolName !== 'read' &&
153
154
  event.toolName !== 'web_search' &&
154
155
  event.toolName !== 'web_fetch' &&
156
+ agentOperationAction(event.toolName) === undefined &&
155
157
  !isImageGenerationTool(event.toolName)) {
156
158
  this.#finishCodeModeOutputCall(event.callId, event.parentCallId);
157
159
  return [];
158
160
  }
161
+ if (event.parentCallId !== undefined && agentOperationAction(event.toolName) !== undefined)
162
+ this.#codeModeSourceCallIds.add(event.callId);
159
163
  if (event.type === 'tool.started')
160
164
  return this.#toolStarted(event);
161
165
  this.#finishToolCall(event);
@@ -252,6 +256,7 @@ export class MarAgentConversationNormalizer {
252
256
  input: event.input,
253
257
  itemId: ownItemId,
254
258
  structured: 'input' in event,
259
+ inputTruncated: event.truncated === true,
255
260
  executionId: event.executionId,
256
261
  ...(event.turnId === undefined ? {} : { turnId: event.turnId }),
257
262
  active: true,
@@ -264,7 +269,7 @@ export class MarAgentConversationNormalizer {
264
269
  if (event.toolName === 'apply_patch' && 'input' in event)
265
270
  return [fileChangeItem(ownItemId, 'IN_PROGRESS', [])];
266
271
  return [
267
- genericToolItem(ownItemId, event.toolName, 'IN_PROGRESS', event.input, null, null, event.truncated === true, event.data, subagentTitle, subagentDetails)
272
+ genericToolItem(ownItemId, event.toolName, 'IN_PROGRESS', event.input, null, null, event.truncated === true, event.data, subagentTitle, subagentDetails, undefined, undefined, event.truncated === true)
268
273
  ];
269
274
  }
270
275
  #toolOutput(event) {
@@ -279,14 +284,13 @@ export class MarAgentConversationNormalizer {
279
284
  stderrDroppedBytes: 0
280
285
  };
281
286
  const displayed = [displayOutput.stdout, displayOutput.stderr].filter(Boolean).join('\n');
282
- const bounded = publicOutputSnapshot(displayed, output.truncated ||
283
- displayOutput.stdoutDroppedBytes > 0 ||
284
- displayOutput.stderrDroppedBytes > 0);
287
+ const bounded = publicOutputSnapshot(displayed, event.outputTruncation !== undefined);
285
288
  const snapshot = {
286
289
  outputPreview: bounded.text,
287
290
  truncated: bounded.truncated || inputOutput.length > 10_000,
288
291
  displayOutput,
289
- processId: output.processId
292
+ processId: output.processId,
293
+ ...(event.outputTruncation ? { outputTruncation: event.outputTruncation } : {})
290
294
  };
291
295
  if (parentCallId !== undefined && (toolName === 'exec' || toolName === 'exec_wait'))
292
296
  return this.#codeModeToolOutput(callId, parentCallId, toolName, executionId, turnId, output.processId, snapshot);
@@ -309,7 +313,7 @@ export class MarAgentConversationNormalizer {
309
313
  displayOutput: snapshot.displayOutput,
310
314
  outputHeadTruncated: snapshot.displayOutput.stdoutDroppedBytes > 0 ||
311
315
  snapshot.displayOutput.stderrDroppedBytes > 0
312
- })
316
+ }, undefined, undefined, undefined, event.outputTruncation, state.inputTruncated)
313
317
  ];
314
318
  }
315
319
  const command = this.#commands.get(state.commandOrigin);
@@ -320,6 +324,10 @@ export class MarAgentConversationNormalizer {
320
324
  command.displayOutput = display;
321
325
  command.outputPreview = snapshot.outputPreview;
322
326
  command.truncated = snapshot.truncated;
327
+ if (event.outputTruncation)
328
+ command.outputTruncation = event.outputTruncation;
329
+ else
330
+ delete command.outputTruncation;
323
331
  return [commandItem(command, 'IN_PROGRESS')];
324
332
  }
325
333
  #toolOutputDelta(event) {
@@ -375,26 +383,11 @@ export class MarAgentConversationNormalizer {
375
383
  const command = target.commandOrigin === undefined ? undefined : this.#commands.get(target.commandOrigin);
376
384
  const item = command
377
385
  ? 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);
386
+ : genericToolItem(target.itemId, target.toolName, 'IN_PROGRESS', target.input, null, null, false, undefined, undefined, undefined, undefined, undefined, target.inputTruncated);
380
387
  const blocks = [
381
388
  ...(output.stdout ? [{ channel: 'STDOUT', text: output.stdout }] : []),
382
389
  ...(output.stderr ? [{ channel: 'STDERR', text: output.stderr }] : [])
383
390
  ];
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
391
  return [
399
392
  {
400
393
  ...item,
@@ -402,9 +395,7 @@ export class MarAgentConversationNormalizer {
402
395
  merge: true,
403
396
  payload: {
404
397
  ...item.payload,
405
- outputPreview: boundedText.text,
406
- output: boundedText,
407
- toolPresentation: bounded.presentation
398
+ output: boundToolOutput(blocks, event.outputTruncation)
408
399
  }
409
400
  }
410
401
  ];
@@ -458,7 +449,13 @@ export class MarAgentConversationNormalizer {
458
449
  .filter(Boolean)
459
450
  .join('')
460
451
  }
461
- })
452
+ }, undefined, undefined, undefined, entries.some((entry) => entry.outputTruncation === 'SOURCE')
453
+ ? 'SOURCE'
454
+ : entries.some((entry) => entry.outputTruncation === 'HEAD' ||
455
+ entry.displayOutput.stdoutDroppedBytes > 0 ||
456
+ entry.displayOutput.stderrDroppedBytes > 0)
457
+ ? 'HEAD'
458
+ : undefined, target.inputTruncated)
462
459
  ];
463
460
  }
464
461
  #trackCodeModeOutputCall(event) {
@@ -626,9 +623,13 @@ export class MarAgentConversationNormalizer {
626
623
  const state = this.#tools.get(event.callId);
627
624
  if (event.toolName === 'exec' && state?.commandOrigin !== undefined) {
628
625
  const command = this.#commands.get(state.commandOrigin);
629
- const result = execResult(event.data, event.summary, event.truncated === true);
626
+ const result = execResult(event.data, event.summary, event.outputTruncation !== undefined);
630
627
  if (command !== undefined && result !== undefined) {
631
628
  applyCommandResult(command, result);
629
+ if (event.outputTruncation)
630
+ command.outputTruncation = event.outputTruncation;
631
+ else
632
+ delete command.outputTruncation;
632
633
  const data = record(event.data);
633
634
  const display = execDisplayOutput(data?.displayOutput);
634
635
  if (display !== undefined)
@@ -672,7 +673,7 @@ export class MarAgentConversationNormalizer {
672
673
  }
673
674
  const item = genericToolItem(state?.itemId ?? itemId('tool', event.callId), event.toolName, 'COMPLETED', state?.input, generatedImages.length === 0
674
675
  ? event.summary
675
- : generatedImages.map((image) => image.name).join(', '), null, event.truncated, event.data, agentId === undefined ? state?.subagentTitle : this.#subagentTitles.get(agentId), details, state?.sleepStartedAt);
676
+ : generatedImages.map((image) => image.name).join(', '), null, event.outputTruncation !== undefined, event.data, agentId === undefined ? state?.subagentTitle : this.#subagentTitles.get(agentId), details, state?.sleepStartedAt, event.outputTruncation, state?.inputTruncated, event.summaryTruncated === true);
676
677
  return [
677
678
  {
678
679
  ...item,
@@ -703,7 +704,7 @@ export class MarAgentConversationNormalizer {
703
704
  return [
704
705
  genericToolItem(state?.itemId ?? itemId('tool', event.callId), event.toolName, event.code === 'MAR_AGENT_CANCELLED' || event.code === 'MAR_AGENT_EXECUTION_CANCELLED'
705
706
  ? 'CANCELLED'
706
- : 'FAILED', state?.input, event.message ?? event.code, event.code, event.truncated === true, state?.presentationData, state?.subagentTitle, state?.subagentDetails, state?.sleepStartedAt)
707
+ : 'FAILED', state?.input, event.message ?? event.code, event.code, event.truncated === true, state?.presentationData, state?.subagentTitle, state?.subagentDetails, state?.sleepStartedAt, event.outputTruncation, state?.inputTruncated)
707
708
  ];
708
709
  }
709
710
  #codeModeToolResults(event) {
@@ -1026,33 +1027,30 @@ function codeExecutionError(data) {
1026
1027
  message: compactRunnerText(error.message, 1000)
1027
1028
  };
1028
1029
  }
1029
- function genericToolItem(id, toolName, status, input, outputSummary = null, errorCode = null, truncated = false, output, subagentTitle, knownSubagentDetails, sleepStartedAt) {
1030
+ function genericToolItem(id, toolName, status, input, outputSummary = null, errorCode = null, truncated = false, output, subagentTitle, knownSubagentDetails, sleepStartedAt, outputTruncation, inputTruncated = false, summaryTruncated = false) {
1030
1031
  if (toolName === 'code_exec') {
1031
1032
  const code = typeof input === 'string' ? input : record(input)?.code;
1032
1033
  const source = typeof code === 'string' ? code : compactRunnerValue(input, 10_000).text || toolName;
1033
1034
  const resultData = record(output);
1034
- const codeOutput = codeObservationOutput(resultData, outputSummary);
1035
+ const codeOutput = codeObservationOutput(resultData, null);
1035
1036
  const resultError = codeExecutionError(resultData);
1036
1037
  const preview = errorCode === null
1037
1038
  ? (outputSummary ?? '')
1038
1039
  : [errorCode, outputSummary].filter(Boolean).join(': ');
1039
- return commandItem({
1040
+ const item = commandItem({
1040
1041
  itemId: id,
1041
1042
  command: compactRunnerText(source, 10_000),
1042
1043
  cwd: null,
1043
- outputPreview: compactRunnerText(preview, 10_000),
1044
+ outputPreview: '',
1044
1045
  exitCode: null,
1045
- truncated: truncated ||
1046
- resultData?.truncated === true ||
1047
- source.length > 10_000 ||
1048
- preview.length > 10_000
1046
+ truncated: truncated || source.length > 10_000 || preview.length > 10_000
1049
1047
  }, status, 'Code execution', {
1050
1048
  kind: 'CODE',
1051
- ...(source.length > 10_000 || resultData?.outputHeadTruncated === true
1049
+ ...(source.length > 10_000 || inputTruncated || outputTruncation !== undefined
1052
1050
  ? {
1053
1051
  truncation: {
1054
- ...(source.length > 10_000 ? { input: true } : {}),
1055
- ...(resultData?.outputHeadTruncated === true ? { output: 'HEAD' } : {})
1052
+ ...(source.length > 10_000 || inputTruncated ? { input: true } : {}),
1053
+ ...(outputTruncation === undefined ? {} : { output: outputTruncation })
1056
1054
  }
1057
1055
  }
1058
1056
  : {}),
@@ -1068,6 +1066,12 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
1068
1066
  }),
1069
1067
  ...(codeOutput === undefined ? {} : { output: codeOutput })
1070
1068
  }, toolName);
1069
+ if (codeOutput === undefined && errorCode === null && outputSummary !== null) {
1070
+ item.payload.outputSummary = compactRunnerText(outputSummary, 10_000);
1071
+ if (summaryTruncated || outputSummary.length > 10_000)
1072
+ item.payload.outputSummaryTruncated = true;
1073
+ }
1074
+ return item;
1071
1075
  }
1072
1076
  if (toolName === 'code_exec_wait' || toolName === 'exec_wait') {
1073
1077
  const inputRecord = record(input);
@@ -1081,40 +1085,17 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
1081
1085
  ? [{ channel: 'STDERR', text: resultData.stderr }]
1082
1086
  : [])
1083
1087
  ];
1084
- const codeOutput = toolName === 'code_exec_wait' ? codeObservationOutput(resultData, outputSummary) : undefined;
1088
+ const codeOutput = toolName === 'code_exec_wait' ? codeObservationOutput(resultData, null) : undefined;
1085
1089
  const resultError = toolName === 'code_exec_wait' ? codeExecutionError(resultData) : undefined;
1086
1090
  const action = typeof inputRecord?.action === 'string' ? inputRecord.action : 'poll';
1087
1091
  const inputSummary = compactRunnerValue(input, 10_000);
1088
- const result = output === undefined ? null : compactRunnerValue(output, 10_000);
1089
- const resultSummary = [outputSummary, result?.text]
1090
- .filter((value, index, values) => typeof value === 'string' && value.length > 0 && values.indexOf(value) === index)
1091
- .join('\n');
1092
- const details = [
1093
- `Action: ${compactRunnerText(action, 128)}`,
1094
- `Input: ${inputSummary.text || '{}'}`,
1095
- resultSummary.length === 0 ? '' : `Result: ${compactRunnerText(resultSummary, 10_000)}`,
1096
- errorCode === null ? '' : `Error: ${compactRunnerText(errorCode, 80)}`
1097
- ]
1098
- .filter(Boolean)
1099
- .join('\n');
1100
- return commandItem({
1092
+ const item = commandItem({
1101
1093
  itemId: id,
1102
1094
  command: '',
1103
1095
  cwd: null,
1104
- outputPreview: status === 'IN_PROGRESS' && outputSummary !== null
1105
- ? outputSummary
1106
- : legacyBlocks.length > 0
1107
- ? legacyBlocks
1108
- .map((block) => block.text)
1109
- .filter(Boolean)
1110
- .join('\n')
1111
- : details,
1096
+ outputPreview: '',
1112
1097
  exitCode: typeof resultData?.exitCode === 'number' ? resultData.exitCode : null,
1113
- truncated: truncated ||
1114
- resultData?.truncated === true ||
1115
- inputSummary.truncated ||
1116
- result?.truncated === true ||
1117
- resultSummary.length > 10_000
1098
+ truncated: truncated || inputSummary.truncated
1118
1099
  }, status, toolName === 'code_exec_wait' ? 'Code execution wait' : 'Command wait', {
1119
1100
  kind: 'CONTROL',
1120
1101
  toolName,
@@ -1135,21 +1116,21 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
1135
1116
  }),
1136
1117
  ...(display === undefined && legacyBlocks.length > 0 ? { output: legacyBlocks } : {}),
1137
1118
  ...(codeOutput === undefined ? {} : { output: codeOutput }),
1138
- ...((typeof inputRecord?.data === 'string' && inputRecord.data.length > 10_000) ||
1139
- resultData?.outputHeadTruncated === true ||
1140
- (display !== undefined && (display.stdoutDroppedBytes || display.stderrDroppedBytes)) ||
1141
- (display === undefined && legacyBlocks.length > 0 && truncated)
1119
+ ...(inputTruncated ||
1120
+ (typeof inputRecord?.data === 'string' && inputRecord.data.length > 10_000) ||
1121
+ outputTruncation !== undefined ||
1122
+ (display !== undefined && (display.stdoutDroppedBytes || display.stderrDroppedBytes))
1142
1123
  ? {
1143
1124
  truncation: {
1144
- ...(typeof inputRecord?.data === 'string' && inputRecord.data.length > 10_000
1125
+ ...(inputTruncated ||
1126
+ (typeof inputRecord?.data === 'string' && inputRecord.data.length > 10_000)
1145
1127
  ? { input: true }
1146
1128
  : {}),
1147
- ...(resultData?.outputHeadTruncated === true ||
1148
- (display !== undefined &&
1149
- (display.stdoutDroppedBytes || display.stderrDroppedBytes))
1150
- ? { output: 'HEAD' }
1151
- : display === undefined && legacyBlocks.length > 0 && truncated
1152
- ? { output: 'SOURCE' }
1129
+ ...(outputTruncation !== undefined
1130
+ ? { output: outputTruncation }
1131
+ : display !== undefined &&
1132
+ (display.stdoutDroppedBytes || display.stderrDroppedBytes)
1133
+ ? { output: 'HEAD' }
1153
1134
  : {})
1154
1135
  }
1155
1136
  }
@@ -1165,8 +1146,32 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
1165
1146
  }
1166
1147
  })
1167
1148
  });
1149
+ if (display === undefined &&
1150
+ legacyBlocks.length === 0 &&
1151
+ codeOutput === undefined &&
1152
+ errorCode === null &&
1153
+ outputSummary !== null) {
1154
+ item.payload.outputSummary = compactRunnerText(outputSummary, 10_000);
1155
+ if (summaryTruncated || outputSummary.length > 10_000)
1156
+ item.payload.outputSummaryTruncated = true;
1157
+ }
1158
+ return item;
1168
1159
  }
1169
1160
  const subagent = marAgentSubagentProjection(toolName, input, output, subagentTitle, knownSubagentDetails);
1161
+ const agentOperation = agentOperationPresentation(toolName, input, output);
1162
+ if (agentOperation &&
1163
+ record(output)?.agentOperation === undefined &&
1164
+ typeof subagent?.subagentId === 'string') {
1165
+ agentOperation.targets = [
1166
+ {
1167
+ agentId: subagent.subagentId,
1168
+ ...(typeof subagent.subagentSessionId === 'string'
1169
+ ? { sessionId: subagent.subagentSessionId }
1170
+ : {}),
1171
+ ...(typeof subagent.title === 'string' ? { title: subagent.title } : {})
1172
+ }
1173
+ ];
1174
+ }
1170
1175
  const toolCategory = isImageGenerationTool(toolName) ? 'IMAGE_GENERATION' : undefined;
1171
1176
  const presentation = projectToolPresentation(toolName, input, output, sleepStartedAt);
1172
1177
  const inputSummary = compactRunnerValue(input, 10_000);
@@ -1179,13 +1184,20 @@ function genericToolItem(id, toolName, status, input, outputSummary = null, erro
1179
1184
  toolName: compactRunnerText(toolName, 128) || 'unknown',
1180
1185
  title: compactRunnerText(toolName, 500) || 'unknown',
1181
1186
  inputSummary: inputSummary.text || null,
1182
- outputSummary: outputSummary === null ? null : compactRunnerText(outputSummary, 10_000),
1183
- ...(outputSummary === null ? {} : { output: publicOutputSnapshot(outputSummary, truncated) }),
1187
+ outputSummary: typeof output === 'string' || errorCode !== null ? null : outputSummary,
1188
+ ...(typeof output === 'string' ? { output: publicToolOutput(output, outputTruncation) } : {}),
1189
+ ...(typeof output !== 'string' && outputSummary !== null && summaryTruncated
1190
+ ? { outputSummaryTruncated: true }
1191
+ : {}),
1184
1192
  progressLabel: status === 'IN_PROGRESS' ? 'Running' : null,
1185
1193
  errorCode: errorCode === null ? null : compactRunnerText(errorCode, 80),
1186
- truncated: truncated || inputSummary.truncated || (outputSummary?.length ?? 0) > 10_000,
1194
+ ...(errorCode !== null && outputSummary
1195
+ ? { errorMessage: compactRunnerText(outputSummary, 1000) }
1196
+ : {}),
1197
+ ...(inputTruncated || inputSummary.truncated ? { inputTruncated: true } : {}),
1187
1198
  ...(toolCategory === undefined ? {} : { toolCategory }),
1188
1199
  ...(presentation === undefined ? {} : { toolPresentation: presentation }),
1200
+ ...(agentOperation === undefined ? {} : { agentOperation }),
1189
1201
  ...subagent
1190
1202
  },
1191
1203
  merge: true
@@ -1294,7 +1306,14 @@ function commandItem(command, status, title, execution, toolName = 'exec') {
1294
1306
  ]
1295
1307
  })
1296
1308
  };
1297
- const bounded = boundExecutionPresentation({ toolName, ...detail });
1309
+ const { output: detailOutput, truncation, ...executionMetadata } = detail;
1310
+ const blocks = detailOutput ??
1311
+ (!detail.error && command.outputPreview
1312
+ ? [{ channel: 'COMBINED', text: command.outputPreview }]
1313
+ : undefined);
1314
+ const output = blocks === undefined
1315
+ ? undefined
1316
+ : boundToolOutput(blocks, command.outputTruncation ?? truncation?.output);
1298
1317
  return {
1299
1318
  itemId: command.itemId,
1300
1319
  kind: 'command_execution',
@@ -1303,22 +1322,17 @@ function commandItem(command, status, title, execution, toolName = 'exec') {
1303
1322
  ...(title === undefined ? {} : { title }),
1304
1323
  command: command.command,
1305
1324
  cwd: command.cwd,
1306
- outputPreview: command.outputPreview,
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
- },
1325
+ ...(output === undefined ? {} : { output }),
1314
1326
  exitCode: command.exitCode,
1315
1327
  durationMs: null,
1316
- truncated: command.truncated ||
1317
- command.inputTruncated === true ||
1318
- bounded.truncated ||
1319
- (display !== undefined &&
1320
- (display.stdoutDroppedBytes > 0 || display.stderrDroppedBytes > 0)),
1321
- toolPresentation: bounded.presentation
1328
+ toolPresentation: {
1329
+ kind: 'EXECUTION',
1330
+ execution: {
1331
+ toolName,
1332
+ ...executionMetadata,
1333
+ ...(truncation?.input ? { truncation: { input: true } } : {})
1334
+ }
1335
+ }
1322
1336
  },
1323
1337
  merge: true
1324
1338
  };
@@ -1421,8 +1435,8 @@ function execResult(value, summary, eventTruncated = false) {
1421
1435
  ...(exitCode === undefined ? {} : { exitCode }),
1422
1436
  ...(data?.cached === true || summaryData?.cached === true ? { cached: true } : {}),
1423
1437
  truncated: eventTruncated ||
1424
- data?.truncated === true ||
1425
- summaryData?.truncated === true ||
1438
+ (execDisplayOutput(data?.displayOutput) === undefined && data?.truncated === true) ||
1439
+ (data === undefined && summaryData?.truncated === true) ||
1426
1440
  structuredSummaryIncomplete
1427
1441
  };
1428
1442
  }
@@ -1458,14 +1472,11 @@ function marAgentSubagentProjection(toolName, input, output, knownTitle, knownDe
1458
1472
  ...(title.length === 0 ? {} : { title }),
1459
1473
  ...subagentPayload(details),
1460
1474
  ...(typeof details.latestMessage?.text === 'string'
1461
- ? {
1462
- outputSummary: boundedToolSummary(details.latestMessage.text),
1463
- output: publicOutputSnapshot(details.latestMessage.text, details.latestMessage.truncated === true)
1464
- }
1475
+ ? { outputSummary: null, output: undefined }
1465
1476
  : typeof outputData?.errorMessage === 'string'
1466
1477
  ? {
1467
- outputSummary: compactRunnerText(outputData.errorMessage, 10_000),
1468
- output: publicOutputSnapshot(outputData.errorMessage)
1478
+ outputSummary: null,
1479
+ output: publicToolOutput(outputData.errorMessage)
1469
1480
  }
1470
1481
  : {}),
1471
1482
  ...(typeof outputData?.errorCode === 'string'
@@ -240,19 +240,24 @@ export class MarAgentSessionRuntimeRegistry {
240
240
  throw failure.reason;
241
241
  }
242
242
  async #destroyRuntime(runtime, aliases, reason, runId, changedCategories = []) {
243
- nodeLog('runner.mar-agent.runtime.releasing', {
244
- runtimeId: runtime.runtimeId,
245
- sessionId: runtime.session.id,
246
- reason,
247
- ...(runId === undefined ? {} : { runId }),
248
- ...(changedCategories.length === 0 ? {} : { changedCategories })
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 > 1)
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
- nodeLog('runner.mar-agent.runtime.cleanup_failed', {
267
- sessionId,
268
- code: 'MAR_AGENT_RUNTIME_CLEANUP_FAILED'
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
  }
@@ -1,3 +1,4 @@
1
+ import { boundToolOutput } from '@myagentroam/protocol';
1
2
  export function compactRunnerText(value, limit) {
2
3
  return value.length <= limit ? value : `${value.slice(0, Math.max(0, limit - 1))}…`;
3
4
  }
@@ -9,6 +10,10 @@ export function publicOutputSnapshot(value, truncated = false) {
9
10
  bounded = bounded.slice(1);
10
11
  return { text: bounded, truncated: truncated || text.length > 10_000 };
11
12
  }
13
+ export function publicToolOutput(value, truncation, channel = 'TEXT') {
14
+ const text = typeof value === 'string' ? value : compactRunnerValue(value, Number.MAX_SAFE_INTEGER).text;
15
+ return boundToolOutput(text ? [{ channel, text }] : [], truncation);
16
+ }
12
17
  export function compactRunnerValue(value, limit) {
13
18
  if (value === undefined || value === null)
14
19
  return { text: '', truncated: false };
@@ -1,4 +1,4 @@
1
- import { compactRunnerText, compactRunnerValue, publicOutputSnapshot } from '../normalization.js';
1
+ import { compactRunnerText, compactRunnerValue, publicToolOutput } from '../normalization.js';
2
2
  import { shellExecution } from '../execution-presentation.js';
3
3
  export function normalizeOpenCodeTool(toolName, state) {
4
4
  const status = state?.status === 'completed'
@@ -21,14 +21,14 @@ export function normalizeOpenCodeTool(toolName, state) {
21
21
  ? input.cmd
22
22
  : publicToolName, 10_000),
23
23
  cwd: typeof input?.cwd === 'string' ? compactRunnerText(input.cwd, 4_096) : null,
24
- outputPreview: typeof state?.output === 'string' ? compactRunnerText(state.output, 10_000) : '',
25
24
  exitCode: typeof state?.exitCode === 'number' ? state.exitCode : null,
26
25
  durationMs: null,
27
- truncated: typeof state?.output === 'string' && state.output.length > 10_000,
28
26
  ...(typeof state?.output === 'string'
29
- ? { output: publicOutputSnapshot(state.output) }
27
+ ? { output: publicToolOutput(state.output, undefined, 'COMBINED') }
30
28
  : {}),
31
- toolPresentation: shellExecution(typeof state?.output === 'string' ? state.output : undefined)
29
+ toolPresentation: shellExecution((typeof input?.command === 'string' && input.command.length > 10_000) ||
30
+ (typeof input?.cmd === 'string' && input.cmd.length > 10_000) ||
31
+ (typeof input?.cwd === 'string' && input.cwd.length > 4_096))
32
32
  }
33
33
  };
34
34
  return {
@@ -39,10 +39,10 @@ export function normalizeOpenCodeTool(toolName, state) {
39
39
  title: compactRunnerText(typeof state?.title === 'string' ? state.title : toolName, 500) ||
40
40
  publicToolName,
41
41
  inputSummary: compactRunnerValue(state?.input, 10_000).text || null,
42
- outputSummary: typeof state?.output === 'string' ? compactRunnerText(state.output, 10_000) : null,
42
+ outputSummary: null,
43
43
  progressLabel: null,
44
44
  errorCode: status === 'FAILED' ? 'OPENCODE_TOOL_FAILED' : null,
45
- truncated: false,
45
+ ...(compactRunnerValue(state?.input, 10_000).truncated ? { inputTruncated: true } : {}),
46
46
  ...(normalizedName === 'read'
47
47
  ? {
48
48
  toolPresentation: {
@@ -53,7 +53,7 @@ export function normalizeOpenCodeTool(toolName, state) {
53
53
  }
54
54
  }
55
55
  : {}),
56
- ...(typeof state?.output === 'string' ? { output: publicOutputSnapshot(state.output) } : {}),
56
+ ...(typeof state?.output === 'string' ? { output: publicToolOutput(state.output) } : {}),
57
57
  ...subagent
58
58
  }
59
59
  };
@@ -77,8 +77,8 @@ function openCodeSubagentProjection(toolName, input, output) {
77
77
  ...(nativeResult === undefined
78
78
  ? {}
79
79
  : {
80
- outputSummary: compactRunnerText(nativeResult.result, 10_000) || null,
81
- output: publicOutputSnapshot(nativeResult.result)
80
+ outputSummary: null,
81
+ output: publicToolOutput(nativeResult.result)
82
82
  })
83
83
  };
84
84
  }