@xfxstudio/claworld 0.2.22 → 0.2.23-beta.1

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.
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "name": "Claworld Persona Relay",
10
10
  "description": "Claworld relay world channel plugin for OpenClaw.",
11
- "version": "0.2.22",
11
+ "version": "0.2.23-beta.1",
12
12
  "configSchema": {
13
13
  "type": "object",
14
14
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfxstudio/claworld",
3
- "version": "0.2.22",
3
+ "version": "0.2.23-beta.1",
4
4
  "description": "Claworld channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -174,6 +174,20 @@ const CLAWORLD_RELAY_OPERATIONAL_NOTICE_PATTERNS = [
174
174
  /^⚠️\s*Agent failed before reply:/i,
175
175
  ];
176
176
 
177
+ // Older/runtime-variant OpenClaw hosts may surface provider/runtime failures as
178
+ // plain final text without setting `isError`. Keep this fallback at the bridge
179
+ // boundary so business logic never has to guess.
180
+ const CLAWORLD_RELAY_RUNTIME_ERROR_PATTERNS = [
181
+ /^⚠️\s*Agent failed before reply:/i,
182
+ /^LLM request failed:/i,
183
+ /^LLM request timed out\./i,
184
+ /^LLM request unauthorized\./i,
185
+ /^The AI service is temporarily overloaded\./i,
186
+ /^The AI service returned an error\./i,
187
+ /^⚠️\s*API rate limit reached\./i,
188
+ /^⚠️\s*.+\s+returned a billing error\b/i,
189
+ ];
190
+
177
191
  const CLAWORLD_RELAY_OPERATIONAL_SUFFIX_PATTERNS = [
178
192
  /^Usage:\s+.+\s+in\s+\/\s+.+\s+out(?:\s+·\s+est\s+.+)?$/i,
179
193
  ];
@@ -201,18 +215,21 @@ function classifyRelayContinuationText(text) {
201
215
  if (!normalized) {
202
216
  return {
203
217
  text: '',
204
- operational: Boolean(String(text || '').trim()),
218
+ operationalNotice: Boolean(String(text || '').trim()),
219
+ runtimeError: false,
205
220
  };
206
221
  }
207
222
  if (CLAWORLD_RELAY_OPERATIONAL_NOTICE_PATTERNS.some((pattern) => pattern.test(normalized))) {
208
223
  return {
209
224
  text: '',
210
- operational: true,
225
+ operationalNotice: true,
226
+ runtimeError: false,
211
227
  };
212
228
  }
213
229
  return {
214
230
  text: normalized,
215
- operational: false,
231
+ operationalNotice: false,
232
+ runtimeError: false,
216
233
  };
217
234
  }
218
235
 
@@ -220,6 +237,45 @@ function sanitizeRelayContinuationText(text) {
220
237
  return classifyRelayContinuationText(text).text;
221
238
  }
222
239
 
240
+ function classifyRelayContinuationPayload(payload = {}) {
241
+ const rawText = String(payload?.text ?? payload?.body ?? '').trim();
242
+ const normalized = stripRelayOperationalSuffix(rawText);
243
+ const textClassification = classifyRelayContinuationText(rawText);
244
+ const runtimeError = payload?.isError === true
245
+ || CLAWORLD_RELAY_RUNTIME_ERROR_PATTERNS.some((pattern) => pattern.test(normalized));
246
+ if (runtimeError) {
247
+ return {
248
+ text: '',
249
+ previewText: normalized,
250
+ operationalNotice: false,
251
+ runtimeError: true,
252
+ nonRenderable: true,
253
+ };
254
+ }
255
+ return {
256
+ text: textClassification.text,
257
+ previewText: normalized,
258
+ operationalNotice: textClassification.operationalNotice,
259
+ runtimeError: false,
260
+ nonRenderable: textClassification.operationalNotice,
261
+ };
262
+ }
263
+
264
+ function resolveRelaySilentReason(runtimeOutputSummary = {}, continuation = {}) {
265
+ const counts = runtimeOutputSummary?.counts || {};
266
+ if (Number(counts.runtimeErrorFinal || 0) > 0) {
267
+ return 'runtime_failed_before_reply';
268
+ }
269
+ if (Number(counts.operationalNotice || 0) > 0 && Number(counts.nonRenderableFinal || 0) === Number(counts.final || 0)) {
270
+ return 'operational_notice_only';
271
+ }
272
+ const normalizedSource = normalizePluginOptionalText(continuation?.source);
273
+ if (normalizedSource && normalizedSource !== 'none') {
274
+ return normalizedSource;
275
+ }
276
+ return 'no_renderable_reply';
277
+ }
278
+
223
279
  function previewRuntimeOutputText(text, maxLength = 120) {
224
280
  const normalized = String(text || '').replace(/\s+/g, ' ').trim();
225
281
  if (!normalized) return '';
@@ -1269,7 +1325,9 @@ function createDeliveryReplyDispatcher({
1269
1325
  reasoningEnd: 0,
1270
1326
  compactionStart: 0,
1271
1327
  compactionEnd: 0,
1328
+ nonRenderableFinal: 0,
1272
1329
  operationalNotice: 0,
1330
+ runtimeErrorFinal: 0,
1273
1331
  },
1274
1332
  previews: {
1275
1333
  final: [],
@@ -1278,6 +1336,7 @@ function createDeliveryReplyDispatcher({
1278
1336
  partial: [],
1279
1337
  reasoning: [],
1280
1338
  operationalNotice: [],
1339
+ runtimeErrorFinal: [],
1281
1340
  },
1282
1341
  relayContinuationSource: 'none',
1283
1342
  relayContinuationPreview: null,
@@ -1288,14 +1347,21 @@ function createDeliveryReplyDispatcher({
1288
1347
  runtimeOutputSummary.counts[kind] += 1;
1289
1348
  const text = String(payload?.text ?? payload?.body ?? '').trim();
1290
1349
  if (kind === 'final') {
1291
- if (text) {
1292
- finalTexts.push(text);
1293
- appendRuntimeOutputPreview(runtimeOutputSummary.previews.final, text);
1294
- const classified = classifyRelayContinuationText(text);
1295
- if (classified.operational) {
1296
- runtimeOutputSummary.counts.operationalNotice += 1;
1297
- appendRuntimeOutputPreview(runtimeOutputSummary.previews.operationalNotice, text);
1298
- }
1350
+ const classified = classifyRelayContinuationPayload(payload);
1351
+ if (classified.text) {
1352
+ finalTexts.push(classified.text);
1353
+ appendRuntimeOutputPreview(runtimeOutputSummary.previews.final, classified.text);
1354
+ }
1355
+ if (classified.nonRenderable) {
1356
+ runtimeOutputSummary.counts.nonRenderableFinal += 1;
1357
+ }
1358
+ if (classified.operationalNotice) {
1359
+ runtimeOutputSummary.counts.operationalNotice += 1;
1360
+ appendRuntimeOutputPreview(runtimeOutputSummary.previews.operationalNotice, classified.previewText || text);
1361
+ }
1362
+ if (classified.runtimeError) {
1363
+ runtimeOutputSummary.counts.runtimeErrorFinal += 1;
1364
+ appendRuntimeOutputPreview(runtimeOutputSummary.previews.runtimeErrorFinal, classified.previewText || text);
1299
1365
  }
1300
1366
  return;
1301
1367
  }
@@ -1328,6 +1394,30 @@ function createDeliveryReplyDispatcher({
1328
1394
  runtimeOutputSummary.counts[kind] += 1;
1329
1395
  };
1330
1396
 
1397
+ const submitRelayReply = async (replyText) => {
1398
+ if (typeof relayClient?.submitDeliveryReply !== 'function') {
1399
+ throw new Error('relay client does not support reply submission');
1400
+ }
1401
+ return await relayClient.submitDeliveryReply({
1402
+ deliveryId,
1403
+ sessionKey,
1404
+ replyText,
1405
+ source: 'openclaw-autochain',
1406
+ });
1407
+ };
1408
+
1409
+ const submitRelayKeptSilent = async (reason) => {
1410
+ if (typeof relayClient?.submitDeliveryKeptSilent !== 'function') {
1411
+ throw new Error('relay client does not support kept_silent submission');
1412
+ }
1413
+ return await relayClient.submitDeliveryKeptSilent({
1414
+ deliveryId,
1415
+ sessionKey,
1416
+ reason,
1417
+ source: 'openclaw-autochain',
1418
+ });
1419
+ };
1420
+
1331
1421
  const flushReply = async (text) => {
1332
1422
  const normalized = String(text || '').trim();
1333
1423
  if (!normalized || replied || suppressed) return false;
@@ -1335,25 +1425,9 @@ function createDeliveryReplyDispatcher({
1335
1425
  suppressed = true;
1336
1426
  return false;
1337
1427
  }
1338
- if (typeof relayClient.sendReplyAndWaitForAck === 'function') {
1339
- const replyResult = await relayClient.sendReplyAndWaitForAck({
1340
- deliveryId,
1341
- sessionKey,
1342
- replyText: normalized,
1343
- source: 'openclaw-autochain',
1344
- });
1345
- replyTransport = replyResult?.transport || 'websocket';
1346
- replyFallbackUsed = replyResult?.fallbackUsed === true;
1347
- } else {
1348
- relayClient.sendReply({
1349
- deliveryId,
1350
- sessionKey,
1351
- replyText: normalized,
1352
- source: 'openclaw-autochain',
1353
- });
1354
- replyTransport = 'websocket-fire-and-forget';
1355
- replyFallbackUsed = false;
1356
- }
1428
+ const replyResult = await submitRelayReply(normalized);
1429
+ replyTransport = replyResult?.transport || null;
1430
+ replyFallbackUsed = replyResult?.fallbackUsed === true;
1357
1431
  replied = true;
1358
1432
  return true;
1359
1433
  };
@@ -1364,19 +1438,11 @@ function createDeliveryReplyDispatcher({
1364
1438
  suppressed = true;
1365
1439
  return false;
1366
1440
  }
1367
- if (typeof relayClient.sendKeepSilentAndWaitForAck === 'function') {
1368
- const silentResult = await relayClient.sendKeepSilentAndWaitForAck({
1369
- deliveryId,
1370
- sessionKey,
1371
- reason: normalizePluginOptionalText(reason) || 'no_renderable_reply',
1372
- source: 'openclaw-autochain',
1373
- });
1374
- keptSilentTransport = silentResult?.transport || 'websocket';
1375
- keptSilentFallbackUsed = silentResult?.fallbackUsed === true;
1376
- } else {
1377
- keptSilentTransport = 'unsupported';
1378
- keptSilentFallbackUsed = false;
1379
- }
1441
+ const silentResult = await submitRelayKeptSilent(
1442
+ normalizePluginOptionalText(reason) || 'no_renderable_reply',
1443
+ );
1444
+ keptSilentTransport = silentResult?.transport || null;
1445
+ keptSilentFallbackUsed = silentResult?.fallbackUsed === true;
1380
1446
  keptSilent = true;
1381
1447
  return true;
1382
1448
  };
@@ -1411,21 +1477,35 @@ function createDeliveryReplyDispatcher({
1411
1477
  const markDispatchIdle = async () => {
1412
1478
  await dispatchApi.dispatcher.waitForIdle?.();
1413
1479
  if (!replied && !suppressed) {
1414
- const continuation = buildRelayContinuationText({
1480
+ const allowPartialFallback = (
1481
+ runtimeOutputSummary.counts.final > 0
1482
+ && finalTexts.length === 0
1483
+ && blockTexts.length === 0
1484
+ && runtimeOutputSummary.counts.nonRenderableFinal === 0
1485
+ );
1486
+ const safeContinuation = buildRelayContinuationText({
1415
1487
  finalTexts,
1416
1488
  blockTexts,
1417
1489
  partialText: partialContinuationText,
1418
- allowPartialFallback:
1419
- runtimeOutputSummary.counts.final > 0 && finalTexts.length === 0 && blockTexts.length === 0,
1490
+ allowPartialFallback,
1420
1491
  });
1421
- runtimeOutputSummary.relayContinuationSource = continuation.source;
1422
- runtimeOutputSummary.relayContinuationPreview = continuation.text
1423
- ? previewRuntimeOutputText(continuation.text)
1492
+ runtimeOutputSummary.relayContinuationSource = safeContinuation.source;
1493
+ runtimeOutputSummary.relayContinuationPreview = safeContinuation.text
1494
+ ? previewRuntimeOutputText(safeContinuation.text)
1424
1495
  : null;
1425
- if (continuation.text) {
1426
- await flushReply(continuation.text);
1496
+ if (safeContinuation.text) {
1497
+ await flushReply(safeContinuation.text);
1427
1498
  } else {
1428
- await flushKeptSilent(continuation.source);
1499
+ const silentReason = resolveRelaySilentReason(runtimeOutputSummary, safeContinuation);
1500
+ if (runtimeOutputSummary.counts.runtimeErrorFinal > 0) {
1501
+ logger.warn?.(`[claworld:${runtimeAccountId}] runtime produced non-renderable error finals; returning kept_silent`, {
1502
+ deliveryId,
1503
+ sessionKey,
1504
+ localAgentId,
1505
+ runtimeOutputSummary,
1506
+ });
1507
+ }
1508
+ await flushKeptSilent(silentReason);
1429
1509
  }
1430
1510
  }
1431
1511
  await dispatchApi.markDispatchIdle?.();
@@ -1470,13 +1550,14 @@ function createDeliveryReplyDispatcher({
1470
1550
  final: [...runtimeOutputSummary.previews.final],
1471
1551
  block: [...runtimeOutputSummary.previews.block],
1472
1552
  tool: [...runtimeOutputSummary.previews.tool],
1473
- partial: [...runtimeOutputSummary.previews.partial],
1474
- reasoning: [...runtimeOutputSummary.previews.reasoning],
1475
- operationalNotice: [...runtimeOutputSummary.previews.operationalNotice],
1476
- },
1477
- relayContinuationSource: runtimeOutputSummary.relayContinuationSource,
1478
- relayContinuationPreview: runtimeOutputSummary.relayContinuationPreview,
1479
- replyTransport,
1553
+ partial: [...runtimeOutputSummary.previews.partial],
1554
+ reasoning: [...runtimeOutputSummary.previews.reasoning],
1555
+ operationalNotice: [...runtimeOutputSummary.previews.operationalNotice],
1556
+ runtimeErrorFinal: [...runtimeOutputSummary.previews.runtimeErrorFinal],
1557
+ },
1558
+ relayContinuationSource: runtimeOutputSummary.relayContinuationSource,
1559
+ relayContinuationPreview: runtimeOutputSummary.relayContinuationPreview,
1560
+ replyTransport,
1480
1561
  replyFallbackUsed,
1481
1562
  keptSilentTransport,
1482
1563
  keptSilentFallbackUsed,
@@ -1709,12 +1790,13 @@ async function maybeBridgeRuntimeDelivery({
1709
1790
  });
1710
1791
 
1711
1792
  try {
1712
- if (typeof relayClient?.sendAcceptedAndWaitForAck === 'function') {
1713
- await relayClient.sendAcceptedAndWaitForAck({
1714
- deliveryId,
1715
- sessionKey,
1716
- source: 'runtime_dispatch',
1717
- });
1793
+ const acceptedResult = await relayClient.acceptDeliveryHttp({
1794
+ deliveryId,
1795
+ sessionKey,
1796
+ source: 'runtime_dispatch',
1797
+ });
1798
+ if (acceptedResult.status < 200 || acceptedResult.status >= 300) {
1799
+ throw new Error(`failed to submit relay delivery acceptance: ${acceptedResult.status}`);
1718
1800
  }
1719
1801
  } catch (error) {
1720
1802
  logger.warn?.(`[claworld:${runtimeAccountId}] delivery acceptance acknowledgement failed`, {
@@ -1748,8 +1830,8 @@ async function maybeBridgeRuntimeDelivery({
1748
1830
  && metadata.allowReply !== false
1749
1831
  && replied !== true
1750
1832
  && runtimeOutputSummary.counts.final > 0
1751
- && runtimeOutputSummary.counts.operationalNotice > 0
1752
- && runtimeOutputSummary.counts.final === runtimeOutputSummary.counts.operationalNotice
1833
+ && runtimeOutputSummary.counts.nonRenderableFinal > 0
1834
+ && runtimeOutputSummary.counts.final === runtimeOutputSummary.counts.nonRenderableFinal
1753
1835
  && runtimeOutputSummary.counts.block === 0
1754
1836
  && runtimeOutputSummary.counts.tool === 0
1755
1837
  && runtimeOutputSummary.counts.partial === 0
@@ -29,6 +29,21 @@ import {
29
29
  TERMINAL_CLOSE_REASONS,
30
30
  } from './relay-client-shared.js';
31
31
 
32
+ const DELIVERY_VISIBILITY_RETRY_ATTEMPTS = 20;
33
+ const DELIVERY_VISIBILITY_RETRY_DELAY_MS = 10;
34
+
35
+ function isDeliveryVisibilityMiss(result = {}) {
36
+ return Number(result?.status) === 404
37
+ && normalizeOptionalText(result?.body?.error) === 'delivery_not_found';
38
+ }
39
+
40
+ async function waitForDeliveryVisibilityRetry() {
41
+ await new Promise((resolve) => {
42
+ const timer = setTimeout(resolve, DELIVERY_VISIBILITY_RETRY_DELAY_MS);
43
+ if (typeof timer?.unref === 'function') timer.unref();
44
+ });
45
+ }
46
+
32
47
  export class ClaworldRelayClient extends EventEmitter {
33
48
  constructor({
34
49
  logger = console,
@@ -244,6 +259,18 @@ export class ClaworldRelayClient extends EventEmitter {
244
259
  return { status: response.status, body };
245
260
  }
246
261
 
262
+ async requestJsonWithDeliveryVisibilityRetry(pathName, init = {}, fallback = {}) {
263
+ let attempt = 0;
264
+ while (true) {
265
+ const result = await this.requestJson(pathName, init, fallback);
266
+ if (!isDeliveryVisibilityMiss(result) || attempt >= DELIVERY_VISIBILITY_RETRY_ATTEMPTS - 1) {
267
+ return result;
268
+ }
269
+ attempt += 1;
270
+ await waitForDeliveryVisibilityRetry();
271
+ }
272
+ }
273
+
247
274
  async openSocket({
248
275
  wsUrl,
249
276
  agentId,
@@ -879,7 +906,7 @@ export class ClaworldRelayClient extends EventEmitter {
879
906
  replyText,
880
907
  source,
881
908
  });
882
- const result = await this.requestJson(`/v1/deliveries/${encodeURIComponent(envelope.deliveryId)}/reply`, {
909
+ const result = await this.requestJsonWithDeliveryVisibilityRetry(`/v1/deliveries/${encodeURIComponent(envelope.deliveryId)}/reply`, {
883
910
  method: 'POST',
884
911
  headers: buildRuntimeAuthHeaders(this.runtimeConfig, { 'content-type': 'application/json' }),
885
912
  body: JSON.stringify({
@@ -901,7 +928,7 @@ export class ClaworldRelayClient extends EventEmitter {
901
928
 
902
929
  async acceptDeliveryHttp({ deliveryId, sessionKey = null, source = 'runtime_dispatch' } = {}) {
903
930
  const normalizedDeliveryId = normalizeOptionalText(deliveryId);
904
- const result = await this.requestJson(`/v1/deliveries/${encodeURIComponent(normalizedDeliveryId)}/accepted`, {
931
+ const result = await this.requestJsonWithDeliveryVisibilityRetry(`/v1/deliveries/${encodeURIComponent(normalizedDeliveryId)}/accepted`, {
905
932
  method: 'POST',
906
933
  headers: buildRuntimeAuthHeaders(this.runtimeConfig, { 'content-type': 'application/json' }),
907
934
  body: JSON.stringify({
@@ -932,6 +959,10 @@ export class ClaworldRelayClient extends EventEmitter {
932
959
  timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS,
933
960
  httpFallback = true,
934
961
  } = {}) {
962
+ const ackPromise = this.waitForReplyAck({
963
+ deliveryId,
964
+ timeoutMs,
965
+ });
935
966
  const envelope = this.sendReply({
936
967
  deliveryId,
937
968
  sessionKey,
@@ -940,10 +971,7 @@ export class ClaworldRelayClient extends EventEmitter {
940
971
  });
941
972
 
942
973
  try {
943
- const ack = await this.waitForReplyAck({
944
- deliveryId: envelope.deliveryId,
945
- timeoutMs,
946
- });
974
+ const ack = await ackPromise;
947
975
  return {
948
976
  ok: true,
949
977
  envelope,
@@ -1011,6 +1039,24 @@ export class ClaworldRelayClient extends EventEmitter {
1011
1039
  }
1012
1040
  }
1013
1041
 
1042
+ async submitDeliveryReply({
1043
+ deliveryId,
1044
+ sessionKey,
1045
+ replyText,
1046
+ source = 'subagent',
1047
+ timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS,
1048
+ httpFallback = true,
1049
+ } = {}) {
1050
+ return await this.sendReplyAndWaitForAck({
1051
+ deliveryId,
1052
+ sessionKey,
1053
+ replyText,
1054
+ source,
1055
+ timeoutMs,
1056
+ httpFallback,
1057
+ });
1058
+ }
1059
+
1014
1060
  async sendAcceptedAndWaitForAck({
1015
1061
  deliveryId,
1016
1062
  sessionKey,
@@ -1018,6 +1064,10 @@ export class ClaworldRelayClient extends EventEmitter {
1018
1064
  timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS,
1019
1065
  httpFallback = true,
1020
1066
  } = {}) {
1067
+ const ackPromise = this.waitForAcceptedAck({
1068
+ deliveryId,
1069
+ timeoutMs,
1070
+ });
1021
1071
  const envelope = this.sendAccepted({
1022
1072
  deliveryId,
1023
1073
  sessionKey,
@@ -1025,10 +1075,7 @@ export class ClaworldRelayClient extends EventEmitter {
1025
1075
  });
1026
1076
 
1027
1077
  try {
1028
- const ack = await this.waitForAcceptedAck({
1029
- deliveryId: envelope.deliveryId,
1030
- timeoutMs,
1031
- });
1078
+ const ack = await ackPromise;
1032
1079
  return {
1033
1080
  ok: true,
1034
1081
  envelope,
@@ -1082,7 +1129,7 @@ export class ClaworldRelayClient extends EventEmitter {
1082
1129
 
1083
1130
  async keepDeliverySilentHttp({ deliveryId, reason = null, source = 'openclaw-autochain' } = {}) {
1084
1131
  const normalizedDeliveryId = normalizeOptionalText(deliveryId);
1085
- const result = await this.requestJson(`/v1/deliveries/${encodeURIComponent(normalizedDeliveryId)}/kept-silent`, {
1132
+ const result = await this.requestJsonWithDeliveryVisibilityRetry(`/v1/deliveries/${encodeURIComponent(normalizedDeliveryId)}/kept-silent`, {
1086
1133
  method: 'POST',
1087
1134
  headers: buildRuntimeAuthHeaders(this.runtimeConfig, { 'content-type': 'application/json' }),
1088
1135
  body: JSON.stringify({
@@ -1113,6 +1160,10 @@ export class ClaworldRelayClient extends EventEmitter {
1113
1160
  timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS,
1114
1161
  httpFallback = true,
1115
1162
  } = {}) {
1163
+ const ackPromise = this.waitForKeepSilentAck({
1164
+ deliveryId,
1165
+ timeoutMs,
1166
+ });
1116
1167
  const envelope = this.sendKeepSilent({
1117
1168
  deliveryId,
1118
1169
  sessionKey,
@@ -1121,10 +1172,7 @@ export class ClaworldRelayClient extends EventEmitter {
1121
1172
  });
1122
1173
 
1123
1174
  try {
1124
- const ack = await this.waitForKeepSilentAck({
1125
- deliveryId: envelope.deliveryId,
1126
- timeoutMs,
1127
- });
1175
+ const ack = await ackPromise;
1128
1176
  return {
1129
1177
  ok: true,
1130
1178
  envelope,
@@ -1192,6 +1240,24 @@ export class ClaworldRelayClient extends EventEmitter {
1192
1240
  }
1193
1241
  }
1194
1242
 
1243
+ async submitDeliveryKeptSilent({
1244
+ deliveryId,
1245
+ sessionKey,
1246
+ reason = null,
1247
+ source = 'openclaw-autochain',
1248
+ timeoutMs = DEFAULT_REPLY_ACK_TIMEOUT_MS,
1249
+ httpFallback = true,
1250
+ } = {}) {
1251
+ return await this.sendKeepSilentAndWaitForAck({
1252
+ deliveryId,
1253
+ sessionKey,
1254
+ reason,
1255
+ source,
1256
+ timeoutMs,
1257
+ httpFallback,
1258
+ });
1259
+ }
1260
+
1195
1261
  async createChatRequest({ fromAgentId, displayName, agentCode, requestContext = {} } = {}) {
1196
1262
  const normalized = normalizeChatRequestInput({ requestContext, source: 'direct_lookup' });
1197
1263
  const normalizedDisplayName = normalizeOptionalText(displayName);