@myagentroam/node 0.11.42 → 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.
Files changed (29) hide show
  1. package/dist/connector.js +9 -2
  2. package/dist/hosting/hosted-conversation-node-service.js +1 -2
  3. package/dist/marctl-guidance.js +3 -1
  4. package/dist/runner/abstract-runner.js +2 -2
  5. package/dist/runner/claude/managed-run-controller.js +1 -1
  6. package/dist/runner/claude/native-transcript.js +1 -1
  7. package/dist/runner/claude/tool-normalizer.js +21 -12
  8. package/dist/runner/codex/conversation-parser.js +17 -9
  9. package/dist/runner/codex/managed-run-controller.js +1 -1
  10. package/dist/runner/codex/tool-normalizer.js +17 -9
  11. package/dist/runner/execution-presentation.js +0 -3
  12. package/dist/runner/mar-agent/agent-network-extension.js +2 -2
  13. package/dist/runner/mar-agent/conversation-normalizer.js +259 -43
  14. package/dist/runner/mar-agent/managed-run-controller.js +2 -1
  15. package/dist/runner/mar-agent/runtime-model-factory.js +2 -4
  16. package/dist/runner/mar-agent-runner.js +32 -8
  17. package/dist/runner/normalization.js +8 -0
  18. package/dist/runner/opencode/tool-normalizer.js +8 -4
  19. package/dist/runtime-state.js +0 -1
  20. package/dist/service/agent-network-bindings.js +4 -2
  21. package/dist/service/agent-network-invoke.js +5 -2
  22. package/dist/service/agent-network-observations.js +15 -13
  23. package/dist/service/agent-network-service.js +39 -15
  24. package/dist/service/goal-continuation-coordinator.js +5 -0
  25. package/dist/service/runner-service.js +7 -3
  26. package/dist/session/runtime/conversation-projection.js +3 -1
  27. package/dist/session/session-lifecycle-service.js +7 -4
  28. package/dist/session/session-message-service.js +4 -2
  29. package/package.json +4 -4
package/dist/connector.js CHANGED
@@ -647,10 +647,17 @@ export class NodeConnector {
647
647
  }),
648
648
  resources: async (signal) => {
649
649
  signal.throwIfAborted();
650
- const run = this.runtime.activeSessionRun(sessionId);
650
+ const currentSessionId = this.runtime.getAgentSessionById(sessionId)?.id;
651
+ if (!currentSessionId)
652
+ return [];
653
+ const run = this.runtime.activeSessionRun(currentSessionId);
651
654
  if (!run || !run.initiatedByUserId)
652
655
  return [];
653
- const result = await this.agentNetworkService.list({ sessionId, runId: run.id, requestUserId: run.initiatedByUserId }, { scope: 'children', limit: 100 });
656
+ const result = await this.agentNetworkService.list({
657
+ sessionId: currentSessionId,
658
+ runId: run.id,
659
+ requestUserId: run.initiatedByUserId
660
+ }, { scope: 'children', limit: 100 });
654
661
  signal.throwIfAborted();
655
662
  const data = result;
656
663
  if (!data.sessions?.length && !data.truncated)
@@ -943,8 +943,7 @@ function modelSummary(model, index) {
943
943
  : { responsesTransport: model.responsesTransport }),
944
944
  responsesPreviousResponseId: model.responsesPreviousResponseId,
945
945
  enabled: model.enabled,
946
- sortOrder: index,
947
- apiKeyConfigured: true
946
+ sortOrder: index
948
947
  };
949
948
  }
950
949
  function terminalHostedTurnStatus(status) {
@@ -5,7 +5,7 @@ export function hasMarctlContext(environment) {
5
5
  !!environment['MAR_CTL_NODE_ID'] &&
6
6
  !!environment['MAR_CTL_WORKSPACE_ID']);
7
7
  }
8
- export const marctlManagementDescription = 'Use marctl for model and effort configuration, renaming, persistent prompts, schedules, authorized Node discovery, remote commands, and file transfer.';
8
+ export const marctlManagementDescription = 'Use marctl to manage MAR Agent session settings (model, effort, title, persistent prompts, and schedules), discover authorized MAR Nodes, and execute commands or transfer files on those Nodes. Use native agent_* tools for other Agent lifecycle and collaboration operations.';
9
9
  const marctlSafety = 'Acceptance is not completion. If a request result is unknown, inspect history before retrying. Session IDs and parent relationships do not grant authorization.';
10
10
  export const marctlManagementInstructions = [
11
11
  '## MAR Workspace management',
@@ -21,8 +21,10 @@ export const marctlInstructions = [
21
21
  'Run marctl from the shell. Commands use the authenticated Node and Workspace; marctl help agents, nodes, ssh or scp shows options.',
22
22
  'Use agents start --title <title> -m <text> [--runner <runner>] [--model <id>] [--effort <effort>] [--goal <objective>]. An Agent must supply a nonblank title; a manual terminal may omit it. The default Runner is the current Session Runner; a terminal without a current Session must specify --runner or an explicit --parent. Start returns without waiting.',
23
23
  'Use agents send <id> -m <text> [--steer|--queue], agents wait [<id>] [--wait-for message|completion] [--timeout <duration>], agents stop <id> --execution <execution-id>, agents list [--scope children|descendants|workspace|profile], and agents view <id> [--history]. Wait defaults to direct-child completion for 30 seconds; --timeout 0ms takes a snapshot. Stop clears the target Session Goal.',
24
+ 'Prefer agents send <id> --steer -m <text> for timely communication or course correction. Use --queue only for deliberately deferred input: it is consumed after current work and earlier queued inputs finish, and with an active Goal it is not consumed until that Goal exits. Acceptance is not a guarantee of immediate processing.',
24
25
  'Start and send accept repeated --image <local-path> for PNG, JPEG, GIF or WebP; limits are five images, 5 MiB each and 10 MiB total. Send can update a Goal alone with --goal <objective> or --clear-goal; omitted Goal leaves it unchanged. Decide a direct child approval with send <id> --approval <approval-id> --decision approve|reject.',
25
26
  'List accepts --agent <id> for a relation root, --query, --parent, --limit and --cursor. Use --scope profile [--runner <runner>] for Runner models; configured profiles do not guarantee account availability.',
27
+ 'Only direct-child updates are collected automatically. Sending to a non-child never subscribes; an explicit wait observes it only for that call.',
26
28
  'Use agents config, rename, prompt and schedule for management. marctl nodes, ssh and scp use authorized Nodes.',
27
29
  marctlSafety
28
30
  ].join('\n\n');
@@ -40,8 +40,8 @@ export class AbstractRunner {
40
40
  childModels() {
41
41
  return this.profileForValidation().models;
42
42
  }
43
- assertChildModel(modelId) {
44
- void modelId;
43
+ assertChildModel(modelId, executionContext) {
44
+ void [modelId, executionContext];
45
45
  }
46
46
  presentSession(session, capabilities, context) {
47
47
  void [session, capabilities, context];
@@ -462,7 +462,7 @@ export class ClaudeManagedRunController {
462
462
  const tool = toolInputs.get(result.toolUseId);
463
463
  if (tool === undefined)
464
464
  continue;
465
- const normalized = normalizeClaudeTool(tool.name, tool.input, result.output, result.failed, tool.inputTruncated || result.truncated, knownSubagents, result.claudeResult);
465
+ const normalized = normalizeClaudeTool(tool.name, tool.input, result.output, result.failed, tool.inputTruncated || result.truncated, knownSubagents, result.claudeResult, result.truncated);
466
466
  this.host.emitItem(runId, {
467
467
  itemId: boundedConversationItemId('claude-tool', result.toolUseId),
468
468
  kind,
@@ -339,7 +339,7 @@ export const claudeNativeTranscriptAdapter = {
339
339
  return {
340
340
  userText: (text) => publicGoalHistoryText(stripClaudePlanTag(text)),
341
341
  planText: claudePlanText,
342
- normalizeTool: (entry) => normalizeClaudeTool(entry.toolName, entry.input, entry.outputSummary, entry.failed, entry.inputTruncated || entry.outputTruncated, titles, claudeNativeToolResultMetadata(entry.subagentResult)),
342
+ normalizeTool: (entry) => normalizeClaudeTool(entry.toolName, entry.input, entry.outputSummary, entry.failed, entry.inputTruncated || entry.outputTruncated, titles, claudeNativeToolResultMetadata(entry.subagentResult), entry.outputTruncated),
343
343
  userInputQuestions: (entry) => entry.toolName === 'AskUserQuestion' && isPlainRecord(entry.input)
344
344
  ? claudeUserInputQuestions(entry.input)
345
345
  : []
@@ -1,6 +1,6 @@
1
1
  import { claudeContentBlocks } from './message-parsers.js';
2
- import { compactRunnerText, compactRunnerValue } from '../normalization.js';
3
- import { publicOutputSnapshot, shellExecution } from '../execution-presentation.js';
2
+ import { compactRunnerText, compactRunnerValue, publicOutputSnapshot } from '../normalization.js';
3
+ import { shellExecution } from '../execution-presentation.js';
4
4
  import { RunnerUsageTracker, usageToken, usageTokenSum } from '../../service/runner-usage-tracker.js';
5
5
  export class ClaudeUsageNormalizer {
6
6
  tracker;
@@ -69,7 +69,16 @@ export function extractClaudeToolResults(message) {
69
69
  return [];
70
70
  const blocks = claudeContentBlocks(message).filter((block) => block.type === 'tool_result' && typeof block.tool_use_id === 'string');
71
71
  return blocks.map((block) => {
72
- const output = compactRunnerValue(block.content, 10_000);
72
+ const textBlocks = Array.isArray(block.content)
73
+ ? block.content.flatMap((part) => {
74
+ const value = record(part);
75
+ return value?.type === 'text' && typeof value.text === 'string' ? [value.text] : [];
76
+ })
77
+ : [];
78
+ const content = Array.isArray(block.content) && textBlocks.length === block.content.length
79
+ ? textBlocks.join('\n')
80
+ : block.content;
81
+ const output = publicOutputSnapshot(content);
73
82
  // A message-level structured result cannot be assigned to multiple calls.
74
83
  const structured = blocks.length === 1 ? structuredRecord(message.tool_use_result) : undefined;
75
84
  const fields = structured ?? structuredRecord(block.content);
@@ -90,27 +99,27 @@ export function extractClaudeToolResults(message) {
90
99
  };
91
100
  });
92
101
  }
93
- export function normalizeClaudeTool(toolName, input, output, failed, truncated, knownSubagents = new Map(), resultMetadata) {
102
+ export function normalizeClaudeTool(toolName, input, output, failed, truncated, knownSubagents = new Map(), resultMetadata, sourceOutputTruncated = output === null ? false : truncated) {
94
103
  const values = record(input);
95
104
  const normalizedToolName = compactRunnerText(toolName, 128) || 'unknown';
96
105
  const normalizedOutput = output === null ? null : compactRunnerText(output, 10_000);
97
- const outputTruncated = truncated || (output?.length ?? 0) > 10_000;
106
+ const outputTruncated = sourceOutputTruncated || (output?.length ?? 0) > 10_000;
98
107
  const subagent = claudeSubagentProjection(toolName, input, resultMetadata ?? output, knownSubagents);
99
108
  if (isCommandTool(toolName))
100
109
  return {
101
110
  kind: 'command_execution',
102
111
  payload: {
112
+ toolName: normalizedToolName,
103
113
  command: compactRunnerText(typeof values?.command === 'string' ? values.command : normalizedToolName, 10_000),
104
114
  cwd: null,
105
115
  outputPreview: normalizedOutput ?? '',
106
- outputRef: null,
107
116
  exitCode: null,
108
117
  durationMs: null,
109
- truncated: outputTruncated,
118
+ truncated: truncated || outputTruncated,
110
119
  ...(output === null || output === undefined
111
120
  ? {}
112
- : { output: publicOutputSnapshot(output, truncated) }),
113
- toolPresentation: shellExecution(output ?? undefined, truncated)
121
+ : { output: publicOutputSnapshot(output, outputTruncated) }),
122
+ toolPresentation: shellExecution(output ?? undefined, outputTruncated)
114
123
  }
115
124
  };
116
125
  if (isFileTool(toolName)) {
@@ -132,8 +141,7 @@ export function normalizeClaudeTool(toolName, input, output, failed, truncated,
132
141
  path: normalizedPath,
133
142
  change: 'MODIFIED',
134
143
  additions: null,
135
- deletions: null,
136
- diffAvailable: false
144
+ deletions: null
137
145
  }
138
146
  ]
139
147
  }
@@ -147,9 +155,10 @@ export function normalizeClaudeTool(toolName, input, output, failed, truncated,
147
155
  title: compactRunnerText(toolName, 500) || normalizedToolName,
148
156
  inputSummary: compactRunnerValue(input, 10_000).text || null,
149
157
  outputSummary: normalizedOutput,
158
+ ...(output === null ? {} : { output: publicOutputSnapshot(output, outputTruncated) }),
150
159
  progressLabel: null,
151
160
  errorCode: failed ? 'TOOL_EXECUTION_FAILED' : null,
152
- truncated: outputTruncated,
161
+ truncated: truncated || outputTruncated,
153
162
  ...(toolName === 'Read'
154
163
  ? {
155
164
  toolPresentation: {
@@ -131,7 +131,8 @@ import { runnerErrorProjection } from '../runner-error.js';
131
131
  import { conversationImageAttachmentSchema } from '@myagentroam/protocol';
132
132
  import { parseCodexComposerImageMarkers } from './composer-image-markers.js';
133
133
  import { normalizeCodexTool } from './tool-normalizer.js';
134
- import { publicOutputSnapshot, shellExecution } from '../execution-presentation.js';
134
+ import { shellExecution } from '../execution-presentation.js';
135
+ import { publicOutputSnapshot } from '../normalization.js';
135
136
  import { publicGoalHistoryText } from '../../service/goal-runtime.js';
136
137
  const MAX_COMPOSER_ATTACHMENT_BYTES = 5 * 1024 * 1024;
137
138
  const MAX_COMPOSER_ATTACHMENTS_BYTES = 10 * 1024 * 1024;
@@ -553,6 +554,7 @@ export function mergeCodexCustomToolItems(invocation, result) {
553
554
  outputPreview: resultPayload.outputPreview ??
554
555
  resultPayload.outputSummary ??
555
556
  invocationPayload.outputPreview,
557
+ ...(resultPayload.output === undefined ? {} : { output: resultPayload.output }),
556
558
  exitCode: resultPayload.exitCode ?? invocationPayload.exitCode,
557
559
  durationMs: resultPayload.durationMs ?? invocationPayload.durationMs,
558
560
  truncated: invocationPayload.truncated === true || resultPayload.truncated === true,
@@ -572,6 +574,7 @@ export function mergeCodexCustomToolItems(invocation, result) {
572
574
  payload: {
573
575
  ...invocationPayload,
574
576
  outputSummary: resultPayload.outputSummary ?? invocationPayload.outputSummary,
577
+ ...(resultPayload.output === undefined ? {} : { output: resultPayload.output }),
575
578
  errorCode: resultPayload.errorCode ?? invocationPayload.errorCode,
576
579
  truncated: invocationPayload.truncated === true || resultPayload.truncated === true,
577
580
  ...(resultPayload.attachments === undefined ? {} : { attachments: resultPayload.attachments })
@@ -718,7 +721,6 @@ export function codexOfficialItem(session, nativeTurnId, value, turnSequence, it
718
721
  : '(No command provided)',
719
722
  cwd: typeof value.cwd === 'string' ? compactRunnerText(value.cwd, 4_096) : null,
720
723
  outputPreview: publicOutputSnapshot(output).text,
721
- outputRef: null,
722
724
  exitCode: typeof value.exitCode === 'number' && Number.isInteger(value.exitCode)
723
725
  ? value.exitCode
724
726
  : null,
@@ -756,6 +758,7 @@ export function codexOfficialItem(session, nativeTurnId, value, turnSequence, it
756
758
  toolName: typeof value.tool === 'string' ? value.tool : '',
757
759
  inputSummary: codexCompactJson(value.arguments),
758
760
  outputSummary: codexCompactJson(value.result),
761
+ ...(value.result == null ? {} : { output: publicOutputSnapshot(value.result) }),
759
762
  ...(value.error === undefined ? {} : { errorCode: codexCompactJson(value.error) })
760
763
  }
761
764
  };
@@ -800,12 +803,16 @@ export function codexOfficialItem(session, nativeTurnId, value, turnSequence, it
800
803
  : typeof value.name === 'string'
801
804
  ? value.name
802
805
  : 'tool';
806
+ const outputValue = value.contentItems ?? value.output;
807
+ const output = outputValue == null ? undefined : publicOutputSnapshot(codexToolOutput(outputValue));
803
808
  const normalized = normalizeCodexTool({
804
809
  name,
805
810
  namespace: typeof value.namespace === 'string' ? value.namespace : 'codex',
806
811
  rawInput: value.arguments ?? value.input,
807
812
  inputSummary: codexCompactJson(value.arguments ?? value.input),
808
- outputSummary: codexToolOutputSummary(value.contentItems ?? value.output),
813
+ outputSummary: output?.text ?? null,
814
+ outputTruncated: output?.truncated ?? false,
815
+ truncated: output?.truncated ?? false,
809
816
  outputOnly: value.type === 'custom_tool_call_output' ||
810
817
  value.type === 'function_call_output' ||
811
818
  value.type === 'customToolCallOutput' ||
@@ -900,7 +907,6 @@ export function codexLiveConversationItem(value, completed, imageAttachments = [
900
907
  : '(No command provided)',
901
908
  cwd: typeof value.cwd === 'string' ? compactRunnerText(value.cwd, 4_096) : null,
902
909
  outputPreview: publicOutputSnapshot(output).text,
903
- outputRef: null,
904
910
  exitCode: typeof value.exitCode === 'number' && Number.isInteger(value.exitCode)
905
911
  ? value.exitCode
906
912
  : null,
@@ -937,6 +943,7 @@ export function codexLiveConversationItem(value, completed, imageAttachments = [
937
943
  title: compactRunnerText(`${server}.${tool}`, 500),
938
944
  inputSummary: input.text || null,
939
945
  outputSummary: output.text || null,
946
+ ...(value.result == null ? {} : { output: publicOutputSnapshot(value.result) }),
940
947
  progressLabel: null,
941
948
  errorCode: error.text || null,
942
949
  truncated: input.truncated || output.truncated || error.truncated
@@ -1013,7 +1020,8 @@ export function codexLiveConversationItem(value, completed, imageAttachments = [
1013
1020
  ? value.name
1014
1021
  : 'tool';
1015
1022
  const input = compactRunnerValue(value.arguments ?? value.input, 10_000);
1016
- const output = compactRunnerValue(codexToolOutput(value.contentItems ?? value.output), 10_000);
1023
+ const outputValue = value.contentItems ?? value.output;
1024
+ const output = outputValue == null ? undefined : publicOutputSnapshot(codexToolOutput(outputValue));
1017
1025
  const outputOnly = value.type === 'custom_tool_call_output' ||
1018
1026
  value.type === 'function_call_output' ||
1019
1027
  value.type === 'customToolCallOutput' ||
@@ -1023,8 +1031,9 @@ export function codexLiveConversationItem(value, completed, imageAttachments = [
1023
1031
  namespace: typeof value.namespace === 'string' ? value.namespace : 'codex',
1024
1032
  rawInput: value.arguments ?? value.input,
1025
1033
  inputSummary: input.text || null,
1026
- outputSummary: output.text || null,
1027
- truncated: input.truncated || output.truncated,
1034
+ outputSummary: output?.text ?? null,
1035
+ truncated: input.truncated || output?.truncated === true,
1036
+ outputTruncated: output?.truncated ?? false,
1028
1037
  outputOnly,
1029
1038
  attachments: imageAttachments
1030
1039
  });
@@ -1067,8 +1076,7 @@ function normalizeCodexFileChanges(changes) {
1067
1076
  path,
1068
1077
  change,
1069
1078
  additions: nonnegativeIntegerOrNull(value.additions),
1070
- deletions: nonnegativeIntegerOrNull(value.deletions),
1071
- diffAvailable: value.diffAvailable === true
1079
+ deletions: nonnegativeIntegerOrNull(value.deletions)
1072
1080
  }
1073
1081
  ];
1074
1082
  });
@@ -1,7 +1,7 @@
1
1
  import { NODE_MCP } from '../../mcp/naming.js';
2
2
  import { nodeExecutionEnvironment } from '../../node-execution-environment.js';
3
3
  import { extractId } from './conversation-parser.js';
4
- import { publicOutputSnapshot } from '../execution-presentation.js';
4
+ import { publicOutputSnapshot } from '../normalization.js';
5
5
  import { normalizeCodexApproval } from './tool-normalizer.js';
6
6
  import { parseSecretEnvironment } from '../../mcp/secret-environment.js';
7
7
  import { safeErrorCode } from '../../util/safe-error.js';
@@ -1,5 +1,5 @@
1
- import { compactRunnerText } from '../normalization.js';
2
- import { publicOutputSnapshot, shellExecution } from '../execution-presentation.js';
1
+ import { compactRunnerText, publicOutputSnapshot } from '../normalization.js';
2
+ import { shellExecution } from '../execution-presentation.js';
3
3
  export function normalizeCodexApproval(method) {
4
4
  return method === 'item/commandExecution/requestApproval'
5
5
  ? { toolName: 'command_execution', reason: 'Command execution requires approval.' }
@@ -9,6 +9,7 @@ export function normalizeCodexTool(input) {
9
9
  const name = compactRunnerText(input.name, 128) || 'tool';
10
10
  const rawInput = input.rawInput;
11
11
  const attachments = input.attachments ?? [];
12
+ const outputTruncated = input.outputTruncated ?? (input.outputSummary != null && input.truncated === true);
12
13
  const subagent = codexSubagentProjection(input.namespace, name, rawInput, input.outputSummary);
13
14
  if (isCommandTool(name)) {
14
15
  const outputPreview = compactRunnerText(input.outputSummary ?? '', 10_000);
@@ -16,12 +17,13 @@ export function normalizeCodexTool(input) {
16
17
  return {
17
18
  kind: 'command_execution',
18
19
  payload: {
20
+ toolName: name,
19
21
  outputPreview,
20
22
  truncated: input.truncated === true || (input.outputSummary?.length ?? 0) > 10_000,
21
23
  ...(input.outputSummary == null
22
24
  ? {}
23
- : { output: publicOutputSnapshot(input.outputSummary, input.truncated === true) }),
24
- toolPresentation: shellExecution(input.outputSummary ?? undefined, input.truncated === true),
25
+ : { output: publicOutputSnapshot(input.outputSummary, outputTruncated) }),
26
+ toolPresentation: shellExecution(input.outputSummary ?? undefined, outputTruncated),
25
27
  ...(attachments.length === 0 ? {} : { attachments })
26
28
  }
27
29
  };
@@ -36,16 +38,16 @@ export function normalizeCodexTool(input) {
36
38
  return {
37
39
  kind: 'command_execution',
38
40
  payload: {
41
+ toolName: name,
39
42
  command: compactRunnerText(command, 10_000),
40
43
  cwd: typeof values?.cwd === 'string' ? compactRunnerText(values.cwd, 4_096) : null,
41
44
  outputPreview,
42
- outputRef: null,
43
45
  exitCode: null,
44
46
  durationMs: null,
45
- toolPresentation: shellExecution(input.outputSummary ?? undefined, input.truncated === true),
47
+ toolPresentation: shellExecution(input.outputSummary ?? undefined, outputTruncated),
46
48
  ...(input.outputSummary == null
47
49
  ? {}
48
- : { output: publicOutputSnapshot(input.outputSummary, input.truncated === true) }),
50
+ : { output: publicOutputSnapshot(input.outputSummary, outputTruncated) }),
49
51
  truncated: input.truncated === true ||
50
52
  command.length > 10_000 ||
51
53
  (input.outputSummary?.length ?? 0) > 10_000,
@@ -57,7 +59,10 @@ export function normalizeCodexTool(input) {
57
59
  return {
58
60
  kind: 'tool_call',
59
61
  payload: {
60
- outputSummary: input.outputSummary ?? null,
62
+ outputSummary: input.outputSummary == null ? null : compactRunnerText(input.outputSummary, 10_000),
63
+ ...(input.outputSummary == null
64
+ ? {}
65
+ : { output: publicOutputSnapshot(input.outputSummary, outputTruncated) }),
61
66
  ...subagent,
62
67
  ...(attachments.length === 0 ? {} : { attachments })
63
68
  }
@@ -69,7 +74,10 @@ export function normalizeCodexTool(input) {
69
74
  namespace: compactRunnerText(input.namespace ?? 'codex', 128),
70
75
  toolName: name,
71
76
  inputSummary: input.inputSummary ?? null,
72
- outputSummary: input.outputSummary ?? null,
77
+ outputSummary: input.outputSummary == null ? null : compactRunnerText(input.outputSummary, 10_000),
78
+ ...(input.outputSummary == null
79
+ ? {}
80
+ : { output: publicOutputSnapshot(input.outputSummary, outputTruncated) }),
73
81
  progressLabel: null,
74
82
  errorCode: null,
75
83
  truncated: input.truncated === true,
@@ -6,9 +6,6 @@ function tail(text, limit) {
6
6
  const first = result.charCodeAt(0);
7
7
  return first >= 0xdc00 && first <= 0xdfff ? result.slice(1) : result;
8
8
  }
9
- export function publicOutputSnapshot(text, truncated = false) {
10
- return { text: tail(text, 10_000), truncated: truncated || text.length > 10_000 };
11
- }
12
9
  /** Keep public execution output bounded without copying an unbounded source. */
13
10
  export function boundExecutionPresentation(execution) {
14
11
  let truncated = (execution.output?.length ?? 0) > 4;
@@ -52,7 +52,7 @@ const tools = [
52
52
  },
53
53
  {
54
54
  action: 'send',
55
- description: 'Send input, decide a child approval or update a Goal; goal:null leaves it unchanged, goal:{clear:true} clears it.',
55
+ description: 'Send input, decide a child approval or update a Goal; goal:null leaves it unchanged, goal:{clear:true} clears it. Prefer REPLACE_CURRENT for timely communication or course correction. QUEUE is consumed only after current work and earlier queued inputs finish; an active Goal must exit first. Sending to a non-child does not subscribe to its updates.',
56
56
  properties: {
57
57
  agentId: text,
58
58
  content: { type: 'string' },
@@ -72,7 +72,7 @@ const tools = [
72
72
  },
73
73
  {
74
74
  action: 'wait',
75
- description: 'Wait for completion or messages; defaults to direct children, completion and 30 seconds. Use waitMs 0 for a snapshot.',
75
+ description: 'Wait for completion or messages; defaults to direct children, completion and 30 seconds. Use waitMs 0 for a snapshot. Non-child targets are observed only during this call.',
76
76
  properties: {
77
77
  agentId: text,
78
78
  agentIds: { type: 'array', items: text, minItems: 1, maxItems: 8 },