@myagentroam/node 0.10.29 → 0.10.31

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.
@@ -17,7 +17,7 @@ export class MarAgentConversationNormalizer {
17
17
  messageItemId(nativeItemId) {
18
18
  return itemId('message', nativeItemId);
19
19
  }
20
- normalize(event) {
20
+ normalize(event, options = {}) {
21
21
  if (event.type === 'execution.failed') {
22
22
  const projected = runnerErrorProjection({ code: event.code, message: event.message }, 'MAR_AGENT_RUN_FAILED');
23
23
  return [
@@ -99,19 +99,12 @@ export class MarAgentConversationNormalizer {
99
99
  }
100
100
  }
101
101
  ];
102
- if (event.type === 'context.compacting' || event.type === 'context.compacted')
103
- return [
104
- {
105
- itemId: itemId('compact', event.compactionId),
106
- kind: 'context_compaction',
107
- status: event.type === 'context.compacting' ? 'IN_PROGRESS' : 'COMPLETED',
108
- payload: {
109
- phase: event.type === 'context.compacting' ? 'STARTED' : 'COMPLETED',
110
- summary: null
111
- },
112
- merge: true
113
- }
114
- ];
102
+ if (event.type === 'context.compacting' ||
103
+ event.type === 'context.compacted' ||
104
+ event.type === 'context.compact_failed') {
105
+ const anchorItemId = this.#compactAnchorItemId(event, options.publicItemIdPrefix);
106
+ return [normalizeContextCompaction(event, anchorItemId)];
107
+ }
115
108
  if (event.type === 'subagent.started' || event.type === 'subagent.completed')
116
109
  return this.#subagentLifecycle(event);
117
110
  return [];
@@ -204,6 +197,18 @@ export class MarAgentConversationNormalizer {
204
197
  genericToolItem(ownItemId, event.toolName, 'IN_PROGRESS', event.input, null, null, event.truncated === true, undefined, subagentTitle, subagentDetails)
205
198
  ];
206
199
  }
200
+ #compactAnchorItemId(event, publicItemIdPrefix) {
201
+ const anchor = event.anchor;
202
+ if (anchor === undefined || !validCompactAnchor(anchor.id))
203
+ return undefined;
204
+ const itemId = anchor.kind === 'message'
205
+ ? this.messageItemId(anchor.id)
206
+ : this.#tools.get(anchor.id)?.itemId;
207
+ if (itemId === undefined)
208
+ return undefined;
209
+ const publicItemId = publicItemIdPrefix === undefined ? itemId : `${publicItemIdPrefix}:${itemId}`;
210
+ return publicItemId.length <= 128 ? publicItemId : undefined;
211
+ }
207
212
  #toolCompleted(event) {
208
213
  const state = this.#tools.get(event.callId);
209
214
  if ((event.toolName === 'exec' || event.toolName === 'exec_wait') &&
@@ -526,6 +531,38 @@ function eventMetadata(event, eventId) {
526
531
  function itemId(kind, value) {
527
532
  return boundedConversationItemId(`mar-agent-${kind}`, value);
528
533
  }
534
+ function normalizeContextCompaction(event, anchorItemId) {
535
+ const completed = event.type === 'context.compacted';
536
+ const failed = event.type === 'context.compact_failed';
537
+ const cancelled = failed && event.cancelled === true;
538
+ const code = failed && event.code.trim().length > 0
539
+ ? compactRunnerText(event.code, 80)
540
+ : failed
541
+ ? 'MAR_AGENT_COMPACT_FAILED'
542
+ : undefined;
543
+ return {
544
+ itemId: itemId('compact', event.compactionId),
545
+ kind: 'context_compaction',
546
+ status: failed ? (cancelled ? 'CANCELLED' : 'FAILED') : completed ? 'COMPLETED' : 'IN_PROGRESS',
547
+ payload: {
548
+ phase: completed ? 'COMPLETED' : 'STARTED',
549
+ summary: null,
550
+ ...(event.async === undefined ? {} : { mode: event.async ? 'BACKGROUND' : 'BLOCKING' }),
551
+ ...(event.type === 'context.compacting' && event.stage !== undefined
552
+ ? { stage: event.stage }
553
+ : {}),
554
+ ...(anchorItemId === undefined ? {} : { anchorItemId }),
555
+ ...(event.type === 'context.compacted' && event.retainedContext !== undefined
556
+ ? { retainedContext: event.retainedContext }
557
+ : {}),
558
+ ...(code === undefined ? {} : { code })
559
+ },
560
+ merge: true
561
+ };
562
+ }
563
+ function validCompactAnchor(value) {
564
+ return value !== undefined && value.length > 0 && value.length <= 128 ? value : undefined;
565
+ }
529
566
  function genericToolItem(id, toolName, status, input, outputSummary = null, errorCode = null, truncated = false, output, subagentTitle, knownSubagentDetails) {
530
567
  if (toolName === 'code_exec') {
531
568
  const code = typeof input === 'string' ? input : record(input)?.code;
@@ -730,6 +767,14 @@ function matchingSubagentControlOutput(toolName, input, output) {
730
767
  const operation = marAgentSubagentOperation(toolName);
731
768
  if (operation === undefined)
732
769
  return undefined;
770
+ if (toolName === 'agent_wait') {
771
+ const targets = structuredRecord(input)?.agentIds;
772
+ if (Array.isArray(targets) && targets.length !== 1)
773
+ return undefined;
774
+ const agents = structuredRecord(output)?.agents;
775
+ if (Array.isArray(agents))
776
+ output = agents.length === 1 ? agents[0] : undefined;
777
+ }
733
778
  const outputAgentId = marAgentAgentId(output);
734
779
  if (operation === 'START')
735
780
  return outputAgentId === undefined ? undefined : output;
@@ -851,6 +896,8 @@ function marAgentAgentId(value) {
851
896
  const direct = boundedId(data.agentId);
852
897
  if (direct !== undefined)
853
898
  return direct;
899
+ if (Array.isArray(data.agentIds))
900
+ return data.agentIds.length === 1 ? boundedId(data.agentIds[0]) : undefined;
854
901
  for (const key of ['data', 'result', 'output']) {
855
902
  const nested = marAgentAgentId(data[key]);
856
903
  if (nested !== undefined)
@@ -31,8 +31,15 @@ export function projectMarAgentHistory(session, entries, options = {}) {
31
31
  const items = [...turn.items];
32
32
  if (index < 0)
33
33
  items.push(item);
34
- else
35
- items[index] = { ...items[index], ...item, startedAt: items[index].startedAt };
34
+ else {
35
+ const existing = items[index];
36
+ items[index] = {
37
+ ...existing,
38
+ ...item,
39
+ payload: mergeCompactLifecycleFacts(existing, item),
40
+ startedAt: existing.startedAt
41
+ };
42
+ }
36
43
  turns.set(turn.id, { ...turn, items });
37
44
  };
38
45
  for (const entry of entries) {
@@ -97,6 +104,28 @@ export function projectMarAgentHistory(session, entries, options = {}) {
97
104
  }
98
105
  return [...turns.values()];
99
106
  }
107
+ function mergeCompactLifecycleFacts(previous, next) {
108
+ if (previous.kind !== 'context_compaction' || next.kind !== 'context_compaction')
109
+ return next.payload;
110
+ const previousPayload = record(previous.payload);
111
+ const nextPayload = record(next.payload);
112
+ if (previousPayload === undefined || nextPayload === undefined)
113
+ return next.payload;
114
+ return {
115
+ ...nextPayload,
116
+ ...(nextPayload.mode === undefined && previousPayload.mode !== undefined
117
+ ? { mode: previousPayload.mode }
118
+ : {}),
119
+ ...(nextPayload.anchorItemId === undefined && previousPayload.anchorItemId !== undefined
120
+ ? { anchorItemId: previousPayload.anchorItemId }
121
+ : {})
122
+ };
123
+ }
124
+ function record(value) {
125
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
126
+ ? value
127
+ : undefined;
128
+ }
100
129
  function historyItem(session, turn, id, kind, status, payload, at, permissionStop) {
101
130
  return {
102
131
  id,
@@ -941,7 +941,7 @@ export class MarAgentManagedRunController {
941
941
  normalizer = new MarAgentConversationNormalizer();
942
942
  this.#normalizers.set(runId, normalizer);
943
943
  }
944
- for (const item of normalizer.normalize(event)) {
944
+ for (const item of normalizer.normalize(event, { publicItemIdPrefix: runId })) {
945
945
  const attachments = item.generatedImages === undefined
946
946
  ? []
947
947
  : (this.host.registerGeneratedImages?.(runId, event.sessionId, item.generatedImages) ??
@@ -961,6 +961,7 @@ export class MarAgentManagedRunController {
961
961
  function contextUsageChanged(event) {
962
962
  return (event.type === 'context.compacted' ||
963
963
  (event.type === 'usage.updated' &&
964
+ event.purpose !== 'compact' &&
964
965
  (event.contextInputTokens !== undefined || event.inputTokens !== undefined)));
965
966
  }
966
967
  function isExecutionScopedMcp(server) {
@@ -45,7 +45,12 @@ if (process.env['MAR_NOTIFICATION_CHANNELS'] === '1') {
45
45
  .regex(/^[^\r\n]*$/u)
46
46
  .optional(),
47
47
  message: z.string().min(1).max(4000),
48
- recipientEmail: z.string().email().max(320).optional(),
48
+ recipientEmail: z
49
+ .string()
50
+ .min(3)
51
+ .max(320)
52
+ .optional()
53
+ .describe('Single recipient email address.'),
49
54
  templateId: z.enum(['', 'notification-en-US', 'notification-zh-CN']).optional()
50
55
  }
51
56
  }, async (args) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/node",
3
- "version": "0.10.29",
3
+ "version": "0.10.31",
4
4
  "description": "MyAgentRoam Node runtime CLI.",
5
5
  "license": "Apache-2.0 AND GPL-2.0-or-later",
6
6
  "type": "module",
@@ -37,10 +37,10 @@
37
37
  "playwright": "1.62.1",
38
38
  "ws": "^8.21.3",
39
39
  "zod": "4.4.3",
40
- "@myagentroam/agent": "0.10.29",
40
+ "@myagentroam/agent": "0.10.31",
41
41
  "@myagentroam/code-navigation": "0.10.1",
42
- "@myagentroam/marctl": "0.10.3",
43
- "@myagentroam/protocol": "0.10.29"
42
+ "@myagentroam/protocol": "0.10.31",
43
+ "@myagentroam/marctl": "0.10.3"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/ws": "^8.18.1"