@xfxstudio/claworld 2026.4.30-testing.2 → 2026.4.30-testing.3

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.
@@ -557,19 +557,23 @@ export class ClaworldRelayClient extends EventEmitter {
557
557
  this.heartbeatTimer = null;
558
558
  }
559
559
 
560
+ buildWsNotConnectedError(stage = 'send') {
561
+ return createRuntimeBoundaryError({
562
+ code: 'relay_ws_not_connected',
563
+ category: 'transport',
564
+ status: 409,
565
+ message: 'relay websocket is not connected',
566
+ publicMessage: 'relay websocket is not connected',
567
+ recoverable: true,
568
+ context: this.buildBoundaryContext({
569
+ stage,
570
+ }),
571
+ });
572
+ }
573
+
560
574
  send(payload) {
561
575
  if (!this.ws || this.ws.readyState !== 1) {
562
- throw createRuntimeBoundaryError({
563
- code: 'relay_ws_not_connected',
564
- category: 'transport',
565
- status: 409,
566
- message: 'relay websocket is not connected',
567
- publicMessage: 'relay websocket is not connected',
568
- recoverable: true,
569
- context: this.buildBoundaryContext({
570
- stage: 'send',
571
- }),
572
- });
576
+ throw this.buildWsNotConnectedError('send');
573
577
  }
574
578
  this.ws.send(JSON.stringify(payload));
575
579
  }
@@ -663,7 +667,7 @@ export class ClaworldRelayClient extends EventEmitter {
663
667
  return envelope;
664
668
  }
665
669
 
666
- waitForReplyAck({ deliveryId, timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS } = {}) {
670
+ waitForReplyAck({ deliveryId, timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS, signal = null } = {}) {
667
671
  const normalizedDeliveryId = normalizeOptionalText(deliveryId);
668
672
  if (!normalizedDeliveryId) {
669
673
  return Promise.reject(createRuntimeBoundaryError({
@@ -675,6 +679,20 @@ export class ClaworldRelayClient extends EventEmitter {
675
679
  recoverable: true,
676
680
  }));
677
681
  }
682
+ if (signal?.aborted) {
683
+ return Promise.reject(createRuntimeBoundaryError({
684
+ code: 'relay_reply_ack_wait_cancelled',
685
+ category: 'transport',
686
+ status: 499,
687
+ message: `relay reply acknowledgement wait cancelled for ${normalizedDeliveryId}`,
688
+ publicMessage: 'relay reply acknowledgement wait cancelled',
689
+ recoverable: true,
690
+ context: this.buildBoundaryContext({
691
+ stage: 'reply_ack_wait',
692
+ deliveryId: normalizedDeliveryId,
693
+ }),
694
+ }));
695
+ }
678
696
 
679
697
  return new Promise((resolve, reject) => {
680
698
  let settled = false;
@@ -686,6 +704,7 @@ export class ClaworldRelayClient extends EventEmitter {
686
704
  this.off('command.accepted', onCommandAccepted);
687
705
  this.off('disconnect', onDisconnect);
688
706
  this.off('close', onDisconnect);
707
+ signal?.removeEventListener('abort', onAbort);
689
708
  };
690
709
 
691
710
  const settleResolve = (value) => {
@@ -739,10 +758,26 @@ export class ClaworldRelayClient extends EventEmitter {
739
758
  }));
740
759
  };
741
760
 
761
+ const onAbort = () => {
762
+ settleReject(createRuntimeBoundaryError({
763
+ code: 'relay_reply_ack_wait_cancelled',
764
+ category: 'transport',
765
+ status: 499,
766
+ message: `relay reply acknowledgement wait cancelled for ${normalizedDeliveryId}`,
767
+ publicMessage: 'relay reply acknowledgement wait cancelled',
768
+ recoverable: true,
769
+ context: this.buildBoundaryContext({
770
+ stage: 'reply_ack_wait',
771
+ deliveryId: normalizedDeliveryId,
772
+ }),
773
+ }));
774
+ };
775
+
742
776
  this.on('reply.accepted', onReplyAccepted);
743
777
  this.on('command.accepted', onCommandAccepted);
744
778
  this.on('disconnect', onDisconnect);
745
779
  this.on('close', onDisconnect);
780
+ signal?.addEventListener('abort', onAbort, { once: true });
746
781
 
747
782
  timeout = setTimeout(() => {
748
783
  settleReject(buildReplyAckTimeoutError({
@@ -837,7 +872,7 @@ export class ClaworldRelayClient extends EventEmitter {
837
872
  });
838
873
  }
839
874
 
840
- waitForKeepSilentAck({ deliveryId, timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS } = {}) {
875
+ waitForKeepSilentAck({ deliveryId, timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS, signal = null } = {}) {
841
876
  const normalizedDeliveryId = normalizeOptionalText(deliveryId);
842
877
  if (!normalizedDeliveryId) {
843
878
  return Promise.reject(createRuntimeBoundaryError({
@@ -849,6 +884,20 @@ export class ClaworldRelayClient extends EventEmitter {
849
884
  recoverable: true,
850
885
  }));
851
886
  }
887
+ if (signal?.aborted) {
888
+ return Promise.reject(createRuntimeBoundaryError({
889
+ code: 'relay_kept_silent_ack_wait_cancelled',
890
+ category: 'transport',
891
+ status: 499,
892
+ message: `relay kept_silent acknowledgement wait cancelled for ${normalizedDeliveryId}`,
893
+ publicMessage: 'relay kept_silent acknowledgement wait cancelled',
894
+ recoverable: true,
895
+ context: this.buildBoundaryContext({
896
+ stage: 'kept_silent_ack_wait',
897
+ deliveryId: normalizedDeliveryId,
898
+ }),
899
+ }));
900
+ }
852
901
 
853
902
  return new Promise((resolve, reject) => {
854
903
  let settled = false;
@@ -859,6 +908,7 @@ export class ClaworldRelayClient extends EventEmitter {
859
908
  this.off('kept_silent.accepted', onKeptSilentAccepted);
860
909
  this.off('disconnect', onDisconnect);
861
910
  this.off('close', onDisconnect);
911
+ signal?.removeEventListener('abort', onAbort);
862
912
  };
863
913
 
864
914
  const settleResolve = (value) => {
@@ -898,9 +948,25 @@ export class ClaworldRelayClient extends EventEmitter {
898
948
  }));
899
949
  };
900
950
 
951
+ const onAbort = () => {
952
+ settleReject(createRuntimeBoundaryError({
953
+ code: 'relay_kept_silent_ack_wait_cancelled',
954
+ category: 'transport',
955
+ status: 499,
956
+ message: `relay kept_silent acknowledgement wait cancelled for ${normalizedDeliveryId}`,
957
+ publicMessage: 'relay kept_silent acknowledgement wait cancelled',
958
+ recoverable: true,
959
+ context: this.buildBoundaryContext({
960
+ stage: 'kept_silent_ack_wait',
961
+ deliveryId: normalizedDeliveryId,
962
+ }),
963
+ }));
964
+ };
965
+
901
966
  this.on('kept_silent.accepted', onKeptSilentAccepted);
902
967
  this.on('disconnect', onDisconnect);
903
968
  this.on('close', onDisconnect);
969
+ signal?.addEventListener('abort', onAbort, { once: true });
904
970
 
905
971
  timeout = setTimeout(() => {
906
972
  settleReject(buildKeepSilentAckTimeoutError({
@@ -943,6 +1009,69 @@ export class ClaworldRelayClient extends EventEmitter {
943
1009
  };
944
1010
  }
945
1011
 
1012
+ async submitReplyHttpFallback({
1013
+ deliveryId,
1014
+ sessionKey,
1015
+ replyText,
1016
+ source = 'subagent',
1017
+ error = null,
1018
+ } = {}) {
1019
+ this.logger.warn?.('[claworld:relay-client] reply websocket transport failed; attempting HTTP fallback', {
1020
+ accountId: this.runtimeConfig?.accountId || null,
1021
+ agentId: this.boundAgentId,
1022
+ deliveryId: normalizeOptionalText(deliveryId),
1023
+ sessionKey: normalizeOptionalText(sessionKey) || null,
1024
+ error: error?.message || String(error),
1025
+ });
1026
+
1027
+ const fallbackResult = await this.replyToDeliveryHttp({
1028
+ deliveryId,
1029
+ replyText,
1030
+ source,
1031
+ });
1032
+
1033
+ if (fallbackResult.status >= 200 && fallbackResult.status < 300) {
1034
+ return {
1035
+ ok: true,
1036
+ envelope: fallbackResult.envelope,
1037
+ ack: {
1038
+ event: 'reply.accepted',
1039
+ data: fallbackResult.body,
1040
+ },
1041
+ transport: 'http',
1042
+ fallbackUsed: true,
1043
+ };
1044
+ }
1045
+
1046
+ if (isReplyAlreadyApplied(fallbackResult, fallbackResult.envelope.deliveryId)) {
1047
+ return {
1048
+ ok: true,
1049
+ envelope: fallbackResult.envelope,
1050
+ ack: {
1051
+ event: 'reply.accepted',
1052
+ data: {
1053
+ ...(fallbackResult.body && typeof fallbackResult.body === 'object' ? fallbackResult.body : {}),
1054
+ repliedDeliveryId: fallbackResult.envelope.deliveryId,
1055
+ },
1056
+ },
1057
+ transport: 'http-already-applied',
1058
+ fallbackUsed: true,
1059
+ };
1060
+ }
1061
+
1062
+ throw buildReplyFallbackError({
1063
+ deliveryId: fallbackResult.envelope.deliveryId,
1064
+ status: fallbackResult.status,
1065
+ body: fallbackResult.body,
1066
+ context: this.buildBoundaryContext({
1067
+ stage: 'reply_fallback',
1068
+ deliveryId: fallbackResult.envelope.deliveryId,
1069
+ sessionKey: normalizeOptionalText(sessionKey) || null,
1070
+ fallbackFrom: error?.code || error?.message || null,
1071
+ }),
1072
+ });
1073
+ }
1074
+
946
1075
  async acceptDeliveryHttp({ deliveryId, sessionKey = null, source = 'runtime_dispatch' } = {}) {
947
1076
  const normalizedDeliveryId = normalizeOptionalText(deliveryId);
948
1077
  const result = await this.requestJsonWithDeliveryVisibilityRetry(`/v1/runtime-deliveries/${encodeURIComponent(normalizedDeliveryId)}/accepted`, {
@@ -976,16 +1105,43 @@ export class ClaworldRelayClient extends EventEmitter {
976
1105
  timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS,
977
1106
  httpFallback = true,
978
1107
  } = {}) {
1108
+ if (httpFallback && (!this.ws || this.ws.readyState !== 1)) {
1109
+ return await this.submitReplyHttpFallback({
1110
+ deliveryId,
1111
+ sessionKey,
1112
+ replyText,
1113
+ source,
1114
+ error: this.buildWsNotConnectedError('reply_send'),
1115
+ });
1116
+ }
1117
+
1118
+ const ackAbortController = new AbortController();
979
1119
  const ackPromise = this.waitForReplyAck({
980
1120
  deliveryId,
981
1121
  timeoutMs,
1122
+ signal: ackAbortController.signal,
982
1123
  });
983
- const envelope = this.sendReply({
984
- deliveryId,
985
- sessionKey,
986
- replyText,
987
- source,
988
- });
1124
+ let envelope;
1125
+
1126
+ try {
1127
+ envelope = this.sendReply({
1128
+ deliveryId,
1129
+ sessionKey,
1130
+ replyText,
1131
+ source,
1132
+ });
1133
+ } catch (error) {
1134
+ ackAbortController.abort();
1135
+ void ackPromise.catch(() => {});
1136
+ if (!httpFallback) throw error;
1137
+ return await this.submitReplyHttpFallback({
1138
+ deliveryId,
1139
+ sessionKey,
1140
+ replyText,
1141
+ source,
1142
+ error,
1143
+ });
1144
+ }
989
1145
 
990
1146
  try {
991
1147
  const ack = await ackPromise;
@@ -999,59 +1155,12 @@ export class ClaworldRelayClient extends EventEmitter {
999
1155
  } catch (error) {
1000
1156
  if (!httpFallback) throw error;
1001
1157
 
1002
- this.logger.warn?.('[claworld:relay-client] reply websocket acknowledgement failed; attempting HTTP fallback', {
1003
- accountId: this.runtimeConfig?.accountId || null,
1004
- agentId: this.boundAgentId,
1158
+ return await this.submitReplyHttpFallback({
1005
1159
  deliveryId: envelope.deliveryId,
1006
1160
  sessionKey: envelope.sessionKey,
1007
- error: error?.message || String(error),
1008
- });
1009
-
1010
- const fallbackResult = await this.replyToDeliveryHttp({
1011
- deliveryId: envelope.deliveryId,
1012
1161
  replyText,
1013
1162
  source,
1014
- });
1015
-
1016
- if (fallbackResult.status >= 200 && fallbackResult.status < 300) {
1017
- return {
1018
- ok: true,
1019
- envelope,
1020
- ack: {
1021
- event: 'reply.accepted',
1022
- data: fallbackResult.body,
1023
- },
1024
- transport: 'http',
1025
- fallbackUsed: true,
1026
- };
1027
- }
1028
-
1029
- if (isReplyAlreadyApplied(fallbackResult, envelope.deliveryId)) {
1030
- return {
1031
- ok: true,
1032
- envelope,
1033
- ack: {
1034
- event: 'reply.accepted',
1035
- data: {
1036
- ...(fallbackResult.body && typeof fallbackResult.body === 'object' ? fallbackResult.body : {}),
1037
- repliedDeliveryId: envelope.deliveryId,
1038
- },
1039
- },
1040
- transport: 'http-already-applied',
1041
- fallbackUsed: true,
1042
- };
1043
- }
1044
-
1045
- throw buildReplyFallbackError({
1046
- deliveryId: envelope.deliveryId,
1047
- status: fallbackResult.status,
1048
- body: fallbackResult.body,
1049
- context: this.buildBoundaryContext({
1050
- stage: 'reply_fallback',
1051
- deliveryId: envelope.deliveryId,
1052
- sessionKey: envelope.sessionKey,
1053
- fallbackFrom: error?.code || error?.message || null,
1054
- }),
1163
+ error,
1055
1164
  });
1056
1165
  }
1057
1166
  }
@@ -1169,6 +1278,69 @@ export class ClaworldRelayClient extends EventEmitter {
1169
1278
  };
1170
1279
  }
1171
1280
 
1281
+ async submitKeepSilentHttpFallback({
1282
+ deliveryId,
1283
+ sessionKey,
1284
+ reason = null,
1285
+ source = 'openclaw-autochain',
1286
+ error = null,
1287
+ } = {}) {
1288
+ this.logger.warn?.('[claworld:relay-client] kept_silent websocket transport failed; attempting HTTP fallback', {
1289
+ accountId: this.runtimeConfig?.accountId || null,
1290
+ agentId: this.boundAgentId,
1291
+ deliveryId: normalizeOptionalText(deliveryId),
1292
+ sessionKey: normalizeOptionalText(sessionKey) || null,
1293
+ error: error?.message || String(error),
1294
+ });
1295
+
1296
+ const fallbackResult = await this.keepDeliverySilentHttp({
1297
+ deliveryId,
1298
+ reason,
1299
+ source,
1300
+ });
1301
+
1302
+ if (fallbackResult.status >= 200 && fallbackResult.status < 300) {
1303
+ return {
1304
+ ok: true,
1305
+ envelope: fallbackResult.envelope,
1306
+ ack: {
1307
+ event: 'kept_silent.accepted',
1308
+ data: fallbackResult.body,
1309
+ },
1310
+ transport: 'http',
1311
+ fallbackUsed: true,
1312
+ };
1313
+ }
1314
+
1315
+ if (isDeliveryKeptSilentAlreadyApplied(fallbackResult, fallbackResult.envelope.deliveryId)) {
1316
+ return {
1317
+ ok: true,
1318
+ envelope: fallbackResult.envelope,
1319
+ ack: {
1320
+ event: 'kept_silent.accepted',
1321
+ data: {
1322
+ ...(fallbackResult.body && typeof fallbackResult.body === 'object' ? fallbackResult.body : {}),
1323
+ keptSilentDeliveryId: fallbackResult.envelope.deliveryId,
1324
+ },
1325
+ },
1326
+ transport: 'http-already-applied',
1327
+ fallbackUsed: true,
1328
+ };
1329
+ }
1330
+
1331
+ throw buildKeepSilentFallbackError({
1332
+ deliveryId: fallbackResult.envelope.deliveryId,
1333
+ status: fallbackResult.status,
1334
+ body: fallbackResult.body,
1335
+ context: this.buildBoundaryContext({
1336
+ stage: 'kept_silent_fallback',
1337
+ deliveryId: fallbackResult.envelope.deliveryId,
1338
+ sessionKey: normalizeOptionalText(sessionKey) || null,
1339
+ fallbackFrom: error?.code || error?.message || null,
1340
+ }),
1341
+ });
1342
+ }
1343
+
1172
1344
  async sendKeepSilentAndWaitForAck({
1173
1345
  deliveryId,
1174
1346
  sessionKey,
@@ -1177,16 +1349,43 @@ export class ClaworldRelayClient extends EventEmitter {
1177
1349
  timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS,
1178
1350
  httpFallback = true,
1179
1351
  } = {}) {
1352
+ if (httpFallback && (!this.ws || this.ws.readyState !== 1)) {
1353
+ return await this.submitKeepSilentHttpFallback({
1354
+ deliveryId,
1355
+ sessionKey,
1356
+ reason,
1357
+ source,
1358
+ error: this.buildWsNotConnectedError('kept_silent_send'),
1359
+ });
1360
+ }
1361
+
1362
+ const ackAbortController = new AbortController();
1180
1363
  const ackPromise = this.waitForKeepSilentAck({
1181
1364
  deliveryId,
1182
1365
  timeoutMs,
1366
+ signal: ackAbortController.signal,
1183
1367
  });
1184
- const envelope = this.sendKeepSilent({
1185
- deliveryId,
1186
- sessionKey,
1187
- reason,
1188
- source,
1189
- });
1368
+ let envelope;
1369
+
1370
+ try {
1371
+ envelope = this.sendKeepSilent({
1372
+ deliveryId,
1373
+ sessionKey,
1374
+ reason,
1375
+ source,
1376
+ });
1377
+ } catch (error) {
1378
+ ackAbortController.abort();
1379
+ void ackPromise.catch(() => {});
1380
+ if (!httpFallback) throw error;
1381
+ return await this.submitKeepSilentHttpFallback({
1382
+ deliveryId,
1383
+ sessionKey,
1384
+ reason,
1385
+ source,
1386
+ error,
1387
+ });
1388
+ }
1190
1389
 
1191
1390
  try {
1192
1391
  const ack = await ackPromise;
@@ -1200,59 +1399,12 @@ export class ClaworldRelayClient extends EventEmitter {
1200
1399
  } catch (error) {
1201
1400
  if (!httpFallback) throw error;
1202
1401
 
1203
- this.logger.warn?.('[claworld:relay-client] kept_silent websocket acknowledgement failed; attempting HTTP fallback', {
1204
- accountId: this.runtimeConfig?.accountId || null,
1205
- agentId: this.boundAgentId,
1402
+ return await this.submitKeepSilentHttpFallback({
1206
1403
  deliveryId: envelope.deliveryId,
1207
1404
  sessionKey: envelope.sessionKey,
1208
- error: error?.message || String(error),
1209
- });
1210
-
1211
- const fallbackResult = await this.keepDeliverySilentHttp({
1212
- deliveryId: envelope.deliveryId,
1213
1405
  reason: envelope.reason,
1214
1406
  source: envelope.source,
1215
- });
1216
-
1217
- if (fallbackResult.status >= 200 && fallbackResult.status < 300) {
1218
- return {
1219
- ok: true,
1220
- envelope,
1221
- ack: {
1222
- event: 'kept_silent.accepted',
1223
- data: fallbackResult.body,
1224
- },
1225
- transport: 'http',
1226
- fallbackUsed: true,
1227
- };
1228
- }
1229
-
1230
- if (isDeliveryKeptSilentAlreadyApplied(fallbackResult, envelope.deliveryId)) {
1231
- return {
1232
- ok: true,
1233
- envelope,
1234
- ack: {
1235
- event: 'kept_silent.accepted',
1236
- data: {
1237
- ...(fallbackResult.body && typeof fallbackResult.body === 'object' ? fallbackResult.body : {}),
1238
- keptSilentDeliveryId: envelope.deliveryId,
1239
- },
1240
- },
1241
- transport: 'http-already-applied',
1242
- fallbackUsed: true,
1243
- };
1244
- }
1245
-
1246
- throw buildKeepSilentFallbackError({
1247
- deliveryId: envelope.deliveryId,
1248
- status: fallbackResult.status,
1249
- body: fallbackResult.body,
1250
- context: this.buildBoundaryContext({
1251
- stage: 'kept_silent_fallback',
1252
- deliveryId: envelope.deliveryId,
1253
- sessionKey: envelope.sessionKey,
1254
- fallbackFrom: error?.code || error?.message || null,
1255
- }),
1407
+ error,
1256
1408
  });
1257
1409
  }
1258
1410
  }
@@ -1,15 +1,6 @@
1
1
  export const CLAWORLD_PLUGIN_BRIDGE_PROTOCOL = 'claworld.delivery_reply.v1';
2
2
 
3
3
  const DELIVERY_EVENT_TYPE = 'delivery';
4
- const MANAGEMENT_EVENT_TYPES = new Set([
5
- 'notification',
6
- 'domain_notification',
7
- 'management_wake',
8
- 'management_tick',
9
- 'conversation_lifecycle',
10
- 'platform_recommendation',
11
- 'ops_recommendation',
12
- ]);
13
4
 
14
5
  function normalizeText(value, fallback = null) {
15
6
  if (value == null) return fallback;
@@ -25,28 +16,27 @@ function normalizePayload(payload = null) {
25
16
  export function createRelayEventProtocol() {
26
17
  return {
27
18
  version: CLAWORLD_PLUGIN_BRIDGE_PROTOCOL,
28
- eventTypes: [DELIVERY_EVENT_TYPE, ...MANAGEMENT_EVENT_TYPES],
29
- requiredEnvelopeFields: ['eventType', 'sessionKey', 'payload'],
19
+ eventTypes: [DELIVERY_EVENT_TYPE],
20
+ requiredEnvelopeFields: ['eventType', 'deliveryId', 'sessionKey', 'payload'],
30
21
  describeEvent(event = {}) {
31
22
  const payload = normalizePayload(event.payload);
32
23
  const missing = [];
33
- const eventType = normalizeText(event.eventType, null);
34
- if (eventType !== DELIVERY_EVENT_TYPE && !MANAGEMENT_EVENT_TYPES.has(eventType)) {
24
+ if (normalizeText(event.eventType, null) !== DELIVERY_EVENT_TYPE) {
35
25
  missing.push('eventType');
36
26
  }
37
- if (eventType === DELIVERY_EVENT_TYPE && !normalizeText(event.deliveryId, null)) {
27
+ if (!normalizeText(event.deliveryId, null)) {
38
28
  missing.push('deliveryId');
39
29
  }
40
30
  if (!normalizeText(event.sessionKey, null)) {
41
31
  missing.push('sessionKey');
42
32
  }
43
- if (eventType === DELIVERY_EVENT_TYPE && !normalizeText(payload.text, null)) {
33
+ if (!normalizeText(payload.text, null)) {
44
34
  missing.push('payload.text');
45
35
  }
46
36
  return {
47
37
  ok: missing.length === 0,
48
38
  missing,
49
- role: eventType === DELIVERY_EVENT_TYPE ? 'delivery' : 'management',
39
+ role: 'delivery',
50
40
  };
51
41
  },
52
42
  };
@@ -47,6 +47,10 @@ export function buildConversationSessionKey(conversationKey = null, fallbackSess
47
47
  export function resolveRuntimeSessionTarget(event = {}, options = {}) {
48
48
  const payload = normalizePayload(event.payload);
49
49
  const eventType = normalizeText(event.eventType || event.type || payload.eventType, null);
50
+ const providedSessionKind = normalizeText(
51
+ event.sessionKind,
52
+ normalizeText(payload.sessionKind, normalizeText(options.sessionKind, null)),
53
+ );
50
54
  const targetAgentId = normalizeText(
51
55
  event.targetAgentId,
52
56
  normalizeText(payload.targetAgentId, normalizeText(options.targetAgentId, null)),
@@ -60,15 +64,15 @@ export function resolveRuntimeSessionTarget(event = {}, options = {}) {
60
64
  normalizeText(payload.sessionKey, normalizeText(options.sessionKey, null)),
61
65
  );
62
66
 
63
- if (CLAWORLD_MANAGEMENT_EVENT_TYPES.includes(eventType)) {
67
+ if (providedSessionKind === CLAWORLD_SESSION_KINDS.management || CLAWORLD_MANAGEMENT_EVENT_TYPES.includes(eventType)) {
64
68
  const managementSessionKey = normalizeText(
65
69
  options.managementSessionKey,
66
- buildManagementSessionKey(targetAgentId),
70
+ normalizeText(providedSessionKey, buildManagementSessionKey(targetAgentId)),
67
71
  );
68
72
  return {
69
73
  sessionKind: CLAWORLD_SESSION_KINDS.management,
70
74
  target: normalizeText(options.managementTarget, 'management_session'),
71
- sessionKey: managementSessionKey || providedSessionKey,
75
+ sessionKey: providedSessionKey || managementSessionKey,
72
76
  managementSessionKey: managementSessionKey || null,
73
77
  conversationSessionKey: conversationKey ? buildConversationSessionKey(conversationKey) : null,
74
78
  targetAgentId,